diff --git a/app/libs/walletconnect-1.5.5.aar b/app/libs/walletconnect-1.5.5.aar new file mode 100644 index 0000000000..4e2f1b4fb7 Binary files /dev/null and b/app/libs/walletconnect-1.5.5.aar differ diff --git a/app/libs/walletconnect.aar b/app/libs/walletconnect.aar deleted file mode 100644 index 129de60a79..0000000000 Binary files a/app/libs/walletconnect.aar and /dev/null differ 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 6329729b5d..07582f5c87 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -9,6 +9,7 @@ import com.tangem.tap.common.ui.SimpleCancelableAlertDialog import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.ApproveWcSessionDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.BnbTransactionDialog +import com.tangem.tap.features.details.ui.walletconnect.dialogs.ChooseNetworkDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.ClipboardOrScanQrDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialog import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionDialog @@ -58,7 +59,7 @@ class DialogManager : StoreSubscriber { return } val context = context ?: return - if (dialog != null) return + if (dialog != null && dialog == state.dialog) return dialog = when (state.dialog) { is AppDialog.SimpleOkDialog -> SimpleOkDialog.create(state.dialog, context) @@ -87,18 +88,20 @@ class DialogManager : StoreSubscriber { SimpleAlertDialog.create( titleRes = R.string.wallet_connect, messageRes = R.string.wallet_connect_same_wcuri, - context = context + context = context, ) } is WalletConnectDialog.SessionTimeout -> { SimpleAlertDialog.create( titleRes = R.string.wallet_connect, messageRes = R.string.wallet_connect_error_timeout, - context = context + context = context, ) } is WalletConnectDialog.ApproveWcSession -> - ApproveWcSessionDialog.create(state.dialog.session, context) + ApproveWcSessionDialog.create(state.dialog.session, state.dialog.networks, context) + is WalletConnectDialog.ChooseNetwork -> + ChooseNetworkDialog.create(state.dialog.networks, context) is WalletConnectDialog.ClipboardOrScanQr -> ClipboardOrScanQrDialog.create(state.dialog.clipboardUri, context) is WalletConnectDialog.RequestTransaction -> @@ -112,7 +115,7 @@ class DialogManager : StoreSubscriber { sessionId = state.dialog.sessionId, cardId = state.dialog.cardId, dAppName = state.dialog.dAppName, - context = context + context = context, ) is WalletConnectDialog.UnsupportedNetwork -> SimpleAlertDialog.create( diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt index 7a0488d1a5..f29950807f 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt @@ -76,6 +76,6 @@ fun Store<*>.dispatchDialogShow(dialog: StateDialog) { fun Store<*>.dispatchDialogHide() { scope.launch(Dispatchers.Main) { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index 4927405ccd..5e74cc3d0b 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -34,7 +34,7 @@ sealed class GlobalAction : Action { // dialogs data class ShowDialog(val stateDialog: StateDialog) : GlobalAction() - object HideDialog : GlobalAction() + data class HideDialog(val stateDialog: StateDialog? = null) : GlobalAction() sealed class Onboarding { data class Start(val scanResponse: ScanResponse?, val fromHomeScreen: Boolean = true) : GlobalAction() diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 449d47ae10..d8804bb12a 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -68,7 +68,11 @@ fun globalReducer(action: Action, state: AppState): GlobalState { globalState.copy(dialog = action.stateDialog) } is GlobalAction.HideDialog -> { - globalState.copy(dialog = null) + if (action.stateDialog == null || action.stateDialog == globalState.dialog) { + globalState.copy(dialog = null) + } else { + globalState + } } is GlobalAction.ExchangeManager.Init.Success -> { globalState.copy(exchangeManager = action.exchangeManager) diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt index 8cd6e7e5ba..fbb6528a7a 100644 --- a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt +++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt @@ -51,7 +51,7 @@ class SimpleCancelableAlertDialog { setNegativeButton(context.getText(secondaryButtonRes)) { _, _ -> secondaryButtonAction()} } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } 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 7d36064f1e..b25ae971e7 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 @@ -5,7 +5,13 @@ import com.tangem.common.extensions.guard import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.features.details.redux.walletconnect.* +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession +import com.tangem.tap.features.details.redux.walletconnect.WalletForSession +import com.tangem.tap.features.details.redux.walletconnect.WcPersonalSignData +import com.tangem.tap.features.details.redux.walletconnect.WcTransactionData +import com.tangem.tap.features.details.redux.walletconnect.WcTransactionType import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.walletConnectRepository @@ -427,22 +433,30 @@ class WalletConnectManager { onSessionClosed(session) } } + client.onWalletChangeNetwork = { id: Long, chainId: Int -> + Timber.d("On WC Switch Chain") + val blockchain = Blockchain.fromChainId(chainId) + Timber.d("WC switch chainID\nNew Blockchain: $blockchain") + val session = sessions[client.session]?.toWalletConnectSession() + if (session != null) { + store.dispatchOnMain(WalletConnectAction.SwitchBlockchain(blockchain, session)) + } + } client.onCustomRequest = { id: Long, data: String -> Timber.d("Custom Request") Timber.d(data) - val request = EthSignHelper.parseCustomRequest(data) when (request.method) { WCMethodExtended.ETH_SIGN_TYPE_DATA_V4 -> handleTypedDataV4(request, client, id) - WCMethodExtended.SWITCH_CHAIN -> { - val blockchain = request.blockchainFromChainId() - Timber.d("WC switch chainID\nNew Blockchain: $blockchain") - val session = sessions[client.session]?.toWalletConnectSession() - if (session != null) { - store.dispatchOnMain(WalletConnectAction.SwitchBlockchain(blockchain, session)) - } - } + // WCMethodExtended.SWITCH_CHAIN -> { + // val blockchain = request.blockchainFromChainId() + // Timber.d("WC switch chainID\nNew Blockchain: $blockchain") + // val session = sessions[client.session]?.toWalletConnectSession() + // if (session != null) { + // store.dispatchOnMain(WalletConnectAction.SwitchBlockchain(blockchain, session)) + // } + // } else -> { Timber.d("WC: unrecognized custom request") } 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 988207c5e6..fe1e16e326 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,7 +1,6 @@ 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 @@ -22,21 +21,17 @@ sealed class WalletConnectAction : Action { ) : WalletConnectAction() data class ShowClipboardOrScanQrDialog(val wcUri: String) : WalletConnectAction() - object UnsupportedCard : WalletConnectAction() - data class OpenSession( val wcUri: String, ) : WalletConnectAction() - data class AddScanResponse( - val scanResponse: ScanResponse - ): WalletConnectAction() + data class SetNewSessionData( + val newSession: DataForNewSession, + ) : WalletConnectAction() object RefuseOpeningSession : WalletConnectAction() - data class OpeningSessionTimeout(val session: WCSession) : WalletConnectAction() - data class ScanCard( val session: WalletConnectSession, val chainId: Int?, ) : WalletConnectAction() @@ -49,16 +44,16 @@ sealed class WalletConnectAction : Action { data class SwitchBlockchain( val blockchain: Blockchain?, - val session: WalletConnectSession + val session: WalletConnectSession, ) : WalletConnectAction() + data class SelectNetwork(val networks: List) : WalletConnectAction() + data class ChooseNetwork(val blockchain: Blockchain) : WalletConnectAction() data class UpdateBlockchain( - val updatedSession: WalletConnectSession + val updatedSession: WalletConnectSession, ) : WalletConnectAction() - data class FailureEstablishingSession(val session: WCSession?) : WalletConnectAction() - data class SetSessionsRestored(val sessions: List) : 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 61bfaf5e79..11f1a35c7f 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 @@ -1,8 +1,11 @@ package com.tangem.tap.features.details.redux.walletconnect import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.DerivationStyle +import com.tangem.common.card.Card import com.tangem.common.extensions.guard import com.tangem.domain.common.ScanResponse +import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.AppState @@ -16,16 +19,17 @@ import com.tangem.tap.domain.walletconnect.WalletConnectManager import com.tangem.tap.domain.walletconnect.WalletConnectNetworkUtils import com.tangem.tap.domain.walletconnect.WcWalletManagerFactory 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() - val walletConnectMiddleware: Middleware = { dispatch, state -> { next -> { action -> @@ -57,13 +61,22 @@ class WalletConnectMiddleware { store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.QrScan)) } } + is WalletConnectAction.SelectNetwork -> { + store.dispatch(GlobalAction.ShowDialog(WalletConnectDialog.ChooseNetwork(action.networks))) + } + is WalletConnectAction.ChooseNetwork -> { + val data = state()?.walletConnectState?.newSessionData ?: return + scope.launch { + prepareWalletManager(data.scanResponse, store.state.walletState, action.blockchain, data.session) + } + } is WalletConnectAction.ShowClipboardOrScanQrDialog -> { store.dispatchOnMain( GlobalAction.ShowDialog( WalletConnectDialog.ClipboardOrScanQr( - action.wcUri - ) - ) + action.wcUri, + ), + ), ) } is WalletConnectAction.OpeningSessionTimeout -> { @@ -85,8 +98,8 @@ class WalletConnectMiddleware { is WalletConnectAction.RefuseOpeningSession -> { store.dispatch( GlobalAction.ShowDialog( - WalletConnectDialog.OpeningSessionRejected - ) + WalletConnectDialog.OpeningSessionRejected, + ), ) } is WalletConnectAction.ScanCard -> { @@ -103,14 +116,14 @@ class WalletConnectMiddleware { transaction = action.transaction, session = action.session, id = action.id, - type = action.type + type = action.type, ) } is WalletConnectAction.HandlePersonalSignRequest -> { walletConnectManager.handlePersonalSignRequest( message = action.message, session = action.session, - id = action.id + id = action.id, ) } is WalletConnectAction.RejectRequest -> { @@ -131,9 +144,9 @@ class WalletConnectMiddleware { session = action.sessionData.session, sessionId = action.id, cardId = action.sessionData.wallet.cardId, - dAppName = action.sessionData.peerMeta.name - ) - ) + dAppName = action.sessionData.peerMeta.name, + ), + ), ) } is WalletConnectAction.BinanceTransaction.Transfer -> { @@ -145,47 +158,48 @@ class WalletConnectMiddleware { session = action.sessionData.session, sessionId = action.id, cardId = action.sessionData.wallet.cardId, - dAppName = action.sessionData.peerMeta.name - ) - ) + dAppName = action.sessionData.peerMeta.name, + ), + ), ) } is WalletConnectAction.BinanceTransaction.Sign -> { walletConnectManager.signBnb( - action.id, action.data, action.sessionData + action.id, action.data, action.sessionData, ) } is WalletConnectAction.SwitchBlockchain -> { + if (action.session.wallet.derivationStyle == DerivationStyle.LEGACY) { + Timber.d("Cannot switch chains on AC01/AC02 wallets") + return + } val blockchain = action.blockchain.guard { store.dispatchOnMain(GlobalAction.ShowDialog(WalletConnectDialog.UnsupportedNetwork)) return } - val factory = WcWalletManagerFactory( factory = store.state.globalState.tapWalletManager.walletManagerFactory, - currenciesRepository = currenciesRepository + currenciesRepository = currenciesRepository, ) val walletState = store.state.walletState scope.launch { val walletManager = factory.getWalletManager( - wallet = action.session.wallet, - blockchain = blockchain, - walletState = walletState - ).guard { + wallet = action.session.wallet, + blockchain = blockchain, + walletState = walletState, + ).guard { store.dispatchOnMain( GlobalAction.ShowDialog( - WalletConnectDialog.AddNetwork(blockchain.fullName) - ) + 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 - + blockchain = action.blockchain, ) val updatedSession = action.session.copy(wallet = updatedWallet) store.dispatchOnMain(WalletConnectAction.UpdateBlockchain(updatedSession)) @@ -199,7 +213,7 @@ class WalletConnectMiddleware { private fun scanCard(session: WalletConnectSession, chainId: Int?) { val blockchain = WalletConnectNetworkUtils.parseBlockchain( - chainId = chainId, peer = session.peerMeta + chainId = chainId, peer = session.peerMeta, ) ?: Blockchain.Ethereum store.dispatch( @@ -210,36 +224,47 @@ class WalletConnectMiddleware { }, onFailure = { store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(null)) - }, R.string.wallet_connect_scan_card_message - ) + }, + R.string.wallet_connect_scan_card_message, + ), ) } - private fun handleScanResponse( - scanResponse: ScanResponse, session: WalletConnectSession, blockchain: Blockchain - ) { - val card = scanResponse.card - if (!card.isMultiwalletAllowed) { - store.dispatchOnMain(WalletConnectAction.UnsupportedCard) - return + private suspend fun getAvailableBlockchains(card: Card, walletState: WalletState): List { + return if (walletState.cardId == card.cardId) { + walletState.currencies.filter { + it.isBlockchain() && !it.isCustomCurrency(card.derivationStyle) && it.blockchain.isEvm() + }.map { it.blockchain } + } else { + currenciesRepository + .loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed) + .filter { + it.blockchain.isEvm() && + it.derivationPath == it.blockchain.derivationPath(card.derivationStyle)?.rawPath + } + .map { it.blockchain } } + } + private suspend fun prepareWalletManager( + scanResponse: ScanResponse, + walletState: WalletState, + blockchain: Blockchain, + session: WalletConnectSession, + ) { val factory = WcWalletManagerFactory( factory = store.state.globalState.tapWalletManager.walletManagerFactory, - currenciesRepository = currenciesRepository + currenciesRepository = currenciesRepository, ) - val walletState = store.state.walletState - scope.launch { - val walletManager = factory.getWalletManager(scanResponse, blockchain, walletState).guard { - store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(session.session)) - store.dispatchOnMain( - GlobalAction.ShowDialog( - WalletConnectDialog.AddNetwork(blockchain.fullName) - ) - ) - return@launch - } - + val walletManager = factory.getWalletManager(scanResponse, blockchain, walletState).guard { + store.dispatchOnMain(WalletConnectAction.FailureEstablishingSession(session.session)) + store.dispatchOnMain( + GlobalAction.ShowDialog( + WalletConnectDialog.AddNetwork(blockchain.fullName), + ), + ) + return + } val wallet = walletManager.wallet val derivedKey = if (wallet.publicKey.blockchainKey.contentEquals(wallet.publicKey.seedKey)) { @@ -252,24 +277,48 @@ class WalletConnectMiddleware { walletPublicKey = wallet.publicKey.seedKey, derivedPublicKey = derivedKey, derivationPath = wallet.publicKey.derivationPath, - blockchain = wallet.blockchain + derivationStyle = scanResponse.card.derivationStyle, + blockchain = wallet.blockchain, ) + withMainContext { + val updatedSession = session.copy(wallet = walletForSession) + walletConnectManager.updateSession(updatedSession) + + store.dispatch(WalletConnectAction.ApproveSession(session.session)) + } + } + + private fun handleScanResponse( + scanResponse: ScanResponse, session: WalletConnectSession, blockchain: Blockchain, + ) { + val card = scanResponse.card + if (!card.isMultiwalletAllowed) { + store.dispatchOnMain(WalletConnectAction.UnsupportedCard) + return + } + val walletState = store.state.walletState + val updatedSession = session.copy(wallet = session.wallet.copy(blockchain = blockchain)) + store.dispatch( + WalletConnectAction.SetNewSessionData( + DataForNewSession( + updatedSession, scanResponse, blockchain, + ), + ), + ) + + scope.launch { + val blockchains = if (blockchain.isEvm()) getAvailableBlockchains(card, walletState) else emptyList() + withMainContext { - val updatedSession = session.copy(wallet = walletForSession) - walletConnectManager.updateSession(updatedSession) - - store.dispatch(WalletConnectAction.AddScanResponse(scanResponse)) - store.dispatch( GlobalAction.ShowDialog( WalletConnectDialog.ApproveWcSession( - updatedSession - ) - ) + updatedSession, blockchains, + ), + ), ) } } - } } \ No newline at end of file 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 191fa7b170..544b6fa7be 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 @@ -13,18 +13,17 @@ class WalletConnectReducer { is WalletConnectAction.ApproveSession.Success -> { state.copy( loading = false, - sessions = state.sessions + action.session + sessions = state.sessions + action.session, ) } - is WalletConnectAction.OpenSession -> { + is WalletConnectAction.OpenSession -> { state.copy(loading = true) } - is WalletConnectAction.AddScanResponse -> { - state.copy(scanResponse = action.scanResponse) + is WalletConnectAction.SetNewSessionData -> { + state.copy(newSessionData = action.newSession) } is WalletConnectAction.SetSessionsRestored -> WalletConnectState(sessions = action.sessions) - is WalletConnectAction.RemoveSession -> { val sessions = state.sessions.filterNot { it.session.toUri() == action.session.toUri() } 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 fbd95c6393..2c6c6db95c 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 @@ -2,6 +2,7 @@ package com.tangem.tap.features.details.redux.walletconnect import com.squareup.moshi.JsonClass import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.DerivationStyle import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.WalletManager import com.tangem.common.hdWallet.DerivationPath @@ -15,7 +16,13 @@ import com.trustwallet.walletconnect.models.session.WCSession data class WalletConnectState( val loading: Boolean = false, val sessions: List = listOf(), - val scanResponse: ScanResponse? = null + val newSessionData: DataForNewSession? = null, +) + +data class DataForNewSession( + val session: WalletConnectSession, + val scanResponse: ScanResponse, + val blockchain: Blockchain?, ) data class WalletConnectSession( @@ -37,8 +44,9 @@ data class WalletForSession( val walletPublicKey: ByteArray? = null, val derivedPublicKey: ByteArray? = null, val derivationPath: DerivationPath? = null, + val derivationStyle: DerivationStyle? = null, val isTestNet: Boolean = false, - val blockchain: Blockchain? = if (isTestNet) Blockchain.EthereumTestnet else Blockchain.Ethereum + val blockchain: Blockchain? = if (isTestNet) Blockchain.EthereumTestnet else Blockchain.Ethereum, ) { fun getBlockchainForSession(): Blockchain { @@ -86,16 +94,24 @@ sealed class WalletConnectDialog : StateDialog { data class AddNetwork(val network: String) : WalletConnectDialog() object OpeningSessionRejected : WalletConnectDialog() object SessionTimeout : WalletConnectDialog() - data class ApproveWcSession(val session: WalletConnectSession) : WalletConnectDialog() + data class ApproveWcSession( + val session: WalletConnectSession, val networks: List, + ) : WalletConnectDialog() + + data class ChooseNetwork( + val networks: List, + ) : WalletConnectDialog() + data class RequestTransaction(val dialogData: TransactionRequestDialogData) : WalletConnectDialog() data class PersonalSign(val data: PersonalSignDialogData) : WalletConnectDialog() - data class BnbTransactionDialog(val data: BinanceMessageData, - val session: WCSession, - val sessionId: Long, - val cardId: String, - val dAppName: String + data class BnbTransactionDialog( + 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/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt index 34147c0b72..8d3de292ae 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt @@ -11,6 +11,7 @@ import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater import com.google.accompanist.appcompattheme.AppCompatTheme import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState import com.tangem.tap.store import org.rekotlin.StoreSubscriber @@ -38,7 +39,16 @@ class WalletConnectFragment : Fragment(), StoreSubscriber { AppCompatTheme { WalletConnectScreen( state = screenState.value, - onBackPressed = { store.dispatch(NavigationAction.PopBackTo()) }, + onBackPressed = { + if (screenState.value.isLoading) { + store.dispatch( + WalletConnectAction.FailureEstablishingSession( + store.state.walletConnectState.newSessionData?.session?.session, + ), + ) + } + store.dispatch(NavigationAction.PopBackTo()) + }, ) } } 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 84b9151436..83569b788b 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 @@ -2,34 +2,43 @@ package com.tangem.tap.features.details.ui.walletconnect.dialogs import android.content.Context import androidx.appcompat.app.AlertDialog +import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession import com.tangem.tap.store import com.tangem.wallet.R class ApproveWcSessionDialog { companion object { - fun create(session: WalletConnectSession, context: Context): AlertDialog { + 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 + session.peerMeta.url, ) return AlertDialog.Builder(context).apply { setTitle(context.getString(R.string.wallet_connect)) setMessage(message) setPositiveButton(context.getText(R.string.common_start)) { _, _ -> - store.dispatch(WalletConnectAction.ApproveSession( - session.session - )) + store.dispatch( + WalletConnectAction.ChooseNetwork( + session.wallet.blockchain!!, + ), + ) + } + if (networks.size > 1) { + setNeutralButton(context.getText(R.string.wallet_connect_select_network)) { _, _ -> + store.dispatch(WalletConnectAction.SelectNetwork(networks)) + } } setNegativeButton(context.getText(R.string.common_reject)) { _, _ -> store.dispatch(WalletConnectAction.FailureEstablishingSession(session.session)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog(WalletConnectDialog.ApproveWcSession(session, networks))) } }.create() } 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..1763c140d0 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 @@ -58,7 +58,7 @@ class BnbTransactionDialog { store.dispatch(WalletConnectAction.RejectRequest(session, sessionId)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt new file mode 100644 index 0000000000..2b1779dafc --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ChooseNetworkDialog.kt @@ -0,0 +1,34 @@ +package com.tangem.tap.features.details.ui.walletconnect.dialogs + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.tangem.blockchain.common.Blockchain +import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction +import com.tangem.tap.store +import com.tangem.wallet.R + +object ChooseNetworkDialog { + fun create( + blockchains: List, + context: Context, + ): AlertDialog { + return AlertDialog.Builder(context) + .setTitle(context.getString(R.string.wallet_connect_select_network)) + .setNegativeButton(context.getString(R.string.common_cancel)) { _, _ -> /* no-op */ } + .setOnDismissListener { + store.dispatch(GlobalAction.HideDialog()) + } + .setSingleChoiceItems(blockchains.map { it.fullName }.toTypedArray(), 0) { _, which -> + blockchains.getOrNull(which)?.let { selectedBlockchain -> + store.dispatch( + WalletConnectAction.ChooseNetwork( + blockchain = selectedBlockchain, + ), + ) + store.dispatch(GlobalAction.HideDialog()) + } + } + .create() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt index 809b37cf66..30604f69e9 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/dialogs/ClipboardOrScanQrDialog.kt @@ -22,7 +22,7 @@ class ClipboardOrScanQrDialog { store.dispatch(NavigationAction.NavigateTo(AppScreen.QrScan)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } 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..ebbf5ac86c 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 @@ -29,7 +29,7 @@ class PersonalSignDialog { store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } 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..81d5fd6770 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 @@ -45,7 +45,7 @@ class TransactionDialog { store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id)) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt index 883ce390dc..0c8b5d924e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/AddMoreBackupCardsDialog.kt @@ -20,7 +20,7 @@ class AddMoreBackupCardsDialog { } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt index 9b619eef7d..f6ef3c6138 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/BackupInProgressDialog.kt @@ -13,10 +13,10 @@ class BackupInProgressDialog { setTitle(R.string.alert_title) setMessage(R.string.onboarding_backup_exit_warning) setPositiveButton(R.string.warning_button_ok) { _, _ -> - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt index 8b88890be8..6ed98a06cc 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/ConfirmDiscardingBackupDialog.kt @@ -20,7 +20,7 @@ class ConfirmDiscardingBackupDialog { store.dispatch(BackupAction.DiscardSavedBackup) } setOnDismissListener { - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) } setCancelable(false) }.create() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt index 41ccf7083b..9419fb3965 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/dialogs/UnfinishedBackupFoundDialog.kt @@ -15,12 +15,12 @@ class UnfinishedBackupFoundDialog { setTitle(R.string.alert_title) setMessage(R.string.welcome_interrupted_backup_alert_message) setPositiveButton(R.string.welcome_interrupted_backup_alert_resume) { _, _ -> - store.dispatch(GlobalAction.HideDialog) + store.dispatch(GlobalAction.HideDialog()) store.dispatch(BackupAction.ResumeBackup) } setNegativeButton(R.string.welcome_interrupted_backup_alert_discard) { _, _ -> - store.dispatch(GlobalAction.HideDialog) - store.dispatch(GlobalAction.ShowDialog(BackupDialog.ConfirmDiscardingBackup)) + store.dispatch(GlobalAction.HideDialog()) + store.dispatch(GlobalAction.ShowDialog(BackupDialog.ConfirmDiscardingBackup)) } setCancelable(false) }.create() diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index cb51a59e81..4fb2fa8dcb 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -93,4 +93,6 @@ Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + + Select network \ 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 db5cb3bd3d..55f342c1af 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -93,4 +93,6 @@ Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + + Select network \ 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 aa671c19a4..939315c9a1 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -94,4 +94,6 @@ Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + + Select network \ 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 9c4dc47dd3..f7ddc1c883 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -110,4 +110,6 @@ Сбросить карту Сброс к заводским настройкам Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа. + + Выберите сеть diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 44984bde11..53782ce6b3 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -112,4 +112,6 @@ Reset the card Reset to Factory Settings Factory Reset will completely delete the wallet from the selected card. You will not be able to restore the current wallet or use the card to recover the access code. + + Select network