Skip to content
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
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ on:
branches:
- master

permissions:
contents: read

env:
CARGO_HTTP_MULTIPLEXING: "false"
CARGO_NET_RETRY: "10"
Expand Down Expand Up @@ -91,7 +94,7 @@ jobs:
java-version: "17"

- name: Install build dependencies
run: cd rust && cargo xtask install-deps
run: cd rust && cargo --locked xtask install-deps

- name: Build Rust FFI and generate Kotlin bindings
run: just build-android
Expand Down Expand Up @@ -185,7 +188,7 @@ jobs:
prefix-key: v1-rust

- name: Run tests
run: cd rust && cargo test --workspace
run: cd rust && cargo test --locked --workspace
Comment thread
praveenperera marked this conversation as resolved.

clippy:
runs-on: ubuntu-latest
Expand All @@ -204,4 +207,4 @@ jobs:
cache-bin: false
prefix-key: v1-rust

- run: cd rust && cargo clippy --all-targets --all-features -- -D warnings
- run: cd rust && cargo clippy --locked --all-targets --all-features -- -D warnings
2 changes: 1 addition & 1 deletion .github/workflows/mobile-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
java-version: '17'

- name: Install build dependencies
run: cd rust && cargo xtask install-deps
run: cd rust && cargo --locked xtask install-deps

- name: Build Rust FFI and generate Kotlin bindings
run: just build-android
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/regenerate-bindings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
java-version: '17'

- name: Install build dependencies
run: cd rust && cargo xtask install-deps
run: cd rust && cargo --locked xtask install-deps

- name: Build Rust FFI and generate Kotlin bindings
run: just build-android
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,9 @@ private suspend fun setupTapSigner(
app.sheetState = null
app.alertState =
TaggedItem(
AppAlertState.TapSignerSetupFailed(e.message ?: "Unknown error"),
AppAlertState.TapSignerSetupFailed(
"TapSigner setup failed. Please try again.",
),
)
}
}
Expand Down Expand Up @@ -310,7 +312,12 @@ private suspend fun changeTapSignerPin(
Log.e("TapSignerConfirmPin", "Error changing PIN")

// check error type and show appropriate alert
val errorMessage = e.message ?: "Unknown error"
val errorMessage =
if (isAuthError(e)) {
"Wrong PIN, please try again"
} else {
"TapSigner PIN change failed. Please try again."
}
app.alertState =
TaggedItem(
AppAlertState.General(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ private suspend fun signAction(
}
}

private fun isAuthError(error: Exception): Boolean {
internal fun isAuthError(error: Exception): Boolean {
// check if error is a bad auth error using type-safe FFI function
return error is org.bitcoinppl.cove_core.TapSignerReaderException &&
error.isAuthError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import kotlinx.coroutines.launch
import org.bitcoinppl.cove.AppManager
import org.bitcoinppl.cove.TaggedItem
import org.bitcoinppl.cove.nfc.TapCardNfcManager
import org.bitcoinppl.cove.runCatchingCancellable
import org.bitcoinppl.cove_core.AppAlertState
import org.bitcoinppl.cove_core.TapSignerRoute

Expand Down Expand Up @@ -126,27 +127,30 @@ fun TapSignerImportRetryView(
manager.isTagDetected = false
manager.isScanning = true

try {
val deriveInfo = nfc.derive(pin)
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null
val result =
runCatchingCancellable(
"TapSignerImportRetryView",
"TapSigner import retry failed",
) {
nfc.derive(pin)
}

manager.resetRoute(TapSignerRoute.ImportSuccess(tapSigner, deriveInfo))
} catch (e: Exception) {
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null

app.alertState =
TaggedItem(
AppAlertState.TapSignerDeriveFailed(
e.message ?: "Unknown error occurred",
),
)
}
result
.onSuccess { deriveInfo ->
manager.resetRoute(TapSignerRoute.ImportSuccess(tapSigner, deriveInfo))
}.onFailure {
app.alertState =
TaggedItem(
AppAlertState.TapSignerDeriveFailed(
"TapSigner import failed. Please try again.",
),
)
}
}
},
modifier = Modifier.fillMaxWidth().padding(bottom = 30.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ fun TapSignerImportSuccessView(
try {
walletId = persistWallet(tapSigner, deriveInfo)
} catch (e: Exception) {
android.util.Log.e("TapSignerImportSuccess", "Failed to save wallet", e)
error = e.message ?: "Failed to save wallet"
android.util.Log.e("TapSignerImportSuccess", "Failed to save TapSigner wallet")
error = "Failed to save wallet"
} finally {
saving = false
}
Expand Down Expand Up @@ -155,8 +155,11 @@ fun TapSignerImportSuccessView(
try {
walletId = persistWallet(tapSigner, deriveInfo)
} catch (e: Exception) {
android.util.Log.e("TapSignerImportSuccess", "Failed to save wallet", e)
error = e.message ?: "Failed to save wallet"
android.util.Log.e(
"TapSignerImportSuccess",
"Failed to save TapSigner wallet",
)
error = "Failed to save wallet"
} finally {
saving = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,27 @@ class TapSignerManager(
return
}

android.util.Log.d(tag, "Navigating to $to, current path: $path")
android.util.Log.d(
tag,
"Navigating to ${routeKind(to)}, current path count: ${path.size}",
)
path.add(to)
}

private fun routeKind(route: org.bitcoinppl.cove_core.TapSignerRoute): String =
when (route) {
is org.bitcoinppl.cove_core.TapSignerRoute.InitSelect -> "initSelect"
is org.bitcoinppl.cove_core.TapSignerRoute.InitAdvanced -> "initAdvanced"
is org.bitcoinppl.cove_core.TapSignerRoute.StartingPin -> "startingPin"
is org.bitcoinppl.cove_core.TapSignerRoute.NewPin -> "newPin"
is org.bitcoinppl.cove_core.TapSignerRoute.ConfirmPin -> "confirmPin"
is org.bitcoinppl.cove_core.TapSignerRoute.SetupSuccess -> "setupSuccess"
is org.bitcoinppl.cove_core.TapSignerRoute.SetupRetry -> "setupRetry"
is org.bitcoinppl.cove_core.TapSignerRoute.ImportSuccess -> "importSuccess"
is org.bitcoinppl.cove_core.TapSignerRoute.ImportRetry -> "importRetry"
is org.bitcoinppl.cove_core.TapSignerRoute.EnterPin -> "enterPin"
}

private fun shouldPreventNavigation(
from: org.bitcoinppl.cove_core.TapSignerRoute,
to: org.bitcoinppl.cove_core.TapSignerRoute,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.bitcoinppl.cove.flows.TapSignerFlow

import org.bitcoinppl.cove.Log
import org.bitcoinppl.cove.nfc.TapCardNfcManager
import org.bitcoinppl.cove_core.*
import org.bitcoinppl.cove_core.tapcard.TapSigner
Expand All @@ -12,21 +11,14 @@ import org.bitcoinppl.cove_core.types.Psbt
class TapSignerNfcHelper(
private val tapSigner: TapSigner,
) {
private val tag = "TapSignerNfcHelper"
private val nfcManager = TapCardNfcManager.getInstance()
private var lastResponse: TapSignerResponse? = null

suspend fun setupTapSigner(
factoryPin: String,
newPin: String,
chainCode: ByteArray? = null,
): SetupCmdResponse =
try {
doSetupTapSigner(factoryPin, newPin, chainCode)
} catch (e: Exception) {
Log.e(tag, "Setup failed", e)
throw e
}
): SetupCmdResponse = doSetupTapSigner(factoryPin, newPin, chainCode)

suspend fun derive(pin: String): DeriveInfo =
performTapSignerCmd(TapSignerCmd.Derive(pin)) { response ->
Expand Down Expand Up @@ -87,17 +79,12 @@ class TapSignerNfcHelper(
cmd: TapSignerCmd,
successResult: (TapSignerResponse?) -> T?,
): T {
try {
val (result, response) = nfcManager.performTapSignerCmd(cmd, successResult)
// store last response for retry scenarios (matches iOS behavior)
// clean up previous response before storing new one
lastResponse?.destroy()
lastResponse = response
return result
} catch (e: Exception) {
Log.e(tag, "TapSigner command failed", e)
throw e
}
val (result, response) = nfcManager.performTapSignerCmd(cmd, successResult)
// store last response for retry scenarios (matches iOS behavior)
// clean up previous response before storing new one
lastResponse?.destroy()
lastResponse = response
return result
}

private suspend fun doSetupTapSigner(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.bitcoinppl.cove.AppManager
import org.bitcoinppl.cove.TaggedItem
import org.bitcoinppl.cove.findActivity
import org.bitcoinppl.cove.nfc.TapCardNfcManager
import org.bitcoinppl.cove.runCatchingCancellable
import org.bitcoinppl.cove_core.AppAlertState
import org.bitcoinppl.cove_core.SetupCmdResponse
import org.bitcoinppl.cove_core.TapSignerRoute
Expand Down Expand Up @@ -136,35 +137,44 @@ fun TapSignerSetupRetryView(
manager.isTagDetected = false
manager.isScanning = true

try {
val result = nfc.continueSetup(response)
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null

when (result) {
is SetupCmdResponse.Complete -> {
manager.resetRoute(TapSignerRoute.SetupSuccess(tapSigner, result.v1))
}
else -> {
manager.resetRoute(TapSignerRoute.SetupRetry(tapSigner, result))
val result =
try {
runCatchingCancellable(
"TapSignerSetupRetryView",
"TapSigner setup retry failed",
) {
nfc.continueSetup(response)
}
} finally {
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null
}
} catch (e: Exception) {
manager.isScanning = false
manager.isTagDetected = false
nfcManager.onMessageUpdate = null
nfcManager.onTagDetected = null

app.sheetState = null
app.alertState =
TaggedItem(
AppAlertState.TapSignerSetupFailed(
e.message ?: "Unknown error",
),
)
}
result
.onSuccess { setupResponse ->
when (setupResponse) {
is SetupCmdResponse.Complete -> {
manager.resetRoute(
TapSignerRoute.SetupSuccess(tapSigner, setupResponse.v1),
)
}
else -> {
manager.resetRoute(
TapSignerRoute.SetupRetry(tapSigner, setupResponse),
)
}
}
}.onFailure {
app.sheetState = null
app.alertState =
TaggedItem(
AppAlertState.TapSignerSetupFailed(
"TapSigner setup failed. Please try again.",
),
)
}
}
},
modifier = Modifier.fillMaxWidth().padding(bottom = 30.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fun TapSignerSetupSuccessView(
walletId = walletManager.id
}
} catch (e: Exception) {
android.util.Log.e("TapSignerSetupSuccess", "Failed to save wallet", e)
android.util.Log.e("TapSignerSetupSuccess", "Failed to save TapSigner wallet")
}
}

Expand Down
Loading
Loading