[Refactoring] make tokenAdaptor single for each wallet session #6322

pull/6322/head
Krypto Pank 2 years ago
parent cd919ac11f
commit 97672a4ee6
  1. 4
      AlphaWallet/AppCoordinator.swift
  2. 2
      AlphaWallet/Tokens/Coordinators/FungibleTokenCoordinator.swift
  3. 2
      AlphaWallet/Tokens/Coordinators/SingleChainTokenCoordinator.swift
  4. 4
      AlphaWallet/Tokens/ViewModels/FungibleTokenDetailsViewModel.swift
  5. 4
      AlphaWallet/Transfer/ViewModels/TransactionConfirmation/DappOrWalletConnectTransactionViewModel.swift
  6. 6
      AlphaWallet/Transfer/ViewModels/TransactionConfirmation/SendFungiblesTransactionViewModel.swift
  7. 15
      AlphaWalletTests/Factories/FakeSessionsProvider.swift
  8. 11
      AlphaWalletTests/Factories/WalletSession.swift
  9. 4
      AlphaWalletTests/Tokens/Helpers/TokenAdaptorTest.swift
  10. 6
      AlphaWalletTests/ViewControllers/PaymentCoordinatorTests.swift
  11. 3
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Activities/ActivitiesService.swift
  12. 10
      modules/AlphaWalletFoundation/AlphaWalletFoundation/TokenScriptClient/EventSource.swift
  13. 68
      modules/AlphaWalletFoundation/AlphaWalletFoundation/TokenScriptClient/Models/TokenScriptSupportable.swift
  14. 170
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Tokens/Helpers/TokenAdaptor.swift
  15. 27
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Tokens/TokensProcessingPipeline.swift
  16. 16
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Tokens/Types/TokenViewModel.swift
  17. 5
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Types/Session.swift
  18. 9
      modules/AlphaWalletFoundation/AlphaWalletFoundation/Types/SessionsProvider.swift

@ -594,6 +594,7 @@ class AppCoordinator: NSObject, Coordinator {
analytics: analytics,
blockchainsProvider: blockchainsProvider,
tokensDataStore: tokensDataStore,
eventsDataStore: eventsDataStore,
assetDefinitionStore: assetDefinitionStore,
reachability: reachability,
wallet: wallet)
@ -614,7 +615,8 @@ class AppCoordinator: NSObject, Coordinator {
coinTickersFetcher: coinTickersFetcher,
assetDefinitionStore: assetDefinitionStore,
eventsDataStore: eventsDataStore,
currencyService: currencyService)
currencyService: currencyService,
sessionsProvider: sessionsProvider)
pipeline.start()

@ -154,7 +154,7 @@ extension FungibleTokenCoordinator: FungibleTokenDetailsViewControllerDelegate {
func didTap(action: TokenInstanceAction, token: Token, in viewController: FungibleTokenDetailsViewController) {
guard let navigationController = viewController.navigationController else { return }
let tokenHolder = token.getTokenHolder(assetDefinitionStore: assetDefinitionStore, forWallet: session.account)
let tokenHolder = session.tokenAdaptor.getTokenHolder(token: token)
delegate?.didPress(for: .send(type: .tokenScript(action: action, token: token, tokenHolder: tokenHolder)), viewController: navigationController, in: self)
}

@ -112,7 +112,7 @@ class SingleChainTokenCoordinator: Coordinator {
}
private func showTokenInstanceActionView(forAction action: TokenInstanceAction, fungibleTokenObject token: Token, navigationController: UINavigationController) {
let tokenHolder = token.getTokenHolder(assetDefinitionStore: assetDefinitionStore, forWallet: session.account)
let tokenHolder = session.tokenAdaptor.getTokenHolder(token: token)
delegate?.didPress(for: .send(type: .tokenScript(action: action, token: token, tokenHolder: tokenHolder)), viewController: navigationController, in: self)
}
}

@ -24,7 +24,7 @@ final class FungibleTokenDetailsViewModel {
.map { $0?.balance.ticker }
.eraseToAnyPublisher()
}()
private lazy var tokenHolder: TokenHolder = token.getTokenHolder(assetDefinitionStore: assetDefinitionStore, forWallet: session.account)
private lazy var tokenHolder: TokenHolder = session.tokenAdaptor.getTokenHolder(token: token)
private let session: WalletSession
private let assetDefinitionStore: AssetDefinitionStore
private let tokenActionsProvider: SupportedTokenActionsProvider
@ -81,7 +81,7 @@ final class FungibleTokenDetailsViewModel {
}
private func buildTokenActions() -> [TokenInstanceAction] {
let xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
let xmlHandler = session.tokenAdaptor.xmlHandler(token: token)
let actionsFromTokenScript = xmlHandler.actions
infoLog("[TokenScript] actions names: \(actionsFromTokenScript.map(\.name))")
if actionsFromTokenScript.isEmpty {

@ -124,7 +124,7 @@ extension TransactionConfirmationViewModel {
case .nativeCryptocurrency:
symbol = transactionType.tokenObject.symbol
case .erc20, .erc1155, .erc721, .erc721ForTickets, .erc875:
symbol = transactionType.tokenObject.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
symbol = session.tokenAdaptor.tokenScriptOverrides(token: transactionType.tokenObject).symbolInPluralForm
}
let newBalance = NumberFormatter.shortCrypto.string(for: newBalance) ?? "-"
@ -138,7 +138,7 @@ extension TransactionConfirmationViewModel {
case .nativeCryptocurrency:
symbol = transactionType.tokenObject.symbol
case .erc20, .erc1155, .erc721, .erc721ForTickets, .erc875:
symbol = transactionType.tokenObject.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
symbol = session.tokenAdaptor.tokenScriptOverrides(token: transactionType.tokenObject).symbolInPluralForm
}
let balance = NumberFormatter.shortCrypto.string(for: balance)

@ -144,7 +144,7 @@ extension TransactionConfirmationViewModel {
case .nativeCryptocurrency:
symbol = transactionType.tokenObject.symbol
case .erc20, .erc1155, .erc721, .erc721ForTickets, .erc875:
symbol = transactionType.tokenObject.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
symbol = session.tokenAdaptor.tokenScriptOverrides(token: transactionType.tokenObject).symbolInPluralForm
}
//TODO: extract to constants
@ -187,7 +187,7 @@ extension TransactionConfirmationViewModel {
case .nativeCryptocurrency:
symbol = transactionType.tokenObject.symbol
case .erc20, .erc1155, .erc721, .erc721ForTickets, .erc875:
symbol = transactionType.tokenObject.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
symbol = session.tokenAdaptor.tokenScriptOverrides(token: transactionType.tokenObject).symbolInPluralForm
}
let newBalance = NumberFormatter.shortCrypto.string(for: newBalance) ?? "-"
@ -201,7 +201,7 @@ extension TransactionConfirmationViewModel {
case .nativeCryptocurrency:
symbol = transactionType.tokenObject.symbol
case .erc20, .erc1155, .erc721, .erc721ForTickets, .erc875:
symbol = transactionType.tokenObject.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
symbol = session.tokenAdaptor.tokenScriptOverrides(token: transactionType.tokenObject).symbolInPluralForm
}
let balance = NumberFormatter.alternateAmount.string(double: balance)

@ -44,7 +44,8 @@ extension FakeSessionsProvider {
tokensDataStore: FakeTokensDataStore(servers: servers),
assetDefinitionStore: .make(),
reachability: FakeReachabilityManager(true),
wallet: wallet)
wallet: wallet,
eventsDataStore: FakeEventsDataStore(account: wallet))
provider.start()
@ -62,6 +63,7 @@ class FakeSessionsProvider: SessionsProvider {
private let assetDefinitionStore: AssetDefinitionStore
private let reachability: ReachabilityManagerProtocol
private let wallet: Wallet
private let eventsDataStore: NonActivityEventsDataStore
var sessions: AnyPublisher<ServerDictionary<WalletSession>, Never> {
return sessionsSubject.eraseToAnyPublisher()
@ -84,7 +86,8 @@ class FakeSessionsProvider: SessionsProvider {
tokensDataStore: FakeTokensDataStore(servers: servers),
assetDefinitionStore: .make(),
reachability: FakeReachabilityManager(false),
wallet: .make())
wallet: .make(),
eventsDataStore: FakeEventsDataStore(account: .make()))
}
init(config: Config,
@ -93,8 +96,10 @@ class FakeSessionsProvider: SessionsProvider {
tokensDataStore: TokensDataStore,
assetDefinitionStore: AssetDefinitionStore,
reachability: ReachabilityManagerProtocol,
wallet: Wallet) {
wallet: Wallet,
eventsDataStore: NonActivityEventsDataStore) {
self.eventsDataStore = eventsDataStore
self.wallet = wallet
self.reachability = reachability
self.assetDefinitionStore = assetDefinitionStore
@ -149,6 +154,7 @@ class FakeSessionsProvider: SessionsProvider {
server: blockchain.server,
reachability: reachability)
}
let tokenAdaptor = TokenAdaptor(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, wallet: wallet)
return WalletSession(
account: wallet,
@ -158,7 +164,8 @@ class FakeSessionsProvider: SessionsProvider {
ercTokenProvider: ercTokenProvider,
importToken: importToken,
blockchainProvider: blockchain,
nftProvider: FakeNftProvider())
nftProvider: FakeNftProvider(),
tokenAdaptor: tokenAdaptor)
}
public func session(for server: RPCServer) -> WalletSession? {

@ -9,20 +9,23 @@ extension WalletSession {
let blockchainProvider = RpcBlockchainProvider(server: server, analytics: analytics, params: .defaultParams(for: server))
let ercTokenProvider = TokenProvider(account: account, blockchainProvider: blockchainProvider)
let importToken: ImportToken = .make(server: server)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider())
let tokenAdaptor = TokenAdaptor(assetDefinitionStore: .make(), eventsDataStore: FakeEventsDataStore(account: account), wallet: account)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider(), tokenAdaptor: tokenAdaptor)
}
static func make(account: Wallet = .make(), server: RPCServer = .main, config: Config = .make(), analytics: AnalyticsLogger = FakeAnalyticsService(), importToken: TokenImportable & TokenOrContractFetchable) -> WalletSession {
let blockchainProvider = RpcBlockchainProvider(server: server, analytics: analytics, params: .defaultParams(for: server))
let ercTokenProvider = TokenProvider(account: account, blockchainProvider: blockchainProvider)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider())
let tokenAdaptor = TokenAdaptor(assetDefinitionStore: .make(), eventsDataStore: FakeEventsDataStore(account: account), wallet: account)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider(), tokenAdaptor: tokenAdaptor)
}
static func makeStormBirdSession(account: Wallet = .makeStormBird(), server: RPCServer, config: Config = .make(), analytics: AnalyticsLogger = FakeAnalyticsService()) -> WalletSession {
let blockchainProvider = RpcBlockchainProvider(server: server, analytics: analytics, params: .defaultParams(for: server))
let ercTokenProvider = TokenProvider(account: account, blockchainProvider: blockchainProvider)
let importToken: ImportToken = .make(server: server)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider())
let tokenAdaptor = TokenAdaptor(assetDefinitionStore: .make(), eventsDataStore: FakeEventsDataStore(account: account), wallet: account)
return WalletSession(account: account, server: server, config: config, analytics: analytics, ercTokenProvider: ercTokenProvider, importToken: importToken, blockchainProvider: blockchainProvider, nftProvider: FakeNftProvider(), tokenAdaptor: tokenAdaptor)
}
}

@ -43,7 +43,7 @@ class TokenAdaptorTest: XCTestCase {
]
let assetDefinitionStore = AssetDefinitionStore.make()
let token = Token(contract: Constants.nullAddress)
let bundles = TokenAdaptor(token: token, assetDefinitionStore: assetDefinitionStore, eventsDataStore: FakeEventsDataStore()).bundleTestsOnly(tokens: tokens)
let bundles = TokenAdaptor(assetDefinitionStore: assetDefinitionStore, eventsDataStore: FakeEventsDataStore(), wallet: .make()).bundleTestsOnly(tokens: tokens, token: token)
XCTAssertEqual(bundles.count, 2)
}
@ -94,7 +94,7 @@ class TokenAdaptorTest: XCTestCase {
let assetDefinitionStore = AssetDefinitionStore.make()
let token = Token(contract: Constants.nullAddress)
let bundles = TokenAdaptor(token: token, assetDefinitionStore: assetDefinitionStore, eventsDataStore: FakeEventsDataStore()).bundleTestsOnly(tokens: tokens)
let bundles = TokenAdaptor(assetDefinitionStore: assetDefinitionStore, eventsDataStore: FakeEventsDataStore(), wallet: .make()).bundleTestsOnly(tokens: tokens, token: token)
XCTAssertEqual(bundles.count, 2)
}

@ -35,7 +35,8 @@ extension WalletDataProcessingPipeline {
tokensDataStore: tokensDataStore,
assetDefinitionStore: .make(),
reachability: FakeReachabilityManager(true),
wallet: wallet)
wallet: wallet,
eventsDataStore: FakeEventsDataStore(account: wallet))
sessionsProvider.start()
@ -60,7 +61,8 @@ extension WalletDataProcessingPipeline {
coinTickersFetcher: coinTickersFetcher,
assetDefinitionStore: .make(),
eventsDataStore: eventsDataStore,
currencyService: currencyService)
currencyService: currencyService,
sessionsProvider: sessionsProvider)
let fetcher = WalletBalanceFetcher(wallet: wallet, tokensService: pipeline, currencyService: .make())

