Updated on 2026-08-14
This commit is contained in:
parent
a3295ea181
commit
aa52b659ce
7 changed files with 79 additions and 29 deletions
|
|
@ -48,19 +48,30 @@ class WalletConnectSdkHelper {
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
suspend fun prepareTransactionData(data: EthTransactionData): WcTransactionData? {
|
||||
suspend fun prepareTransactionData(data: EthTransactionData): WcTransactionData {
|
||||
val transaction = data.transaction
|
||||
val blockchain = Blockchain.fromNetworkId(data.networkId) ?: return null
|
||||
val walletManager = getWalletManager(blockchain, data.rawDerivationPath) ?: return null
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(data.networkId)) {
|
||||
"Blockchain not found"
|
||||
}
|
||||
val walletManager = requireNotNull(getWalletManager(blockchain, data.rawDerivationPath)) {
|
||||
"WalletManager not found"
|
||||
}
|
||||
|
||||
walletManager.safeUpdate(isDemoCard())
|
||||
val wallet = walletManager.wallet
|
||||
val balance = wallet.amounts[AmountType.Coin]?.value ?: return null
|
||||
val balance = requireNotNull(wallet.amounts[AmountType.Coin]?.value) {
|
||||
"Coin balance not found"
|
||||
}
|
||||
|
||||
val decimals = wallet.blockchain.decimals()
|
||||
|
||||
val value = (transaction.value ?: "0").hexToBigDecimal()
|
||||
.movePointLeft(decimals) ?: return null
|
||||
val value = (transaction.value ?: "0")
|
||||
.hexToBigDecimal()
|
||||
.movePointLeft(decimals)
|
||||
|
||||
requireNotNull(value) {
|
||||
"Transaction amount is null"
|
||||
}
|
||||
|
||||
val gasLimit = getGasLimitFromTx(value, walletManager, transaction)
|
||||
|
||||
|
|
@ -69,20 +80,23 @@ class WalletConnectSdkHelper {
|
|||
is Result.Success -> result.data.toBigDecimal()
|
||||
is Result.Failure -> {
|
||||
(result.error as? Throwable)?.let { Timber.e(it, "getGasPrice failed") }
|
||||
return null
|
||||
|
||||
error("Unable to get gas price: ${result.error}")
|
||||
}
|
||||
null -> return null
|
||||
null -> error("Gas price is null")
|
||||
}
|
||||
|
||||
val fee = (gasLimit * gasPrice).movePointLeft(decimals)
|
||||
val total = value + fee
|
||||
|
||||
val destinationAddress = requireNotNull(transaction.to) { "Destination address is null" }
|
||||
|
||||
val transactionData = TransactionData(
|
||||
amount = Amount(value, wallet.blockchain),
|
||||
// TODO refactoring
|
||||
fee = Fee.Common(Amount(fee, wallet.blockchain)),
|
||||
sourceAddress = transaction.from,
|
||||
destinationAddress = transaction.to!!,
|
||||
destinationAddress = destinationAddress,
|
||||
extras = EthereumTransactionExtras(
|
||||
data = transaction.data.removePrefix(HEX_PREFIX).hexToBytes(),
|
||||
gasLimit = gasLimit.toBigInteger(),
|
||||
|
|
@ -102,6 +116,7 @@ class WalletConnectSdkHelper {
|
|||
id = data.id,
|
||||
type = data.type,
|
||||
)
|
||||
|
||||
return WcTransactionData(
|
||||
type = data.type,
|
||||
transaction = transactionData,
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ internal class DefaultWalletConnectRepository(
|
|||
|
||||
override fun rejectRequest(requestData: RequestData, error: WalletConnectError) {
|
||||
val session = currentSessions.find { it.topic == requestData.topic }
|
||||
|
||||
analyticsHandler.send(
|
||||
WalletConnect.RequestHandled(
|
||||
WalletConnect.RequestHandledParams(
|
||||
|
|
@ -385,17 +386,18 @@ internal class DefaultWalletConnectRepository(
|
|||
),
|
||||
),
|
||||
)
|
||||
cancelRequest(requestData.topic, requestData.requestId)
|
||||
|
||||
cancelRequest(requestData.topic, requestData.requestId, error.error)
|
||||
}
|
||||
|
||||
override fun cancelRequest(topic: String, id: Long) {
|
||||
override fun cancelRequest(topic: String, id: Long, message: String) {
|
||||
Web3Wallet.respondSessionRequest(
|
||||
params = Wallet.Params.SessionRequestResponse(
|
||||
sessionTopic = topic,
|
||||
jsonRpcResponse = Wallet.Model.JsonRpcResponse.JsonRpcError(
|
||||
id = id,
|
||||
code = 0,
|
||||
message = "",
|
||||
message = message,
|
||||
),
|
||||
),
|
||||
onSuccess = {},
|
||||
|
|
@ -406,8 +408,8 @@ internal class DefaultWalletConnectRepository(
|
|||
override fun reject() {
|
||||
Web3Wallet.rejectSession(
|
||||
params = Wallet.Params.SessionReject(
|
||||
sessionProposal?.proposerPublicKey ?: "",
|
||||
"",
|
||||
proposerPublicKey = sessionProposal?.proposerPublicKey ?: "",
|
||||
reason = "",
|
||||
),
|
||||
onSuccess = {
|
||||
Timber.d("Rejected successfully: $it")
|
||||
|
|
|
|||
|
|
@ -260,10 +260,18 @@ class WalletConnectInteractor(
|
|||
)
|
||||
else -> {
|
||||
currentRequest = sessionRequest
|
||||
val data = prepareRequestData(sessionRequest)
|
||||
if (data != null) {
|
||||
handler.onSessionRequest(data)
|
||||
|
||||
val data = prepareRequestData(sessionRequest).getOrElse { e ->
|
||||
val wrappedError = e as? WalletConnectError ?: WalletConnectError.UnknownError(
|
||||
message = e.localizedMessage ?: "Unknown error",
|
||||
)
|
||||
|
||||
walletConnectRepository.rejectRequest(requestData, wrappedError)
|
||||
handler.onSessionRejected(wrappedError)
|
||||
return
|
||||
}
|
||||
|
||||
handler.onSessionRequest(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,7 +361,9 @@ class WalletConnectInteractor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun prepareRequestData(sessionRequest: WalletConnectEvents.SessionRequest): WcPreparedRequest? {
|
||||
private suspend fun prepareRequestData(
|
||||
sessionRequest: WalletConnectEvents.SessionRequest,
|
||||
): Result<WcPreparedRequest> {
|
||||
return sessionRequestConverter.prepareRequest(sessionRequest, userWalletId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,5 +27,5 @@ interface WalletConnectRepository {
|
|||
|
||||
fun rejectRequest(requestData: RequestData, error: WalletConnectError)
|
||||
|
||||
fun cancelRequest(topic: String, id: Long)
|
||||
fun cancelRequest(topic: String, id: Long, message: String = "")
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.tap.domain.walletconnect.WalletConnectSdkHelper
|
|||
import com.tangem.tap.domain.walletconnect2.domain.mapper.mapToTransaction
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.BnbData
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.EthTransactionData
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectError
|
||||
import com.tangem.tap.domain.walletconnect2.domain.models.WalletConnectEvents
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcEthTransactionType
|
||||
|
||||
|
|
@ -17,15 +18,18 @@ internal class WcSessionRequestConverter(
|
|||
suspend fun prepareRequest(
|
||||
sessionRequest: WalletConnectEvents.SessionRequest,
|
||||
userWalletId: String,
|
||||
): WcPreparedRequest? {
|
||||
val networkId = blockchainHelper.chainIdToNetworkIdOrNull(sessionRequest.chainId ?: "") ?: return null
|
||||
): Result<WcPreparedRequest> = runCatching {
|
||||
val networkId = requireNotNull(blockchainHelper.chainIdToNetworkIdOrNull(sessionRequest.chainId.orEmpty())) {
|
||||
"Failed to get network ID for chain ID: ${sessionRequest.chainId}"
|
||||
}
|
||||
val derivationPath = getDerivationPath(
|
||||
sessionsRepository = sessionsRepository,
|
||||
sessionRequest = sessionRequest,
|
||||
userWalletId = userWalletId,
|
||||
walletAddress = getWalletAddress(sessionRequest.request),
|
||||
)
|
||||
return when (val request = sessionRequest.request) {
|
||||
|
||||
when (val request = sessionRequest.request) {
|
||||
is WcRequest.EthSendTransaction -> {
|
||||
val data = sdkHelper.prepareTransactionData(
|
||||
EthTransactionData(
|
||||
|
|
@ -38,7 +42,8 @@ internal class WcSessionRequestConverter(
|
|||
metaName = sessionRequest.metaName,
|
||||
metaUrl = sessionRequest.metaUrl,
|
||||
),
|
||||
) ?: return null
|
||||
)
|
||||
|
||||
WcPreparedRequest.EthTransaction(
|
||||
preparedRequestData = data,
|
||||
topic = sessionRequest.topic,
|
||||
|
|
@ -58,7 +63,8 @@ internal class WcSessionRequestConverter(
|
|||
metaName = sessionRequest.metaName,
|
||||
metaUrl = sessionRequest.metaUrl,
|
||||
),
|
||||
) ?: return null
|
||||
)
|
||||
|
||||
WcPreparedRequest.EthTransaction(
|
||||
preparedRequestData = data,
|
||||
topic = sessionRequest.topic,
|
||||
|
|
@ -122,7 +128,7 @@ internal class WcSessionRequestConverter(
|
|||
derivationPath = derivationPath,
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
else -> throw WalletConnectError.UnsupportedMethod
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,12 @@ sealed class WalletConnectError(val error: String) : Exception() {
|
|||
override val message: String?,
|
||||
) : WalletConnectError("ExternalApprovalError")
|
||||
|
||||
object WrongUserWallet : WalletConnectError("WrongUserWallet")
|
||||
object UnsupportedMethod : WalletConnectError("UnsupportedMethod")
|
||||
object SigningError : WalletConnectError("SigningError")
|
||||
object ValidationError : WalletConnectError("ValidationError")
|
||||
data class UnknownError(
|
||||
override val message: String,
|
||||
) : WalletConnectError(message)
|
||||
|
||||
data object WrongUserWallet : WalletConnectError("WrongUserWallet")
|
||||
data object UnsupportedMethod : WalletConnectError("UnsupportedMethod")
|
||||
data object SigningError : WalletConnectError("SigningError")
|
||||
data object ValidationError : WalletConnectError("ValidationError")
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.qrscanning.models.SourceType
|
|||
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
|
||||
|
|
@ -20,6 +21,7 @@ import com.tangem.tap.features.demo.DemoHelper
|
|||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
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
|
||||
|
|
@ -135,6 +137,17 @@ class WalletConnectMiddleware {
|
|||
),
|
||||
)
|
||||
}
|
||||
is WalletConnectError.UnknownError -> {
|
||||
store.dispatchOnMain(
|
||||
GlobalAction.ShowDialog(
|
||||
AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.wallet_connect_title,
|
||||
messageId = R.string.wallet_connect_error_with_framework_message,
|
||||
args = listOf(action.error.message),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletConnectError.ExternalApprovalError -> {
|
||||
Timber.e(action.error, "ExternalApprovalError ${action.error.message}")
|
||||
// do not show dialog on this event
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue