Updated on 2026-08-14
This commit is contained in:
parent
76209eb454
commit
64d429f642
15 changed files with 120 additions and 110 deletions
|
|
@ -23,6 +23,7 @@ dependencies {
|
||||||
implementation(projects.domain.models)
|
implementation(projects.domain.models)
|
||||||
implementation(projects.domain.wallets.models)
|
implementation(projects.domain.wallets.models)
|
||||||
implementation(projects.domain.appCurrency.models)
|
implementation(projects.domain.appCurrency.models)
|
||||||
|
implementation(projects.domain.tokens.models)
|
||||||
|
|
||||||
/** Project - Utils */
|
/** Project - Utils */
|
||||||
implementation(projects.core.utils)
|
implementation(projects.core.utils)
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,9 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val visaApiRequestMaker: VisaApiRequestMaker,
|
private val visaApiRequestMaker: VisaApiRequestMaker,
|
||||||
private val visaApi: TangemVisaApi,
|
private val visaApi: TangemVisaApi,
|
||||||
|
private val visaCurrencyFactory: VisaCurrencyFactory,
|
||||||
) : VisaRepository {
|
) : VisaRepository {
|
||||||
|
|
||||||
private val currencyFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
|
|
||||||
VisaCurrencyFactory()
|
|
||||||
}
|
|
||||||
private val txDetailsFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
|
private val txDetailsFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
|
||||||
VisaTxDetailsFactory()
|
VisaTxDetailsFactory()
|
||||||
}
|
}
|
||||||
|
|
@ -79,20 +77,22 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
|
|
||||||
private suspend fun fetchVisaCurrency(userWalletId: UserWalletId, address: String) {
|
private suspend fun fetchVisaCurrency(userWalletId: UserWalletId, address: String) {
|
||||||
val contractInfoProvider = visaLibLoader.getOrCreateProvider()
|
val contractInfoProvider = visaLibLoader.getOrCreateProvider()
|
||||||
|
val paymentAccountAddress = getPaymentAccountAddress(userWalletId)
|
||||||
|
val userWallet = findVisaUserWallet(userWalletId)
|
||||||
|
|
||||||
parZip(
|
parZip(
|
||||||
dispatchers.io,
|
dispatchers.io,
|
||||||
{
|
{
|
||||||
contractInfoProvider.getContractInfo(
|
contractInfoProvider.getContractInfo(
|
||||||
walletAddress = address,
|
walletAddress = address,
|
||||||
paymentAccountAddress = getPaymentAccountAddress(userWalletId),
|
paymentAccountAddress = paymentAccountAddress,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{ getFiatRate() },
|
{ getFiatRate() },
|
||||||
{ contractInfo, fiatRate ->
|
{ contractInfo, fiatRate ->
|
||||||
fetchedCurrencies.update { value ->
|
fetchedCurrencies.update { value ->
|
||||||
value.apply {
|
value.apply {
|
||||||
put(address, currencyFactory.create(contractInfo, fiatRate))
|
put(address, visaCurrencyFactory.create(userWallet, contractInfo, fiatRate))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -157,7 +157,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO select correct account when multiple accounts are available (will be implemented when backend is ready)
|
// There will be only one payment account (backend has filtered for us), so we can take the first one
|
||||||
customerInfo.paymentAccounts.firstOrNull()?.paymentAccountAddress
|
customerInfo.paymentAccounts.firstOrNull()?.paymentAccountAddress
|
||||||
}.getOrNull()
|
}.getOrNull()
|
||||||
|
|
||||||
|
|
@ -187,14 +187,14 @@ internal class DefaultVisaRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getFiatRate(): BigDecimal? {
|
private suspend fun getFiatRate(): BigDecimal {
|
||||||
val fiatCurrencyId = VisaConstants.fiatCurrency.code.lowercase()
|
val fiatCurrencyId = VisaConstants.fiatCurrency.code.lowercase()
|
||||||
val quotes = tangemTechApi.getQuotes(
|
val quotes = tangemTechApi.getQuotes(
|
||||||
currencyId = fiatCurrencyId,
|
currencyId = fiatCurrencyId,
|
||||||
coinIds = VisaConstants.TOKEN_ID,
|
coinIds = VisaConstants.TOKEN_ID,
|
||||||
).getOrThrow()
|
).getOrThrow()
|
||||||
|
|
||||||
return quotes.quotes[VisaConstants.TOKEN_ID]?.price
|
return quotes.quotes[VisaConstants.TOKEN_ID]?.price ?: error("No price found")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeWalletAddresses(userWallet: UserWallet): Set<Address> {
|
private fun makeWalletAddresses(userWallet: UserWallet): Set<Address> {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,28 @@
|
||||||
package com.tangem.data.visa.utils
|
package com.tangem.data.visa.utils
|
||||||
|
|
||||||
|
import com.tangem.blockchain.common.Blockchain
|
||||||
|
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||||
|
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||||
|
import com.tangem.data.common.currency.getNetwork
|
||||||
|
import com.tangem.domain.common.util.derivationStyleProvider
|
||||||
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
|
import com.tangem.domain.tokens.model.NetworkAddress
|
||||||
import com.tangem.domain.visa.model.VisaCurrency
|
import com.tangem.domain.visa.model.VisaCurrency
|
||||||
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
import com.tangem.lib.visa.model.VisaContractInfo
|
import com.tangem.lib.visa.model.VisaContractInfo
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.joda.time.DateTimeZone
|
import org.joda.time.DateTimeZone
|
||||||
import org.joda.time.Instant
|
import org.joda.time.Instant
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class VisaCurrencyFactory {
|
internal class VisaCurrencyFactory @Inject constructor(
|
||||||
|
private val cryptoCurrencyFactory: CryptoCurrencyFactory,
|
||||||
|
private val excludedBlockchains: ExcludedBlockchains,
|
||||||
|
) {
|
||||||
|
|
||||||
fun create(contractInfo: VisaContractInfo, fiatRate: BigDecimal?): VisaCurrency {
|
fun create(userWallet: UserWallet, contractInfo: VisaContractInfo, fiatRate: BigDecimal): VisaCurrency {
|
||||||
val now = Instant.now()
|
val now = Instant.now()
|
||||||
val currentLimit = if (contractInfo.limitsChangeDate > now) {
|
val currentLimit = if (contractInfo.limitsChangeDate > now) {
|
||||||
contractInfo.oldLimits
|
contractInfo.oldLimits
|
||||||
|
|
@ -19,11 +31,30 @@ internal class VisaCurrencyFactory {
|
||||||
}
|
}
|
||||||
val remainingOtpLimit = getRemainingOtp(currentLimit, now)
|
val remainingOtpLimit = getRemainingOtp(currentLimit, now)
|
||||||
|
|
||||||
|
val currencyNetwork = getNetwork(
|
||||||
|
blockchain = Blockchain.Polygon,
|
||||||
|
extraDerivationPath = null,
|
||||||
|
derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider,
|
||||||
|
excludedBlockchains = excludedBlockchains,
|
||||||
|
canHandleTokens = true,
|
||||||
|
) ?: error("Unable to create network for Visa currency")
|
||||||
|
|
||||||
|
val cryptoCurrency = cryptoCurrencyFactory.createToken(
|
||||||
|
network = currencyNetwork,
|
||||||
|
rawId = CryptoCurrency.RawID(VisaConstants.TOKEN_ID),
|
||||||
|
name = contractInfo.token.name,
|
||||||
|
symbol = contractInfo.token.symbol,
|
||||||
|
decimals = contractInfo.token.decimals,
|
||||||
|
contractAddress = contractInfo.token.address,
|
||||||
|
)
|
||||||
|
|
||||||
return VisaCurrency(
|
return VisaCurrency(
|
||||||
|
cryptoCurrency = cryptoCurrency,
|
||||||
symbol = contractInfo.token.symbol,
|
symbol = contractInfo.token.symbol,
|
||||||
networkName = VisaConstants.NETWORK_NAME,
|
networkName = VisaConstants.NETWORK_NAME,
|
||||||
decimals = contractInfo.token.decimals,
|
decimals = contractInfo.token.decimals,
|
||||||
fiatRate = fiatRate,
|
fiatRate = fiatRate,
|
||||||
|
priceChange = BigDecimal.ZERO, // [Second Visa Iteration] pass to create() params if needed
|
||||||
fiatCurrency = VisaConstants.fiatCurrency,
|
fiatCurrency = VisaConstants.fiatCurrency,
|
||||||
balances = with(contractInfo) {
|
balances = with(contractInfo) {
|
||||||
VisaCurrency.Balances(
|
VisaCurrency.Balances(
|
||||||
|
|
@ -40,6 +71,12 @@ internal class VisaCurrencyFactory {
|
||||||
singleTransaction = currentLimit.singleTransactionLimit,
|
singleTransaction = currentLimit.singleTransactionLimit,
|
||||||
expirationDate = getLimitsExpirationDate(currentLimit, now),
|
expirationDate = getLimitsExpirationDate(currentLimit, now),
|
||||||
),
|
),
|
||||||
|
paymentAccountAddress = NetworkAddress.Single(
|
||||||
|
NetworkAddress.Address(
|
||||||
|
value = contractInfo.paymentAccountAddress,
|
||||||
|
type = NetworkAddress.Address.Type.Primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,22 @@
|
||||||
package com.tangem.domain.visa.model
|
package com.tangem.domain.visa.model
|
||||||
|
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
|
import com.tangem.domain.tokens.model.NetworkAddress
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
data class VisaCurrency(
|
data class VisaCurrency(
|
||||||
|
val cryptoCurrency: CryptoCurrency,
|
||||||
val networkName: String,
|
val networkName: String,
|
||||||
val symbol: String,
|
val symbol: String,
|
||||||
val decimals: Int,
|
val decimals: Int,
|
||||||
val fiatRate: BigDecimal?,
|
val fiatRate: BigDecimal,
|
||||||
|
val priceChange: BigDecimal,
|
||||||
val fiatCurrency: AppCurrency,
|
val fiatCurrency: AppCurrency,
|
||||||
val balances: Balances,
|
val balances: Balances,
|
||||||
val limits: Limits,
|
val limits: Limits,
|
||||||
|
val paymentAccountAddress: NetworkAddress,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
data class Balances(
|
data class Balances(
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,19 @@ package com.tangem.feature.wallet.child.wallet.model.intents
|
||||||
|
|
||||||
import arrow.core.getOrElse
|
import arrow.core.getOrElse
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.mapToAddressModels
|
|
||||||
import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
|
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|
||||||
import com.tangem.domain.tokens.model.Network
|
|
||||||
import com.tangem.domain.visa.GetVisaCurrencyUseCase
|
import com.tangem.domain.visa.GetVisaCurrencyUseCase
|
||||||
import com.tangem.domain.visa.GetVisaTxDetailsUseCase
|
import com.tangem.domain.visa.GetVisaTxDetailsUseCase
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.BalancesAndLimitsBottomSheetConverter
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.BalancesAndLimitsBottomSheetConverter
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.VisaTxDetailsBottomSheetConverter
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.VisaTxDetailsBottomSheetConverter
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal interface VisaWalletIntents {
|
internal interface VisaWalletIntents {
|
||||||
|
|
||||||
fun onDepositClick()
|
|
||||||
|
|
||||||
fun onBalancesAndLimitsClick()
|
fun onBalancesAndLimitsClick()
|
||||||
|
|
||||||
fun onVisaTransactionClick(id: String)
|
fun onVisaTransactionClick(id: String)
|
||||||
|
|
@ -36,7 +26,6 @@ internal interface VisaWalletIntents {
|
||||||
internal class VisaWalletIntentsImplementor @Inject constructor(
|
internal class VisaWalletIntentsImplementor @Inject constructor(
|
||||||
private val stateController: WalletStateController,
|
private val stateController: WalletStateController,
|
||||||
private val eventSender: WalletEventSender,
|
private val eventSender: WalletEventSender,
|
||||||
private val getCurrencyStatusUseCase: GetCryptoCurrencyStatusSyncUseCase,
|
|
||||||
private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase,
|
private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase,
|
||||||
private val getVisaTxDetailsUseCase: GetVisaTxDetailsUseCase,
|
private val getVisaTxDetailsUseCase: GetVisaTxDetailsUseCase,
|
||||||
private val dispatchers: CoroutineDispatcherProvider,
|
private val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
|
@ -46,38 +35,6 @@ internal class VisaWalletIntentsImplementor @Inject constructor(
|
||||||
BalancesAndLimitsBottomSheetConverter(eventSender)
|
BalancesAndLimitsBottomSheetConverter(eventSender)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDepositClick() {
|
|
||||||
val userWalletId = stateController.getSelectedWalletId()
|
|
||||||
|
|
||||||
modelScope.launch(dispatchers.main) {
|
|
||||||
val currencyStatus = getPrimaryCurrencyStatus(userWalletId) ?: return@launch
|
|
||||||
|
|
||||||
createReceiveBottomSheetContent(currencyStatus)?.let { content ->
|
|
||||||
stateController.showBottomSheet(content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createReceiveBottomSheetContent(currencyStatus: CryptoCurrencyStatus): TangemBottomSheetConfigContent? {
|
|
||||||
val currency = currencyStatus.currency
|
|
||||||
val addresses = currencyStatus.value.networkAddress?.availableAddresses
|
|
||||||
|
|
||||||
if (addresses == null) {
|
|
||||||
Timber.e("Addresses should not be null")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return TokenReceiveBottomSheetConfig(
|
|
||||||
name = currency.name,
|
|
||||||
symbol = currency.symbol,
|
|
||||||
network = currency.network.name,
|
|
||||||
addresses = addresses.mapToAddressModels(currency).toImmutableList(),
|
|
||||||
showMemoDisclaimer = currency.network.transactionExtrasType != Network.TransactionExtrasType.NONE,
|
|
||||||
onCopyClick = { /* no-op */ },
|
|
||||||
onShareClick = { /* no-op */ },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBalancesAndLimitsClick() {
|
override fun onBalancesAndLimitsClick() {
|
||||||
modelScope.launch(dispatchers.main) {
|
modelScope.launch(dispatchers.main) {
|
||||||
val userWalletId = stateController.getSelectedWalletId()
|
val userWalletId = stateController.getSelectedWalletId()
|
||||||
|
|
@ -95,14 +52,6 @@ internal class VisaWalletIntentsImplementor @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getPrimaryCurrencyStatus(userWalletId: UserWalletId): CryptoCurrencyStatus? {
|
|
||||||
return getCurrencyStatusUseCase(userWalletId)
|
|
||||||
.getOrElse {
|
|
||||||
Timber.e("Failed to get primary currency $it")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onVisaTransactionClick(id: String) {
|
override fun onVisaTransactionClick(id: String) {
|
||||||
modelScope.launch(dispatchers.main) {
|
modelScope.launch(dispatchers.main) {
|
||||||
val userWalletId = stateController.getSelectedWalletId()
|
val userWalletId = stateController.getSelectedWalletId()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
|
||||||
|
|
||||||
internal data class DepositButtonState(
|
|
||||||
val isEnabled: Boolean,
|
|
||||||
val onClick: () -> Unit,
|
|
||||||
)
|
|
||||||
|
|
@ -96,7 +96,6 @@ internal sealed interface WalletState : WalletStateHolder {
|
||||||
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
override val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||||
override val balancesAndLimitBlockState: BalancesAndLimitsBlockState,
|
override val balancesAndLimitBlockState: BalancesAndLimitsBlockState,
|
||||||
override val txHistoryState: TxHistoryState,
|
override val txHistoryState: TxHistoryState,
|
||||||
val depositButtonState: DepositButtonState,
|
|
||||||
) : Visa()
|
) : Visa()
|
||||||
|
|
||||||
data class Locked(
|
data class Locked(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState
|
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.DepositButtonState
|
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
import kotlinx.collections.immutable.mutate
|
import kotlinx.collections.immutable.mutate
|
||||||
|
|
@ -29,8 +28,8 @@ internal class SetRefreshStateTransformer(
|
||||||
}
|
}
|
||||||
is WalletState.Visa.Content -> {
|
is WalletState.Visa.Content -> {
|
||||||
prevState.copy(
|
prevState.copy(
|
||||||
|
buttons = prevState.buttons.toUpdatedState(),
|
||||||
pullToRefreshConfig = prevState.pullToRefreshConfig.toUpdatedState(isRefreshing),
|
pullToRefreshConfig = prevState.pullToRefreshConfig.toUpdatedState(isRefreshing),
|
||||||
depositButtonState = prevState.depositButtonState.toUpdatedState(isRefreshing),
|
|
||||||
balancesAndLimitBlockState = prevState.balancesAndLimitBlockState.toUpdatedState(isRefreshing),
|
balancesAndLimitBlockState = prevState.balancesAndLimitBlockState.toUpdatedState(isRefreshing),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -75,10 +74,6 @@ internal class SetRefreshStateTransformer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DepositButtonState.toUpdatedState(isRefreshing: Boolean): DepositButtonState {
|
|
||||||
return copy(isEnabled = !isRefreshing)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun BalancesAndLimitsBlockState.toUpdatedState(isRefreshing: Boolean): BalancesAndLimitsBlockState {
|
private fun BalancesAndLimitsBlockState.toUpdatedState(isRefreshing: Boolean): BalancesAndLimitsBlockState {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is BalancesAndLimitsBlockState.Content -> copy(isEnabled = !isRefreshing)
|
is BalancesAndLimitsBlockState.Content -> copy(isEnabled = !isRefreshing)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.ui.format.bigdecimal.crypto
|
||||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||||
import com.tangem.core.ui.format.bigdecimal.format
|
import com.tangem.core.ui.format.bigdecimal.format
|
||||||
import com.tangem.domain.common.util.getCardsCount
|
import com.tangem.domain.common.util.getCardsCount
|
||||||
|
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.visa.exception.RefreshTokenExpiredException
|
import com.tangem.domain.visa.exception.RefreshTokenExpiredException
|
||||||
import com.tangem.domain.visa.model.VisaCurrency
|
import com.tangem.domain.visa.model.VisaCurrency
|
||||||
import com.tangem.domain.wallets.models.UserWallet
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
|
|
@ -15,11 +16,14 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditiona
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||||
|
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
|
||||||
import com.tangem.utils.extensions.isZero
|
import com.tangem.utils.extensions.isZero
|
||||||
|
import kotlinx.collections.immutable.PersistentList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import org.joda.time.Days
|
import org.joda.time.Days
|
||||||
|
|
||||||
internal class SetBalancesAndLimitsTransformer(
|
internal class SetVisaInfoTransformer(
|
||||||
private val userWallet: UserWallet,
|
private val userWallet: UserWallet,
|
||||||
private val maybeVisaCurrency: Either<Throwable, VisaCurrency>,
|
private val maybeVisaCurrency: Either<Throwable, VisaCurrency>,
|
||||||
private val clickIntents: WalletClickIntents,
|
private val clickIntents: WalletClickIntents,
|
||||||
|
|
@ -35,15 +39,15 @@ internal class SetBalancesAndLimitsTransformer(
|
||||||
}
|
}
|
||||||
|
|
||||||
return prevState.copy(
|
return prevState.copy(
|
||||||
|
buttons = createVisaButtonsDimmed(),
|
||||||
walletCardState = getErrorWalletCardState(prevState.walletCardState),
|
walletCardState = getErrorWalletCardState(prevState.walletCardState),
|
||||||
depositButtonState = prevState.depositButtonState.copy(isEnabled = false),
|
|
||||||
balancesAndLimitBlockState = BalancesAndLimitsBlockState.Error,
|
balancesAndLimitBlockState = BalancesAndLimitsBlockState.Error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return prevState.copy(
|
return prevState.copy(
|
||||||
|
buttons = createVisaButtons(visaCurrency = visaCurrency),
|
||||||
walletCardState = getContentWalletCardState(prevState.walletCardState, visaCurrency),
|
walletCardState = getContentWalletCardState(prevState.walletCardState, visaCurrency),
|
||||||
depositButtonState = prevState.depositButtonState.copy(isEnabled = true),
|
|
||||||
balancesAndLimitBlockState = getContentBlockState(visaCurrency),
|
balancesAndLimitBlockState = getContentBlockState(visaCurrency),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -115,4 +119,43 @@ internal class SetBalancesAndLimitsTransformer(
|
||||||
onUnlockVisaAccessNotificationClick = clickIntents::onUnlockVisaAccessClick,
|
onUnlockVisaAccessNotificationClick = clickIntents::onUnlockVisaAccessClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createVisaButtonsDimmed(): PersistentList<WalletManageButton> {
|
||||||
|
return persistentListOf(
|
||||||
|
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
||||||
|
WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createVisaButtons(visaCurrency: VisaCurrency): PersistentList<WalletManageButton> {
|
||||||
|
// [Second Visa Iteration] Make VisaCurrency contain CryptoCurrencyStatus
|
||||||
|
val cryptoCurrencyStatus = CryptoCurrencyStatus(
|
||||||
|
currency = visaCurrency.cryptoCurrency,
|
||||||
|
value = CryptoCurrencyStatus.Loaded(
|
||||||
|
amount = visaCurrency.balances.available,
|
||||||
|
fiatAmount = visaCurrency.balances.available.multiply(visaCurrency.fiatRate),
|
||||||
|
fiatRate = visaCurrency.fiatRate,
|
||||||
|
priceChange = visaCurrency.priceChange,
|
||||||
|
yieldBalance = null,
|
||||||
|
hasCurrentNetworkTransactions = false,
|
||||||
|
pendingTransactions = emptySet(),
|
||||||
|
networkAddress = visaCurrency.paymentAccountAddress,
|
||||||
|
sources = CryptoCurrencyStatus.Sources(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return return persistentListOf(
|
||||||
|
WalletManageButton.Receive(
|
||||||
|
enabled = true,
|
||||||
|
dimContent = false,
|
||||||
|
onClick = { clickIntents.onReceiveClick(cryptoCurrencyStatus = cryptoCurrencyStatus) },
|
||||||
|
onLongClick = { clickIntents.onCopyAddressLongClick(cryptoCurrencyStatus = cryptoCurrencyStatus) },
|
||||||
|
),
|
||||||
|
WalletManageButton.Buy(
|
||||||
|
enabled = true,
|
||||||
|
dimContent = false,
|
||||||
|
onClick = { clickIntents.onMultiWalletBuyClick(userWalletId = userWallet.walletId) },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ internal class WalletLoadingStateFactory(
|
||||||
return WalletState.Visa.Content(
|
return WalletState.Visa.Content(
|
||||||
pullToRefreshConfig = createPullToRefreshConfig(),
|
pullToRefreshConfig = createPullToRefreshConfig(),
|
||||||
walletCardState = userWallet.toLoadingWalletCardState(),
|
walletCardState = userWallet.toLoadingWalletCardState(),
|
||||||
buttons = createMultiWalletActions(userWallet),
|
buttons = createVisaDimmedButtons(),
|
||||||
warnings = persistentListOf(),
|
warnings = persistentListOf(),
|
||||||
bottomSheetConfig = null,
|
bottomSheetConfig = null,
|
||||||
balancesAndLimitBlockState = BalancesAndLimitsBlockState.Loading,
|
balancesAndLimitBlockState = BalancesAndLimitsBlockState.Loading,
|
||||||
|
|
@ -76,7 +76,6 @@ internal class WalletLoadingStateFactory(
|
||||||
value = TxHistoryState.getDefaultLoadingTransactions(clickIntents::onExploreClick),
|
value = TxHistoryState.getDefaultLoadingTransactions(clickIntents::onExploreClick),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
depositButtonState = DepositButtonState(isEnabled = false, clickIntents::onDepositClick),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,6 +116,13 @@ internal class WalletLoadingStateFactory(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createVisaDimmedButtons(): PersistentList<WalletManageButton> {
|
||||||
|
return persistentListOf(
|
||||||
|
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
||||||
|
WalletManageButton.Buy(enabled = true, dimContent = true, onClick = {}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createDimmedButtons(): PersistentList<WalletManageButton> {
|
private fun createDimmedButtons(): PersistentList<WalletManageButton> {
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
WalletManageButton.Receive(enabled = true, dimContent = true, onClick = {}, onLongClick = null),
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import com.tangem.domain.visa.model.VisaTxHistoryItem
|
||||||
import com.tangem.domain.wallets.models.UserWallet
|
import com.tangem.domain.wallets.models.UserWallet
|
||||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetBalancesAndLimitsTransformer
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetVisaInfoTransformer
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryCountTransformer
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryCountTransformer
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsErrorTransformer
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsErrorTransformer
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsTransformer
|
import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetTxHistoryItemsTransformer
|
||||||
|
|
@ -62,7 +62,7 @@ internal class VisaWalletSubscriber(
|
||||||
|
|
||||||
private fun setLoadedCurrencyState(maybeCurrency: Either<Throwable, VisaCurrency>) {
|
private fun setLoadedCurrencyState(maybeCurrency: Either<Throwable, VisaCurrency>) {
|
||||||
stateController.update(
|
stateController.update(
|
||||||
SetBalancesAndLimitsTransformer(
|
SetVisaInfoTransformer(
|
||||||
userWallet = userWallet,
|
userWallet = userWallet,
|
||||||
maybeVisaCurrency = maybeCurrency,
|
maybeVisaCurrency = maybeCurrency,
|
||||||
clickIntents = clickIntents,
|
clickIntents = clickIntents,
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrenc
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.BalancesAndLimitsBottomSheet
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.BalancesAndLimitsBottomSheet
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.VisaTxDetailsBottomSheet
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.VisaTxDetailsBottomSheet
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.balancesAndLimitsBlock
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.balancesAndLimitsBlock
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.depositButton
|
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||||
import com.tangem.features.markets.entry.BottomSheetState
|
import com.tangem.features.markets.entry.BottomSheetState
|
||||||
import com.tangem.features.markets.entry.MarketsEntryComponent
|
import com.tangem.features.markets.entry.MarketsEntryComponent
|
||||||
|
|
@ -230,11 +229,6 @@ private fun WalletContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
(selectedWallet as? WalletState.Visa.Content)?.let {
|
(selectedWallet as? WalletState.Visa.Content)?.let {
|
||||||
depositButton(
|
|
||||||
modifier = itemModifier.fillMaxWidth(),
|
|
||||||
state = it.depositButtonState,
|
|
||||||
)
|
|
||||||
|
|
||||||
balancesAndLimitsBlock(
|
balancesAndLimitsBlock(
|
||||||
modifier = itemModifier,
|
modifier = itemModifier,
|
||||||
state = it.balancesAndLimitBlockState,
|
state = it.balancesAndLimitBlockState,
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.visa
|
|
||||||
|
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import com.tangem.core.ui.components.PrimaryButtonIconStart
|
|
||||||
import com.tangem.feature.wallet.impl.R
|
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.DepositButtonState
|
|
||||||
|
|
||||||
private const val DEPOSIT_BUTTON_CONTENT_TYPE = "DepositButton"
|
|
||||||
|
|
||||||
internal fun LazyListScope.depositButton(state: DepositButtonState, modifier: Modifier = Modifier) {
|
|
||||||
item(key = DEPOSIT_BUTTON_CONTENT_TYPE, contentType = DEPOSIT_BUTTON_CONTENT_TYPE) {
|
|
||||||
PrimaryButtonIconStart(
|
|
||||||
modifier = modifier,
|
|
||||||
text = "Deposit",
|
|
||||||
iconResId = R.drawable.ic_arrow_down_24,
|
|
||||||
onClick = state.onClick,
|
|
||||||
enabled = state.isEnabled,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -81,7 +81,14 @@ internal class DefaultVisaContractInfoProvider(
|
||||||
{ fetchBalances(paymentAccount, paymentToken) },
|
{ fetchBalances(paymentAccount, paymentToken) },
|
||||||
{ fetchLimits(paymentAccount, paymentToken, walletAddress) },
|
{ fetchLimits(paymentAccount, paymentToken, walletAddress) },
|
||||||
{ token, balances, (oldLimit, newLimit, changeDate) ->
|
{ token, balances, (oldLimit, newLimit, changeDate) ->
|
||||||
VisaContractInfo(token, balances, oldLimit, newLimit, changeDate)
|
VisaContractInfo(
|
||||||
|
token = token,
|
||||||
|
balances = balances,
|
||||||
|
oldLimits = oldLimit,
|
||||||
|
newLimits = newLimit,
|
||||||
|
paymentAccountAddress = paymentAccount.contractAddress,
|
||||||
|
limitsChangeDate = changeDate,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ data class VisaContractInfo(
|
||||||
val balances: Balances,
|
val balances: Balances,
|
||||||
val oldLimits: Limits,
|
val oldLimits: Limits,
|
||||||
val newLimits: Limits,
|
val newLimits: Limits,
|
||||||
|
val paymentAccountAddress: String,
|
||||||
val limitsChangeDate: Instant,
|
val limitsChangeDate: Instant,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue