Updated on 2026-08-14
This commit is contained in:
commit
e22641bb3f
28 changed files with 253 additions and 123 deletions
BIN
app/libs/walletconnect-1.5.5.aar
Normal file
BIN
app/libs/walletconnect-1.5.5.aar
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -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<GlobalState> {
|
|||
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<GlobalState> {
|
|||
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<GlobalState> {
|
|||
sessionId = state.dialog.sessionId,
|
||||
cardId = state.dialog.cardId,
|
||||
dAppName = state.dialog.dAppName,
|
||||
context = context
|
||||
context = context,
|
||||
)
|
||||
is WalletConnectDialog.UnsupportedNetwork ->
|
||||
SimpleAlertDialog.create(
|
||||
|
|
|
|||
|
|
@ -76,6 +76,6 @@ fun Store<*>.dispatchDialogShow(dialog: StateDialog) {
|
|||
|
||||
fun Store<*>.dispatchDialogHide() {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class SimpleCancelableAlertDialog {
|
|||
setNegativeButton(context.getText(secondaryButtonRes)) { _, _ -> secondaryButtonAction()}
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,22 @@ 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))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Timber.d("WC: unrecognized custom request")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: NewWcSessionData,
|
||||
) : 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<Blockchain>) : 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<WalletConnectSession>) :
|
||||
WalletConnectAction()
|
||||
|
||||
|
|
|
|||
|
|
@ -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<AppState> = { 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,47 +213,59 @@ 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(
|
||||
GlobalAction.ScanCard(
|
||||
additionalBlockchainsToDerive = listOf(blockchain),
|
||||
onSuccess = { scanResponse ->
|
||||
handleScanResponse(scanResponse, session, blockchain)
|
||||
handleScanResponse(scanResponse = scanResponse, session = session, blockchain = blockchain)
|
||||
},
|
||||
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<Blockchain> {
|
||||
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 +278,46 @@ 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(
|
||||
NewWcSessionData(session = updatedSession, scanResponse = scanResponse, blockchain = 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
|
||||
)
|
||||
)
|
||||
WalletConnectDialog.ApproveWcSession(session = updatedSession, networks = blockchains),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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<WalletConnectSession> = listOf(),
|
||||
val scanResponse: ScanResponse? = null
|
||||
val newSessionData: NewWcSessionData? = null,
|
||||
)
|
||||
|
||||
data class NewWcSessionData(
|
||||
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<Blockchain>,
|
||||
) : WalletConnectDialog()
|
||||
|
||||
data class ChooseNetwork(
|
||||
val networks: List<Blockchain>,
|
||||
) : 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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<WalletConnectState> {
|
|||
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())
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,34 +2,39 @@ 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<Blockchain>, 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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class BnbTransactionDialog {
|
|||
store.dispatch(WalletConnectAction.RejectRequest(session, sessionId))
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Blockchain>,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ class ClipboardOrScanQrDialog {
|
|||
store.dispatch(NavigationAction.NavigateTo(AppScreen.QrScan))
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class PersonalSignDialog {
|
|||
store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id))
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class TransactionDialog {
|
|||
store.dispatch(WalletConnectAction.RejectRequest(data.session, data.id))
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class AddMoreBackupCardsDialog {
|
|||
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
}.create()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class ConfirmDiscardingBackupDialog {
|
|||
store.dispatch(BackupAction.DiscardSavedBackup)
|
||||
}
|
||||
setOnDismissListener {
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.HideDialog())
|
||||
}
|
||||
setCancelable(false)
|
||||
}.create()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -93,4 +93,6 @@
|
|||
<string name="reset_card_to_factory_button_title">Reset the card</string>
|
||||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">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.</string>
|
||||
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
</resources>
|
||||
|
|
@ -93,4 +93,6 @@
|
|||
<string name="reset_card_to_factory_button_title">Reset the card</string>
|
||||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">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.</string>
|
||||
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
</resources>
|
||||
|
|
@ -94,4 +94,6 @@
|
|||
<string name="reset_card_to_factory_button_title">Reset the card</string>
|
||||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">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.</string>
|
||||
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
</resources>
|
||||
|
|
@ -110,4 +110,6 @@
|
|||
<string name="reset_card_to_factory_button_title">Сбросить карту</string>
|
||||
<string name="card_settings_reset_card_to_factory">Сброс к заводским настройкам</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты. Вы не сможете восстановить текущий кошелек или использовать эту карту для восстановления кода доступа.</string>
|
||||
|
||||
<string name="wallet_connect_select_network">Выберите сеть</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -112,4 +112,6 @@
|
|||
<string name="reset_card_to_factory_button_title">Reset the card</string>
|
||||
<string name="card_settings_reset_card_to_factory">Reset to Factory Settings</string>
|
||||
<string name="card_settings_reset_card_to_factory_footer">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.</string>
|
||||
|
||||
<string name="wallet_connect_select_network">Select network</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue