Updated on 2026-08-14
This commit is contained in:
parent
9c68c9ff00
commit
4f499f41c7
17 changed files with 159 additions and 179 deletions
|
|
@ -7,7 +7,6 @@ import arrow.core.right
|
|||
import com.squareup.moshi.Moshi
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter
|
||||
|
|
@ -15,7 +14,6 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.walletconnect.model.*
|
||||
import com.tangem.domain.walletconnect.model.sdkcopy.WcSdkSessionRequest
|
||||
|
|
@ -156,16 +154,6 @@ internal class WcEthNetwork(
|
|||
val ethChainId = chainId.reference.toIntOrNull() ?: return null
|
||||
return Blockchain.fromChainId(ethChainId)
|
||||
}
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = network.toBlockchain()
|
||||
if (!blockchain.isEvm()) return null
|
||||
val chainId = blockchain.getChainId() ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class Factories @Inject constructor(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
WcMutableFee {
|
||||
|
||||
private var approvalAmount: WcApprovedAmount? = null
|
||||
// in case of change TransactionExtras
|
||||
// change approvalAmount for example
|
||||
private var isIgnoreDAppFee: Boolean = false
|
||||
private var dAppFee: Fee? = null
|
||||
|
||||
override val securityStatus: LceFlow<Throwable, BlockAidTransactionCheck.Result> =
|
||||
|
|
@ -102,7 +105,7 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
},
|
||||
)
|
||||
approvalAmount = action.amount
|
||||
dAppFee = null
|
||||
isIgnoreDAppFee = true
|
||||
uncompiled.copy(extras = extras.copy(callData = callData))
|
||||
}
|
||||
is WcEthTxAction.UpdateFee -> uncompiled.copy(fee = action.fee)
|
||||
|
|
@ -111,8 +114,11 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
emit(newState)
|
||||
}
|
||||
|
||||
override fun dAppFee(): Fee? {
|
||||
return dAppFee
|
||||
override suspend fun dAppFee(): Fee? {
|
||||
if (isIgnoreDAppFee) return null
|
||||
if (dAppFee != null) return dAppFee
|
||||
return ethTxHelper.getDAppFee(method.transaction, wallet, network)
|
||||
.also { dAppFee = it }
|
||||
}
|
||||
|
||||
override fun updateFee(fee: Fee) {
|
||||
|
|
@ -120,9 +126,8 @@ internal class WcEthSendTransactionUseCase @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun invoke(): Flow<WcSignState<TransactionData>> = flow {
|
||||
dAppFee = ethTxHelper.getDAppFee(method.transaction, wallet, network)
|
||||
val transactionData = ethTxHelper.createTransactionData(
|
||||
dAppFee = dAppFee,
|
||||
dAppFee = dAppFee(),
|
||||
network = context.network,
|
||||
txParams = method.transaction,
|
||||
) ?: return@flow
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
|
|||
WcMutableFee {
|
||||
|
||||
private var approvalAmount: WcApprovedAmount? = null
|
||||
// in case of change TransactionExtras
|
||||
// change approvalAmount for example
|
||||
private var isIgnoreDAppFee: Boolean = false
|
||||
private var dAppFee: Fee? = null
|
||||
|
||||
override val securityStatus = blockAidDelegate.getSecurityStatus(
|
||||
|
|
@ -101,7 +104,7 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
|
|||
},
|
||||
)
|
||||
approvalAmount = action.amount
|
||||
dAppFee = null
|
||||
isIgnoreDAppFee = true
|
||||
uncompiled.copy(extras = extras.copy(callData = callData))
|
||||
}
|
||||
is WcEthTxAction.UpdateFee -> uncompiled.copy(fee = action.fee)
|
||||
|
|
@ -115,17 +118,19 @@ internal class WcEthSignTransactionUseCase @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun invoke(): Flow<WcSignState<TransactionData>> = flow {
|
||||
dAppFee = ethTxHelper.getDAppFee(method.transaction, wallet, network)
|
||||
val transactionData = ethTxHelper.createTransactionData(
|
||||
dAppFee = dAppFee,
|
||||
dAppFee = dAppFee(),
|
||||
network = context.network,
|
||||
txParams = method.transaction,
|
||||
) ?: return@flow
|
||||
emitAll(delegate.invoke(transactionData))
|
||||
}
|
||||
|
||||
override fun dAppFee(): Fee? {
|
||||
return dAppFee
|
||||
override suspend fun dAppFee(): Fee? {
|
||||
if (isIgnoreDAppFee) return null
|
||||
if (dAppFee != null) return dAppFee
|
||||
return ethTxHelper.getDAppFee(method.transaction, wallet, network)
|
||||
.also { dAppFee = it }
|
||||
}
|
||||
|
||||
override fun getAmount(): WcApprovedAmount? {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.squareup.moshi.Moshi
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.extensions.decodeBase58
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
|
|
@ -17,7 +16,6 @@ import com.tangem.data.walletconnect.request.WcRequestToUseCaseConverter.Compani
|
|||
import com.tangem.data.walletconnect.sign.WcMethodUseCaseContext
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletconnect.model.HandleMethodError
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethodName
|
||||
|
|
@ -88,27 +86,14 @@ internal class WcSolanaNetwork(
|
|||
override val namespaceKey: NamespaceKey = NamespaceKey("solana")
|
||||
|
||||
override fun toBlockchain(chainId: CAIP2): Blockchain? {
|
||||
val isMainNet = MAINNET_CHAIN_ID.any { it.lowercase() == chainId.reference.lowercase() }
|
||||
if (chainId.namespace != namespaceKey.key) return null
|
||||
return when (chainId.reference) {
|
||||
MAINNET_CHAIN_ID -> Blockchain.Solana
|
||||
TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
|
||||
return when {
|
||||
isMainNet -> Blockchain.Solana
|
||||
chainId.reference.lowercase() == TESTNET_CHAIN_ID -> Blockchain.SolanaTestnet
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun toCAIP2(network: Network): CAIP2? {
|
||||
val blockchain = network.toBlockchain()
|
||||
val chainId = when (blockchain) {
|
||||
Blockchain.Solana -> MAINNET_CHAIN_ID
|
||||
Blockchain.SolanaTestnet -> TESTNET_CHAIN_ID
|
||||
else -> null
|
||||
}
|
||||
chainId ?: return null
|
||||
return CAIP2(
|
||||
namespace = namespaceKey.key,
|
||||
reference = chainId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun WcSolanaMethodName.toMethod(request: WcSdkSessionRequest): Either<Throwable, WcSolanaMethod?> {
|
||||
|
|
@ -140,7 +125,7 @@ internal class WcSolanaNetwork(
|
|||
)
|
||||
|
||||
companion object {
|
||||
private const val MAINNET_CHAIN_ID = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
|
||||
private val MAINNET_CHAIN_ID = listOf("5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")
|
||||
private const val TESTNET_CHAIN_ID = "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
|
||||
}
|
||||
}
|
||||
|
|
@ -110,8 +110,10 @@ internal class AssociateNetworksDelegate(
|
|||
.distinctBy { it.rawId }
|
||||
}
|
||||
|
||||
private fun Map<String, Namespace.Proposal>.setOfChainId(): Set<String> =
|
||||
this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
|
||||
private fun missingNetworkName(chainId: String): String = chainId.replaceFirstChar(Char::titlecase)
|
||||
|
||||
companion object {
|
||||
internal fun Map<String, Namespace.Proposal>.setOfChainId(): Set<String> =
|
||||
this.values.flatMap { proposal -> proposal.chains ?: listOf() }.toSet()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.data.walletconnect.pair
|
|||
|
||||
import com.reown.walletkit.client.Wallet
|
||||
import com.tangem.data.walletconnect.model.CAIP10
|
||||
import com.tangem.data.walletconnect.model.CAIP2
|
||||
import com.tangem.data.walletconnect.pair.AssociateNetworksDelegate.Companion.setOfChainId
|
||||
import com.tangem.data.walletconnect.utils.WcNamespaceConverter
|
||||
import com.tangem.data.walletconnect.utils.WcNetworksConverter
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
|
@ -22,6 +24,26 @@ internal class CaipNamespaceDelegate(
|
|||
val userWallet = sessionForApprove.wallet
|
||||
val result = mutableMapOf<String, Session>()
|
||||
|
||||
val requiredNamespaces = sessionProposal.requiredNamespaces.setOfChainId()
|
||||
val optionalNamespaces = sessionProposal.optionalNamespaces.setOfChainId()
|
||||
val allWcNetworks = (requiredNamespaces + optionalNamespaces)
|
||||
.mapNotNull { chainId ->
|
||||
val network = namespaceConverters
|
||||
.firstNotNullOfOrNull { it.toNetwork(chainId, userWallet) }
|
||||
?: return@mapNotNull null
|
||||
val caip2 = CAIP2.fromRaw(chainId) ?: return@mapNotNull null
|
||||
network to caip2
|
||||
}
|
||||
|
||||
suspend fun createCAIP10(userWalletId: UserWalletId, network: Network): CAIP10? {
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, network)
|
||||
val chainId = allWcNetworks
|
||||
.find { (wcNetwork, _) -> network.rawId == wcNetwork.rawId }
|
||||
?.second
|
||||
if (chainId == null || address == null) return null
|
||||
return CAIP10(chainId = chainId, accountAddress = address)
|
||||
}
|
||||
|
||||
wcNetworksConverter.convertNetworksForApprove(sessionForApprove)
|
||||
.mapNotNull { createCAIP10(userWallet.walletId, it) }
|
||||
.forEach { account ->
|
||||
|
|
@ -52,13 +74,6 @@ internal class CaipNamespaceDelegate(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun createCAIP10(userWalletId: UserWalletId, network: Network): CAIP10? {
|
||||
val address = walletManagersFacade.getDefaultAddress(userWalletId, network)
|
||||
val chainId = namespaceConverters.firstNotNullOfOrNull { it.toCAIP2(network) }
|
||||
if (chainId == null || address == null) return null
|
||||
return CAIP10(chainId = chainId, accountAddress = address)
|
||||
}
|
||||
|
||||
private data class Session(
|
||||
val chains: MutableSet<String> = mutableSetOf(),
|
||||
val accounts: MutableSet<String> = mutableSetOf(),
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
}.onCompletion {
|
||||
if (it != null) {
|
||||
Timber.tag(WC_TAG).e(it, "Completed with error $pairRequest")
|
||||
emit(WcPairState.Error(WcPairError.Unknown(it.message.orEmpty())))
|
||||
} else {
|
||||
Timber.tag(WC_TAG).i("Completed successfully $pairRequest")
|
||||
}
|
||||
|
|
@ -134,7 +135,7 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
private suspend fun walletKitApproveSession(
|
||||
sessionForApprove: WcSessionApprove,
|
||||
sdkSessionProposal: Wallet.Model.SessionProposal,
|
||||
): Either<WcPairError, Wallet.Model.SettledSessionResponse.Result> {
|
||||
): Either<WcPairError, Wallet.Model.SettledSessionResponse.Result> = try {
|
||||
val namespaces = caipNamespaceDelegate.associate(
|
||||
sdkSessionProposal,
|
||||
sessionForApprove,
|
||||
|
|
@ -143,7 +144,10 @@ internal class DefaultWcPairUseCase @AssistedInject constructor(
|
|||
proposerPublicKey = sdkSessionProposal.proposerPublicKey,
|
||||
namespaces = namespaces,
|
||||
)
|
||||
return sdkDelegate.approve(sessionApprove)
|
||||
sdkDelegate.approve(sessionApprove)
|
||||
} catch (e: Throwable) {
|
||||
Timber.tag(WC_TAG).e(e, "Failed to sdk approve session $pairRequest")
|
||||
WcPairError.ApprovalFailed(e.message.orEmpty()).left()
|
||||
}
|
||||
|
||||
private suspend fun buildProposalState(
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ internal class WcPairSdkDelegate : WcSdkObserver {
|
|||
private fun Throwable.toApproveError() = WcPairError.ApprovalFailed(this.localizedMessage.orEmpty()).left()
|
||||
|
||||
companion object {
|
||||
private const val CALLBACK_TIMEOUT = 30
|
||||
private const val CALLBACK_TIMEOUT = 60
|
||||
// com.reown.android.pairing.engine.domain.PairingEngine.pair
|
||||
private val pairingExpiredMessages = listOf(
|
||||
"Pairing URI expired",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ internal class DefaultWcSessionsManager(
|
|||
if (someMigrated) return@transform // ignore emit, wait next one
|
||||
}
|
||||
val associatedSessions: List<WcSession> = associate(inSdk, inStore, wallets)
|
||||
val someRemove = removeUnknownSessions(inStore, associatedSessions)
|
||||
val someRemove = removeUnknownSessions(inStore, inSdk, associatedSessions)
|
||||
if (someRemove) return@transform // ignore emit, wait next one
|
||||
emit(associatedSessions.groupBy { it.wallet })
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ internal class DefaultWcSessionsManager(
|
|||
override suspend fun removeSession(session: WcSession): Either<Throwable, Unit> {
|
||||
val topic = session.sdkModel.topic
|
||||
val sdkCall = sdkDisconnectSession(topic)
|
||||
.onRight { onSessionDelete.trySend(Wallet.Model.SessionDelete.Success(topic = topic, reason = "")) }
|
||||
onSessionDelete.trySend(Wallet.Model.SessionDelete.Success(topic = topic, reason = ""))
|
||||
analytics.send(WcAnalyticEvents.SessionDisconnected(session.sdkModel.appMetaData))
|
||||
return sdkCall
|
||||
}
|
||||
|
|
@ -142,10 +142,17 @@ internal class DefaultWcSessionsManager(
|
|||
return wcSessions
|
||||
}
|
||||
|
||||
private suspend fun removeUnknownSessions(storeSessions: Set<WcSessionDTO>, wcSessions: List<WcSession>): Boolean {
|
||||
private suspend fun removeUnknownSessions(
|
||||
storeSessions: Set<WcSessionDTO>,
|
||||
inSdkSessions: List<Wallet.Model.Session>,
|
||||
wcSessions: List<WcSession>,
|
||||
): Boolean {
|
||||
val unknownStoredSessions = storeSessions
|
||||
.filterNot { dto -> wcSessions.any { it.sdkModel.topic == dto.topic } }
|
||||
val haveSomeUnknown = unknownStoredSessions.isNotEmpty()
|
||||
val unknownSdkSessions = inSdkSessions
|
||||
.filterNot { sdkSession -> wcSessions.any { it.sdkModel.topic == sdkSession.topic } }
|
||||
val haveSomeUnknownSdkSessions = unknownSdkSessions.isNotEmpty()
|
||||
|
||||
if (haveSomeUnknown) {
|
||||
Timber.tag(WC_TAG).i("removeUnknownSessions $unknownStoredSessions")
|
||||
|
|
@ -164,7 +171,10 @@ internal class DefaultWcSessionsManager(
|
|||
store.removeSessions(emptyNetworksDto)
|
||||
}
|
||||
if (haveEmptySessions) {
|
||||
emptyNetworkSessions.map { scope.launch { sdkDisconnectSession(it.sdkModel.topic) } }
|
||||
emptyNetworkSessions.forEach { scope.launch { sdkDisconnectSession(it.sdkModel.topic) } }
|
||||
}
|
||||
if (haveSomeUnknownSdkSessions) {
|
||||
unknownSdkSessions.forEach { scope.launch { sdkDisconnectSession(it.topic) } }
|
||||
}
|
||||
return haveSomeUnknown || haveEmptyDto
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ internal interface WcNamespaceConverter {
|
|||
fun toBlockchain(chainId: CAIP2): Blockchain?
|
||||
fun toBlockchain(chainId: String): Blockchain? = toCAIP2(chainId)?.let { caip2 -> toBlockchain(caip2) }
|
||||
|
||||
fun toCAIP2(network: Network): CAIP2?
|
||||
fun toCAIP2(chainId: String): CAIP2? = CAIP2.fromRaw(chainId)
|
||||
|
||||
fun toNetwork(chainId: String, wallet: UserWallet): Network? {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ interface WcListTransactionUseCase :
|
|||
* [updateFee] triggered a new [TransactionData] emit
|
||||
*/
|
||||
interface WcMutableFee {
|
||||
fun dAppFee(): Fee?
|
||||
suspend fun dAppFee(): Fee?
|
||||
fun updateFee(fee: Fee)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcTransactionUseCase
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WcCommonTransactionUMConverter @Inject constructor(
|
||||
private val signTypedDataUMConverter: WcSignTypedDataUMConverter,
|
||||
private val signTransactionUMConverter: WcSignTransactionUMConverter,
|
||||
private val sendTransactionUMConverter: WcSendTransactionUMConverter,
|
||||
) : Converter<WcCommonTransactionUMConverter.Input, WcCommonTransactionUM?> {
|
||||
|
||||
override fun convert(value: Input): WcCommonTransactionUM? {
|
||||
return when (value.useCase) {
|
||||
is WcMessageSignUseCase -> {
|
||||
when (value.useCase.method) {
|
||||
is WcEthMethod.SignTypedData -> signTypedDataUMConverter.convert(
|
||||
WcSignTypedDataUMConverter.Input(
|
||||
useCase = value.useCase,
|
||||
signState = value.signState,
|
||||
signModel = value.signState.signModel as WcMessageSignUseCase.SignModel,
|
||||
actions = value.actions,
|
||||
),
|
||||
)
|
||||
is WcEthMethod.MessageSign, is WcSolanaMethod.SignMessage -> signTransactionUMConverter.convert(
|
||||
WcSignTransactionUMConverter.Input(
|
||||
useCase = value.useCase,
|
||||
signState = value.signState,
|
||||
signModel = value.signState.signModel as WcMessageSignUseCase.SignModel,
|
||||
actions = value.actions,
|
||||
),
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
is WcTransactionUseCase -> sendTransactionUMConverter.convert(
|
||||
WcSendTransactionUMConverter.Input(
|
||||
useCase = value.useCase,
|
||||
signState = value.signState,
|
||||
actions = value.actions,
|
||||
feeSelectorUM = value.feeSelectorUM,
|
||||
),
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
data class Input(
|
||||
val useCase: WcSignUseCase<*>,
|
||||
val signState: WcSignState<*>,
|
||||
val actions: WcTransactionActionsUM,
|
||||
val feeSelectorUM: FeeSelectorUM? = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -2,7 +2,9 @@ package com.tangem.features.walletconnect.transaction.converter
|
|||
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.*
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.features.send.v2.api.entity.FeeSelectorUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
|
|
@ -20,7 +22,7 @@ internal class WcSendTransactionUMConverter @Inject constructor(
|
|||
private val requestBlockUMConverter: WcTransactionRequestBlockUMConverter,
|
||||
) : Converter<WcSendTransactionUMConverter.Input, WcSendTransactionUM?> {
|
||||
|
||||
override fun convert(value: Input): WcSendTransactionUM? = when (value.useCase.method) {
|
||||
override fun convert(value: Input): WcSendTransactionUM? = when (value.context.method) {
|
||||
is WcEthMethod.SendTransaction,
|
||||
is WcEthMethod.SignTransaction,
|
||||
is WcSolanaMethod.SignAllTransaction,
|
||||
|
|
@ -31,23 +33,23 @@ internal class WcSendTransactionUMConverter @Inject constructor(
|
|||
onSend = value.actions.onSign,
|
||||
appInfo = appInfoContentUMConverter.convert(
|
||||
WcTransactionAppInfoContentUMConverter.Input(
|
||||
session = value.useCase.session,
|
||||
session = value.context.session,
|
||||
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
|
||||
),
|
||||
),
|
||||
feeState = constructFeeState(useCase = value.useCase, actions = value.actions),
|
||||
walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.useCase.network),
|
||||
feeState = value.feeState,
|
||||
walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.context.network),
|
||||
estimatedWalletChanges = WcSendReceiveTransactionCheckResultsUM(),
|
||||
isLoading = value.signState.domainStep == WcSignStep.Signing,
|
||||
address = WcAddressConverter.convert(value.useCase.derivationState),
|
||||
address = WcAddressConverter.convert(value.context.derivationState),
|
||||
),
|
||||
feeSelectorUM = value.feeSelectorUM ?: FeeSelectorUM.Loading,
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = buildList {
|
||||
addAll(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest),
|
||||
WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest),
|
||||
),
|
||||
)
|
||||
}.toImmutableList(),
|
||||
|
|
@ -57,17 +59,9 @@ internal class WcSendTransactionUMConverter @Inject constructor(
|
|||
else -> null
|
||||
}
|
||||
|
||||
private fun constructFeeState(
|
||||
useCase: WcTransactionUseCase,
|
||||
actions: WcTransactionActionsUM,
|
||||
): WcTransactionFeeState {
|
||||
val mutableFee = useCase as? WcMutableFee ?: return WcTransactionFeeState.None
|
||||
val dAppFee = mutableFee.dAppFee()
|
||||
return WcTransactionFeeState.Success(dAppFee = dAppFee, onClick = actions.onShowFeeBottomSheet)
|
||||
}
|
||||
|
||||
data class Input(
|
||||
val useCase: WcTransactionUseCase,
|
||||
val context: WcMethodContext,
|
||||
val feeState: WcTransactionFeeState,
|
||||
val signState: WcSignState<*>,
|
||||
val actions: WcTransactionActionsUM,
|
||||
val feeSelectorUM: FeeSelectorUM?,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
|
|
@ -23,25 +24,25 @@ internal class WcSignTransactionUMConverter @Inject constructor(
|
|||
onSign = value.actions.onSign,
|
||||
appInfo = appInfoContentUMConverter.convert(
|
||||
WcTransactionAppInfoContentUMConverter.Input(
|
||||
session = value.useCase.session,
|
||||
session = value.context.session,
|
||||
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
|
||||
),
|
||||
),
|
||||
walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.useCase.network),
|
||||
walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.context.network),
|
||||
isLoading = value.signState.domainStep == WcSignStep.Signing,
|
||||
address = WcAddressConverter.convert(value.useCase.derivationState),
|
||||
address = WcAddressConverter.convert(value.context.derivationState),
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
|
||||
WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest, value.signModel),
|
||||
).toImmutableList(),
|
||||
onCopy = value.actions.onCopy,
|
||||
),
|
||||
)
|
||||
|
||||
data class Input(
|
||||
val useCase: WcMessageSignUseCase,
|
||||
val context: WcMethodContext,
|
||||
val signState: WcSignState<*>,
|
||||
val signModel: WcMessageSignUseCase.SignModel,
|
||||
val actions: WcTransactionActionsUM,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.walletconnect.transaction.converter
|
||||
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMethodContext
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
|
|
@ -23,20 +24,20 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
|
|||
onSign = value.actions.onSign,
|
||||
appInfo = appInfoContentUMConverter.convert(
|
||||
WcTransactionAppInfoContentUMConverter.Input(
|
||||
session = value.useCase.session,
|
||||
session = value.context.session,
|
||||
onShowVerifiedAlert = value.actions.onShowVerifiedAlert,
|
||||
),
|
||||
),
|
||||
walletName = value.useCase.session.wallet.name.takeIf { value.useCase.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.useCase.network),
|
||||
address = WcAddressConverter.convert(value.useCase.derivationState),
|
||||
walletName = value.context.session.wallet.name.takeIf { value.context.session.showWalletInfo },
|
||||
networkInfo = networkInfoUMConverter.convert(value.context.network),
|
||||
address = WcAddressConverter.convert(value.context.derivationState),
|
||||
isLoading = value.signState.domainStep == WcSignStep.Signing,
|
||||
),
|
||||
transactionRequestInfo = WcTransactionRequestInfoUM(
|
||||
blocks = buildList {
|
||||
addAll(
|
||||
requestBlockUMConverter.convert(
|
||||
WcTransactionRequestBlockUMConverter.Input(value.useCase.rawSdkRequest, value.signModel),
|
||||
WcTransactionRequestBlockUMConverter.Input(value.context.rawSdkRequest, value.signModel),
|
||||
),
|
||||
)
|
||||
}.toImmutableList(),
|
||||
|
|
@ -45,7 +46,7 @@ internal class WcSignTypedDataUMConverter @Inject constructor(
|
|||
)
|
||||
|
||||
data class Input(
|
||||
val useCase: WcMessageSignUseCase,
|
||||
val context: WcMethodContext,
|
||||
val signState: WcSignState<*>,
|
||||
val signModel: WcMessageSignUseCase.SignModel,
|
||||
val actions: WcTransactionActionsUM,
|
||||
|
|
|
|||
|
|
@ -36,11 +36,12 @@ import com.tangem.features.send.v2.api.subcomponents.feeSelector.FeeSelectorRelo
|
|||
import com.tangem.features.send.v2.api.subcomponents.feeSelector.entity.FeeSelectorData
|
||||
import com.tangem.features.walletconnect.connections.routing.WcInnerRoute
|
||||
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcHandleMethodErrorConverter
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcSendTransactionUMConverter
|
||||
import com.tangem.features.walletconnect.transaction.entity.blockaid.WcSendReceiveTransactionCheckResultsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionModel
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionFeeState
|
||||
import com.tangem.features.walletconnect.transaction.entity.send.WcSendTransactionUM
|
||||
import com.tangem.features.walletconnect.transaction.routes.WcTransactionRoutes
|
||||
import com.tangem.features.walletconnect.transaction.ui.blockaid.WcSendAndReceiveBlockAidUiConverter
|
||||
|
|
@ -62,7 +63,7 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
private val router: Router,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val useCaseFactory: WcRequestUseCaseFactory,
|
||||
private val converter: WcCommonTransactionUMConverter,
|
||||
private val converter: WcSendTransactionUMConverter,
|
||||
private val blockAidUiConverter: WcSendAndReceiveBlockAidUiConverter,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
private val getNetworkCoinUseCase: GetNetworkCoinStatusUseCase,
|
||||
|
|
@ -198,20 +199,28 @@ internal class WcSendTransactionModel @Inject constructor(
|
|||
is Lce.Error -> WcSendReceiveTransactionCheckResultsUM(isLoading = false)
|
||||
is Lce.Loading -> WcSendReceiveTransactionCheckResultsUM(isLoading = true)
|
||||
}
|
||||
|
||||
val feeState = when {
|
||||
useCase is WcMutableFee ->
|
||||
WcTransactionFeeState
|
||||
.Success(dAppFee = useCase.dAppFee(), onClick = { onShowFeeBottomSheet() })
|
||||
else -> WcTransactionFeeState.None
|
||||
}
|
||||
val actions = WcTransactionActionsUM(
|
||||
onShowVerifiedAlert = ::showVerifiedAlert,
|
||||
onDismiss = { cancel(useCase) },
|
||||
onSign = { onSign(securityCheck.getOrNull()) },
|
||||
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
|
||||
)
|
||||
var transactionUM = converter.convert(
|
||||
WcCommonTransactionUMConverter.Input(
|
||||
useCase = useCase,
|
||||
WcSendTransactionUMConverter.Input(
|
||||
context = useCase,
|
||||
feeState = feeState,
|
||||
signState = signState,
|
||||
actions = WcTransactionActionsUM(
|
||||
onShowVerifiedAlert = ::showVerifiedAlert,
|
||||
onDismiss = { cancel(useCase) },
|
||||
onSign = { onSign(securityCheck.getOrNull()) },
|
||||
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
|
||||
onShowFeeBottomSheet = ::onShowFeeBottomSheet,
|
||||
),
|
||||
actions = actions,
|
||||
feeSelectorUM = uiState.value?.feeSelectorUM,
|
||||
),
|
||||
) as? WcSendTransactionUM
|
||||
)
|
||||
transactionUM = transactionUM?.copy(
|
||||
transaction = transactionUM.transaction.copy(estimatedWalletChanges = blockAidState),
|
||||
spendAllowance = blockAidState.spendAllowance,
|
||||
|
|
|
|||
|
|
@ -11,13 +11,16 @@ import com.tangem.core.decompose.navigation.Router
|
|||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.domain.walletconnect.WcRequestUseCaseFactory
|
||||
import com.tangem.domain.walletconnect.model.WcEthMethod
|
||||
import com.tangem.domain.walletconnect.model.WcSolanaMethod
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcMessageSignUseCase
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignState
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignStep
|
||||
import com.tangem.domain.walletconnect.usecase.method.WcSignUseCase
|
||||
import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcCommonTransactionUMConverter
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcHandleMethodErrorConverter
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcSignTransactionUMConverter
|
||||
import com.tangem.features.walletconnect.transaction.converter.WcSignTypedDataUMConverter
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcCommonTransactionModel
|
||||
import com.tangem.features.walletconnect.transaction.entity.common.WcTransactionActionsUM
|
||||
import com.tangem.features.walletconnect.transaction.entity.sign.WcSignTransactionUM
|
||||
|
|
@ -40,7 +43,8 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
private val router: Router,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val useCaseFactory: WcRequestUseCaseFactory,
|
||||
private val converter: WcCommonTransactionUMConverter,
|
||||
private val signTypedDataUMConverter: WcSignTypedDataUMConverter,
|
||||
private val signTransactionUMConverter: WcSignTransactionUMConverter,
|
||||
) : Model(), WcCommonTransactionModel {
|
||||
|
||||
private val params = paramsContainer.require<WcTransactionModelParams>()
|
||||
|
|
@ -58,24 +62,44 @@ internal class WcSignTransactionModel @Inject constructor(
|
|||
useCase.invoke()
|
||||
.onEach { signState ->
|
||||
if (signingIsDone(signState)) return@onEach
|
||||
val signTransactionUM = converter.convert(
|
||||
WcCommonTransactionUMConverter.Input(
|
||||
useCase = useCase,
|
||||
signState = signState,
|
||||
actions = WcTransactionActionsUM(
|
||||
onShowVerifiedAlert = ::showVerifiedAlert,
|
||||
onDismiss = { cancel(useCase) },
|
||||
onSign = useCase::sign,
|
||||
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
|
||||
),
|
||||
),
|
||||
) as? WcSignTransactionUM
|
||||
val signTransactionUM = convertToUI(useCase, signState)
|
||||
_uiState.emit(signTransactionUM)
|
||||
}
|
||||
.launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertToUI(
|
||||
useCase: WcMessageSignUseCase,
|
||||
signState: WcSignState<WcMessageSignUseCase.SignModel>,
|
||||
): WcSignTransactionUM? {
|
||||
val actions = WcTransactionActionsUM(
|
||||
onShowVerifiedAlert = ::showVerifiedAlert,
|
||||
onDismiss = { cancel(useCase) },
|
||||
onSign = useCase::sign,
|
||||
onCopy = { copyData(useCase.rawSdkRequest.request.params) },
|
||||
)
|
||||
return when (useCase.method) {
|
||||
is WcEthMethod.SignTypedData -> signTypedDataUMConverter.convert(
|
||||
WcSignTypedDataUMConverter.Input(
|
||||
context = useCase,
|
||||
signState = signState,
|
||||
signModel = signState.signModel,
|
||||
actions = actions,
|
||||
),
|
||||
)
|
||||
is WcEthMethod.MessageSign, is WcSolanaMethod.SignMessage -> signTransactionUMConverter.convert(
|
||||
WcSignTransactionUMConverter.Input(
|
||||
context = useCase,
|
||||
signState = signState,
|
||||
signModel = signState.signModel,
|
||||
actions = actions,
|
||||
),
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
_uiState.value?.transaction?.onDismiss?.invoke() ?: router.pop()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue