add disconnect function

This commit is contained in:
Michele Balistreri 2020-10-13 12:01:32 +02:00
parent 46b8387b14
commit 2f643b53f1
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
4 changed files with 45 additions and 15 deletions

View File

@ -13,6 +13,7 @@ import im.status.keycard.connect.data.PairingManager
import im.status.keycard.connect.data.SettingsManager import im.status.keycard.connect.data.SettingsManager
import im.status.keycard.connect.net.EthereumRPC import im.status.keycard.connect.net.EthereumRPC
import im.status.keycard.connect.net.WalletConnect import im.status.keycard.connect.net.WalletConnect
import org.walletconnect.Session
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
object Registry { object Registry {
@ -52,7 +53,7 @@ object Registry {
value.add(0, KotlinJsonAdapterFactory()) 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 //TODO: remove this hack, it is needed now because KEthereum does not add the KotlinJsonAdapterFactory
moshiAddKotlin() moshiAddKotlin()
@ -70,6 +71,6 @@ object Registry {
cardManager.start() cardManager.start()
ethereumRPC = EthereumRPC(settingsManager.rpcEndpoint) ethereumRPC = EthereumRPC(settingsManager.rpcEndpoint)
walletConnect = WalletConnect(settingsManager.bip32Path, settingsManager.chainID) walletConnect = WalletConnect(sessionListener, settingsManager.bip32Path, settingsManager.chainID)
} }
} }

View File

@ -44,8 +44,7 @@ import pm.gnosis.eip712.adapters.moshi.MoshiAdapter
import pm.gnosis.eip712.typedDataHash import pm.gnosis.eip712.typedDataHash
import java.io.File 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 scope = MainScope()
private val moshi = Moshi.Builder().build() private val moshi = Moshi.Builder().build()
private val okHttpClient = OkHttpClient() private val okHttpClient = OkHttpClient()
@ -56,12 +55,8 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand
private var signAction: (RecoverableSignature) -> Unit = this::nop private var signAction: (RecoverableSignature) -> Unit = this::nop
override fun onStatus(status: Session.Status) { override fun onStatus(status: Session.Status) {
when (status) { if (status == Session.Status.Closed) {
is Session.Status.Error -> println("WalletConnect Error") session = null
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
} }
} }
@ -94,7 +89,7 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand
private fun onCustomCall(call: Session.MethodCall.Custom) { private fun onCustomCall(call: Session.MethodCall.Custom) {
when(call.method) { when(call.method) {
"personal_sign" -> runOnValidParam<String>(call, 0) { signText(call.id, it) } "personal_sign" -> runOnValidParam<String>(call, 0) { signText(call.id, it) }
"eth_signTypedData" -> { runOnValidParam<String>(call, 1) { @Suppress("UNCHECKED_CAST") signTypedData(call.id, it) } } "eth_signTypedData" -> { runOnValidParam<String>(call, 1) { signTypedData(call.id, it) } }
"eth_signTransaction" -> { runOnValidParam<Map<*, *>>(call, 0) { signTransaction(call.id, toTransaction(toSendTransaction(call.id, it)), false)} } "eth_signTransaction" -> { runOnValidParam<Map<*, *>>(call, 0) { signTransaction(call.id, toTransaction(toSendTransaction(call.id, it)), false)} }
"eth_sendRawTransaction" -> { runOnValidParam<String>(call, 0) { relayTX(call.id, it) } } "eth_sendRawTransaction" -> { runOnValidParam<String>(call, 0) { relayTX(call.id, it) } }
else -> session?.rejectRequest(call.id, 1L, "Not implemented") 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))) 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 { val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply {
putExtra(SIGN_TEXT_MESSAGE, text) 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))) 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 { val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply {
putExtra(SIGN_TEXT_MESSAGE, message) putExtra(SIGN_TEXT_MESSAGE, message)
@ -160,6 +155,8 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand
Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT) 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) { private fun signTransaction(id: Long, tx: Transaction, send: Boolean) {
requestId = id requestId = id
@ -227,11 +224,16 @@ class WalletConnect(var bip32Path: String, var chainID: Long) : ExportKeyCommand
Session.PeerMeta(name = "Keycard Connect") Session.PeerMeta(name = "Keycard Connect")
) )
session?.addCallback(Registry.walletConnect.sessionStatusListener)
session?.addCallback(Registry.walletConnect) session?.addCallback(Registry.walletConnect)
session?.init() session?.init()
} }
} }
fun disconnect() {
session?.kill()
}
override fun onResponse(keyPair: BIP32KeyPair) { override fun onResponse(keyPair: BIP32KeyPair) {
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
val addr = keyPair.toEthereumAddress().toHexString() val addr = keyPair.toEthereumAddress().toHexString()

View File

@ -6,6 +6,7 @@ import android.nfc.NfcAdapter
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.Button
import android.widget.ViewSwitcher import android.widget.ViewSwitcher
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.zxing.client.android.Intents 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.Registry
import im.status.keycard.connect.card.* import im.status.keycard.connect.card.*
import im.status.keycard.connect.data.* import im.status.keycard.connect.data.*
import org.walletconnect.Session
import kotlin.reflect.KClass import kotlin.reflect.KClass
class MainActivity : AppCompatActivity(), ScriptListener { class MainActivity : AppCompatActivity(), ScriptListener, Session.Callback {
private lateinit var viewSwitcher: ViewSwitcher private lateinit var viewSwitcher: ViewSwitcher
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -28,7 +30,7 @@ class MainActivity : AppCompatActivity(), ScriptListener {
inflater.inflate(R.layout.activity_nfc, viewSwitcher) inflater.inflate(R.layout.activity_nfc, viewSwitcher)
setContentView(viewSwitcher) setContentView(viewSwitcher)
Registry.init(this, this) Registry.init(this, this, this)
Registry.scriptExecutor.defaultScript = cardCheckupScript() Registry.scriptExecutor.defaultScript = cardCheckupScript()
} }
@ -77,6 +79,10 @@ class MainActivity : AppCompatActivity(), ScriptListener {
integrator.initiateScan() integrator.initiateScan()
} }
fun disconnectWallet(@Suppress("UNUSED_PARAMETER") view: View) {
Registry.walletConnect.disconnect()
}
fun changePIN(@Suppress("UNUSED_PARAMETER") view: View) { fun changePIN(@Suppress("UNUSED_PARAMETER") view: View) {
startCommand(ChangePINActivity::class) startCommand(ChangePINActivity::class)
} }
@ -137,4 +143,24 @@ class MainActivity : AppCompatActivity(), ScriptListener {
Registry.walletConnect.connect(uri) 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<Button>(R.id.walletConnectButton)
button.setOnClickListener(this::disconnectWallet)
button.text = getString(R.string.disconnect_wallet)
}
private fun walletConnectDisconnected() {
val button = findViewById<Button>(R.id.walletConnectButton)
button.setOnClickListener(this::connectWallet)
button.text = getString(R.string.connect_wallet)
}
} }

View File

@ -44,4 +44,5 @@
<string name="reinstall_cash_checkbox">Install Cash applet</string> <string name="reinstall_cash_checkbox">Install Cash applet</string>
<string name="reinstall_ndef_checkbox">Install NDEF applet</string> <string name="reinstall_ndef_checkbox">Install NDEF applet</string>
<string name="reinstall_button">Select cap file and install</string> <string name="reinstall_button">Select cap file and install</string>
<string name="disconnect_wallet">Disconnect</string>
</resources> </resources>