diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Interface.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Interface.swift index 83ea234b5c..233450cd6c 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Interface.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Interface.swift @@ -10,6 +10,8 @@ public struct AccountPortfoliosClient: Sendable { /// Will return the portfolio after fetch, as well will notify any subscribes through `portfolioForAccount` public var fetchAccountPortfolio: FetchAccountPortfolio + public var portfolioUpdates: PortfolioUpdates + /// Subscribe to portfolio changes for a given account address public var portfolioForAccount: PortfolioForAccount @@ -21,6 +23,8 @@ extension AccountPortfoliosClient { public typealias FetchAccountPortfolio = @Sendable (_ address: AccountAddress, _ forceResfresh: Bool) async throws -> AccountPortfolio public typealias FetchAccountPortfolios = @Sendable (_ addresses: [AccountAddress], _ forceResfresh: Bool) async throws -> [AccountPortfolio] public typealias PortfolioForAccount = @Sendable (_ address: AccountAddress) async -> AnyAsyncSequence + + public typealias PortfolioUpdates = @Sendable () -> AnyAsyncSequence> public typealias Portfolios = @Sendable () -> [AccountPortfolio] } diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift index c58c1331a8..f35119fa7c 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Live.swift @@ -66,6 +66,9 @@ extension AccountPortfoliosClient: DependencyKey { 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] = { @@ -116,9 +119,6 @@ extension AccountPortfoliosClient: DependencyKey { } } - let portfolios = accounts.map { AccountPortfolio(account: $0) } - await state.handlePortfoliosUpdate(portfolios) - // Load additional details _ = await accounts.parallelMap(fetchPoolAndStakeUnitsDetails) @@ -137,6 +137,11 @@ extension AccountPortfoliosClient: DependencyKey { return portfolio }, + portfolioUpdates: { + state.portfoliosSubject + .map { $0.map { Array($0.values) } } + .eraseToAnyAsyncSequence() + }, portfolioForAccount: { address in await state.portfolioForAccount(address) }, diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Mock.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Mock.swift index 61caf26162..7678c4eae3 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Mock.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+Mock.swift @@ -5,6 +5,7 @@ extension AccountPortfoliosClient: TestDependencyKey { public static let testValue = AccountPortfoliosClient( fetchAccountPortfolios: unimplemented("\(AccountPortfoliosClient.self).fetchAccountPortfolios"), fetchAccountPortfolio: unimplemented("\(AccountPortfoliosClient.self).fetchAccountPortfolio"), + portfolioUpdates: unimplemented("\(AccountPortfoliosClient.self).fetchAccountPortfolio"), portfolioForAccount: unimplemented("\(AccountPortfoliosClient.self).portfolioForAccount"), portfolios: unimplemented("\(AccountPortfoliosClient.self).portfolios") ) @@ -12,6 +13,7 @@ extension AccountPortfoliosClient: TestDependencyKey { public static let noop = AccountPortfoliosClient( fetchAccountPortfolios: { _, _ in throw NoopError() }, fetchAccountPortfolio: { _, _ in throw NoopError() }, + portfolioUpdates: { AsyncLazySequence([]).eraseToAnyAsyncSequence() }, portfolioForAccount: { _ in fatalError() }, portfolios: { fatalError() } ) diff --git a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift index f0d02fedd4..54be6f2171 100644 --- a/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift +++ b/RadixWallet/Clients/AccountPortfoliosClient/AccountPortfoliosClient+State.swift @@ -45,7 +45,7 @@ extension AccountPortfoliosClient.State { } func portfolioForAccount(_ address: AccountAddress) -> AnyAsyncSequence { - portfoliosSubject.compactMap { $0[address].unwrap()?.wrappedValue }.eraseToAnyAsyncSequence() + portfoliosSubject.compactMap { $0[address].unwrap()?.wrappedValue }.removeDuplicates().eraseToAnyAsyncSequence() } private func setOrUpdateAccountPortfolio(_ portfolio: AccountPortfoliosClient.AccountPortfolio) { diff --git a/RadixWallet/Clients/TokenPriceClient/TokenPriceClient+Live.swift b/RadixWallet/Clients/TokenPriceClient/TokenPriceClient+Live.swift index 716be8681c..36458663b6 100644 --- a/RadixWallet/Clients/TokenPriceClient/TokenPriceClient+Live.swift +++ b/RadixWallet/Clients/TokenPriceClient/TokenPriceClient+Live.swift @@ -48,6 +48,7 @@ extension TokenPricesClient.TokenPrices { formatter.numberStyle = .decimal formatter.maximumFractionDigits = Int(RETDecimal.maxDivisibility) formatter.roundingMode = .down + formatter.decimalSeparator = "." // Enfore dot notation for RETDecimal self = tokenPricesResponse.tokens.reduce(into: [:]) { partialResult, next in let trimmed = formatter.string(for: next.price) ?? "" diff --git a/RadixWallet/Core/FeaturePrelude/Loadable.swift b/RadixWallet/Core/FeaturePrelude/Loadable.swift index 03af3c9665..f121fc080b 100644 --- a/RadixWallet/Core/FeaturePrelude/Loadable.swift +++ b/RadixWallet/Core/FeaturePrelude/Loadable.swift @@ -223,7 +223,7 @@ extension Loadable { } } - public func firstd(where predicate: (Value.Element) -> Bool) -> Loadable where Value: Sequence { + public func first(where predicate: (Value.Element) -> Bool) -> Loadable where Value: Sequence { switch self { case .idle: return .idle @@ -292,6 +292,10 @@ extension Loadable { concat(other).map(join) } + public func reduce(_ join: (Element) -> Void) -> Void where Value == Array { + + } + public mutating func mutateValue(_ mutate: (inout Value) -> Void) { switch self { case .idle, .loading, .failure: @@ -307,16 +311,29 @@ extension Loadable { public mutating func refresh( from other: Loadable, valueChangeMap: (_ old: Value, _ new: Value) -> Value = { _, new in new } - ) { + ) where Value: Equatable { switch (self, other) { - // If `other` is success, update the content regardless of the current state - case let (.success(oldValue), .success(newValue)): - self = .success(valueChangeMap(oldValue, newValue)) - case let (_, .success(otherValue)): + // Update to success if no current value + case let (.idle, .success(otherValue)), + let (.loading, .success(otherValue)), + let (.failure, .success(otherValue)): + self = .success(otherValue) + + // Update to new value only if it changed + case let (.success(oldValue), .success(newValue)): + if oldValue != newValue { + self = .success(valueChangeMap(oldValue, newValue)) + } + // If current state is success, don't update if `other` is loading or failed case (.success, _): break + + case (.loading, .loading), + (.idle, .idle): + break + // If current state is other than .success case let (_, other): self = other diff --git a/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift b/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift index 1226e85f42..0c1b07f576 100644 --- a/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/AssetsView+Reducer.swift @@ -195,7 +195,7 @@ public struct AssetsView: Sendable, FeatureReducer { return nil } - return .init(sections: sections) + return .init(sections: sections, destination: state.resources.fungibleTokenList?.destination) }() state.accountPortfolio.refresh(from: .success(portfolio)) @@ -210,7 +210,8 @@ public struct AssetsView: Sendable, FeatureReducer { }, isSelected: mode.nonXrdRowSelected(poolUnit.resource.resourceAddress) ) - }.asIdentifiable() + }.asIdentifiable(), + destination: state.resources.poolUnitsList?.destination ) let stakes = portfolio.account.poolUnitResources.radixNetworkStakes @@ -234,13 +235,14 @@ public struct AssetsView: Sendable, FeatureReducer { dict[resource] = selectedtokens } } : nil, - stakeUnitDetails: state.accountPortfolio.stakeUnitDetails.flatten() + stakeUnitDetails: state.accountPortfolio.stakeUnitDetails.flatten(), + destination: state.resources.stakeUnitList?.destination ) state.totalFiatWorth.refresh(from: portfolio.totalFiatWorth) state.resources = .init( fungibleTokenList: fungibleTokenList, - nonFungibleTokenList: !nfts.isEmpty ? .init(rows: .init(uniqueElements: nfts)) : nil, + nonFungibleTokenList: !nfts.isEmpty ? .init(rows: nfts.asIdentifiable(), destination: state.resources.nonFungibleTokenList?.destination) : nil, stakeUnitList: stakeUnitList, poolUnitsList: poolUnitList ) @@ -250,6 +252,8 @@ public struct AssetsView: Sendable, FeatureReducer { extension AccountPortfoliosClient.AccountPortfolio { mutating func refresh(from portfolio: AccountPortfoliosClient.AccountPortfolio) { self.account = portfolio.account + self.isCurrencyAmountVisible = portfolio.isCurrencyAmountVisible + self.fiatCurrency = portfolio.fiatCurrency self.stakeUnitDetails.refresh(from: portfolio.stakeUnitDetails) self.poolUnitDetails.refresh(from: portfolio.poolUnitDetails) } diff --git a/RadixWallet/Features/AssetsFeature/Components/FungibleAssetList/FungibleAssetList+Reducer.swift b/RadixWallet/Features/AssetsFeature/Components/FungibleAssetList/FungibleAssetList+Reducer.swift index da4dce3970..423fe297d4 100644 --- a/RadixWallet/Features/AssetsFeature/Components/FungibleAssetList/FungibleAssetList+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/Components/FungibleAssetList/FungibleAssetList+Reducer.swift @@ -4,16 +4,10 @@ import SwiftUI // MARK: - FungibleAssetList public struct FungibleAssetList: Sendable, FeatureReducer { public struct State: Sendable, Hashable { - public var sections: IdentifiedArrayOf + public var sections: IdentifiedArrayOf = [] @PresentationState public var destination: Destination.State? - - public init( - sections: IdentifiedArrayOf = [] - ) { - self.sections = sections - } } @CasePathable diff --git a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift index df00b4430c..878e5ba867 100644 --- a/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift +++ b/RadixWallet/Features/AssetsFeature/Components/HelperViews/ResourceBalance/ResourceBalanceView.swift @@ -386,7 +386,7 @@ extension ResourceBalanceView { } .disabled(onTap == nil) .buttonStyle(.borderless) - .roundedCorners(strokeColor: .red) // .app.gray3 + .roundedCorners(strokeColor: .app.gray3) } } } diff --git a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift index b89ddaabad..d86a09c78a 100644 --- a/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift +++ b/RadixWallet/Features/AssetsFeature/Components/NonFungibleAssetList/NonFungibleAssetList+Reducer.swift @@ -7,10 +7,6 @@ public struct NonFungibleAssetList: Sendable, FeatureReducer { @PresentationState public var destination: Destination.State? - - public init(rows: IdentifiedArrayOf) { - self.rows = rows - } } public enum ChildAction: Sendable, Equatable { 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) } } } diff --git a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/StakeUnitList.swift b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/StakeUnitList.swift index 021d5045fc..286b179706 100644 --- a/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/StakeUnitList.swift +++ b/RadixWallet/Features/AssetsFeature/Components/StakeUnitList/StakeUnitList.swift @@ -23,11 +23,13 @@ public struct StakeUnitList: Sendable, FeatureReducer { account: OnLedgerEntity.Account, selectedLiquidStakeUnits: IdentifiedArrayOf?, selectedStakeClaimTokens: SelectedStakeClaimTokens?, - stakeUnitDetails: Loadable> + stakeUnitDetails: Loadable>, + destination: Destination.State? = nil ) { self.account = account self.selectedLiquidStakeUnits = selectedLiquidStakeUnits self.selectedStakeClaimTokens = selectedStakeClaimTokens + self.destination = destination switch stakeUnitDetails { case .idle, .loading: diff --git a/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+Reducer.swift b/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+Reducer.swift index a831d5eab3..2f8ebf73d9 100644 --- a/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+Reducer.swift +++ b/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+Reducer.swift @@ -8,7 +8,7 @@ extension Home { public var id: AccountAddress { account.address } public var accountWithInfo: AccountWithInfo - public var portfolio: Loadable + public var accountWithResources: Loadable public var showFiatWorth: Bool = true public var totalFiatWorth: Loadable @@ -16,7 +16,7 @@ extension Home { account: Profile.Network.Account ) { self.accountWithInfo = .init(account: account) - self.portfolio = .loading + self.accountWithResources = .loading self.totalFiatWorth = .loading } } @@ -29,7 +29,8 @@ extension Home { } public enum InternalAction: Sendable, Equatable { - case accountPortfolioUpdate(AccountPortfoliosClient.AccountPortfolio) + case accountUpdated(OnLedgerEntity.Account) + case fiatWorthUpdated(Loadable) case checkAccountAccessToMnemonic } @@ -46,21 +47,10 @@ extension Home { public func reduce(into state: inout State, viewAction: ViewAction) -> Effect { switch viewAction { case .task: - let accountAddress = state.account.address - if state.portfolio.wrappedValue == nil { - state.portfolio = .loading - } - self.checkAccountAccessToMnemonic(state: &state) - return .run { send in - for try await accountPortfolio in await accountPortfoliosClient.portfolioForAccount(accountAddress) { - guard !Task.isCancelled else { - return - } - await send(.internal(.accountPortfolioUpdate(accountPortfolio))) - } - } + return .none + case .exportMnemonicButtonTapped: return .send(.delegate(.exportMnemonic)) @@ -74,23 +64,26 @@ extension Home { public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { switch internalAction { - case let .accountPortfolioUpdate(portfolio): - state.isDappDefinitionAccount = portfolio.account.metadata.accountType == .dappDefinition + case let .accountUpdated(account): + assert(account.address == state.account.address) - assert(portfolio.account.address == state.account.address) + state.isDappDefinitionAccount = account.metadata.accountType == .dappDefinition + state.accountWithResources.refresh(from: .success(account)) - state.portfolio = .success(portfolio) - state.totalFiatWorth.refresh(from: portfolio.totalFiatWorth) return .send(.internal(.checkAccountAccessToMnemonic)) case .checkAccountAccessToMnemonic: checkAccountAccessToMnemonic(state: &state) return .none + + case let .fiatWorthUpdated(fiatWorth): + state.totalFiatWorth.refresh(from: fiatWorth) + return .none } } private func checkAccountAccessToMnemonic(state: inout State) { - state.checkAccountAccessToMnemonic(portfolio: state.portfolio.account.wrappedValue) + state.checkAccountAccessToMnemonic(portfolio: state.accountWithResources.wrappedValue) } } } diff --git a/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+View.swift b/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+View.swift index 0cd771d28d..f6dd63e7c2 100644 --- a/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+View.swift +++ b/RadixWallet/Features/HomeFeature/Children/AccountRow/Home+AccountRow+View.swift @@ -47,7 +47,7 @@ extension Home.AccountRow { self.appearanceID = state.account.appearanceID self.showFiatWorth = state.showFiatWorth self.fiatWorth = state.totalFiatWorth - self.isLoadingResources = state.portfolio.isLoading + self.isLoadingResources = state.accountWithResources.isLoading self.tag = .init(state: state) self.isLedgerAccount = state.isLedgerAccount @@ -55,7 +55,7 @@ extension Home.AccountRow { self.mnemonicHandlingCallToAction = state.mnemonicHandlingCallToAction // Resources - guard let portfolio = state.portfolio.wrappedValue else { + guard let accountWithResources = state.accountWithResources.wrappedValue else { self.fungibleResourceIcons = [] self.nonFungibleResourcesCount = 0 self.stakedValidatorsCount = 0 @@ -64,13 +64,13 @@ extension Home.AccountRow { return } - let fungibleResources = portfolio.account.fungibleResources + let fungibleResources = accountWithResources.fungibleResources let xrdIcon: [Thumbnail.TokenContent] = fungibleResources.xrdResource != nil ? [.xrd] : [] let otherIcons: [Thumbnail.TokenContent] = fungibleResources.nonXrdResources.map { .other($0.metadata.iconURL) } self.fungibleResourceIcons = xrdIcon + otherIcons - self.nonFungibleResourcesCount = portfolio.account.nonFungibleResources.count - self.stakedValidatorsCount = portfolio.account.poolUnitResources.radixNetworkStakes.count - self.poolUnitsCount = portfolio.account.poolUnitResources.poolUnits.count + self.nonFungibleResourcesCount = accountWithResources.nonFungibleResources.count + self.stakedValidatorsCount = accountWithResources.poolUnitResources.radixNetworkStakes.count + self.poolUnitsCount = accountWithResources.poolUnitResources.poolUnits.count } } diff --git a/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift b/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift index 442d57cda3..5eab49d784 100644 --- a/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift +++ b/RadixWallet/Features/HomeFeature/Coordinator/Home+View.swift @@ -6,7 +6,7 @@ extension Home.State { .init( hasNotification: shouldWriteDownPersonasSeedPhrase, showRadixBanner: showRadixBanner, - totalFiatWorth: totalFiatWorth + totalFiatWorth: showFiatWorth ? totalFiatWorth : nil ) } } diff --git a/RadixWallet/Features/HomeFeature/Coordinator/Home.swift b/RadixWallet/Features/HomeFeature/Coordinator/Home.swift index 0976013e17..8614bd3e8e 100644 --- a/RadixWallet/Features/HomeFeature/Coordinator/Home.swift +++ b/RadixWallet/Features/HomeFeature/Coordinator/Home.swift @@ -13,13 +13,7 @@ public struct Home: Sendable, FeatureReducer { public var showRadixBanner: Bool = false public var showFiatWorth: Bool = true - public var totalFiatWorth: Loadable? { - guard showFiatWorth else { - return nil - } - - return accountRows.map(\.totalFiatWorth).reduce(+) - } + public var totalFiatWorth: Loadable = .idle // MARK: - Destination @PresentationState @@ -47,6 +41,8 @@ public struct Home: Sendable, FeatureReducer { case loadedShouldWriteDownPersonasSeedPhrase(Bool) case currentGatewayChanged(to: Radix.Gateway) case shouldShowNPSSurvey(Bool) + case accountsResourcesLoaded(Loadable<[OnLedgerEntity.Account]>) + case accountsFiatWorthLoaded([AccountAddress: Loadable]) } public enum ChildAction: Sendable, Equatable { @@ -151,6 +147,8 @@ public struct Home: Sendable, FeatureReducer { .merge(with: loadShouldWriteDownPersonasSeedPhrase()) .merge(with: loadGateways()) .merge(with: loadNPSSurveyStatus()) + .merge(with: loadAccountResources()) + .merge(with: loadFiatValues()) case .createAccountButtonTapped: state.destination = .createAccount( @@ -206,6 +204,14 @@ public struct Home: Sendable, FeatureReducer { errorQueue.schedule(error) return .none + case let .accountsResourcesLoaded(accountsResources): + state.accountRows.mutateAll { row in + if let accountResources = accountsResources.first(where: { $0.address == row.id }).unwrap() { + row.accountWithResources.refresh(from: accountResources) + } + } + return .none + case let .loadedShouldWriteDownPersonasSeedPhrase(shouldBackup): state.shouldWriteDownPersonasSeedPhrase = shouldBackup return .none @@ -231,6 +237,14 @@ public struct Home: Sendable, FeatureReducer { state.destination = .npsSurvey(.init()) } return .none + case let .accountsFiatWorthLoaded(fiatWorths): + state.accountRows.mutateAll { + if let fiatWorth = fiatWorths[$0.id] { + $0.totalFiatWorth.refresh(from: fiatWorth) + } + } + state.totalFiatWorth = state.accountRows.map(\.totalFiatWorth).reduce(+) ?? .loading + return .none } } @@ -372,6 +386,38 @@ public struct Home: Sendable, FeatureReducer { await npsSurveyClient.uploadUserFeedback(feedback) } } + + private func loadAccountResources() -> Effect { + .run { send in + for try await accountResources in accountPortfoliosClient.portfolioUpdates().map { $0.map { $0.map(\.account) } }.removeDuplicates() { + guard !Task.isCancelled else { return } + await send(.internal(.accountsResourcesLoaded(accountResources))) + } + } + } + + private func loadFiatValues() -> Effect { + .run { send in + let accountsTotalFiatWorth = accountPortfoliosClient.portfolioUpdates() + .compactMap { portfoliosLoadable in + portfoliosLoadable.wrappedValue?.reduce(into: [AccountAddress: Loadable]()) { partialResult, portfolio in + partialResult[portfolio.account.address] = portfolio.totalFiatWorth + } + } + .filter { + // All items should load + if let aggregated = Array($0.values).reduce(+), aggregated.didLoad { + return true + } + return false + } + + for try await accountsTotalFiatWorth in accountsTotalFiatWorth.removeDuplicates() { + guard !Task.isCancelled else { return } + await send(.internal(.accountsFiatWorthLoaded(accountsTotalFiatWorth))) + } + } + } } extension Home.State { diff --git a/RadixWallet/Features/HomeFeature/Models/AccountWithInfoHolder.swift b/RadixWallet/Features/HomeFeature/Models/AccountWithInfoHolder.swift index 4535922f80..3453daffb9 100644 --- a/RadixWallet/Features/HomeFeature/Models/AccountWithInfoHolder.swift +++ b/RadixWallet/Features/HomeFeature/Models/AccountWithInfoHolder.swift @@ -47,12 +47,13 @@ extension DeviceFactorSourceControlled { return } - guard let xrdResource else { - mnemonicHandlingCallToAction = nil - return - } +// guard let xrdResource else { +// mnemonicHandlingCallToAction = nil +// return +// } - let hasValue = xrdResource.amount.nominalAmount > 0 + // Disabled for now, to be revised with MFA + let hasValue = true // xrdResource.amount.nominalAmount > 0 let hasAlreadyBackedUpMnemonic = userDefaults.getFactorSourceIDOfBackedUpMnemonics().contains(factorSourceID) let exportMnemonicNeeded = !hasAlreadyBackedUpMnemonic && hasValue