diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/EthSignHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/EthSignHelper.kt new file mode 100644 index 0000000000..fe8a593787 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/EthSignHelper.kt @@ -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(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>(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; +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt index c5e727e23b..2a071fa5ce 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectManager.kt @@ -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 { diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 74f1abc2b0..ad8b9084be 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -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? {