diff --git a/README.md b/README.md index 1ff0885..e21682b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ At the moment all dApps tested worked fine. The implemented functions are: * eth_sendRawTransaction * eth_signTransaction * eth_sign +* eth_signTypedData * personal_sign ### Seed management @@ -36,7 +37,6 @@ At the moment all dApps tested worked fine. The implemented functions are: * allow switching account (BIP32 path) on card and used network (for WalletConnect) ## What needs to be done for 1.0 -* implement signedTypedData (WalletConnect integration) * design and implement a user-friendly UI ## Future plans (after 1.0) diff --git a/app/build.gradle b/app/build.gradle index a63f48e..109ce9c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,6 +68,8 @@ dependencies { implementation "com.github.komputing.kethereum:extensions_kotlin:$kethereum_version" implementation "com.github.komputing.kethereum:keccak_shortcut:$kethereum_version" implementation 'com.github.komputing:khex:1.0.0' + implementation 'com.github.gnosis.svalinn-kotlin:eip712-adapter-moshi:v0.13.0' + implementation 'com.github.gnosis.svalinn-kotlin:eip712:v0.13.0' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' diff --git a/app/src/main/java/im/status/keycard/connect/net/WalletConnect.kt b/app/src/main/java/im/status/keycard/connect/net/WalletConnect.kt index 47b2ce9..003e596 100644 --- a/app/src/main/java/im/status/keycard/connect/net/WalletConnect.kt +++ b/app/src/main/java/im/status/keycard/connect/net/WalletConnect.kt @@ -39,7 +39,11 @@ import org.walletconnect.impls.FileWCSessionStore import org.walletconnect.impls.MoshiPayloadAdapter import org.walletconnect.impls.OkHttpTransport import org.walletconnect.impls.WCSession +import pm.gnosis.eip712.EIP712JsonParser +import pm.gnosis.eip712.adapters.moshi.MoshiAdapter +import pm.gnosis.eip712.typedDataHash import java.io.File +import kotlin.reflect.typeOf class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand.Listener, SignCommand.Listener, Session.Callback { @@ -91,7 +95,7 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand private fun onCustomCall(call: Session.MethodCall.Custom) { when(call.method) { "personal_sign" -> runOnValidParam(call, 0) { signText(call.id, it) } - "eth_signTypedData" -> { runOnValidParam>(call, 1) { @Suppress("UNCHECKED_CAST") signTypedData(call.id, it as Map) } } + "eth_signTypedData" -> { runOnValidParam(call, 1) { @Suppress("UNCHECKED_CAST") signTypedData(call.id, it) } } "eth_signTransaction" -> { runOnValidParam>(call, 0) { signTransaction(call.id, toTransaction(toSendTransaction(call.id, it)), false)} } "eth_sendRawTransaction" -> { runOnValidParam(call, 0) { relayTX(call.id, it) } } else -> session?.rejectRequest(call.id, 1L, "Not implemented") @@ -140,9 +144,21 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT) } - private fun signTypedData(id: Long, message: Map) { + private fun signTypedData(id: Long, message: String) { requestId = id - session?.rejectRequest(id, 1L, "Not implemented yet") + uiAction = { + val domainWithMessage = EIP712JsonParser(MoshiAdapter()).parseMessage(message) + val hash = typedDataHash(domainWithMessage.message, domainWithMessage.domain) + Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(SignCommand(Registry.walletConnect, hash))) + } + + signAction = { session?.approveRequest(requestId, "0x${it.r.toNoPrefixHexString()}${it.s.toNoPrefixHexString()}${encode((it.recId + 27).toByte())}") } + + val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply { + putExtra(SIGN_TEXT_MESSAGE, message) + } + + Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT) } private fun signTransaction(id: Long, tx: Transaction, send: Boolean) {