Skip to content

Commit

Permalink
Merge pull request #893 from novasamatech/fix/support-treasury-batch
Browse files Browse the repository at this point in the history
Support batch call when extracting requested amount for referendum 86933jup3
  • Loading branch information
ERussel authored Nov 22, 2023
2 parents aa558d6 + 2ac10c7 commit e82c8c8
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 57 deletions.
48 changes: 48 additions & 0 deletions novawallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@
0CF193D32A84FC7C003F12F6 /* SelectedStakingViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF193D22A84FC7C003F12F6 /* SelectedStakingViewModelFactory.swift */; };
0CF193D52A861926003F12F6 /* PredefinedTimeShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF193D42A861925003F12F6 /* PredefinedTimeShortcut.swift */; };
0CF193D72A861D7E003F12F6 /* StartStakingInfoConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF193D62A861D7E003F12F6 /* StartStakingInfoConstants.swift */; };
0CFA16132B0CD8A0007AF885 /* GovSpentAmountExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA16122B0CD8A0007AF885 /* GovSpentAmountExtractor.swift */; };
0CFA16162B0CE51E007AF885 /* GovSpentAmountBatchHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA16152B0CE51E007AF885 /* GovSpentAmountBatchHandler.swift */; };
0CFA16192B0CE709007AF885 /* UtilityPallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA16182B0CE709007AF885 /* UtilityPallet.swift */; };
0CFA161C2B0CE851007AF885 /* Utility+Calls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161B2B0CE851007AF885 /* Utility+Calls.swift */; };
0CFA161E2B0CED07007AF885 /* GovTreasurySpentAmountHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161D2B0CED07007AF885 /* GovTreasurySpentAmountHandler.swift */; };
0CFA16202B0CEF31007AF885 /* GovTreasuryApproveHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA161F2B0CEF31007AF885 /* GovTreasuryApproveHandler.swift */; };
0D5245ED354CC52A842C85A0 /* TransferConfirmViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD8B98AB03AAF06AA891695 /* TransferConfirmViewLayout.swift */; };
0D8213272889988B78188D9A /* DAppWalletAuthInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337EC62037D657258BCBC02F /* DAppWalletAuthInteractor.swift */; };
0DACB56C0BDD4C984FE3C15C /* AssetReceiveWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C1179A25C22AF0875A1ADCD /* AssetReceiveWireframe.swift */; };
Expand Down Expand Up @@ -4416,6 +4422,12 @@
0CF193D22A84FC7C003F12F6 /* SelectedStakingViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedStakingViewModelFactory.swift; sourceTree = "<group>"; };
0CF193D42A861925003F12F6 /* PredefinedTimeShortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredefinedTimeShortcut.swift; sourceTree = "<group>"; };
0CF193D62A861D7E003F12F6 /* StartStakingInfoConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartStakingInfoConstants.swift; sourceTree = "<group>"; };
0CFA16122B0CD8A0007AF885 /* GovSpentAmountExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovSpentAmountExtractor.swift; sourceTree = "<group>"; };
0CFA16152B0CE51E007AF885 /* GovSpentAmountBatchHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovSpentAmountBatchHandler.swift; sourceTree = "<group>"; };
0CFA16182B0CE709007AF885 /* UtilityPallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityPallet.swift; sourceTree = "<group>"; };
0CFA161B2B0CE851007AF885 /* Utility+Calls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Utility+Calls.swift"; sourceTree = "<group>"; };
0CFA161D2B0CED07007AF885 /* GovTreasurySpentAmountHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovTreasurySpentAmountHandler.swift; sourceTree = "<group>"; };
0CFA161F2B0CEF31007AF885 /* GovTreasuryApproveHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GovTreasuryApproveHandler.swift; sourceTree = "<group>"; };
0D3FE2CE7F9F2836755DBA63 /* GovernanceUnlockConfirmProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GovernanceUnlockConfirmProtocols.swift; sourceTree = "<group>"; };
0D65686560E2E6C18A5C34CB /* StartStakingInfoWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StartStakingInfoWireframe.swift; sourceTree = "<group>"; };
0D6E67AD564867E121601F18 /* WalletsListPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WalletsListPresenter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8955,6 +8967,33 @@
path = StakingUnbondSetup;
sourceTree = "<group>";
};
0CFA16142B0CD8A9007AF885 /* Parser */ = {
isa = PBXGroup;
children = (
0CFA16122B0CD8A0007AF885 /* GovSpentAmountExtractor.swift */,
0CFA16152B0CE51E007AF885 /* GovSpentAmountBatchHandler.swift */,
0CFA161D2B0CED07007AF885 /* GovTreasurySpentAmountHandler.swift */,
0CFA161F2B0CEF31007AF885 /* GovTreasuryApproveHandler.swift */,
);
path = Parser;
sourceTree = "<group>";
};
0CFA16172B0CE6F6007AF885 /* UtilityPallet */ = {
isa = PBXGroup;
children = (
0CFA16182B0CE709007AF885 /* UtilityPallet.swift */,
);
path = UtilityPallet;
sourceTree = "<group>";
};
0CFA161A2B0CE83A007AF885 /* UtilityPallet */ = {
isa = PBXGroup;
children = (
0CFA161B2B0CE851007AF885 /* Utility+Calls.swift */,
);
path = UtilityPallet;
sourceTree = "<group>";
};
0D927CDE29F5C9F4CA537F8F /* AccountConfirm */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -11361,6 +11400,7 @@
8438E1DC24C18F11001BDB13 /* Types */ = {
isa = PBXGroup;
children = (
0CFA16172B0CE6F6007AF885 /* UtilityPallet */,
0C500B202B05101100ABEE70 /* AssetTxPaymentPallet */,
0C0CB3862AC5686C00EAC516 /* AssetConversionPallet */,
0C7945B92ABB223D001C07CA /* XTokens */,
Expand Down Expand Up @@ -11991,6 +12031,7 @@
845B08022918C2E5005785D3 /* Action */ = {
isa = PBXGroup;
children = (
0CFA16142B0CD8A9007AF885 /* Parser */,
845B811E28F451A40040CE84 /* GovernanceActionOperationFactory.swift */,
845B08002918406A005785D3 /* Gov2ActionOperationFactory.swift */,
845B08032918C308005785D3 /* Gov1ActionOperationFactory.swift */,
Expand Down Expand Up @@ -12083,6 +12124,7 @@
845BB8C725E45D0600E5FCDC /* Calls */ = {
isa = PBXGroup;
children = (
0CFA161A2B0CE83A007AF885 /* UtilityPallet */,
0CD352992ACD3E3500B3E446 /* Assets */,
0C22006C2ACAAC0F0067BA61 /* AssetConversionPallet */,
0C7945BC2ABB22AA001C07CA /* XTokens */,
Expand Down Expand Up @@ -19833,6 +19875,7 @@
88421062289BBD1900306F2C /* JsonFileRepository.swift in Sources */,
AE8B8835267349C200AB0AA9 /* CustomVlidatorListFilter.swift in Sources */,
F4E17FB827216C2F00FE36D3 /* MoonbeamBonusService.swift in Sources */,
0CFA16202B0CEF31007AF885 /* GovTreasuryApproveHandler.swift in Sources */,
8490141324A92F6D008F705E /* AttributedStringDecorator+Terms.swift in Sources */,
849976CA27B2F9E000B14A6C /* DAppMetamaskAuthorizingState.swift in Sources */,
F484FF5F264BA2720015320F /* ControllerAccountConfirmationLayout.swift in Sources */,
Expand Down Expand Up @@ -19938,6 +19981,7 @@
8860F3E2289D4FFD00C0BF86 /* SectionProtocol.swift in Sources */,
0C22006E2ACAAC2F0067BA61 /* AssetConversionPallet+Call.swift in Sources */,
F4FDA0F826A57626003D753B /* BabeEraOperationFactory.swift in Sources */,
0CFA16162B0CE51E007AF885 /* GovSpentAmountBatchHandler.swift in Sources */,
84AE7AB927D3F96300495267 /* RMRKV1Collection.swift in Sources */,
84AE7AAF27D38B1800495267 /* DrawableIconViewModel.swift in Sources */,
849976D027B3AC0100B14A6C /* MetamaskEvent.swift in Sources */,
Expand Down Expand Up @@ -21109,6 +21153,7 @@
84E25BF027E8EFB500290BF1 /* SubqueryAccumulateReward.swift in Sources */,
88AC5ADA2948A8CC0056DD40 /* TransactionSectionModel.swift in Sources */,
8499FEE227C0AF4700712589 /* ChainModel+Nft.swift in Sources */,
0CFA161E2B0CED07007AF885 /* GovTreasurySpentAmountHandler.swift in Sources */,
0CB64E692B01F798008F268F /* TransferSetupOriginSelectionWireframe.swift in Sources */,
8428765424ADDE0200D91AD8 /* SettingsViewModelFactory.swift in Sources */,
843612C1278FE62900DC739E /* DAppOperationConfirmInteractorError.swift in Sources */,
Expand Down Expand Up @@ -22743,6 +22788,7 @@
8217DCBEB74527D57AC82070 /* ParaStkStakeConfirmViewLayout.swift in Sources */,
06FD6F5999D57B27B29C8738 /* ParaStkStakeConfirmViewFactory.swift in Sources */,
0C9525E32A7AAB2A00BD724D /* StakingTimeModel.swift in Sources */,
0CFA16192B0CE709007AF885 /* UtilityPallet.swift in Sources */,
8846F73129D6BE5000B8B776 /* Data+base58.swift in Sources */,
2BBA744323AA0BF6FE53C212 /* ParaStkSelectCollatorsProtocols.swift in Sources */,
880059E128EF0A5C00E87B9B /* VotingProgressView.swift in Sources */,
Expand Down Expand Up @@ -23157,6 +23203,7 @@
58F385F41D42CC96373EDA42 /* TokensManageProtocols.swift in Sources */,
0C500B242B0511F400ABEE70 /* ExtrinsicProcessor+CustomFee.swift in Sources */,
CA3C4729115D875D0C80A3E8 /* TokensManageWireframe.swift in Sources */,
0CFA16132B0CD8A0007AF885 /* GovSpentAmountExtractor.swift in Sources */,
844C3E6B2A08C05A00C4305F /* DAppWalletAuthViewModelFactory.swift in Sources */,
88E5E2A7295D8FA1001B1D41 /* TitleIconViewModel+Hashable.swift in Sources */,
1772735F89EFA931DF7420AD /* TokensManagePresenter.swift in Sources */,
Expand Down Expand Up @@ -23393,6 +23440,7 @@
6DC454C4BA27C98987F5DC52 /* WalletConnectSessionsViewFactory.swift in Sources */,
F332FA8C330A16C3894B6542 /* WalletConnectSessionDetailsProtocols.swift in Sources */,
D0AD3C44BBFD6A9F9FDEC933 /* WalletConnectSessionDetailsWireframe.swift in Sources */,
0CFA161C2B0CE851007AF885 /* Utility+Calls.swift in Sources */,
0A44D28DF4BCF56131752F35 /* WalletConnectSessionDetailsPresenter.swift in Sources */,
F92E73C24AB577F37B35649E /* WalletConnectSessionDetailsInteractor.swift in Sources */,
E06F3BD43E589BCE3904BBCB /* WalletConnectSessionDetailsViewController.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation
import SubstrateSdk

extension UtilityPallet {
static var batchPath: CallCodingPath {
CallCodingPath(moduleName: name, callName: "batch")
}

static var batchAllPath: CallCodingPath {
CallCodingPath(moduleName: name, callName: "batch_all")
}

static var forceBatchPath: CallCodingPath {
CallCodingPath(moduleName: name, callName: "force_batch")
}

static func isBatch(path: CallCodingPath) -> Bool {
[batchPath, batchAllPath, forceBatchPath].contains(path)
}

struct Call: Codable {
let calls: [RuntimeCall<JSON>]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

enum UtilityPallet {
static let name = "Utility"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ struct ReferendumActionLocal {
}
}

let amountSpendDetails: AmountSpendDetails?
let amountSpendDetailsList: [AmountSpendDetails]
let call: Call<RuntimeCall<JSON>>?

func spentAmount() -> BigUInt? {
guard !amountSpendDetailsList.isEmpty else {
return nil
}

return amountSpendDetailsList.reduce(BigUInt(0)) { $0 + $1.amount }
}

var beneficiary: MultiAddress? {
amountSpendDetailsList.first?.beneficiary
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class GovernanceActionOperationFactory {
codingFactoryOperation: BaseOperation<RuntimeCoderFactoryProtocol>,
connection: JSONRPCEngine,
requestFactory: StorageRequestFactoryProtocol
) -> CompoundOperationWrapper<ReferendumActionLocal.AmountSpendDetails?> {
) -> CompoundOperationWrapper<[ReferendumActionLocal.AmountSpendDetails]> {
let operationManager = OperationManager(operationQueue: operationQueue)
let fetchService = OperationCombiningService<ReferendumActionLocal.AmountSpendDetails?>(
operationManager: operationManager
Expand All @@ -110,59 +110,24 @@ class GovernanceActionOperationFactory {
}

let codingFactory = try codingFactoryOperation.extractNoCancellableResultData()
let context = codingFactory.createRuntimeJsonContext()

let codingPath = CallCodingPath(moduleName: call.moduleName, callName: call.callName)

if codingPath == Treasury.spendCallPath {
let spendCall = try call.args.map(to: Treasury.SpendCall.self, with: context.toRawContext())

let details = ReferendumActionLocal.AmountSpendDetails(
amount: spendCall.amount,
beneficiary: spendCall.beneficiary
)

return [CompoundOperationWrapper.createWithResult(details)]
}

if codingPath == Treasury.approveProposalCallPath {
let approveCall = try call.args.map(to: Treasury.ApproveProposal.self, with: context.toRawContext())

let keyClosure: () throws -> [StringScaleMapper<Treasury.ProposalIndex>] = {
[StringScaleMapper(value: approveCall.proposalId)]
}

let wrapper: CompoundOperationWrapper<[StorageResponse<Treasury.Proposal>]> = requestFactory.queryItems(
engine: connection,
keyParams: keyClosure,
factory: { codingFactory },
storagePath: Treasury.proposalsStoragePath
)

let mapOperation = ClosureOperation<ReferendumActionLocal.AmountSpendDetails?> {
let responses = try wrapper.targetOperation.extractNoCancellableResultData()
guard let proposal = responses.first?.value else {
return nil
}

return ReferendumActionLocal.AmountSpendDetails(
amount: proposal.value,
beneficiary: .accoundId(proposal.beneficiary)
)
}

mapOperation.addDependency(wrapper.targetOperation)

return [CompoundOperationWrapper(targetOperation: mapOperation, dependencies: wrapper.allOperations)]
}
let context = GovSpentAmount.Context(
codingFactory: codingFactory,
connection: connection,
requestFactory: requestFactory
)

return [CompoundOperationWrapper.createWithResult(nil)]
return try GovSpentAmount.Extractor.defaultExtractor.createExtractionWrappers(
from: call,
context: context
) ?? []
}

let fetchOperation = fetchService.longrunOperation()

let mapOperation = ClosureOperation<ReferendumActionLocal.AmountSpendDetails?> {
try fetchOperation.extractNoCancellableResultData().first ?? nil
let mapOperation = ClosureOperation<[ReferendumActionLocal.AmountSpendDetails]> {
let details = try fetchOperation.extractNoCancellableResultData()

return details.compactMap { $0 }
}

mapOperation.addDependency(fetchOperation)
Expand Down Expand Up @@ -199,9 +164,9 @@ extension GovernanceActionOperationFactory: ReferendumActionOperationFactoryProt

let mapOperation = ClosureOperation<ReferendumActionLocal> {
let call = try callFetchWrapper.targetOperation.extractNoCancellableResultData()
let amountDetails = try amountDetailsWrapper.targetOperation.extractNoCancellableResultData()
let amountDetailsList = try amountDetailsWrapper.targetOperation.extractNoCancellableResultData()

return ReferendumActionLocal(amountSpendDetails: amountDetails, call: call)
return ReferendumActionLocal(amountSpendDetailsList: amountDetailsList, call: call)
}

mapOperation.addDependency(callFetchWrapper.targetOperation)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Foundation
import SubstrateSdk
import RobinHood

extension GovSpentAmount {
final class BatchHandler {
private func handleInternal(
call: RuntimeCall<JSON>,
handlers: [GovSpentAmountHandling],
context: GovSpentAmount.Context
) throws -> [CompoundOperationWrapper<ReferendumActionLocal.AmountSpendDetails?>]? {
for handler in handlers {
if
let wrappers = try handler.handle(
call: call,
internalHandlers: handlers,
context: context
) {
return wrappers
}
}

return nil
}
}
}

extension GovSpentAmount.BatchHandler: GovSpentAmountHandling {
func handle(
call: RuntimeCall<JSON>,
internalHandlers: [GovSpentAmountHandling],
context: GovSpentAmount.Context
) throws -> [CompoundOperationWrapper<ReferendumActionLocal.AmountSpendDetails?>]? {
let path = CallCodingPath(moduleName: call.moduleName, callName: call.callName)

guard UtilityPallet.isBatch(path: path) else {
return nil
}

let runtimeContext = context.codingFactory.createRuntimeJsonContext()

let calls = try call.args.map(to: UtilityPallet.Call.self, with: runtimeContext.toRawContext()).calls

let wrappers = try calls.flatMap { call in
try handleInternal(call: call, handlers: internalHandlers, context: context) ?? []
}

return wrappers
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Foundation
import SubstrateSdk
import RobinHood

protocol GovSpentAmountHandling {
func handle(
call: RuntimeCall<JSON>,
internalHandlers: [GovSpentAmountHandling],
context: GovSpentAmount.Context
) throws -> [CompoundOperationWrapper<ReferendumActionLocal.AmountSpendDetails?>]?
}

enum GovSpentAmount {
struct Context {
let codingFactory: RuntimeCoderFactoryProtocol
let connection: JSONRPCEngine
let requestFactory: StorageRequestFactoryProtocol
}

final class Extractor {
let handlers: [GovSpentAmountHandling]

init(handlers: [GovSpentAmountHandling]) {
self.handlers = handlers
}

func createExtractionWrappers(
from call: RuntimeCall<JSON>,
context: GovSpentAmount.Context
) throws -> [CompoundOperationWrapper<ReferendumActionLocal.AmountSpendDetails?>]? {
for handler in handlers {
if let wrappers = try handler.handle(
call: call,
internalHandlers: handlers,
context: context
) {
return wrappers
}
}

return nil
}
}
}

extension GovSpentAmount.Extractor {
static var defaultExtractor: GovSpentAmount.Extractor {
.init(
handlers: [
GovSpentAmount.BatchHandler(),
GovSpentAmount.TreasurySpentHandler(),
GovSpentAmount.TreasuryApproveHandler()
]
)
}
}
Loading

0 comments on commit e82c8c8

Please sign in to comment.