mirror of
https://github.com/status-im/keycard-connect.git
synced 2025-02-27 18:10:28 +00:00
add sign interface
This commit is contained in:
parent
aad3a2bf9a
commit
503743d527
@ -10,13 +10,14 @@
|
|||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:hardwareAccelerated="true"
|
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
<activity android:name=".ui.SignMessageActivity"></activity>
|
||||||
<activity android:name=".ui.PUKActivity" />
|
<activity android:name=".ui.PUKActivity" />
|
||||||
<activity android:name=".ui.ChangePINActivity" />
|
<activity android:name=".ui.ChangePINActivity" />
|
||||||
<activity android:name=".ui.InitActivity" />
|
<activity android:name=".ui.InitActivity" />
|
||||||
|
@ -11,6 +11,9 @@ const val INIT_ACTIVITY_PIN = "initPIN"
|
|||||||
const val INIT_ACTIVITY_PUK = "initPUK"
|
const val INIT_ACTIVITY_PUK = "initPUK"
|
||||||
const val INIT_ACTIVITY_PAIRING = "initPairing"
|
const val INIT_ACTIVITY_PAIRING = "initPairing"
|
||||||
|
|
||||||
|
const val SIGN_TEXT_MESSAGE = "signMessage"
|
||||||
|
|
||||||
const val REQ_INTERACTIVE_SCRIPT = 0x01
|
const val REQ_INTERACTIVE_SCRIPT = 0x01
|
||||||
|
const val REQ_WALLETCONNECT = 0x02
|
||||||
|
|
||||||
const val CACHE_VALIDITY = 15 * 60 * 1000
|
const val CACHE_VALIDITY = 15 * 60 * 1000
|
@ -17,6 +17,7 @@ import kotlin.reflect.KClass
|
|||||||
import androidx.core.app.ComponentActivity.ExtraData
|
import androidx.core.app.ComponentActivity.ExtraData
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
import com.google.zxing.client.android.Intents
|
import com.google.zxing.client.android.Intents
|
||||||
|
import im.status.keycard.connect.data.REQ_WALLETCONNECT
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), ScriptListener {
|
class MainActivity : AppCompatActivity(), ScriptListener {
|
||||||
private lateinit var viewSwitcher: ViewSwitcher
|
private lateinit var viewSwitcher: ViewSwitcher
|
||||||
@ -49,6 +50,7 @@ class MainActivity : AppCompatActivity(), ScriptListener {
|
|||||||
|
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
REQ_INTERACTIVE_SCRIPT -> Registry.scriptExecutor.onUserInteractionReturned(resultCode, data)
|
REQ_INTERACTIVE_SCRIPT -> Registry.scriptExecutor.onUserInteractionReturned(resultCode, data)
|
||||||
|
REQ_WALLETCONNECT -> Registry.walletConnect.onUserInteractionReturned(resultCode, data)
|
||||||
IntentIntegrator.REQUEST_CODE -> qrCodeScanned(resultCode, data)
|
IntentIntegrator.REQUEST_CODE -> qrCodeScanned(resultCode, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package im.status.keycard.connect.ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import im.status.keycard.connect.R
|
||||||
|
import im.status.keycard.connect.data.SIGN_TEXT_MESSAGE
|
||||||
|
|
||||||
|
class SignMessageActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_sign_message)
|
||||||
|
val signText = findViewById<TextView>(R.id.signText)
|
||||||
|
signText.text = intent.getStringExtra(SIGN_TEXT_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sign(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reject(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||||
|
setResult(Activity.RESULT_CANCELED)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package im.status.keycard.connect.walletconnect
|
package im.status.keycard.connect.walletconnect
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||||
import im.status.keycard.applet.BIP32KeyPair
|
import im.status.keycard.applet.BIP32KeyPair
|
||||||
@ -8,6 +10,9 @@ import im.status.keycard.connect.Registry
|
|||||||
import im.status.keycard.connect.card.ExportKeyCommand
|
import im.status.keycard.connect.card.ExportKeyCommand
|
||||||
import im.status.keycard.connect.card.SignCommand
|
import im.status.keycard.connect.card.SignCommand
|
||||||
import im.status.keycard.connect.card.scriptWithAuthentication
|
import im.status.keycard.connect.card.scriptWithAuthentication
|
||||||
|
import im.status.keycard.connect.data.REQ_WALLETCONNECT
|
||||||
|
import im.status.keycard.connect.data.SIGN_TEXT_MESSAGE
|
||||||
|
import im.status.keycard.connect.ui.SignMessageActivity
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@ -30,6 +35,7 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener {
|
|||||||
private val sessionStore = FileWCSessionStore(File(Registry.mainActivity.filesDir, "wcSessions.json").apply { createNewFile() }, moshi)
|
private val sessionStore = FileWCSessionStore(File(Registry.mainActivity.filesDir, "wcSessions.json").apply { createNewFile() }, moshi)
|
||||||
private var session: WCSession? = null
|
private var session: WCSession? = null
|
||||||
private var requestId: Long = 0
|
private var requestId: Long = 0
|
||||||
|
private var action: (data: Intent?) -> Unit = this::nop
|
||||||
|
|
||||||
private val sessionCB = object : Session.Callback {
|
private val sessionCB = object : Session.Callback {
|
||||||
override fun onStatus(status: Session.Status) {
|
override fun onStatus(status: Session.Status) {
|
||||||
@ -69,6 +75,10 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener {
|
|||||||
session?.rejectRequest(call.id, 1L, "Not implemented yet")
|
session?.rejectRequest(call.id, 1L, "Not implemented yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"eth_signTransaction" -> {
|
||||||
|
session?.rejectRequest(call.id, 1L, "Not implemented yet")
|
||||||
|
}
|
||||||
|
|
||||||
"eth_sendRawTransaction" -> {
|
"eth_sendRawTransaction" -> {
|
||||||
session?.rejectRequest(call.id, 1L, "Not implemented yet")
|
session?.rejectRequest(call.id, 1L, "Not implemented yet")
|
||||||
}
|
}
|
||||||
@ -79,14 +89,36 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun signText(id: Long, message: String) {
|
private fun signText(id: Long, message: String) {
|
||||||
requestId = id
|
|
||||||
val msg = Hex.decode(if (message.startsWith("0x", true)) message.drop(2) else message)
|
val msg = Hex.decode(if (message.startsWith("0x", true)) message.drop(2) else message)
|
||||||
val keccak256 = Keccak.Digest256()
|
val text = String(msg)
|
||||||
val hash = keccak256.digest(byteArrayOf(0x19) + "Ethereum Signed Message:\n${msg.size}".toByteArray() + msg)
|
|
||||||
Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(SignCommand(Registry.walletConnect, hash)))
|
requestId = id
|
||||||
|
action = {
|
||||||
|
val keccak256 = Keccak.Digest256()
|
||||||
|
val hash = keccak256.digest(byteArrayOf(0x19) + "Ethereum Signed Message:\n${msg.size}".toByteArray() + msg)
|
||||||
|
Registry.scriptExecutor.runScript(scriptWithAuthentication().plus(SignCommand(Registry.walletConnect, hash)))
|
||||||
|
}
|
||||||
|
|
||||||
|
val intent = Intent(Registry.mainActivity, SignMessageActivity::class.java).apply {
|
||||||
|
putExtra(SIGN_TEXT_MESSAGE, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
Registry.mainActivity.startActivityForResult(intent, REQ_WALLETCONNECT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun nop(@Suppress("UNUSED_PARAMETER") data: Intent?) { }
|
||||||
|
|
||||||
|
fun onUserInteractionReturned(resultCode: Int, data: Intent?) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
action.invoke(data)
|
||||||
|
} else {
|
||||||
|
session?.rejectRequest(requestId, -1, "Rejected by user")
|
||||||
|
}
|
||||||
|
|
||||||
|
action = this::nop
|
||||||
|
}
|
||||||
|
|
||||||
fun connect(uri: String) {
|
fun connect(uri: String) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
session?.kill()
|
session?.kill()
|
||||||
@ -114,7 +146,6 @@ class WalletConnect : ExportKeyCommand.Listener, SignCommand.Listener {
|
|||||||
override fun onResponse(signature: RecoverableSignature) {
|
override fun onResponse(signature: RecoverableSignature) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
session?.approveRequest(requestId, "0x${toHexString(signature.r)}${toHexString(signature.s)}${toHexString(byteArrayOf(signature.recId.toByte()))}")
|
session?.approveRequest(requestId, "0x${toHexString(signature.r)}${toHexString(signature.s)}${toHexString(byteArrayOf(signature.recId.toByte()))}")
|
||||||
//session?.rejectRequest(requestId, -1, "Rejected by user")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
51
app/src/main/res/layout/activity_sign_message.xml
Normal file
51
app/src/main/res/layout/activity_sign_message.xml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".ui.SignMessageActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/signTextLabel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="52dp"
|
||||||
|
android:text="@string/sign_text_label"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.498"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/signButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="80dp"
|
||||||
|
android:layout_marginEnd="68dp"
|
||||||
|
android:onClick="sign"
|
||||||
|
android:text="@string/sign_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/signText" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/rejectButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="64dp"
|
||||||
|
android:layout_marginTop="80dp"
|
||||||
|
android:onClick="reject"
|
||||||
|
android:text="@string/reject_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/signText" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/signText"
|
||||||
|
android:layout_width="306dp"
|
||||||
|
android:layout_height="389dp"
|
||||||
|
android:layout_marginTop="52dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.495"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/signTextLabel" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -10,7 +10,10 @@
|
|||||||
<string name="title_activity_change_pin">ChangePINActivity</string>
|
<string name="title_activity_change_pin">ChangePINActivity</string>
|
||||||
<string name="change_pin_prompt">New PIN</string>
|
<string name="change_pin_prompt">New PIN</string>
|
||||||
<string name="change_pin">Change PIN</string>
|
<string name="change_pin">Change PIN</string>
|
||||||
<string name="puk_prompt" >Insert your PUK</string>
|
<string name="puk_prompt">Insert your PUK</string>
|
||||||
<string name="nfc_prompt">Tap your card</string>
|
<string name="nfc_prompt">Tap your card</string>
|
||||||
<string name="connect_wallet" >Connect to WalletConnect</string>
|
<string name="connect_wallet">Connect to WalletConnect</string>
|
||||||
|
<string name="sign_button">Sign</string>
|
||||||
|
<string name="reject_button">Reject</string>
|
||||||
|
<string name="sign_text_label">Sign a message</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user