start walletconnect integration

This commit is contained in:
Michele Balistreri 2019-11-05 17:45:08 +03:00
parent 97f7b9256a
commit 4fd3dc530e
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
10 changed files with 111 additions and 14 deletions

View File

@ -9,7 +9,7 @@ android {
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "im.status.keycard.connect"
minSdkVersion 23
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
@ -48,7 +48,12 @@ dependencies {
implementation 'androidx.security:security-crypto:1.0.0-alpha02'
implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
implementation 'com.github.status-im.status-keycard-java:android:3.0.1'
implementation "com.github.walletconnect:kotlin-walletconnect-lib:0.9.3"
implementation 'com.github.walletconnect:kotlin-walletconnect-lib:0.9.3'
implementation 'com.journeyapps:zxing-android-embedded:4.0.0'
implementation 'com.google.zxing:core:3.4.0'
implementation 'com.squareup.moshi:moshi:1.9.1'
implementation 'com.squareup.okhttp3:okhttp:4.2.1'
implementation 'com.squareup.moshi:moshi-kotlin:1.9.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

View File

@ -10,13 +10,14 @@
android:required="true" />
<application
android:hardwareAccelerated="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ui.PUKActivity"></activity>
<activity android:name=".ui.PUKActivity" />
<activity android:name=".ui.ChangePINActivity" />
<activity android:name=".ui.InitActivity" />
<activity android:name=".ui.PairingActivity" />

View File

@ -7,7 +7,9 @@ import im.status.keycard.android.NFCCardManager
import im.status.keycard.connect.card.*
import im.status.keycard.connect.data.PINCache
import im.status.keycard.connect.data.PairingManager
import im.status.keycard.connect.walletconnect.SessionManager
@SuppressLint("StaticFieldLeak")
object Registry {
lateinit var pinCache: PINCache
private set
@ -15,7 +17,9 @@ object Registry {
lateinit var pairingManager: PairingManager
private set
@SuppressLint("StaticFieldLeak")
lateinit var mainActivity: Activity
private set
lateinit var scriptExecutor: CardScriptExecutor
private set
@ -25,15 +29,21 @@ object Registry {
lateinit var nfcAdapter: NfcAdapter
private set
lateinit var walletConnect: SessionManager
fun init(activity: Activity, listener: ScriptListener) {
this.mainActivity = activity
pairingManager = PairingManager(activity)
pinCache = PINCache()
nfcAdapter = NfcAdapter.getDefaultAdapter(activity)
scriptExecutor = CardScriptExecutor(activity, listener)
scriptExecutor = CardScriptExecutor(listener)
cardManager = NFCCardManager()
cardManager.setCardListener(scriptExecutor)
cardManager.start()
walletConnect = SessionManager()
}
}

View File

@ -3,11 +3,12 @@ package im.status.keycard.connect.card
import android.app.Activity
import android.content.Intent
import im.status.keycard.applet.KeycardCommandSet
import im.status.keycard.connect.Registry
import im.status.keycard.io.CardChannel
import im.status.keycard.io.CardListener
class CardScriptExecutor(private val activity: Activity, private val listener: ScriptListener) : CardListener {
class ScriptContext(val activity: Activity, val cmdSet: KeycardCommandSet)
class CardScriptExecutor(private val listener: ScriptListener) : CardListener {
data class ScriptContext(val activity: Activity, val cmdSet: KeycardCommandSet)
enum class State {
READY, UX_ONGOING, RUNNING
@ -20,7 +21,7 @@ class CardScriptExecutor(private val activity: Activity, private val listener: S
private var waitingCmd: CardCommand? = null
override fun onConnected(channel: CardChannel) {
val executionContext = ScriptContext(activity, KeycardCommandSet(channel))
val executionContext = ScriptContext(Registry.mainActivity, KeycardCommandSet(channel))
if (state == State.READY) {
startScript()

View File

@ -10,7 +10,7 @@ import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
class PairingManager(context: Context) {
private lateinit var sharedPreferences: SharedPreferences
private val sharedPreferences: SharedPreferences
private fun id(instanceUID: ByteArray) : String {
return Base64.encodeToString(instanceUID, NO_PADDING or NO_WRAP)

View File

@ -8,11 +8,15 @@ import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.widget.ViewSwitcher
import com.google.zxing.integration.android.IntentIntegrator
import im.status.keycard.connect.R
import im.status.keycard.connect.Registry
import im.status.keycard.connect.card.*
import im.status.keycard.connect.data.REQ_INTERACTIVE_SCRIPT
import kotlin.reflect.KClass
import androidx.core.app.ComponentActivity.ExtraData
import androidx.core.content.ContextCompat.getSystemService
import com.google.zxing.client.android.Intents
class MainActivity : AppCompatActivity(), ScriptListener {
private lateinit var viewSwitcher: ViewSwitcher
@ -43,8 +47,9 @@ class MainActivity : AppCompatActivity(), ScriptListener {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQ_INTERACTIVE_SCRIPT) {
Registry.scriptExecutor.onUserInteractionReturned(resultCode, data)
when (requestCode) {
REQ_INTERACTIVE_SCRIPT -> Registry.scriptExecutor.onUserInteractionReturned(resultCode, data)
IntentIntegrator.REQUEST_CODE -> qrCodeScanned(resultCode, data)
}
}
@ -64,6 +69,13 @@ class MainActivity : AppCompatActivity(), ScriptListener {
Registry.scriptExecutor.cancelScript()
}
fun connectWallet(@Suppress("UNUSED_PARAMETER") view: View) {
val integrator = IntentIntegrator(this)
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
integrator.setOrientationLocked(false)
integrator.initiateScan()
}
fun changePIN(@Suppress("UNUSED_PARAMETER") view: View) {
startCommand(ChangePINActivity::class)
}
@ -72,4 +84,14 @@ class MainActivity : AppCompatActivity(), ScriptListener {
val intent = Intent(this, activity.java)
startActivity(intent)
}
private fun qrCodeScanned(resultCode: Int, data: Intent?) {
if (resultCode != Activity.RESULT_OK || data == null) return
val uri: String? = data.getStringExtra(Intents.Scan.RESULT)
if (uri != null && uri.startsWith("wc:")) {
Registry.walletConnect.connect(uri)
}
}
}

View File

@ -0,0 +1,44 @@
package im.status.keycard.connect.walletconnect
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import im.status.keycard.connect.Registry
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import org.walletconnect.Session
import org.walletconnect.Session.Config.Companion.fromWCUri
import org.walletconnect.impls.*
import java.io.File
class SessionManager {
private val scope = MainScope()
private val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
private val okHttpClient = OkHttpClient()
private val sessionStore = FileWCSessionStore(File(Registry.mainActivity.filesDir, "wcSessions.json").apply { createNewFile() }, moshi)
private var session: WCSession? = null
object SessionCB : Session.Callback {
override fun onStatus(status: Session.Status) {
println(status)
}
override fun onMethodCall(call: Session.MethodCall) {
println(call)
}
}
fun connect(uri: String) {
scope.launch {
session = WCSession(
fromWCUri(uri),
MoshiPayloadAdapter(moshi),
sessionStore,
OkHttpTransport.Builder(okHttpClient, moshi),
Session.PeerMeta(name = "Keycard Connect")
)
session?.addCallback(SessionCB)
}
}
}

View File

@ -9,13 +9,26 @@
tools:context=".ui.MainActivity">
<Button
android:id="@+id/button"
android:id="@+id/changePINButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:onClick="changePIN"
android:text="@string/change_pin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.049"
app:layout_constraintHorizontal_bias="0.532"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/walletConnectButton" />
<Button
android:id="@+id/walletConnectButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="connectWallet"
android:text="@string/connect_wallet"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.553"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -12,4 +12,5 @@
<string name="change_pin">Change PIN</string>
<string name="puk_prompt" >Insert your PUK</string>
<string name="nfc_prompt">Tap your card</string>
<string name="connect_wallet" >Connect to WalletConnect</string>
</resources>

View File

@ -8,7 +8,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.5.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files