Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-11 17:48:20 +05:00
parent 6ed1946ac3
commit aac48015b3
88 changed files with 335 additions and 239 deletions

View file

@ -21,6 +21,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.account.derivationIndex
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.send.v2.api.FeeSelectorBlockComponent
import com.tangem.features.send.v2.api.SendComponent

View file

@ -22,14 +22,17 @@ internal class SendAnalyticHelper @Inject constructor(
cryptoCurrency: CryptoCurrency,
sendUM: SendUM,
feeToken: CryptoCurrency,
account: Account.CryptoPortfolio?,
account: Account?,
) {
val destinationUM = sendUM.destinationUM as? DestinationUM.Content
val feeSelectorUM = sendUM.feeSelectorUM as? FeeSelectorUM.Content ?: return
val feeType = feeSelectorUM.toAnalyticType()
val feeTokenSymbol = feeToken.symbol
val isNotMainAccount = account != null && !account.isMainAccount
val derivationIndex = if (isNotMainAccount) account.derivationIndex.value else null
val derivationIndex = when (account) {
is Account.CryptoPortfolio -> if (!account.isMainAccount) account.derivationIndex else null
is Account.Payment -> null
null -> null
}
analyticsEventHandler.send(
SendAnalyticEvents.TransactionScreenOpened(
token = cryptoCurrency.symbol,
@ -37,7 +40,7 @@ internal class SendAnalyticHelper @Inject constructor(
blockchain = cryptoCurrency.network.name,
isNonceNotEmpty = feeSelectorUM.feeNonce is FeeNonce.Nonce,
ensStatus = getEnsStatus(sendUM),
derivationIndex = derivationIndex,
derivationIndex = derivationIndex?.value,
feeToken = feeTokenSymbol,
),
)

View file

@ -158,7 +158,7 @@ internal class SendConfirmComponent(
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val accountFlow: StateFlow<Account.CryptoPortfolio?>,
val accountFlow: StateFlow<Account?>,
val isAccountModeFlow: StateFlow<Boolean>,
val appCurrency: AppCurrency,
val callback: ModelCallback,

View file

@ -147,7 +147,7 @@ internal class SendModel @Inject constructor(
),
)
val accountFlow: StateFlow<Account.CryptoPortfolio?>
val accountFlow: StateFlow<Account?>
field = MutableStateFlow(null)
val isAccountModeFlow: StateFlow<Boolean>
field = MutableStateFlow(false)

View file

@ -24,7 +24,7 @@ internal sealed class SendAmountComponentParams {
abstract val cryptoCurrency: CryptoCurrency
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
abstract val isBalanceHidingFlow: StateFlow<Boolean>
abstract val accountFlow: StateFlow<Account.CryptoPortfolio?>
abstract val accountFlow: StateFlow<Account?>
abstract val isAccountModeFlow: StateFlow<Boolean>
data class AmountParams(
@ -37,7 +37,7 @@ internal sealed class SendAmountComponentParams {
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
override val isBalanceHidingFlow: StateFlow<Boolean>,
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
override val accountFlow: StateFlow<Account?>,
override val isAccountModeFlow: StateFlow<Boolean>,
val callback: ModelCallback,
val currentRoute: StateFlow<CommonSendRoute>,
@ -53,7 +53,7 @@ internal sealed class SendAmountComponentParams {
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
override val isBalanceHidingFlow: StateFlow<Boolean>,
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
override val accountFlow: StateFlow<Account?>,
override val isAccountModeFlow: StateFlow<Boolean>,
val userWallet: UserWallet,
val blockClickEnableFlow: StateFlow<Boolean>,

View file

@ -149,7 +149,7 @@ internal class SendAmountModel @Inject constructor(
private suspend fun initMinBoundary(
cryptoCurrencyStatus: CryptoCurrencyStatus,
account: Account.CryptoPortfolio?,
account: Account?,
isAccountsMode: Boolean,
) {
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
@ -178,11 +178,7 @@ internal class SendAmountModel @Inject constructor(
}
}
private fun initialState(
cryptoCurrencyStatus: CryptoCurrencyStatus,
account: Account.CryptoPortfolio?,
isAccountsMode: Boolean,
) {
private fun initialState(cryptoCurrencyStatus: CryptoCurrencyStatus, account: Account?, isAccountsMode: Boolean) {
val userWallet = userWallet
if (uiState.value is AmountState.Empty && userWallet != null) {
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1

View file

@ -14,7 +14,7 @@ import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
import com.tangem.domain.account.status.supplier.MultiAccountStatusListSupplier
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.filterCryptoPortfolio
import com.tangem.domain.models.network.CryptoCurrencyAddress
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.isLocked
@ -272,36 +272,40 @@ internal class SendDestinationModel @Inject constructor(
return combine(
flow = getWalletsUseCase().conflate(),
flow2 = multiAccountStatusListSupplier().conflate(),
) { wallets, accountList ->
) { wallets, accountStatusLists ->
val cryptoCurrencyNetwork = cryptoCurrency.network
coroutineScope {
accountList.mapNotNull { accountStatusList ->
val wallet =
wallets.filterNot { it.isLocked }.firstOrNull { it.walletId == accountStatusList.userWalletId }
?: return@mapNotNull null
accountStatusLists.mapNotNull { accountStatusList ->
val wallet = wallets
.filterNot { it.isLocked }
.firstOrNull { it.walletId == accountStatusList.userWalletId }
?: return@mapNotNull null
async {
accountStatusList.accountStatuses.map { accountStatus ->
async {
accountStatus.flattenCurrencies()
.filter { it.currency.network.rawId == cryptoCurrencyNetwork.rawId }
.mapNotNull { cryptoCurrencyStatus ->
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
?: return@mapNotNull null
accountStatusList.flattenCurrencies()
.filter { it.currency.network.rawId == cryptoCurrencyNetwork.rawId }
.mapNotNull { cryptoCurrencyStatus ->
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
?: return@mapNotNull null
async {
DestinationWalletUM(
name = wallet.name,
address = address,
cryptoCurrency = cryptoCurrencyStatus.currency,
userWalletId = wallet.walletId,
account = accountStatus.account as? Account.CryptoPortfolio,
)
}
}.awaitAll()
// Find the corresponding account from accountStatuses
val account = accountStatusList.accountStatuses
.filterCryptoPortfolio()
.firstOrNull { accountStatus ->
accountStatus.tokenList
.flattenCurrencies()
.any { it.currency.id == cryptoCurrencyStatus.currency.id }
}?.account
DestinationWalletUM(
name = wallet.name,
address = address,
cryptoCurrency = cryptoCurrencyStatus.currency,
userWalletId = wallet.walletId,
account = account,
)
}
}.awaitAll().flatten()
}
}.awaitAll().flatten()
}

View file

@ -1,9 +1,11 @@
package com.tangem.features.send.v2.subcomponents.destination.model.converters
import com.tangem.common.ui.account.AccountIconUM
import com.tangem.common.ui.account.AccountTitleUM
import com.tangem.common.ui.account.CryptoPortfolioIconConverter
import com.tangem.common.ui.account.toUM
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationRecipientListUM
import com.tangem.features.send.v2.subcomponents.destination.model.transformers.WALLET_DEFAULT_COUNT
@ -59,7 +61,12 @@ internal class SendRecipientWalletListConverter(
accountTitleUM = if (account != null && isAccountsMode) {
AccountTitleUM.Account(
name = account.accountName.toUM().value,
icon = CryptoPortfolioIconConverter.convert(account.icon),
icon = when (account) {
is Account.CryptoPortfolio -> CryptoPortfolioIconConverter.convert(
account.icon,
)
is Account.Payment -> AccountIconUM.Payment
},
prefixText = stringReference(StringsSigns.DOT),
)
} else {

View file

@ -20,5 +20,5 @@ data class DestinationWalletUM(
val userWalletId: UserWalletId,
val address: String,
val cryptoCurrency: CryptoCurrency,
val account: Account.CryptoPortfolio? = null,
val account: Account? = null,
)