Skip to content

Commit faaaecd

Browse files
authored
Merge pull request #1797 from novasamatech/feature/parachain-staking-storage-update
Feature/parachain staking storage update
2 parents b78cf89 + 356d36b commit faaaecd

File tree

7 files changed

+158
-43
lines changed

7 files changed

+158
-43
lines changed

novawallet.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,7 @@
19751975
2D6F51AB2CDDD98300564C00 /* AssetsSearchFlowLayout+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6F51AA2CDDD98300564C00 /* AssetsSearchFlowLayout+Types.swift */; };
19761976
2D6F51B12CE11EB100564C00 /* SpendAssetOperationNetworkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6F51B02CE11EB100564C00 /* SpendAssetOperationNetworkBuilder.swift */; };
19771977
2D6F51B32CE120AB00564C00 /* SpendAssetOperationNetworkListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6F51B22CE120AB00564C00 /* SpendAssetOperationNetworkListInteractor.swift */; };
1978+
2D72133F2F0FC52F00826C7B /* ParaStkScheduledRequestsQueryWrapperFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D72133E2F0FC52F00826C7B /* ParaStkScheduledRequestsQueryWrapperFactory.swift */; };
19781979
2D73AD382EC32587002DE18F /* WalletListFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D73AD372EC32587002DE18F /* WalletListFilter.swift */; };
19791980
2D73AD4A2EC32CDD002DE18F /* WalletsAccountsChooseViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D73AD492EC32CDD002DE18F /* WalletsAccountsChooseViewModelFactory.swift */; };
19801981
2D73AD4F2EC32EE8002DE18F /* GiftWalletChoosePresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D73AD4E2EC32EE8002DE18F /* GiftWalletChoosePresentable.swift */; };
@@ -8553,6 +8554,7 @@
85538554
2D6F51AA2CDDD98300564C00 /* AssetsSearchFlowLayout+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AssetsSearchFlowLayout+Types.swift"; sourceTree = "<group>"; };
85548555
2D6F51B02CE11EB100564C00 /* SpendAssetOperationNetworkBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpendAssetOperationNetworkBuilder.swift; sourceTree = "<group>"; };
85558556
2D6F51B22CE120AB00564C00 /* SpendAssetOperationNetworkListInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpendAssetOperationNetworkListInteractor.swift; sourceTree = "<group>"; };
8557+
2D72133E2F0FC52F00826C7B /* ParaStkScheduledRequestsQueryWrapperFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParaStkScheduledRequestsQueryWrapperFactory.swift; sourceTree = "<group>"; };
85568558
2D73AD372EC32587002DE18F /* WalletListFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletListFilter.swift; sourceTree = "<group>"; };
85578559
2D73AD492EC32CDD002DE18F /* WalletsAccountsChooseViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletsAccountsChooseViewModelFactory.swift; sourceTree = "<group>"; };
85588560
2D73AD4E2EC32EE8002DE18F /* GiftWalletChoosePresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiftWalletChoosePresentable.swift; sourceTree = "<group>"; };
@@ -26279,6 +26281,7 @@
2627926281
841E5558282E6A7700C8438F /* ParaStkDurationOperationFactory.swift */,
2628026282
84C3420628314D9600156569 /* ParaStkScheduledRequestsQueryFactory.swift */,
2628126283
84C11F162840BD46007F7C05 /* ParaStkCollatorsOperationFactory.swift */,
26284+
2D72133E2F0FC52F00826C7B /* ParaStkScheduledRequestsQueryWrapperFactory.swift */,
2628226285
);
2628326286
path = ParachainStaking;
2628426287
sourceTree = "<group>";
@@ -31599,6 +31602,7 @@
3159931602
0C13DFE12AFBBAF600E5F355 /* SwapBaseViewModelFactory.swift in Sources */,
3160031603
843E9B3627C8B915009C143A /* NftFileDownloadService.swift in Sources */,
3160131604
842B17FF28649CCD0014CC57 /* CrossChainSelectionState.swift in Sources */,
31605+
2D72133F2F0FC52F00826C7B /* ParaStkScheduledRequestsQueryWrapperFactory.swift in Sources */,
3160231606
0CAB67532D49338000E3A844 /* StakingGenericRewardsViewController.swift in Sources */,
3160331607
0C1CF72E2E54A73E00B1DA66 /* HydraExchange.swift in Sources */,
3160431608
8437F7C12924FF6400DB6366 /* EvmSubscriptionMessage.swift in Sources */,

