From 4a418d0d6aa58d9f5d5b4277e9f6d656ac9cd528 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Aug 2022 23:14:20 +0300 Subject: [PATCH 01/34] Updated on 2026-08-14 --- .../features/wallet/models/PendingTransaction.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt index 698a4c9eb9..f2cd8d24b1 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt @@ -1,6 +1,11 @@ package com.tangem.tap.features.wallet.models -import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.Token +import com.tangem.blockchain.common.TransactionData +import com.tangem.blockchain.common.TransactionStatus +import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.extensions.isAboveZero import com.tangem.tap.common.extensions.toFormattedString import java.math.BigDecimal @@ -10,8 +15,8 @@ data class PendingTransaction( val type: PendingTransactionType, ) { val address: String? = when (type) { - PendingTransactionType.Incoming -> transactionData.sourceAddress - PendingTransactionType.Outgoing -> transactionData.destinationAddress + PendingTransactionType.Incoming -> nullIfUnknown(transactionData.sourceAddress) + PendingTransactionType.Outgoing -> nullIfUnknown(transactionData.destinationAddress) PendingTransactionType.Unknown -> null } @@ -20,6 +25,8 @@ data class PendingTransaction( val amountValueUi: String? = amountValue?.toFormattedString(transactionData.amount.decimals) val currency: String = transactionData.amount.currencySymbol + + fun nullIfUnknown(address: String):String? = if (address == "unknown") null else address } enum class PendingTransactionType { Incoming, Outgoing, Unknown } From 7851f5e885676e32f7bee46b951a1b0b0ef27706 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:26:53 +0300 Subject: [PATCH 02/34] Updated on 2026-08-14 --- .../tap/common/extensions/WalletManager.kt | 3 +- .../tap/common/redux/global/GlobalState.kt | 2 +- .../note/redux/OnboardingNoteState.kt | 2 +- .../products/twins/redux/TwinCardsState.kt | 2 +- .../tap/features/wallet/redux/WalletState.kt | 66 ++++--------------- .../middlewares/TradeCryptoMiddleware.kt | 27 ++++---- .../redux/reducers/OnWalletLoadedReducer.kt | 11 +--- .../wallet/redux/reducers/WalletReducer.kt | 40 +++++------ .../wallet/ui/WalletDetailsFragment.kt | 4 +- .../wallet/ui/wallet/SingleWalletView.kt | 6 +- .../CurrencyExchangeManager.kt | 8 +++ .../exchangeServices/ExchangeService.kt | 19 ++++++ 12 files changed, 81 insertions(+), 109 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt index 58284b0cc0..311932f7c1 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt @@ -51,11 +51,10 @@ suspend fun WalletManager.safeUpdate(): Result = try { fun WalletManager?.getToUpUrl(): String? { val globalState = store.state.globalState - val exchangeManager = globalState.exchangeManager ?: return null val wallet = this?.wallet ?: return null val defaultAddress = wallet.address - return exchangeManager.getUrl( + return globalState.exchangeManager.getUrl( action = CurrencyExchangeManager.Action.Buy, blockchain = wallet.blockchain, cryptoCurrencyName = wallet.blockchain.currency, diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 62e5217866..1fed436b47 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -25,7 +25,7 @@ data class GlobalState( val appCurrency: FiatCurrency = FiatCurrency.Default, val scanCardFailsCounter: Int = 0, val dialog: StateDialog? = null, - val exchangeManager: CurrencyExchangeManager? = null, + val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(), val resources: AndroidResources = AndroidResources(), val analyticsHandlers: AnalyticsHandler? = null, val userCountryCode: String? = null, diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt index a9ebb0e757..ae7a2db594 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteState.kt @@ -26,7 +26,7 @@ data class OnboardingNoteState( get() = steps.indexOf(currentStep) val isBuyAllowed: Boolean by ReadOnlyProperty { _, _ -> - store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false + store.state.globalState.exchangeManager.availableForBuy(walletBalance.currency) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt index 19cc8ad307..0b2e4b4d1a 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsState.kt @@ -56,7 +56,7 @@ data class TwinCardsState( get() = currentStep == TwinCardsStep.CreateSecondWallet || currentStep == TwinCardsStep.CreateThirdWallet val isBuyAllowed: Boolean by ReadOnlyProperty { _, _ -> - store.state.globalState.exchangeManager?.availableForBuy(walletBalance.currency) ?: false + store.state.globalState.exchangeManager.availableForBuy(walletBalance.currency) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index ec3107b151..891b07a3fd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -7,9 +7,6 @@ import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.common.extensions.isZero -import com.tangem.domain.common.extensions.canHandleToken -import com.tangem.domain.common.extensions.toCoinId -import com.tangem.domain.features.addCustomToken.CustomCurrency import com.tangem.tap.common.entities.Button import com.tangem.tap.common.extensions.toQrCode import com.tangem.tap.common.redux.global.CryptoCurrencyName @@ -17,12 +14,18 @@ import com.tangem.tap.common.toggleWidget.WidgetState import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState -import com.tangem.tap.features.wallet.models.* +import com.tangem.tap.features.wallet.models.Currency +import com.tangem.tap.features.wallet.models.PendingTransaction +import com.tangem.tap.features.wallet.models.TotalBalance +import com.tangem.tap.features.wallet.models.WalletRent +import com.tangem.tap.features.wallet.models.WalletWarning +import com.tangem.tap.features.wallet.models.hasPendingTransactions +import com.tangem.tap.features.wallet.models.hasSendableAmounts +import com.tangem.tap.features.wallet.models.isSendableAmount import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount import com.tangem.tap.features.wallet.redux.reducers.findProgressState import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager import com.tangem.tap.store import org.rekotlin.StateType import java.math.BigDecimal @@ -248,32 +251,6 @@ data class WalletState( return updatedWallets + remainingWallets } - fun updateTradeCryptoState( - exchangeManager: CurrencyExchangeManager?, - walletData: WalletData - ): WalletData { - return walletData.copy( - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - walletData - ) - ) - } - - fun updateTradeCryptoState( - exchangeManager: CurrencyExchangeManager?, - walletDataList: List - ): List { - return walletDataList.map { - it.copy( - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - it - ) - ) - } - } - private fun updateTotalBalance(): WalletState { val walletsData = this.wallets .flatMap(WalletStore::walletsData) @@ -352,39 +329,24 @@ data class Artwork( } } -data class TradeCryptoState( - val isAvailableToSell: () -> Boolean = { false }, - val isAvailableToBuy: () -> Boolean = { false }, -) { - companion object { - fun from( - exchangeManager: CurrencyExchangeManager?, - walletData: WalletData - ): TradeCryptoState { - val exchanger = exchangeManager ?: return walletData.tradeCryptoState - val currency = walletData.currency - - return TradeCryptoState( - isAvailableToSell = { exchanger.availableForSell(currency) }, - isAvailableToBuy = { exchanger.availableForBuy(currency) }, - ) - } - } -} - data class WalletData( val pendingTransactions: List = emptyList(), val hashesCountVerified: Boolean? = null, val walletAddresses: WalletAddresses? = null, val currencyData: BalanceWidgetData = BalanceWidgetData(), val updatingWallet: Boolean = false, - val tradeCryptoState: TradeCryptoState = TradeCryptoState(), val fiatRateString: String? = null, val fiatRate: BigDecimal? = null, val mainButton: WalletMainButton = WalletMainButton.SendButton(false), val currency: Currency, val walletRent: WalletRent? = null, ) { + val isAvailableToBuy: Boolean + get() = store.state.globalState.exchangeManager.availableForBuy(currency) + + val isAvailableToSell: Boolean + get() = store.state.globalState.exchangeManager.availableForSell(currency) + fun shouldShowMultipleAddress(): Boolean { val listOfAddresses = walletAddresses?.list ?: return false return listOfAddresses.size > 1 diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 064647d863..319c940a52 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -37,20 +37,18 @@ class TradeCryptoMiddleware { action: WalletAction.TradeCryptoAction.Buy, ) { if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { - store.dispatchOnMain( - WalletAction.DialogAction.RussianCardholdersWarningDialog - ) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog) return } val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val exchangeManager = store.state.globalState.exchangeManager ?: return val card = store.state.globalState.scanResponse?.card ?: return - val appCurrency = store.state.globalState.appCurrency val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return + val exchangeManager = store.state.globalState.exchangeManager + val appCurrency = store.state.globalState.appCurrency val currency = selectedWalletData.currency if (currency is Currency.Token && currency.blockchain.isTestnet()) { @@ -81,15 +79,13 @@ class TradeCryptoMiddleware { private fun proceedSellAction() { val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val exchangeManager = store.state.globalState.exchangeManager ?: return - val appCurrency = store.state.globalState.appCurrency + val appCurrency = store.state.globalState.appCurrency val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return val currency = selectedWalletData.currency - - exchangeManager.getUrl( + store.state.globalState.exchangeManager.getUrl( action = CurrencyExchangeManager.Action.Sell, blockchain = currency.blockchain, cryptoCurrencyName = currency.currencySymbol, @@ -100,8 +96,8 @@ class TradeCryptoMiddleware { private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) { val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return - val walletManager = - store.state.walletState.getWalletManager(selectedWalletData.currency) + + val walletManager = store.state.walletState.getWalletManager(selectedWalletData.currency) store.dispatchOnMain(PrepareSendScreen( coinAmount = walletManager?.wallet?.amounts?.get(AmountType.Coin), coinRate = selectedWalletData.fiatRate, @@ -116,11 +112,10 @@ class TradeCryptoMiddleware { } private fun openReceiptUrl(transactionId: String) { - val exchangeManager = store.state.globalState.exchangeManager ?: return - store.dispatchOnMain(NavigationAction.PopBackTo()) - exchangeManager.getSellCryptoReceiptUrl(CurrencyExchangeManager.Action.Sell, transactionId)?.let { - store.dispatchOnMain(NavigationAction.OpenUrl(it)) - } + store.state.globalState.exchangeManager.getSellCryptoReceiptUrl( + action = CurrencyExchangeManager.Action.Sell, + transactionId = transactionId, + )?.let { store.dispatchOnMain(NavigationAction.OpenUrl(it)) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index 482285de76..63d378718f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -13,7 +13,9 @@ import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData @@ -38,8 +40,6 @@ class OnWalletLoadedReducer { val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState val fiatCurrency = store.state.globalState.appCurrency - val exchangeManager = store.state.globalState.exchangeManager - val coinAmountValue = wallet.amounts[AmountType.Coin]?.value val formattedAmount = coinAmountValue?.toFormattedCurrencyString( wallet.blockchain.decimals(), @@ -71,7 +71,6 @@ class OnWalletLoadedReducer { pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled), currency = Currency.fromBlockchainNetwork(blockchainNetwork), - tradeCryptoState = TradeCryptoState.from(exchangeManager, walletData), ) val tokens = wallet.getTokens().mapNotNull { token -> @@ -104,7 +103,6 @@ class OnWalletLoadedReducer { ), pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled), - tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData), ) } val newWallets = tokens + newWalletData @@ -118,8 +116,6 @@ class OnWalletLoadedReducer { if (wallet.blockchain != walletState.primaryBlockchain) return walletState val fiatCurrencyName = store.state.globalState.appCurrency.code - val exchangeManager = store.state.globalState.exchangeManager - val token = wallet.getFirstToken() val tokenData = if (token != null) { val tokenAmount = wallet.getTokenAmount(token) @@ -167,7 +163,6 @@ class OnWalletLoadedReducer { ), pendingTransactions = pendingTransactions.removeUnknownTransactions(), mainButton = WalletMainButton.SendButton(sendButtonEnabled), - tradeCryptoState = TradeCryptoState.from(exchangeManager, walletState.primaryWallet), ) val wallets = listOfNotNull(walletData) val updatedStore = walletState.getWalletStore(walletData?.currency)?.updateWallets(wallets) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index fba952b703..bf3d1552a9 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -6,7 +6,11 @@ import com.tangem.blockchain.common.Wallet import com.tangem.common.extensions.mapNotNullValues import com.tangem.domain.common.TwinCardNumber import com.tangem.tap.common.entities.FiatCurrency -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.toFiatRateString +import com.tangem.tap.common.extensions.toFiatString +import com.tangem.tap.common.extensions.toFiatValue +import com.tangem.tap.common.extensions.toFormattedCurrencyString +import com.tangem.tap.common.extensions.toFormattedFiatValue import com.tangem.tap.common.redux.AppState import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.getArtworkUrl @@ -14,7 +18,16 @@ import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.WalletRent -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.AddressData +import com.tangem.tap.features.wallet.redux.Artwork +import com.tangem.tap.features.wallet.redux.ErrorType +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletAddresses +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.store @@ -144,10 +157,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState { currencySymbol = walletData.currencyData.currencySymbol, ), mainButton = WalletMainButton.SendButton(false), - tradeCryptoState = TradeCryptoState.from( - exchangeManager, - walletData - ) ) } ) @@ -171,13 +180,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { currencySymbol = wallet.currencyData.currencySymbol, ), mainButton = WalletMainButton.SendButton(false), - tradeCryptoState = TradeCryptoState.from(exchangeManager, wallet) ) } - val wallets = newState.updateTradeCryptoState( - exchangeManager, - newState.replaceSomeWallets(newWallets) - ) + val wallets = newState.replaceSomeWallets(newWallets) val walletStore = newState.getWalletStore(action.blockchain)?.updateWallets(wallets) newState = newState.updateWalletStore(walletStore) } @@ -210,14 +215,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) ) } - var updatedWalletStore = newState.getWalletStore(action.blockchain) + val updatedWalletStore = newState.getWalletStore(action.blockchain) ?.updateWallets(listOfNotNull(walletData)) - updatedWalletStore = - updatedWalletStore?.updateWallets( - newState.updateTradeCryptoState(exchangeManager, updatedWalletStore.walletsData) - ) - newState = newState.updateWalletStore(updatedWalletStore) } @@ -248,11 +248,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { ) ) } - val updatedWallets = - newState.updateTradeCryptoState( - exchangeManager, - walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData - ) + val updatedWallets = walletStore!!.updateWallets(listOfNotNull(newWalletData) + tokenWallets).walletsData newState = newState.updateWalletsData(updatedWallets) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 0f54d5b13a..a84d052625 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -199,8 +199,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } rowButtons.updateButtonsVisibility( - buyAllowed = selectedWallet.tradeCryptoState.isAvailableToBuy(), - sellAllowed = selectedWallet.tradeCryptoState.isAvailableToSell(), + buyAllowed = selectedWallet.isAvailableToBuy, + sellAllowed = selectedWallet.isAvailableToSell, sendAllowed = selectedWallet.mainButton.enabled, ) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index fa046cc3f0..7f473f4b4d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -117,11 +117,9 @@ class SingleWalletView : WalletView() { } private fun setupRowButtons(state: WalletData, rowButtons: WalletDetailsButtonsRow) { - val allowedToBuy = state.tradeCryptoState.isAvailableToBuy() - val allowedToSell = state.tradeCryptoState.isAvailableToSell() rowButtons.updateButtonsVisibility( - buyAllowed = allowedToBuy, - sellAllowed = allowedToSell, + buyAllowed = state.isAvailableToBuy, + sellAllowed = state.isAvailableToSell, sendAllowed = state.mainButton.enabled, ) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 39f201a9b1..85720c4306 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -74,6 +74,14 @@ class CurrencyExchangeManager( } enum class Action { Buy, Sell } + + companion object { + fun dummy(): CurrencyExchangeManager = CurrencyExchangeManager( + buyService = ExchangeService.dummy(), + sellService = ExchangeService.dummy(), + primaryRules = ExchangeRules.dummy(), + ) + } } suspend fun CurrencyExchangeManager.buyErc20TestnetTokens( diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index 34f37dddf9..f7db8b210f 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -5,6 +5,16 @@ import com.tangem.tap.features.wallet.models.Currency interface ExchangeService: ExchangeRules { suspend fun update() + + companion object { + fun dummy(): ExchangeService = object : ExchangeService { + override suspend fun update() {} + override fun isBuyAllowed(): Boolean = false + override fun isSellAllowed(): Boolean = false + override fun availableForBuy(currency: Currency): Boolean = false + override fun availableForSell(currency: Currency): Boolean = false + } + } } interface ExchangeRules { @@ -12,6 +22,15 @@ interface ExchangeRules { fun isSellAllowed(): Boolean fun availableForBuy(currency: Currency):Boolean fun availableForSell(currency: Currency):Boolean + + companion object { + fun dummy(): ExchangeRules = object : ExchangeRules { + override fun isBuyAllowed(): Boolean = false + override fun isSellAllowed(): Boolean = false + override fun availableForBuy(currency: Currency): Boolean = false + override fun availableForSell(currency: Currency): Boolean = false + } + } } interface ExchangeUrlBuilder { From cf692a7cd64faff7cdbb22c54e5388d6b07c7f12 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:32:29 +0300 Subject: [PATCH 03/34] Updated on 2026-08-14 --- .../tangem/tap/network/exchangeServices/CardExchangeRules.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt index d6c0cfe6c5..ecf9d850b3 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt @@ -16,7 +16,7 @@ class CardExchangeRules( val card = cardProvider() ?: return false return when { - card.isDemoCard() -> false + card.isDemoCard() -> true card.isStart2Coin -> false else -> true } @@ -36,7 +36,7 @@ class CardExchangeRules( val card = cardProvider() ?: return false return when { - card.isDemoCard() -> false + card.isDemoCard() -> true card.isStart2Coin -> false else -> true } From 3caf4762ab1ce46466f0cc2711d6df90fc8518db Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 00:54:17 +0300 Subject: [PATCH 04/34] Updated on 2026-08-14 --- .../tap/network/exchangeServices/mercuryo/MercuryoApi.kt | 9 --------- .../network/exchangeServices/mercuryo/MercuryoService.kt | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt index 45494e0114..87565c3640 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoApi.kt @@ -4,15 +4,6 @@ import com.squareup.moshi.Json import retrofit2.http.GET import retrofit2.http.Path -/** -[REDACTED_AUTHOR] - */ - - - -private val CurrenciesUrl = "https://api.mercuryo.io/v1.6/lib/currencies" - - interface MercuryoApi { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 97190aa9fd..112e3660c8 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -130,6 +130,7 @@ class MercuryoService( private fun blockchainFromCurrencyName(currencyName: String): Blockchain? = when (currencyName) { "BNB" -> Blockchain.BSC "ETH" -> Blockchain.Ethereum + "ADA" -> Blockchain.CardanoShelley else -> Blockchain.values().find { it.currency.lowercase() == currencyName.lowercase() } } } From 6bcd70c9782b9641635fbf2302860de9ecb0215d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 01:38:31 +0300 Subject: [PATCH 05/34] Updated on 2026-08-14 --- .../com/tangem/tap/common/feature/Feature.kt | 8 +++++ .../tap/features/wallet/redux/WalletState.kt | 20 ++++++------ .../wallet/redux/reducers/WalletReducer.kt | 2 -- .../wallet/ui/WalletDetailsFragment.kt | 5 +-- .../wallet/ui/view/WalletDetailsButtonsRow.kt | 15 ++++++--- .../wallet/ui/wallet/SingleWalletView.kt | 32 ++++++++++++------- .../exchangeServices/CardExchangeRules.kt | 6 ++++ .../CurrencyExchangeManager.kt | 2 ++ .../exchangeServices/ExchangeService.kt | 18 +++++++---- .../mercuryo/MercuryoService.kt | 2 ++ .../moonpay/MoonPayService.kt | 2 ++ 11 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/feature/Feature.kt diff --git a/app/src/main/java/com/tangem/tap/common/feature/Feature.kt b/app/src/main/java/com/tangem/tap/common/feature/Feature.kt new file mode 100644 index 0000000000..ce1313c772 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/feature/Feature.kt @@ -0,0 +1,8 @@ +package com.tangem.tap.common.feature + +/** +[REDACTED_AUTHOR] + */ +interface Feature { + fun featureIsSwitchedOn():Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 891b07a3fd..48c886d939 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -51,21 +51,15 @@ data class WalletState( // if you do not delegate - the application crashes on startup, // because twinCardsState has not been created yet - val twinCardsState: TwinCardsState by ReadOnlyProperty { thisRef, property -> + val twinCardsState: TwinCardsState by ReadOnlyProperty { _, _ -> store.state.twinCardsState } val isTangemTwins: Boolean get() = store.state.globalState.scanResponse?.isTangemTwins() == true - val primaryWallet: WalletData? = wallets.firstOrNull() - ?.walletsData?.firstOrNull() - val primaryWalletManager: WalletManager? = - if (wallets.isNotEmpty()) wallets[0].walletManager else null - - val shouldShowDetails: Boolean = - primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && - primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain + val isExchangeServiceFeatureOn: Boolean + get() = store.state.globalState.exchangeManager.featureIsSwitchedOn() val blockchains: List get() = wallets.mapNotNull { it.walletManager?.wallet?.blockchain } @@ -79,6 +73,14 @@ data class WalletState( val walletManagers: List get() = wallets.mapNotNull { it.walletManager } + val primaryWallet: WalletData? = wallets.firstOrNull()?.walletsData?.firstOrNull() + + val primaryWalletManager: WalletManager? = if (wallets.isNotEmpty()) wallets[0].walletManager else null + + val shouldShowDetails: Boolean = + primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && + primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain + fun getWalletManager(currency: Currency?): WalletManager? { if (currency?.blockchain == null) return null return getWalletStore(currency)?.walletManager diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index bf3d1552a9..a4b679512e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -30,7 +30,6 @@ import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData -import com.tangem.tap.store import org.rekotlin.Action import java.math.BigDecimal @@ -48,7 +47,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState { if (action !is WalletAction) return state.walletState - val exchangeManager = store.state.globalState.exchangeManager var newState = state.walletState when (action) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index a84d052625..ab07dd33d5 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -140,7 +140,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), setupAddressCard(selectedWallet) setupNoInternetHandling(state) setupBalanceData(selectedWallet.currencyData) - setupButtons(selectedWallet) + setupButtons(selectedWallet, state.isExchangeServiceFeatureOn) handleCurrencyIcon(selectedWallet) handleWarnings(selectedWallet) @@ -186,7 +186,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), ) } - private fun setupButtons(selectedWallet: WalletData) = with(binding) { + private fun setupButtons(selectedWallet: WalletData, isExchangeServiceFeatureOn: Boolean) = with(binding) { lWalletDetails.btnCopy.setOnClickListener { selectedWallet.walletAddresses?.selectedAddress?.address?.let { addressString -> store.dispatch(WalletAction.CopyAddress(addressString, requireContext())) @@ -199,6 +199,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } rowButtons.updateButtonsVisibility( + exchangeServiceFeatureOn = isExchangeServiceFeatureOn, buyAllowed = selectedWallet.isAvailableToBuy, sellAllowed = selectedWallet.isAvailableToSell, sendAllowed = selectedWallet.mainButton.enabled, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index 1b7eff8f23..af6ec9280b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -35,14 +35,21 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( } fun updateButtonsVisibility( + exchangeServiceFeatureOn: Boolean, buyAllowed: Boolean, sellAllowed: Boolean, sendAllowed: Boolean, ) = with(binding) { - btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) - btnBuy.isEnabled = buyAllowed - btnSell.isVisible = !buyAllowed && sellAllowed - btnTrade.isVisible = buyAllowed && sellAllowed + if (exchangeServiceFeatureOn) { + btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) + btnBuy.isEnabled = buyAllowed + btnSell.isVisible = !buyAllowed && sellAllowed + btnTrade.isVisible = buyAllowed && sellAllowed + } else { + btnBuy.isVisible = false + btnSell.isVisible = false + btnTrade.isVisible = false + } btnSend.isEnabled = sendAllowed } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt index 7f473f4b4d..ab271db8fb 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt @@ -58,7 +58,7 @@ class SingleWalletView : WalletView() { state.primaryWallet ?: return setupTwinCards(state.twinCardsState, binding) - setupButtons(state.primaryWallet, binding) + setupButtons(state.primaryWallet, binding, state.isExchangeServiceFeatureOn) setupAddressCard(state.primaryWallet, binding) showPendingTransactionsIfPresent(state.primaryWallet.pendingTransactions) setupBalance(state, state.primaryWallet) @@ -97,18 +97,23 @@ class SingleWalletView : WalletView() { } } - private fun setupButtons(state: WalletData, binding: FragmentWalletBinding) = with(binding) { - setupRowButtons(state, rowButtons) + private fun setupButtons( + walletData: WalletData, + binding: FragmentWalletBinding, + isExchangeServiceFeatureEnabled: Boolean, + ) = with(binding) { + setupRowButtons(walletData, rowButtons, isExchangeServiceFeatureEnabled) + lAddress.btnCopy.setOnClickListener { - state.walletAddresses?.selectedAddress?.address?.let { addressString -> + walletData.walletAddresses?.selectedAddress?.address?.let { addressString -> store.dispatch(WalletAction.CopyAddress(addressString, fragment!!.requireContext())) } } lAddress.btnShowQr.setOnClickListener { - state.walletAddresses?.selectedAddress?.let { selectedAddress -> + walletData.walletAddresses?.selectedAddress?.let { selectedAddress -> store.dispatch( WalletAction.DialogAction.QrCode( - currency = state.currency, + currency = walletData.currency, selectedAddress = selectedAddress, ), ) @@ -116,11 +121,16 @@ class SingleWalletView : WalletView() { } } - private fun setupRowButtons(state: WalletData, rowButtons: WalletDetailsButtonsRow) { + private fun setupRowButtons( + walletData: WalletData, + rowButtons: WalletDetailsButtonsRow, + isExchangeServiceFeatureEnabled: Boolean, + ) { rowButtons.updateButtonsVisibility( - buyAllowed = state.isAvailableToBuy, - sellAllowed = state.isAvailableToSell, - sendAllowed = state.mainButton.enabled, + exchangeServiceFeatureOn = isExchangeServiceFeatureEnabled, + buyAllowed = walletData.isAvailableToBuy, + sellAllowed = walletData.isAvailableToSell, + sendAllowed = walletData.mainButton.enabled, ) rowButtons.onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) } @@ -128,7 +138,7 @@ class SingleWalletView : WalletView() { rowButtons.onTradeClick = { store.dispatch(WalletAction.DialogAction.ChooseTradeActionDialog) } rowButtons.onSendClick = { - when (state.mainButton) { + when (walletData.mainButton) { is WalletMainButton.SendButton -> store.dispatch(WalletAction.Send()) is WalletMainButton.CreateWalletButton -> store.dispatch(WalletAction.CreateWallet) } diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt index ecf9d850b3..a7f7b9aec2 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CardExchangeRules.kt @@ -12,6 +12,12 @@ class CardExchangeRules( val cardProvider: () -> Card?, ) : ExchangeRules { + override fun featureIsSwitchedOn(): Boolean { + val card = cardProvider() ?: return false + + return !card.isStart2Coin + } + override fun isBuyAllowed(): Boolean { val card = cardProvider() ?: return false diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index 85720c4306..04c92fc542 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -26,6 +26,8 @@ class CurrencyExchangeManager( private val primaryRules: ExchangeRules, ) : ExchangeService, ExchangeUrlBuilder { + override fun featureIsSwitchedOn(): Boolean = primaryRules.featureIsSwitchedOn() + override suspend fun update() { buyService.update() sellService.update() diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt index f7db8b210f..8d6e8e2187 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/ExchangeService.kt @@ -1,13 +1,22 @@ package com.tangem.tap.network.exchangeServices import com.tangem.blockchain.common.Blockchain +import com.tangem.tap.common.feature.Feature import com.tangem.tap.features.wallet.models.Currency -interface ExchangeService: ExchangeRules { +interface Exchanger { + fun isBuyAllowed(): Boolean + fun isSellAllowed(): Boolean + fun availableForBuy(currency: Currency):Boolean + fun availableForSell(currency: Currency):Boolean +} + +interface ExchangeService: Feature, Exchanger { suspend fun update() companion object { fun dummy(): ExchangeService = object : ExchangeService { + override fun featureIsSwitchedOn(): Boolean = false override suspend fun update() {} override fun isBuyAllowed(): Boolean = false override fun isSellAllowed(): Boolean = false @@ -17,14 +26,11 @@ interface ExchangeService: ExchangeRules { } } -interface ExchangeRules { - fun isBuyAllowed(): Boolean - fun isSellAllowed(): Boolean - fun availableForBuy(currency: Currency):Boolean - fun availableForSell(currency: Currency):Boolean +interface ExchangeRules: Feature, Exchanger { companion object { fun dummy(): ExchangeRules = object : ExchangeRules { + override fun featureIsSwitchedOn(): Boolean = false override fun isBuyAllowed(): Boolean = false override fun isSellAllowed(): Boolean = false override fun availableForBuy(currency: Currency): Boolean = false diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt index 97190aa9fd..4d00d9a42c 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/mercuryo/MercuryoService.kt @@ -28,6 +28,8 @@ class MercuryoService( private val blockchainsAvailableToBuy = mutableListOf() private val tokensAvailableToBy = mutableMapOf>() + override fun featureIsSwitchedOn(): Boolean = true + override suspend fun update() { when (val result = performRequest { api.currencies(apiVersion) }) { is Result.Success -> { diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt index fa96286e84..00db516c5b 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/moonpay/MoonPayService.kt @@ -29,6 +29,8 @@ class MoonPayService( private var status: MoonPayStatus? = null + override fun featureIsSwitchedOn(): Boolean = true + override suspend fun update() { withIOContext { performRequest { From 21aef70b4f5fa3db2de67d3a04c067a7f40a3183 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 02:01:55 +0300 Subject: [PATCH 06/34] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_wallet.xml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index fa0eaf1398..f53b6f7f6d 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -47,7 +47,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" - android:paddingBottom="32dp"> + android:paddingBottom="92dp"> - - + + + From e7cf31c1a20b0ea3d23d4e5789e07fb847085cd6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 02:03:58 +0300 Subject: [PATCH 07/34] Updated on 2026-08-14 --- app/src/main/res/layout/fragment_wallet.xml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index f53b6f7f6d..d5daad21ea 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -93,6 +93,17 @@ app:barrierDirection="bottom" app:constraint_referenced_ids="iv_card,tv_twin_card_number" /> + + - - Date: Fri, 19 Aug 2022 15:12:01 +0300 Subject: [PATCH 08/34] Updated on 2026-08-14 --- .../wallet/ui/view/WalletDetailsButtonsRow.kt | 18 ++++++------------ .../layout/view_wallet_details_buttons_row.xml | 6 +++--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt index af6ec9280b..582b5f178c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/view/WalletDetailsButtonsRow.kt @@ -12,12 +12,10 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { - private val binding = ViewWalletDetailsButtonsRowBinding.inflate( LayoutInflater.from(context), this, ) - var onBuyClick: (() -> Unit)? = null var onSellClick: (() -> Unit)? = null var onTradeClick: (() -> Unit)? = null @@ -40,16 +38,12 @@ internal class WalletDetailsButtonsRow @JvmOverloads constructor( sellAllowed: Boolean, sendAllowed: Boolean, ) = with(binding) { - if (exchangeServiceFeatureOn) { - btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) - btnBuy.isEnabled = buyAllowed - btnSell.isVisible = !buyAllowed && sellAllowed - btnTrade.isVisible = buyAllowed && sellAllowed - } else { - btnBuy.isVisible = false - btnSell.isVisible = false - btnTrade.isVisible = false - } + containerExchangeButtons.isVisible = exchangeServiceFeatureOn + + btnBuy.isVisible = (buyAllowed && !sellAllowed) || (!buyAllowed && !sellAllowed) + btnBuy.isEnabled = buyAllowed + btnSell.isVisible = !buyAllowed && sellAllowed + btnTrade.isVisible = buyAllowed && sellAllowed btnSend.isEnabled = sendAllowed } } \ No newline at end of file diff --git a/app/src/main/res/layout/view_wallet_details_buttons_row.xml b/app/src/main/res/layout/view_wallet_details_buttons_row.xml index 39017f271f..3f62e6c9fb 100644 --- a/app/src/main/res/layout/view_wallet_details_buttons_row.xml +++ b/app/src/main/res/layout/view_wallet_details_buttons_row.xml @@ -8,6 +8,7 @@ tools:parentTag="android.widget.LinearLayout"> + /> @@ -48,7 +49,6 @@ android:id="@+id/btn_send" style="@style/TapButtonWithIcon" android:layout_width="0dp" - android:layout_marginStart="6dp" android:layout_weight="1" android:text="@string/wallet_button_send" app:icon="@drawable/ic_send" /> From de95196ad0b8308faaa6143cd245411e8eba0d37 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 19:27:38 +0300 Subject: [PATCH 09/34] Updated on 2026-08-14 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index d0b96119fd..e1c383532f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-104', + tangem_blockchain_sdk: 'develop-105', // tangem_blockchain_sdk: '0.0.1', ] From 3b4f61f6a92855dc6aa23a4bc0a93dbc6b69a4a0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Aug 2022 19:29:46 +0300 Subject: [PATCH 10/34] Updated on 2026-08-14 --- app/src/main/res/layout/view_wallet_details_buttons_row.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/view_wallet_details_buttons_row.xml b/app/src/main/res/layout/view_wallet_details_buttons_row.xml index 3f62e6c9fb..0a6a51bfdd 100644 --- a/app/src/main/res/layout/view_wallet_details_buttons_row.xml +++ b/app/src/main/res/layout/view_wallet_details_buttons_row.xml @@ -22,7 +22,7 @@ android:text="@string/wallet_button_trade" android:visibility="gone" app:icon="@drawable/ic_arrows_up_down" - /> + tools:visibility="visible" /> From b168d40f52156f2172413bf5aeab088ec5522037 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Aug 2022 16:45:21 +0300 Subject: [PATCH 11/34] Updated on 2026-08-14 --- .../send/redux/reducers/FeeReducer.kt | 59 ++++++++----------- .../send/redux/reducers/ReceiptReducer.kt | 22 +++++-- .../features/send/redux/states/FeeState.kt | 24 ++++---- .../tap/features/wallet/redux/WalletState.kt | 1 + dependencies.gradle | 2 +- 5 files changed, 52 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt index fd653557c7..4c2fae60ba 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt @@ -1,13 +1,9 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain -import com.tangem.tap.common.extensions.fullNameWithoutTestnet import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.features.send.redux.FeeActionUi import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.states.FeePrecision import com.tangem.tap.features.send.redux.states.FeeState import com.tangem.tap.features.send.redux.states.FeeType import com.tangem.tap.features.send.redux.states.SendState @@ -28,10 +24,9 @@ class FeeReducer : SendInternalReducer { is FeeActionUi.ChangeSelectedFee -> { val currentFee = createValueOfFeeAmount(action.feeType, state.feeList) state.copy( - selectedFeeType = action.feeType, - currentFee = currentFee + selectedFeeType = action.feeType, + currentFee = currentFee, ) - } is FeeActionUi.ChangeIncludeFee -> state.copy(feeIsIncluded = action.isIncluded) } @@ -46,9 +41,9 @@ class FeeReducer : SendInternalReducer { is FeeAction.ChangeLayoutVisibility -> { fun getVisibility(current: Boolean, proposed: Boolean?): Boolean = proposed ?: current state.copy( - mainLayoutIsVisible = getVisibility(state.mainLayoutIsVisible, action.main), - controlsLayoutIsVisible = getVisibility(state.controlsLayoutIsVisible, action.controls), - feeChipGroupIsVisible = getVisibility(state.feeChipGroupIsVisible, action.chipGroup) + mainLayoutIsVisible = getVisibility(state.mainLayoutIsVisible, action.main), + controlsLayoutIsVisible = getVisibility(state.controlsLayoutIsVisible, action.controls), + feeChipGroupIsVisible = getVisibility(state.feeChipGroupIsVisible, action.chipGroup), ) } is FeeAction.FeeCalculation.SetFeeResult -> { @@ -58,30 +53,30 @@ class FeeReducer : SendInternalReducer { val currentFee = createValueOfFeeAmount(feeType, fees) state.copy( - selectedFeeType = feeType, - feeList = fees, - currentFee = currentFee, - error = null, - feePrecision = getFeePrecision(sendState) + selectedFeeType = feeType, + feeList = fees, + currentFee = currentFee, + error = null, + feeIsApproximate = isFeeApproximate(sendState), ) } else { val feeType = getCurrentFeeType(state) val currentFee = createValueOfFeeAmount(feeType, fees) state.copy( - selectedFeeType = feeType, - feeList = fees, - currentFee = currentFee, - error = null, - feePrecision = getFeePrecision(sendState) + selectedFeeType = feeType, + feeList = fees, + currentFee = currentFee, + error = null, + feeIsApproximate = isFeeApproximate(sendState), ) } } is FeeAction.FeeCalculation.SetFeeError -> { state.copy( - feeList = null, - currentFee = null, - error = action.error + feeList = null, + currentFee = null, + error = action.error, ) } } @@ -104,20 +99,12 @@ class FeeReducer : SendInternalReducer { } } - private fun getFeePrecision(sendState: SendState): FeePrecision { - val blockchain = sendState.walletManager?.wallet?.blockchain - return if ( - (blockchain?.fullNameWithoutTestnet == Blockchain.Arbitrum.fullName || - blockchain?.fullNameWithoutTestnet == Blockchain.Tron.fullName || - blockchain?.fullNameWithoutTestnet == Blockchain.Gnosis.fullName) && - sendState.amountState.typeOfAmount is AmountType.Token - ) { - FeePrecision.CAN_BE_LOWER - } else { - FeePrecision.PRECISE - } - } + private fun isFeeApproximate(sendState: SendState): Boolean { + val blockchain = sendState.walletManager?.wallet?.blockchain ?: return false + val amountType = sendState.amountState.typeOfAmount + return blockchain.isFeeApproximate(amountType) + } private fun getCurrentFeeType(state: FeeState): FeeType { return if (state.selectedFeeType == FeeType.SINGLE) FeeType.NORMAL else state.selectedFeeType diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt index c15813fdaa..64d5cc23d3 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/ReceiptReducer.kt @@ -6,7 +6,18 @@ import com.tangem.tap.common.extensions.scaleToFiat import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.states.* +import com.tangem.tap.features.send.redux.states.AmountState +import com.tangem.tap.features.send.redux.states.FeeState +import com.tangem.tap.features.send.redux.states.MainCurrencyType +import com.tangem.tap.features.send.redux.states.ReceiptCrypto +import com.tangem.tap.features.send.redux.states.ReceiptFiat +import com.tangem.tap.features.send.redux.states.ReceiptLayoutType +import com.tangem.tap.features.send.redux.states.ReceiptState +import com.tangem.tap.features.send.redux.states.ReceiptSymbols +import com.tangem.tap.features.send.redux.states.ReceiptTokenCrypto +import com.tangem.tap.features.send.redux.states.ReceiptTokenFiat +import com.tangem.tap.features.send.redux.states.SendState +import com.tangem.tap.features.wallet.redux.WalletState.Companion.CAN_BE_LOWER_SIGN import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.store import java.math.BigDecimal @@ -125,8 +136,7 @@ class ReceiptReducer : SendInternalReducer { val totalFiat = amountFiat.plus(feeFiat) ReceiptTokenFiat( amountFiat = amountFiat.scaleToFiat(true).stripZeroPlainString(), - feeFiat = feeFiat.scaleToFiat(true) - .stripZeroPlainString().addPrecisionSign(), + feeFiat = feeFiat.scaleToFiat(true).stripZeroPlainString().addPrecisionSign(), totalFiat = totalFiat.scaleToFiat(true).stripZeroPlainString(), willSentToken = tokensToSend.stripZeroPlainString(), willSentFeeCoin = feeCoin.stripZeroPlainString(), @@ -207,6 +217,8 @@ class ReceiptReducer : SendInternalReducer { } } - private fun String.addPrecisionSign(): String = - ("${feeState.feePrecision.symbol} $this").trim() + private fun String.addPrecisionSign(): String { + val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else "" + return result.trim() + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt index 87b29f304b..4c9818a669 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/FeeState.kt @@ -11,21 +11,17 @@ enum class FeeType { SINGLE, LOW, NORMAL, PRIORITY } -enum class FeePrecision(val symbol: String) { - PRECISE(""), CAN_BE_LOWER("<") -} - data class FeeState( - val selectedFeeType: FeeType = FeeType.NORMAL, - val feeList: List? = null, - val currentFee: Amount? = null, - val feeIsIncluded: Boolean = false, - val mainLayoutIsVisible: Boolean = false, - val controlsLayoutIsVisible: Boolean = false, - val feeChipGroupIsVisible: Boolean = true, - val includeFeeSwitcherIsEnabled: Boolean = true, - val error: FeeAction.Error? = null, - val feePrecision: FeePrecision = FeePrecision.PRECISE + val selectedFeeType: FeeType = FeeType.NORMAL, + val feeList: List? = null, + val currentFee: Amount? = null, + val feeIsIncluded: Boolean = false, + val feeIsApproximate: Boolean = false, + val mainLayoutIsVisible: Boolean = false, + val controlsLayoutIsVisible: Boolean = false, + val feeChipGroupIsVisible: Boolean = true, + val includeFeeSwitcherIsEnabled: Boolean = true, + val error: FeeAction.Error? = null, ) : SendScreenState { override val stateId: StateId = StateId.FEE diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 48c886d939..594676e0ec 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -287,6 +287,7 @@ data class WalletState( companion object { const val UNKNOWN_AMOUNT_SIGN = "—" const val ROUGH_SIGN = "≈" + const val CAN_BE_LOWER_SIGN = "<" } } diff --git a/dependencies.gradle b/dependencies.gradle index e1c383532f..8d2e4ea106 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-105', + tangem_blockchain_sdk: 'develop-106', // tangem_blockchain_sdk: '0.0.1', ] From ac3688c1fa3cca7c7dcf1ba9f8b71193a0efe9cd Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 23 Aug 2022 18:39:11 +0300 Subject: [PATCH 12/34] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 4e1c24d3c9..642624ce5b 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -5,7 +5,6 @@ import android.content.pm.ActivityInfo import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat import by.kirich1409.viewbindingdelegate.viewBinding import com.google.android.material.snackbar.Snackbar @@ -85,7 +84,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { } private fun systemActions() { - WindowCompat.setDecorFitsSystemWindows(window, false) + // makes the status bar text dark + window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR val windowInsetsController = WindowInsetsControllerCompat(window, binding.root) windowInsetsController.isAppearanceLightStatusBars = true From 50c0e0d38e66be1261e8d2cab32060354c18f056 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 24 Aug 2022 20:55:01 +0300 Subject: [PATCH 13/34] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 642624ce5b..840cee766b 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -85,7 +85,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { private fun systemActions() { // makes the status bar text dark - window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN val windowInsetsController = WindowInsetsControllerCompat(window, binding.root) windowInsetsController.isAppearanceLightStatusBars = true From 955719a33b6abd474d047a2cc8c94f6b4b52419a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 25 Aug 2022 10:02:08 +0400 Subject: [PATCH 14/34] Updated on 2026-08-14 --- .../ui/cardsettings/CardSettingsScreen.kt | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt index 92eec4c59b..2de4f118fb 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt @@ -2,7 +2,6 @@ package com.tangem.tap.features.details.ui.cardsettings import androidx.compose.foundation.Image import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -10,6 +9,10 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -51,14 +54,12 @@ fun CardSettingsReadCard( Column( modifier = modifier .fillMaxSize(), - verticalArrangement = Arrangement.SpaceBetween, ) { - Box( modifier = modifier - .fillMaxWidth(), - - ) { + .fillMaxWidth() + .padding(bottom = 40.dp), + ) { Image( modifier = modifier .fillMaxWidth() @@ -77,16 +78,13 @@ fun CardSettingsReadCard( contentDescription = "", contentScale = ContentScale.FillWidth, ) - } - - + Spacer(modifier = Modifier.weight(1f)) Column( modifier = modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 32.dp), ) { - Text( text = stringResource(id = R.string.scan_card_settings_title), color = colorResource(id = R.color.text_primary_1), @@ -97,6 +95,9 @@ fun CardSettingsReadCard( text = stringResource(id = R.string.scan_card_settings_message), color = colorResource(id = R.color.text_secondary), style = TangemTypography.body1, + modifier = modifier + .verticalScroll(rememberScrollState()) + .weight(weight = 1f, fill = false), ) Spacer(modifier = modifier.size(29.dp)) DetailsMainButton( @@ -113,11 +114,13 @@ fun CardSettings( state: CardSettingsScreenState, modifier: Modifier = Modifier, ) { - Column( + if (state.cardDetails == null) return + + LazyColumn( modifier = modifier .fillMaxWidth(), ) { - state.cardDetails?.map { + items(state.cardDetails) { val paddingBottom = when (it) { is CardInfo.CardId, is CardInfo.Issuer -> 12.dp is CardInfo.SignedHashes -> 14.dp @@ -156,9 +159,7 @@ fun CardSettings( style = TangemTypography.body2, ) } - } - } } From 806bf97028552305cd0cb070b88f60685da328a6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 25 Aug 2022 15:31:05 +0400 Subject: [PATCH 15/34] Updated on 2026-08-14 --- .../details/ui/resetcard/ResetCardScreen.kt | 149 ++++++++++-------- .../ui/securitymode/SecurityModeScreen.kt | 13 +- 2 files changed, 95 insertions(+), 67 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index 2c07b092ad..58d20cf256 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -5,20 +5,24 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Icon import androidx.compose.material.IconToggleButton import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.layout import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -58,80 +62,99 @@ fun ResetCardView( Column( modifier = modifier .fillMaxSize(), - verticalArrangement = Arrangement.Bottom, + verticalArrangement = Arrangement.SpaceBetween, ) { Box( - modifier = modifier, + modifier = modifier + .padding(bottom = 20.dp), ) { ScreenTitle(titleRes = R.string.reset_card_to_factory_navigation_title) } - Spacer( + + Column( modifier = modifier - .defaultMinSize(20.dp) - .weight(1f), - ) - Text( - text = stringResource(id = R.string.common_attention), - modifier = modifier.padding(start = 20.dp, end = 20.dp), - style = TangemTypography.headline3, - color = colorResource(id = R.color.text_primary_1), - ) - - Spacer(modifier = modifier.size(24.dp)) - - Text( - text = stringResource(id = R.string.reset_card_to_factory_message), - modifier = modifier.padding(start = 20.dp, end = 20.dp), - style = TangemTypography.body1, - color = colorResource(id = R.color.text_secondary), - ) - - Spacer(modifier = modifier.size(44.dp)) - Row( - modifier = modifier - .fillMaxWidth() - .padding(end = 20.dp), + .layout { measurable, constraints -> + val placeable = + measurable.measure( + constraints.copy( + // left 200.dp for min image height + maxHeight = constraints.maxHeight - 215.dp.roundToPx(), + // occupy all height except full image square in case of smaller text + minHeight = constraints.maxHeight - constraints.maxWidth, + ), + ) + layout(placeable.width, placeable.height) { + placeable.place(0, 0) + } + } + .height(IntrinsicSize.Min), + verticalArrangement = Arrangement.Bottom, ) { - IconToggleButton( - checked = state.accepted, - onCheckedChange = state.onAcceptWarningToggleClick, - modifier = modifier.padding(start = 20.dp, end = 20.dp), - ) { - Icon( - painter = painterResource( - if (state.accepted) { - R.drawable.ic_accepted - } else { - R.drawable.ic_unticked - }, - ), - contentDescription = null, - tint = if (state.accepted) { - colorResource(id = R.color.icon_accent) - } else { - colorResource(id = R.color.icon_secondary) - }, - ) - } Text( - text = stringResource(id = R.string.reset_card_to_factory_warning_message), - style = TangemTypography.body2, + text = stringResource(id = R.string.common_attention), + modifier = modifier.padding(start = 20.dp, end = 20.dp), + style = TangemTypography.headline3, + color = colorResource(id = R.color.text_primary_1), + ) + + Spacer(modifier = modifier.size(24.dp)) + + Text( + text = stringResource(id = R.string.reset_card_to_factory_message), + modifier = modifier + .padding(start = 20.dp, end = 20.dp) + .weight(1f, false) + .verticalScroll(rememberScrollState()), + style = TangemTypography.body1, color = colorResource(id = R.color.text_secondary), ) - } - Spacer(modifier = modifier.size(32.dp)) - Box( - modifier = modifier - .padding(start = 16.dp, end = 16.dp, bottom = 32.dp), - ) { - DetailsMainButton( - title = stringResource(id = R.string.reset_card_to_factory_button_title), - onClick = state.onResetButtonClick, - enabled = state.resetButtonEnabled, - ) - } + Spacer(modifier = modifier.size(44.dp)) + Row( + modifier = modifier + .fillMaxWidth() + .padding(end = 20.dp), + ) { + IconToggleButton( + checked = state.accepted, + onCheckedChange = state.onAcceptWarningToggleClick, + modifier = modifier.padding(start = 20.dp, end = 20.dp), + ) { + Icon( + painter = painterResource( + if (state.accepted) { + R.drawable.ic_accepted + } else { + R.drawable.ic_unticked + }, + ), + contentDescription = null, + tint = if (state.accepted) { + colorResource(id = R.color.icon_accent) + } else { + colorResource(id = R.color.icon_secondary) + }, + ) + } + Text( + text = stringResource(id = R.string.reset_card_to_factory_warning_message), + style = TangemTypography.body2, + color = colorResource(id = R.color.text_secondary), + ) + } + Spacer(modifier = modifier.size(32.dp)) + Box( + modifier = modifier + .padding(start = 16.dp, end = 16.dp, bottom = 32.dp), + ) { + DetailsMainButton( + title = stringResource(id = R.string.reset_card_to_factory_button_title), + onClick = state.onResetButtonClick, + enabled = state.resetButtonEnabled, + ) + } + } } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt index e18146767f..66f6adcab7 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt @@ -6,10 +6,11 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.verticalScroll import androidx.compose.material.RadioButton import androidx.compose.material.RadioButtonDefaults import androidx.compose.material.Text @@ -22,6 +23,7 @@ import androidx.compose.ui.unit.dp import com.tangem.tap.common.compose.TangemTypography import com.tangem.tap.features.details.redux.SecurityOption import com.tangem.tap.features.details.ui.common.DetailsMainButton +import com.tangem.tap.features.details.ui.common.ScreenTitle import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R @@ -33,7 +35,7 @@ fun SecurityModeScreen( ) { SettingsScreensScaffold( content = { SecurityModeOptions(state = state, modifier = modifier) }, - titleRes = R.string.card_settings_security_mode, + // titleRes = R.string.card_settings_security_mode, onBackClick = onBackPressed, ) } @@ -47,10 +49,13 @@ fun SecurityModeOptions( Column( modifier = modifier .fillMaxSize() - .padding(bottom = 28.dp) - .offset(y = (-16).dp), + .verticalScroll(rememberScrollState()) + .padding(bottom = 28.dp), verticalArrangement = Arrangement.SpaceBetween, ) { + ScreenTitle(titleRes = R.string.card_settings_security_mode, modifier.padding(bottom = 36.dp)) + + state.availableOptions.map { SecurityOption(option = it, state = state, modifier = modifier) } From 8274288166e632db76f7808b3b5e9ec184c67926 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 25 Aug 2022 18:28:31 +0300 Subject: [PATCH 16/34] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/MainActivity.kt | 6 ++++-- .../tap/features/details/ui/walletconnect/QrScanFragment.kt | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 840cee766b..a005e3f952 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -4,7 +4,9 @@ import android.content.Intent import android.content.pm.ActivityInfo import android.os.Bundle import android.view.View +import android.view.Window import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat import by.kirich1409.viewbindingdelegate.viewBinding import com.google.android.material.snackbar.Snackbar @@ -84,8 +86,8 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { } private fun systemActions() { - // makes the status bar text dark - window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN + + WindowCompat.setDecorFitsSystemWindows(window, false) val windowInsetsController = WindowInsetsControllerCompat(window, binding.root) windowInsetsController.isAppearanceLightStatusBars = true diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt index 9daba1f257..0ee7263879 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/QrScanFragment.kt @@ -9,6 +9,7 @@ import android.view.View import android.view.ViewGroup import androidx.activity.OnBackPressedCallback import androidx.core.content.ContextCompat +import androidx.core.view.WindowCompat import androidx.fragment.app.Fragment import com.google.zxing.Result import com.otaliastudios.cameraview.CameraView @@ -23,6 +24,7 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) } activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { store.dispatch(NavigationAction.PopBackTo()) @@ -54,7 +56,7 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler { override fun handleResult(result: Result) { store.dispatch(NavigationAction.PopBackTo()) - + activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) } if (!result.text.isNullOrBlank()) { store.dispatch(WalletConnectAction.OpenSession(result.text)) } From 829143605020e08eedde1dde9c1f86bb336bd4ec Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 26 Aug 2022 11:02:06 +0400 Subject: [PATCH 17/34] Updated on 2026-08-14 --- .../tangem/wallet/ExampleInstrumentedTest.kt | 24 ---------- .../details/ui/resetcard/ResetCardScreen.kt | 48 ++++++------------- 2 files changed, 14 insertions(+), 58 deletions(-) delete mode 100644 app/src/androidTest/java/com/tangem/wallet/ExampleInstrumentedTest.kt diff --git a/app/src/androidTest/java/com/tangem/wallet/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/tangem/wallet/ExampleInstrumentedTest.kt deleted file mode 100644 index 9a7a795e39..0000000000 --- a/app/src/androidTest/java/com/tangem/wallet/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.tangem.wallet - -import android.support.test.InstrumentationRegistry -import android.support.test.runner.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getTargetContext() - assertEquals("com.tangem.wallet", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index 58d20cf256..eda5e31bcc 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -1,16 +1,13 @@ package com.tangem.tap.features.details.ui.resetcard import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -22,7 +19,6 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.layout import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -40,18 +36,11 @@ fun ResetCardScreen( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - Box(modifier = modifier.background(colorResource(id = R.color.background_primary))) { - Image( - painter = painterResource(id = R.drawable.ic_reset_background), - contentDescription = "", - modifier = modifier.offset(y = (-16).dp), - ) SettingsScreensScaffold( content = { ResetCardView(state = state, modifier = modifier) }, onBackClick = onBackPressed, backgroundColor = Color.Transparent, ) - } } @Composable @@ -61,33 +50,26 @@ fun ResetCardView( ) { Column( modifier = modifier - .fillMaxSize(), + .fillMaxSize() + .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.SpaceBetween, ) { Box( - modifier = modifier - .padding(bottom = 20.dp), + modifier = modifier, ) { + Image( + painter = painterResource(id = R.drawable.ic_reset_background), + contentDescription = "", + modifier = modifier.offset(y = (-82).dp), + ) ScreenTitle(titleRes = R.string.reset_card_to_factory_navigation_title) } - + Spacer( + modifier = modifier.weight(1f), + ) Column( modifier = modifier - .layout { measurable, constraints -> - val placeable = - measurable.measure( - constraints.copy( - // left 200.dp for min image height - maxHeight = constraints.maxHeight - 215.dp.roundToPx(), - // occupy all height except full image square in case of smaller text - minHeight = constraints.maxHeight - constraints.maxWidth, - ), - ) - layout(placeable.width, placeable.height) { - placeable.place(0, 0) - } - } - .height(IntrinsicSize.Min), + .offset(y = (-32).dp), verticalArrangement = Arrangement.Bottom, ) { Text( @@ -102,9 +84,7 @@ fun ResetCardView( Text( text = stringResource(id = R.string.reset_card_to_factory_message), modifier = modifier - .padding(start = 20.dp, end = 20.dp) - .weight(1f, false) - .verticalScroll(rememberScrollState()), + .padding(start = 20.dp, end = 20.dp), style = TangemTypography.body1, color = colorResource(id = R.color.text_secondary), ) @@ -146,7 +126,7 @@ fun ResetCardView( Spacer(modifier = modifier.size(32.dp)) Box( modifier = modifier - .padding(start = 16.dp, end = 16.dp, bottom = 32.dp), + .padding(start = 16.dp, end = 16.dp), ) { DetailsMainButton( title = stringResource(id = R.string.reset_card_to_factory_button_title), From 1c1e1126214bd122ff886003cc449394e0f1a458 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 29 Aug 2022 20:50:10 +0300 Subject: [PATCH 18/34] Updated on 2026-08-14 --- .../com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index 4be9104bb1..9092292f99 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -62,7 +62,7 @@ class WalletAdapter fun bind(wallet: WalletData) = with(binding) { val status = wallet.currencyData.status // Skip changes when on refreshing status - if (status == BalanceStatus.Refreshing) return@with + if (status == BalanceStatus.Refreshing || wallet.fiatRateString == null) return@with val statusMessage = when (status) { BalanceStatus.TransactionInProgress -> { From 4e1a0d6c1feaad495dbc4dd98da3a0ade9429157 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 6 Sep 2022 18:38:48 +0300 Subject: [PATCH 19/34] Updated on 2026-08-14 --- app/src/main/assets/testnet_tokens.json | 10 +++++ .../tap/common/extensions/Blockchain.kt | 2 + .../redux/middlewares/AmountMiddleware.kt | 45 ++++++++++++++----- .../send/redux/middlewares/SendMiddleware.kt | 35 ++------------- .../ui/dialogs/SendTransactionFailsDialog.kt | 23 +++++++++- .../features/wallet/models/WalletWarning.kt | 5 +++ .../tap/features/wallet/redux/WalletState.kt | 34 ++++++++++---- .../redux/reducers/MultiWalletReducer.kt | 21 ++++++++- .../wallet/ui/WalletWarningConverter.kt | 6 +++ app/src/main/res/values-de/strings_final.xml | 10 +---- app/src/main/res/values-fr/strings_final.xml | 10 +---- app/src/main/res/values-it/strings_final.xml | 11 +---- app/src/main/res/values-ru/strings_final.xml | 16 +------ app/src/main/res/values/strings_final.xml | 16 +------ dependencies.gradle | 2 +- .../domain/common/extensions/Blockchain.kt | 5 +++ 16 files changed, 137 insertions(+), 114 deletions(-) diff --git a/app/src/main/assets/testnet_tokens.json b/app/src/main/assets/testnet_tokens.json index 84c055f105..179a72b282 100644 --- a/app/src/main/assets/testnet_tokens.json +++ b/app/src/main/assets/testnet_tokens.json @@ -420,6 +420,16 @@ "networkId" : "stellar/test" } ] + }, + { + "id" : "polkadot", + "symbol" : "DOT", + "name" : "Polkadot", + "networks" : [ + { + "networkId" : "polkadot/test" + } + ] } ], diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt index e2490e7886..73f63aa2a8 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt @@ -28,6 +28,7 @@ fun Blockchain.getRoundIconRes(): Int { Blockchain.Dogecoin -> R.drawable.ic_dogecoin_round Blockchain.Tron, Blockchain.TronTestnet -> R.drawable.ic_tron_round Blockchain.Gnosis -> R.drawable.ic_gnosis_round + Blockchain.Polkadot, Blockchain.PolkadotTestnet -> R.drawable.ic_polkadot_round else -> R.drawable.ic_tangem_logo } } @@ -55,6 +56,7 @@ fun Blockchain.getGreyedOutIconRes(): Int { Blockchain.Dogecoin -> R.drawable.ic_dogecoin_no_color Blockchain.Tron, Blockchain.TronTestnet -> R.drawable.ic_tron_no_color Blockchain.Gnosis -> R.drawable.ic_gnosis_no_color + Blockchain.Polkadot, Blockchain.PolkadotTestnet -> R.drawable.ic_polkadot_no_color else -> R.drawable.ic_tangem_logo } } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt index 3d59d0a270..bfcbc36889 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt @@ -4,11 +4,17 @@ import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.TransactionError import com.tangem.common.extensions.isZero import com.tangem.tap.common.redux.AppState -import com.tangem.tap.features.send.redux.* +import com.tangem.tap.features.send.redux.AmountAction +import com.tangem.tap.features.send.redux.AmountActionUi +import com.tangem.tap.features.send.redux.FeeAction +import com.tangem.tap.features.send.redux.FeeActionUi +import com.tangem.tap.features.send.redux.ReceiptAction +import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.send.redux.states.MainCurrencyType import com.tangem.tap.features.send.redux.states.SendState import org.rekotlin.Action import java.math.BigDecimal +import java.util.* /** [REDACTED_AUTHOR] @@ -62,18 +68,11 @@ class AmountMiddleware { val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto)) val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee) - transactionErrors.remove(TransactionError.TezosSendAll) - if (transactionErrors.isEmpty()) { + val amountFieldErrors = filterErrorsForAmountField(transactionErrors) + if (amountFieldErrors.isEmpty()) { dispatch(AmountAction.SetAmountError(null)) } else { - val amountErrors = extractErrorsForAmountField(transactionErrors) - if (amountErrors.isNotEmpty()) { - transactionErrors.removeAll(amountErrors) - dispatch(AmountAction.SetAmountError(createValidateTransactionError(amountErrors, walletManager))) - } - if (transactionErrors.isNotEmpty()) { - dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager))) - } + dispatch(AmountAction.SetAmountError(createValidateTransactionError(amountFieldErrors, walletManager))) } dispatch(ReceiptAction.RefreshReceipt) dispatch(SendAction.ChangeSendButtonState(sendState.getButtonState())) @@ -104,4 +103,28 @@ class AmountMiddleware { dispatch(AmountActionUi.SetMainCurrency(type)) } +} + +private fun filterErrorsForAmountField(errors: EnumSet): EnumSet { + val showIntoAmountField = EnumSet.noneOf(TransactionError::class.java) + errors.forEach { + when (it) { + TransactionError.AmountExceedsBalance -> { + showIntoAmountField.remove(TransactionError.TotalExceedsBalance) + showIntoAmountField.add(it) + } + TransactionError.FeeExceedsBalance -> { + showIntoAmountField.remove(TransactionError.TotalExceedsBalance) + showIntoAmountField.add(it) + } + TransactionError.TotalExceedsBalance -> { + val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance) + if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it) + } + else -> showIntoAmountField.add(it) + } + } + showIntoAmountField.remove(TransactionError.TezosSendAll) + + return showIntoAmountField } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index df1e3dd5ba..ee1b5eb1d2 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -114,9 +114,8 @@ private fun verifyAndSendTransaction( val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend()) val transactionErrors = walletManager.validateTransaction(amountToSend, feeAmount) - val hadTezosError = transactionErrors.remove(TransactionError.TezosSendAll) when { - hadTezosError -> { + transactionErrors.contains(TransactionError.TezosSendAll) -> { val reduceAmount = walletManager.wallet.blockchain.minimalAmount() dispatch( SendAction.Dialog.TezosWarningDialog( @@ -135,9 +134,6 @@ private fun verifyAndSendTransaction( ), ) } - transactionErrors.isNotEmpty() -> { - dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager))) - } else -> { sendTransaction( action, walletManager, amountToSend, feeAmount, destinationAddress, @@ -272,10 +268,8 @@ private fun sendTransaction( dispatch(SendAction.Dialog.SendTransactionFails.CardSdkError(tangemSdkError)) } is BlockchainSdkError.CreateAccountUnderfunded -> { - // from XLM, XRP - val reserve = error.minReserve.value?.stripZeroPlainString() ?: "0" - val symbol = error.minReserve.currencySymbol - dispatch(SendAction.SendError(TapError.CreateAccountUnderfunded(listOf(reserve, symbol)))) + // from XLM, XRP, Polkadot + dispatch(SendAction.Dialog.SendTransactionFails.BlockchainSdkError(error)) } else -> { when { @@ -300,29 +294,6 @@ private fun sendTransaction( } } -fun extractErrorsForAmountField(errors: EnumSet): EnumSet { - val showIntoAmountField = EnumSet.noneOf(TransactionError::class.java) - errors.forEach { - when (it) { - TransactionError.AmountExceedsBalance -> { - showIntoAmountField.remove(TransactionError.TotalExceedsBalance) - showIntoAmountField.add(it) - } - TransactionError.FeeExceedsBalance -> { - showIntoAmountField.remove(TransactionError.TotalExceedsBalance) - showIntoAmountField.add(it) - } - TransactionError.TotalExceedsBalance -> { - val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance) - if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it) - } - TransactionError.InvalidAmountValue -> showIntoAmountField.add(it) - TransactionError.InvalidFeeValue -> showIntoAmountField.add(it) - } - } - return showIntoAmountField -} - fun createValidateTransactionError( errorList: EnumSet, walletManager: WalletManager, diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt index a01c048058..a4b5ff7539 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt @@ -2,7 +2,10 @@ package com.tangem.tap.features.send.ui.dialogs import android.content.Context import androidx.appcompat.app.AlertDialog +import com.tangem.blockchain.common.BlockchainSdkError +import com.tangem.common.module.ModuleMessageConverter import com.tangem.tangem_sdk_new.extensions.localizedDescription +import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.feedback.SendTransactionFailedEmail import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.send.redux.SendAction @@ -13,14 +16,14 @@ import com.tangem.wallet.R [REDACTED_AUTHOR] */ class SendTransactionFailsDialog { - companion object { fun create(context: Context, dialog: SendAction.Dialog.SendTransactionFails.CardSdkError): AlertDialog { return create(context, dialog.error.localizedDescription(context)) } fun create(context: Context, dialog: SendAction.Dialog.SendTransactionFails.BlockchainSdkError): AlertDialog { - return create(context, dialog.error.customMessage) + val errorConverter = BlockchainSdkErrorConverter(context) + return create(context, errorConverter.convert(dialog.error)) } private fun create(context: Context, errorMessage: String): AlertDialog { @@ -35,4 +38,20 @@ class SendTransactionFailsDialog { }.create() } } +} + +private class BlockchainSdkErrorConverter( + private val context: Context, +) : ModuleMessageConverter { + + override fun convert(message: BlockchainSdkError): String { + return when (message) { + is BlockchainSdkError.CreateAccountUnderfunded -> { + val reserve = message.minReserve.value?.stripZeroPlainString() ?: "0" + val symbol = message.minReserve.currencySymbol + context.getString(R.string.send_error_no_target_account, reserve, symbol) + } + else -> message.customMessage + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt index 0b4a56fa11..8923b18d6e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt @@ -3,6 +3,11 @@ package com.tangem.tap.features.wallet.models sealed class WalletWarning( val showingPosition: Int, ) { + data class ExistentialDeposit( + val blockchainFullName: String, + val existentialDepositString: String, + ) : WalletWarning(1) + object TransactionInProgress : WalletWarning(10) data class BalanceNotEnoughForFee(val blockchainFullName: String) : WalletWarning(30) data class Rent(val walletRent: WalletRent) : WalletWarning(40) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 48c886d939..a5c85a49fb 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -325,9 +325,6 @@ data class Artwork( const val MARTA_CARD_ID = "BC02" const val TWIN_CARD_1 = "https://app.tangem.com/cards/card_tg085.png" const val TWIN_CARD_2 = "https://app.tangem.com/cards/card_tg086.png" - - const val TEMP_CARDANO = - "https://verify.tangem.com/card/artwork?artworkId=card_ru039&CID=CB19000000040976&publicKey=0416E29423A6CC77CD07CBA52873E8F6F894B1AFB18EB3688ACC2C8D8E5AC84B80B0BA1B17B85E578E47044CE96BCFF3FB4499FA4941CAD3C1EF300A492B5B9659" } } @@ -342,6 +339,7 @@ data class WalletData( val mainButton: WalletMainButton = WalletMainButton.SendButton(false), val currency: Currency, val walletRent: WalletRent? = null, + val existentialDepositString: String? = null, ) { val isAvailableToBuy: Boolean get() = store.state.globalState.exchangeManager.availableForBuy(currency) @@ -362,18 +360,38 @@ data class WalletData( fun assembleWarnings(): List { val walletWarnings = mutableListOf() + assembleNonTypedWarnings(walletWarnings) + assembleBlockchainWarnings(walletWarnings) + assembleTokenWarnings(walletWarnings) + + return walletWarnings.sortedBy { it.showingPosition } + } + + private fun assembleNonTypedWarnings(walletWarnings: MutableList) { if (currencyData.status == BalanceStatus.SameCurrencyTransactionInProgress) { walletWarnings.add(WalletWarning.TransactionInProgress) } + } + + private fun assembleBlockchainWarnings(walletWarnings: MutableList) { + if (!currency.isBlockchain()) return + + val blockchainFullName = currency.blockchain.fullName + if (existentialDepositString != null) { + walletWarnings.add(WalletWarning.ExistentialDeposit(blockchainFullName, existentialDepositString)) + } if (walletRent != null) { walletWarnings.add(WalletWarning.Rent(walletRent)) } - if (!currency.isBlockchain() && (blockchainAmountIsEmpty() && !tokenAmountIsEmpty())) { - val fullName = currency.blockchain.fullName - walletWarnings.add(WalletWarning.BalanceNotEnoughForFee(fullName)) - } + } - return walletWarnings.sortedBy { it.showingPosition } + private fun assembleTokenWarnings(walletWarnings: MutableList){ + if (!currency.isToken()) return + + val blockchainFullName = currency.blockchain.fullName + if ((blockchainAmountIsEmpty() && !tokenAmountIsEmpty())) { + walletWarnings.add(WalletWarning.BalanceNotEnoughForFee(blockchainFullName)) + } } private fun blockchainAmountIsEmpty(): Boolean = currencyData.blockchainAmount?.isZero() == true diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index e8f9551910..9821f1f6a7 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -1,15 +1,25 @@ package com.tangem.tap.features.wallet.redux.reducers +import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Token +import com.tangem.blockchain.common.WalletManager import com.tangem.common.extensions.guard import com.tangem.tap.common.extensions.toFiatString import com.tangem.tap.common.extensions.toFormattedCurrencyString import com.tangem.tap.domain.getFirstToken import com.tangem.tap.domain.tokens.models.BlockchainNetwork -import com.tangem.tap.features.wallet.models.* -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.models.Currency +import com.tangem.tap.features.wallet.models.WalletRent +import com.tangem.tap.features.wallet.models.filterByToken +import com.tangem.tap.features.wallet.models.getPendingTransactions +import com.tangem.tap.features.wallet.models.removeUnknownTransactions +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletMainButton +import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN +import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.features.wallet.ui.TokenData @@ -25,6 +35,7 @@ class MultiWalletReducer { it.wallet.blockchain == blockchain.blockchain && (it.wallet.publicKey.derivationPath?.rawPath == blockchain.derivationPath) } ?: return@mapNotNull null + val wallet = walletManager.wallet val cardToken = if (!state.isMultiwalletAllowed) { wallet.getFirstToken()?.symbol?.let { TokenData("", tokenSymbol = it) } @@ -44,6 +55,7 @@ class MultiWalletReducer { blockchain.blockchain, blockchain.derivationPath ), + existentialDepositString = getExistentialDeposit(walletManager), ) WalletStore( @@ -79,6 +91,7 @@ class MultiWalletReducer { action.blockchain.blockchain, action.blockchain.derivationPath ), + existentialDepositString = getExistentialDeposit(walletManager), ) val walletStore = WalletStore( walletManager = walletManager, @@ -166,6 +179,10 @@ class MultiWalletReducer { it.walletRent != null }?.walletRent } + + private fun getExistentialDeposit(walletManager: WalletManager?): String? { + return (walletManager as? ExistentialDepositProvider)?.getExistentialDeposit()?.toPlainString() + } } private fun addTokens( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt index 1e9e127e59..1f319a2a0b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt @@ -15,6 +15,12 @@ class WalletWarningConverter( override fun convert(message: WalletWarning): WalletWarningDescription { val warningMessage = when (message) { + is WalletWarning.ExistentialDeposit -> { + context.getString( + R.string.warning_existential_deposit_message, + message.blockchainFullName, message.existentialDepositString + ) + } is WalletWarning.BalanceNotEnoughForFee -> { context.getString( R.string.token_details_send_blocked_fee_format, diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 96c0876eff..20ebb2312d 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -38,30 +38,25 @@ You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. Do not transfer your funds to tokens in this blockchain, otherwise it may lead to their irretrievable loss. Contract address copied! If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds - Custom Notice Attention The server is not available, please try again later - Hide token Hide %s Hide You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - %s network not found. Please, add it first and try again. This network is not supported. Please select another network. %s network - Card Settings Security Mode Selected application protection method @@ -81,18 +76,15 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - Link More Cards You can synchronize up to three cards into one wallet. It can only be done once. - Privacy policy - Reset to factory settings This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index 3fe6eb9f17..9433ca3e3a 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -38,30 +38,25 @@ You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. Do not transfer your funds to tokens in this blockchain, otherwise it may lead to their irretrievable loss. Contract address copied! If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds - Custom The server is not available, please try again later Notice Attention - Hide token Hide %s Hide You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - %s network not found. Please, add it first and try again. This network is not supported. Please select another network. %s network - Card Settings Security Mode Selected application protection method @@ -81,18 +76,15 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - Link More Cards You can synchronize up to three cards into one wallet. It can only be done once. - Privacy policy - Reset to factory settings This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index afe988cb58..9433ca3e3a 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -38,31 +38,25 @@ You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. Do not transfer your funds to tokens in this blockchain, otherwise it may lead to their irretrievable loss. Contract address copied! If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds - Custom The server is not available, please try again later Notice Attention - Hide token Hide %s Hide You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - %s network not found. Please, add it first and try again. This network is not supported. Please select another network. - %s network - Card Settings Security Mode Selected application protection method @@ -82,18 +76,15 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - Link More Cards You can synchronize up to three cards into one wallet. It can only be done once. - Privacy policy - Reset to factory settings This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 359b5c0488..f475af97dc 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -38,47 +38,36 @@ Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие. Эта функция недоступна в демонстрационном режиме Недостаточно средств для комиссии на вашем %s кошельке для отправки транзакции. Сначала пополните свой %s кошелек. - Доступные сети Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства. Токены в сети Solana не поддерживаются этой картой из-за ограничений прошивки. Не осуществляйте перевод на токены в данной сети, иначе это может привести к их безвозвратной утере. Адрес контракта скопирован! Если вы совершили ошибку с выбором сети при переводе средств с биржи, эта инструкция поможет вам восстановить средства - Пользовательский Уведомление Внимание Сервер недоступен, повторите попытку позднее - Баланс В сумме учтены не все монеты Управление токенами Нет цены - Скрыть токен Скрыть %s Скрыть Вы скрываете токен с главного экрана, но в любой момент сможете добавить его обратно через страницу управления токенами. Невозможно скрыть %s - Токен %s является основной валютой в сети %s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети. - Сеть %s не найдена. Пожалуйста, добавьте её и попробуйте заново. Сеть не поддерживается. Пожалуйста, выберите другую сеть. - Сеть %s - Бэкап кошелька не был произведен Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру - Карты банков РФ в данный момент не принимаются У вас есть карта банка другой страны или платежной системы UnionPay? Да - Чат Tangem Bot - Настройки карты Тип безопасности Выбранный способ защиты приложения @@ -98,18 +87,15 @@ Все сохраненные коды доступа будут удалены. Вам потребуется вводить код доступа при работе с кошельком. WalletConnect Подключение к Dapps - Добавить еще карты Вы можете объединить до трех карт в одном кошельке. Это можно сделать только один раз. - Privacy policy - Сброс к заводским настройкам Это действие приведет к полному удалению кошелька на этой карте. Кошелек невозможно будет восстановить или использовать данную карту для восстановления кода доступа Я понимаю, что после выполнения этого действия у меня больше не будет доступа к текущему кошельку Сбросить карту Сброс к заводским настройкам Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. - Выберите сеть + Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s, он будет деактивирован, а все оставшиеся средства будут уничтожены. diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index ca04743898..c0c24db28f 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -38,49 +38,38 @@ You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. - Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. Do not transfer your funds to tokens in this blockchain, otherwise it may lead to their irretrievable loss. Contract address copied! If you chose the wrong network during your crypto transfer from the exchange, this guide will help you recover your funds - Custom Notice Attention The server is not available, please try again later - Total balance The amount does not include some of your funds Manage tokens No rate - Hide token Hide %s Hide You are about to hide this token from the main screen. You can add it back anytime through the manage tokens page. Unable to hide %s The %s token is the main currency on the %s network and cannot be hidden as long as you have other tokens on this network in the list. - %s network not found. Please, add it first and try again. This network is not supported. Please select another network. - %s network - Your wallet has not been backed up To protect your assets, we advise you to carry out this procedure Remove token - Russian bank cards are not accepted at the moment Do you have a bank card of another country or a UnionPay card? Yes No - Chat Tangem Bot - - Card Settings Security Mode Selected application protection method @@ -100,18 +89,15 @@ This will delete all the saved wallet access codes. Any further operation with the wallet will require submitting the access code. WalletConnect Connect to Dapps - Link More Cards You can synchronize up to three cards into one wallet. It can only be done once. - Privacy policy - Reset to factory settings This action will completely remove the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. I understand that after performing this action, I will no longer have access to the current wallet Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. - Select network + %s network has a concept of Existential Deposit. If your account drops below %s it will be deactivated and any remaining funds will be destroyed. diff --git a/dependencies.gradle b/dependencies.gradle index e1c383532f..4717ab51df 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - tangem_blockchain_sdk: 'develop-105', + tangem_blockchain_sdk: 'develop-107', // tangem_blockchain_sdk: '0.0.1', ] diff --git a/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt index 8708f1a0a8..139bc99365 100644 --- a/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt +++ b/domain/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt @@ -38,6 +38,8 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { "tron/test" -> Blockchain.TronTestnet "xrp", "ripple" -> Blockchain.XRP "xdai" -> Blockchain.Gnosis + "polkadot" -> Blockchain.Polkadot + "polkadot/test" -> Blockchain.PolkadotTestnet else -> null } } @@ -80,6 +82,8 @@ fun Blockchain.toNetworkId(): String { Blockchain.Tron -> "tron" Blockchain.TronTestnet -> "tron/test" Blockchain.Gnosis -> "xdai" + Blockchain.Polkadot -> "polkadot" + Blockchain.PolkadotTestnet -> "polkadot/test" } } @@ -105,6 +109,7 @@ fun Blockchain.toCoinId(): String { Blockchain.Dogecoin -> "dogecoin" Blockchain.Tron, Blockchain.TronTestnet -> "tron" Blockchain.Gnosis -> "xdai" + Blockchain.Polkadot, Blockchain.PolkadotTestnet -> "polkadot" Blockchain.Unknown -> "unknown" } } \ No newline at end of file From 00740e43139b82394cf390458527fd607298326d Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 6 Sep 2022 22:41:45 +0300 Subject: [PATCH 20/34] Updated on 2026-08-14 --- .idea/codeStyles/Project.xml | 2 -- .../tangem/tap/features/wallet/models/WalletWarning.kt | 3 ++- .../com/tangem/tap/features/wallet/redux/WalletState.kt | 8 ++++++-- .../tap/features/wallet/ui/WalletWarningConverter.kt | 6 +++--- app/src/main/res/values-de/strings_final.xml | 2 +- app/src/main/res/values-fr/strings_final.xml | 2 +- app/src/main/res/values-it/strings_final.xml | 2 +- app/src/main/res/values-ru/strings_final.xml | 2 +- app/src/main/res/values/strings_final.xml | 2 +- 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 3ab743df69..2add9b412a 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -29,7 +29,6 @@