@ -212,6 +212,7 @@ public class ActivitiesService: NSObject, ActivitiesServiceType {
let activitiesForThisCard: [ActivityTokenObjectTokenHolder] = events.compactMap { eachEvent in
guard let token = tokensService.token(for: contract, server: server) else { return nil }
guard let session = sessions[safe: token.server] else { return nil }
let implicitAttributes = generateImplicitAttributesForToken(forContract: contract, server: server, symbol: token.symbol)
let tokenAttributes = implicitAttributes
@ -235,7 +236,7 @@ public class ActivitiesService: NSObject, ActivitiesServiceType {
tokenHolders = [TokenHolder(tokens: [_token], contractAddress: token.contractAddress, hasAssetDefinition: true)]
} else {
tokenHolders = token.getTokenHolders(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet)
tokenHolders = session.tokenAdaptor.getTokenHolders(token: token)
}
tokensAndTokenHolders[token.addressAndRPCServer] = tokenHolders
}

@ -18,6 +18,7 @@ final class EventSource: NSObject {
private var cancellable = Set<AnyCancellable>()
private let tokensService: TokenProvidable
private let eventFetcher: EventFetcher
private let sessionsProvider: SessionsProvider
init(wallet: Wallet,
tokensService: TokenProvidable,
@ -26,6 +27,7 @@ final class EventSource: NSObject {
config: Config,
sessionsProvider: SessionsProvider) {
self.sessionsProvider = sessionsProvider
self.wallet = wallet
self.assetDefinitionStore = assetDefinitionStore
self.eventsDataStore = eventsDataStore
@ -89,13 +91,9 @@ final class EventSource: NSObject {
for each in xmlHandler.attributesWithEventSource {
guard let eventOrigin = each.eventOrigin else { continue }
guard let session = sessionsProvider.session(for: token.server) else { continue }
let tokenHolders = token.getTokenHolders(
assetDefinitionStore: assetDefinitionStore,
eventsDataStore: eventsDataStore,
forWallet: wallet,
isSourcedFromEvents: false)
let tokenHolders = session.tokenAdaptor.getTokenHolders(token: token, isSourcedFromEvents: false)
let tokenIds = tokenHolders.flatMap { $0.tokenIds }
cards.append((eventOrigin, tokenIds))

@ -19,15 +19,15 @@ public protocol TokenScriptSupportable {
var balanceNft: [TokenBalanceValue] { get }
}
public extension TokenScriptSupportable {
public extension TokenAdaptor {
func title(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore).getLabel(fallback: name)
return title(withAssetDefinitionStore: assetDefinitionStore, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition, symbol: symbol)
func title(token: TokenScriptSupportable) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore).getLabel(fallback: token.name)
return title(token: token, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition, symbol: token.symbol)
}
func titleInPluralForm(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore, eventsDataStore: NonActivityEventsDataStore, forWallet wallet: Wallet) -> String? {
if let tokenHolders = getTokenHolders(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet).first {
func titleInPluralFormOptional(token: TokenScriptSupportable) -> String? {
if let tokenHolders = getTokenHolders(token: token).first {
guard let name = tokenHolders.tokens.first?.values.collectionValue?.name, name.nonEmpty else { return nil }
return name
} else {
@ -35,13 +35,13 @@ public extension TokenScriptSupportable {
}
}
func titleInPluralForm(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore).getNameInPluralForm(fallback: name)
return title(withAssetDefinitionStore: assetDefinitionStore, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition, symbol: symbol)
func titleInPluralForm(token: TokenScriptSupportable) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore).getNameInPluralForm(fallback: token.name)
return title(token: token, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition, symbol: token.symbol)
}
private func title(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore, localizedNameFromAssetDefinition: String, symbol: String) -> String {
let compositeName = compositeTokenName(forContract: contractAddress, fromContractName: name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
private func title(token: TokenScriptSupportable, localizedNameFromAssetDefinition: String, symbol: String) -> String {
let compositeName = compositeTokenName(forContract: token.contractAddress, fromContractName: token.name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
if compositeName.isEmpty {
return symbol
} else {
@ -68,31 +68,31 @@ public extension TokenScriptSupportable {
//
// Use shortest of name and symbol, but abbreviate to 5 characters or less and capitalise.
func shortTitleInPluralForm(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore, eventsDataStore: NonActivityEventsDataStore, forWallet wallet: Wallet) -> String {
func shortTitleInPluralForm(token: TokenScriptSupportable) -> String {
func compositeTokenNameAndSymbol(symbol: String, name: String) -> String {
let daiSymbol = "DAI\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}"
//We could have just trimmed away all trailing \0, but this is faster and safer since only DAI seems to have this problem
if daiSymbol == symbol {
return "\(valueBI) (DAI)".uppercased()
return "\(token.valueBI) (DAI)".uppercased()
} else {
return "\(valueBI) (\(symbol))".uppercased()
return "\(token.valueBI) (\(symbol))".uppercased()
}
}
let xmlHandler = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore)
let xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
func _compositeTokenName(fallback: String = "") -> String {
let localizedNameFromAssetDefinition = xmlHandler.getNameInPluralForm(fallback: fallback)
return compositeTokenName(forContract: contractAddress, fromContractName: name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
return compositeTokenName(forContract: token.contractAddress, fromContractName: token.name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
}
let localizedNameFromAssetDefinition = _compositeTokenName()
let symbol = self.symbol(withAssetDefinitionStore: assetDefinitionStore, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
let symbol = self.symbol(token: token, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
if localizedNameFromAssetDefinition.isEmpty {
if let name = titleInPluralForm(withAssetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet) {
if let name = titleInPluralFormOptional(token: token) {
return name
} else {
let tokenName = _compositeTokenName(fallback: name)
let tokenName = _compositeTokenName(fallback: token.name)
if tokenName.isEmpty {
return symbol
@ -117,28 +117,28 @@ public extension TokenScriptSupportable {
}
}
func shortTitleInPluralForm(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore) -> String {
func shortTitleInPluralForm2(token: TokenScriptSupportable) -> String {
func compositeTokenNameAndSymbol(symbol: String, name: String) -> String {
let daiSymbol = "DAI\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}"
//We could have just trimmed away all trailing \0, but this is faster and safer since only DAI seems to have this problem
if daiSymbol == symbol {
return "\(valueBI) (DAI)".uppercased()
return "\(token.valueBI) (DAI)".uppercased()
} else {
return "\(valueBI) (\(symbol))".uppercased()
return "\(token.valueBI) (\(symbol))".uppercased()
}
}
let xmlHandler = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore)
let xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
func _compositeTokenName(fallback: String = "") -> String {
let localizedNameFromAssetDefinition = xmlHandler.getNameInPluralForm(fallback: fallback)
return compositeTokenName(forContract: contractAddress, fromContractName: name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
return compositeTokenName(forContract: token.contractAddress, fromContractName: token.name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
}
let localizedNameFromAssetDefinition = _compositeTokenName()
let symbol = self.symbol(withAssetDefinitionStore: assetDefinitionStore, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
let symbol = self.symbol(token: token, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
if localizedNameFromAssetDefinition.isEmpty {
let tokenName = _compositeTokenName(fallback: name)
let tokenName = _compositeTokenName(fallback: token.name)
if tokenName.isEmpty {
return symbol
@ -162,22 +162,22 @@ public extension TokenScriptSupportable {
}
}
func symbolInPluralForm(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore).getNameInPluralForm(fallback: name)
return symbol(withAssetDefinitionStore: assetDefinitionStore, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
func symbolInPluralForm2(token: TokenScriptSupportable) -> String {
let localizedNameFromAssetDefinition = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore).getNameInPluralForm(fallback: token.name)
return symbol(token: token, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
}
private func symbol(withAssetDefinitionStore assetDefinitionStore: AssetDefinitionStore, localizedNameFromAssetDefinition: String) -> String {
let compositeName = compositeTokenName(forContract: contractAddress, fromContractName: name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
private func symbol(token: TokenScriptSupportable, localizedNameFromAssetDefinition: String) -> String {
let compositeName = compositeTokenName(forContract: token.contractAddress, fromContractName: token.name, localizedNameFromAssetDefinition: localizedNameFromAssetDefinition)
if compositeName.isEmpty {
return symbol
return token.symbol
} else {
let daiSymbol = "DAI\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}"
//We could have just trimmed away all trailing \0, but this is faster and safer since only DAI seems to have this problem
if daiSymbol == symbol {
if daiSymbol == token.symbol {
return "DAI"
} else {
return symbol
return token.symbol
}
}
}

@ -35,30 +35,68 @@ extension TokenHolderState {
extension TokenHolder: ObservableObject { }
extension TokenScriptSupportable {
public struct TokenAdaptor {
let assetDefinitionStore: AssetDefinitionStore
let eventsDataStore: NonActivityEventsDataStore
let wallet: Wallet
public func getTokenHolders(assetDefinitionStore: AssetDefinitionStore, eventsDataStore: NonActivityEventsDataStore, forWallet account: Wallet, isSourcedFromEvents: Bool = true) -> [TokenHolder] {
let tokenAdaptor = TokenAdaptor(token: self, assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore)
return tokenAdaptor.getTokenHolders(forWallet: account, isSourcedFromEvents: isSourcedFromEvents)
public init(assetDefinitionStore: AssetDefinitionStore,
eventsDataStore: NonActivityEventsDataStore,
wallet: Wallet) {
self.wallet = wallet
self.assetDefinitionStore = assetDefinitionStore
self.eventsDataStore = eventsDataStore
}
public func xmlHandler(token: TokenScriptSupportable) -> XMLHandler {
return XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
}
public func tokenScriptOverrides(token: TokenScriptSupportable) -> TokenScriptOverrides {
return TokenScriptOverrides(token: token, tokenAdaptor: self)
}
/// Generates token holder for fungible token, with id 1
public func getTokenHolder(assetDefinitionStore: AssetDefinitionStore, forWallet account: Wallet) -> TokenHolder {
//`sourceFromEvents`: We'll usually source from events if available, except when we are actually using this func to create the filter to fetch the events
public func getTokenHolders(token: TokenScriptSupportable, isSourcedFromEvents: Bool = true) -> [TokenHolder] {
switch token.type {
case .nativeCryptocurrency, .erc20, .erc875, .erc721ForTickets:
return getNotSupportedByNonFungibleJsonTokenHolders(token: token)
case .erc721, .erc1155:
let tokenType = NonFungibleFromJsonSupportedTokenHandling(token: token)
switch tokenType {
case .supported:
return getSupportedByNonFungibleJsonTokenHolders(token: token, isSourcedFromEvents: isSourcedFromEvents)
case .notSupported:
return getNotSupportedByNonFungibleJsonTokenHolders(token: token)
}
}
}
public func getTokenHolder(token: TokenScriptSupportable) -> TokenHolder {
//TODO id 1 for fungibles. Might come back to bite us?
let hardcodedTokenIdForFungibles = BigUInt(1)
let xmlHandler = XMLHandler(token: self, assetDefinitionStore: assetDefinitionStore)
let xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
//TODO Event support, if/when designed for fungibles
let values = xmlHandler.resolveAttributesBypassingCache(
withTokenIdOrEvent: .tokenId(tokenId: hardcodedTokenIdForFungibles),
server: server,
account: account,
server: token.server,
account: wallet,
assetDefinitionStore: assetDefinitionStore)
let subscribablesForAttributeValues = values.values
let allResolved = subscribablesForAttributeValues.allSatisfy { $0.subscribableValue?.value != nil }
let token = TokenScript.Token(tokenIdOrEvent: .tokenId(tokenId: hardcodedTokenIdForFungibles), tokenType: type, index: 0, name: name, symbol: symbol, status: .available, values: values)
let tokenHolder = TokenHolder(tokens: [token], contractAddress: contractAddress, hasAssetDefinition: true)
let tokenScriptToken = TokenScript.Token(
tokenIdOrEvent: .tokenId(tokenId: hardcodedTokenIdForFungibles),
tokenType: token.type,
index: 0,
name: token.name,
symbol: token.symbol,
status: .available,
values: values)
let tokenHolder = TokenHolder(tokens: [tokenScriptToken], contractAddress: token.contractAddress, hasAssetDefinition: true)
if allResolved {
//no-op
@ -73,41 +111,9 @@ extension TokenScriptSupportable {
return tokenHolder
}
}
public class TokenAdaptor {
private let token: TokenScriptSupportable
private let assetDefinitionStore: AssetDefinitionStore
private let eventsDataStore: NonActivityEventsDataStore
private let xmlHandler: XMLHandler
public init(token: TokenScriptSupportable,
assetDefinitionStore: AssetDefinitionStore,
eventsDataStore: NonActivityEventsDataStore) {
self.token = token
self.assetDefinitionStore = assetDefinitionStore
self.eventsDataStore = eventsDataStore
self.xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
}
//`sourceFromEvents`: We'll usually source from events if available, except when we are actually using this func to create the filter to fetch the events
public func getTokenHolders(forWallet account: Wallet, isSourcedFromEvents: Bool = true) -> [TokenHolder] {
switch token.type {
case .nativeCryptocurrency, .erc20, .erc875, .erc721ForTickets:
return getNotSupportedByNonFungibleJsonTokenHolders(forWallet: account)
case .erc721, .erc1155:
let tokenType = NonFungibleFromJsonSupportedTokenHandling(token: token)
switch tokenType {
case .supported:
return getSupportedByNonFungibleJsonTokenHolders(forWallet: account, isSourcedFromEvents: isSourcedFromEvents)
case .notSupported:
return getNotSupportedByNonFungibleJsonTokenHolders(forWallet: account)
}
}
}
private func getNotSupportedByNonFungibleJsonTokenHolders(forWallet account: Wallet) -> [TokenHolder] {
//TODO: is it possible to make single token holder with multiple token ids without making each token holder for each token id?
private func getNotSupportedByNonFungibleJsonTokenHolders(token: TokenScriptSupportable) -> [TokenHolder] {
var tokens = [TokenScript.Token]()
switch token.type {
case .erc875, .erc721ForTickets, .erc721, .erc1155, .nativeCryptocurrency:
@ -116,62 +122,56 @@ public class TokenAdaptor {
let id = item.balance
guard isNonZeroBalance(id, tokenType: token.type) else { continue }
if let tokenInt = BigUInt(id.drop0x, radix: 16) {
let server = self.token.server
//TODO Event support, if/when designed, for non-OpenSea. Probably need `distinct` or something to that effect
let token = getToken(name: self.token.name, symbol: self.token.symbol, forTokenIdOrEvent: .tokenId(tokenId: tokenInt), index: UInt16(index), inWallet: account, server: server)
let token = getToken(name: token.name, symbol: token.symbol, forTokenIdOrEvent: .tokenId(tokenId: tokenInt), index: UInt16(index), token: token)
tokens.append(token)
}
}
return bundle(tokens: tokens)
return bundle(tokens: tokens, token: token)
case .erc20:
//For fungibles, we have to get 1 token even if the balance.count is 0. Maybe we check value? No, even if value is 0, there might be attributes
let tokenInt: BigUInt = .init(1)
let index = 0
let server = self.token.server
//TODO Event support, if/when designed, for non-OpenSea. Probably need `distinct` or something to that effect
let token = getToken(name: self.token.name, symbol: self.token.symbol, forTokenIdOrEvent: .tokenId(tokenId: tokenInt), index: UInt16(index), inWallet: account, server: server)
tokens.append(token)
return bundle(tokens: tokens)
let tokenScriptToken = getToken(name: token.name, symbol: token.symbol, forTokenIdOrEvent: .tokenId(tokenId: tokenInt), index: UInt16(index), token: token)
tokens.append(tokenScriptToken)
return bundle(tokens: tokens, token: token)
}
}
private func getSupportedByNonFungibleJsonTokenHolders(forWallet account: Wallet, isSourcedFromEvents: Bool) -> [TokenHolder] {
private func getSupportedByNonFungibleJsonTokenHolders(token: TokenScriptSupportable, isSourcedFromEvents: Bool) -> [TokenHolder] {
var tokens = [TokenScript.Token]()
for nonFungibleBalance in token.balanceNft.compactMap({ $0.nonFungibleBalance }) {
if let token = getTokenForNonFungible(nonFungible: nonFungibleBalance, inWallet: account, server: self.token.server, isSourcedFromEvents: isSourcedFromEvents, tokenType: self.token.type) {
if let token = getTokenForNonFungible(nonFungible: nonFungibleBalance, token: token, isSourcedFromEvents: isSourcedFromEvents) {
tokens.append(token)
}
}
return bundle(tokens: tokens)
return bundle(tokens: tokens, token: token)
}
//NOTE: internal for testing purposes
public func bundleTestsOnly(tokens: [TokenScript.Token]) -> [TokenHolder] {
bundle(tokens: tokens)
public func bundleTestsOnly(tokens: [TokenScript.Token], token: TokenScriptSupportable) -> [TokenHolder] {
bundle(tokens: tokens, token: token)
}
private func bundle(tokens: [TokenScript.Token]) -> [TokenHolder] {
private func bundle(tokens: [TokenScript.Token], token: TokenScriptSupportable) -> [TokenHolder] {
switch token.type {
case .nativeCryptocurrency, .erc20, .erc875:
if !tokens.isEmpty && tokens[0].isSpawnableMeetupContract {
return tokens.sorted { $0.id < $1.id }.map { getTokenHolder(for: [$0]) }
return tokens.sorted { $0.id < $1.id }.map { getTokenHolder(for: [$0], token: token) }
} else {
break
var tokenHolders: [TokenHolder] = []
for each in groupTokensByFields(tokens: tokens) {
for tokens in breakBundlesFurtherToHaveContinuousSeatRange(tokens: each) {
tokenHolders.append(getTokenHolder(for: tokens, token: token))
}
}
return sortBundlesUpcomingFirst(bundles: tokenHolders)
}
case .erc721, .erc721ForTickets, .erc1155:
return tokens.map { getTokenHolder(for: [$0]) }
}
var tokenHolders: [TokenHolder] = []
let groups = groupTokensByFields(tokens: tokens)
for each in groups {
let results = breakBundlesFurtherToHaveContinuousSeatRange(tokens: each)
for tokens in results {
tokenHolders.append(getTokenHolder(for: tokens))
}
return tokens.map { getTokenHolder(for: [$0], token: token) }
}
tokenHolders = sortBundlesUpcomingFirst(bundles: tokenHolders)
return tokenHolders
}
private func sortBundlesUpcomingFirst(bundles: [TokenHolder]) -> [TokenHolder] {
@ -229,21 +229,25 @@ public class TokenAdaptor {
symbol: String,
forTokenIdOrEvent tokenIdOrEvent: TokenIdOrEvent,
index: UInt16,
inWallet account: Wallet,
server: RPCServer) -> TokenScript.Token {
token: TokenScriptSupportable) -> TokenScript.Token {
xmlHandler.getToken(
let xmlHandler = xmlHandler(token: token)
return xmlHandler.getToken(
name: name,
symbol: symbol,
fromTokenIdOrEvent: tokenIdOrEvent,
index: index,
inWallet: account,
server: server,
inWallet: wallet,
server: token.server,
tokenType: token.type,
assetDefinitionStore: assetDefinitionStore)
}
private func getFirstMatchingEvent(nonFungible: NonFungibleFromJson, inWallet account: Wallet, isSourcedFromEvents: Bool) -> EventInstanceValue? {
private func getFirstMatchingEvent(nonFungible: NonFungibleFromJson,
token: TokenScriptSupportable,
isSourcedFromEvents: Bool) -> EventInstanceValue? {
let xmlHandler = xmlHandler(token: token)
if isSourcedFromEvents, let attributeWithEventSource = xmlHandler.attributesWithEventSource.first, let eventFilter = attributeWithEventSource.eventOrigin?.eventFilter, let eventName = attributeWithEventSource.eventOrigin?.eventName, let eventContract = attributeWithEventSource.eventOrigin?.contract {
let filterName = eventFilter.name
let filterValue: String
@ -252,7 +256,7 @@ public class TokenAdaptor {
case .tokenId:
filterValue = eventFilter.value.replacingOccurrences(of: "${tokenId}", with: nonFungible.tokenId)
case .ownerAddress:
filterValue = eventFilter.value.replacingOccurrences(of: "${ownerAddress}", with: account.address.eip55String)
filterValue = eventFilter.value.replacingOccurrences(of: "${ownerAddress}", with: wallet.address.eip55String)
case .label, .contractAddress, .symbol:
filterValue = eventFilter.value
}
@ -276,7 +280,7 @@ public class TokenAdaptor {
return tokenIdOrEvent
}
private func getTokenForNonFungible(nonFungible: NonFungibleFromJson, inWallet account: Wallet, server: RPCServer, isSourcedFromEvents: Bool, tokenType: TokenType) -> TokenScript.Token? {
private func getTokenForNonFungible(nonFungible: NonFungibleFromJson, token: TokenScriptSupportable, isSourcedFromEvents: Bool) -> TokenScript.Token? {
switch nonFungible.tokenType {
case .erc721:
break
@ -284,13 +288,14 @@ public class TokenAdaptor {
guard !nonFungible.value.isZero else { return nil }
}
let event = getFirstMatchingEvent(nonFungible: nonFungible, inWallet: account, isSourcedFromEvents: isSourcedFromEvents)
let event = getFirstMatchingEvent(nonFungible: nonFungible, token: token, isSourcedFromEvents: isSourcedFromEvents)
let tokenIdOrEvent: TokenIdOrEvent = getTokenIdOrEvent(event: event, nonFungible: nonFungible)
let xmlHandler = xmlHandler(token: token)
var values = xmlHandler.resolveAttributesBypassingCache(
withTokenIdOrEvent: tokenIdOrEvent,
server: token.server,
account: account,
account: wallet,
assetDefinitionStore: assetDefinitionStore)
values.setTokenId(string: nonFungible.tokenId)
@ -350,7 +355,8 @@ public class TokenAdaptor {
values: values)
}
private func getTokenHolder(for tokens: [TokenScript.Token]) -> TokenHolder {
private func getTokenHolder(for tokens: [TokenScript.Token], token: TokenScriptSupportable) -> TokenHolder {
let xmlHandler = xmlHandler(token: token)
return TokenHolder(
tokens: tokens,
contractAddress: token.contractAddress,

@ -73,14 +73,16 @@ public final class WalletDataProcessingPipeline: TokensProcessingPipeline {
return Publishers.Merge(whenCollectionHasChanged, initialSnapshot)
.eraseToAnyPublisher()
}
private let sessionsProvider: SessionsProvider
public init(wallet: Wallet, tokensService: TokensService, coinTickersFetcher: CoinTickersFetcher, assetDefinitionStore: AssetDefinitionStore, eventsDataStore: NonActivityEventsDataStore, currencyService: CurrencyService) {
public init(wallet: Wallet, tokensService: TokensService, coinTickersFetcher: CoinTickersFetcher, assetDefinitionStore: AssetDefinitionStore, eventsDataStore: NonActivityEventsDataStore, currencyService: CurrencyService, sessionsProvider: SessionsProvider) {
self.wallet = wallet
self.currencyService = currencyService
self.eventsDataStore = eventsDataStore
self.tokensService = tokensService
self.coinTickersFetcher = coinTickersFetcher
self.assetDefinitionStore = assetDefinitionStore
self.sessionsProvider = sessionsProvider
}
public func tokens(for servers: [RPCServer]) -> [Token] {
@ -151,17 +153,18 @@ public final class WalletDataProcessingPipeline: TokensProcessingPipeline {
}
public func tokenHolders(for token: TokenIdentifiable) -> [TokenHolder] {
tokenViewModel(for: token.contractAddress, server: token.server).flatMap { [assetDefinitionStore, eventsDataStore, wallet] in
$0.getTokenHolders(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet)
} ?? []
guard let session = sessionsProvider.session(for: token.server) else { return [] }
let tokenAdaptor = session.tokenAdaptor
return tokenViewModel(for: token.contractAddress, server: token.server).flatMap { tokenAdaptor.getTokenHolders(token: $0) } ?? []
}
public func tokenHoldersPublisher(for token: TokenIdentifiable) -> AnyPublisher<[TokenHolder], Never> {
tokenViewModelPublisher(for: token.contractAddress, server: token.server)
guard let session = sessionsProvider.session(for: token.server) else { return .empty() }
let tokenAdaptor = session.tokenAdaptor
return tokenViewModelPublisher(for: token.contractAddress, server: token.server)
.compactMap { $0 }
.map { [assetDefinitionStore, eventsDataStore, wallet] in
$0.getTokenHolders(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet)
}.eraseToAnyPublisher()
.map { tokenAdaptor.getTokenHolders(token: $0) }
.eraseToAnyPublisher()
}
public func token(for contract: AlphaWallet.Address) -> Token? {
@ -219,7 +222,9 @@ public final class WalletDataProcessingPipeline: TokensProcessingPipeline {
private func applyTokenScriptOverrides(tokens: [TokenViewModel]) -> AnyPublisher<[TokenViewModel], Never> {
let overrides = tokens.map { token -> TokenViewModel in
let overrides = TokenScriptOverrides(token: token, assetDefinitionStore: assetDefinitionStore, wallet: wallet, eventsDataStore: eventsDataStore)
guard let session = sessionsProvider.session(for: token.server) else { return token }
let overrides = session.tokenAdaptor.tokenScriptOverrides(token: token)
return token.override(tokenScriptOverrides: overrides)
}
return .just(overrides)
@ -227,8 +232,8 @@ public final class WalletDataProcessingPipeline: TokensProcessingPipeline {
private func applyTokenScriptOverrides(token: TokenViewModel?) -> TokenViewModel? {
guard let token = token else { return token }
let overrides = TokenScriptOverrides(token: token, assetDefinitionStore: assetDefinitionStore, wallet: wallet, eventsDataStore: eventsDataStore)
guard let session = sessionsProvider.session(for: token.server) else { return token }
let overrides = session.tokenAdaptor.tokenScriptOverrides(token: token)
return token.override(tokenScriptOverrides: overrides)
}

@ -34,18 +34,18 @@ public struct TokenScriptOverrides {
public let hasNoBaseAssetDefinition: Bool
public let server: RPCServerOrAny?
init(token: TokenScriptSupportable, assetDefinitionStore: AssetDefinitionStore, wallet: Wallet, eventsDataStore: NonActivityEventsDataStore) {
let xmlHandler = XMLHandler(token: token, assetDefinitionStore: assetDefinitionStore)
self.symbolInPluralForm = token.symbolInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
self.title = token.title(withAssetDefinitionStore: assetDefinitionStore)
init(token: TokenScriptSupportable, tokenAdaptor: TokenAdaptor) {
let xmlHandler = tokenAdaptor.xmlHandler(token: token)
self.symbolInPluralForm = tokenAdaptor.symbolInPluralForm2(token: token)
self.title = tokenAdaptor.title(token: token)
//NOTE: replace if needed
switch token.type {
case .erc20, .nativeCryptocurrency:
self.shortTitleInPluralForm = token.shortTitleInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
self.titleInPluralForm = token.titleInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
self.shortTitleInPluralForm = tokenAdaptor.shortTitleInPluralForm(token: token)
self.titleInPluralForm = tokenAdaptor.titleInPluralForm(token: token)
case .erc875, .erc1155, .erc721, .erc721ForTickets:
self.shortTitleInPluralForm = token.shortTitleInPluralForm(withAssetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet)
self.titleInPluralForm = token.titleInPluralForm(withAssetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, forWallet: wallet) ?? token.titleInPluralForm(withAssetDefinitionStore: assetDefinitionStore)
self.shortTitleInPluralForm = tokenAdaptor.shortTitleInPluralForm(token: token)
self.titleInPluralForm = tokenAdaptor.titleInPluralFormOptional(token: token) ?? tokenAdaptor.titleInPluralForm(token: token)
}
self.hasNoBaseAssetDefinition = xmlHandler.hasNoBaseAssetDefinition

@ -21,6 +21,7 @@ public final class WalletSession: Equatable {
}
public let blockchainProvider: BlockchainProvider
public let nftProvider: NFTProvider
public let tokenAdaptor: TokenAdaptor
public init(account: Wallet,
server: RPCServer,
@ -29,8 +30,10 @@ public final class WalletSession: Equatable {
ercTokenProvider: TokenProviderType,
importToken: TokenImportable & TokenOrContractFetchable,
blockchainProvider: BlockchainProvider,
nftProvider: NFTProvider) {
nftProvider: NFTProvider,
tokenAdaptor: TokenAdaptor) {
self.tokenAdaptor = tokenAdaptor
self.nftProvider = nftProvider
self.analytics = analytics
self.account = account

@ -26,6 +26,7 @@ open class BaseSessionsProvider: SessionsProvider {
private let assetDefinitionStore: AssetDefinitionStore
private let reachability: ReachabilityManagerProtocol
private let wallet: Wallet
private let eventsDataStore: NonActivityEventsDataStore
public var sessions: AnyPublisher<ServerDictionary<WalletSession>, Never> {
return sessionsSubject.eraseToAnyPublisher()
@ -39,10 +40,12 @@ open class BaseSessionsProvider: SessionsProvider {
analytics: AnalyticsLogger,
blockchainsProvider: BlockchainsProvider,
tokensDataStore: TokensDataStore,
eventsDataStore: NonActivityEventsDataStore,
assetDefinitionStore: AssetDefinitionStore,
reachability: ReachabilityManagerProtocol,
wallet: Wallet) {
self.eventsDataStore = eventsDataStore
self.wallet = wallet
self.reachability = reachability
self.assetDefinitionStore = assetDefinitionStore
@ -90,7 +93,8 @@ open class BaseSessionsProvider: SessionsProvider {
reachability: reachability)
let nftProvider = AlphaWalletNFTProvider(analytics: analytics, wallet: wallet, server: blockchain.server, config: config)
let tokenAdaptor = TokenAdaptor(assetDefinitionStore: assetDefinitionStore, eventsDataStore: eventsDataStore, wallet: wallet)
return WalletSession(
account: wallet,
server: blockchain.server,
@ -99,7 +103,8 @@ open class BaseSessionsProvider: SessionsProvider {
ercTokenProvider: ercTokenProvider,
importToken: importToken,
blockchainProvider: blockchain,
nftProvider: nftProvider)
nftProvider: nftProvider,
tokenAdaptor: tokenAdaptor)
}
public func session(for server: RPCServer) -> WalletSession? {

Loading…
Cancel
Save