From 2f643b53f1a06a19dc1d9c776251eb50a7664966 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Tue, 13 Oct 2020 12:01:32 +0200 Subject: [PATCH] add disconnect function --- .../im/status/keycard/connect/Registry.kt | 5 ++-- .../keycard/connect/net/WalletConnect.kt | 24 ++++++++------- .../status/keycard/connect/ui/MainActivity.kt | 30 +++++++++++++++++-- app/src/main/res/values/strings.xml | 1 + 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/im/status/keycard/connect/Registry.kt b/app/src/main/java/im/status/keycard/connect/Registry.kt index 5d60261..08dfaa3 100644 --- a/app/src/main/java/im/status/keycard/connect/Registry.kt +++ b/app/src/main/java/im/status/keycard/connect/Registry.kt @@ -13,6 +13,7 @@ import im.status.keycard.connect.data.PairingManager import im.status.keycard.connect.data.SettingsManager import im.status.keycard.connect.net.EthereumRPC import im.status.keycard.connect.net.WalletConnect +import org.walletconnect.Session @SuppressLint("StaticFieldLeak") object Registry { @@ -52,7 +53,7 @@ object Registry { value.add(0, KotlinJsonAdapterFactory()) } - fun init(activity: Activity, listener: ScriptListener) { + fun init(activity: Activity, listener: ScriptListener, sessionListener: Session.Callback) { //TODO: remove this hack, it is needed now because KEthereum does not add the KotlinJsonAdapterFactory moshiAddKotlin() @@ -70,6 +71,6 @@ object Registry { cardManager.start() ethereumRPC = EthereumRPC(settingsManager.rpcEndpoint) - walletConnect = WalletConnect(settingsManager.bip32Path, settingsManager.chainID) + walletConnect = WalletConnect(sessionListener, settingsManager.bip32Path, settingsManager.chainID) } } \ No newline at end of file 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 e4f5062..3072c52 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 @@ -44,8 +44,7 @@ import pm.gnosis.eip712.adapters.moshi.MoshiAdapter import pm.gnosis.eip712.typedDataHash import java.io.File -class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand.Listener, SignCommand.Listener, Session.Callback { - +class WalletConnect(var sessionStatusListener : Session.Callback, var bip32Path: String, var chainID: Long) : ExportKeyCommand.Listener, SignCommand.Listener, Session.Callback { private val scope = MainScope() private val moshi = Moshi.Builder().build() private val okHttpClient = OkHttpClient() @@ -56,12 +55,8 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand private var signAction: (RecoverableSignature) -> Unit = this::nop override fun onStatus(status: Session.Status) { - when (status) { - is Session.Status.Error -> println("WalletConnect Error") - is Session.Status.Approved -> println("WalletConnect Approved") - is Session.Status.Connected -> println("WalletConnect Connected") - is Session.Status.Disconnected -> println("WalletConnect Disconnected") - is Session.Status.Closed -> session = null + if (status == Session.Status.Closed) { + session = null } } @@ -94,7 +89,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) } } + "eth_signTypedData" -> { runOnValidParam(call, 1) { 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") @@ -134,7 +129,7 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand 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())}") } + signAction = { session?.approveRequest(requestId, formatDataSignature(it)) } val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply { putExtra(SIGN_TEXT_MESSAGE, text) @@ -151,7 +146,7 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand 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())}") } + signAction = { session?.approveRequest(requestId, formatDataSignature(it)) } val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply { putExtra(SIGN_TEXT_MESSAGE, message) @@ -160,6 +155,8 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT) } + private fun formatDataSignature(sig: RecoverableSignature) : String = "0x${sig.r.toNoPrefixHexString()}${sig.s.toNoPrefixHexString()}${encode((sig.recId + 27).toByte())}" + private fun signTransaction(id: Long, tx: Transaction, send: Boolean) { requestId = id @@ -227,11 +224,16 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand Session.PeerMeta(name = "Keycard Connect") ) + session?.addCallback(Registry.walletConnect.sessionStatusListener) session?.addCallback(Registry.walletConnect) session?.init() } } + fun disconnect() { + session?.kill() + } + override fun onResponse(keyPair: BIP32KeyPair) { scope.launch(Dispatchers.IO) { val addr = keyPair.toEthereumAddress().toHexString() diff --git a/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt b/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt index 91497f3..1e84ecd 100644 --- a/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt +++ b/app/src/main/java/im/status/keycard/connect/ui/MainActivity.kt @@ -6,6 +6,7 @@ import android.nfc.NfcAdapter import android.os.Bundle import android.view.LayoutInflater import android.view.View +import android.widget.Button import android.widget.ViewSwitcher import androidx.appcompat.app.AppCompatActivity import com.google.zxing.client.android.Intents @@ -14,9 +15,10 @@ import im.status.keycard.connect.R import im.status.keycard.connect.Registry import im.status.keycard.connect.card.* import im.status.keycard.connect.data.* +import org.walletconnect.Session import kotlin.reflect.KClass -class MainActivity : AppCompatActivity(), ScriptListener { +class MainActivity : AppCompatActivity(), ScriptListener, Session.Callback { private lateinit var viewSwitcher: ViewSwitcher override fun onCreate(savedInstanceState: Bundle?) { @@ -28,7 +30,7 @@ class MainActivity : AppCompatActivity(), ScriptListener { inflater.inflate(R.layout.activity_nfc, viewSwitcher) setContentView(viewSwitcher) - Registry.init(this, this) + Registry.init(this, this, this) Registry.scriptExecutor.defaultScript = cardCheckupScript() } @@ -77,6 +79,10 @@ class MainActivity : AppCompatActivity(), ScriptListener { integrator.initiateScan() } + fun disconnectWallet(@Suppress("UNUSED_PARAMETER") view: View) { + Registry.walletConnect.disconnect() + } + fun changePIN(@Suppress("UNUSED_PARAMETER") view: View) { startCommand(ChangePINActivity::class) } @@ -137,4 +143,24 @@ class MainActivity : AppCompatActivity(), ScriptListener { Registry.walletConnect.connect(uri) } } + + override fun onMethodCall(call: Session.MethodCall) {} + override fun onStatus(status: Session.Status) { + when (status) { + is Session.Status.Error, Session.Status.Closed, Session.Status.Disconnected -> walletConnectDisconnected() + is Session.Status.Connected, Session.Status.Approved -> walletConnectConnected() + } + } + + private fun walletConnectConnected() { + val button = findViewById