From e00503d4ef3ca1e8843136e9ba4080f66d1a77c4 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Fri, 15 Mar 2024 17:30:06 +0200 Subject: [PATCH 01/12] add message back --- .../Features/AssetTransferFeature/AssetTransfer+Reducer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RadixWallet/Features/AssetTransferFeature/AssetTransfer+Reducer.swift b/RadixWallet/Features/AssetTransferFeature/AssetTransfer+Reducer.swift index 676e98f6a7..46345a072b 100644 --- a/RadixWallet/Features/AssetTransferFeature/AssetTransfer+Reducer.swift +++ b/RadixWallet/Features/AssetTransferFeature/AssetTransfer+Reducer.swift @@ -77,7 +77,7 @@ public struct AssetTransfer: Sendable, FeatureReducer { let manifest = try await createManifest(accounts) Task { _ = try await dappInteractionClient.addWalletInteraction( - .transaction(.init(send: .init(transactionManifest: manifest))), + .transaction(.init(send: .init(transactionManifest: manifest, message: message))), .accountTransfer ) } From 87e6ac50afd2f097326e094527dee4f7089eaff9 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Fri, 15 Mar 2024 17:39:15 +0200 Subject: [PATCH 02/12] fix missing title --- .../TransferAccountList/TransferAccountList+View.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RadixWallet/Features/AssetTransferFeature/Components/TransferAccountList/TransferAccountList+View.swift b/RadixWallet/Features/AssetTransferFeature/Components/TransferAccountList/TransferAccountList+View.swift index 8f245c6ac6..a14a5f4143 100644 --- a/RadixWallet/Features/AssetTransferFeature/Components/TransferAccountList/TransferAccountList+View.swift +++ b/RadixWallet/Features/AssetTransferFeature/Components/TransferAccountList/TransferAccountList+View.swift @@ -90,11 +90,11 @@ private extension View { private func addAsset(with destinationStore: PresentationStoreOf) -> some View { sheet(store: destinationStore.scope(state: \.state.addAsset, action: \.addAsset)) { assetsStore in AssetsView.View(store: assetsStore) + .navigationTitle(L10n.AssetTransfer.AddAssets.navigationTitle) + .navigationBarTitleDisplayMode(.inline) .withNavigationBar { assetsStore.send(.view(.closeButtonTapped)) } - .navigationTitle(L10n.AssetTransfer.AddAssets.navigationTitle) - .navigationBarTitleDisplayMode(.inline) } } } From 316067b020d1bf17e7efb0b0ef6082b079648d1a Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Wed, 20 Mar 2024 10:06:21 +0200 Subject: [PATCH 03/12] wip --- .../OnLedgerEntitiesClient+ComplexTypes.swift | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift index ff163b94dd..3498ea9cd1 100644 --- a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift +++ b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift @@ -66,7 +66,7 @@ extension OnLedgerEntitiesClient { let isXRD = resourceAddress.isXRD(on: networkID) let details: ResourceBalance.Fungible = .init(isXRD: isXRD, amount: .init(nominalAmount: amount), guarantee: guarantee) - return .init(resource: resource, details: .fungible(details)) + return .init(resource: resource, details: .fungible(details), id: resource.resourceAddress) } private func poolUnit( @@ -115,7 +115,8 @@ extension OnLedgerEntitiesClient { nonXrdResources: nonXrdResources ), guarantee: guarantee - )) + )), + id: resource.resourceAddress ) } else { guard let details = try await getPoolUnitDetails(resource, forAmount: amount) else { @@ -127,7 +128,8 @@ extension OnLedgerEntitiesClient { details: .poolUnit(.init( details: details, guarantee: guarantee - )) + )), + id: resource.resourceAddress ) } } @@ -170,7 +172,7 @@ extension OnLedgerEntitiesClient { guarantee: guarantee ) - return .init(resource: resource, details: .liquidStakeUnit(details)) + return .init(resource: resource, details: .liquidStakeUnit(details), id: resource.resourceAddress) } // MARK: Non-fungibles @@ -220,7 +222,7 @@ extension OnLedgerEntitiesClient { )] } else { result = tokens.map { token in - .init(resource: resource, details: .nonFungible(token)) + .init(resource: resource, details: .nonFungible(token), id: token.id) } guard result.count == ids.count else { @@ -238,7 +240,7 @@ extension OnLedgerEntitiesClient { try NonFungibleGlobalId.fromParts(resourceAddress: resourceAddress.intoEngine(), nonFungibleLocalId: localId) } .map { id in - ResourceBalance(resource: resource, details: .nonFungible(.init(id: id, data: nil))) + ResourceBalance(resource: resource, details: .nonFungible(.init(id: id, data: nil)), id: id) } guard result.count == ids.count else { @@ -296,7 +298,8 @@ extension OnLedgerEntitiesClient { stakeClaims: stakeClaimTokens.asIdentifiable() ), validatorName: stakeClaimValidator.metadata.name - )) + )), + id: resource.id ) } } From 138e86651220e562884b05041ac8a564fccd7aed Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 11:48:09 +0200 Subject: [PATCH 04/12] refresh --- .../AccountPortfoliosClient+Live.swift | 63 ++++++++++++------- RadixWallet/EngineKit/TXID.swift | 2 +- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift index f35119fa7c..18589bd4a0 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift @@ -27,10 +27,10 @@ extension AccountPortfoliosClient: DependencyKey { /// Fetches the pool and stake units details for a given account; Will update the portfolio accordingly @Sendable - func fetchPoolAndStakeUnitsDetails(_ account: OnLedgerEntity.Account) async { + func fetchPoolAndStakeUnitsDetails(_ account: OnLedgerEntity.Account, cachingStrategy: OnLedgerEntitiesClient.CachingStrategy) async { async let poolDetailsFetch = Task { do { - let poolUnitDetails = try await onLedgerEntitiesClient.getOwnedPoolUnitsDetails(account) + let poolUnitDetails = try await onLedgerEntitiesClient.getOwnedPoolUnitsDetails(account, cachingStrategy: cachingStrategy) await state.set(poolDetails: .success(poolUnitDetails), forAccount: account.address) } catch { await state.set(poolDetails: .failure(error), forAccount: account.address) @@ -38,7 +38,7 @@ extension AccountPortfoliosClient: DependencyKey { }.result async let stakeUnitDetails = Task { do { - let stakeUnitDetails = try await onLedgerEntitiesClient.getOwnedStakesDetails(account: account) + let stakeUnitDetails = try await onLedgerEntitiesClient.getOwnedStakesDetails(account: account, cachingStrategy: cachingStrategy) await state.set(stakeUnitDetails: .success(stakeUnitDetails.asIdentifiable()), forAccount: account.address) } catch { await state.set(stakeUnitDetails: .failure(error), forAccount: account.address) @@ -48,6 +48,23 @@ extension AccountPortfoliosClient: DependencyKey { _ = await (poolDetailsFetch, stakeUnitDetails) } + @Sendable + func applyTokenPrices(_ resources: [ResourceAddress], forceRefresh: Bool) async { + if !resources.isEmpty { + let prices = try? await tokenPricesClient.getTokenPrices( + .init( + tokens: Array(resources.uniqued()), + currency: state.selectedCurrency + ), + forceRefresh + ) + + if let prices { + await state.setTokenPrices(prices) + } + } + } + return AccountPortfoliosClient( fetchAccountPortfolios: { accountAddresses, forceRefresh in let gateway = await gatewaysClient.getCurrentGateway() @@ -74,12 +91,7 @@ extension AccountPortfoliosClient: DependencyKey { let allResources: [ResourceAddress] = { if gateway == .mainnet { /// Only Mainnet resources have prices - return (currentAccounts + accounts) - .flatMap { - $0.allFungibleResourceAddresses + - $0.poolUnitResources.poolUnits.flatMap(\.poolResources) + - [.mainnetXRDAddress] - } + return (currentAccounts + accounts).flatMap(\.resourcesWithPrices) + [.mainnetXRDAddress] } else { #if DEBUG /// Helpful for testing on stokenet @@ -105,22 +117,12 @@ extension AccountPortfoliosClient: DependencyKey { } }() - if !allResources.isEmpty { - let prices = try? await tokenPricesClient.getTokenPrices( - .init( - tokens: Array(allResources), - currency: preferences.fiatCurrencyPriceTarget - ), - forceRefresh - ) - - if let prices { - await state.setTokenPrices(prices) - } - } + await applyTokenPrices(Array(allResources), forceRefresh: forceRefresh) // Load additional details - _ = await accounts.parallelMap(fetchPoolAndStakeUnitsDetails) + _ = await accounts.parallelMap { + await fetchPoolAndStakeUnitsDetails($0, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) + } return Array(state.portfoliosSubject.value.wrappedValue!.values) }, @@ -132,8 +134,14 @@ extension AccountPortfoliosClient: DependencyKey { let account = try await onLedgerEntitiesClient.getAccount(accountAddress) let portfolio = AccountPortfolio(account: account) + let currentResources = await state.tokenPrices.keys + await applyTokenPrices( + currentResources + account.resourcesWithPrices, + forceRefresh: forceRefresh + ) + await state.handlePortfolioUpdate(portfolio) - await fetchPoolAndStakeUnitsDetails(account) + await fetchPoolAndStakeUnitsDetails(account, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) return portfolio }, @@ -149,3 +157,10 @@ extension AccountPortfoliosClient: DependencyKey { ) }() } + +extension OnLedgerEntity.Account { + /// The resources which can have prices + fileprivate var resourcesWithPrices: [ResourceAddress] { + allFungibleResourceAddresses + poolUnitResources.poolUnits.flatMap(\.poolResources) + } +} diff --git a/RadixWallet/EngineKit/TXID.swift b/RadixWallet/EngineKit/TXID.swift index 6bb1447cd7..a8348b9d5a 100644 --- a/RadixWallet/EngineKit/TXID.swift +++ b/RadixWallet/EngineKit/TXID.swift @@ -4,7 +4,7 @@ public typealias TXID = TransactionHash extension TXID { public func formatted(_ format: AddressFormat = .default) -> String { - bytes().hex() + asStr() } public var hex: String { From 404319e9fbe41150912dfd31793e45178e7da3ac Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 12:51:08 +0200 Subject: [PATCH 05/12] wip --- .../Components/StakeUnitList/Components/ValidatorStakeView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift index c4064c606a..d13b34244b 100644 --- a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift @@ -83,7 +83,6 @@ struct ValidatorStakeView: View { onTap: onTap, onClaimAllTapped: onClaimAllTapped ) - .padding(.small1) } } } From e216ccc0244a4e147c009f0ac9a8b9ec0aab01d5 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 12:59:10 +0200 Subject: [PATCH 06/12] wip --- .../Components/StakeUnitList/Components/ValidatorStakeView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift index d13b34244b..c4064c606a 100644 --- a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/Components/ValidatorStakeView.swift @@ -83,6 +83,7 @@ struct ValidatorStakeView: View { onTap: onTap, onClaimAllTapped: onClaimAllTapped ) + .padding(.small1) } } } From 3640fbec8d705966d50c025fa4762bfaad2bbf00 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 13:01:05 +0200 Subject: [PATCH 07/12] rev --- .../OnLedgerEntitiesClient+ComplexTypes.swift | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift index 3498ea9cd1..ff163b94dd 100644 --- a/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift +++ b/RadixWallet/Clients/OnLedgerEntitiesClient/Helpers/OnLedgerEntitiesClient+ComplexTypes.swift @@ -66,7 +66,7 @@ extension OnLedgerEntitiesClient { let isXRD = resourceAddress.isXRD(on: networkID) let details: ResourceBalance.Fungible = .init(isXRD: isXRD, amount: .init(nominalAmount: amount), guarantee: guarantee) - return .init(resource: resource, details: .fungible(details), id: resource.resourceAddress) + return .init(resource: resource, details: .fungible(details)) } private func poolUnit( @@ -115,8 +115,7 @@ extension OnLedgerEntitiesClient { nonXrdResources: nonXrdResources ), guarantee: guarantee - )), - id: resource.resourceAddress + )) ) } else { guard let details = try await getPoolUnitDetails(resource, forAmount: amount) else { @@ -128,8 +127,7 @@ extension OnLedgerEntitiesClient { details: .poolUnit(.init( details: details, guarantee: guarantee - )), - id: resource.resourceAddress + )) ) } } @@ -172,7 +170,7 @@ extension OnLedgerEntitiesClient { guarantee: guarantee ) - return .init(resource: resource, details: .liquidStakeUnit(details), id: resource.resourceAddress) + return .init(resource: resource, details: .liquidStakeUnit(details)) } // MARK: Non-fungibles @@ -222,7 +220,7 @@ extension OnLedgerEntitiesClient { )] } else { result = tokens.map { token in - .init(resource: resource, details: .nonFungible(token), id: token.id) + .init(resource: resource, details: .nonFungible(token)) } guard result.count == ids.count else { @@ -240,7 +238,7 @@ extension OnLedgerEntitiesClient { try NonFungibleGlobalId.fromParts(resourceAddress: resourceAddress.intoEngine(), nonFungibleLocalId: localId) } .map { id in - ResourceBalance(resource: resource, details: .nonFungible(.init(id: id, data: nil)), id: id) + ResourceBalance(resource: resource, details: .nonFungible(.init(id: id, data: nil))) } guard result.count == ids.count else { @@ -298,8 +296,7 @@ extension OnLedgerEntitiesClient { stakeClaims: stakeClaimTokens.asIdentifiable() ), validatorName: stakeClaimValidator.metadata.name - )), - id: resource.id + )) ) } } From cbc7f1eb2634596e746202aa8918664d6c28b130 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 13:33:13 +0200 Subject: [PATCH 08/12] wip --- .../Coordinator/AccountDetails+View.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RadixWallet/Features/AccountDetailsFeature/Coordinator/AccountDetails+View.swift b/RadixWallet/Features/AccountDetailsFeature/Coordinator/AccountDetails+View.swift index ca0271a2b6..ae6662ae25 100644 --- a/RadixWallet/Features/AccountDetailsFeature/Coordinator/AccountDetails+View.swift +++ b/RadixWallet/Features/AccountDetailsFeature/Coordinator/AccountDetails+View.swift @@ -53,7 +53,7 @@ extension AccountDetails { viewStore.send(.showFiatWorthToggled) } .foregroundColor(.app.white) - .padding([.bottom, .horizontal], .medium1) + .padding(.horizontal, .medium1) } prompts( @@ -65,6 +65,7 @@ extension AccountDetails { historyButton() transferButton() } + .padding(.top, .small1) AssetsView.View(store: store.scope(state: \.assets, action: \.child.assets)) .roundedCorners(.top, radius: .medium1) From 539d001ffc6cc8de5860f73be26d11c5b7ac3e0f Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 15:02:45 +0200 Subject: [PATCH 09/12] fix --- .../Clients/NPSSurveyClient/NPSSurveyClient+Live.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift b/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift index 9f6c5fe575..cb02bc64bb 100644 --- a/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift +++ b/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift @@ -19,9 +19,10 @@ extension NPSSurveyClient: DependencyKey { }, incrementTransactionCompleteCounter: { let currentCounter = userDefaults.getTransactionsCompletedCounter() ?? 0 + let lastDate = userDefaults.getDateOfLastSubmittedNPSSurvey() let updatedCounter = currentCounter + 1 userDefaults.setTransactionsCompletedCounter(updatedCounter) - if Self.shouldAskUserForFeedback(updatedCounter) { + if Self.shouldAskUserForFeedback(updatedCounter, dateOfLastSubmittedNPSSurvey: lastDate) { shouldAskForFeedbackSubject.send(true) } }, @@ -37,14 +38,13 @@ extension NPSSurveyClient { private static let nextFeedbackIntervalThresholdInMonths = 3 @Sendable - static func shouldAskUserForFeedback(_ transactionCounter: Int) -> Bool { - @Dependency(\.userDefaults) var userDefaults + static func shouldAskUserForFeedback(_ transactionCounter: Int, dateOfLastSubmittedNPSSurvey: Date?) -> Bool { @Dependency(\.date) var date if transactionCounter == Self.feedbackTransactionCounterThreshold { return true } else if transactionCounter > Self.feedbackTransactionCounterThreshold { - guard let lastSubmittedDate = userDefaults.getDateOfLastSubmittedNPSSurvey() else { + guard let lastSubmittedDate = dateOfLastSubmittedNPSSurvey else { // No submit date saved? // Can happen if user did close the app while the original NPS survey was shown. // And since the next NPS survey check will happen only after user did perform From 0abfc783753d6f4f88368e047bf852a2038aba2a Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Thu, 21 Mar 2024 16:45:59 +0200 Subject: [PATCH 10/12] wip --- .../AccountPortfoliosClient+Live.swift | 156 ++++++++++-------- .../Core/SharedModels/Assets/FiatWorth.swift | 4 - 2 files changed, 85 insertions(+), 75 deletions(-) diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift index 18589bd4a0..b062e32f43 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift @@ -65,85 +65,99 @@ extension AccountPortfoliosClient: DependencyKey { } } - return AccountPortfoliosClient( - fetchAccountPortfolios: { accountAddresses, forceRefresh in - let gateway = await gatewaysClient.getCurrentGateway() - await state.setRadixGateway(gateway) - if forceRefresh { - for accountAddress in accountAddresses { - cacheClient.removeFolder(.onLedgerEntity(.account(accountAddress.asGeneral))) - } + @Sendable + func fetchAccountPortfolios(_ accountAddresses: [AccountAddress], _ forceResfresh: Bool) async throws -> [AccountPortfolio] { + let gateway = await gatewaysClient.getCurrentGateway() + await state.setRadixGateway(gateway) + if forceRefresh { + for accountAddress in accountAddresses { + cacheClient.removeFolder(.onLedgerEntity(.account(accountAddress.asGeneral))) } + } - /// Explicetely load and set the currency target and visibility to make sure - /// it is available for usage before resources are loaded - let preferences = await appPreferencesClient.getPreferences().display - await state.setSelectedCurrency(preferences.fiatCurrencyPriceTarget) - await state.setIsCurrencyAmountVisble(preferences.isCurrencyAmountVisible) - - let accounts = try await onLedgerEntitiesClient.getAccounts(accountAddresses).map(\.nonEmptyVaults) - - let portfolios = accounts.map { AccountPortfolio(account: $0) } - await state.handlePortfoliosUpdate(portfolios) - - /// Put together all resources from already fetched and new accounts - let currentAccounts = state.portfoliosSubject.value.wrappedValue.map { $0.values.map(\.account) } ?? [] - let allResources: [ResourceAddress] = { - if gateway == .mainnet { - /// Only Mainnet resources have prices - return (currentAccounts + accounts).flatMap(\.resourcesWithPrices) + [.mainnetXRDAddress] - } else { - #if DEBUG - /// Helpful for testing on stokenet - return [ - .mainnetXRDAddress, - try! .init(validatingAddress: - "resource_rdx1t4tjx4g3qzd98nayqxm7qdpj0a0u8ns6a0jrchq49dyfevgh6u0gj3" - ), - try! .init(validatingAddress: - "resource_rdx1t45js47zxtau85v0tlyayerzrgfpmguftlfwfr5fxzu42qtu72tnt0" - ), - try! .init(validatingAddress: - "resource_rdx1tk7g72c0uv2g83g3dqtkg6jyjwkre6qnusgjhrtz0cj9u54djgnk3c" - ), - try! .init(validatingAddress: - "resource_rdx1tkk83magp3gjyxrpskfsqwkg4g949rmcjee4tu2xmw93ltw2cz94sq" - ), - ] - #else - /// No price for resources on testnets - return [] - #endif - } - }() - - await applyTokenPrices(Array(allResources), forceRefresh: forceRefresh) - - // Load additional details - _ = await accounts.parallelMap { - await fetchPoolAndStakeUnitsDetails($0, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) + /// Explicetely load and set the currency target and visibility to make sure + /// it is available for usage before resources are loaded + let preferences = await appPreferencesClient.getPreferences().display + await state.setSelectedCurrency(preferences.fiatCurrencyPriceTarget) + await state.setIsCurrencyAmountVisble(preferences.isCurrencyAmountVisible) + + let accounts = try await onLedgerEntitiesClient.getAccounts(accountAddresses).map(\.nonEmptyVaults) + + let portfolios = accounts.map { AccountPortfolio(account: $0) } + await state.handlePortfoliosUpdate(portfolios) + + /// Put together all resources from already fetched and new accounts + let currentAccounts = state.portfoliosSubject.value.wrappedValue.map { $0.values.map(\.account) } ?? [] + let allResources: [ResourceAddress] = { + if gateway == .mainnet { + /// Only Mainnet resources have prices + return (currentAccounts + accounts).flatMap(\.resourcesWithPrices) + [.mainnetXRDAddress] + } else { + #if DEBUG + /// Helpful for testing on stokenet + return [ + .mainnetXRDAddress, + try! .init(validatingAddress: + "resource_rdx1t4tjx4g3qzd98nayqxm7qdpj0a0u8ns6a0jrchq49dyfevgh6u0gj3" + ), + try! .init(validatingAddress: + "resource_rdx1t45js47zxtau85v0tlyayerzrgfpmguftlfwfr5fxzu42qtu72tnt0" + ), + try! .init(validatingAddress: + "resource_rdx1tk7g72c0uv2g83g3dqtkg6jyjwkre6qnusgjhrtz0cj9u54djgnk3c" + ), + try! .init(validatingAddress: + "resource_rdx1tkk83magp3gjyxrpskfsqwkg4g949rmcjee4tu2xmw93ltw2cz94sq" + ), + ] + #else + /// No price for resources on testnets + return [] + #endif } + }() - return Array(state.portfoliosSubject.value.wrappedValue!.values) - }, - fetchAccountPortfolio: { accountAddress, forceRefresh in - if forceRefresh { - cacheClient.removeFolder(.onLedgerEntity(.account(accountAddress.asGeneral))) - } + await applyTokenPrices(Array(allResources), forceRefresh: forceRefresh) - let account = try await onLedgerEntitiesClient.getAccount(accountAddress) - let portfolio = AccountPortfolio(account: account) + // Load additional details + _ = await accounts.parallelMap { + await fetchPoolAndStakeUnitsDetails($0, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) + } - let currentResources = await state.tokenPrices.keys - await applyTokenPrices( - currentResources + account.resourcesWithPrices, - forceRefresh: forceRefresh - ) + return Array(state.portfoliosSubject.value.wrappedValue!.values) + } - await state.handlePortfolioUpdate(portfolio) - await fetchPoolAndStakeUnitsDetails(account, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) + @Sendable + func fetchAccountPortfolio(_ accountAddress: AccountAddress, _ forceRefresh: Bool) async throws -> AccountPortfolio { + if forceRefresh { + cacheClient.removeFolder(.onLedgerEntity(.account(accountAddress.asGeneral))) + } + + let account = try await onLedgerEntitiesClient.getAccount(accountAddress) + let portfolio = AccountPortfolio(account: account) - return portfolio + let currentResources = await state.tokenPrices.keys + await applyTokenPrices( + currentResources + account.resourcesWithPrices, + forceRefresh: forceRefresh + ) + + await state.handlePortfolioUpdate(portfolio) + await fetchPoolAndStakeUnitsDetails(account, cachingStrategy: forceRefresh ? .forceUpdate : .useCache) + + return portfolio + } + + return AccountPortfoliosClient( + fetchAccountPortfolios: { accountAddresses, forceRefresh in + try await Task.detached { + try await fetchAccountPortfolios(accountAddresses, forceRefresh) + }.value + }, + fetchAccountPortfolio: { accountAddress, forceRefresh in + try await Task.detached { + try await fetchAccountPortfolio(accountAddress, forceRefresh) + }.value }, portfolioUpdates: { state.portfoliosSubject diff --git a/RadixWallet/Core/SharedModels/Assets/FiatWorth.swift b/RadixWallet/Core/SharedModels/Assets/FiatWorth.swift index 0d5d0119a5..200202e372 100644 --- a/RadixWallet/Core/SharedModels/Assets/FiatWorth.swift +++ b/RadixWallet/Core/SharedModels/Assets/FiatWorth.swift @@ -93,10 +93,6 @@ extension FiatWorth { let value = worth.value ?? .zero // Zero for the unknown case, just to do to the base formatting - if value < 1 { - formatter.maximumFractionDigits = 8 - } - let formattedValue = { guard let double = try? value.asDouble(), let value = formatter.string(for: double) else { // Good enough fallback From 14e1647c6286e8df78a177717325083ca0f7459a Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Fri, 22 Mar 2024 07:39:31 +0200 Subject: [PATCH 11/12] wip --- Gemfile.lock | 109 ++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 68066e014f..c4838e7fc6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,32 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.6) + CFPropertyList (3.0.7) + base64 + nkf rexml - addressable (2.8.5) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) - artifactory (3.0.15) + artifactory (3.0.17) atomos (0.1.3) - aws-eventstream (1.2.0) - aws-partitions (1.826.0) - aws-sdk-core (3.183.0) - aws-eventstream (~> 1, >= 1.0.2) + aws-eventstream (1.3.0) + aws-partitions (1.899.0) + aws-sdk-core (3.191.4) + aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) + aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.71.0) - aws-sdk-core (~> 3, >= 3.177.0) + aws-sdk-kms (1.78.0) + aws-sdk-core (~> 3, >= 3.191.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.135.0) - aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-s3 (1.146.0) + aws-sdk-core (~> 3, >= 3.191.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.6) - aws-sigv4 (1.6.0) + aws-sigv4 (~> 1.8) + aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) + base64 (0.2.0) claide (1.1.0) colored (1.2) colored2 (3.1.2) @@ -32,11 +35,10 @@ GEM declarative (0.0.20) digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) + domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.103.0) + excon (0.110.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -65,7 +67,7 @@ GEM faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) - fastimage (2.2.7) + fastimage (2.3.0) fastlane (2.216.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) @@ -109,39 +111,40 @@ GEM fastlane-plugin-json (1.1.0) fastlane-plugin-xcconfig (2.0.0) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.49.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.1) + google-apis-androidpublisher_v3 (0.58.0) + google-apis-core (>= 0.14.0, < 2.a) + google-apis-core (0.14.1) addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) + googleauth (~> 1.9) httpclient (>= 2.8.1, < 3.a) mini_mime (~> 1.0) representable (~> 3.0) retriable (>= 2.0, < 4.a) rexml - webrick - google-apis-iamcredentials_v1 (0.17.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-playcustomapp_v1 (0.13.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.19.0) - google-apis-core (>= 0.9.0, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-apis-iamcredentials_v1 (0.20.0) + google-apis-core (>= 0.14.0, < 2.a) + google-apis-playcustomapp_v1 (0.15.0) + google-apis-core (>= 0.14.0, < 2.a) + google-apis-storage_v1 (0.36.0) + google-apis-core (>= 0.14.0, < 2.a) + google-cloud-core (1.7.0) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) - google-cloud-env (1.6.0) - faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.3.1) - google-cloud-storage (1.44.0) + google-cloud-env (2.1.1) + faraday (>= 1.0, < 3.a) + google-cloud-errors (1.4.0) + google-cloud-storage (1.49.0) addressable (~> 2.8) digest-crc (~> 0.4) - google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.19.0) + google-apis-core (~> 0.13) + google-apis-iamcredentials_v1 (~> 0.18) + google-apis-storage_v1 (~> 0.33) google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) + googleauth (~> 1.9) mini_mime (~> 1.0) - googleauth (1.8.1) - faraday (>= 0.17.3, < 3.a) + googleauth (1.11.0) + faraday (>= 1.0, < 3.a) + google-cloud-env (~> 2.1) jwt (>= 1.4, < 3.0) multi_json (~> 1.11) os (>= 0.9, < 2.0) @@ -151,19 +154,21 @@ GEM domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) - json (2.6.3) - jwt (2.7.1) + json (2.7.1) + jwt (2.8.1) + base64 mini_magick (4.12.0) mini_mime (1.1.5) multi_json (1.15.0) - multipart-post (2.3.0) + multipart-post (2.4.0) nanaimo (0.3.0) naturally (2.2.1) + nkf (0.2.0) optparse (0.1.1) os (1.1.4) - plist (3.7.0) - public_suffix (5.0.3) - rake (13.0.6) + plist (3.7.1) + public_suffix (5.0.4) + rake (13.1.0) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) @@ -174,7 +179,7 @@ GEM ruby2_keywords (0.0.5) rubyzip (2.3.2) security (0.1.3) - signet (0.18.0) + signet (0.19.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) @@ -187,20 +192,16 @@ GEM unicode-display_width (>= 1.1.1, < 3) trailblazer-option (0.1.2) tty-cursor (0.7.1) - tty-screen (0.8.1) + tty-screen (0.8.2) tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) - unicode-display_width (2.4.2) - webrick (1.8.1) + unicode-display_width (2.5.0) word_wrap (1.0.0) xcode-install (2.8.1) claide (>= 0.9.1) fastlane (>= 2.1.0, < 3.0.0) - xcodeproj (1.22.0) + xcodeproj (1.24.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) From 5eaa6853fbbb43943769d5a6320af0b45d2bcc22 Mon Sep 17 00:00:00 2001 From: Ghenadie Vasiliev-Pusca Date: Fri, 22 Mar 2024 07:45:12 +0200 Subject: [PATCH 12/12] fix --- .../AccountPortfoliosClient/AccountPortfoliosClient+Live.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift index b062e32f43..075562cb43 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift @@ -66,7 +66,7 @@ extension AccountPortfoliosClient: DependencyKey { } @Sendable - func fetchAccountPortfolios(_ accountAddresses: [AccountAddress], _ forceResfresh: Bool) async throws -> [AccountPortfolio] { + func fetchAccountPortfolios(_ accountAddresses: [AccountAddress], _ forceRefresh: Bool) async throws -> [AccountPortfolio] { let gateway = await gatewaysClient.getCurrentGateway() await state.setRadixGateway(gateway) if forceRefresh {