Skip to content

Commit

Permalink
Merge pull request #422 from nova-wallet/develop
Browse files Browse the repository at this point in the history
v3.9.0
  • Loading branch information
ERussel committed Sep 29, 2022
2 parents 321187a + 383e765 commit 771b2a5
Show file tree
Hide file tree
Showing 153 changed files with 5,425 additions and 1,172 deletions.
232 changes: 199 additions & 33 deletions novawallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Binary file modified novawallet/Assets.xcassets/iconLock.imageset/iconLock.pdf
Binary file not shown.
12 changes: 12 additions & 0 deletions novawallet/Assets.xcassets/iconTransferable.imageset/Contents.json
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.
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
)
}
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>) {}
}
Loading

0 comments on commit 771b2a5

Please sign in to comment.