Updated on 2026-08-14
This commit is contained in:
commit
a8e9144dad
16 changed files with 78 additions and 26 deletions
|
|
@ -2,9 +2,15 @@ package com.tangem.tap.proxy
|
|||
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.Message
|
||||
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.cosmos.CosmosTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.blockchains.optimism.OptimismWalletManager
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarMemo
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ton.TonTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
|
|
@ -18,6 +24,8 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository
|
|||
import com.tangem.domain.common.BlockchainNetwork
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.XlmMemoType
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.determineXlmMemoType
|
||||
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
|
||||
import com.tangem.lib.crypto.TransactionManager
|
||||
import com.tangem.lib.crypto.models.*
|
||||
|
|
@ -143,6 +151,25 @@ class TransactionManagerImpl(
|
|||
return blockchain.getExploreTxUrl(txAddress)
|
||||
}
|
||||
|
||||
override fun getMemoExtras(networkId: String, memo: String?): TransactionExtras? {
|
||||
val blockchain = Blockchain.fromNetworkId(networkId)
|
||||
if (memo == null) return null
|
||||
return when (blockchain) {
|
||||
Blockchain.Stellar -> {
|
||||
val xmlMemo = when (determineXlmMemoType(memo)) {
|
||||
XlmMemoType.TEXT -> StellarMemo.Text(memo)
|
||||
XlmMemoType.ID -> StellarMemo.Id(memo.toBigInteger())
|
||||
}
|
||||
StellarTransactionExtras(xmlMemo)
|
||||
}
|
||||
Blockchain.Binance -> BinanceTransactionExtras(memo)
|
||||
Blockchain.XRP -> memo.toLongOrNull()?.let { XrpTransactionBuilder.XrpTransactionExtras(it) }
|
||||
Blockchain.Cosmos -> CosmosTransactionExtras(memo)
|
||||
Blockchain.TON -> TonTransactionExtras(memo)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNativeTokenDecimals(networkId: String): Int {
|
||||
return Blockchain.fromNetworkId(networkId)?.decimals() ?: error("blockchain not found")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ data class ExchangeDataResponse(
|
|||
|
||||
@Json(name = "externalTxUrl")
|
||||
val externalTxUrl: String?, // null if DEX, url of provider exchange status page if CEX
|
||||
|
||||
@Json(name = "txExtraIdName")
|
||||
val txExtraIdName: String?,
|
||||
|
||||
@Json(name = "txExtraId")
|
||||
val txExtraId: String?,
|
||||
)
|
||||
|
||||
enum class TxType {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ object PreferencesKeys {
|
|||
|
||||
val IS_WALLET_SWAP_PROMO_SHOW_KEY by lazy { booleanPreferencesKey(name = "isWalletSwapPromoShown") }
|
||||
|
||||
val IS_TOKEN_SWAP_PROMO_SHOW_KEY by lazy { stringSetPreferencesKey(name = "isTokenSwapPromoShown") }
|
||||
val IS_TOKEN_SWAP_PROMO_SHOW_KEY by lazy { booleanPreferencesKey(name = "isTokenSwapPromoShown") }
|
||||
}
|
||||
|
||||
/** Preferences keys set that should be migrated from "PreferencesDataSource" to a new DataStore<Preferences> */
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ class DefaultSwapPromoRepository(
|
|||
.map { it && checkPromoPeriod() }
|
||||
}
|
||||
|
||||
override fun isReadyToShowToken(userWalletId: String, currencyId: String): Flow<Boolean> {
|
||||
return appPreferencesStore.get(IS_TOKEN_SWAP_PROMO_SHOW_KEY, emptySet())
|
||||
.map { !it.contains(userWalletId + currencyId) && checkPromoPeriod() }
|
||||
override fun isReadyToShowToken(): Flow<Boolean> {
|
||||
return appPreferencesStore.get(IS_TOKEN_SWAP_PROMO_SHOW_KEY, true)
|
||||
.map { it && checkPromoPeriod() }
|
||||
}
|
||||
|
||||
override suspend fun setNeverToShowWallet() {
|
||||
|
|
@ -33,14 +33,11 @@ class DefaultSwapPromoRepository(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun setNeverToShowToken(userWalletId: String, currencyId: String) {
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
val storesCurrencies = mutablePreferences.getOrDefault(IS_TOKEN_SWAP_PROMO_SHOW_KEY, emptySet())
|
||||
mutablePreferences.set(
|
||||
key = IS_TOKEN_SWAP_PROMO_SHOW_KEY,
|
||||
value = storesCurrencies.toMutableSet().apply { add(userWalletId + currencyId) },
|
||||
)
|
||||
}
|
||||
override suspend fun setNeverToShowToken() {
|
||||
appPreferencesStore.store(
|
||||
key = IS_TOKEN_SWAP_PROMO_SHOW_KEY,
|
||||
value = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkPromoPeriod(): Boolean {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
|
||||
class ShouldShowSwapPromoTokenUseCase(private val swapPromoRepository: SwapPromoRepository) {
|
||||
|
||||
operator fun invoke(userWalletId: String, currencyId: String): Flow<Boolean> =
|
||||
swapPromoRepository.isReadyToShowToken(userWalletId, currencyId)
|
||||
operator fun invoke(): Flow<Boolean> = swapPromoRepository.isReadyToShowToken()
|
||||
|
||||
suspend fun neverToShow(userWalletId: String, currencyId: String) =
|
||||
swapPromoRepository.setNeverToShowToken(userWalletId, currencyId)
|
||||
suspend fun neverToShow() = swapPromoRepository.setNeverToShowToken()
|
||||
}
|
||||
|
|
@ -5,9 +5,9 @@ import kotlinx.coroutines.flow.Flow
|
|||
interface SwapPromoRepository {
|
||||
fun isReadyToShowWallet(): Flow<Boolean>
|
||||
|
||||
fun isReadyToShowToken(userWalletId: String, currencyId: String): Flow<Boolean>
|
||||
fun isReadyToShowToken(): Flow<Boolean>
|
||||
|
||||
suspend fun setNeverToShowWallet()
|
||||
|
||||
suspend fun setNeverToShowToken(userWalletId: String, currencyId: String)
|
||||
suspend fun setNeverToShowToken()
|
||||
}
|
||||
|
|
@ -85,7 +85,7 @@ class GetCurrencyWarningsUseCase(
|
|||
val currency = currencyStatus.currency
|
||||
val cryptoStatuses = operations.getCurrenciesStatusesSync()
|
||||
return combine(
|
||||
showSwapPromoTokenUseCase(userWalletId.stringValue, currency.id.value).conflate(),
|
||||
showSwapPromoTokenUseCase().conflate(),
|
||||
flowOf(marketCryptoCurrencyRepository.isExchangeable(userWalletId, currency)).conflate(),
|
||||
) { shouldShowSwapPromo, isExchangeable ->
|
||||
if (shouldShowSwapPromo && isExchangeable) {
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
|||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.converters.*
|
||||
import com.tangem.feature.swap.domain.api.SwapRepository
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
import com.tangem.feature.swap.domain.models.DataError
|
||||
import com.tangem.feature.swap.domain.models.ExpressException
|
||||
import com.tangem.feature.swap.domain.models.createFromAmountWithOffset
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ class ExpressDataConverter : Converter<ExchangeDataResponse, SwapDataModel> {
|
|||
txTo = transactionDto.txTo,
|
||||
externalTxId = requireNotNull(transactionDto.externalTxId),
|
||||
externalTxUrl = requireNotNull(transactionDto.externalTxUrl),
|
||||
txExtraIdName = transactionDto.txExtraIdName,
|
||||
txExtraId = transactionDto.txExtraId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.feature.swap.domain.api
|
|||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
import com.tangem.feature.swap.domain.models.DataError
|
||||
import com.tangem.feature.swap.domain.models.domain.*
|
||||
import java.math.BigDecimal
|
||||
|
||||
interface SwapRepository {
|
||||
|
|
|
|||
|
|
@ -25,5 +25,7 @@ sealed class ExpressTransactionModel {
|
|||
override val txTo: String,
|
||||
val externalTxId: String,
|
||||
val externalTxUrl: String,
|
||||
val txExtraIdName: String?,
|
||||
val txExtraId: String?,
|
||||
) : ExpressTransactionModel()
|
||||
}
|
||||
|
|
@ -499,13 +499,23 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
toAddress = currencyToGet.value.networkAddress?.defaultAddress?.value ?: "",
|
||||
).getOrNull()
|
||||
|
||||
val exchangeDataCex = exchangeData?.transaction as? ExpressTransactionModel.CEX ?: return TxState.UnknownError
|
||||
val txExtras = transactionManager.getMemoExtras(
|
||||
currencyToSend.currency.network.backendId,
|
||||
exchangeDataCex.txExtraId,
|
||||
)
|
||||
if (txExtras == null && exchangeDataCex.txExtraId != null) {
|
||||
return TxState.UnknownError
|
||||
}
|
||||
val txData = walletManagersFacade.createTransaction(
|
||||
amount = amount.value.convertToAmount(currencyToSend.currency),
|
||||
fee = getFeeForTransaction(txFee),
|
||||
memo = null,
|
||||
destination = (exchangeData?.transaction as ExpressTransactionModel.CEX).txTo,
|
||||
destination = exchangeDataCex.txTo,
|
||||
userWalletId = userWalletId,
|
||||
network = currencyToSend.currency.network,
|
||||
)?.copy(
|
||||
extras = txExtras,
|
||||
)
|
||||
|
||||
val result = sendTransactionUseCase(
|
||||
|
|
|
|||
|
|
@ -563,14 +563,14 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
|
||||
override fun onSwapPromoDismiss() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
shouldShowSwapPromoTokenUseCase.neverToShow(userWalletId.stringValue, cryptoCurrency.id.value)
|
||||
shouldShowSwapPromoTokenUseCase.neverToShow()
|
||||
analyticsEventsHandler.send(TokenSwapPromoAnalyticsEvent.Close)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSwapPromoClick() {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
shouldShowSwapPromoTokenUseCase.neverToShow(userWalletId.stringValue, cryptoCurrency.id.value)
|
||||
shouldShowSwapPromoTokenUseCase.neverToShow()
|
||||
analyticsEventsHandler.send(TokenSwapPromoAnalyticsEvent.Exchange(cryptoCurrency.symbol))
|
||||
}
|
||||
onSwapClick()
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ spr-client = "3.6.2"
|
|||
# endregion Other libraries
|
||||
|
||||
# region Tangem
|
||||
tangemBlockchainSdk = "release-app_5.4-417"
|
||||
tangemBlockchainSdk = "release-app_5.4-419"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "release-app_5.4-315"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
plugins {
|
||||
alias(deps.plugins.kotlin.jvm)
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.kotlin.serialization)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
|
|
@ -7,4 +10,7 @@ dependencies {
|
|||
|
||||
/** Coroutines */
|
||||
implementation(deps.kotlin.coroutines)
|
||||
|
||||
/** SDK */
|
||||
implementation(deps.tangem.blockchain)
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.lib.crypto
|
||||
|
||||
import com.tangem.blockchain.common.TransactionExtras
|
||||
import com.tangem.lib.crypto.models.*
|
||||
import com.tangem.lib.crypto.models.transactions.SendTxResult
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -71,4 +72,7 @@ interface TransactionManager {
|
|||
|
||||
@Throws(IllegalStateException::class)
|
||||
fun getExplorerTransactionLink(networkId: String, txAddress: String): String
|
||||
|
||||
// TODO: move to another place to use as in Send feature
|
||||
fun getMemoExtras(networkId: String, memo: String?): TransactionExtras?
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue