From ea37cec21f98de88afd6cf0b9d60a437e6b9505c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 30 Jan 2023 18:21:13 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/proxy/TransactionManagerImpl.kt | 5 + .../tangem/tap/proxy/UserWalletManagerImpl.kt | 106 +++++++++--------- .../swap/domain/BlockchainInteractor.kt | 2 + .../swap/domain/BlockchainInteractorImpl.kt | 4 + .../feature/swap/domain/SwapInteractorImpl.kt | 7 +- .../feature/swap/domain/models/ui/TxState.kt | 7 +- .../feature/swap/presentation/SwapFragment.kt | 2 +- .../feature/swap/router/CustomTabsManager.kt | 3 +- .../tangem/feature/swap/ui/StateBuilder.kt | 8 +- .../feature/swap/viewmodels/SwapViewModel.kt | 12 +- .../tangem/lib/crypto/TransactionManager.kt | 3 + .../tangem/lib/crypto/UserWalletManager.kt | 5 + 12 files changed, 100 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt index b1cdd1eec0..9ad9faf3a0 100644 --- a/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/TransactionManagerImpl.kt @@ -111,6 +111,11 @@ class TransactionManagerImpl( return handleSendResult(sendResult) } + override fun getExplorerTransactionLink(networkId: String, txAddress: String): String { + val blockchain = Blockchain.fromNetworkId(networkId) ?: error("blockchain not found") + return blockchain.getExploreTxUrl(txAddress) + } + override fun getNativeTokenDecimals(networkId: String): Int { return Blockchain.fromNetworkId(networkId)?.decimals() ?: error("blockchain not found") } diff --git a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt index 7af01a37c6..76a34f2d5f 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -92,32 +92,37 @@ class UserWalletManagerImpl( // todo check is it sync operation override fun addToken(currency: Currency) { + val card = requireNotNull(appStateHolder.getActualCard()) { "card not found" } + val blockchain = requireNotNull(Blockchain.fromNetworkId(currency.networkId)) { "blockchain not found" } val action = if (currency is NativeToken) { - val card = appStateHolder.getActualCard() - if (card != null) addNativeTokenToWalletAction(currency, card) else error("Card not found") + addNativeTokenToWalletAction(card, blockchain) } else { - addNonNativeTokenToWalletAction(currency as NonNativeToken) + addNonNativeTokenToWalletAction(currency as NonNativeToken, card, blockchain) } val mainStore = requireNotNull(appStateHolder.mainStore) { "mainStore is null" } mainStore.dispatch(action) } override fun getWalletAddress(networkId: String): String { - val blockchain = Blockchain.fromNetworkId(networkId) - val card = appStateHolder.getActualCard() - if (blockchain != null && card != null) { - val blockchainNetwork = BlockchainNetwork(blockchain, card) - val walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork) - if (walletManager != null) { - return walletManager.wallet.address - } else { - error("no wallet manager found") - } + val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" } + val card = requireNotNull(appStateHolder.getActualCard()) { "card not found" } + val blockchainNetwork = BlockchainNetwork(blockchain, card) + val walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork) + if (walletManager != null) { + return walletManager.wallet.address } else { - error("no blockchain or card found") + error("no wallet manager found") } } + override fun getLastTransactionHash(networkId: String): String? { + val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" } + val card = requireNotNull(appStateHolder.getActualCard()) { "card not found" } + val blockchainNetwork = BlockchainNetwork(blockchain, card) + val walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork) + return walletManager?.wallet?.recentTransactions?.lastOrNull()?.hash?.let { HEX_PREFIX + it } + } + override fun getCurrentWalletTokensBalance(networkId: String): Map { val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" } val walletManager = getActualWalletManager(blockchain) @@ -159,50 +164,39 @@ class UserWalletManagerImpl( ) } - private fun addNativeTokenToWalletAction(token: NativeToken, card: CardDTO): Action { - val blockchain = Blockchain.fromNetworkId(token.networkId) - val scanResponse = appStateHolder.scanResponse - if (blockchain != null && scanResponse != null) { - val blockchainNetwork = BlockchainNetwork(blockchain, card) - var walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork) - if (walletManager == null) { - walletManager = walletManagerFactory.makeWalletManagerForApp( - scanResponse = scanResponse, - blockchain = blockchain, - derivationParams = createDerivationParams(card.derivationStyle), - ) - } - return WalletAction.MultiWallet.AddBlockchain( - blockchain = blockchainNetwork, - walletManager = walletManager, - save = true, + private fun addNativeTokenToWalletAction(card: CardDTO, blockchain: Blockchain): Action { + val scanResponse = requireNotNull(appStateHolder.scanResponse) { "scanResponse not found" } + val blockchainNetwork = BlockchainNetwork(blockchain, card) + var walletManager = appStateHolder.walletState?.getWalletManager(blockchainNetwork) + if (walletManager == null) { + walletManager = walletManagerFactory.makeWalletManagerForApp( + scanResponse = scanResponse, + blockchain = blockchain, + derivationParams = createDerivationParams(card.derivationStyle), ) - } else { - error("blockchain is not supported") } + return WalletAction.MultiWallet.AddBlockchain( + blockchain = blockchainNetwork, + walletManager = walletManager, + save = true, + ) } - private fun addNonNativeTokenToWalletAction(token: NonNativeToken): Action { - val card = appStateHolder.getActualCard() - val blockchain = Blockchain.fromNetworkId(token.networkId) - if (card != null && blockchain != null) { - return WalletAction.MultiWallet.AddToken( - token = com.tangem.blockchain.common.Token( - id = token.id, - name = token.name, - symbol = token.symbol, - contractAddress = token.contractAddress, - decimals = token.decimalCount, - ), - blockchain = BlockchainNetwork( - blockchain, - card, - ), - save = true, - ) - } else { - error("no card or blockchain found") - } + private fun addNonNativeTokenToWalletAction(token: NonNativeToken, card: CardDTO, blockchain: Blockchain): Action { + return WalletAction.MultiWallet.AddToken( + token = com.tangem.blockchain.common.Token( + id = token.id, + name = token.name, + symbol = token.symbol, + contractAddress = token.contractAddress, + decimals = token.decimalCount, + ), + blockchain = BlockchainNetwork( + blockchain, + card, + ), + save = true, + ) } private fun createDerivationParams(derivationStyle: DerivationStyle?): DerivationParams? { @@ -217,4 +211,8 @@ class UserWalletManagerImpl( "No wallet manager found" } } + + companion object { + private const val HEX_PREFIX = "0x" + } } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt index 153295b9f4..9830aea157 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractor.kt @@ -13,4 +13,6 @@ interface BlockchainInteractor { * workaround till not use backend only and not integrated server vs sdk */ fun getBlockchainInfo(networkId: String): NetworkInfo + + fun getExplorerTransactionLink(networkId: String, txAddress: String): String } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractorImpl.kt index 8ba3774b95..969b20c5b3 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/BlockchainInteractorImpl.kt @@ -19,6 +19,10 @@ internal class BlockchainInteractorImpl @Inject constructor( } } + override fun getExplorerTransactionLink(networkId: String, txAddress: String): String { + return transactionManager.getExplorerTransactionLink(networkId, txAddress) + } + override fun getTokenDecimals(token: Currency): Int { return if (token is Currency.NonNativeToken) { token.decimalCount diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index 2fcdcc5b52..292bc0b692 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -125,9 +125,9 @@ internal class SwapInteractorImpl @Inject constructor( dataToSign = transactionData.data, ) return when (result) { - SendTxResult.Success -> { + is SendTxResult.Success -> { allowPermissionsHandler.addAddressToInProgress(forTokenContractAddress) - TxState.TxSent() + TxState.TxSent(txAddress = userWalletManager.getLastTransactionHash(networkId) ?: "") } SendTxResult.UserCancelledError -> TxState.UserCancelled is SendTxResult.BlockchainSdkError -> TxState.BlockchainError @@ -211,11 +211,12 @@ internal class SwapInteractorImpl @Inject constructor( isSwap = true, ) return when (result) { - SendTxResult.Success -> { + is SendTxResult.Success -> { userWalletManager.addToken(cryptoCurrencyConverter.convert(currencyToGet)) TxState.TxSent( fromAmount = amountFormatter.formatSwapAmountToUI(swapData.fromTokenAmount, currencyToSend.symbol), toAmount = amountFormatter.formatSwapAmountToUI(swapData.toTokenAmount, currencyToGet.symbol), + txAddress = userWalletManager.getLastTransactionHash(networkId) ?: "", ) } SendTxResult.UserCancelledError -> TxState.UserCancelled diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt index 5da6797569..85f32a42ed 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/TxState.kt @@ -2,7 +2,12 @@ package com.tangem.feature.swap.domain.models.ui sealed class TxState { - data class TxSent(val fromAmount: String? = null, val toAmount: String? = null) : TxState() + data class TxSent( + val fromAmount: String? = null, + val toAmount: String? = null, + val txAddress: String, + ) : TxState() + object UserCancelled : TxState() object BlockchainError : TxState() object TangemSdkError : TxState() diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt index 4cdec15b75..d74ac54e33 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapFragment.kt @@ -31,7 +31,7 @@ class SwapFragment : Fragment() { viewModel.setRouter( SwapRouter( fragmentManager = WeakReference(parentFragmentManager), - customTabsManager = CustomTabsManager(WeakReference(activity?.application)), + customTabsManager = CustomTabsManager(WeakReference(context)), ), ) viewModel.onScreenOpened() diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt index 2ca16d01e8..15e39f08f3 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/router/CustomTabsManager.kt @@ -10,8 +10,7 @@ class CustomTabsManager(private val context: WeakReference) { fun openUrl(url: String) { val customTabsIntent = CustomTabsIntent.Builder() .setDefaultColorSchemeParams( - CustomTabColorSchemeParams.Builder() - .build(), + CustomTabColorSchemeParams.Builder().build(), ) .build() context.get()?.let { customTabsIntent.launchUrl(it, Uri.parse(url)) } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 0d24f31906..d2d3ed232e 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -259,12 +259,16 @@ internal class StateBuilder(val actions: UiActions) { ) } - fun createSuccessState(uiState: SwapStateHolder, txState: TxState.TxSent): SwapStateHolder { + fun createSuccessState( + uiState: SwapStateHolder, + txState: TxState.TxSent, + onSecondaryBtnClick: () -> Unit, + ): SwapStateHolder { return uiState.copy( successState = SwapSuccessStateHolder( fromTokenAmount = txState.fromAmount ?: "", toTokenAmount = txState.toAmount ?: "", - onSecondaryButtonClick = {}, + onSecondaryButtonClick = onSecondaryBtnClick, ), ) } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 1056c842c6..4d19288be4 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -223,7 +223,17 @@ internal class SwapViewModel @Inject constructor( .onSuccess { when (it) { is TxState.TxSent -> { - uiState = stateBuilder.createSuccessState(uiState, it) + uiState = stateBuilder.createSuccessState(uiState, it) { + val txHash = it.txAddress + if (txHash.isNotEmpty()) { + swapRouter.openUrl( + blockchainInteractor.getExplorerTransactionLink( + networkId = dataState.networkId, + txAddress = it.txAddress, + ), + ) + } + } analyticsEventHandler.send(SwapEvents.SwapInProgressScreen) swapRouter.openScreen(SwapScreen.Success) } diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/TransactionManager.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/TransactionManager.kt index 0e28767c68..3c40b3a4c0 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/TransactionManager.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/TransactionManager.kt @@ -53,4 +53,7 @@ interface TransactionManager { */ @Throws(IllegalStateException::class) fun getBlockchainInfo(networkId: String): ProxyNetworkInfo + + @Throws(IllegalStateException::class) + fun getExplorerTransactionLink(networkId: String, txAddress: String): String } \ No newline at end of file diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt index 607dc45eeb..86a6075341 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/UserWalletManager.kt @@ -33,6 +33,7 @@ interface UserWalletManager { * * @param currency to add to wallet */ + @Throws(IllegalStateException::class) fun addToken(currency: Currency) /** @@ -40,6 +41,7 @@ interface UserWalletManager { * * @param networkId for currency */ + @Throws(IllegalStateException::class) fun getWalletAddress(networkId: String): String /** @@ -63,4 +65,7 @@ interface UserWalletManager { * Returns selected app currency */ fun getUserAppCurrency(): ProxyFiatCurrency + + @Throws(IllegalStateException::class) + fun getLastTransactionHash(networkId: String): String? } \ No newline at end of file