From 5d13f006d84fb0719e20869e74fe8806b62ab4dc Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Aug 2022 12:35:41 +0400 Subject: [PATCH 01/15] Updated on 2026-08-14 --- .../tap/domain/walletconnect/WalletConnectNetworkUtils.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt index 3da00c517b..6b2a457e43 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectNetworkUtils.kt @@ -12,6 +12,9 @@ class WalletConnectNetworkUtils { peer: WCPeerMeta, ): Blockchain? { return when { + peer.url.contains("pancakeswap.finance") -> { + Blockchain.BSC + } chainId != null -> { Blockchain.fromChainId(chainId) } From 122a8ead52e11bd07a1ec6d69aca56fc463c2bde Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Aug 2022 12:37:59 +0400 Subject: [PATCH 02/15] Updated on 2026-08-14 --- .../tap/features/details/redux/DetailsMiddleware.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 7825d58a8f..a465940186 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -98,14 +98,16 @@ class DetailsMiddleware { fun handle(action: DetailsAction.ResetToFactory) { when (action) { is DetailsAction.ResetToFactory.Start -> { - store.dispatch(NavigationAction.NavigateTo(AppScreen.ResetToFactory)) - } - is DetailsAction.ResetToFactory.Proceed -> { val card = store.state.detailsState.cardSettingsState?.card ?: return if (card.isTangemTwins()) { store.dispatch(DetailsAction.ReCreateTwinsWallet) return + } else { + store.dispatch(NavigationAction.NavigateTo(AppScreen.ResetToFactory)) } + } + is DetailsAction.ResetToFactory.Proceed -> { + val card = store.state.detailsState.cardSettingsState?.card ?: return scope.launch { val result = tangemSdkManager.resetToFactorySettings(card) withContext(Dispatchers.Main) { From e942dcb6c99d9cbe72debe7eb2673edf6402a467 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Aug 2022 12:39:22 +0400 Subject: [PATCH 03/15] Updated on 2026-08-14 --- .../details/redux/walletconnect/WalletConnectMiddleware.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index d98fb0b0f5..d209c6d1f8 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -222,7 +222,10 @@ class WalletConnectMiddleware { val blockchain = WalletConnectNetworkUtils.parseBlockchain( chainId = chainId, peer = session.peerMeta, - ) ?: Blockchain.Ethereum + ).guard { + store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork)) + return + } store.dispatch( GlobalAction.ScanCard( From 2621bad76b33699b12b1dc2ee51dced74e12a36c Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 31 Aug 2022 11:10:38 +0400 Subject: [PATCH 04/15] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 3 - .../com/tangem/tap/common/DialogManager.kt | 1 - .../com/tangem/tap/domain/TapWalletManager.kt | 7 +- .../walletconnect/WalletConnectManager.kt | 14 ++- .../walletconnect/WalletConnectSdkHelper.kt | 6 +- .../walletconnect/WcWalletManagerFactory.kt | 48 ++------- .../walletconnect/WalletConnectAction.kt | 7 +- .../walletconnect/WalletConnectMiddleware.kt | 102 ++++++++---------- .../walletconnect/WalletConnectReducer.kt | 1 + .../redux/walletconnect/WalletConnectState.kt | 6 +- .../ui/walletconnect/SessionsAdapter.kt | 55 ---------- .../ui/walletconnect/WalletConnectScreen.kt | 1 - .../walletconnect/WalletConnectScreenState.kt | 2 - .../dialogs/ApproveWcSessionDialog.kt | 1 - .../dialogs/BnbTransactionDialog.kt | 3 +- .../dialogs/PersonalSignDialog.kt | 11 +- .../dialogs/TransactionDialog.kt | 2 - .../ui/walletconnect/dialogs/WcDialog.kt | 1 - app/src/main/res/values-ru/strings.xml | 8 +- .../main/res/values/strings_untranslated.xml | 24 ++--- 20 files changed, 100 insertions(+), 203 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/SessionsAdapter.kt diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index a005e3f952..6a80a26d24 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -4,7 +4,6 @@ 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 @@ -26,7 +25,6 @@ import com.tangem.tap.common.shop.GooglePayService import com.tangem.tap.common.shop.GooglePayService.Companion.LOAD_PAYMENT_DATA_REQUEST_CODE import com.tangem.tap.common.shop.googlepay.GooglePayUtil.createPaymentsClient import com.tangem.tap.domain.TangemSdkManager -import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.shop.redux.ShopAction import com.tangem.wallet.R import com.tangem.wallet.databinding.ActivityMainBinding @@ -67,7 +65,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler { backupService = BackupService.init(tangemSdk, this) store.dispatch(GlobalAction.SetResources(getAndroidResources())) - store.dispatch(WalletConnectAction.RestoreSessions) store.dispatch( ShopAction.CheckIfGooglePayAvailable( GooglePayService(createPaymentsClient(this), this) 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 96cf1b874b..ef357f782f 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -113,7 +113,6 @@ class DialogManager : StoreSubscriber { data = state.dialog.data, session = state.dialog.session, sessionId = state.dialog.sessionId, - cardId = state.dialog.cardId, dAppName = state.dialog.dAppName, context = context, ) 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 8bd8cf8ef7..55e86e7368 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -23,6 +23,7 @@ import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.domain.extensions.makeWalletManagersForApp import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.demo.isDemoCard +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.store @@ -88,14 +89,16 @@ class TapWalletManager { withMainContext { store.dispatch(WalletAction.ResetState(data.card.cardId)) + store.dispatch(WalletConnectAction.ResetState) store.dispatch(GlobalAction.SaveScanNoteResponse(data)) store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard)) store.dispatch(WalletAction.MultiWallet.SetIsMultiwalletAllowed(data.card.isMultiwalletAllowed)) + store.dispatch(WalletConnectAction.RestoreSessions(data)) store.dispatch( WalletAction.MultiWallet.ShowWalletBackupWarning( show = data.card.settings.isBackupAllowed - && data.card.backupStatus == Card.BackupStatus.NoBackup - ) + && data.card.backupStatus == Card.BackupStatus.NoBackup, + ), ) loadData(data) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index 7e4fae297a..45c3dee2e3 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -1,7 +1,9 @@ package com.tangem.tap.domain.walletconnect import com.tangem.blockchain.common.Blockchain +import com.tangem.common.card.EllipticCurve import com.tangem.common.extensions.guard +import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.global.GlobalAction @@ -69,7 +71,7 @@ class WalletConnectManager { remotePeerId = null, session = session, client = client, - wallet = WalletForSession(cardId = "") + wallet = WalletForSession(), ) setupConnectionTimeoutCheck(session) } @@ -110,8 +112,12 @@ class WalletConnectManager { } } - fun restoreSessions() { + fun restoreSessions(scanResponse: ScanResponse) { + val walletPublicKey = scanResponse.card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 }?.publicKey + ?: return val sessions = walletConnectRepository.loadSavedSessions() + // filter sessions for this particular card + .filter { it.wallet.walletPublicKey.contentEquals(walletPublicKey) } this.sessions = sessions .map { session -> WalletConnectActiveData( @@ -126,8 +132,8 @@ class WalletConnectManager { setListeners(it.client) it.client.connect(it.session, tangemPeerMeta, it.peerId, it.remotePeerId) } - } - .map { it.session to it }.toMap().toMutableMap() + }.associateBy { it.session }.toMutableMap() + store.dispatchOnMain(WalletConnectAction.SetSessionsRestored(sessions)) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 04f1ec8141..b23a5e1456 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -92,7 +92,6 @@ class WalletConnectSdkHelper { ) ) val dialogData = TransactionRequestDialogData( - cardId = session.wallet.cardId, dAppName = session.peerMeta.name, dAppUrl = session.peerMeta.url, amount = value.toFormattedString(decimals), @@ -235,7 +234,6 @@ class WalletConnectSdkHelper { val dialogData = PersonalSignDialogData( - cardId = session.wallet.cardId, dAppName = session.peerMeta.name, message = messageString, session = session.session, @@ -272,11 +270,11 @@ class WalletConnectSdkHelper { suspend fun signPersonalMessage(hashToSign: ByteArray, wallet: WalletForSession): String? { val key = wallet.derivedPublicKey ?: wallet.walletPublicKey val command = SignHashCommand(hashToSign, wallet.walletPublicKey!!, wallet.derivationPath) - return when (val result = tangemSdkManager.runTaskAsync(command, wallet.cardId)) { + return when (val result = tangemSdkManager.runTaskAsync(command)) { is CompletionResult.Success -> { val hash = result.data.signature return EthereumUtils.prepareSignedMessageData( - hash, hashToSign, CryptoUtils.decompressPublicKey(key!!) + hash, hashToSign, CryptoUtils.decompressPublicKey(key!!), ) } is CompletionResult.Failure -> { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WcWalletManagerFactory.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WcWalletManagerFactory.kt index 72134d880b..144f3b873d 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WcWalletManagerFactory.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WcWalletManagerFactory.kt @@ -1,13 +1,10 @@ package com.tangem.tap.domain.walletconnect import com.tangem.blockchain.common.Blockchain -import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.WalletManagerFactory -import com.tangem.common.card.EllipticCurve import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.TapWorkarounds.isTestCard -import com.tangem.tap.domain.extensions.getPrimaryCurve import com.tangem.tap.domain.extensions.makeWalletManagerForApp import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.tap.domain.tokens.models.BlockchainNetwork @@ -17,51 +14,25 @@ import com.tangem.tap.features.wallet.redux.WalletState class WcWalletManagerFactory( private val factory: WalletManagerFactory, private val currenciesRepository: CurrenciesRepository, - ) { - - suspend fun getWalletManager( - wallet: WalletForSession, blockchain: Blockchain, walletState: WalletState +) { + fun getWalletManager( + wallet: WalletForSession, blockchain: Blockchain, walletState: WalletState, ): WalletManager? { val blockchainToMake = if (blockchain == Blockchain.Ethereum && wallet.isTestNet) { Blockchain.EthereumTestnet } else { blockchain } - val blockchainNetwork = BlockchainNetwork( blockchain = blockchainToMake, derivationPath = wallet.derivationPath?.rawPath, - tokens = emptyList() + tokens = emptyList(), ) - - return if (walletState.cardId == wallet.cardId) { - walletState.getWalletManager(blockchainNetwork) - } else { - val blockchainNetworkWithTokens = currenciesRepository - .loadSavedCurrencies( - cardId = wallet.cardId, - isHdWalletSupported = wallet.derivationPath != null - ).firstOrNull { it == blockchainNetwork } - - if (blockchainNetworkWithTokens != null) { - factory.makeWalletManager( - blockchain = blockchainToMake, - publicKey = Wallet.PublicKey( - wallet.walletPublicKey!!, - wallet.derivedPublicKey, - wallet.derivationPath - ), - tokens = blockchainNetworkWithTokens.tokens, - curve = blockchainToMake.getPrimaryCurve() ?: EllipticCurve.Secp256k1 - ) - } else { - null - } - } + return walletState.getWalletManager(blockchainNetwork) } suspend fun getWalletManager( - scanResponse: ScanResponse, blockchain: Blockchain, walletState: WalletState + scanResponse: ScanResponse, blockchain: Blockchain, walletState: WalletState, ): WalletManager? { val card = scanResponse.card val blockchainToMake = if (blockchain == Blockchain.Ethereum && card.isTestCard) { @@ -69,14 +40,13 @@ class WcWalletManagerFactory( } else { blockchain } - val blockchainNetwork = BlockchainNetwork( blockchain = blockchainToMake, - card = card + card = card, ) return if (walletState.cardId == card.cardId) { - walletState.getWalletManager(blockchainNetwork) + walletState.getWalletManager(blockchainNetwork) } else { if (currenciesRepository .loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed) @@ -84,7 +54,7 @@ class WcWalletManagerFactory( ) { factory.makeWalletManagerForApp( scanResponse = scanResponse, - blockchainNetwork = blockchainNetwork + blockchainNetwork = blockchainNetwork, ) } else { null diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt index 14a871fbd9..0258af7316 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectAction.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.details.redux.walletconnect import com.tangem.blockchain.common.Blockchain +import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.redux.NotificationAction import com.tangem.wallet.R import com.trustwallet.walletconnect.models.binance.WCBinanceTradeOrder @@ -11,11 +12,9 @@ import com.trustwallet.walletconnect.models.session.WCSession import org.rekotlin.Action sealed class WalletConnectAction : Action { - + object ResetState : WalletConnectAction() data class HandleDeepLink(val wcUri: String?) : WalletConnectAction() - - object RestoreSessions : WalletConnectAction() - + data class RestoreSessions(val scanResponse: ScanResponse) : WalletConnectAction() data class StartWalletConnect( val copiedUri: String?, ) : WalletConnectAction() diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt index d98fb0b0f5..8fdcfa10ce 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectMiddleware.kt @@ -22,14 +22,13 @@ import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.scope import com.tangem.tap.store -import com.tangem.wallet.R import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.Middleware import timber.log.Timber class WalletConnectMiddleware { - private val walletConnectManager = WalletConnectManager() + private var walletConnectManager = WalletConnectManager() val walletConnectMiddleware: Middleware = { dispatch, state -> { next -> { action -> @@ -43,8 +42,9 @@ class WalletConnectMiddleware { if (DemoHelper.tryHandle(state, action)) return when (action) { + is WalletConnectAction.ResetState -> walletConnectManager = WalletConnectManager() is WalletConnectAction.RestoreSessions -> { - walletConnectManager.restoreSessions() + walletConnectManager.restoreSessions(action.scanResponse) } is WalletConnectAction.HandleDeepLink -> { if (!action.wcUri.isNullOrBlank()) { @@ -74,7 +74,13 @@ class WalletConnectMiddleware { is WalletConnectAction.ChooseNetwork -> { val data = state()?.walletConnectState?.newSessionData ?: return scope.launch { - prepareWalletManager(data.scanResponse, store.state.walletState, action.blockchain, data.session) + prepareWalletManager( + scanResponse = data.scanResponse, + walletState = store.state.walletState, + blockchain = action.blockchain, + session = data.session, + walletConnectManager = walletConnectManager, + ) } } is WalletConnectAction.ShowClipboardOrScanQrDialog -> { @@ -110,7 +116,8 @@ class WalletConnectMiddleware { ) } is WalletConnectAction.ScanCard -> { - scanCard(action.session, action.chainId) + val scanResponse = store.state.globalState.scanResponse ?: return + scanCard(scanResponse, action.session, action.chainId) } is WalletConnectAction.ApproveSession -> { walletConnectManager.approve(action.session) @@ -150,7 +157,6 @@ class WalletConnectMiddleware { data = messageData, session = action.sessionData.session, sessionId = action.id, - cardId = action.sessionData.wallet.cardId, dAppName = action.sessionData.peerMeta.name, ), ), @@ -164,7 +170,6 @@ class WalletConnectMiddleware { data = messageData, session = action.sessionData.session, sessionId = action.id, - cardId = action.sessionData.wallet.cardId, dAppName = action.sessionData.peerMeta.name, ), ), @@ -189,28 +194,26 @@ class WalletConnectMiddleware { currenciesRepository = currenciesRepository, ) val walletState = store.state.walletState - scope.launch { - val walletManager = factory.getWalletManager( - wallet = action.session.wallet, - blockchain = blockchain, - walletState = walletState, - ).guard { - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.AddNetwork(blockchain.fullName), - ), - ) - return@launch - } - val updatedWallet = action.session.wallet.copy( - walletPublicKey = walletManager.wallet.publicKey.seedKey, - derivedPublicKey = walletManager.wallet.publicKey.derivedKey, - derivationPath = walletManager.wallet.publicKey.derivationPath, - blockchain = action.blockchain, + val walletManager = factory.getWalletManager( + wallet = action.session.wallet, + blockchain = blockchain, + walletState = walletState, + ).guard { + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.AddNetwork(blockchain.fullName), + ), ) - val updatedSession = action.session.copy(wallet = updatedWallet) - store.dispatchOnMain(WalletConnectAction.UpdateBlockchain(updatedSession)) + return } + val updatedWallet = action.session.wallet.copy( + walletPublicKey = walletManager.wallet.publicKey.seedKey, + derivedPublicKey = walletManager.wallet.publicKey.derivedKey, + derivationPath = walletManager.wallet.publicKey.derivationPath, + blockchain = action.blockchain, + ) + val updatedSession = action.session.copy(wallet = updatedWallet) + store.dispatchOnMain(WalletConnectAction.UpdateBlockchain(updatedSession)) } is WalletConnectAction.UpdateBlockchain -> { walletConnectManager.updateBlockchain(action.updatedSession) @@ -218,24 +221,13 @@ class WalletConnectMiddleware { } } - private fun scanCard(session: WalletConnectSession, chainId: Int?) { + private fun scanCard(scanResponse: ScanResponse, session: WalletConnectSession, chainId: Int?) { val blockchain = WalletConnectNetworkUtils.parseBlockchain( chainId = chainId, peer = session.peerMeta, ) ?: Blockchain.Ethereum - store.dispatch( - GlobalAction.ScanCard( - additionalBlockchainsToDerive = listOf(blockchain), - onSuccess = { scanResponse -> - handleScanResponse(scanResponse = scanResponse, session = session, blockchain = blockchain) - }, - onFailure = { - store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(null)) - }, - R.string.wallet_connect_scan_card_message, - ), - ) + handleScanResponse(scanResponse = scanResponse, session = session, blockchain = blockchain) } private suspend fun getAvailableBlockchains(card: Card, walletState: WalletState): List { @@ -259,6 +251,7 @@ class WalletConnectMiddleware { walletState: WalletState, blockchain: Blockchain, session: WalletConnectSession, + walletConnectManager: WalletConnectManager, ) { val factory = WcWalletManagerFactory( factory = store.state.globalState.tapWalletManager.walletManagerFactory, @@ -273,21 +266,20 @@ class WalletConnectMiddleware { ) return } - val wallet = walletManager.wallet - val derivedKey = - if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { - null - } else { - walletManager.wallet.publicKey.blockchainKey - } - val walletForSession = WalletForSession( - cardId = scanResponse.card.cardId, - walletPublicKey = wallet.publicKey.seedKey, - derivedPublicKey = derivedKey, - derivationPath = wallet.publicKey.derivationPath, - derivationStyle = scanResponse.card.derivationStyle, - blockchain = wallet.blockchain, - ) + val wallet = walletManager.wallet + val derivedKey = + if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { + null + } else { + walletManager.wallet.publicKey.blockchainKey + } + val walletForSession = WalletForSession( + walletPublicKey = wallet.publicKey.seedKey, + derivedPublicKey = derivedKey, + derivationPath = wallet.publicKey.derivationPath, + derivationStyle = scanResponse.card.derivationStyle, + blockchain = wallet.blockchain, + ) withMainContext { val updatedSession = session.copy(wallet = walletForSession) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt index 544b6fa7be..e4cc76254c 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectReducer.kt @@ -10,6 +10,7 @@ class WalletConnectReducer { if (action !is WalletConnectAction) return state return when (action) { + is WalletConnectAction.ResetState -> return WalletConnectState() is WalletConnectAction.ApproveSession.Success -> { state.copy( loading = false, diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt index 0bdfaf69f6..97afb372a2 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/walletconnect/WalletConnectState.kt @@ -40,7 +40,6 @@ data class WalletConnectSession( @JsonClass(generateAdapter = true) data class WalletForSession( - val cardId: String, val walletPublicKey: ByteArray? = null, val derivedPublicKey: ByteArray? = null, val derivationPath: DerivationPath? = null, @@ -59,7 +58,6 @@ data class WalletForSession( other as WalletForSession - if (cardId != other.cardId) return false if (walletPublicKey != null) { if (other.walletPublicKey == null) return false if (!walletPublicKey.contentEquals(other.walletPublicKey)) return false @@ -76,8 +74,7 @@ data class WalletForSession( } override fun hashCode(): Int { - var result = cardId.hashCode() - result = 31 * result + (walletPublicKey?.contentHashCode() ?: 0) + var result = (walletPublicKey?.contentHashCode() ?: 0) result = 31 * result + (derivedPublicKey?.contentHashCode() ?: 0) result = 31 * result + (derivationPath?.hashCode() ?: 0) result = 31 * result + isTestNet.hashCode() @@ -112,7 +109,6 @@ sealed class WalletConnectDialog : StateDialog { val data: BinanceMessageData, val session: WCSession, val sessionId: Long, - val cardId: String, val dAppName: String, ) : WalletConnectDialog() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/SessionsAdapter.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/SessionsAdapter.kt deleted file mode 100644 index 95c28cf26a..0000000000 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/SessionsAdapter.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.tangem.tap.features.details.ui.walletconnect - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.chip.Chip -import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction -import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession -import com.tangem.tap.store -import com.tangem.wallet.R - -class WalletConnectSessionsAdapter - : ListAdapter( - DiffUtilCallback -) { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SessionsViewHolder { - val layout = LayoutInflater.from(parent.context) - .inflate(R.layout.item_wallet_connect_session, parent, false) - return SessionsViewHolder(layout) - } - - override fun onBindViewHolder(holder: SessionsViewHolder, position: Int) { - holder.bind(currentList[position]) - } - - object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame( - oldItem: WalletConnectSession, newItem: WalletConnectSession, - ) = oldItem == newItem - - override fun areItemsTheSame( - oldItem: WalletConnectSession, newItem: WalletConnectSession, - ) = oldItem == newItem - } - - class SessionsViewHolder(val view: View) : - RecyclerView.ViewHolder(view) { - - fun bind(session: WalletConnectSession) { - view.findViewById(R.id.tv_card_id).text = view.context.getString( - R.string.wallet_connect_card_number, session.wallet.cardId - ) - view.findViewById(R.id.tv_d_app_name).text = session.peerMeta.name - - view.findViewById(R.id.btn_disconnect).setOnClickListener { - store.dispatch(WalletConnectAction.DisconnectSession(session.session)) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt index 71a9386b36..8474878afc 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreen.kt @@ -169,7 +169,6 @@ fun WalletConnectScreenPreview() { sessions = listOf( WcSessionForScreen( description = "session from some dApp", - cardId = "12312312321", sessionId = "", ), ), diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreenState.kt index 44792f9623..e1d915dc5b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectScreenState.kt @@ -11,14 +11,12 @@ data class WalletConnectScreenState( data class WcSessionForScreen( val description: String, - val cardId: String, val sessionId: String, ) { companion object { fun fromSession(session: WalletConnectSession): WcSessionForScreen { return WcSessionForScreen( description = session.peerMeta.name, - cardId = session.wallet.cardId, sessionId = session.session.toUri(), ) } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt index b9fd651bb8..ab95ef6ef8 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ApproveWcSessionDialog.kt @@ -14,7 +14,6 @@ class ApproveWcSessionDialog { fun create(session: WalletConnectSession, networks: List, context: Context): AlertDialog { val message = context.getString( R.string.wallet_connect_request_session_start, - session.wallet.cardId, session.peerMeta.name, session.peerMeta.url, ) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt index 2ec39ca844..3d0fb57930 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/BnbTransactionDialog.kt @@ -15,7 +15,6 @@ class BnbTransactionDialog { data: BinanceMessageData, session: WCSession, sessionId: Long, - cardId: String, dAppName: String, context: Context, ): AlertDialog { @@ -40,7 +39,7 @@ class BnbTransactionDialog { val fullMessage = context.getString( R.string.wallet_connect_bnb_sign_message, - dAppName, cardId, message + dAppName, message, ) val positiveButtonTitle = context.getText(R.string.common_sign) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt index 789384c758..5d6e001087 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/PersonalSignDialog.kt @@ -15,10 +15,12 @@ class PersonalSignDialog { context: Context, ): AlertDialog { val message = - context.getString(R.string.wallet_connect_alert_sign_message, data.cardId) + - context.getString(R.string.wallet_connect_personal_sign_message, - data.dAppName, - data.message) + context.getString(R.string.wallet_connect_alert_sign_message) + + context.getString( + R.string.wallet_connect_personal_sign_message, + data.dAppName, + data.message, + ) return AlertDialog.Builder(context).apply { setTitle(context.getString(R.string.wallet_connect)) setMessage(message) @@ -37,7 +39,6 @@ class PersonalSignDialog { } data class PersonalSignDialogData( - val cardId: String, val dAppName: String, val message: String, val session: WCSession, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt index 192fc3d9e1..245cbd2ae0 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/TransactionDialog.kt @@ -17,7 +17,6 @@ class TransactionDialog { ): AlertDialog { val message = context.getString( R.string.wallet_connect_create_tx_message, - data.cardId, data.dAppName, data.dAppUrl, data.amount, @@ -53,7 +52,6 @@ class TransactionDialog { } data class TransactionRequestDialogData( - val cardId: String, val dAppName: String, val dAppUrl: String, val amount: String, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt index 4bbb63e270..f71c14a348 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/WcDialog.kt @@ -45,7 +45,6 @@ data class ButtonData( interface DialogMessageData data class WcTransactionDialogMessageData( - val cardId: String, val dAppName: String, val dAppUrl: String, val amount: String, diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d36add64ec..c0059a0e36 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -328,8 +328,8 @@ %1s (%2s) Эта карта не является векселем на предъявителя. В настоящее время мы не можем сопоставить количество подписей на карте с информацией в блокчейне. Это нормально, но в редких случаях может означать, что предыдущий владелец скрывает автономную подпись, что является проблемой безопасности.\n\nНе принимайте эту карту в качестве физического платежа от кого-то, кому Вы не доверяете.\n\nВо всех остальных отношениях - это совершенно безопасно.\n\nTangem — единственный аппаратный кошелек, предлагающий защиту от подсчета подписей. WalletConnect - Карта %1s\nЗапрос на создание транзакции для %2s\n%3s\n\nСумма: %4s\nКомиссия: %5s\nВсего: %6s\nБаланс: %7s - Запрос на запуск сеанса для карты с идентификатором %1s\nдля %2s\n\nURL: %3s + Запрос на создание транзакции для %1s\n%2s\n\nСумма: %3s\nКомиссия: %4s\nВсего: %5s\nБаланс: %6s + Запрос на запуск сеанса для %1s\n\nURL: %2s Сессии WalletConnect Сеанс WalletConnect открыт с %s Упс. Нет сессий. @@ -338,7 +338,7 @@ Карта: %s Коснитесь карты, чтобы привязать ее WalletConnect Не удается отправить транзакцию. Недостаточно средств. - Просьба подписать сообщение\nкартой %s\n\n + Просьба подписать сообщение\n Сообщение для %s:\n%s Буфер обмена содержит код WalletConnect. Использовать скопированное значение или отсканировать QR-код Вставить из буфера обмена @@ -348,7 +348,7 @@ Операция не может быть завершена. \n\nВы уже установили сеанс WalletConnect с этими параметрами. Не удалось установить сеанс WalletConnect: ошибка времени выполнения. Пожалуйста, повторите попытку позже. Транзакция BNB успешно подписана и отправлена в DApp - DApp %s, запрашивает\nподпись транзакции BNB с\nкартой: %s\n\n%s + DApp %s, запрашивает\nподпись транзакции BNB с\n%s Сведения о транзакции:\nОт: %s\nКому: %s\nСумма: %s Торговый ордер на %s\nЦена: %s\nСумма к получению: %s\nСумма к оплате: %s Мои предложения diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 405518a258..55c6923133 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -140,24 +140,23 @@ Card: %s Tap card to bind to wallet connect - Card: %1s\n - Request to create transaction for %2s - \n%3s + + Request to create transaction for %1s + \n%2s - \n\nAmount: %4s - \nFee: %5s - \nTotal: %6s - \nBalance: %7s + \n\nAmount: %3s + \nFee: %4s + \nTotal: %5s + \nBalance: %6s Can\'t send transaction. Not enough funds. - Request to start a session for card with ID %1s\n - for %2s\n\n + Request to start a session for %1s\n\n - URL: %3s + URL: %2s - Requesting to sign a message\nwith card %s\n\n + Requesting to sign a message\n Message for %s:\n%s @@ -305,8 +304,7 @@ The BNB transaction has been successfully signed and sent to the Dapp Dapp %s, requesting to\n -sign BNB transaction with\n -Card: %s\n +sign BNB transaction \n %s Transaction details:\n From 1fabb60777ebc335c82addc8df9fbc8f6614019f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 08:16:33 +0300 Subject: [PATCH 05/15] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 4 +- .../warningMessage/WarningMessagesManager.kt | 39 ++++++------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 0c69e5de88..619380c6b1 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -24,7 +24,6 @@ import com.tangem.tap.common.shop.TangemShopService import com.tangem.tap.domain.configurable.config.ConfigManager import com.tangem.tap.domain.configurable.config.FeaturesLocalLoader import com.tangem.tap.domain.configurable.config.FeaturesRemoteLoader -import com.tangem.tap.domain.configurable.warningMessage.RemoteWarningLoader import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.tap.domain.walletconnect.WalletConnectRepository @@ -101,8 +100,7 @@ class TapApplication : Application(), ImageLoaderFactory { zendeskConfig = config.zendesk!! ) } - val warningsManager = WarningMessagesManager(RemoteWarningLoader(moshi)) - warningsManager.load { store.dispatch(GlobalAction.SetWarningManager(warningsManager)) } + store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager())) } } private fun initFeedbackManager() { 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 10dbcb2cbb..683302ba73 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 @@ -1,35 +1,17 @@ package com.tangem.tap.domain.configurable.warningMessage import com.tangem.blockchain.common.Blockchain -import com.tangem.common.extensions.VoidCallback import com.tangem.tap.common.extensions.containsAny import com.tangem.tap.common.extensions.removeBy -import com.tangem.wallet.BuildConfig import com.tangem.wallet.R /** [REDACTED_AUTHOR] */ -class WarningMessagesManager( - private val warningLoader: RemoteWarningLoader, -) { +class WarningMessagesManager { private val warningsList: MutableList = mutableListOf() - fun load(onComplete: VoidCallback? = null) { - // exclude annoying remote debug warnings - if (BuildConfig.DEBUG) { - onComplete?.invoke() - return - } - warningLoader.load { remoteList -> - warningsList.clear() - warningsList.addAll(remoteList) - sortByPriority() - onComplete?.invoke() - } - } - fun addWarning(warning: WarningMessage) { if (findWarning(warning) == null) { warningsList.add(warning) @@ -37,7 +19,10 @@ class WarningMessagesManager( } } - fun getWarnings(location: WarningMessage.Location, forBlockchains: List = emptyList()): List { + fun getWarnings( + location: WarningMessage.Location, + forBlockchains: List = emptyList(), + ): List { return warningsList .filter { !it.isHidden && it.location.contains(location) } .filter { @@ -94,7 +79,7 @@ class WarningMessagesManager( null, R.string.alert_title, R.string.alert_developer_card, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) fun alreadySignedHashesWarning(): WarningMessage = WarningMessage( @@ -106,7 +91,7 @@ class WarningMessagesManager( null, R.string.alert_title, R.string.alert_card_signed_transactions, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) fun signedHashesMultiWalletWarning(): WarningMessage = WarningMessage( @@ -131,7 +116,7 @@ class WarningMessagesManager( null, R.string.warning_rate_app_title, R.string.warning_rate_app_message, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) fun isAlreadySignedHashesWarning(warning: WarningMessage): Boolean { @@ -147,7 +132,7 @@ class WarningMessagesManager( null, R.string.warning_failed_to_verify_card_title, R.string.warning_failed_to_verify_card_message, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) fun remainingSignaturesNotEnough(remainingSignatures: Int): WarningMessage = WarningMessage( @@ -160,7 +145,7 @@ class WarningMessagesManager( titleResId = R.string.alert_title, messageResId = R.string.warning_low_signatures_format, origin = WarningMessage.Origin.Local, - messageFormatArg = remainingSignatures.toString() + messageFormatArg = remainingSignatures.toString(), ) fun testCardWarning(): WarningMessage = WarningMessage( @@ -172,7 +157,7 @@ class WarningMessagesManager( null, R.string.alert_title, R.string.warning_testnet_card_message, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) fun demoCardWarning(): WarningMessage = WarningMessage( @@ -184,7 +169,7 @@ class WarningMessagesManager( null, R.string.alert_title, R.string.alert_demo_message, - WarningMessage.Origin.Local + WarningMessage.Origin.Local, ) const val REMAINING_SIGNATURES_WARNING = 10 From 7124a57c4e7d0624ad84d4e3e308b84052705dbe Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 08:18:52 +0300 Subject: [PATCH 06/15] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 4 +- .../warningMessage/WarningLoader.kt | 52 ------------------- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningLoader.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 619380c6b1..e0c6267ceb 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -65,9 +65,7 @@ class TapApplication : Application(), ImageLoaderFactory { NetworkConnectivity.createInstance(store, this) preferencesStorage = PreferencesStorage(this) - currenciesRepository = CurrenciesRepository( - this, store.state.domainNetworks.tangemTechService - ) + currenciesRepository = CurrenciesRepository(this, store.state.domainNetworks.tangemTechService) walletConnectRepository = WalletConnectRepository(this) foregroundActivityObserver = ForegroundActivityObserver() diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningLoader.kt b/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningLoader.kt deleted file mode 100644 index c95fc39a24..0000000000 --- a/app/src/main/java/com/tangem/tap/domain/configurable/warningMessage/WarningLoader.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.tangem.tap.domain.configurable.warningMessage - -import com.google.firebase.ktx.Firebase -import com.google.firebase.remoteconfig.ktx.remoteConfig -import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.Moshi -import com.squareup.moshi.Types -import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler -import com.tangem.tap.domain.configurable.Loader - -/** -[REDACTED_AUTHOR] - */ -class RemoteWarningLoader( - private val moshi: Moshi, -) : Loader> { - - override fun load(onComplete: (List) -> Unit) { - val emptyConfig = listOf() - val remoteConfig = Firebase.remoteConfig - remoteConfig.fetchAndActivate().addOnCompleteListener { - if (!it.isSuccessful) { - onComplete(emptyConfig) - return@addOnCompleteListener - } - - val config = remoteConfig.getValue(Loader.warnings) - val jsonConfig = config.asString() - if (jsonConfig.isEmpty()) { - onComplete(emptyConfig) - return@addOnCompleteListener - } - - val adapterType = Types.newParameterizedType(List::class.java, WarningMessage::class.java) - val warningsAdapter: JsonAdapter> = moshi.adapter(adapterType) - try { - val warnings = warningsAdapter.fromJson(jsonConfig) ?: listOf() - onComplete(warnings) - } catch (ex: Exception) { - handleError(ex) - onComplete(emptyConfig) - } - }.addOnFailureListener { - handleError(it) - onComplete(emptyConfig) - } - } - - private fun handleError(ex: Exception) { - FirebaseAnalyticsHandler.logException("remote_config_error.warnings", ex) - } -} \ No newline at end of file From 30d2fab20896034fc3f7c62726f6628696761c4b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 09:31:18 +0300 Subject: [PATCH 07/15] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 142 +++++++++--------- .../java/com/tangem/tap/common/AssetReader.kt | 32 ++++ .../analytics/AppsFlyerAnalyticsHandler.kt | 7 +- .../analytics/GlobalAnalyticsHandler.kt | 4 +- .../common/feedback/AdditionalFeedbackInfo.kt | 11 -- .../configurable/config/ConfigLoaders.kt | 41 +---- .../configurable/config/ConfigManager.kt | 13 +- .../tap/domain/twins/TwinCardsManager.kt | 5 +- .../products/twins/redux/TwinCardsAction.kt | 2 +- .../products/twins/ui/TwinsCardsFragment.kt | 12 +- 10 files changed, 120 insertions(+), 149 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/AssetReader.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index e0c6267ceb..d8a0b72c7e 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -1,17 +1,17 @@ package com.tangem.tap import android.app.Application +import android.content.Context +import android.content.pm.PackageManager import coil.ImageLoader import coil.ImageLoaderFactory import com.appsflyer.AppsFlyerLib -import com.google.firebase.ktx.Firebase -import com.google.firebase.remoteconfig.ktx.remoteConfig -import com.google.firebase.remoteconfig.ktx.remoteConfigSettings import com.tangem.Log import com.tangem.LogFormat import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.domain.DomainLayer import com.tangem.network.common.MoshiConverter +import com.tangem.tap.common.AndroidAssetReader import com.tangem.tap.common.analytics.GlobalAnalyticsHandler import com.tangem.tap.common.feedback.AdditionalFeedbackInfo import com.tangem.tap.common.feedback.FeedbackManager @@ -21,9 +21,9 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.appReducer import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.shop.TangemShopService +import com.tangem.tap.domain.configurable.config.Config import com.tangem.tap.domain.configurable.config.ConfigManager import com.tangem.tap.domain.configurable.config.FeaturesLocalLoader -import com.tangem.tap.domain.configurable.config.FeaturesRemoteLoader import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.domain.tokens.CurrenciesRepository import com.tangem.tap.domain.walletconnect.WalletConnectRepository @@ -36,7 +36,7 @@ import timber.log.Timber val store = Store( reducer = ::appReducer, middleware = AppState.getMiddleware(), - state = AppState() + state = AppState(), ) val logConfig = LogConfig() @@ -48,98 +48,98 @@ lateinit var walletConnectRepository: WalletConnectRepository lateinit var shopService: TangemShopService class TapApplication : Application(), ImageLoaderFactory { + override fun onCreate() { super.onCreate() - DomainLayer.init() if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) - Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings { - this.minimumFetchIntervalInSeconds = 60 - }) - } else { - Firebase.remoteConfig.setConfigSettingsAsync(remoteConfigSettings { - this.minimumFetchIntervalInSeconds = 3600 - }) } + foregroundActivityObserver = ForegroundActivityObserver() + registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks) + + DomainLayer.init() NetworkConnectivity.createInstance(store, this) preferencesStorage = PreferencesStorage(this) currenciesRepository = CurrenciesRepository(this, store.state.domainNetworks.tangemTechService) walletConnectRepository = WalletConnectRepository(this) - foregroundActivityObserver = ForegroundActivityObserver() - registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks) - initFeedbackManager() - loadConfigs() + val configLoader = FeaturesLocalLoader(AndroidAssetReader(this), MoshiConverter.defaultMoshi()) + initConfigManager(configLoader) { config -> + shopService = TangemShopService(this, config.shopify!!) + initAppsFlyer(this, config) + initFeedbackManager(this, preferencesStorage, config) + } + initWarningMessagesManager() BlockchainSdkRetrofitBuilder.enableNetworkLogging = BuildConfig.DEBUG - - initAppsFlyer() } override fun newImageLoader(): ImageLoader { return createCoilImageLoader(context = this) } - private fun loadConfigs() { - val moshi = MoshiConverter.defaultMoshi() - val localLoader = FeaturesLocalLoader(this, moshi) - val remoteLoader = FeaturesRemoteLoader(moshi) - val configManager = ConfigManager(localLoader, remoteLoader) - configManager.load { config -> + private fun initConfigManager(loader: FeaturesLocalLoader, onComplete: (Config) -> Unit) { + val configManager = ConfigManager() + configManager.load(loader) { config -> store.dispatch(GlobalAction.SetConfigManager(configManager)) - shopService = TangemShopService( - application = this, - shopifyShop = config.shopify!! - ) - store.state.globalState.feedbackManager?.initChat( - context = this, - zendeskConfig = config.zendesk!! - ) + onComplete(config) } - store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager())) } } - private fun initFeedbackManager() { - val infoHolder = AdditionalFeedbackInfo() - infoHolder.setAppVersion(this) - - val logLevels = listOf( - Log.Level.ApduCommand, - Log.Level.Apdu, - Log.Level.Tlv, - Log.Level.Nfc, - Log.Level.Command, - Log.Level.Session, - Log.Level.View, - Log.Level.Network, - Log.Level.Error, - ) - val logWriter = TangemLogCollector( - levels = logLevels, - messageFormatter = LogFormat.StairsFormatter(), - ) - Log.addLogger(logWriter) - - store.dispatch( - GlobalAction.SetFeedbackManager( - FeedbackManager( - infoHolder = infoHolder, - logCollector = logWriter, - preferencesStorage = preferencesStorage, - ), - ), - ) - } - - private fun initAppsFlyer() { - val devKey = store.state.globalState.configManager?.config?.appsFlyerDevKey ?: return - AppsFlyerLib.getInstance().init(devKey, null, this) - AppsFlyerLib.getInstance().start(this) - val analyticsHandler = GlobalAnalyticsHandler.createDefaultAnalyticHandlers(this) + private fun initAppsFlyer(context: Context, config: Config) { + AppsFlyerLib.getInstance().init(config.appsFlyerDevKey, null, context) + AppsFlyerLib.getInstance().start(context) + val analyticsHandler = GlobalAnalyticsHandler.createDefaultAnalyticHandlers(context) store.dispatch(GlobalAction.SetAnanlyticHandlers(analyticsHandler)) } + + private fun initFeedbackManager(context: Context, preferencesStorage: PreferencesStorage, config: Config) { + fun initAdditionalFeedbackInfo(context: Context): AdditionalFeedbackInfo = AdditionalFeedbackInfo().apply { + appVersion = try { + val pInfo = context.packageManager.getPackageInfo(context.packageName, 0) + pInfo.versionName + } catch (e: PackageManager.NameNotFoundException) { + e.printStackTrace() + "x.y.z" + } + } + + fun initTangemLogCollector(): TangemLogCollector { + val logLevels = listOf( + Log.Level.ApduCommand, + Log.Level.Apdu, + Log.Level.Tlv, + Log.Level.Nfc, + Log.Level.Command, + Log.Level.Session, + Log.Level.View, + Log.Level.Network, + Log.Level.Error, + ) + return TangemLogCollector(logLevels, LogFormat.StairsFormatter()) + } + + val additionalFeedbackInfo = initAdditionalFeedbackInfo(context) + val tangemLogCollector = initTangemLogCollector() + Log.addLogger(tangemLogCollector) + + val feedbackManager = FeedbackManager( + infoHolder = additionalFeedbackInfo, + logCollector = tangemLogCollector, + preferencesStorage = preferencesStorage, + ) + feedbackManager.initChat( + context = context, + zendeskConfig = config.zendesk!!, + ) + store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager)) + } + + private fun initWarningMessagesManager() { + store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager())) + } } data class LogConfig( diff --git a/app/src/main/java/com/tangem/tap/common/AssetReader.kt b/app/src/main/java/com/tangem/tap/common/AssetReader.kt new file mode 100644 index 0000000000..2beadc1c7b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/AssetReader.kt @@ -0,0 +1,32 @@ +package com.tangem.tap.common + +import android.content.Context +import com.tangem.tap.common.extensions.readAssetAsString +import com.tangem.tap.common.extensions.readFile +import com.tangem.tap.common.extensions.rewriteFile + +/** +[REDACTED_AUTHOR] + */ +interface AssetReader { + fun readAssetAsString(name: String): String + fun readFile(fileName: String): String + fun rewriteFile(content: String, fileName: String) +} + +class AndroidAssetReader( + private val context: Context, +) : AssetReader { + + override fun readAssetAsString(name: String): String { + return context.readAssetAsString(name) + } + + override fun readFile(fileName: String): String { + return context.readFile(fileName) + } + + override fun rewriteFile(content: String, fileName: String) { + context.rewriteFile(content, fileName) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/AppsFlyerAnalyticsHandler.kt index 64beb11b4a..16fa1644ab 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/AppsFlyerAnalyticsHandler.kt @@ -1,6 +1,6 @@ package com.tangem.tap.common.analytics -import android.app.Application +import android.content.Context import com.appsflyer.AFInAppEventParameterName import com.appsflyer.AFInAppEventType import com.appsflyer.AppsFlyerLib @@ -8,7 +8,7 @@ import com.shopify.buy3.Storefront import com.tangem.common.card.Card import com.tangem.common.core.TangemSdkError -class AppsFlyerAnalyticsHandler(val context: Application): AnalyticsHandler() { +class AppsFlyerAnalyticsHandler(val context: Context): AnalyticsHandler() { override fun triggerEvent( event: AnalyticsEvent, @@ -16,8 +16,7 @@ class AppsFlyerAnalyticsHandler(val context: Application): AnalyticsHandler() { blockchain: String?, params: Map ) { - AppsFlyerLib.getInstance().logEvent(context, - event.event, prepareParams(card, blockchain)) + AppsFlyerLib.getInstance().logEvent(context, event.event, prepareParams(card, blockchain)) } override fun logCardSdkError( diff --git a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt index c500f330b2..197f396621 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/GlobalAnalyticsHandler.kt @@ -1,6 +1,6 @@ package com.tangem.tap.common.analytics -import android.app.Application +import android.content.Context import com.shopify.buy3.Storefront import com.tangem.common.card.Card import com.tangem.common.core.TangemSdkError @@ -42,7 +42,7 @@ class GlobalAnalyticsHandler(val analyticsHandlers: List) : } companion object { - fun createDefaultAnalyticHandlers(context: Application): GlobalAnalyticsHandler { + fun createDefaultAnalyticHandlers(context: Context): GlobalAnalyticsHandler { return GlobalAnalyticsHandler( listOf( FirebaseAnalyticsHandler, diff --git a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt index ddc7a41b23..70912f24a6 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt @@ -1,7 +1,5 @@ package com.tangem.tap.common.feedback -import android.content.Context -import android.content.pm.PackageManager import android.os.Build import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType @@ -45,15 +43,6 @@ class AdditionalFeedbackInfo { var fee: String = "" var token: String = "" - fun setAppVersion(context: Context) { - try { - val pInfo = context.packageManager.getPackageInfo(context.packageName, 0) - appVersion = pInfo.versionName - } catch (e: PackageManager.NameNotFoundException) { - e.printStackTrace() - } - } - fun setCardInfo(data: ScanResponse) { cardId = data.card.cardId cardBlockchain = data.walletData?.blockchain ?: "" diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt index 4c19bab889..ba33d98210 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt @@ -1,12 +1,8 @@ package com.tangem.tap.domain.configurable.config -import android.content.Context -import com.google.firebase.ktx.Firebase -import com.google.firebase.remoteconfig.ktx.remoteConfig import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi -import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler -import com.tangem.tap.common.extensions.readAssetAsString +import com.tangem.tap.common.AssetReader import com.tangem.tap.domain.configurable.Loader import timber.log.Timber @@ -14,8 +10,8 @@ import timber.log.Timber [REDACTED_AUTHOR] */ class FeaturesLocalLoader( - private val context: Context, - private val moshi: Moshi, + private val assetReader: AssetReader, + private val moshi: Moshi, ) : Loader { override fun load(onComplete: (ConfigModel) -> Unit) { @@ -23,8 +19,8 @@ class FeaturesLocalLoader( val featureAdapter: JsonAdapter = moshi.adapter(FeatureModel::class.java) val valuesAdapter: JsonAdapter = moshi.adapter(ConfigValueModel::class.java) - val jsonFeatures = context.readAssetAsString(Loader.featuresName) - val jsonConfigValues = context.readAssetAsString(Loader.configValuesName) + val jsonFeatures = assetReader.readAssetAsString(Loader.featuresName) + val jsonConfigValues = assetReader.readAssetAsString(Loader.configValuesName) ConfigModel(featureAdapter.fromJson(jsonFeatures), valuesAdapter.fromJson(jsonConfigValues)) } catch (ex: Exception) { @@ -33,31 +29,4 @@ class FeaturesLocalLoader( } onComplete(config) } -} - -class FeaturesRemoteLoader( - private val moshi: Moshi, -) : Loader { - - override fun load(onComplete: (ConfigModel) -> Unit) { - val emptyConfig = ConfigModel.empty() - val remoteConfig = Firebase.remoteConfig - remoteConfig.fetchAndActivate().addOnCompleteListener { - if (it.isSuccessful) { - val config = remoteConfig.getValue(Loader.featuresName) - val jsonConfig = config.asString() - if (jsonConfig.isEmpty()) { - onComplete(emptyConfig) - return@addOnCompleteListener - } - val featureAdapter: JsonAdapter = moshi.adapter(FeatureModel::class.java) - onComplete(ConfigModel(featureAdapter.fromJson(jsonConfig), null)) - } else { - onComplete(emptyConfig) - } - }.addOnFailureListener { - FirebaseAnalyticsHandler.logException("remote_config_error.features", it) - onComplete(emptyConfig) - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt index bb94004636..62f367cb33 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt @@ -24,26 +24,19 @@ data class Config( val zendesk: ZendeskConfig? = null, ) -class ConfigManager( - private val localLoader: Loader, - private val remoteLoader: Loader -) { +class ConfigManager { var config: Config = Config() private set private var defaultConfig = Config() - fun load(onComplete: ((config: Config) -> Unit)? = null) { - localLoader.load { configModel -> + fun load(configLoader: Loader, onComplete: ((config: Config) -> Unit)? = null) { + configLoader.load { configModel -> setupFeature(configModel.features) setupKey(configModel.configValues) onComplete?.invoke(config) } - // Uncomment to enable remote config -// remoteLoader.load { config -> -// setupFeature(config.features) -// } } fun turnOff(name: String) { diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt index 43c91a54fb..1d02623442 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt @@ -13,6 +13,7 @@ import com.tangem.common.extensions.toHexString import com.tangem.domain.common.ScanResponse import com.tangem.network.common.MoshiConverter import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.tap.common.AssetReader import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.AnalyticsHandler import com.tangem.tap.tangemSdkManager @@ -119,10 +120,6 @@ class TwinCardsManager( } } -interface AssetReader { - fun readAssetAsString(name: String): String -} - private class Issuer( val id: String, val privateKey: String, diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsAction.kt index ee4bd5ddab..5c915f9cb0 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsAction.kt @@ -4,9 +4,9 @@ import com.tangem.Message import com.tangem.blockchain.common.WalletManager import com.tangem.common.extensions.VoidCallback import com.tangem.domain.common.ScanResponse +import com.tangem.tap.common.AssetReader import com.tangem.tap.common.redux.StateDialog import com.tangem.tap.domain.TapError -import com.tangem.tap.domain.twins.AssetReader import com.tangem.tap.domain.twins.TwinCardsManager import com.tangem.tap.features.onboarding.OnboardingWalletBalance import org.rekotlin.Action diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt index 7827a4f196..ee7eb79471 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/ui/TwinsCardsFragment.kt @@ -15,10 +15,10 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.common.extensions.VoidCallback import com.tangem.domain.common.TwinCardNumber import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget +import com.tangem.tap.common.AndroidAssetReader import com.tangem.tap.common.extensions.beginDelayedTransition import com.tangem.tap.common.extensions.getDrawableCompat import com.tangem.tap.common.extensions.hide -import com.tangem.tap.common.extensions.readAssetAsString import com.tangem.tap.common.extensions.show import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.redux.navigation.AppScreen @@ -26,7 +26,6 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.common.redux.navigation.ShareElement import com.tangem.tap.common.toggleWidget.RefreshBalanceWidget import com.tangem.tap.common.transitions.InternalNoteLayoutTransition -import com.tangem.tap.domain.twins.AssetReader import com.tangem.tap.domain.twins.TwinsCardWidget import com.tangem.tap.features.addBackPressHandler import com.tangem.tap.features.onboarding.products.BaseOnboardingFragment @@ -46,13 +45,6 @@ class TwinsCardsFragment : BaseOnboardingFragment() { private lateinit var twinsWidget: TwinsCardWidget private lateinit var btnRefreshBalanceWidget: RefreshBalanceWidget - private val assetReader: AssetReader by lazy { - object : AssetReader { - override fun readAssetAsString(name: String): String = - requireContext().readAssetAsString(name) - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) postponeEnterTransition() @@ -250,7 +242,7 @@ class TwinsCardsFragment : BaseOnboardingFragment() { store.dispatch( TwinCardsAction.Wallet.LaunchFirstStep( Message(getString(R.string.twins_recreate_title_format, twinIndexNumber)), - assetReader + AndroidAssetReader(requireContext()), ) ) } From d624229c4be897dc6f97a0acb795903bd2245e98 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 14:14:46 +0300 Subject: [PATCH 08/15] Updated on 2026-08-14 --- .../reducers/TransactionExtrasReducer.kt | 64 +++++++++--------- .../send/redux/states/AddressPayIdState.kt | 67 ++++++++++++------- .../stateSubscribers/SendStateSubscriber.kt | 10 +-- .../res/layout/layout_send_address_payid.xml | 1 + app/src/main/res/values-de/strings_final.xml | 4 ++ app/src/main/res/values-fr/strings_final.xml | 4 ++ app/src/main/res/values-it/strings_final.xml | 4 ++ app/src/main/res/values-ru/strings.xml | 4 -- app/src/main/res/values-ru/strings_final.xml | 4 ++ app/src/main/res/values/strings_final.xml | 4 ++ .../main/res/values/strings_untranslated.xml | 6 -- 11 files changed, 100 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt index 4215143301..71000abec1 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/TransactionExtrasReducer.kt @@ -3,8 +3,19 @@ package com.tangem.tap.features.send.redux.reducers import com.tangem.blockchain.blockchains.stellar.StellarMemo import com.tangem.blockchain.common.Blockchain import com.tangem.tap.features.send.redux.SendScreenAction -import com.tangem.tap.features.send.redux.TransactionExtrasAction.* -import com.tangem.tap.features.send.redux.states.* +import com.tangem.tap.features.send.redux.TransactionExtrasAction.BinanceMemo +import com.tangem.tap.features.send.redux.TransactionExtrasAction.Prepare +import com.tangem.tap.features.send.redux.TransactionExtrasAction.Release +import com.tangem.tap.features.send.redux.TransactionExtrasAction.XlmMemo +import com.tangem.tap.features.send.redux.TransactionExtrasAction.XrpDestinationTag +import com.tangem.tap.features.send.redux.states.BinanceMemoState +import com.tangem.tap.features.send.redux.states.InputViewValue +import com.tangem.tap.features.send.redux.states.SendState +import com.tangem.tap.features.send.redux.states.TransactionExtraError +import com.tangem.tap.features.send.redux.states.TransactionExtrasState +import com.tangem.tap.features.send.redux.states.XlmMemoState +import com.tangem.tap.features.send.redux.states.XlmMemoType +import com.tangem.tap.features.send.redux.states.XrpDestinationTagState /** [REDACTED_AUTHOR] @@ -53,42 +64,33 @@ class TransactionExtrasReducer : SendInternalReducer { } private fun handleXlmMemo( - action: XlmMemo, - sendState: SendState, - infoState: TransactionExtrasState, + action: XlmMemo, + sendState: SendState, + infoState: TransactionExtrasState, ): SendState { fun clearMemo(memo: XlmMemoState): XlmMemoState = memo.copy(text = null, id = null, error = null) val result = when (action) { -// is XlmMemo.ChangeSelectedMemo -> { -// val inputViewValue = InputViewValue("", false) -// val memo = infoState.xlmMemo?.copy( -// viewFieldValue = inputViewValue, -// selectedMemoType = action.memoType, -// ) ?: XlmMemoState(inputViewValue, action.memoType) -// -// infoState.copy(xlmMemo = clearMemo(memo)) -// } is XlmMemo.HandleUserInput -> { val inputViewValue = InputViewValue(action.data, true) var memo = infoState.xlmMemo?.copy(viewFieldValue = inputViewValue) - ?: XlmMemoState(inputViewValue) + ?: XlmMemoState(inputViewValue) memo = clearMemo(memo) - memo = when (infoState.xlmMemo?.selectedMemoType) { - XlmMemoType.TEXT -> memo.copy(text = StellarMemo.Text(action.data)) - XlmMemoType.ID -> { - val id = action.data.toBigIntegerOrNull() - if (id != null) { - if (id > XlmMemoState.MAX_NUMBER) { - memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) - } else { - memo.copy(id = StellarMemo.Id(id)) - } + memo = when (memo.selectedMemoType) { + XlmMemoType.TEXT -> { + if (XlmMemoState.isAssignableValue(action.data)) { + memo.copy(text = StellarMemo.Text(action.data)) } else { - memo + memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) + } + } + XlmMemoType.ID -> { + if (XlmMemoState.isAssignableValue(action.data)) { + memo.copy(id = StellarMemo.Id(action.data.toBigInteger())) + } else { + memo.copy(error = TransactionExtraError.INVALID_XLM_MEMO) } } - null -> memo } infoState.copy(xlmMemo = memo) } @@ -117,16 +119,16 @@ class TransactionExtrasReducer : SendInternalReducer { } private fun handleXrpTag( - action: XrpDestinationTag, - sendState: SendState, - infoState: TransactionExtrasState, + action: XrpDestinationTag, + sendState: SendState, + infoState: TransactionExtrasState, ): SendState { val result = when (action) { is XrpDestinationTag.HandleUserInput -> { val tag = action.data.toLongOrNull() if (tag != null) { val input = InputViewValue(action.data, true) - val tagState = if (tag <= XrpDestinationTagState.MAX_NUMBER){ + val tagState = if (tag <= XrpDestinationTagState.MAX_NUMBER) { XrpDestinationTagState(input, tag) } else { XrpDestinationTagState(input, error = TransactionExtraError.INVALID_DESTINATION_TAG) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt index e4f816c106..30fe37f60a 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt @@ -1,19 +1,20 @@ package com.tangem.tap.features.send.redux.states +import androidx.core.text.isDigitsOnly import com.tangem.blockchain.blockchains.stellar.StellarMemo import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction import java.math.BigInteger data class AddressPayIdState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val normalFieldValue: String? = null, - val truncatedFieldValue: String? = null, - val destinationWalletAddress: String? = null, - val error: AddressPayIdVerifyAction.Error? = null, - val truncateHandler: ((String) -> String)? = null, - val sendingToPayIdEnabled: Boolean = false, - val pasteIsEnabled: Boolean = false, - val inputIsEnabled: Boolean = true + val viewFieldValue: InputViewValue = InputViewValue(""), + val normalFieldValue: String? = null, + val truncatedFieldValue: String? = null, + val destinationWalletAddress: String? = null, + val error: AddressPayIdVerifyAction.Error? = null, + val truncateHandler: ((String) -> String)? = null, + val sendingToPayIdEnabled: Boolean = false, + val pasteIsEnabled: Boolean = false, + val inputIsEnabled: Boolean = true, ) : SendScreenState { override val stateId: StateId = StateId.ADDRESS_PAY_ID @@ -26,9 +27,9 @@ data class AddressPayIdState( } data class TransactionExtrasState( - val xlmMemo: XlmMemoState? = null, - val binanceMemo: BinanceMemoState? = null, - val xrpDestinationTag: XrpDestinationTagState? = null + val xlmMemo: XlmMemoState? = null, + val binanceMemo: BinanceMemoState? = null, + val xrpDestinationTag: XrpDestinationTagState? = null, ) : IdStateHolder { override val stateId: StateId = StateId.TRANSACTION_EXTRAS } @@ -38,11 +39,10 @@ enum class XlmMemoType { } data class XlmMemoState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val selectedMemoType: XlmMemoType = XlmMemoType.ID, - val text: StellarMemo.Text? = null, - val id: StellarMemo.Id? = null, - val error: TransactionExtraError? = null, + val viewFieldValue: InputViewValue = InputViewValue(""), + val text: StellarMemo.Text? = null, + val id: StellarMemo.Id? = null, + val error: TransactionExtraError? = null, ) { val memo: StellarMemo? get() = when (selectedMemoType) { @@ -50,16 +50,37 @@ data class XlmMemoState( XlmMemoType.ID -> id } + val selectedMemoType: XlmMemoType + get() = determineMemoType(viewFieldValue.value) + companion object { - val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16) + fun determineMemoType(value: String): XlmMemoType = when { + value.isNotEmpty() && value.isDigitsOnly() -> XlmMemoType.ID + else -> XlmMemoType.TEXT + } + + fun isAssignableValue(value: String): Boolean = when (determineMemoType(value)) { + XlmMemoType.TEXT -> { + // from org.stellar.sdk.MemoText + value.toByteArray().size <= 28 + } + XlmMemoType.ID -> { + try { + // from com.tangem.blockchain.blockchains.stellar.StellarMemo.toStellarSdkMemo + value.toBigInteger() in BigInteger.ZERO..(Long.MAX_VALUE.toBigInteger() * 2.toBigInteger()) + } catch (ex: NumberFormatException) { + false + } + } + } } } data class BinanceMemoState( val viewFieldValue: InputViewValue = InputViewValue(""), val memo: BigInteger? = null, - val error: TransactionExtraError? = null - ) { + val error: TransactionExtraError? = null, +) { companion object { val MAX_NUMBER: BigInteger = BigInteger("FFFFFFFFFFFFFFFF", 16) } @@ -67,9 +88,9 @@ data class BinanceMemoState( // tag must contains only digits data class XrpDestinationTagState( - val viewFieldValue: InputViewValue = InputViewValue(""), - val tag: Long? = null, - val error: TransactionExtraError? = null + val viewFieldValue: InputViewValue = InputViewValue(""), + val tag: Long? = null, + val error: TransactionExtraError? = null, ) { companion object { const val MAX_NUMBER: Long = 4294967295 diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 4496bd570b..02b4f56c5f 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -2,7 +2,6 @@ package com.tangem.tap.features.send.ui.stateSubscribers import android.app.Dialog import android.content.Context -import android.text.InputType import android.text.SpannableStringBuilder import android.view.View import android.view.ViewGroup @@ -32,7 +31,6 @@ import com.tangem.tap.features.send.redux.states.SendState import com.tangem.tap.features.send.redux.states.StateId import com.tangem.tap.features.send.redux.states.TransactionExtraError import com.tangem.tap.features.send.redux.states.TransactionExtrasState -import com.tangem.tap.features.send.redux.states.XlmMemoType import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog @@ -84,14 +82,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : showView(binanceMemoContainer, infoState.binanceMemo) infoState.xlmMemo?.let { - etXlmMemo.inputType = when (it.selectedMemoType) { - XlmMemoType.TEXT -> InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS - XlmMemoType.ID -> InputType.TYPE_CLASS_NUMBER - } if (!it.viewFieldValue.isFromUserInput) etXlmMemo.setText(it.viewFieldValue.value) if (it.error != null) { if (it.error == TransactionExtraError.INVALID_XLM_MEMO) { - tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo_id) + tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo) } } else { tilXlmMemo.error = null @@ -113,7 +107,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : infoState.binanceMemo?.let { if (infoState.binanceMemo.error != null) { if (infoState.binanceMemo.error == TransactionExtraError.INVALID_BINANCE_MEMO) { - tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo_id) + tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo) } } else { tilBinanceMemo.error = null diff --git a/app/src/main/res/layout/layout_send_address_payid.xml b/app/src/main/res/layout/layout_send_address_payid.xml index 232b778f22..b16e59b974 100644 --- a/app/src/main/res/layout/layout_send_address_payid.xml +++ b/app/src/main/res/layout/layout_send_address_payid.xml @@ -153,6 +153,7 @@ android:layout_height="wrap_content" android:background="@color/backgroundLightGray" android:ellipsize="middle" + android:inputType="text|textNoSuggestions" android:paddingStart="0dp" android:paddingEnd="0dp" android:singleLine="true" diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 96c0876eff..a2c94fc2da 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -95,4 +95,8 @@ 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 + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction \ 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..01b15baa13 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -95,4 +95,8 @@ 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 + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction \ 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..f6b98a333f 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -96,4 +96,8 @@ 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 + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d36add64ec..2c0bc407a8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -147,10 +147,6 @@ Добавить Удалить Поиск - Памятка - Тег назначения - Недопустимый тег назначения. Он не будет добавлен в транзакцию. - Недопустимый идентификатор памятки. Он не будет добавлен в транзакцию. Приложение Отправить отзыв Успешно отправлено diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index 359b5c0488..3ccd9d13aa 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -112,4 +112,8 @@ Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. Выберите сеть + Memo + Tag + Недопустимый Memo. Он не будет добавлен в транзакцию. + Недопустимый Tag. Он не будет добавлен в транзакцию. diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index ca04743898..0e11c29566 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -114,4 +114,8 @@ 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 + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 405518a258..8e7398a50e 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -40,12 +40,6 @@ Remove Search - - Memo - Destination tag - Invalid destination tag. It won\'t be added to the transaction - Invalid Memo ID. It won\'t be added to the transaction - App Send feedback Sent successfully From 5c14c7062ead3c532c707b8ab6e1184ed63bc197 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 18:28:19 +0300 Subject: [PATCH 09/15] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TapErrors.kt | 1 + .../send/redux/middlewares/SendMiddleware.kt | 12 +++++++++++- app/src/main/res/values-de/strings_blockchain.xml | 1 + app/src/main/res/values-fr/strings_blockchain.xml | 1 + app/src/main/res/values-it/strings_blockchain.xml | 1 + app/src/main/res/values-ru/strings_blockchain.xml | 1 + app/src/main/res/values/strings_blockchain.xml | 1 + 7 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt index 9d3cc79eee..1db3b2194f 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt @@ -31,6 +31,7 @@ sealed class TapError( object InsufficientBalance : TapError(R.string.send_error_insufficient_balance) object BlockchainInternalError : TapError(R.string.send_error_blockchain_internal) object AmountExceedsBalance : TapError(R.string.send_validation_amount_exceeds_balance) + data class AmountLowerExistentialDeposit(override val args: List) : TapError(R.string.send_error_minimum_balance_format) object FeeExceedsBalance : TapError(R.string.send_validation_invalid_fee) object TotalExceedsBalance : TapError(R.string.send_validation_invalid_total) object InvalidAmountValue : TapError(R.string.send_validation_invalid_amount) 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 ee1b5eb1d2..54be369642 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 @@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux.middlewares import com.google.firebase.crashlytics.FirebaseCrashlytics import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras +import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder import com.tangem.blockchain.common.Amount @@ -301,12 +302,21 @@ fun createValidateTransactionError( val tapErrors = errorList.map { when (it) { TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance + TransactionError.AmountLowerExistentialDeposit -> { + if (walletManager is ExistentialDepositProvider) { + val args = listOf(walletManager.getExistentialDeposit().stripZeroPlainString()) + TapError.AmountLowerExistentialDeposit(args) + } else { + TapError.UnknownError + } + } TransactionError.FeeExceedsBalance -> TapError.FeeExceedsBalance TransactionError.TotalExceedsBalance -> TapError.TotalExceedsBalance TransactionError.InvalidAmountValue -> TapError.InvalidAmountValue TransactionError.InvalidFeeValue -> TapError.InvalidFeeValue TransactionError.DustAmount -> { - TapError.DustAmount(listOf(walletManager.dustValue?.stripZeroPlainString() ?: "0")) + val args = listOf(walletManager.dustValue?.stripZeroPlainString() ?: "0") + TapError.DustAmount(args) } TransactionError.DustChange -> TapError.DustChange else -> TapError.UnknownError diff --git a/app/src/main/res/values-de/strings_blockchain.xml b/app/src/main/res/values-de/strings_blockchain.xml index 2f52667c19..0185fd6d8f 100644 --- a/app/src/main/res/values-de/strings_blockchain.xml +++ b/app/src/main/res/values-de/strings_blockchain.xml @@ -17,4 +17,5 @@ Der Betrag geht über die Bilanz hinaus Der Gesamtbetrag geht über die Bilanz hinaus Die Gebühr geht über die Bilanz hinaus + Minimum balance is %s \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_blockchain.xml b/app/src/main/res/values-fr/strings_blockchain.xml index f6e2cdef63..62b57fe369 100644 --- a/app/src/main/res/values-fr/strings_blockchain.xml +++ b/app/src/main/res/values-fr/strings_blockchain.xml @@ -17,4 +17,5 @@ Pour ne pas payer une commission élevée la prochaine fois que vous rechargez votre portefeuille, veuillez réduire le montant de %s XTZ Réduire de %s XTZ Non, envoyer toute la somme + Minimum balance is %s \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_blockchain.xml b/app/src/main/res/values-it/strings_blockchain.xml index cd0f690a23..06d7ed8db4 100644 --- a/app/src/main/res/values-it/strings_blockchain.xml +++ b/app/src/main/res/values-it/strings_blockchain.xml @@ -17,4 +17,5 @@ Per evitare di pagare una commissione maggiore la prossima volta che ricarichi il tuo portafoglio, riduci l\'importo di %s XTZ Riduci di %s XTZ No, invia l\'intero importo + Minimum balance is %s \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings_blockchain.xml b/app/src/main/res/values-ru/strings_blockchain.xml index 98b7ad7194..102a5145b4 100644 --- a/app/src/main/res/values-ru/strings_blockchain.xml +++ b/app/src/main/res/values-ru/strings_blockchain.xml @@ -17,4 +17,5 @@ Чтобы не платить повышенную комиссию при следующем пополнении кошелька, уменьшите сумму на %s XTZ Уменьшить на %s XTZ Нет, отправить все + Минимальный баланс: %s \ No newline at end of file diff --git a/app/src/main/res/values/strings_blockchain.xml b/app/src/main/res/values/strings_blockchain.xml index 35bc8cf334..09cca7bfaa 100644 --- a/app/src/main/res/values/strings_blockchain.xml +++ b/app/src/main/res/values/strings_blockchain.xml @@ -17,4 +17,5 @@ To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ Reduce by %s XTZ No, send all + Minimum balance is %s \ No newline at end of file From be1db0b2ab5a68693c264301cfd55382631e4a6a Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 20:06:00 +0300 Subject: [PATCH 10/15] Updated on 2026-08-14 --- .../tangem/tap/features/send/redux/reducers/ReceiptReducer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9d7ac05a20..4d4154218c 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 @@ -218,7 +218,7 @@ class ReceiptReducer : SendInternalReducer { } private fun String.addPrecisionSign(): String { - val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else "" + val result = if (feeState.feeIsApproximate) "$CAN_BE_LOWER_SIGN $this" else this return result.trim() } } \ No newline at end of file From bdf6a18a02d5f64bcd84ef8fb867efd84497c643 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 20:16:47 +0300 Subject: [PATCH 11/15] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/TapApplication.kt | 12 +++++++----- .../main/java/com/tangem/tap/common/AssetReader.kt | 12 ------------ 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index d8a0b72c7e..4674adf0e6 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -66,11 +66,7 @@ class TapApplication : Application(), ImageLoaderFactory { walletConnectRepository = WalletConnectRepository(this) val configLoader = FeaturesLocalLoader(AndroidAssetReader(this), MoshiConverter.defaultMoshi()) - initConfigManager(configLoader) { config -> - shopService = TangemShopService(this, config.shopify!!) - initAppsFlyer(this, config) - initFeedbackManager(this, preferencesStorage, config) - } + initConfigManager(configLoader, ::initWithConfigDependency) initWarningMessagesManager() BlockchainSdkRetrofitBuilder.enableNetworkLogging = BuildConfig.DEBUG @@ -88,6 +84,12 @@ class TapApplication : Application(), ImageLoaderFactory { } } + private fun initWithConfigDependency(config: Config) { + shopService = TangemShopService(this, config.shopify!!) + initAppsFlyer(this, config) + initFeedbackManager(this, preferencesStorage, config) + } + private fun initAppsFlyer(context: Context, config: Config) { AppsFlyerLib.getInstance().init(config.appsFlyerDevKey, null, context) AppsFlyerLib.getInstance().start(context) diff --git a/app/src/main/java/com/tangem/tap/common/AssetReader.kt b/app/src/main/java/com/tangem/tap/common/AssetReader.kt index 2beadc1c7b..3f5eb10dd9 100644 --- a/app/src/main/java/com/tangem/tap/common/AssetReader.kt +++ b/app/src/main/java/com/tangem/tap/common/AssetReader.kt @@ -2,16 +2,12 @@ package com.tangem.tap.common import android.content.Context import com.tangem.tap.common.extensions.readAssetAsString -import com.tangem.tap.common.extensions.readFile -import com.tangem.tap.common.extensions.rewriteFile /** [REDACTED_AUTHOR] */ interface AssetReader { fun readAssetAsString(name: String): String - fun readFile(fileName: String): String - fun rewriteFile(content: String, fileName: String) } class AndroidAssetReader( @@ -21,12 +17,4 @@ class AndroidAssetReader( override fun readAssetAsString(name: String): String { return context.readAssetAsString(name) } - - override fun readFile(fileName: String): String { - return context.readFile(fileName) - } - - override fun rewriteFile(content: String, fileName: String) { - context.rewriteFile(content, fileName) - } } \ No newline at end of file From 2ed3b93d825d5d52afe79df3c2d37d90125f449d Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 23:18:08 +0300 Subject: [PATCH 12/15] Updated on 2026-08-14 --- .../tap/features/send/redux/middlewares/AmountMiddleware.kt | 1 + dependencies.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 bfcbc36889..69bdcc3166 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 @@ -120,6 +120,7 @@ private fun filterErrorsForAmountField(errors: EnumSet): EnumS TransactionError.TotalExceedsBalance -> { val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance) if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it) + showIntoAmountField.remove(TransactionError.AmountLowerExistentialDeposit) } else -> showIntoAmountField.add(it) } diff --git a/dependencies.gradle b/dependencies.gradle index 394b8cc997..8762730416 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-111', + tangem_blockchain_sdk: 'develop-113', // tangem_blockchain_sdk: '0.0.1', ] From 63c1a0e3dfd2d6d03b1852f74063261a7eaa6c3b Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 15 Sep 2022 23:18:08 +0300 Subject: [PATCH 13/15] Updated on 2026-08-14 --- .../tap/features/send/redux/middlewares/AmountMiddleware.kt | 1 + dependencies.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 bfcbc36889..69bdcc3166 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 @@ -120,6 +120,7 @@ private fun filterErrorsForAmountField(errors: EnumSet): EnumS TransactionError.TotalExceedsBalance -> { val notAcceptable = listOf(TransactionError.AmountExceedsBalance, TransactionError.FeeExceedsBalance) if (!showIntoAmountField.containsAll(notAcceptable)) showIntoAmountField.add(it) + showIntoAmountField.remove(TransactionError.AmountLowerExistentialDeposit) } else -> showIntoAmountField.add(it) } diff --git a/dependencies.gradle b/dependencies.gradle index 394b8cc997..8762730416 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-111', + tangem_blockchain_sdk: 'develop-113', // tangem_blockchain_sdk: '0.0.1', ] From 33986b6290362e3e21f013151ca94ebc3e0548f4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 16 Sep 2022 12:23:03 +0300 Subject: [PATCH 14/15] Updated on 2026-08-14 --- .../send/ui/stateSubscribers/SendStateSubscriber.kt | 6 +++--- app/src/main/res/values-de/strings_blockchain.xml | 5 +++++ app/src/main/res/values-de/strings_final.xml | 5 ----- app/src/main/res/values-fr/strings_blockchain.xml | 5 +++++ app/src/main/res/values-fr/strings_final.xml | 5 ----- app/src/main/res/values-it/strings_blockchain.xml | 5 +++++ app/src/main/res/values-it/strings_final.xml | 5 ----- app/src/main/res/values-ru/strings_final.xml | 4 ++-- app/src/main/res/values/strings_blockchain.xml | 5 +++++ app/src/main/res/values/strings_final.xml | 5 ----- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 31fa218cfd..fe3bee237d 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -81,7 +81,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : if (!it.viewFieldValue.isFromUserInput) etXlmMemo.setText(it.viewFieldValue.value) if (it.error != null) { if (it.error == TransactionExtraError.INVALID_XLM_MEMO) { - tilXlmMemo.error = fg.getText(R.string.send_error_invalid_memo) + tilXlmMemo.error = fg.getText(R.string.send_extras_error_invalid_memo) } } else { tilXlmMemo.error = null @@ -91,7 +91,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : if (infoState.xrpDestinationTag.error != null) { if (infoState.xrpDestinationTag.error == TransactionExtraError.INVALID_DESTINATION_TAG) { tilDestinationTag.error = - fg.getText(R.string.send_error_invalid_destination_tag) + fg.getText(R.string.send_extras_error_invalid_destination_tag) } } else { tilDestinationTag.error = null @@ -103,7 +103,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : infoState.binanceMemo?.let { if (infoState.binanceMemo.error != null) { if (infoState.binanceMemo.error == TransactionExtraError.INVALID_BINANCE_MEMO) { - tilBinanceMemo.error = fg.getText(R.string.send_error_invalid_memo) + tilBinanceMemo.error = fg.getText(R.string.send_extras_error_invalid_memo) } } else { tilBinanceMemo.error = null diff --git a/app/src/main/res/values-de/strings_blockchain.xml b/app/src/main/res/values-de/strings_blockchain.xml index 0185fd6d8f..98c248c381 100644 --- a/app/src/main/res/values-de/strings_blockchain.xml +++ b/app/src/main/res/values-de/strings_blockchain.xml @@ -18,4 +18,9 @@ Der Gesamtbetrag geht über die Bilanz hinaus Die Gebühr geht über die Bilanz hinaus Minimum balance is %s + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction + %s network has a concept of Existential Deposit. If your account drops below %s %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-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index 7e585b36f2..13aa0a643a 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -86,9 +86,4 @@ 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 - Memo - Tag - Invalid Memo. It won\'t be added to the transaction - Invalid Tag. It won\'t be added to the transaction - %s network has a concept of Existential Deposit. If your account drops below %s %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_blockchain.xml b/app/src/main/res/values-fr/strings_blockchain.xml index 62b57fe369..43e0d8c933 100644 --- a/app/src/main/res/values-fr/strings_blockchain.xml +++ b/app/src/main/res/values-fr/strings_blockchain.xml @@ -18,4 +18,9 @@ Réduire de %s XTZ Non, envoyer toute la somme Minimum balance is %s + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction + %s network has a concept of Existential Deposit. If your account drops below %s %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 5d8b24ed0f..737bdd59c1 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -86,9 +86,4 @@ 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 - Memo - Tag - Invalid Memo. It won\'t be added to the transaction - Invalid Tag. It won\'t be added to the transaction - %s network has a concept of Existential Deposit. If your account drops below %s %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_blockchain.xml b/app/src/main/res/values-it/strings_blockchain.xml index 06d7ed8db4..d4e7c01f40 100644 --- a/app/src/main/res/values-it/strings_blockchain.xml +++ b/app/src/main/res/values-it/strings_blockchain.xml @@ -18,4 +18,9 @@ Riduci di %s XTZ No, invia l\'intero importo Minimum balance is %s + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction + %s network has a concept of Existential Deposit. If your account drops below %s %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 5d8b24ed0f..737bdd59c1 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -86,9 +86,4 @@ 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 - Memo - Tag - Invalid Memo. It won\'t be added to the transaction - Invalid Tag. It won\'t be added to the transaction - %s network has a concept of Existential Deposit. If your account drops below %s %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 4bc89187dc..09b2609172 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -99,7 +99,7 @@ Выберите сеть Memo Tag - Недопустимый Memo. Он не будет добавлен в транзакцию. - Недопустимый Tag. Он не будет добавлен в транзакцию. + Недопустимый Memo. Он не будет добавлен в транзакцию. + Недопустимый Tag. Он не будет добавлен в транзакцию. Сеть %s использует концепцию экзистенциального депозита. Если баланс вашего счета опустится ниже %s %s, он будет деактивирован, а все оставшиеся средства будут уничтожены. diff --git a/app/src/main/res/values/strings_blockchain.xml b/app/src/main/res/values/strings_blockchain.xml index 09cca7bfaa..1d6e8df503 100644 --- a/app/src/main/res/values/strings_blockchain.xml +++ b/app/src/main/res/values/strings_blockchain.xml @@ -18,4 +18,9 @@ Reduce by %s XTZ No, send all Minimum balance is %s + Memo + Tag + Invalid Memo. It won\'t be added to the transaction + Invalid Tag. It won\'t be added to the transaction + %s network has a concept of Existential Deposit. If your account drops below %s %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/strings_final.xml b/app/src/main/res/values/strings_final.xml index fa691840a2..adee69f918 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -99,9 +99,4 @@ 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 - Memo - Tag - Invalid Memo. It won\'t be added to the transaction - Invalid Tag. It won\'t be added to the transaction - %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. From daa57f5ff22de703d2dea3c5727d3a3df664add7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 16 Sep 2022 12:35:41 +0300 Subject: [PATCH 15/15] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/domain/TapErrors.kt | 1 - .../send/ui/dialogs/SendTransactionFailsDialog.kt | 11 ++++++++--- app/src/main/res/values-de/strings_blockchain.xml | 3 ++- app/src/main/res/values-fr/strings_blockchain.xml | 3 ++- app/src/main/res/values-it/strings_blockchain.xml | 3 ++- app/src/main/res/values-ru/strings_blockchain.xml | 3 ++- app/src/main/res/values/strings_blockchain.xml | 3 ++- 7 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt index 1db3b2194f..674487ff78 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt @@ -38,7 +38,6 @@ sealed class TapError( object InvalidFeeValue : TapError(R.string.send_error_invalid_fee_value) data class DustAmount(override val args: List) : TapError(R.string.send_error_dust_amount_format) object DustChange : TapError(R.string.send_error_dust_change) - data class CreateAccountUnderfunded(override val args: List) : TapError(R.string.send_error_no_target_account) data class UnsupportedState( val stateError: String, 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 a4b5ff7539..0e35552e43 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,6 +2,7 @@ package com.tangem.tap.features.send.ui.dialogs import android.content.Context import androidx.appcompat.app.AlertDialog +import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.common.module.ModuleMessageConverter import com.tangem.tangem_sdk_new.extensions.localizedDescription @@ -47,9 +48,13 @@ private class BlockchainSdkErrorConverter( 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) + val resStringId = when (message.blockchain) { + Blockchain.Polkadot, Blockchain.PolkadotTestnet -> R.string.no_account_polkadot + else -> R.string.send_error_no_target_account + } + val reserveValueString = message.minReserve.value?.stripZeroPlainString() ?: "0" + val argument = "$reserveValueString ${message.minReserve.currencySymbol}" + context.getString(resStringId, argument) } else -> message.customMessage } diff --git a/app/src/main/res/values-de/strings_blockchain.xml b/app/src/main/res/values-de/strings_blockchain.xml index 98c248c381..5cb1360d71 100644 --- a/app/src/main/res/values-de/strings_blockchain.xml +++ b/app/src/main/res/values-de/strings_blockchain.xml @@ -5,7 +5,7 @@ Falsche Gebühr Minimaler Betrag ist %s Restbestand zu klein - Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %s %s + Gebühr oder mehr sein + Das Zielkonto ist nicht erstellt. Der abzusendende Betrag soll %s + Gebühr oder mehr sein Um ein Konto zu erstellen, senden Sie 1+ XLM an diese Adresse Erhalt der Gebühr fehlgeschlagen Unbekannter Fehler @@ -23,4 +23,5 @@ Invalid Memo. It won\'t be added to the transaction Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. + Destination account is not active. Send %s or more to activate the account. \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings_blockchain.xml b/app/src/main/res/values-fr/strings_blockchain.xml index 43e0d8c933..5bbb85c2f3 100644 --- a/app/src/main/res/values-fr/strings_blockchain.xml +++ b/app/src/main/res/values-fr/strings_blockchain.xml @@ -5,7 +5,7 @@ Commission non valide Le montant minimal est de %s Le reste est trop petit - Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %s %s + commissions ou plus + Le compte cible n\'a pas été créé. Le montant à envoyer doit être de %s + commissions ou plus Pour créer un compte, envoyez 1+ XLM à cette adresse Échec de réception des commissions Erreur inconnue @@ -23,4 +23,5 @@ Invalid Memo. It won\'t be added to the transaction Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. + Destination account is not active. Send %s or more to activate the account. \ No newline at end of file diff --git a/app/src/main/res/values-it/strings_blockchain.xml b/app/src/main/res/values-it/strings_blockchain.xml index d4e7c01f40..775778dbb0 100644 --- a/app/src/main/res/values-it/strings_blockchain.xml +++ b/app/src/main/res/values-it/strings_blockchain.xml @@ -7,7 +7,7 @@ L\'importo residuo è molto basso Errore sconosciuto L\'importo supera il saldo - Per creare un account, invia %s %s a questo indirizzo + Per creare un account, invia %s a questo indirizzo Impossibile ottenere la commissione Per creare un account, invia 1+ XLM a questo indirizzo Indirizzo non valido @@ -23,4 +23,5 @@ Invalid Memo. It won\'t be added to the transaction Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. + Destination account is not active. Send %s or more to activate the account. \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings_blockchain.xml b/app/src/main/res/values-ru/strings_blockchain.xml index 102a5145b4..61a4c91467 100644 --- a/app/src/main/res/values-ru/strings_blockchain.xml +++ b/app/src/main/res/values-ru/strings_blockchain.xml @@ -7,7 +7,7 @@ Сдача слишком мала Для создания учетной записи отправьте 1+ XLM на этот адрес Не удалось получить комиссию - Целевая учетная запись не создана. Сумма для отправки должна быть %1$s %2$s + плата за создание или больше + Целевая учетная запись не создана. Сумма для отправки должна быть %s + плата за создание или больше Неизвестная ошибка Неверный адрес Недопустимая сумма @@ -18,4 +18,5 @@ Уменьшить на %s XTZ Нет, отправить все Минимальный баланс: %s + Аккаунт получателя не активирован. Отправьте %s или более для активации аккаунта. \ No newline at end of file diff --git a/app/src/main/res/values/strings_blockchain.xml b/app/src/main/res/values/strings_blockchain.xml index 1d6e8df503..6a496314b1 100644 --- a/app/src/main/res/values/strings_blockchain.xml +++ b/app/src/main/res/values/strings_blockchain.xml @@ -7,7 +7,7 @@ Change is too small To create account send 1+ XLM to this address Failed to get fee - Target account is not created. Amount to send should be %s %s + fee or more to create + Target account is not created. Amount to send should be %s + fee or more to create Unknown error Invalid address Invalid amount @@ -23,4 +23,5 @@ Invalid Memo. It won\'t be added to the transaction Invalid Tag. It won\'t be added to the transaction %s network has a concept of Existential Deposit. If your account drops below %s %s it will be deactivated and any remaining funds will be destroyed. + Destination account is not active. Send %s or more to activate the account. \ No newline at end of file