Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fake Wallet should validate the signatures it receives from Seed Vault #86

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fakewallet/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package com.solanamobile.fakewallet.ui

import android.content.Intent
import android.os.Bundle
import android.os.PersistableBundle
import android.util.Log
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -28,12 +29,15 @@ class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding

private var shownMessageIndex: Int? = null
private var pendingEvent: ViewModelEvent? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

pendingEvent = savedInstanceState?.getParcelable(KEY_PENDING_EVENT)

val seedListadapter = SeedListAdapter(
lifecycleScope = lifecycleScope,
implementationLimits = viewModel.uiState.map { uiState ->
Expand Down Expand Up @@ -125,50 +129,55 @@ class MainActivity : AppCompatActivity() {
lifecycle.coroutineScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.viewModelEvents.collect { event ->
check(pendingEvent == null) { "Received a request while another is pending" }
when (event) {
is ViewModelEvent.AuthorizeNewSeed -> {
val i = Wallet.authorizeSeed(WalletContractV1.PURPOSE_SIGN_SOLANA_TRANSACTION)
@Suppress("deprecation")
startActivityForResult(i, REQUEST_AUTHORIZE_SEED_ACCESS)
pendingEvent = event
}
is ViewModelEvent.DeauthorizeSeed -> {
try {
Wallet.deauthorizeSeed(this@MainActivity, event.authToken)
Log.d(TAG, "Seed ${event.authToken} deauthorized")
viewModel.onDeauthorizeSeedSuccess()
viewModel.onDeauthorizeSeedSuccess(event)
} catch (e: Exception) {
Log.e(TAG, "Failed to deauthorize seed", e)
viewModel.onDeauthorizeSeedFailure(-1)
viewModel.onDeauthorizeSeedFailure(event, -1)
}
}
is ViewModelEvent.UpdateAccountName -> {
try {
Wallet.updateAccountName(this@MainActivity, event.authToken,
event.accountId, event.name)
Log.d(TAG, "Account name updated (to '${event.name})'")
viewModel.onUpdateAccountNameSuccess()
viewModel.onUpdateAccountNameSuccess(event)
} catch (e: Exception) {
Log.e(TAG, "Failed to update account name", e)
viewModel.onUpdateAccountNameFailure(-1)
viewModel.onUpdateAccountNameFailure(event, -1)
}
}
is ViewModelEvent.SignTransactions -> {
val i = Wallet.signTransactions(
event.authToken, event.transactions)
@Suppress("deprecation")
startActivityForResult(i, REQUEST_SIGN_TRANSACTIONS)
pendingEvent = event
}
is ViewModelEvent.SignMessages -> {
val i = Wallet.signMessages(
event.authToken, event.messages)
@Suppress("deprecation")
startActivityForResult(i, REQUEST_SIGN_MESSAGES)
pendingEvent = event
}
is ViewModelEvent.RequestPublicKeys -> {
val i = Wallet.requestPublicKeys(
event.authToken, event.derivationPaths)
@Suppress("deprecation")
startActivityForResult(i, REQUEST_GET_PUBLIC_KEYS)
pendingEvent = event
}
}
}
Expand All @@ -180,55 +189,68 @@ class MainActivity : AppCompatActivity() {
@Suppress("deprecation")
super.onActivityResult(requestCode, resultCode, data)

val event = pendingEvent!!
pendingEvent = null

when (requestCode) {
REQUEST_AUTHORIZE_SEED_ACCESS -> {
check(event is ViewModelEvent.AuthorizeNewSeed)
try {
val authToken = Wallet.onAuthorizeSeedResult(resultCode, data)
Log.d(TAG, "Seed authorized, AuthToken=$authToken")
viewModel.onAuthorizeNewSeedSuccess(authToken)
viewModel.onAuthorizeNewSeedSuccess(event, authToken)
} catch (e: Wallet.ActionFailedException) {
Log.e(TAG, "Seed authorization failed", e)
viewModel.onAuthorizeNewSeedFailure(resultCode)
viewModel.onAuthorizeNewSeedFailure(event, resultCode)
}
}
REQUEST_SIGN_TRANSACTIONS -> {
check(event is ViewModelEvent.SignTransactions)
try {
val result = Wallet.onSignTransactionsResult(resultCode, data)
Log.d(TAG, "Transaction signed: signatures=$result")
viewModel.onSignTransactionsSuccess(result)
viewModel.onSignTransactionsSuccess(event, result)
} catch (e: Wallet.ActionFailedException) {
Log.e(TAG, "Transaction signing failed", e)
viewModel.onSignTransactionsFailure(resultCode)
viewModel.onSignTransactionsFailure(event, resultCode)
}
}
REQUEST_SIGN_MESSAGES -> {
check(event is ViewModelEvent.SignMessages)
try {
val result = Wallet.onSignMessagesResult(resultCode, data)
Log.d(TAG, "Message signed: signatures=$result")
viewModel.onSignMessagesSuccess(result)
viewModel.onSignMessagesSuccess(event, result)
} catch (e: Wallet.ActionFailedException) {
Log.e(TAG, "Message signing failed", e)
viewModel.onSignMessagesFailure(resultCode)
viewModel.onSignMessagesFailure(event, resultCode)
}
}
REQUEST_GET_PUBLIC_KEYS -> {
check(event is ViewModelEvent.RequestPublicKeys)
try {
val result = Wallet.onRequestPublicKeysResult(resultCode, data)
Log.d(TAG, "Public key retrieved: publicKey=$result")
viewModel.onRequestPublicKeysSuccess(result)
viewModel.onRequestPublicKeysSuccess(event, result)
} catch (e: Wallet.ActionFailedException) {
Log.e(TAG, "Transaction signing failed", e)
viewModel.onRequestPublicKeysFailure(resultCode)
viewModel.onRequestPublicKeysFailure(event, resultCode)
}
}
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(KEY_PENDING_EVENT, pendingEvent)
}

companion object {
private val TAG = MainActivity::class.simpleName
private const val REQUEST_AUTHORIZE_SEED_ACCESS = 0
private const val REQUEST_SIGN_TRANSACTIONS = 1
private const val REQUEST_SIGN_MESSAGES = 2
private const val REQUEST_GET_PUBLIC_KEYS = 3
private const val KEY_PENDING_EVENT = "pendingEvent"
}
}
Loading