From 4d60d07309ec930c6fe6ce95541a248d3d7b1f7e Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 13:54:46 +0300 Subject: [PATCH 01/13] Updated on 2026-08-14 --- .../tangem/tap/features/demo/DemoHelper.kt | 114 +++++++++++++++++- 1 file changed, 109 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index 24e8671c33..f30ec0bbb7 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -85,7 +85,7 @@ class DemoConfig { ) val demoCardIds: List by lazy { - val demoIds = (releaseDemoCardIds + testDemoCardIds).toMutableList() + val demoIds = getReleaseIds().toMutableList() if (BuildConfig.DEBUG) demoIds.addAll(debugTestDemoCardIds) return@lazy demoIds.distinct() @@ -103,6 +103,11 @@ class DemoConfig { fun getBalance(blockchain: Blockchain): Amount = walletBalances[blockchain]?.copy() ?: Amount(BigDecimal.ZERO, blockchain).copy() + private fun getReleaseIds(): List { + return (releaseDemoCardIds + + releaseDemoCardIds_19042022).distinct() + } + private val releaseDemoCardIds = mutableListOf( // Tangem Wallet: "AC01000000041100", @@ -145,14 +150,113 @@ class DemoConfig { "AB02000000051059", ) + // https://tangem.slack.com/archives/GMXC6PP71/p1650360610759269 + private val releaseDemoCardIds_19042022 = listOf( + // Wallet + "AC01000000045754", + "AC01000000041662", + "AC01000000041647", + "AC01000000041209", + "AC01000000042462", + "AC01000000041100", + "AC01000000041621", + "AC01000000045960", + "AC01000000041092", + "AC01000000041217", + "AC01000000013489", + "AC01000000028610", + "AC01000000028701", + "AC01000000028578", + "AC01000000027281", + "AC01000000027216", + "AC01000000028594", + "AC01000000028602", + "AC01000000028636", + "AC01000000013968", + "AC01000000027208", + "AC01000000013471", + "AC01000000028586", + "AC01000000013703", + "AC01000000028628", + "AC01000000028693", + "AC01000000028685", + "AC01000000013950", + "AC01000000013828", + "AC01000000013497", + "AC01000000013836", + "AC01000000013505", +// Note BTC + "AB01000000059608", + "AB01000000046647", + "AB01000000046571", + "AB01000000046746", + "AB01000000059574", + "AB01000000046753", + "AB01000000046605", + "AB01000000046761", + "AB01000000046720", + "AB01000000046530", + "AB01000000016475", + "AB01000000016483", + "AB01000000016491", + "AB01000000020709", + "AB01000000020717", + "AB01000000015550", + "AB01000000015394", + "AB01000000016079", + "AB01000000016087", + "AB01000000016095", + "AB01000000020915", + "AB01000000017184", + "AB01000000020907", + "AB01000000017192", + "AB01000000016210", + "AB01000000016111", + "AB01000000016103", + "AB01000000015766", + "AB01000000015774", + "AB01000000015782", + "AB01000000022598", + "AB01000000022580", +// Note ETH + "AB02000000051083", + "AB02000000051059", + "AB02000000051158", + "AB02000000050986", + "AB02000000051026", + "AB02000000050960", + "AB02000000051042", + "AB02000000051091", + "AB02000000051034", + "AB02000000051133", + "AB02000000019924", + "AB02000000019932", + "AB02000000022092", + "AB02000000022282", + "AB02000000023983", + "AB02000000023439", + "AB02000000020328", + "AB02000000020310", + "AB02000000021565", + "AB02000000022357", + "AB02000000023355", + "AB02000000022324", + "AB02000000022100", + "AB02000000019999", + "AB02000000020013", + "AB02000000020005", + "AB02000000020021", + "AB02000000020039", + "AB02000000020278", + "AB02000000020252", + "AB02000000018652", + "AB02000000018561", + ) + private val testDemoCardIds = listOf( "FB20000000000186", // Note ETH "FB10000000000196", // Note BTC "FB30000000000176", // Wallet - //TODO: delete bellow ids before 3.28 release - "AB01000000045060", // Note BTC - "AB02000000045028", // Note ETH - "AC79000000000004", // Wallet 4.46 ) private val debugTestDemoCardIds = listOf( From c4bcbe8a2c7ae92d83233b8606222223e21e3b93 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 18:35:45 +0400 Subject: [PATCH 02/13] Updated on 2026-08-14 --- app/src/main/assets/testnet_tokens.json | 60 +++++++++---------- .../tap/domain/tokens/CurrenciesRepository.kt | 4 +- .../com/tangem/tap/domain/tokens/Currency.kt | 30 ++++------ .../domain/common/extensions/Blockchain.kt | 40 ++++++------- 4 files changed, 65 insertions(+), 69 deletions(-) diff --git a/app/src/main/assets/testnet_tokens.json b/app/src/main/assets/testnet_tokens.json index 029758adb2..e1e7139851 100644 --- a/app/src/main/assets/testnet_tokens.json +++ b/app/src/main/assets/testnet_tokens.json @@ -1,12 +1,12 @@ { "tokens" : [ { - "id" : "polygon/test", + "id" : "polygon-pos/test", "symbol" : "MATIC", "name" : "Polygon", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0x0000000000000000000000000000000000001010", "decimalCount" : 18 } @@ -18,17 +18,17 @@ "name" : "Dai Stablecoin", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0xcB1e72786A6eb3b44C2a2429e317c8a2462CFeb1", "decimalCount" : 18 }, { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0xec5dcb5dbf4b114c9d0f65bccab49ec54f6a0867", "decimalCount" : 18 }, { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0x8a9424745056eb399fd19a0ec26a14316684e274", "decimalCount" : 18 } @@ -40,7 +40,7 @@ "name" : "Dummy ERC20", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1", "decimalCount" : 18 } @@ -52,12 +52,12 @@ "name" : "Ether", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0x714550C2C1Ea08688607D86ed8EeF4f5E4F22323", "decimalCount" : 18 }, { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0xd66c6b4f0be8ce5b39d52e0fd1344c389929b378", "decimalCount" : 18 } @@ -69,7 +69,7 @@ "name" : "Test Token", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e", "decimalCount" : 18 } @@ -81,17 +81,17 @@ "name" : "Tether USD", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0x3813e82e6f7098b9583FC0F33a962D02018B6803", "decimalCount" : 6 }, { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0x337610d27c682e347c9cd60bd4b3b107c9d34ddd", "decimalCount" : 18 }, { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684", "decimalCount" : 18 } @@ -103,7 +103,7 @@ "name" : "Wrapped Ether", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa", "decimalCount" : 18 } @@ -115,7 +115,7 @@ "name" : "Wrapped Matic", "contracts" : [ { - "networkId" : "polygon-pos", + "networkId" : "polygon-pos/test", "address" : "0xd0A1E359811322d97991E03f863a0C30C2cF029C", "decimalCount" : 18 } @@ -135,7 +135,7 @@ "name" : "Tangem Coin A", "contracts" : [ { - "networkId" : "solana", + "networkId" : "solana/test", "address" : "22PTNbX31Zuztd6nD82fC8nQdT2hUfWv9XWXKuDkrFqR", "decimalCount" : 9 } @@ -147,14 +147,14 @@ "name" : "Tangem Coin B", "contracts" : [ { - "networkId" : "solana", + "networkId" : "solana/test", "address" : "HmSghNPg6KCk711YJA92aPejt8auyFkvmaED6jbHfUs4", "decimalCount" : 9 } ] }, { - "id" : "binance/test", + "id" : "binancecoin/test", "symbol" : "BNB", "name" : "Binance", "contracts" : [ @@ -167,14 +167,14 @@ "name" : "Hemster - 452", "contracts" : [ { - "networkId" : "binancecoin", + "networkId" : "binancecoin/test", "address" : "HEM-452", "decimalCount" : 8 } ] }, { - "id" : "bsc/test", + "id" : "binance-smart-chain/test", "symbol" : "BNB", "name" : "Bsc", "contracts" : [ @@ -187,7 +187,7 @@ "name" : "Binance-Peg BTCB Token", "contracts" : [ { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0x6ce8da28e2f864420840cf74474eff5fd80e65b8", "decimalCount" : 18 } @@ -199,7 +199,7 @@ "name" : "Binance-Peg BUSD Token", "contracts" : [ { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0xed24fc36d5ee211ea25a80239fb8c4cfd80f12ee", "decimalCount" : 18 } @@ -211,7 +211,7 @@ "name" : "Binance-Peg USDC Token", "contracts" : [ { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0x64544969ed7ebf5f083679233325356ebe738930", "decimalCount" : 18 } @@ -223,7 +223,7 @@ "name" : "Binance-Peg XRP", "contracts" : [ { - "networkId" : "binance-smart-chain", + "networkId" : "binance-smart-chain/test", "address" : "0xa83575490d7df4e2f47b7d38ef351a2722ca45b9", "decimalCount" : 18 } @@ -255,7 +255,7 @@ "name" : "Xeenus", "contracts" : [ { - "networkId" : "ethereum", + "networkId" : "ethereum/test", "address" : "0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c", "decimalCount" : 18 } @@ -267,7 +267,7 @@ "name" : "Yeenus", "contracts" : [ { - "networkId" : "ethereum", + "networkId" : "ethereum/test", "address" : "0xc6fDe3FD2Cc2b173aEC24cc3f267cb3Cd78a26B7", "decimalCount" : 8 } @@ -279,7 +279,7 @@ "name" : "Zeenus", "contracts" : [ { - "networkId" : "ethereum", + "networkId" : "ethereum/test", "address" : "0x1f9061B953bBa0E36BF50F21876132DcF276fC6e", "decimalCount" : 0 } @@ -299,7 +299,7 @@ "name" : "The Fuji stablecoin", "contracts" : [ { - "networkId" : "avalanche", + "networkId" : "avalanche/test", "address" : "0x2058ec2791dD28b6f67DB836ddf87534F4Bbdf22", "decimalCount" : 6 } @@ -311,7 +311,7 @@ "name" : "To the Moon", "contracts" : [ { - "networkId" : "avalanche", + "networkId" : "avalanche/test", "address" : "0x97132C109c6816525F7f338DCb7435E1412A7668", "decimalCount" : 9 } @@ -331,7 +331,7 @@ "name" : "Fantom USD", "contracts" : [ { - "networkId" : "fantom", + "networkId" : "fantom/test", "address" : "0x91ea991bd52EE3C40EdA2509701d905e1Ee54074", "decimalCount" : 18 } @@ -343,7 +343,7 @@ "name" : "Wrapped Fantom", "contracts" : [ { - "networkId" : "fantom", + "networkId" : "fantom/test", "address" : "0xf1277d1Ed8AD466beddF92ef448A132661956621", "decimalCount" : 18 } diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt index e7ee96d05b..c65b3159a5 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/CurrenciesRepository.kt @@ -152,7 +152,7 @@ class CurrenciesRepository(val context: Application) { .map { val token = it.toToken() val id = currencies - .find { it.contracts?.find { it.address == token.contractAddress } != null } + .find { it.contracts.find { it.address == token.contractAddress } != null } ?.id token.copy(id = id) } @@ -180,7 +180,7 @@ class CurrenciesRepository(val context: Application) { val fileName = if (isTestNet) "testnet_tokens" else "tokens" val json = context.assets.readJsonFileToString(fileName) return currenciesAdapter.fromJson(json)!!.tokens - .map { Currency.fromJsonObject(it, isTestNet) } + .map { Currency.fromJsonObject(it) } } private fun loadTokensJson(blockchain: Blockchain): String? { diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt index 3bd2e57ef5..175d1e8370 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/Currency.kt @@ -26,8 +26,8 @@ data class CurrenciesFromJson( ) -fun List.toContracts(isTestNet: Boolean): List { - return mapNotNull { Contract.fromJsonObject(it, isTestNet) } +fun List.toContracts(): List { + return mapNotNull { Contract.fromJsonObject(it) } } data class Currency( @@ -39,23 +39,22 @@ data class Currency( ) { companion object { - fun fromJsonObject(currency: CurrencyFromJson, isTestNet: Boolean): Currency { + fun fromJsonObject(currency: CurrencyFromJson): Currency { return Currency( id = currency.id, name = currency.name, symbol = currency.symbol, iconUrl = getIconUrl(currency.id), - contracts = prepareListOfContracts(currency.contracts, currency.id, isTestNet) + contracts = prepareListOfContracts(currency.contracts, currency.id) ) } private fun prepareListOfContracts( contractsFromJson: List?, currencyId: String, - isTestNet: Boolean ): List { - val mainNetwork = Contract.fromCurrencyId(currencyId, isTestNet) - val contracts = contractsFromJson?.toContracts(isTestNet) ?: emptyList() + val mainNetwork = Contract.fromCurrencyId(currencyId) + val contracts = contractsFromJson?.toContracts() ?: emptyList() return (listOfNotNull(mainNetwork) + contracts).distinct() } } @@ -70,11 +69,10 @@ data class Contract( ) { companion object { - fun fromJsonObject(contract: ContractFromJson, isTestNet: Boolean): Contract? { - val networkId = if (isTestNet) contract.networkId + TESTNET else contract.networkId - val blockchain = Blockchain.fromNetworkId(networkId) ?: return null + fun fromJsonObject(contract: ContractFromJson): Contract? { + val blockchain = Blockchain.fromNetworkId(contract.networkId) ?: return null return Contract( - networkId = networkId, + networkId = contract.networkId, blockchain = blockchain, address = contract.address, decimalCount = contract.decimalCount, @@ -82,19 +80,17 @@ data class Contract( ) } - fun fromCurrencyId(currencyId: String, isTestNet: Boolean): Contract? { - val networkId = if (isTestNet) currencyId + TESTNET else currencyId - val blockchain = Blockchain.fromNetworkId(networkId) ?: return null + fun fromCurrencyId(currencyId: String): Contract? { + val blockchain = Blockchain.fromNetworkId(currencyId) ?: return null return Contract( - networkId = networkId, + networkId = currencyId, blockchain = blockchain, address = blockchain.currency, decimalCount = blockchain.decimals(), - iconUrl = getIconUrl(networkId) + iconUrl = getIconUrl(currencyId) ) } - const val TESTNET = "-testnet" } } 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 54def43015..cb2bc7c822 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 @@ -5,30 +5,30 @@ import com.tangem.blockchain.common.Blockchain fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? { return when (networkId) { "avalanche", "avalanche-2" -> Blockchain.Avalanche - "avalanche-testnet", "avalanche-2-testnet" -> Blockchain.AvalancheTestnet + "avalanche/test", "avalanche-2/test" -> Blockchain.AvalancheTestnet "binancecoin" -> Blockchain.Binance - "binancecoin-testnet" -> Blockchain.BinanceTestnet + "binancecoin/test" -> Blockchain.BinanceTestnet "binance-smart-chain" -> Blockchain.BSC - "binance-smart-chain-testnet" -> Blockchain.BSCTestnet + "binance-smart-chain/test" -> Blockchain.BSCTestnet "ethereum" -> Blockchain.Ethereum - "ethereum-testnet" -> Blockchain.EthereumTestnet + "ethereum/test" -> Blockchain.EthereumTestnet "polygon-pos" -> Blockchain.Polygon - "polygon-pos-testnet" -> Blockchain.PolygonTestnet + "polygon-pos/test" -> Blockchain.PolygonTestnet "solana" -> Blockchain.Solana - "solana-testnet" -> Blockchain.SolanaTestnet + "solana/test" -> Blockchain.SolanaTestnet "fantom" -> Blockchain.Fantom - "fantom-testnet" -> Blockchain.FantomTestnet + "fantom/test" -> Blockchain.FantomTestnet "bitcoin" -> Blockchain.Bitcoin - "bitcoin-testnet" -> Blockchain.BitcoinTestnet + "bitcoin/test" -> Blockchain.BitcoinTestnet "bitcoin-cash" -> Blockchain.BitcoinCash - "bitcoin-cash-testnet" -> Blockchain.BitcoinCashTestnet + "bitcoin-cash/test" -> Blockchain.BitcoinCashTestnet "cardano" -> Blockchain.CardanoShelley "dogecoin" -> Blockchain.Dogecoin "ducatus" -> Blockchain.Ducatus "litecoin" -> Blockchain.Litecoin "rsk" -> Blockchain.RSK "stellar" -> Blockchain.Stellar - "stellar-testnet" -> Blockchain.StellarTestnet + "stellar/test" -> Blockchain.StellarTestnet "tezos" -> Blockchain.Tezos "ripple" -> Blockchain.XRP else -> null @@ -39,31 +39,31 @@ fun Blockchain.toNetworkId(): String { return when (this) { Blockchain.Unknown -> "unknown" Blockchain.Avalanche -> "avalanche" - Blockchain.AvalancheTestnet -> "avalanche-testnet" + Blockchain.AvalancheTestnet -> "avalanche/test" Blockchain.Binance -> "binancecoin" - Blockchain.BinanceTestnet -> "binancecoin-testnet" + Blockchain.BinanceTestnet -> "binancecoin/test" Blockchain.BSC -> "binance-smart-chain" - Blockchain.BSCTestnet -> "binance-smart-chain-testnet" + Blockchain.BSCTestnet -> "binance-smart-chain/test" Blockchain.Bitcoin -> "bitcoin" - Blockchain.BitcoinTestnet -> "bitcoin-testnet" + Blockchain.BitcoinTestnet -> "bitcoin/test" Blockchain.BitcoinCash -> "bitcoin-cash" - Blockchain.BitcoinCashTestnet -> "bitcoin-cash-testnet" + Blockchain.BitcoinCashTestnet -> "bitcoin-cash/test" Blockchain.Cardano -> "cardano" Blockchain.CardanoShelley -> "cardano" Blockchain.Dogecoin -> "dogecoin" Blockchain.Ducatus -> "ducatus" Blockchain.Ethereum -> "ethereum" - Blockchain.EthereumTestnet -> "ethereum-testnet" + Blockchain.EthereumTestnet -> "ethereum/test" Blockchain.Fantom -> "fantom" - Blockchain.FantomTestnet -> "fantom-testnet" + Blockchain.FantomTestnet -> "fantom/test" Blockchain.Litecoin -> "litecoin" Blockchain.Polygon -> "matic-network" - Blockchain.PolygonTestnet -> "matic-networks-testnet" + Blockchain.PolygonTestnet -> "matic-networks/test" Blockchain.RSK -> "rootstock" Blockchain.Stellar -> "stellar" - Blockchain.StellarTestnet -> "stellar-testnet" + Blockchain.StellarTestnet -> "stellar/test" Blockchain.Solana -> "solana" - Blockchain.SolanaTestnet -> "solana-testnet" + Blockchain.SolanaTestnet -> "solana/test" Blockchain.Tezos -> "tezos" Blockchain.XRP -> "ripple" } From 8af66687b05853340732039280dc8ced0ed93d67 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 18:38:02 +0400 Subject: [PATCH 03/13] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletAction.kt | 1 + .../wallet/redux/OnboardingWalletMiddleware.kt | 10 +++++++++- .../products/wallet/redux/OnboardingWalletReducer.kt | 6 +++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 4795e9ffa8..78631a152f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -21,6 +21,7 @@ sealed class OnboardingWalletAction : Action { sealed class BackupAction : Action { object DetermineBackupStep : BackupAction() + object IntroduceBackup : BackupAction() object StartBackup : BackupAction() object DismissBackup : BackupAction() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 4050cd2b20..c880488141 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -111,7 +111,15 @@ private fun handleWalletAction(action: Action) { val newAction = when (val backupState = backupService.currentState) { BackupService.State.FinalizingPrimaryCard -> BackupAction.PrepareToWritePrimaryCard is BackupService.State.FinalizingBackupCard -> BackupAction.PrepareToWriteBackupCard(backupState.index) - else -> null + else -> { + if (walletState.backupState.backupStep == BackupStep.InitBackup || + walletState.backupState.backupStep == BackupStep.Finished + ) { + BackupAction.IntroduceBackup + } else { + null + } + } } newAction?.let { store.dispatch(it) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 50ce9878e1..ab36973e17 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -39,6 +39,10 @@ class BackupReducer { ): BackupState { return when (action) { + is BackupAction.IntroduceBackup -> BackupState( + backupStep = BackupStep.InitBackup, + canSkipBackup = state.canSkipBackup, + ) BackupAction.StartAddingPrimaryCard -> state.copy(backupStep = BackupStep.ScanOriginCard) BackupAction.StartAddingBackupCards -> { state.copy(backupStep = BackupStep.AddBackupCards) @@ -104,6 +108,7 @@ class BackupReducer { BackupAction.OnAccessCodeDialogClosed -> { state.copy(backupStep = BackupStep.AddBackupCards) } + BackupAction.DiscardBackup -> BackupState() BackupAction.WritePrimaryCard -> state is BackupAction.WriteBackupCard -> state @@ -117,7 +122,6 @@ class BackupReducer { is BackupAction.CheckAccessCode -> state BackupAction.DetermineBackupStep -> state BackupAction.CheckForUnfinishedBackup -> state - BackupAction.DiscardBackup -> state BackupAction.ResumeBackup -> state BackupAction.DiscardSavedBackup -> state BackupAction.StartBackup -> state From 2649bc96b4ea4678dbff3c8405c87750e565260c Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 18:48:17 +0400 Subject: [PATCH 04/13] Updated on 2026-08-14 --- .../warningMessage/WarningMessage.kt | 2 +- .../warningMessage/WarningMessagesManager.kt | 19 +++++++++++++++ .../redux/middlewares/WarningsMiddleware.kt | 4 ++++ .../ui/adapters/WarningMessagesAdapter.kt | 24 ++++++++++++++++++- app/src/main/res/layout/layout_warning.xml | 2 +- app/src/main/res/values-de/strings_final.xml | 1 + app/src/main/res/values-fr/strings_final.xml | 1 + app/src/main/res/values-it/strings_final.xml | 1 + app/src/main/res/values-ru/strings_final.xml | 1 + app/src/main/res/values/strings_final.xml | 1 + 10 files changed, 53 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt index 500f3844b3..03c10daf6f 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessage.kt @@ -21,7 +21,7 @@ data class WarningMessage( val messageFormatArg: String? = null ) { val blockchainList: List? by lazy { - blockchains?.map { Blockchain.fromId(it.toUpperCase()) } + blockchains?.map { Blockchain.fromId(it.uppercase()) } } diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt index 163ac1264a..40c5755a23 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningMessagesManager.kt @@ -5,6 +5,7 @@ import com.tangem.common.extensions.VoidCallback import com.tangem.tap.common.extensions.containsAny import com.tangem.tap.common.extensions.removeBy import com.tangem.wallet.R +import java.util.* /** [REDACTED_AUTHOR] @@ -181,6 +182,24 @@ class WarningMessagesManager( WarningMessage.Origin.Local ) + fun restoreFundsWarning(): WarningMessage = WarningMessage( + title = "", + message = "", + type = WarningMessage.Type.Temporary, + priority = WarningMessage.Priority.Warning, + listOf(WarningMessage.Location.MainScreen), + blockchains = null, + titleResId = R.string.alert_funds_restoration_message, + messageResId = R.string.alert_funds_restoration_message, + origin = WarningMessage.Origin.Local, + buttonTextId = R.string.warning_button_learn_more + ) + const val REMAINING_SIGNATURES_WARNING = 10 + + fun getRestoreFundsGuideUrl(locale: String): String { + val code = if (locale == Locale("ru").language) "ru" else "en" + return "https://tangem.com/$code/notion" + } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt index 94ee1e747e..5dcf4fba4a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt @@ -8,6 +8,7 @@ import com.tangem.common.card.Card import com.tangem.common.card.FirmwareVersion import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isTestCard +import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.extensions.isGreaterThan import com.tangem.tap.common.redux.global.GlobalState @@ -88,6 +89,9 @@ class WarningsMiddleware { addWarningMessage(WarningMessagesManager.testCardWarning(), autoUpdate = true) return@let } + if (card.useOldStyleDerivation) { + addWarningMessage(warning = WarningMessagesManager.restoreFundsWarning()) + } showWarningLowRemainingSignaturesIfNeeded(card) if (card.firmwareVersion.type != FirmwareVersion.FirmwareType.Release) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt index afcba036da..8dd0d76fc6 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt @@ -1,9 +1,11 @@ package com.tangem.tap.features.wallet.ui.adapters +import android.content.res.Resources import android.graphics.Rect import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.ConfigurationCompat import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView @@ -13,6 +15,7 @@ import com.tangem.tap.common.analytics.AnalyticsEvent import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.configurable.warningMessage.WarningMessage +import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.features.feedback.RateCanBeBetterEmail import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.store @@ -56,7 +59,9 @@ class WarningMessageVH(val binding: LayoutWarningBinding) : RecyclerView.ViewHol tvTitle.text = getString(warning.titleResId, warning.title) tvMessage.text = getString( - resId = warning.messageResId, default = warning.message, formatArgs = warning.messageFormatArg + resId = warning.messageResId, + default = warning.message, + formatArgs = warning.messageFormatArg ) } @@ -73,10 +78,13 @@ class WarningMessageVH(val binding: LayoutWarningBinding) : RecyclerView.ViewHol WarningMessage.Type.Permanent, WarningMessage.Type.TestCard -> { binding.groupControlsTemporary.hide() binding.groupControlsRating.hide() + binding.btnClose.hide() } WarningMessage.Type.Temporary -> { binding.groupControlsRating.hide() binding.groupControlsTemporary.show() + binding.btnClose.hide() + val buttonAction = when (warning.titleResId) { R.string.warning_important_security_info -> { @@ -84,6 +92,19 @@ class WarningMessageVH(val binding: LayoutWarningBinding) : RecyclerView.ViewHol store.dispatch(WalletAction.ShowDialog.SignedHashesMultiWalletDialog) } } + R.string.alert_funds_restoration_message -> { + binding.btnClose.show() + binding.btnClose.setOnClickListener { + store.dispatch(GlobalAction.HideWarningMessage(warning)) + } + val locale = ConfigurationCompat + .getLocales(Resources.getSystem().configuration) + .get(0) + val url = WarningMessagesManager.getRestoreFundsGuideUrl(locale.language) + View.OnClickListener { + store.dispatchOpenUrl(url) + } + } else -> { View.OnClickListener { store.dispatch(GlobalAction.HideWarningMessage(warning)) @@ -99,6 +120,7 @@ class WarningMessageVH(val binding: LayoutWarningBinding) : RecyclerView.ViewHol WarningMessage.Type.AppRating -> { binding.groupControlsTemporary.hide() binding.groupControlsRating.show() + binding.btnClose.show() val analyticsHandler = store.state.globalState.analyticsHandlers binding.btnClose.setOnClickListener { analyticsHandler?.triggerEvent(AnalyticsEvent.APP_RATING_DISMISS) diff --git a/app/src/main/res/layout/layout_warning.xml b/app/src/main/res/layout/layout_warning.xml index e2f6f41d6f..adab88869c 100644 --- a/app/src/main/res/layout/layout_warning.xml +++ b/app/src/main/res/layout/layout_warning.xml @@ -103,7 +103,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="visible" - app:constraint_referenced_ids="btn_close, btn_can_be_better, btn_really_cool" /> + app:constraint_referenced_ids="btn_can_be_better, btn_really_cool" /> diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 9fc6dd2a11..6753ad4f1b 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -40,6 +40,7 @@ Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Contract address copied! + Funds restoration instuction Custom diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index 9fc6dd2a11..6753ad4f1b 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -40,6 +40,7 @@ Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Contract address copied! + Funds restoration instuction Custom diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index 9fc6dd2a11..6753ad4f1b 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -40,6 +40,7 @@ Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Contract address copied! + Funds restoration instuction Custom diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 19b4411fba..9078737b3c 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -40,6 +40,7 @@ Доступные сети Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства. Адрес контракта скопирован! + Инструкция по восстановлению средств Пользовательский diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 9fc6dd2a11..6753ad4f1b 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -40,6 +40,7 @@ Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Contract address copied! + Funds restoration instuction Custom From 901bd78a9a5547331aec45b9e43530d9d0f5c9b2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 18:19:28 +0300 Subject: [PATCH 05/13] Updated on 2026-08-14 --- .../middlewares/MultiWalletMiddleware.kt | 19 +++++++----------- .../redux/middlewares/WalletMiddleware.kt | 20 ++++++++----------- .../redux/middlewares/WarningsMiddleware.kt | 3 ++- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index a5744bcfa7..193f133b26 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.wallet.redux.middlewares -import com.tangem.blockchain.blockchains.solana.SolanaWalletManager import com.tangem.blockchain.common.* import com.tangem.blockchain.extensions.Result import com.tangem.common.extensions.isZero @@ -130,17 +129,13 @@ class MultiWalletMiddleware { scope.launch(Dispatchers.Main) { val blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager) if (walletState?.getWalletData(blockchainNetwork) == null) { - store.dispatch( - WalletAction.MultiWallet.AddBlockchain( - blockchainNetwork, walletManager - ) - ) - store.dispatch( - WalletAction.LoadWallet.Success( - wallet = wallet, - blockchain = blockchainNetwork - ) - ) + store.dispatch(WalletAction.MultiWallet.AddBlockchain( + blockchainNetwork, walletManager + )) + store.dispatch(WalletAction.LoadWallet.Success( + wallet = wallet, + blockchain = blockchainNetwork + )) } } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index fb5468a689..c7528ad95f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -80,18 +80,14 @@ class WalletMiddleware { val coinAmount = action.wallet.amounts[AmountType.Coin]?.value if (coinAmount != null && !coinAmount.isZero()) { if (walletState.getWalletData(action.blockchain) == null) { - store.dispatch( - WalletAction.MultiWallet.AddBlockchain( - action.blockchain, - null - ) - ) - store.dispatch( - WalletAction.LoadWallet.Success( - action.wallet, - action.blockchain - ) - ) + store.dispatch(WalletAction.MultiWallet.AddBlockchain( + action.blockchain, + null + )) + store.dispatch(WalletAction.LoadWallet.Success( + action.wallet, + action.blockchain + )) } } store.dispatch(WalletAction.Warnings.CheckHashesCount.CheckHashesCountOnline) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt index 94ee1e747e..7f6e57d265 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt @@ -9,6 +9,7 @@ import com.tangem.common.card.FirmwareVersion import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.tap.common.analytics.AnalyticsEvent +import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.isGreaterThan import com.tangem.tap.common.redux.global.GlobalState import com.tangem.tap.domain.configurable.warningMessage.WarningMessage @@ -193,7 +194,7 @@ class WarningsMiddleware { } private fun setWarningMessages() { - store.dispatch(WalletAction.Warnings.Set(getWarnings())) + store.dispatchOnMain(WalletAction.Warnings.Set(getWarnings())) } private fun getWarnings(): List { From 5b5d38ccc4cfdcd20cb3fce522f55c3599c6361b Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 20:37:22 +0300 Subject: [PATCH 06/13] Updated on 2026-08-14 --- .../domain/common/form/FieldsValidators.kt | 21 ++++++++++++++++++- .../addCustomToken/redux/AddCustomTokenHub.kt | 5 ++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt b/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt index 431b0ff2af..259714abca 100644 --- a/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt +++ b/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt @@ -1,7 +1,9 @@ package com.tangem.domain.common.form import com.tangem.blockchain.blockchains.ethereum.EthereumAddressService +import com.tangem.blockchain.blockchains.solana.SolanaAddressService import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.address.AddressService import com.tangem.common.Validator import com.tangem.domain.AddCustomTokenError @@ -25,15 +27,32 @@ class StringIsNotEmptyValidator : CustomTokenValidator() { } class TokenContractAddressValidator : CustomTokenValidator() { + + private var blockchain: Blockchain = Blockchain.Unknown + + fun nextValidationFor(blockchain: Blockchain) { + this.blockchain = blockchain + } + override fun validate(data: String?): AddCustomTokenError? { if (data == null || data.isEmpty()) return AddCustomTokenError.FieldIsEmpty - return if (EthereumAddressService().validate(data)) { + return if (getAddressService().validate(data)) { null } else { AddCustomTokenError.InvalidContractAddress } } + + private fun getAddressService(): AddressService { + return when (blockchain) { + Blockchain.Solana, Blockchain.SolanaTestnet -> SolanaAddressService() + else -> { + if (blockchain.isEvm()) EthereumAddressService() + else throw UnsupportedOperationException() + } + } + } } class TokenNetworkValidator : CustomTokenValidator() { diff --git a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt index af0bdd7525..672abcec92 100644 --- a/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt +++ b/domain/src/main/java/com/tangem/domain/features/addCustomToken/redux/AddCustomTokenHub.kt @@ -413,7 +413,10 @@ internal class AddCustomTokenHub : BaseStoreHub("AddCustomT val decimalsValidator: TokenDecimalsValidator = state.getValidator(Decimals) val networkValidator: TokenNetworkValidator = state.getValidator(Network) return when (this) { - ContractAddress -> contractAddressValidator.validate(value as String) + ContractAddress -> { + contractAddressValidator.nextValidationFor(Network.getFieldValue()) + contractAddressValidator.validate(value as String) + } Network, DerivationPath -> networkValidator.validate(value as Blockchain) Name -> nameValidator.validate(value as String) Symbol -> symbolValidator.validate(value as String) From 588123f50c31b1b10e3c88287dbb79a1324d4dc5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 20:38:06 +0300 Subject: [PATCH 07/13] Updated on 2026-08-14 --- .../tokens/addCustomToken/compose/DebugActions.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt index c9b231783d..1bbbce94ce 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt @@ -47,10 +47,10 @@ fun AddCustomTokenDebugActions() { @Composable private fun AllInOne() { // validation error - ContractAddressButton( - name = "invalid", - address = "unk" - ) +// ContractAddressButton( +// name = "invalid", +// address = "unk" +// ) // active = true ContractAddressButton( name = "true", @@ -71,6 +71,10 @@ private fun AllInOne() { name = "unknown", address = "0x1111111111111111112111111111111111111113" ) + ContractAddressButton( + name = "solana", + address = "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB" + ) } @Composable From a8975ac38b2322d884c3545e5f0a0f14bddaaaa9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 19 Apr 2022 21:46:12 +0300 Subject: [PATCH 08/13] Updated on 2026-08-14 --- .../com/tangem/tap/common/compose/Warning.kt | 53 +++++++++++++++++++ .../compose/AddCustomTokenScreen.kt | 20 +++---- .../domain/common/form/FieldsValidators.kt | 8 ++- 3 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/compose/Warning.kt diff --git a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt new file mode 100644 index 0000000000..8ea4eceef2 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt @@ -0,0 +1,53 @@ +package com.tangem.tap.common.compose + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.tangem.common.module.ModuleMessage +import com.tangem.tap.common.moduleMessage.ModuleMessageConverter +import com.tangem.wallet.R + +/** +[REDACTED_AUTHOR] + */ +@Composable +fun AddCustomTokenWarning( + modifier: Modifier = Modifier, + warning: ModuleMessage, + converter: ModuleMessageConverter +) { + Surface( + modifier = modifier, + shape = MaterialTheme.shapes.small, + color = colorResource(id = R.color.warning_warning), + elevation = 4.dp, + ) { + Column( + modifier = Modifier.padding(16.dp), + ) { + Text( + text = stringResource(id = R.string.common_warning), + color = colorResource(id = R.color.white), + fontSize = 14.sp, + fontWeight = FontWeight.Bold + ) + SpacerH8() + Text( + text = converter.convert(warning), + color = colorResource(id = R.color.white), + fontSize = 13.sp, + lineHeight = 18.sp + ) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt index ea27e5137f..8463eba5ac 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.tangem.domain.AddCustomTokenError import com.tangem.domain.common.form.DataField import com.tangem.domain.common.form.FieldId @@ -22,6 +21,7 @@ import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenState import com.tangem.domain.features.addCustomToken.redux.ScreenState import com.tangem.domain.features.addCustomToken.redux.ViewStates import com.tangem.domain.redux.domainStore +import com.tangem.tap.common.compose.AddCustomTokenWarning import com.tangem.tap.common.compose.ComposeDialogManager import com.tangem.tap.common.compose.ToggledRippleTheme import com.tangem.tap.common.compose.keyboardAsState @@ -51,7 +51,7 @@ fun AddCustomTokenScreen(state: MutableState) { LazyColumn( contentPadding = PaddingValues(bottom = 90.dp) ) { -// item { AddCustomTokenDebugActions() } + item { AddCustomTokenDebugActions() } item { Surface( modifier = Modifier.padding(16.dp), @@ -110,19 +110,11 @@ fun Warnings(warnings: List) { warnings.lastIndex -> Modifier.padding(16.dp, 8.dp, 16.dp, 16.dp) else -> Modifier.padding(16.dp, 8.dp, 16.dp, 0.dp) } - Surface( + AddCustomTokenWarning( modifier = modifier.fillMaxWidth(), - shape = MaterialTheme.shapes.small, - color = colorResource(id = R.color.warning_warning), - elevation = 4.dp, - ) { - Text( - modifier = Modifier.padding(16.dp), - text = warningConverter.convert(item), - color = colorResource(id = R.color.white), - fontSize = 14.sp - ) - } + warning = item, + converter = warningConverter + ) } } } diff --git a/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt b/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt index 259714abca..f526b968ab 100644 --- a/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt +++ b/domain/src/main/java/com/tangem/domain/common/form/FieldsValidators.kt @@ -47,9 +47,13 @@ class TokenContractAddressValidator : CustomTokenValidator() { private fun getAddressService(): AddressService { return when (blockchain) { Blockchain.Solana, Blockchain.SolanaTestnet -> SolanaAddressService() + Blockchain.Unknown -> EthereumAddressService() else -> { - if (blockchain.isEvm()) EthereumAddressService() - else throw UnsupportedOperationException() + if (blockchain.isEvm()) { + EthereumAddressService() + } else { + throw UnsupportedOperationException() + } } } } From 13851ef9991d30af2643d420c19f59d33e3ef6a1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Apr 2022 10:45:51 +0400 Subject: [PATCH 09/13] Updated on 2026-08-14 --- .../tangem/tap/features/wallet/ui/WalletDetailsFragment.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 f10f7820af..1006df572c 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 @@ -54,9 +54,7 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), override fun onStart() { super.onStart() store.subscribe(this) { state -> - state.skipRepeats { oldState, newState -> - oldState.walletState == newState.walletState - }.select { it.walletState } + state.select { it.walletState } } } From bd1eea292cfc257c42ccf084067b929d70b7571d Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Apr 2022 11:19:10 +0400 Subject: [PATCH 10/13] Updated on 2026-08-14 --- .../ui/compose/CollapsedCurrencyItem.kt | 36 +++++++++++++--- .../features/tokens/ui/compose/NetworkItem.kt | 42 ++++++++++++++----- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CollapsedCurrencyItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CollapsedCurrencyItem.kt index e4b3810766..19de899ac1 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CollapsedCurrencyItem.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/CollapsedCurrencyItem.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.tokens.ui.compose import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape @@ -71,6 +72,7 @@ fun CollapsedCurrencyItem( if (contract.address == currency.symbol) { BlockchainNetworkItem( blockchain = Blockchain.fromNetworkId(contract.networkId), + isMainNetwork = true, addedBlockchains = addedBlockchains ) } else { @@ -95,6 +97,7 @@ fun CollapsedCurrencyItem( } else { BlockchainNetworkItem( blockchain = blockchain, + isMainNetwork = false, addedBlockchains = addedBlockchains ) } @@ -114,18 +117,39 @@ fun CollapsedCurrencyItem( @Composable fun BlockchainNetworkItem( blockchain: Blockchain?, + isMainNetwork: Boolean, addedBlockchains: List ) { val added = addedBlockchains.contains(blockchain) val icon = if (added) blockchain?.getRoundIconRes() else blockchain?.getGreyedOutIconRes() if (icon != null) { - Image( - painter = painterResource(id = icon), - contentDescription = null, - Modifier - .size(20.dp) - ) + Box(Modifier + .size(20.dp)) { + Image( + painter = painterResource(id = icon), + contentDescription = null, + Modifier + .size(20.dp) + ) + if (isMainNetwork) { + Box( + modifier = Modifier + .align(Alignment.TopEnd) + .size(7.dp) + .clip(CircleShape) + .background(Color.White) + ) { + Box( + modifier = Modifier + .align(Alignment.Center) + .size(5.dp) + .clip(CircleShape) + .background(Color(0xFF1ACE80)) + ) + } + } + } Spacer(modifier = Modifier.size(5.dp)) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/NetworkItem.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/NetworkItem.kt index bdb5107ae2..1c6f8e74c3 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/NetworkItem.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/compose/NetworkItem.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.tokens.ui.compose import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* @@ -53,17 +54,36 @@ fun NetworkItem( interactionSource = remember { MutableInteractionSource() } ) ) { - SubcomposeAsyncImage( - model = if (added) blockchain.getRoundIconRes() else blockchain.getGreyedOutIconRes(), - contentDescription = blockchain.fullName, - loading = { CurrencyPlaceholderIcon(blockchain.id) }, - error = { CurrencyPlaceholderIcon(blockchain.id) }, - modifier = Modifier - .clip(CircleShape) - .padding(start = 8.dp, top = 16.dp, bottom = 16.dp, end = 6.dp) - .size(20.dp) - .align(Alignment.CenterVertically) - ) + Box(modifier = Modifier + .align(Alignment.CenterVertically) + .padding(start = 8.dp, top = 16.dp, bottom = 16.dp, end = 6.dp) + ) { + SubcomposeAsyncImage( + model = if (added) blockchain.getRoundIconRes() else blockchain.getGreyedOutIconRes(), + contentDescription = blockchain.fullName, + loading = { CurrencyPlaceholderIcon(blockchain.id) }, + error = { CurrencyPlaceholderIcon(blockchain.id) }, + modifier = Modifier + .size(20.dp) + ) + if (isBlockchain) { + Box( + modifier = Modifier + .align(Alignment.TopEnd) + .size(7.dp) + .clip(CircleShape) + .background(Color.White) + ) { + Box( + modifier = Modifier + .align(Alignment.Center) + .size(5.dp) + .clip(CircleShape) + .background(Color(0xFF1ACE80)) + ) + } + } + } Row( modifier = Modifier .fillMaxHeight() From 789d57631b55f83b176d8f851d2a9ecc38fcd24b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Apr 2022 13:03:53 +0400 Subject: [PATCH 11/13] Updated on 2026-08-14 --- .../com/tangem/tap/features/wallet/redux/WalletAction.kt | 2 ++ .../wallet/redux/middlewares/WarningsMiddleware.kt | 5 ++++- .../wallet/ui/adapters/WarningMessagesAdapter.kt | 1 + .../com/tangem/tap/persistence/PreferencesStorage.kt | 9 +++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 03c58d7f42..be4d9c7bab 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -91,6 +91,8 @@ sealed class WalletAction : Action { } class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings() + + object RestoreFundsWarningClosed : Warnings() } data class LoadFiatRate( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt index 2e361962ed..5197928d6e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WarningsMiddleware.kt @@ -66,6 +66,9 @@ class WarningsMiddleware { ) } } + is WalletAction.Warnings.RestoreFundsWarningClosed -> { + preferencesStorage.saveRestoreFundsWarningClosed() + } } } @@ -90,7 +93,7 @@ class WarningsMiddleware { addWarningMessage(WarningMessagesManager.testCardWarning(), autoUpdate = true) return@let } - if (card.useOldStyleDerivation) { + if (card.useOldStyleDerivation && !preferencesStorage.wasRestoreFundsWarningClosed()) { addWarningMessage(warning = WarningMessagesManager.restoreFundsWarning()) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt index 8dd0d76fc6..f3084472e8 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WarningMessagesAdapter.kt @@ -96,6 +96,7 @@ class WarningMessageVH(val binding: LayoutWarningBinding) : RecyclerView.ViewHol binding.btnClose.show() binding.btnClose.setOnClickListener { store.dispatch(GlobalAction.HideWarningMessage(warning)) + store.dispatch(WalletAction.Warnings.RestoreFundsWarningClosed) } val locale = ConfigurationCompat .getLocales(Resources.getSystem().configuration) diff --git a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt index 7bee7c8c6f..edc53e26fb 100644 --- a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt @@ -64,12 +64,21 @@ class PreferencesStorage(applicationContext: Application) { preferences.edit { putInt(APP_LAUNCH_COUNT_KEY, ++count) } } + fun wasRestoreFundsWarningClosed(): Boolean { + return preferences.getBoolean(RESTORE_FUNDS_CLOSED_KEY, false) + } + + fun saveRestoreFundsWarningClosed() { + preferences.edit { putBoolean(RESTORE_FUNDS_CLOSED_KEY, true) } + } + companion object { private const val PREFERENCES_NAME = "tapPrefs" private const val APP_CURRENCY_KEY = "appCurrency" private const val DISCLAIMER_ACCEPTED_KEY = "disclaimerAccepted" private const val TWINS_ONBOARDING_SHOWN_KEY = "twinsOnboardingShown" private const val APP_LAUNCH_COUNT_KEY = "launchCount" + private const val RESTORE_FUNDS_CLOSED_KEY = "restoreFundsClosed" } } From 2d98489526ffad19f3aefd2de26f07e03a42b627 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Apr 2022 13:02:30 +0300 Subject: [PATCH 12/13] Updated on 2026-08-14 --- .../com/tangem/tap/domain/TapWalletManager.kt | 39 ---------------- .../tap/features/wallet/redux/WalletAction.kt | 2 + .../tap/features/wallet/redux/WalletState.kt | 9 ++-- .../redux/middlewares/WalletMiddleware.kt | 46 +++++++++++++++++++ .../wallet/redux/reducers/WalletReducer.kt | 9 ++++ 5 files changed, 63 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 7605a39ee5..611ecbfb50 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -1,6 +1,5 @@ package com.tangem.tap.domain -import com.tangem.blockchain.blockchains.solana.RentProvider import com.tangem.blockchain.common.* import com.tangem.common.extensions.guard import com.tangem.common.services.Result @@ -15,7 +14,6 @@ import com.tangem.tap.common.ThrottlerWithValues import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.safeUpdate -import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.redux.global.FiatCurrencyName import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.currenciesRepository @@ -25,8 +23,6 @@ import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.domain.extensions.makeWalletManagersForApp import com.tangem.tap.domain.tokens.BlockchainNetwork import com.tangem.tap.features.demo.isDemoCard -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity @@ -60,7 +56,6 @@ class TapWalletManager { } when (result) { is Result.Success -> { - checkForRentWarning(walletManager) dispatchOnMain(WalletAction.LoadWallet.Success(result.data, blockchainNetwork)) } is Result.Failure -> { @@ -329,40 +324,6 @@ class TapWalletManager { else -> null } } - - private suspend fun checkForRentWarning(walletManager: WalletManager) { - val rentProvider = walletManager as? RentProvider ?: return - - when (val result = rentProvider.minimalBalanceForRentExemption()) { - is com.tangem.blockchain.extensions.Result.Success -> { - fun isNeedToShowWarning(balance: BigDecimal, rentExempt: BigDecimal): Boolean = - balance < rentExempt - - val balance = walletManager.wallet.fundsAvailable(AmountType.Coin) - val outgoingTxs = - walletManager.wallet.getPendingTransactions(PendingTransactionType.Outgoing) - val rentExempt = result.data - val show = if (outgoingTxs.isEmpty()) { - isNeedToShowWarning(balance, rentExempt) - } else { - val outgoingAmount = outgoingTxs.sumOf { it.amount ?: BigDecimal.ZERO } - val rest = balance.minus(outgoingAmount) - isNeedToShowWarning(rest, rentExempt) - } - if (!show) return - - val currency = walletManager.wallet.blockchain.currency - dispatchOnMain( - WalletAction.SetWalletRent( - blockchain = BlockchainNetwork.fromWalletManager(walletManager), - minRent = ("${rentProvider.rentAmount().stripZeroPlainString()} $currency"), - rentExempt = ("${rentExempt.stripZeroPlainString()} $currency") - ) - ) - } - is com.tangem.blockchain.extensions.Result.Failure -> {} - } - } } fun Wallet.getFirstToken(): Token? { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 03c58d7f42..77549829d7 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -159,4 +159,6 @@ sealed class WalletAction : Action { val minRent: String, val rentExempt: String ) : WalletAction() + + data class RemoveWalletRent(val blockchain: BlockchainNetwork) : WalletAction() } \ 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 8ad7344077..de5d1ee593 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 @@ -395,6 +395,9 @@ sealed interface Currency { return derivationPath != blockchain.derivationPath(derivationStyle)?.rawPath } + fun isBlockchain(): Boolean = this is Blockchain + + fun isToken(): Boolean = this is Token companion object { fun fromBlockchainNetwork( @@ -402,13 +405,13 @@ sealed interface Currency { token: com.tangem.blockchain.common.Token? = null ): Currency { return if (token != null) { - Currency.Token( + Token( token = token, blockchain = blockchainNetwork.blockchain, derivationPath = blockchainNetwork.derivationPath ) } else { - Currency.Blockchain( + Blockchain( blockchain = blockchainNetwork.blockchain, derivationPath = blockchainNetwork.derivationPath ) @@ -430,7 +433,7 @@ sealed interface Currency { } fun fromTokenWithBlockchain(tokenWithBlockchain: TokenWithBlockchain): Token { - return Currency.Token( + return Token( token = tokenWithBlockchain.token, blockchain = tokenWithBlockchain.blockchain, derivationPath = null diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index c7528ad95f..428ef7b4b5 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -3,8 +3,10 @@ package com.tangem.tap.features.wallet.redux.middlewares import android.content.Intent import android.net.Uri import androidx.core.content.ContextCompat +import com.tangem.blockchain.blockchains.solana.RentProvider import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.WalletManager import com.tangem.common.CompletionResult import com.tangem.common.core.TangemSdkError import com.tangem.common.extensions.isZero @@ -20,9 +22,12 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.extensions.toSendableAmounts +import com.tangem.tap.domain.tokens.BlockchainNetwork import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.send.redux.PrepareSendScreen +import com.tangem.tap.features.wallet.models.PendingTransactionType +import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.redux.* import com.tangem.tap.network.NetworkStateChanged import com.tangem.tap.scope @@ -34,6 +39,7 @@ import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction import org.rekotlin.Middleware +import java.math.BigDecimal class WalletMiddleware { private val tradeCryptoMiddleware = TradeCryptoMiddleware() @@ -77,6 +83,7 @@ class WalletMiddleware { } } is WalletAction.LoadWallet.Success -> { + checkForRentWarning(walletState.getWalletManager(action.blockchain)) val coinAmount = action.wallet.amounts[AmountType.Coin]?.value if (coinAmount != null && !coinAmount.isZero()) { if (walletState.getWalletData(action.blockchain) == null) { @@ -289,4 +296,43 @@ class WalletMiddleware { tokenRate = tokenRate ) } + + private fun checkForRentWarning(walletManager: WalletManager?) { + val rentProvider = walletManager as? RentProvider ?: return + + scope.launch { + when (val result = rentProvider.minimalBalanceForRentExemption()) { + is com.tangem.blockchain.extensions.Result.Success -> { + fun isNeedToShowWarning(balance: BigDecimal, rentExempt: BigDecimal): Boolean { + return balance < rentExempt + } + + val balance = walletManager.wallet.fundsAvailable(AmountType.Coin) + val outgoingTxs = walletManager.wallet.getPendingTransactions(PendingTransactionType.Outgoing) + val rentExempt = result.data + val show = if (outgoingTxs.isEmpty()) { + isNeedToShowWarning(balance, rentExempt) + } else { + val outgoingAmount = outgoingTxs.sumOf { it.amount ?: BigDecimal.ZERO } + val rest = balance.minus(outgoingAmount) + isNeedToShowWarning(rest, rentExempt) + } + + val currency = walletManager.wallet.blockchain.currency + if (show) { + dispatchOnMain(WalletAction.SetWalletRent( + blockchain = BlockchainNetwork.fromWalletManager(walletManager), + minRent = ("${rentProvider.rentAmount().stripZeroPlainString()} $currency"), + rentExempt = ("${rentExempt.stripZeroPlainString()} $currency") + )) + } else { + dispatchOnMain(WalletAction.RemoveWalletRent( + blockchain = BlockchainNetwork.fromWalletManager(walletManager), + )) + } + } + is com.tangem.blockchain.extensions.Result.Failure -> {} + } + } + } } 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 35fab475ae..97e6e778ec 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 @@ -314,6 +314,15 @@ private fun internalReduce(action: Action, state: AppState): WalletState { newState = newState.updateWalletsData(listOf(walletData)) } } + is WalletAction.RemoveWalletRent -> { + var walletData = newState.getWalletData(action.blockchain) + if (walletData == null) { + newState + } else { + walletData = walletData.copy(warningRent = null) + newState = newState.updateWalletsData(listOf(walletData)) + } + } } return newState } From a75226b865ab0663068fac897aac65468f079bbb Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 20 Apr 2022 13:09:57 +0300 Subject: [PATCH 13/13] Updated on 2026-08-14 --- app/build.gradle | 28 ++++-- .../com/tangem/tap/common/DialogManager.kt | 1 + .../java/com/tangem/tap/common/TestActions.kt | 75 +++++++++++++++ .../tap/common/extensions/WalletManager.kt | 4 +- .../tangem/tap/common/redux/StateDialog.kt | 5 + .../compose/AddCustomTokenScreen.kt | 3 +- .../TestAddCostomTokenActions.kt} | 6 +- .../wallet/ui/WalletDetailsFragment.kt | 26 +++-- .../ui/test/TestWalletDetailsActions.kt | 94 +++++++++++++++++++ 9 files changed, 222 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/TestActions.kt rename app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/{DebugActions.kt => test/TestAddCostomTokenActions.kt} (98%) create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt diff --git a/app/build.gradle b/app/build.gradle index 78402e567b..bd37eb2e39 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,11 @@ apply plugin: 'kotlin-kapt' apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' +ext.configVar = [ + configEnvironment: "CONFIG_ENVIRONMENT", + testActionEnabled: "TEST_ACTION_ENABLED", +] + android { compileSdkVersion 31 defaultConfig { @@ -13,19 +18,14 @@ android { minSdkVersion 21 targetSdkVersion 31 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + buildConfigField 'Boolean', configVar.testActionEnabled, 'false' } buildFeatures { compose true viewBinding true } buildTypes { - release { - debuggable false - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.debug - buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"prod\"' - } debug { debuggable true minifyEnabled false @@ -34,14 +34,24 @@ android { firebaseCrashlytics { mappingFileUploadEnabled false } - buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"dev\"' + buildConfigField 'String', configVar.configEnvironment, '\"dev\"' + buildConfigField 'Boolean', configVar.testActionEnabled, 'true' } debug_beta { initWith release debuggable false versionNameSuffix "-beta" applicationIdSuffix ".debug" - buildConfigField 'String', 'CONFIG_ENVIRONMENT', '\"prod\"' + buildConfigField 'String', configVar.configEnvironment, '\"prod\"' + buildConfigField 'Boolean', configVar.testActionEnabled, 'false' + } + release { + debuggable false + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.debug + buildConfigField 'String', configVar.configEnvironment, '\"prod\"' + buildConfigField 'Boolean', configVar.testActionEnabled, 'false' } } kotlinOptions { diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index 56ce4dd062..ac00ee4f88 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -53,6 +53,7 @@ class DialogManager : StoreSubscriber { is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context) is AppDialog.ScanFailsDialog -> ScanFailsDialog.create(context) is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context) + is AppDialog.TestActionsDialog -> TestActionsBottomSheetDialog(state.dialog, context) is TwinCardsAction.Wallet.ShowInterruptDialog -> CreateWalletInterruptDialog.create(state.dialog, context) is WalletConnectDialog.UnsupportedCard -> SimpleAlertDialog.create( diff --git a/app/src/main/java/com/tangem/tap/common/TestActions.kt b/app/src/main/java/com/tangem/tap/common/TestActions.kt new file mode 100644 index 0000000000..d5939dae64 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/TestActions.kt @@ -0,0 +1,75 @@ +package com.tangem.tap.common + +import android.content.Context +import android.os.Bundle +import android.view.View +import android.widget.Button +import androidx.appcompat.widget.LinearLayoutCompat +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog +import com.tangem.tap.common.extensions.dispatchDialogHide +import com.tangem.tap.common.extensions.dispatchDialogShow +import com.tangem.tap.common.extensions.show +import com.tangem.tap.common.redux.AppDialog +import com.tangem.tap.store +import com.tangem.wallet.BuildConfig + +/** +[REDACTED_AUTHOR] + */ + +object TestActions { + + // It used only for the test actions in debug or debug_beta builds + var testAmountInjectionForWalletManagerEnabled = false + + /** + * @param isTestView - true must be used if you want to show or hide your view depends on BuildConfig + */ + fun initFor(view: View, actions: List, isTestView: Boolean = false) { + if (isTestView) view.show(BuildConfig.TEST_ACTION_ENABLED) + if (!BuildConfig.TEST_ACTION_ENABLED) return + + view.setOnClickListener { + store.dispatchDialogShow(AppDialog.TestActionsDialog(actions)) + } + } +} + +typealias TestAction = Pair Unit> + +class TestActionsBottomSheetDialog( + private val appDialog: AppDialog.TestActionsDialog, + context: Context +) : BottomSheetDialog(context) { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(createContentView()) + behavior.state = BottomSheetBehavior.STATE_EXPANDED + behavior.peekHeight = 400 + setOnCancelListener { + store.dispatchDialogHide() + } + } + + private fun createContentView(): View { + val actionButtons = mutableListOf() + appDialog.actionsList.forEach { (actionName, action) -> + val view = Button(context).apply { + text = actionName + setOnClickListener { + action() + cancel() + } + } + actionButtons.add(view) + } + + return LinearLayoutCompat(context).apply { + orientation = LinearLayoutCompat.VERTICAL + actionButtons.forEach { addView(it) } + } + } +} \ No newline at end of file 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 0adf835be5..540d23c3f7 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 @@ -4,6 +4,7 @@ import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.common.services.Result +import com.tangem.tap.common.TestActions import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.amountToCreateAccount import com.tangem.tap.domain.getFirstToken @@ -20,8 +21,9 @@ import timber.log.Timber [REDACTED_AUTHOR] */ suspend fun WalletManager.safeUpdate(): Result = try { - if (isDemoWallet()) { + if (isDemoWallet() || TestActions.testAmountInjectionForWalletManagerEnabled) { delay(500) + TestActions.testAmountInjectionForWalletManagerEnabled = false Result.Success(wallet) } else { update() diff --git a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt index 6419e09ac2..77f99b84b5 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt @@ -1,6 +1,7 @@ package com.tangem.tap.common.redux import com.tangem.common.extensions.VoidCallback +import com.tangem.tap.common.TestAction import com.tangem.tap.features.wallet.redux.AddressData import com.tangem.tap.features.wallet.redux.Currency @@ -17,4 +18,8 @@ sealed class AppDialog : StateDialog { val currency: Currency, val addressData: AddressData, ) : AppDialog() + + data class TestActionsDialog( + val actionsList: List + ) : AppDialog() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt index 8463eba5ac..d9736ae8d0 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt @@ -26,6 +26,7 @@ import com.tangem.tap.common.compose.ComposeDialogManager import com.tangem.tap.common.compose.ToggledRippleTheme import com.tangem.tap.common.compose.keyboardAsState import com.tangem.tap.common.moduleMessage.ModuleMessageConverter +import com.tangem.tap.features.tokens.addCustomToken.compose.test.TestAddCustomTokenActions import com.tangem.wallet.R /** @@ -51,7 +52,7 @@ fun AddCustomTokenScreen(state: MutableState) { LazyColumn( contentPadding = PaddingValues(bottom = 90.dp) ) { - item { AddCustomTokenDebugActions() } + item { TestAddCustomTokenActions() } item { Surface( modifier = Modifier.padding(16.dp), diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/TestAddCostomTokenActions.kt similarity index 98% rename from app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt rename to app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/TestAddCostomTokenActions.kt index 1bbbce94ce..981e2a1b74 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/DebugActions.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/test/TestAddCostomTokenActions.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.features.tokens.addCustomToken.compose +package com.tangem.tap.features.tokens.addCustomToken.compose.test import androidx.compose.foundation.layout.* import androidx.compose.material.Button @@ -25,8 +25,8 @@ import timber.log.Timber [REDACTED_AUTHOR] */ @Composable -fun AddCustomTokenDebugActions() { - if (!BuildConfig.DEBUG) return +fun TestAddCustomTokenActions() { + if (!BuildConfig.TEST_ACTION_ENABLED) return Column() { // deep test 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 1006df572c..2c1fa686cd 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 @@ -15,6 +15,7 @@ import by.kirich1409.viewbindingdelegate.viewBinding import com.squareup.picasso.Picasso import com.tangem.common.extensions.guard import com.tangem.tap.common.SnackbarHandler +import com.tangem.tap.common.TestActions import com.tangem.tap.common.extensions.* import com.tangem.tap.common.redux.StateDialog import com.tangem.tap.common.redux.navigation.NavigationAction @@ -24,6 +25,7 @@ import com.tangem.tap.features.wallet.models.PendingTransaction import com.tangem.tap.features.wallet.redux.* import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendDialog +import com.tangem.tap.features.wallet.ui.test.TestWalletDetails import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.FragmentWalletDetailsBinding @@ -68,12 +70,11 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), (activity as? AppCompatActivity)?.setSupportActionBar(binding.toolbar) binding.toolbar.setNavigationOnClickListener { activity?.onBackPressed() } - setupTransactionsRecyclerView() setupButtons() + setupTestActionButton() } - private fun setupTransactionsRecyclerView() = with(binding) { pendingTransactionAdapter = PendingTransactionsAdapter() rvPendingTransaction.layoutManager = LinearLayoutManager(requireContext()) @@ -91,6 +92,15 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), btnSell.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Sell) } } + private fun setupTestActionButton() { + view?.findViewById(R.id.l_balance)?.let { view -> + TestActions.initFor( + view = view, + actions = TestWalletDetails.solanaRentExemptWarning() + ) + } + } + override fun newState(state: WalletState) { if (activity == null || view == null) return if (state.selectedCurrency == null) return @@ -111,11 +121,13 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), binding.srlWalletDetails.setOnRefreshListener { if (selectedWallet.currencyData.status != BalanceStatus.Loading) { - store.dispatch( - WalletAction.LoadWallet( - blockchain = BlockchainNetwork(selectedWallet.currency.blockchain, selectedWallet.currency.derivationPath, emptyList()) + store.dispatch(WalletAction.LoadWallet( + blockchain = BlockchainNetwork( + selectedWallet.currency.blockchain, + selectedWallet.currency.derivationPath, + emptyList() ) - ) + )) } } @@ -163,6 +175,8 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } private fun handleNotEnoughFundsOnMainCurrency(selectedWalletData: WalletData) = with(binding) { + if (selectedWalletData.currency.isBlockchain()) return@with + if (selectedWalletData.shouldShowCoinAmountWarning()) { val blockchainName = selectedWalletData.currency.blockchain.fullName val warningMessage = requireContext().getString( diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt new file mode 100644 index 0000000000..1c32663fc8 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/test/TestWalletDetailsActions.kt @@ -0,0 +1,94 @@ +package com.tangem.tap.features.wallet.ui.test + +import com.tangem.blockchain.blockchains.solana.SolanaWalletManager +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.Blockchain +import com.tangem.domain.common.ScanResponse +import com.tangem.domain.common.TapWorkarounds.isTestCard +import com.tangem.tap.common.TestAction +import com.tangem.tap.common.TestActions +import com.tangem.tap.domain.tokens.BlockchainNetwork +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.store +import java.math.BigDecimal +import kotlin.random.Random + +/** +[REDACTED_AUTHOR] + */ +class TestWalletDetails { + companion object { + fun solanaRentExemptWarning(): List { + val checker = SolanaRentWarningActionEmitter() + return listOf( + "BALANCE = 0.0" to { checker.setZeroBalance() }, + "BALANCE < 0.00089088" to { checker.setLessThanRentExempt() }, + "BALANCE > 0.00089088" to { checker.setMoreThanRentExempt() }, + "BALANCE = 0.00089087" to { checker.setLessThanRentExemptByOne() }, + "BALANCE = 0.00089088 (rent exempt)" to { checker.setForRentExemptBarrier() }, + "BALANCE = 0.00089089" to { checker.setMoreThanRentExemptByOne() }, + ) + } + } +} + +private class SolanaRentWarningActionEmitter { + + private val zero = BigDecimal.ZERO + private val one = BigDecimal(0.00000001) + private val rentExemptBarrier = BigDecimal(0.00089088) + private val lessThanRentExemptByOne = rentExemptBarrier.minus(one) + private val moreThanRentExemptByOne = rentExemptBarrier.plus(one) + private val moreThanRentExempt = rentExemptBarrier.plus(Random.nextDouble().toBigDecimal()) + private val lessThanRentExempt = rentExemptBarrier + .minus(Random.nextDouble(0.0, rentExemptBarrier.minus(one).toDouble()).toBigDecimal()) + + fun setZeroBalance() { + setBalance(zero) + } + + fun setForRentExemptBarrier() { + setBalance(rentExemptBarrier) + } + + fun setLessThanRentExemptByOne() { + setBalance(lessThanRentExemptByOne) + } + + fun setMoreThanRentExemptByOne() { + setBalance(moreThanRentExemptByOne) + } + + fun setMoreThanRentExempt() { + setBalance(moreThanRentExempt) + } + + fun setLessThanRentExempt() { + setBalance(lessThanRentExempt) + } + + private fun setBalance(value: BigDecimal) { + val amount = Amount(getBlockchain()).copy(value = value) + getWalletManager().apply { + TestActions.testAmountInjectionForWalletManagerEnabled = true + wallet.setAmount(amount) + } + store.dispatch(WalletAction.LoadData) + } + + private fun getWalletManager(): SolanaWalletManager { + return store.state.walletState.getWalletManager(BlockchainNetwork( + blockchain = getBlockchain(), + card = scanResponse().card + )) as SolanaWalletManager + } + + private fun getBlockchain(): Blockchain = when { + scanResponse().card.isTestCard -> Blockchain.SolanaTestnet + else -> Blockchain.Solana + } + + private fun scanResponse(): ScanResponse { + return store.state.globalState.scanResponse ?: throw UnsupportedOperationException() + } +} \ No newline at end of file