novawallet/Common/Services/RemoteSubscription/Substrate/ParaStkAccountSubscribeHandlingFactory.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ final class ParaStkAccountSubscribeHandlingFactory: RemoteSubscriptionHandlingFa
2828
remoteFactory: StorageKeyFactory(),
2929
operationManager: operationManager
3030
)
31+
let queryWrapperFactory = ParaStkScheduledRequestsQueryWrapperFactory(
32+
storageRequestFactory: storageRequestFactory,
33+
operationManager: operationManager
34+
)
3135

3236
return ParaStkScheduledRequestsUpdater(
3337
remoteStorageKey: remoteStorageKey,
@@ -37,7 +41,7 @@ final class ParaStkAccountSubscribeHandlingFactory: RemoteSubscriptionHandlingFa
3741
accountId: accountId,
3842
chainId: chainId,
3943
operationManager: operationManager,
40-
storageRequestFactory: storageRequestFactory,
44+
queryWrapperFactory: queryWrapperFactory,
4145
logger: logger
4246
)
4347
}

novawallet/Common/Services/RemoteSubscription/Substrate/ParaStkScheduledRequestsUpdater.swift

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ final class ParaStkScheduledRequestsUpdater: BaseStorageChildSubscription {
66
let chainRegistry: ChainRegistryProtocol
77
let accountId: AccountId
88
let chainId: ChainModel.Id
9-
let storageRequestFactory: StorageRequestFactoryProtocol
9+
let queryWrapperFactory: ParaStkScheduledRequestsQueryWrapperFactoryProtocol
1010

1111
private lazy var localKeyFactory = LocalStorageKeyFactory()
1212

@@ -18,13 +18,13 @@ final class ParaStkScheduledRequestsUpdater: BaseStorageChildSubscription {
1818
accountId: AccountId,
1919
chainId: ChainModel.Id,
2020
operationManager: OperationManagerProtocol,
21-
storageRequestFactory: StorageRequestFactoryProtocol,
21+
queryWrapperFactory: ParaStkScheduledRequestsQueryWrapperFactoryProtocol,
2222
logger: LoggerProtocol
2323
) {
2424
self.chainRegistry = chainRegistry
2525
self.accountId = accountId
2626
self.chainId = chainId
27-
self.storageRequestFactory = storageRequestFactory
27+
self.queryWrapperFactory = queryWrapperFactory
2828

2929
super.init(
3030
remoteStorageKey: remoteStorageKey,
@@ -68,12 +68,14 @@ final class ParaStkScheduledRequestsUpdater: BaseStorageChildSubscription {
6868
let responses = try requestResponsesClosure()
6969

7070
return zip(collators, responses).compactMap { collator, response in
71-
guard
72-
let scheduledRequests = response.value,
73-
let delegationRequest = scheduledRequests.first(where: { $0.delegator == delegatorId }) else {
74-
return nil
71+
let delegationRequest = response.value?.first { request in
72+
guard let requestDelegator = request.delegator else { return true }
73+
74+
return requestDelegator.wrappedValue == delegatorId
7575
}
7676

77+
guard let delegationRequest else { return nil }
78+
7779
return ParachainStaking.DelegatorScheduledRequest(
7880
collatorId: collator,
7981
whenExecutable: delegationRequest.whenExecutable,
@@ -109,18 +111,18 @@ final class ParaStkScheduledRequestsUpdater: BaseStorageChildSubscription {
109111
connection: JSONRPCEngine,
110112
blockHash: Data?
111113
) -> CompoundOperationWrapper<[StorageResponse<[ParachainStaking.ScheduledRequest]>]> {
112-
let keyParams: () throws -> [BytesCodable] = {
113-
let delegator = try decodingOperation.extractNoCancellableResultData()
114-
return delegator.collators().map { BytesCodable(wrappedValue: $0) }
115-
}
116-
117-
return storageRequestFactory.queryItems(
118-
engine: connection,
119-
keyParams: keyParams,
120-
factory: {
121-
try codingFactoryOperation.extractNoCancellableResultData()
114+
let delegatorId = accountId
115+
116+
return queryWrapperFactory.createQueryWrapper(
117+
using: connection,
118+
with: {
119+
try decodingOperation
120+
.extractNoCancellableResultData()
121+
.collators()
122+
.map { BytesCodable(wrappedValue: $0) }
122123
},
123-
storagePath: ParachainStaking.delegationRequestsPath,
124+
delegator: { delegatorId },
125+
codingFactory: { try codingFactoryOperation.extractNoCancellableResultData() },
124126
at: blockHash
125127
)
126128
}

novawallet/Common/Substrate/Types/ParachainStaking/ParachainStakingDelegator.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ extension ParachainStaking {
2424
}
2525

2626
struct ScheduledRequest: Decodable, Encodable, Equatable {
27-
@BytesCodable var delegator: AccountId
27+
/// legacy field to comply with older parachain-staking pallet version
28+
var delegator: BytesCodable?
2829
@StringCodable var whenExecutable: RoundIndex
2930
let action: DelegationAction
3031
}

novawallet/Modules/Staking/Operations/ParachainStaking/ParaStkScheduledRequestsQueryFactory.swift

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ extension ParachainStaking {
5252
}
5353

5454
final class ScheduledRequestsQueryFactory: ParaStkScheduledRequestsQueryFactoryProtocol {
55-
let operationQueue: OperationQueue
55+
let queryWrapperFactory: ParaStkScheduledRequestsQueryWrapperFactoryProtocol
5656

57-
init(operationQueue: OperationQueue) {
58-
self.operationQueue = operationQueue
57+
init(queryWrapperFactory: ParaStkScheduledRequestsQueryWrapperFactoryProtocol) {
58+
self.queryWrapperFactory = queryWrapperFactory
5959
}
6060

6161
func createOperation(
@@ -64,36 +64,29 @@ extension ParachainStaking {
6464
runtimeService: RuntimeCodingServiceProtocol,
6565
connection: JSONRPCEngine
6666
) -> CompoundOperationWrapper<[ParachainStaking.DelegatorScheduledRequest]> {
67-
let operationManager = OperationManager(operationQueue: operationQueue)
68-
69-
let queryFactory = StorageRequestFactory(
70-
remoteFactory: StorageKeyFactory(),
71-
operationManager: operationManager
72-
)
73-
7467
let codingFactoryOperation = runtimeService.fetchCoderFactoryOperation()
7568

76-
let queryWrapper: CompoundOperationWrapper<[StorageResponse<[ParachainStaking.ScheduledRequest]>]> =
77-
queryFactory.queryItems(
78-
engine: connection,
79-
keyParams: { collators },
80-
factory: { try codingFactoryOperation.extractNoCancellableResultData() },
81-
storagePath: ParachainStaking.delegationRequestsPath
82-
)
69+
let queryWrapper = queryWrapperFactory.createQueryWrapper(
70+
using: connection,
71+
with: { collators },
72+
delegator: { delegator },
73+
codingFactory: { try codingFactoryOperation.extractNoCancellableResultData() }
74+
)
8375

8476
queryWrapper.addDependency(operations: [codingFactoryOperation])
8577

8678
let mapOperation = ClosureOperation<[ParachainStaking.DelegatorScheduledRequest]> {
8779
let responses = try queryWrapper.targetOperation.extractNoCancellableResultData()
8880

8981
return zip(collators, responses).compactMap { collator, response in
90-
guard
91-
let delegatorRequest = response.value?.first(
92-
where: { $0.delegator == delegator }
93-
) else {
94-
return nil
82+
let delegatorRequest = response.value?.first { request in
83+
guard let requestDelegator = request.delegator else { return true }
84+
85+
return requestDelegator.wrappedValue == delegator
9586
}
9687

88+
guard let delegatorRequest else { return nil }
89+
9790
return ParachainStaking.DelegatorScheduledRequest(
9891
collatorId: collator,
9992
whenExecutable: delegatorRequest.whenExecutable,
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import Foundation
2+
import SubstrateSdk
3+
import Operation_iOS
4+
5+
// For more convenient usage cause of long type name
6+
private typealias Interface = ParaStkScheduledRequestsQueryWrapperFactoryProtocol
7+
8+
typealias DelegationRequestsQueryResult = [StorageResponse<[ParachainStaking.ScheduledRequest]>]
9+
10+
protocol ParaStkScheduledRequestsQueryWrapperFactoryProtocol {
11+
func createQueryWrapper<K1, K2>(
12+
using connection: JSONRPCEngine,
13+
with collators: @escaping () throws -> [K1],
14+
delegator: @escaping () throws -> K2,
15+
codingFactory: @escaping () throws -> RuntimeCoderFactoryProtocol,
16+
at blockHash: Data?
17+
) -> CompoundOperationWrapper<DelegationRequestsQueryResult> where K1: Encodable, K2: Encodable
18+
}
19+
20+
extension ParaStkScheduledRequestsQueryWrapperFactoryProtocol {
21+
func createQueryWrapper<K1, K2>(
22+
using connection: JSONRPCEngine,
23+
with collators: @escaping () throws -> [K1],
24+
delegator: @escaping () throws -> K2,
25+
codingFactory: @escaping () throws -> RuntimeCoderFactoryProtocol,
26+
at blockHash: Data? = nil
27+
) -> CompoundOperationWrapper<DelegationRequestsQueryResult> where K1: Encodable, K2: Encodable {
28+
createQueryWrapper(
29+
using: connection,
30+
with: collators,
31+
delegator: delegator,
32+
codingFactory: codingFactory,
33+
at: blockHash
34+
)
35+
}
36+
}
37+
38+
final class ParaStkScheduledRequestsQueryWrapperFactory {
39+
private let storageRequestFactory: StorageRequestFactoryProtocol
40+
private let operationManager: OperationManagerProtocol
41+
42+
init(
43+
storageRequestFactory: StorageRequestFactoryProtocol,
44+
operationManager: OperationManagerProtocol
45+
) {
46+
self.storageRequestFactory = storageRequestFactory
47+
self.operationManager = operationManager
48+
}
49+
}
50+
51+
extension ParaStkScheduledRequestsQueryWrapperFactory: Interface {
52+
func createQueryWrapper<K1, K2>(
53+
using connection: JSONRPCEngine,
54+
with collators: @escaping () throws -> [K1],
55+
delegator: @escaping () throws -> K2,
56+
codingFactory: @escaping () throws -> RuntimeCoderFactoryProtocol,
57+
at blockHash: Data?
58+
) -> CompoundOperationWrapper<DelegationRequestsQueryResult> where K1: Encodable, K2: Encodable {
59+
OperationCombiningService.compoundNonOptionalWrapper(
60+
operationManager: operationManager
61+
) { [weak self] in
62+
guard let self else { throw BaseOperationError.parentOperationCancelled }
63+
64+
let codingFactory = try codingFactory()
65+
let metadata = codingFactory.metadata
66+
67+
let storageMetadata = metadata.getStorageMetadata(
68+
for: ParachainStaking.delegationRequestsPath
69+
)
70+
71+
guard let storageMetadata else { throw ParaStkRequestsQueryError.storageMetadataNotFound }
72+
73+
return switch storageMetadata.type {
74+
case .map:
75+
storageRequestFactory.queryItems(
76+
engine: connection,
77+
keyParams: collators,
78+
factory: { codingFactory },
79+
storagePath: ParachainStaking.delegationRequestsPath,
80+
at: blockHash
81+
)
82+
case .doubleMap:
83+
storageRequestFactory.queryItems(
84+
engine: connection,
85+
keyParams1: collators,
86+
keyParams2: { try Array(repeating: try delegator(), count: collators().count) },
87+
factory: { codingFactory },
88+
storagePath: ParachainStaking.delegationRequestsPath,
89+
at: blockHash
90+
)
91+
default:
92+
throw ParaStkRequestsQueryError.unexpectedStorageType
93+
}
94+
}
95+
}
96+
}
97+
98+
// MARK: - Errors
99+
100+
enum ParaStkRequestsQueryError: Error {
101+
case storageMetadataNotFound
102+
case unexpectedStorageType
103+
}

novawallet/Modules/Staking/StakingMain/Parachain/StakingMainPresenterFactory+Parachain.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,22 @@ extension StakingMainPresenterFactory {
9494

9595
let applicationHandler = ApplicationHandler()
9696

97+
let queryWrapperFactory = ParaStkScheduledRequestsQueryWrapperFactory(
98+
storageRequestFactory: storageRequestFactory,
99+
operationManager: operationManager
100+
)
101+
let scheduledRequestsFactory = ParachainStaking.ScheduledRequestsQueryFactory(
102+
queryWrapperFactory: queryWrapperFactory
103+
)
104+
97105
return StakingParachainInteractor(
98106
selectedWalletSettings: SelectedWalletSettings.shared,
99107
sharedState: state,
100108
walletLocalSubscriptionFactory: WalletLocalSubscriptionFactory.shared,
101109
priceLocalSubscriptionFactory: PriceProviderFactory.shared,
102110
networkInfoFactory: networkInfoFactory,
103111
durationOperationFactory: durationFactory,
104-
scheduledRequestsFactory: ParachainStaking.ScheduledRequestsQueryFactory(operationQueue: operationQueue),
112+
scheduledRequestsFactory: scheduledRequestsFactory,
105113
collatorsOperationFactory: collatorsOperationFactory,
106114
yieldBoostSupport: ParaStkYieldBoostSupport(),
107115
yieldBoostProviderFactory: ParaStkYieldBoostProviderFactory.shared,

0 commit comments

Comments
 (0)