Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup staking proxy #935

Merged
merged 10 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import RobinHood

protocol ProxyListLocalSubscriptionHandler {
func handleAllProxies(result: Result<[DataProviderChange<ProxyAccountModel>], Error>)
func handleProxies(
result: Result<ProxyDefinition?, Error>,
accountId: AccountId,
chainId: ChainModel.Id
)
}

extension ProxyListLocalSubscriptionHandler {
func handleAllProxies(result _: Result<[DataProviderChange<ProxyAccountModel>], Error>) {}
func handleProxies(
result _: Result<ProxyDefinition?, Error>,
accountId _: AccountId,
chainId _: ChainModel.Id
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,40 @@ import RobinHood

protocol ProxyListLocalSubscriptionFactoryProtocol {
func getProxyListProvider() throws -> StreamableProvider<ProxyAccountModel>
func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition>
}

final class ProxyListLocalSubscriptionFactory: BaseLocalSubscriptionFactory {
static let shared = ProxyListLocalSubscriptionFactory(
ERussel marked this conversation as resolved.
Show resolved Hide resolved
chainRegistry: ChainRegistryFacade.sharedRegistry,
streamableProviderFactory: SubstrateDataProviderFactory(
facade: SubstrateDataStorageFacade.shared,
operationManager: OperationManagerFacade.sharedManager,
logger: Logger.shared
),
storageFacade: UserDataStorageFacade.shared,
operationManager: OperationManager(operationQueue: OperationManagerFacade.sharedDefaultQueue),
operationManager: OperationManagerFacade.sharedManager,
logger: Logger.shared
)

let chainRegistry: ChainRegistryProtocol
let streamableProviderFactory: SubstrateDataProviderFactoryProtocol
let storageFacade: StorageFacadeProtocol
let operationManager: OperationManagerProtocol
let logger: LoggerProtocol

init(
chainRegistry: ChainRegistryProtocol,
streamableProviderFactory: SubstrateDataProviderFactoryProtocol,
storageFacade: StorageFacadeProtocol,
operationManager: OperationManagerProtocol,
logger: LoggerProtocol
) {
self.chainRegistry = chainRegistry
self.streamableProviderFactory = streamableProviderFactory
self.storageFacade = storageFacade
self.operationManager = operationManager
self.logger = logger
Expand Down Expand Up @@ -64,4 +80,54 @@ extension ProxyListLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryPr

return provider
}

func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition> {
clearIfNeeded()

let codingPath = Proxy.proxyList
let localKey = try LocalStorageKeyFactory().createFromStoragePath(
codingPath,
accountId: accountId,
chainId: chainId
)

if let dataProvider = getProvider(for: localKey) as? DataProvider<DecodedProxyDefinition> {
return AnyDataProvider(dataProvider)
}

guard let runtimeCodingProvider = chainRegistry.getRuntimeProvider(for: chainId) else {
throw ChainRegistryError.runtimeMetadaUnavailable
}

let repository = InMemoryDataProviderRepository<DecodedProxyDefinition>()

let streamableProvider = streamableProviderFactory.createStorageProvider(for: localKey)
let fallback = StorageProviderSourceFallback<ProxyDefinition>.init(
usesRuntimeFallback: false,
missingEntryStrategy: .defaultValue(nil)
)
let trigger = DataProviderProxyTrigger()
let source: StorageProviderSource<ProxyDefinition> = StorageProviderSource(
itemIdentifier: localKey,
possibleCodingPaths: [codingPath],
runtimeService: runtimeCodingProvider,
provider: streamableProvider,
trigger: trigger,
fallback: fallback,
operationManager: operationManager
)

let dataProvider = DataProvider(
source: AnyDataProviderSource(source),
repository: AnyDataProviderRepository(repository),
updateTrigger: trigger
)

saveProvider(dataProvider, for: localKey)

return AnyDataProvider(dataProvider)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ protocol ProxyListLocalStorageSubscriber where Self: AnyObject {
var proxyListLocalSubscriptionHandler: ProxyListLocalSubscriptionHandler { get }

func subscribeAllProxies() -> StreamableProvider<ProxyAccountModel>?

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id,
modifyInternalList: @escaping (ProxyDefinition) -> ProxyDefinition
) -> AnyDataProvider<DecodedProxyDefinition>?
}

extension ProxyListLocalStorageSubscriber {
Expand Down Expand Up @@ -42,6 +48,54 @@ extension ProxyListLocalStorageSubscriber {

return provider
}

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id,
modifyInternalList: @escaping (ProxyDefinition) -> ProxyDefinition
) -> AnyDataProvider<DecodedProxyDefinition>? {
guard let provider = try? proxyListLocalSubscriptionFactory.getProxyListProvider(
for: accountId,
chainId: chainId
) else {
return nil
}

let updateClosure = { [weak self] (changes: [DataProviderChange<DecodedProxyDefinition>]) in
let proxies = changes.reduceToLastChange()?.item.map { modifyInternalList($0) } ?? nil

self?.proxyListLocalSubscriptionHandler.handleProxies(
result: .success(proxies),
accountId: accountId,
chainId: chainId
)
return
}

let failureClosure = { [weak self] (error: Error) in
self?.proxyListLocalSubscriptionHandler.handleProxies(
result: .failure(error),
accountId: accountId,
chainId: chainId
)
return
}

let options = DataProviderObserverOptions(
alwaysNotifyOnRefresh: false,
waitsInProgressSyncOnAdd: false
)

provider.addObserver(
self,
deliverOn: .main,
executing: updateClosure,
failing: failureClosure,
options: options
)

return provider
}
}

extension ProxyListLocalStorageSubscriber where Self: ProxyListLocalSubscriptionHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ protocol StakingLocalStorageSubscriber where Self: AnyObject {
api: LocalChainExternalApi,
assetPrecision: Int16
) -> AnySingleValueProvider<TotalRewardItem>?

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id
) -> AnyDataProvider<DecodedProxyDefinition>?
}

extension StakingLocalStorageSubscriber {
Expand Down Expand Up @@ -653,53 +648,6 @@ extension StakingLocalStorageSubscriber {

return provider
}

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id
) -> AnyDataProvider<DecodedProxyDefinition>? {
guard let provider = try? stakingLocalSubscriptionFactory.getProxyListProvider(
for: accountId,
chainId: chainId
) else {
return nil
}

let updateClosure = { [weak self] (changes: [DataProviderChange<DecodedProxyDefinition>]) in
let proxies = changes.reduceToLastChange()?.item?.filterStakingProxy()

self?.stakingLocalSubscriptionHandler.handleProxies(
result: .success(proxies),
accountId: accountId,
chainId: chainId
)
return
}

let failureClosure = { [weak self] (error: Error) in
self?.stakingLocalSubscriptionHandler.handleProxies(
result: .failure(error),
accountId: accountId,
chainId: chainId
)
return
}

let options = DataProviderObserverOptions(
alwaysNotifyOnRefresh: false,
waitsInProgressSyncOnAdd: false
)

provider.addObserver(
self,
deliverOn: .main,
executing: updateClosure,
failing: failureClosure,
options: options
)

return provider
}
}

extension StakingLocalStorageSubscriber where Self: StakingLocalSubscriptionHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ protocol StakingLocalSubscriptionHandler {
func handleActiveEra(result: Result<ActiveEraInfo?, Error>, chainId: ChainModel.Id)

func handleCurrentEra(result: Result<EraIndex?, Error>, chainId: ChainModel.Id)

func handleProxies(
result: Result<ProxyDefinition?, Error>,
accountId: AccountId,
chainId: ChainModel.Id
)
}

extension StakingLocalSubscriptionHandler {
Expand Down Expand Up @@ -109,10 +103,4 @@ extension StakingLocalSubscriptionHandler {
func handleActiveEra(result _: Result<ActiveEraInfo?, Error>, chainId _: ChainModel.Id) {}

func handleCurrentEra(result _: Result<EraIndex?, Error>, chainId _: ChainModel.Id) {}

func handleProxies(
result _: Result<ProxyDefinition?, Error>,
accountId _: AccountId,
chainId _: ChainModel.Id
) {}
}
6 changes: 3 additions & 3 deletions novawallet/Common/Services/Proxy/ProxyModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ struct ProxyDefinition: Decodable, Equatable {
}
}

extension ProxyDefinition {
func filterStakingProxy() -> ProxyDefinition {
.init(definition: definition.filter { $0.proxyType.allowStaking })
enum ProxyFilter {
static func filteredStakingProxy(from proxy: ProxyDefinition) -> ProxyDefinition {
ProxyDefinition(definition: proxy.definition.filter { $0.proxyType.allowStaking })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ protocol RelaychainStakingSharedStateProtocol: AnyObject {
var stakingOption: Multistaking.ChainAssetOption { get }
var globalRemoteSubscriptionService: StakingRemoteSubscriptionServiceProtocol { get }
var accountRemoteSubscriptionService: StakingAccountUpdatingServiceProtocol { get }
var proxyLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryProtocol { get }
var localSubscriptionFactory: StakingLocalSubscriptionFactoryProtocol { get }
var eraValidatorService: EraValidatorServiceProtocol { get }
var rewardCalculatorService: RewardCalculatorServiceProtocol { get }
Expand All @@ -29,6 +30,7 @@ final class RelaychainStakingSharedState: RelaychainStakingSharedStateProtocol {
let globalRemoteSubscriptionService: StakingRemoteSubscriptionServiceProtocol
let accountRemoteSubscriptionService: StakingAccountUpdatingServiceProtocol
let localSubscriptionFactory: StakingLocalSubscriptionFactoryProtocol
let proxyLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryProtocol
let eraValidatorService: EraValidatorServiceProtocol
let rewardCalculatorService: RewardCalculatorServiceProtocol
let logger: LoggerProtocol
Expand All @@ -45,6 +47,7 @@ final class RelaychainStakingSharedState: RelaychainStakingSharedStateProtocol {
globalRemoteSubscriptionService: StakingRemoteSubscriptionServiceProtocol,
accountRemoteSubscriptionService: StakingAccountUpdatingServiceProtocol,
localSubscriptionFactory: StakingLocalSubscriptionFactoryProtocol,
proxyLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryProtocol,
eraValidatorService: EraValidatorServiceProtocol,
rewardCalculatorService: RewardCalculatorServiceProtocol,
timeModel: StakingTimeModel,
Expand All @@ -55,6 +58,7 @@ final class RelaychainStakingSharedState: RelaychainStakingSharedStateProtocol {
self.globalRemoteSubscriptionService = globalRemoteSubscriptionService
self.accountRemoteSubscriptionService = accountRemoteSubscriptionService
self.localSubscriptionFactory = localSubscriptionFactory
self.proxyLocalSubscriptionFactory = proxyLocalSubscriptionFactory
self.eraValidatorService = eraValidatorService
self.rewardCalculatorService = rewardCalculatorService
self.timeModel = timeModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ final class StakingSharedStateFactory {
let rewardCalculatorService: RewardCalculatorServiceProtocol
let timeModel: StakingTimeModel
let localSubscriptionFactory: StakingLocalSubscriptionFactoryProtocol
let proxySubscriptionFactory: ProxyListLocalSubscriptionFactoryProtocol
}

struct NominationPoolsServices {
Expand Down Expand Up @@ -166,7 +167,8 @@ final class StakingSharedStateFactory {
eraValidatorService: globalServices.eraValidatorService,
rewardCalculatorService: globalServices.rewardCalculatorService,
timeModel: globalServices.timeModel,
localSubscriptionFactory: globalServices.localSubscriptionFactory
localSubscriptionFactory: globalServices.localSubscriptionFactory,
proxySubscriptionFactory: ProxyListLocalSubscriptionFactory.shared
)
}

Expand Down Expand Up @@ -260,6 +262,7 @@ extension StakingSharedStateFactory: StakingSharedStateFactoryProtocol {
globalRemoteSubscriptionService: services.globalRemoteSubscriptionService,
accountRemoteSubscriptionService: services.accountRemoteSubscriptionService,
localSubscriptionFactory: services.localSubscriptionFactory,
proxyLocalSubscriptionFactory: services.proxySubscriptionFactory,
eraValidatorService: services.eraValidatorService,
rewardCalculatorService: services.rewardCalculatorService,
timeModel: services.timeModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ extension StakingRelaychainInteractor {
nominatorProvider = subscribeNomination(for: stashAccountId, chainId: chainId)
validatorProvider = subscribeValidator(for: stashAccountId, chainId: chainId)
payeeProvider = subscribePayee(for: stashAccountId, chainId: chainId)
proxyProvider = subscribeProxies(for: stashAccountId, chainId: chainId)
proxyProvider = subscribeProxies(
for: stashAccountId,
chainId: chainId,
modifyInternalList: ProxyFilter.filteredStakingProxy
)

performTotalRewardSubscription()

Expand Down Expand Up @@ -262,7 +266,9 @@ extension StakingRelaychainInteractor: StakingLocalStorageSubscriber, StakingLoc
presenter?.didReceiveBagListScoreFactor(result: .failure(error))
}
}
}

extension StakingRelaychainInteractor: ProxyListLocalStorageSubscriber, ProxyListLocalSubscriptionHandler {
func handleProxies(result: Result<ProxyDefinition?, Error>, accountId _: AccountId, chainId _: ChainModel.Id) {
presenter?.didReceiveProxy(result: result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ final class StakingRelaychainInteractor: RuntimeConstantFetching, AnyCancellable
sharedState.localSubscriptionFactory
}

var proxyListLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryProtocol {
sharedState.proxyLocalSubscriptionFactory
}

var stakingOption: Multistaking.ChainAssetOption { sharedState.stakingOption }

let chainRegistry: ChainRegistryProtocol
Expand Down
Loading
Loading