Updated on 2026-08-14
This commit is contained in:
commit
b38bcdc546
3 changed files with 160 additions and 12 deletions
|
|
@ -0,0 +1,99 @@
|
|||
package com.tangem.tap.domain.walletconnect
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonParser
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.trustwallet.walletconnect.JSONRPC_VERSION
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage
|
||||
|
||||
class EthSignHelper {
|
||||
companion object {
|
||||
private val gson: Gson by lazy {
|
||||
GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.serializeNulls()
|
||||
.create()
|
||||
}
|
||||
|
||||
fun tryToParseEthTypedMessage(data: String): WCEthereumSignMessage? {
|
||||
val request =
|
||||
gson.fromJson<CustomJsonRpcRequests>(data)
|
||||
return if (request.method == WCMethodExtended.ETH_SIGN_TYPE_DATA_V4) {
|
||||
WCEthereumSignMessage(
|
||||
listOf(
|
||||
request.params[0].asString,
|
||||
request.params[1].asString,
|
||||
),
|
||||
WCEthereumSignMessage.WCSignType.TYPED_MESSAGE
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun tryToParseEthTypedMessageString(message: String): String? {
|
||||
return try {
|
||||
val messageString = message
|
||||
.replace("\\", "")
|
||||
.removePrefix("\"")
|
||||
.removeSuffix("\"")
|
||||
val messageJson = JsonParser().parse(messageString)
|
||||
val filteredMap = gson.fromJson<Map<*,*>>(messageJson)
|
||||
.filterKeys { it == "domain" || it == "message"}
|
||||
|
||||
gson.toJson(filteredMap)
|
||||
} catch (exception: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CustomJsonRpcRequests(
|
||||
val id: Long,
|
||||
val jsonrpc: String = JSONRPC_VERSION,
|
||||
val method: WCMethodExtended?,
|
||||
val params: JsonArray
|
||||
)
|
||||
|
||||
enum class WCMethodExtended {
|
||||
@SerializedName("wc_sessionRequest")
|
||||
SESSION_REQUEST,
|
||||
|
||||
@SerializedName("wc_sessionUpdate")
|
||||
SESSION_UPDATE,
|
||||
|
||||
@SerializedName("eth_sign")
|
||||
ETH_SIGN,
|
||||
|
||||
@SerializedName("personal_sign")
|
||||
ETH_PERSONAL_SIGN,
|
||||
|
||||
@SerializedName("eth_signTypedData")
|
||||
ETH_SIGN_TYPE_DATA,
|
||||
|
||||
@SerializedName("eth_signTypedData_v4")
|
||||
ETH_SIGN_TYPE_DATA_V4,
|
||||
|
||||
@SerializedName("eth_signTransaction")
|
||||
ETH_SIGN_TRANSACTION,
|
||||
|
||||
@SerializedName("eth_sendTransaction")
|
||||
ETH_SEND_TRANSACTION,
|
||||
|
||||
@SerializedName("bnb_sign")
|
||||
BNB_SIGN,
|
||||
|
||||
@SerializedName("bnb_tx_confirmation")
|
||||
BNB_TRANSACTION_CONFIRM,
|
||||
|
||||
@SerializedName("get_accounts")
|
||||
GET_ACCOUNTS,
|
||||
|
||||
@SerializedName("trust_signTransaction")
|
||||
SIGN_TRANSACTION;
|
||||
}
|
||||
|
|
@ -11,10 +11,7 @@ import com.tangem.tap.store
|
|||
import com.tangem.tap.walletConnectRepository
|
||||
import com.trustwallet.walletconnect.WCClient
|
||||
import com.trustwallet.walletconnect.models.WCPeerMeta
|
||||
import com.trustwallet.walletconnect.models.binance.WCBinanceCancelOrder
|
||||
import com.trustwallet.walletconnect.models.binance.WCBinanceTradeOrder
|
||||
import com.trustwallet.walletconnect.models.binance.WCBinanceTransferOrder
|
||||
import com.trustwallet.walletconnect.models.binance.WCBinanceTxConfirmParam
|
||||
import com.trustwallet.walletconnect.models.binance.*
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumTransaction
|
||||
import com.trustwallet.walletconnect.models.session.WCSession
|
||||
|
|
@ -26,6 +23,17 @@ import okhttp3.logging.HttpLoggingInterceptor
|
|||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.MutableMap
|
||||
import kotlin.collections.filter
|
||||
import kotlin.collections.first
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.get
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.map
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
import kotlin.collections.toMap
|
||||
import kotlin.collections.toMutableMap
|
||||
|
||||
class WalletConnectManager {
|
||||
|
||||
|
|
@ -402,6 +410,29 @@ class WalletConnectManager {
|
|||
onSessionClosed(session)
|
||||
}
|
||||
}
|
||||
client.onCustomRequest = { id: Long, data: String ->
|
||||
Timber.d("Custom Request")
|
||||
Timber.d(data)
|
||||
|
||||
val message = EthSignHelper.tryToParseEthTypedMessage(data)
|
||||
if (message != null) {
|
||||
Timber.d("onEthSign_v4: $message")
|
||||
FirebaseAnalyticsHandler.logWcEvent(
|
||||
FirebaseAnalyticsHandler.WcAnalyticsEvent.Action(
|
||||
FirebaseAnalyticsHandler.WcAction.PersonalSign
|
||||
)
|
||||
)
|
||||
sessions[client.session]?.toWalletConnectSession()?.let { sessionData ->
|
||||
store.dispatchOnMain(
|
||||
WalletConnectAction.HandlePersonalSignRequest(
|
||||
message,
|
||||
sessionData,
|
||||
id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -212,8 +212,15 @@ class WalletConnectSdkHelper {
|
|||
session: WalletConnectSession,
|
||||
id: Long,
|
||||
): WcPersonalSignData {
|
||||
val messageData = message.data.removePrefix(HEX_PREFIX).hexToBytes()
|
||||
val messageString = message.data.hexToAscii() ?: message.data
|
||||
val messageData =
|
||||
try {
|
||||
message.data.removePrefix(HEX_PREFIX).hexToBytes()
|
||||
} catch (exception: Exception) {
|
||||
message.data.asciiToHex()!!.hexToBytes()
|
||||
}
|
||||
val messageString = message.data.hexToAscii()
|
||||
?: EthSignHelper.tryToParseEthTypedMessageString(message.data)
|
||||
?: message.data
|
||||
|
||||
val prefixData = (ETH_MESSAGE_PREFIX + messageData.size.toString()).toByteArray()
|
||||
val hashToSign = (prefixData + messageData).toKeccak()
|
||||
|
|
@ -235,12 +242,23 @@ class WalletConnectSdkHelper {
|
|||
}
|
||||
|
||||
private fun String.hexToAscii(): String? {
|
||||
return removePrefix(HEX_PREFIX).hexToBytes()
|
||||
.map {
|
||||
val char = it.toInt().toChar()
|
||||
if (char.isAscii()) char else return null
|
||||
}
|
||||
.joinToString("")
|
||||
return try {
|
||||
removePrefix(HEX_PREFIX).hexToBytes()
|
||||
.map {
|
||||
val char = it.toInt().toChar()
|
||||
if (char.isAscii()) char else return null
|
||||
}
|
||||
.joinToString("")
|
||||
} catch (exception: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.asciiToHex(): String? {
|
||||
return map {
|
||||
if (!it.isAscii()) return null
|
||||
Integer.toHexString(it.code)
|
||||
}.joinToString("")
|
||||
}
|
||||
|
||||
suspend fun signPersonalMessage(hashToSign: ByteArray, wallet: WalletForSession): String? {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue