Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ private suspend fun deriveAction(
if (isAuthError(e)) {
Log.w("TapSignerEnterPin", "TapSigner auth failed - likely wrong PIN")
manager.errorMessage = "Wrong PIN, please try again"
} else if (isConnectionError(e)) {
Log.w("TapSignerEnterPin", "TapSigner connection lost")
manager.errorMessage = "Tag connection lost, please hold your phone still"
} else {
manager.errorMessage = "Connection failed, please try again"
}
Expand Down Expand Up @@ -317,6 +320,9 @@ private suspend fun backupAction(
if (isAuthError(e)) {
Log.w("TapSignerEnterPin", "TapSigner auth failed - likely wrong PIN")
manager.errorMessage = "Wrong PIN, please try again"
} else if (isConnectionError(e)) {
Log.w("TapSignerEnterPin", "TapSigner connection lost")
manager.errorMessage = "Tag connection lost, please hold your phone still"
} else {
manager.errorMessage = "Connection failed, please try again"
}
Expand Down Expand Up @@ -374,6 +380,9 @@ private suspend fun signAction(
if (isAuthError(e)) {
Log.w("TapSignerEnterPin", "TapSigner auth failed - likely wrong PIN")
manager.errorMessage = "Wrong PIN, please try again"
} else if (isConnectionError(e)) {
Log.w("TapSignerEnterPin", "TapSigner connection lost")
manager.errorMessage = "Tag connection lost, please hold your phone still"
} else {
manager.errorMessage = "Connection failed, please try again"
}
Expand All @@ -385,3 +394,9 @@ private fun isAuthError(error: Exception): Boolean {
return error is org.bitcoinppl.cove_core.TapSignerReaderException &&
error.isAuthError()
}

private fun isConnectionError(error: Exception): Boolean {
// check if error is a connection error using type-safe FFI function
return error is org.bitcoinppl.cove_core.TapSignerReaderException &&
error.isConnectionError()
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,7 @@ private class TapCardTransport(
response
} catch (e: Exception) {
Log.e(tag, "APDU error", e)
throw TransportException.UnknownException(
"Tag connection lost, please hold your phone still and try again"
)
throw TransportException.ConnectionException("Tag connection lost, please hold your phone still")
}
Comment thread
kartikangiras marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

Expand Down
37 changes: 35 additions & 2 deletions android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3244,6 +3244,8 @@ internal object UniffiLib {
): RustBuffer.ByValue
external fun uniffi_cove_fn_method_tapsignerreadererror_isautherror(`ptr`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): Byte
external fun uniffi_cove_fn_method_tapsignerreadererror_isconnectionerror(`ptr`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): Byte
external fun uniffi_cove_fn_method_tapsignerreadererror_isnobackuperror(`ptr`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): Byte
external fun uniffi_cove_fn_method_tapsignerreadererror_uniffi_trait_display(`ptr`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
Expand Down Expand Up @@ -46601,6 +46603,16 @@ sealed class TapSignerReaderException: kotlin.Exception() {
}


fun `isConnectionError`(): kotlin.Boolean {
return FfiConverterBoolean.lift(
uniffiRustCall() { _status ->
UniffiLib.uniffi_cove_fn_method_tapsignerreadererror_isconnectionerror(FfiConverterTypeTapSignerReaderError.lower(this),
_status)
}
)
}


fun `isNoBackupError`(): kotlin.Boolean {
return FfiConverterBoolean.lift(
uniffiRustCall() { _status ->
Expand Down Expand Up @@ -47725,6 +47737,14 @@ sealed class TransportException: kotlin.Exception() {
get() = "v1=${ v1 }"
}

class ConnectionException(

val v1: kotlin.String
) : TransportException() {
override val message
get() = "v1=${ v1 }"
}

class UnknownException(

val v1: kotlin.String
Expand Down Expand Up @@ -47779,7 +47799,10 @@ public object FfiConverterTypeTransportError : FfiConverterRustBuffer<TransportE
6 -> TransportException.CvcChangeException(
FfiConverterString.read(buf),
)
7 -> TransportException.UnknownException(
7 -> TransportException.ConnectionException(
FfiConverterString.read(buf),
)
8 -> TransportException.UnknownException(
FfiConverterString.read(buf),
)
else -> throw RuntimeException("invalid error enum value, something is very wrong!!")
Expand Down Expand Up @@ -47818,6 +47841,11 @@ public object FfiConverterTypeTransportError : FfiConverterRustBuffer<TransportE
4UL
+ FfiConverterString.allocationSize(value.v1)
)
is TransportException.ConnectionException -> (
// Add the size for the Int that specifies the variant plus the size needed for all fields
4UL
+ FfiConverterString.allocationSize(value.v1)
)
is TransportException.UnknownException -> (
// Add the size for the Int that specifies the variant plus the size needed for all fields
4UL
Expand Down Expand Up @@ -47858,11 +47886,16 @@ public object FfiConverterTypeTransportError : FfiConverterRustBuffer<TransportE
FfiConverterString.write(value.v1, buf)
Unit
}
is TransportException.UnknownException -> {
is TransportException.ConnectionException -> {
buf.putInt(7)
FfiConverterString.write(value.v1, buf)
Unit
}
is TransportException.UnknownException -> {
buf.putInt(8)
FfiConverterString.write(value.v1, buf)
Unit
}
}.let { /* this makes the `when` an expression, which ensures it is exhaustive */ }
}

Expand Down
6 changes: 5 additions & 1 deletion ios/Cove/AppManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

private let walletModeChangeDelayMs = 250

@Observable final class AppManager: FfiReconcile {
@MainActor
@Observable

Check warning on line 8 in ios/Cove/AppManager.swift

View workflow job for this annotation

GitHub Actions / swiftformat

Remove trailing space at end of a line. (trailingSpace)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trim trailing whitespace.

swiftformat is flagging a trailing space after @Observable.

Proposed fix
-@Observable 
+@Observable
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Observable
`@Observable`
🧰 Tools
🪛 GitHub Check: swiftformat

[warning] 8-8:
Remove trailing space at end of a line. (trailingSpace)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/AppManager.swift` at line 8, Remove the trailing whitespace after
the attribute declaration so `@Observable ` becomes `@Observable`; edit the
`AppManager.swift` file to delete the extra space following the `@Observable`
attribute (ensure there are no other trailing spaces on that line) and save/run
swiftformat to confirm the warning is cleared.

final class AppManager: FfiReconcile {
Comment on lines +7 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find FfiReconcile protocol declaration and call sites that may now cross actor boundaries.
rg -nP '\bprotocol\s+FfiReconcile\b' --type=swift -C5
rg -nP '\bAppManager\.shared\.(dispatch|pushRoute|popRoute|setRoute|resetRoute|reset|reloadWallets|selectWallet|loadWallets|toggleSidebar)\b' --type=swift -C2
rg -nP '\b\.reconcile\s*\(' --type=swift -C2

Repository: bitcoinppl/cove

Length of output: 6326


🏁 Script executed:

# Get the full FfiReconcile protocol definition with isolation attributes
rg -A 20 'public protocol FfiReconcile' --type=swift ios/CoveCore/Sources/CoveCore/generated/cove.swift

Repository: bitcoinppl/cove

Length of output: 827


🏁 Script executed:

# Get AppManager.reconcile() and dispatch(action:) implementations
cat -n ios/Cove/AppManager.swift | head -350 | tail -150

Repository: bitcoinppl/cove

Length of output: 5335


🏁 Script executed:

# Check the context of AuthManager.reset() call
cat -n ios/Cove/AuthManager.swift | sed -n '115,130p'

Repository: bitcoinppl/cove

Length of output: 443


🏁 Script executed:

# Get broader context around AuthManager.reset() call
cat -n ios/Cove/AuthManager.swift | sed -n '100,135p'

Repository: bitcoinppl/cove

Length of output: 1205


🏁 Script executed:

# Find all dispatch(action:) calls to check their context
rg -n 'dispatch\(action:' --type=swift -B 3 -A 1

Repository: bitcoinppl/cove

Length of output: 50371


🏁 Script executed:

# Check for any Swift compilation errors in the project
find . -name "*.swift" -type f | head -5

Repository: bitcoinppl/cove

Length of output: 276


🏁 Script executed:

# Search for nonisolated declarations in AppManager or similar patterns
rg -n 'nonisolated func (reconcile|dispatch)' --type=swift

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Check if there are any `@unchecked` Sendable or actor isolation suppression patterns
rg -n '@unchecked|nonisolated|-suppress' --type=swift ios/Cove/AppManager.swift

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Check AppManager.swift around the reconcile and dispatch methods for any actor isolation issues
cat -n ios/Cove/AppManager.swift | sed -n '238,245p'

Repository: bitcoinppl/cove

Length of output: 348


🏁 Script executed:

# Look for any build configuration or Swift settings that enable strict concurrency
fd -i 'build.settings|swiftsettings|xcconfig' --type f | head -10

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Check if there are any generated error/warning indicators in the codebase
rg -i 'error:|warning:|fixme' ios/Cove/AppManager.swift | head -20

Repository: bitcoinppl/cove

Length of output: 131


Mark reconcile(message:) and dispatch(action:) as nonisolated.

The class-level @MainActor annotation makes both methods main-actor-isolated, but FfiReconcile protocol declares reconcile(message:) with no isolation attributes. Since Rust FFI callbacks invoke this method from non-Swift contexts (potentially from background threads), a main-actor-isolated implementation would violate actor boundaries at runtime. The existing DispatchQueue.main.async wrapper in the reconcile() implementation confirms this was a known concern. Both protocol-conforming methods (reconcile and dispatch) should be marked nonisolated to allow FFI entry from any context, with the main actor dispatch handled explicitly in the method body as already done.

🧰 Tools
🪛 GitHub Check: swiftformat

[warning] 8-8:
Remove trailing space at end of a line. (trailingSpace)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/AppManager.swift` around lines 7 - 9, AppManager is annotated
`@MainActor` which makes its methods actor-isolated, but FfiReconcile's callbacks
(reconcile(message:) and dispatch(action:)) are invoked from non-Swift/FFI
contexts; mark both methods as nonisolated so they can be called from any thread
and keep the existing explicit MainActor dispatch inside their bodies (e.g.,
continue using DispatchQueue.main.async or Task { `@MainActor` ... } within
reconcile(message:) and dispatch(action:) to run UI/main-thread work). Locate
the implementations of reconcile(message:) and dispatch(action:) in AppManager
and add the nonisolated modifier to each method signature while preserving the
current main-thread dispatch logic.

static let shared = makeShared()

private let logger = Log(id: "AppManager")
Expand Down Expand Up @@ -93,6 +95,7 @@
self.rust.listenForUpdates(updater: self)
}

@MainActor
public func getWalletManager(id: WalletId) throws -> WalletManager {
if let walletvm = walletManager, walletvm.id == id {
logger.debug("found and using vm for \(id)")
Expand All @@ -107,6 +110,7 @@
return walletManager!
}

@MainActor
public func getSendFlowManager(_ wm: WalletManager, presenter: SendFlowPresenter) -> SendFlowManager {
let id = wm.id

Expand Down
1 change: 1 addition & 0 deletions ios/Cove/Flows/TapSignerFlow/TapSignerConfirmPinView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct TapSignerConfirmPinView: View {
case let .failure(error):
if error.isAuthError() { return app.alertState = .init(.tapSignerInvalidAuth) }
if error.isNoBackupError() { return app.alertState = .init(.tapSignerNoBackup(tapSigner: args.tapSigner)) }
if error.isConnectionError() { return app.alertState = .init(.general(title: "Connection Lost", message: "Tag connection lost, please hold your phone still")) }
app.alertState = .init(.general(title: "Error", message: error.description))
}
}
Expand Down
6 changes: 6 additions & 0 deletions ios/Cove/Flows/TapSignerFlow/TapSignerEnterPinView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct TapSignerEnterPin: View {
if error.isAuthError() {
app.sheetState = nil
app.alertState = .init(.tapSignerWrongPin(tapSigner: tapSigner, action: .derive))
} else if error.isConnectionError() {
app.alertState = .init(.general(title: "Connection Lost", message: "Tag connection lost, please hold your phone still"))
} else {
app.alertState = .init(.tapSignerDeriveFailed(message: error.description))
}
Expand Down Expand Up @@ -83,6 +85,8 @@ struct TapSignerEnterPin: View {
if error.isAuthError() {
app.sheetState = nil
app.alertState = .init(.tapSignerWrongPin(tapSigner: tapSigner, action: .backup))
} else if error.isConnectionError() {
app.alertState = .init(.general(title: "Connection Lost", message: "Tag connection lost, please hold your phone still"))
} else {
app.alertState = .init(
.general(title: "Backup Failed!", message: error.description)
Expand Down Expand Up @@ -128,6 +132,8 @@ struct TapSignerEnterPin: View {
if error.isAuthError() {
app.sheetState = nil
app.alertState = .init(.tapSignerWrongPin(tapSigner: tapSigner, action: .sign(psbt)))
} else if error.isConnectionError() {
app.alertState = .init(.general(title: "Connection Lost", message: "Tag connection lost, please hold your phone still"))
} else {
app.alertState = .init(
.general(title: "Signing Failed!", message: error.description)
Expand Down
4 changes: 3 additions & 1 deletion ios/Cove/ImportWalletManager.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import SwiftUI

@Observable class ImportWalletManager: ImportWalletManagerReconciler {
@MainActor
@Observable

Check warning on line 4 in ios/Cove/ImportWalletManager.swift

View workflow job for this annotation

GitHub Actions / swiftformat

Remove trailing space at end of a line. (trailingSpace)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trim trailing whitespace.

swiftformat is flagging a trailing space after @Observable.

Proposed fix
-@Observable 
+@Observable
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Observable
`@Observable`
🧰 Tools
🪛 GitHub Check: swiftformat

[warning] 4-4:
Remove trailing space at end of a line. (trailingSpace)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/ImportWalletManager.swift` at line 4, Remove the trailing whitespace
after the `@Observable` attribute in ImportWalletManager.swift so that the
annotation is exactly "@Observable" with no extra spaces; update the declaration
that uses the `@Observable` attribute (the annotation line in the
ImportWalletManager class/file) to eliminate the trailing space so swiftformat
no longer flags it.

final class ImportWalletManager: ImportWalletManagerReconciler {
private let logger = Log(id: "ImportWalletManager")
var rust: RustImportWalletManager

Expand Down
3 changes: 2 additions & 1 deletion ios/Cove/Security.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import Foundation
import KeychainSwift

class KeychainAccessor: KeychainAccess {
@MainActor
final class KeychainAccessor: KeychainAccess {
let keychain: KeychainSwift

init() {
Expand Down
3 changes: 1 addition & 2 deletions ios/Cove/ShareSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import LinkPresentation
import SwiftUI
import UIKit

@MainActor
private class ShareableFile: NSObject, UIActivityItemSource {
private final class ShareableFile: NSObject, UIActivityItemSource {
let url: URL
let iconImage: UIImage?

Expand Down
20 changes: 16 additions & 4 deletions ios/Cove/TapSignerNFC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,12 @@ private class TapCardNFC: NSObject, NFCTagReaderSessionDelegate {
} catch let error as TapSignerReaderError {
logger.error("TAPSIGNER error: \(error)")
tapSignerError = error
if case .TapSignerError(.CkTap(.BadAuth)) = error {
if error.isAuthError() {
return session.invalidate(errorMessage: "Wrong PIN, please try again")
}
if error.isConnectionError() {
return session.invalidate(errorMessage: "Tag connection lost, please hold your phone still")
}
session.invalidate(errorMessage: "TapSigner error: \(error.description)")
} catch {
logger.error("Error creating reader: \(error)")
Expand Down Expand Up @@ -439,9 +442,18 @@ class TapCardTransport: TapcardTransportProtocol, @unchecked Sendable {

if let error {
logger.error("APDU error: \(error)")
continuation.resume(
throwing: TransportError.UnknownError(error.localizedDescription)
)
// Check if this is a connection error
if let nfcError = error as? NFCReaderError,
nfcError.code == .readerTransceiveErrorTagConnectionLost
{
continuation.resume(
throwing: TransportError.ConnectionError(error.localizedDescription)
)
} else {
continuation.resume(
throwing: TransportError.UnknownError(error.localizedDescription)
)
}
return
}

Expand Down
4 changes: 3 additions & 1 deletion ios/Cove/WalletManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

extension WeakReconciler: WalletManagerReconciler where Reconciler == WalletManager {}

@Observable final class WalletManager: AnyReconciler, WalletManagerReconciler {
@MainActor
@Observable

Check warning on line 6 in ios/Cove/WalletManager.swift

View workflow job for this annotation

GitHub Actions / swiftformat

Remove trailing space at end of a line. (trailingSpace)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Trim trailing whitespace.

swiftformat is flagging a trailing space after @Observable.

Proposed fix
-@Observable 
+@Observable
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Observable
`@Observable`
🧰 Tools
🪛 GitHub Check: swiftformat

[warning] 6-6:
Remove trailing space at end of a line. (trailingSpace)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/WalletManager.swift` at line 6, Remove the trailing whitespace after
the `@Observable` attribute in WalletManager.swift: edit the line containing
"@Observable " to be "@Observable" (no trailing space), save and re-run
swiftformat/lint to confirm the warning is cleared; ensure no other lines in the
file have trailing spaces.

final class WalletManager: AnyReconciler, WalletManagerReconciler {
Comment on lines +5 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect generated UniFFI bindings & related protocols for actor isolation expectations.
fd -t f 'WalletManagerReconciler|wallet_manager' ios/CoveCore | head -50
rg -nP '\b(protocol|func)\s+(WalletManagerReconciler|reconcile|reconcileMany|dispatch)\b' --type=swift -C2
rg -nP '\bAnyReconciler\b' --type=swift -C3
rg -nP '\bWeakReconciler\b' --type=swift -C3

Repository: bitcoinppl/cove

Length of output: 34306


🏁 Script executed:

cat -n ios/Cove/WalletManager.swift | head -280 | tail -250

Repository: bitcoinppl/cove

Length of output: 9241


🏁 Script executed:

# Check for trailing whitespace on line 6 specifically
sed -n '6p' ios/Cove/WalletManager.swift | od -c | grep -E '(space|tab)$' && echo "Trailing whitespace found" || echo "No trailing whitespace"

Repository: bitcoinppl/cove

Length of output: 141


🏁 Script executed:

# Check if reconcile/reconcileMany methods have nonisolated marker
rg -A 5 'func reconcile\(message:|func reconcileMany\(messages:' ios/Cove/WalletManager.swift

Repository: bitcoinppl/cove

Length of output: 542


🏁 Script executed:

# Check line 6 directly with hexdump alternative
sed -n '6p' ios/Cove/WalletManager.swift | cat -A

Repository: bitcoinppl/cove

Length of output: 73


🏁 Script executed:

# Search for any recent fixes or build-related comments
rg -i 'mainactor|nonisolated|compilation|doesnt compile|actor isolation' ios/Cove/WalletManager.swift

Repository: bitcoinppl/cove

Length of output: 100


🏁 Script executed:

# Check if there are any other managers with `@MainActor` to compare pattern
rg '@MainActor' ios/Cove/ --type swift | grep -E 'class|struct'

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Look at other reconciler implementations to see if they use nonisolated
rg -B2 -A8 'func reconcile\(message:' ios/Cove/*.swift | grep -E '(nonisolated|@MainActor|class )' -A1 -B1

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Look for any PR or branch information, recent commits
git log --oneline -20 ios/Cove/WalletManager.swift

Repository: bitcoinppl/cove

Length of output: 148


🏁 Script executed:

# Check if `@MainActor` is recently added (compare with git)
git show HEAD:ios/Cove/WalletManager.swift | head -10

Repository: bitcoinppl/cove

Length of output: 353


🏁 Script executed:

# Verify current full signature of reconcile to be absolutely certain
sed -n '238,244p' ios/Cove/WalletManager.swift

Repository: bitcoinppl/cove

Length of output: 288


🏁 Script executed:

# Check generated protocol definition more carefully to see isolation context
rg -A 10 'public protocol WalletManagerReconciler' ios/CoveCore/Sources/CoveCore/generated/cove.swift | head -20

Repository: bitcoinppl/cove

Length of output: 418


🏁 Script executed:

# Final check: does WalletManager or other managers actually have nonisolated on reconcile?
rg 'nonisolated.*func reconcile' ios/Cove/ --type swift

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Check other managers to see if they have `@MainActor`
rg -B2 'class.*AnyReconciler.*Reconciler {' ios/Cove/ --type swift | grep '@MainActor' | wc -l

Repository: bitcoinppl/cove

Length of output: 211


🏁 Script executed:

# Verify the exact line 6 content with hex
sed -n '6p' ios/Cove/WalletManager.swift | xxd

Repository: bitcoinppl/cove

Length of output: 103


🏁 Script executed:

# Check if the repo has recent actor-related changes
git log --oneline --all -30 | grep -i 'actor\|mainactor\|isolation'

Repository: bitcoinppl/cove

Length of output: 41


🏁 Script executed:

# Verify trailing space on line 6 using sed and wc
sed -n '6p' ios/Cove/WalletManager.swift | wc -c
# Compare with line 5 (should have no trailing space)
sed -n '5p' ios/Cove/WalletManager.swift | wc -c

Repository: bitcoinppl/cove

Length of output: 65


🏁 Script executed:

# Check what line 6 actually contains by looking at raw bytes
sed -n '6p' ios/Cove/WalletManager.swift | od -An -tx1

Repository: bitcoinppl/cove

Length of output: 102


Add nonisolated to reconcile/reconcileMany methods to satisfy protocol conformance under @MainActor isolation.

WalletManager is marked @MainActor, making all instance methods main-actor isolated. However, both AnyReconciler and the generated WalletManagerReconciler protocol declare reconcile and reconcileMany as non-isolated. The class conformance won't compile unless these specific methods are marked nonisolated.

The internal DispatchQueue.main.async wrapping becomes redundant once methods are nonisolated, since they're called from Rust on a background thread; removing it and marking the methods nonisolated is the idiomatic pattern.

Also fix trailing whitespace on line 6 (@Observable).

🧰 Tools
🪛 GitHub Check: swiftformat

[warning] 6-6:
Remove trailing space at end of a line. (trailingSpace)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/WalletManager.swift` around lines 5 - 7, WalletManager is `@MainActor`
but must implement nonisolated reconcile and reconcileMany from
AnyReconciler/WalletManagerReconciler; mark the instance methods reconcile(...)
and reconcileMany(...) as nonisolated, remove the redundant
DispatchQueue.main.async wrappers inside those methods (since they'll be called
from background threads), and ensure the `@Observable` annotation has no trailing
whitespace on the class declaration line.

typealias Message = WalletManagerReconcileMessage
typealias Action = WalletManagerAction

Expand Down
22 changes: 20 additions & 2 deletions ios/CoveCore/Sources/CoveCore/generated/cove.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28627,6 +28627,14 @@ public func isAuthError() -> Bool {
})
}

public func isConnectionError() -> Bool {
return try! FfiConverterBool.lift(try! rustCall() {
uniffi_cove_fn_method_tapsignerreadererror_isconnectionerror(
FfiConverterTypeTapSignerReaderError_lower(self),$0
)
})
}

public func isNoBackupError() -> Bool {
return try! FfiConverterBool.lift(try! rustCall() {
uniffi_cove_fn_method_tapsignerreadererror_isnobackuperror(
Expand Down Expand Up @@ -29338,6 +29346,8 @@ enum TransportError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError
)
case CvcChangeError(String
)
case ConnectionError(String
)
case UnknownError(String
)

Expand Down Expand Up @@ -29397,7 +29407,10 @@ public struct FfiConverterTypeTransportError: FfiConverterRustBuffer {
case 6: return .CvcChangeError(
try FfiConverterString.read(from: &buf)
)
case 7: return .UnknownError(
case 7: return .ConnectionError(
try FfiConverterString.read(from: &buf)
)
case 8: return .UnknownError(
try FfiConverterString.read(from: &buf)
)

Expand Down Expand Up @@ -29442,10 +29455,15 @@ public struct FfiConverterTypeTransportError: FfiConverterRustBuffer {
FfiConverterString.write(v1, into: &buf)


case let .UnknownError(v1):
case let .ConnectionError(v1):
writeInt(&buf, Int32(7))
FfiConverterString.write(v1, into: &buf)


case let .UnknownError(v1):
writeInt(&buf, Int32(8))
FfiConverterString.write(v1, into: &buf)

}
}
}
Expand Down
4 changes: 4 additions & 0 deletions rust/src/tap_card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub enum TransportError {
#[error("CvcChangeError: {0}")]
CvcChangeError(String),

#[error("ConnectionError: {0}")]
ConnectionError(String),

#[error("UnknownError: {0}")]
UnknownError(String),
}
Expand Down Expand Up @@ -108,6 +111,7 @@ impl From<TransportError> for ApduError {
TransportError::IncorrectSignature(msg) => Self::IncorrectSignature(msg),
TransportError::UnknownCardType(msg) => Self::UnknownCardType(msg),
TransportError::CvcChangeError(_) => Self::CkTap(CkTapError::BadArguments.into()),
TransportError::ConnectionError(_) => Self::CkTap(CkTapError::BadArguments.into()),
TransportError::UnknownError(_) => Self::CkTap(CkTapError::BadArguments.into()),
}
}
Expand Down
9 changes: 9 additions & 0 deletions rust/src/tap_card/tap_signer_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,10 @@ impl TapSignerReaderError {
pub const fn is_no_backup_error(&self) -> bool {
matches!(self, Self::TapSignerError(TransportError::CkTap(CkTapError::BackupFirst)))
}

pub const fn is_connection_error(&self) -> bool {
matches!(self, Self::TapSignerError(TransportError::ConnectionError(_)))
}
}

mod ffi {
Expand Down Expand Up @@ -622,6 +626,11 @@ impl TapSignerReaderError {
fn ffi_is_no_backup_error(&self) -> bool {
self.is_no_backup_error()
}

#[uniffi::method(name = "isConnectionError")]
fn ffi_is_connection_error(&self) -> bool {
self.is_connection_error()
}
}

// MARK: - FFI PREVIEW
Expand Down
Loading