-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #422 from nova-wallet/develop
v3.9.0
- Loading branch information
Showing
153 changed files
with
5,425 additions
and
1,172 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
12 changes: 12 additions & 0 deletions
12
novawallet/Assets.xcassets/iconTransferable.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "Icon.pdf", | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file not shown.
225 changes: 225 additions & 0 deletions
225
novawallet/Common/DataProvider/CrowdloanContributionLocalSubscriptionFactory.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
import SubstrateSdk | ||
import RobinHood | ||
|
||
protocol CrowdloanContributionLocalSubscriptionFactoryProtocol { | ||
func getCrowdloanContributionDataProvider( | ||
for accountId: AccountId, | ||
chain: ChainModel | ||
) -> StreamableProvider<CrowdloanContributionData>? | ||
|
||
func getAllLocalCrowdloanContributionDataProvider() -> StreamableProvider<CrowdloanContributionData>? | ||
} | ||
|
||
final class CrowdloanContributionLocalSubscriptionFactory: SubstrateLocalSubscriptionFactory, | ||
CrowdloanContributionLocalSubscriptionFactoryProtocol { | ||
let operationFactory: CrowdloanOperationFactoryProtocol | ||
let paraIdOperationFactory: ParaIdOperationFactoryProtocol | ||
let eventCenter: EventCenterProtocol | ||
|
||
init( | ||
operationFactory: CrowdloanOperationFactoryProtocol, | ||
operationManager: OperationManagerProtocol, | ||
chainRegistry: ChainRegistryProtocol, | ||
storageFacade: StorageFacadeProtocol, | ||
paraIdOperationFactory: ParaIdOperationFactoryProtocol, | ||
eventCenter: EventCenterProtocol, | ||
logger: LoggerProtocol | ||
) { | ||
self.operationFactory = operationFactory | ||
self.paraIdOperationFactory = paraIdOperationFactory | ||
self.eventCenter = eventCenter | ||
|
||
super.init( | ||
chainRegistry: chainRegistry, | ||
storageFacade: storageFacade, | ||
operationManager: operationManager, | ||
logger: logger | ||
) | ||
} | ||
|
||
func getCrowdloanContributionDataProvider( | ||
for accountId: AccountId, | ||
chain: ChainModel | ||
) -> StreamableProvider<CrowdloanContributionData>? { | ||
let cacheKey = "crowdloanContributions-\(accountId.toHex())-\(chain.chainId)" | ||
|
||
if let provider = getProvider(for: cacheKey) as? StreamableProvider<CrowdloanContributionData> { | ||
return provider | ||
} | ||
|
||
let offchainSources: [ExternalContributionSourceProtocol] = [ | ||
ParallelContributionSource(), | ||
AcalaContributionSource( | ||
paraIdOperationFactory: paraIdOperationFactory, | ||
acalaChainId: KnowChainId.acala | ||
) | ||
] | ||
|
||
let onChainSyncService = createOnChainSyncService(chainId: chain.chainId, accountId: accountId) | ||
let offChainSyncServices = createOffChainSyncServices( | ||
from: offchainSources, | ||
chain: chain, | ||
accountId: accountId | ||
) | ||
|
||
let syncServices = [onChainSyncService] + offChainSyncServices | ||
|
||
let source = CrowdloanContributionStreamableSource( | ||
syncServices: syncServices, | ||
chainId: chain.chainId, | ||
accountId: accountId, | ||
eventCenter: eventCenter | ||
) | ||
|
||
let crowdloansFilter = NSPredicate.crowdloanContribution( | ||
for: chain.chainId, | ||
accountId: accountId | ||
) | ||
|
||
let mapper = CrowdloanContributionDataMapper() | ||
let repository = storageFacade.createRepository( | ||
filter: crowdloansFilter, | ||
sortDescriptors: [], | ||
mapper: AnyCoreDataMapper(mapper) | ||
) | ||
|
||
let observable = CoreDataContextObservable( | ||
service: storageFacade.databaseService, | ||
mapper: AnyCoreDataMapper(mapper), | ||
predicate: { entity in | ||
accountId.toHex() == entity.chainAccountId && | ||
chain.chainId == entity.chainId | ||
} | ||
) | ||
|
||
observable.start { [weak self] error in | ||
if let error = error { | ||
self?.logger.error("Did receive error: \(error)") | ||
} | ||
} | ||
|
||
let provider = StreamableProvider( | ||
source: AnyStreamableSource(source), | ||
repository: AnyDataProviderRepository(repository), | ||
observable: AnyDataProviderRepositoryObservable(observable), | ||
operationManager: operationManager | ||
) | ||
|
||
saveProvider(provider, for: cacheKey) | ||
|
||
return provider | ||
} | ||
|
||
private func createOnChainSyncService(chainId: ChainModel.Id, accountId: AccountId) -> SyncServiceProtocol { | ||
let mapper = CrowdloanContributionDataMapper() | ||
let onChainFilter = NSPredicate.crowdloanContribution( | ||
for: chainId, | ||
accountId: accountId, | ||
source: nil | ||
) | ||
let onChainCrowdloansRepository = storageFacade.createRepository( | ||
filter: onChainFilter, | ||
sortDescriptors: [], | ||
mapper: AnyCoreDataMapper(mapper) | ||
) | ||
return CrowdloanOnChainSyncService( | ||
operationFactory: operationFactory, | ||
chainRegistry: chainRegistry, | ||
repository: AnyDataProviderRepository(onChainCrowdloansRepository), | ||
accountId: accountId, | ||
chainId: chainId, | ||
operationManager: operationManager, | ||
logger: logger | ||
) | ||
} | ||
|
||
private func createOffChainSyncServices( | ||
from sources: [ExternalContributionSourceProtocol], | ||
chain: ChainModel, | ||
accountId: AccountId | ||
) -> [SyncServiceProtocol] { | ||
let mapper = CrowdloanContributionDataMapper() | ||
|
||
return sources.map { source in | ||
let chainFilter = NSPredicate.crowdloanContribution( | ||
for: chain.chainId, | ||
accountId: accountId, | ||
source: source.sourceName | ||
) | ||
let serviceRepository = storageFacade.createRepository( | ||
filter: chainFilter, | ||
sortDescriptors: [], | ||
mapper: AnyCoreDataMapper(mapper) | ||
) | ||
return CrowdloanOffChainSyncService( | ||
source: source, | ||
chain: chain, | ||
accountId: accountId, | ||
operationManager: operationManager, | ||
repository: AnyDataProviderRepository(serviceRepository), | ||
logger: logger | ||
) | ||
} | ||
} | ||
|
||
func getAllLocalCrowdloanContributionDataProvider() -> StreamableProvider<CrowdloanContributionData>? { | ||
let cacheKey = "all-crowdloanContributions" | ||
|
||
if let provider = getProvider(for: cacheKey) as? StreamableProvider<CrowdloanContributionData> { | ||
return provider | ||
} | ||
|
||
let source = EmptyStreamableSource<CrowdloanContributionData>() | ||
let mapper = CrowdloanContributionDataMapper() | ||
let repository = storageFacade.createRepository( | ||
filter: nil, | ||
sortDescriptors: [], | ||
mapper: AnyCoreDataMapper(mapper) | ||
) | ||
|
||
let observable = CoreDataContextObservable( | ||
service: storageFacade.databaseService, | ||
mapper: AnyCoreDataMapper(mapper), | ||
predicate: { _ in | ||
true | ||
} | ||
) | ||
|
||
observable.start { [weak self] error in | ||
if let error = error { | ||
self?.logger.error("Did receive error: \(error)") | ||
} | ||
} | ||
|
||
let provider = StreamableProvider( | ||
source: AnyStreamableSource(source), | ||
repository: AnyDataProviderRepository(repository), | ||
observable: AnyDataProviderRepositoryObservable(observable), | ||
operationManager: operationManager | ||
) | ||
|
||
saveProvider(provider, for: cacheKey) | ||
|
||
return provider | ||
} | ||
} | ||
|
||
extension CrowdloanContributionLocalSubscriptionFactory { | ||
static let operationManager = OperationManagerFacade.sharedManager | ||
|
||
static let shared = CrowdloanContributionLocalSubscriptionFactory( | ||
operationFactory: CrowdloanOperationFactory( | ||
requestOperationFactory: StorageRequestFactory( | ||
remoteFactory: StorageKeyFactory(), | ||
operationManager: operationManager | ||
), | ||
operationManager: operationManager | ||
), | ||
operationManager: operationManager, | ||
chainRegistry: ChainRegistryFacade.sharedRegistry, | ||
storageFacade: SubstrateDataStorageFacade.shared, | ||
paraIdOperationFactory: ParaIdOperationFactory.shared, | ||
eventCenter: EventCenter.shared, | ||
logger: Logger.shared | ||
) | ||
} |
120 changes: 120 additions & 0 deletions
120
novawallet/Common/DataProvider/Subscription/CrowdloansLocalStorageSubscriber.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import Foundation | ||
import RobinHood | ||
|
||
protocol CrowdloanContributionLocalSubscriptionHandler: AnyObject { | ||
func handleCrowdloans( | ||
result: Result<[DataProviderChange<CrowdloanContributionData>], Error>, | ||
accountId: AccountId, | ||
chain: ChainModel | ||
) | ||
|
||
func handleAllCrowdloans(result: Result<[DataProviderChange<CrowdloanContributionData>], Error>) | ||
} | ||
|
||
protocol CrowdloansLocalStorageSubscriber: AnyObject { | ||
var crowdloansLocalSubscriptionFactory: CrowdloanContributionLocalSubscriptionFactoryProtocol { get } | ||
var crowdloansLocalSubscriptionHandler: CrowdloanContributionLocalSubscriptionHandler { get } | ||
|
||
func subscribeToCrowdloansProvider( | ||
for account: AccountId, | ||
chain: ChainModel | ||
) -> StreamableProvider<CrowdloanContributionData>? | ||
|
||
func subscribeToAllCrowdloansProvider() -> StreamableProvider<CrowdloanContributionData>? | ||
} | ||
|
||
extension CrowdloansLocalStorageSubscriber { | ||
func subscribeToCrowdloansProvider( | ||
for accountId: AccountId, | ||
chain: ChainModel | ||
) -> StreamableProvider<CrowdloanContributionData>? { | ||
guard let provider = crowdloansLocalSubscriptionFactory.getCrowdloanContributionDataProvider( | ||
for: accountId, | ||
chain: chain | ||
) else { | ||
return nil | ||
} | ||
|
||
let updateClosure = { [weak self] (changes: [DataProviderChange<CrowdloanContributionData>]) in | ||
self?.crowdloansLocalSubscriptionHandler.handleCrowdloans( | ||
result: .success(changes), | ||
accountId: accountId, | ||
chain: chain | ||
) | ||
return | ||
} | ||
|
||
let failureClosure = { [weak self] (error: Error) in | ||
self?.crowdloansLocalSubscriptionHandler.handleCrowdloans( | ||
result: .failure(error), | ||
accountId: accountId, | ||
chain: chain | ||
) | ||
return | ||
} | ||
|
||
let options = StreamableProviderObserverOptions( | ||
alwaysNotifyOnRefresh: true, | ||
waitsInProgressSyncOnAdd: false, | ||
initialSize: 0, | ||
refreshWhenEmpty: false | ||
) | ||
|
||
provider.addObserver( | ||
self, | ||
deliverOn: .main, | ||
executing: updateClosure, | ||
failing: failureClosure, | ||
options: options | ||
) | ||
|
||
return provider | ||
} | ||
|
||
func subscribeToAllCrowdloansProvider() -> StreamableProvider<CrowdloanContributionData>? { | ||
guard let provider = crowdloansLocalSubscriptionFactory.getAllLocalCrowdloanContributionDataProvider() else { | ||
return nil | ||
} | ||
|
||
let updateClosure = { [weak self] (changes: [DataProviderChange<CrowdloanContributionData>]) in | ||
self?.crowdloansLocalSubscriptionHandler.handleAllCrowdloans(result: .success(changes)) | ||
return | ||
} | ||
|
||
let failureClosure = { [weak self] (error: Error) in | ||
self?.crowdloansLocalSubscriptionHandler.handleAllCrowdloans(result: .failure(error)) | ||
return | ||
} | ||
|
||
let options = StreamableProviderObserverOptions( | ||
alwaysNotifyOnRefresh: true, | ||
waitsInProgressSyncOnAdd: false, | ||
initialSize: 0, | ||
refreshWhenEmpty: false | ||
) | ||
|
||
provider.addObserver( | ||
self, | ||
deliverOn: .main, | ||
executing: updateClosure, | ||
failing: failureClosure, | ||
options: options | ||
) | ||
|
||
return provider | ||
} | ||
} | ||
|
||
extension CrowdloansLocalStorageSubscriber where Self: CrowdloanContributionLocalSubscriptionHandler { | ||
var crowdloansLocalSubscriptionHandler: CrowdloanContributionLocalSubscriptionHandler { self } | ||
} | ||
|
||
extension CrowdloanContributionLocalSubscriptionHandler { | ||
func handleCrowdloans( | ||
result _: Result<[DataProviderChange<CrowdloanContributionData>], Error>, | ||
accountId _: AccountId, | ||
chain _: ChainModel | ||
) {} | ||
|
||
func handleAllCrowdloans(result _: Result<[DataProviderChange<CrowdloanContributionData>], Error>) {} | ||
} |
Oops, something went wrong.