Updated on 2026-08-14

This commit is contained in:
Tangem 2022-01-13 09:06:47 +00:00
commit b38bcdc546
3 changed files with 160 additions and 12 deletions

View file

@ -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;
}

View file

@ -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 {

View file

@ -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? {