Skip to content

Refactor UniFFI standalone functions to enum/record methods#612

Merged
praveenperera merged 10 commits intomasterfrom
use-methods
Mar 11, 2026
Merged

Refactor UniFFI standalone functions to enum/record methods#612
praveenperera merged 10 commits intomasterfrom
use-methods

Conversation

@praveenperera
Copy link
Contributor

@praveenperera praveenperera commented Mar 6, 2026

Convert standalone FFI functions to impl methods on their respective types where UniFFI supports it. This moves functions like fiatCurrencyEmoji() to FiatCurrency.emojiString(), hashRoute() to Route.hashValue(), walletMetadataIsEqual() to WalletMetadata.isEqual(), etc. Update Swift and Kotlin callers to use the new method syntax, remove wrapper extensions that are no longer needed, and regenerate bindings for both platforms.

Summary by CodeRabbit

  • Refactor

    • Internal APIs consolidated for more consistent cross-platform behavior.
  • Display Updates

    • Network names, color scheme labels, fiat currency labels (emoji + name), UTXO name/date, and wallet color options updated for clearer, consistent presentation across Android and iOS.
  • Bug Fixes

    • TapSigner authentication/error detection and migration watchdog checks adjusted for more reliable error handling and migration detection.

@coderabbitai
Copy link

coderabbitai bot commented Mar 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Many Rust free-function UniFFI exports were moved to type-bound methods and instance accessors; generated UniFFI bindings and platform call sites in Kotlin and Swift were updated accordingly (replacing helper functions/extensions with zero-arg methods or instance methods). No behavioral logic changes beyond API surface and call-site adaptations.

Changes

Cohort / File(s) Summary
Rust — API-to-method migration
rust/src/*, rust/crates/cove-types/src/*, rust/src/wallet/*, rust/src/router.rs, rust/src/tap_card/*, rust/src/mnemonic/ffi.rs, rust/src/multi_format.rs, rust/src/node_connect.rs, rust/src/signed_import.rs, rust/src/bootstrap.rs, rust/crates/cove-types/src/color_scheme.rs, rust/crates/cove-types/src/utxo.rs
Replaced many exported free functions with inherent methods and moved UniFFI exposure to per-type methods (e.g., Utxo.name()/date()/hashToUint()/isEqual(), BootstrapStep.isMigrationInProgress(), FiatCurrency.emojiString()/symbolString()/suffixString(), TapSignerReaderError.isAuthError()/isNoBackupError(), WalletAddressType.sortOrder()). Adjusted exports/visibility and added/removed corresponding UniFFI bindings.
Android (Kotlin) — generated bindings & call-site updates
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt, android/app/src/main/java/org/bitcoinppl/cove_core/types/cove_types.kt, android/app/src/main/java/org/bitcoinppl/cove/..., android/app/src/main/java/org/bitcoinppl/cove/utils/BootstrapStepExt.kt
Updated generated Kotlin Uniffi bindings and app call sites to use instance methods (e.g., colorScheme.capitalizedString(), fiatCurrency.emojiString(), selectedNodeSelection.toNode(), error.isAuthError(), step.isMigrationInProgress()). Removed/adjusted now-unused extension wrappers and imports.
iOS (Swift) — extensions & call-site updates
ios/Cove/Extention/*, ios/Cove/Flows/*, ios/CoveCore/Sources/CoveCore/CoveCore.swift, ios/Cove/WalletManager.swift, ios/Cove/Flows/SettingsFlow/SettingsPicker.swift
Removed or rewired Swift extensions that proxied free helpers; call sites updated to instance methods or description/new displayName (e.g., utxo.name(), utxo.date(), error.isAuthError(), toNode(), network.description). Added SettingsEnum.displayName default implementation.
Platform UI — local data-access changes
ios/Cove/Flows/CoinControlFlow/*, ios/Cove/Flows/SendFlow/Common/*, android/.../SettingsFlow/*
Replaced property accesses with zero-arg method calls for Utxo fields and similar data (no layout/UX changes). Minor text rendering switches to new instance accessors.
FFI binding regeneration & safety improvements
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt, android/app/src/main/java/org/bitcoinppl/cove_core/types/cove_types.kt
Regenerated/rewired Uniffi binding signatures to reflect renamed functions and method-style exports (more precise types, RustBuffer usage, renamed functions), and added Kotlin wrappers for the new instance methods introduced in Rust.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

android

🐰 Refactor hop, hooray!
Free functions hopped into place,
Now methods show their gentle face.
Calls are neater, bindings bright—
I nibble bugs and dance all night. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: converting standalone UniFFI functions to enum/record methods, which is the primary objective throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch use-methods

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR refactors ~20 standalone UniFFI FFI functions into impl methods on their respective types (e.g., fiatCurrencyEmoji(c)c.emojiString(), hashRoute(r)r.stableHash()), regenerates the Swift and Kotlin bindings, and removes the now-redundant wrapper extensions on both platforms. Alongside the API cleanup, the PR adds a meaningful safety feature: a pre-open database encryption-key verification step (verify_database_key) with V1→V2 header auto-upgrade support and two new AppInitError variants (DatabaseKeyMismatch, DatabaseVerificationFailed). The version is bumped to 1.3.0 across Rust, iOS, and Android.

Key points:

  • rust/src/mnemonic/ffi.rs: in_groups is missing an explicit #[uniffi::method(name = ...)] annotation. It will export as inGroups instead of the old numberOfWordsInGroups, with no corresponding caller update in this PR — a likely runtime/compile break.
  • ios/CoveCore/.../generated/cove.swift: StringOrData loses its Equatable and Hashable Swift conformances — a source-breaking change.
  • ios/Cove.xcodeproj/project.pbxproj: Minimum iOS deployment target raised from 18.0 to 18.4 with no stated justification, excluding users on 18.0–18.3.
  • The stableHash() methods use DefaultHasher, which is not stable across process restarts or Rust versions; the name implies more guarantees than the implementation provides.
  • New verify_v1_database_key correctly performs an early return after decrypting the first non-zero block, keeping startup overhead low.

Confidence Score: 3/5

  • Safe to merge after resolving the mnemonic FFI naming issue and confirming the iOS deployment-target bump is intentional.
  • The broad binding refactor is well-executed and the database key-verification feature is a meaningful correctness improvement with good test coverage. However, the missing #[uniffi::method] annotation on in_groups in mnemonic/ffi.rs is a likely runtime or compile-time break for callers of the old numberOfWordsInGroups function, the StringOrData Equatable/Hashable removal is a source-breaking API change in Swift, and the unexplained iOS 18.4 deployment-target bump narrows the supported device range.
  • rust/src/mnemonic/ffi.rs (missing method annotation), ios/CoveCore/Sources/CoveCore/generated/cove.swift (StringOrData conformance removal), and ios/Cove.xcodeproj/project.pbxproj (deployment target bump).

Important Files Changed

Filename Overview
rust/src/database/encrypted_backend.rs Adds verify_database_key function for pre-open key validation; adds V1→V2 header auto-upgrade; extracts decrypt_disk_block helper; well-tested with new unit tests. Minor concern: V1 block iteration could be slow for sparse databases.
rust/src/bootstrap.rs Adds database key verification step before opening the database; introduces DatabaseKeyMismatch and DatabaseVerificationFailed error variants in AppInitError; refactors BootstrapStep::isMigrationInProgress to an impl method. New unit tests added. The extra startup check is a meaningful correctness improvement.
rust/src/mnemonic/ffi.rs Converts number_of_words_in_groups and number_of_words_to_word_count standalone functions to impl methods. in_groups is missing an explicit #[uniffi::method(name = ...)] annotation, meaning it exports with a different name (inGroups) than the old standalone (numberOfWordsInGroups), and no caller-side update is present in the PR.
ios/Cove.xcodeproj/project.pbxproj Version bump to 1.3.0 (build 64) and iOS deployment target raised from 18.0 to 18.4. The target bump is unexplained and will exclude users on iOS 18.0–18.3.
ios/CoveCore/Sources/CoveCore/generated/cove.swift Regenerated UniFFI bindings for iOS. Removes standalone functions and adds impl methods correctly. StringOrData loses Equatable and Hashable conformance, which is a source-breaking change for any Swift code using it in sets/dictionaries.
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt Regenerated Kotlin UniFFI bindings. Correctly removes standalone functions and adds impl methods. Adds new AppInitException variants and new methods like isMigrationInProgress, emojiString, isAuthError, etc. Large automated change.
rust/src/router.rs Converts is_route_equal, hash_route, is_tap_signer_route_equal, and after_pin_action_user_message to impl methods. Also fixes a grammar typo in the Sign PIN action message ("need must" → "must"). stableHash uses DefaultHasher which is not stable across runs.
ios/Cove/CoveApp.swift Updates to use new method-call syntax (isMigrationInProgress()) and adds handling for the new DatabaseKeyMismatch error case with a user-friendly recovery message. Clean change.
rust/crates/cove-cspp/src/cspp.rs Adds tracing instrumentation (info!/warn!) to master-key load/generate paths and refactors the lookup to reuse intermediate results. Purely additive logging improvement with no logic changes.
ios/CoveCore/Sources/CoveCore/CoveCore.swift Removes Swift extension wrappers that are no longer needed after the refactor (e.g., AfterPinAction.userMessage, HardwareWalletMetadata.isTapSigner, BootstrapStep.isMigrationInProgress, Utxo.name/date). Clean-up with no logic issues.
ios/CoveCore/Sources/CoveCore/generated/cove_types.swift Regenerated cove-types Swift bindings. Adds methods date(), hashToUint(), isEqual(), name() to Utxo, and capitalizedString() to ColorSchemeSelection. Removes old standalone functions. Correct automated regeneration.

Sequence Diagram

sequenceDiagram
    participant App as iOS/Android App
    participant Bootstrap as bootstrap.rs
    participant KeyVerify as verify_database_key
    participant DB as EncryptedBackend
    participant FFI as UniFFI (Swift/Kotlin)

    App->>Bootstrap: bootstrap()
    Bootstrap->>Bootstrap: derive_encryption_key()
    Bootstrap->>KeyVerify: verify_database_key(&db_path)
    alt File does not exist
        KeyVerify-->>Bootstrap: Ok(())
    else V2 header present
        KeyVerify->>KeyVerify: verify_header_tag(key, header)
        alt Tag matches
            KeyVerify-->>Bootstrap: Ok(())
        else Tag mismatch
            KeyVerify-->>Bootstrap: Err(DatabaseKeyMismatch)
            Bootstrap-->>App: AppInitError::DatabaseKeyMismatch
        end
    else V1 header present
        KeyVerify->>KeyVerify: verify_v1_database_key (read first non-zero block)
        alt Decryption succeeds
            KeyVerify-->>Bootstrap: Ok(())
        else Decryption fails
            KeyVerify-->>Bootstrap: Err(HeaderIntegrity → DatabaseKeyMismatch)
            Bootstrap-->>App: AppInitError::DatabaseKeyMismatch
        end
    end
    Bootstrap->>DB: open_or_create_database()
    alt V1 header
        DB->>DB: upgrade header V1→V2 in-place
    end
    DB-->>Bootstrap: Database handle
    Bootstrap->>FFI: expose methods on types (e.g. route.stableHash(), fiatCurrency.emojiString())
    Bootstrap-->>App: Ok(wallet_count)
Loading

Comments Outside Diff (5)

  1. ios/Cove.xcodeproj/project.pbxproj, line 1498 (link)

    iOS deployment target raised to 18.4 without explanation

    The minimum deployment target jumps from 18.0 to 18.4 in both build configurations. iOS 18.4 was only recently released, which would exclude users still on iOS 18.0–18.3 from updating. Is there a specific API or framework requirement that necessitates this bump? If not, reverting to 18.0 (or at most 18.2/18.3) would preserve a broader user base.

  2. rust/src/mnemonic/ffi.rs, line 1583-1586 (link)

    in_groups missing #[uniffi::method] rename annotation

    Every other method in this PR that needed a name different from the snake_case-to-camelCase default uses an explicit #[uniffi::method(name = "...")] attribute (e.g., ffi_to_word_count"toWordCount", ffi_is_auth_error"isAuthError"). Here in_groups has no such annotation, so it will be exported as inGroups in Swift/Kotlin.

    The old standalone function was called numberOfWordsInGroups (Swift) / numberofwordsingroups (Kotlin). Any existing callers of that name will break. No caller-side update for this function is present in the PR diff, which suggests either the callers were not updated or the regenerated bindings still carry the old function (a checksum mismatch at runtime).

  3. ios/CoveCore/Sources/CoveCore/generated/cove.swift, line 24243 (link)

    StringOrData loses Equatable and Hashable conformance

    Previously StringOrData was declared as Equatable, Hashable in the generated Swift binding. After this PR it becomes a plain enum StringOrData with no protocol conformances.

    Any call-site that places a StringOrData value into a Set, uses it as a Dictionary key, or performs a == / != comparison will now fail to compile. This is a source-breaking change that deserves a call-out in the PR (even if no current callers hit it today, adding a conformance back as an extension would prevent future surprises).

  4. rust/src/router.rs, line 3658-3663 (link)

    DefaultHasher is not stable – stableHash name is misleading

    std::collections::hash_map::DefaultHasher is explicitly documented as not guaranteed to produce the same values across different Rust versions, builds, or even processes. The method is correctly used only for in-memory Hashable conformance (Swift) and won't be persisted, so it works in practice, but naming it stableHash implies cross-session or cross-version stability that the implementation cannot guarantee. The same applies to WalletMetadata::stable_hash.

    Consider renaming to sessionHash, hashValue, or simply leaning on the existing Hash derive, and updating the Swift/Kotlin call-sites accordingly.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  5. rust/src/database/encrypted_backend.rs, line 3156-3175 (link)

    verify_v1_database_key iterates every block but could skip gracefully

    The loop iterates from block 0 to the last block, skipping only all-zero blocks and returning Ok(()) after the first successful decryption. On a heavily used V1 database where the early blocks are all zero (e.g., sparse writes), this could scan many blocks before returning. The early return is correct, but an explicit comment explaining the "verify first non-zero block is enough to confirm the key" invariant would make the intent clearer and guard against future accidental removal of the early return Ok(()).

    Also, File::read_exact_at (via std::os::unix::fs::FileExt) is a Unix-only API. If this code ever needs to compile on Windows, it will fail at that call. A comment noting the Unix-only assumption would be helpful.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Last reviewed commit: daafa30

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
rust/src/router.rs (1)

421-438: ⚠️ Potential issue | 🟡 Minor

Typo in user message string.

Line 427 contains a grammatical error: "you need must enter" should be "you must enter".

Proposed fix
-            Self::Sign(_) => "For security purposes, you need must enter your TAPSIGNER PIN before you can sign a transaction".to_string(),
+            Self::Sign(_) => "For security purposes, you must enter your TAPSIGNER PIN before you can sign a transaction".to_string(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rust/src/router.rs` around lines 421 - 438, The user-facing string in
AfterPinAction::user_message contains a typo ("you need must enter") for the
Sign(_) arm; update that variant's message to read "you must enter your
TAPSIGNER PIN before you can sign a transaction" (ensure change is made in the
user_message method used by ffi_user_message as well).
rust/src/signed_import.rs (1)

185-216: ⚠️ Potential issue | 🟠 Major

Remove #[uniffi::export] impl SignedTransactionOrPsbt — UniFFI does not support arbitrary methods on enum types.

Lines 185–216 export instance methods on SignedTransactionOrPsbt, but UniFFI explicitly treats enums as data types without method support. The #[uniffi::export] impl syntax is reserved for objects (#[derive(uniffi::Object)]), not enums. An open UniFFI issue confirms this feature is not implemented. You have already defined the proper pattern with free functions (signed_transaction_or_psbt_try_parse, signed_transaction_or_psbt_try_from_bytes, etc.); remove the impl block and expose the remaining accessors (tx_id, is_psbt, is_transaction, transaction, psbt) as free functions with the same naming convention, or wrap them in a helper object if you need method-style binding.

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

In `@rust/src/signed_import.rs` around lines 185 - 216, Remove the
#[uniffi::export] impl SignedTransactionOrPsbt block — UniFFI does not support
exporting enum instance methods — and replace those exported instance methods
(ffi_tx_id, ffi_is_psbt, ffi_is_transaction, ffi_transaction, ffi_psbt) with
free functions following the existing naming convention (e.g.,
signed_transaction_or_psbt_<action> or ffi-prefixed free functions) that take a
SignedTransactionOrPsbt argument and internally call the existing methods
tx_id(), is_psbt(), is_transaction(), transaction(), and psbt(); this preserves
the same API surface for bindings without using a #[uniffi::export] impl on the
enum.
🧹 Nitpick comments (1)
ios/Cove/Extention/NodeSelection+Ext.swift (1)

10-17: Consider caching toNode() result if both properties are accessed together.

Both url and name call toNode() independently, which may create redundant conversions if both properties are accessed in sequence. For most use cases this is negligible, but if performance becomes a concern, consider a single computed node property or lazy caching.

♻️ Optional: Single conversion approach

If both properties are commonly accessed together:

extension NodeSelection {
    private var node: Node { toNode() }
    
    var url: String { node.url }
    var name: String { node.name }
}

Note: This still calls toNode() per access to node. For true caching, a different pattern would be needed, but that may be overkill for this use case.

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

In `@ios/Cove/Extention/NodeSelection`+Ext.swift around lines 10 - 17, Both url
and name call toNode() separately; add a private computed helper to perform the
conversion once and reuse it. Add a private var node: Node { toNode() } inside
the NodeSelection extension and change url and name to return node.url and
node.name respectively (keep in mind this computed helper still calls toNode()
per access; implement a stored cache on the underlying type only if true
persistent caching is required).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@rust/src/router.rs`:
- Around line 421-438: The user-facing string in AfterPinAction::user_message
contains a typo ("you need must enter") for the Sign(_) arm; update that
variant's message to read "you must enter your TAPSIGNER PIN before you can sign
a transaction" (ensure change is made in the user_message method used by
ffi_user_message as well).

In `@rust/src/signed_import.rs`:
- Around line 185-216: Remove the #[uniffi::export] impl SignedTransactionOrPsbt
block — UniFFI does not support exporting enum instance methods — and replace
those exported instance methods (ffi_tx_id, ffi_is_psbt, ffi_is_transaction,
ffi_transaction, ffi_psbt) with free functions following the existing naming
convention (e.g., signed_transaction_or_psbt_<action> or ffi-prefixed free
functions) that take a SignedTransactionOrPsbt argument and internally call the
existing methods tx_id(), is_psbt(), is_transaction(), transaction(), and
psbt(); this preserves the same API surface for bindings without using a
#[uniffi::export] impl on the enum.

---

Nitpick comments:
In `@ios/Cove/Extention/NodeSelection`+Ext.swift:
- Around line 10-17: Both url and name call toNode() separately; add a private
computed helper to perform the conversion once and reuse it. Add a private var
node: Node { toNode() } inside the NodeSelection extension and change url and
name to return node.url and node.name respectively (keep in mind this computed
helper still calls toNode() per access; implement a stored cache on the
underlying type only if true persistent caching is required).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67cb0249-0a49-4dfd-8424-32a5e578c66f

📥 Commits

Reviewing files that changed from the base of the PR and between d98f55d and 25f873e.

⛔ Files ignored due to path filters (2)
  • ios/CoveCore/Sources/CoveCore/generated/cove.swift is excluded by !**/generated/**
  • ios/CoveCore/Sources/CoveCore/generated/cove_types.swift is excluded by !**/generated/**
📒 Files selected for processing (46)
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/AppearanceSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/FiatCurrencySettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NetworkSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/TapSignerFlow/TapSignerEnterPinView.kt
  • android/app/src/main/java/org/bitcoinppl/cove/utils/BootstrapStepExt.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/types/cove_types.kt
  • ios/Cove/CoveApp.swift
  • ios/Cove/Extention/Color+Ext.swift
  • ios/Cove/Extention/ColorSchemeSelection+Ext.swift
  • ios/Cove/Extention/Enum+Ext.swift
  • ios/Cove/Extention/Error+Ext.swift
  • ios/Cove/Extention/NodeSelection+Ext.swift
  • ios/Cove/Extention/Routes+Ext.swift
  • ios/Cove/Extention/SignedTransactionOrPsbt+Ext.swift
  • ios/Cove/Extention/String+Ext.swift
  • ios/Cove/Extention/StringOrData+Ext.swift
  • ios/Cove/Extention/WalletAddressType+Ext.swift
  • ios/Cove/Extention/WalletMetadata+Ext.swift
  • ios/Cove/Flows/CoinControlFlow/UtxoListScreen.swift
  • ios/Cove/Flows/CoinControlFlow/UtxoRowPreview.swift
  • ios/Cove/Flows/SendFlow/Common/SendFlowUtxoCustomAmountSheetView.swift
  • ios/Cove/Flows/SettingsFlow/SettingsPicker.swift
  • ios/Cove/Flows/SettingsFlow/WalletSettings/WalletSettingsView.swift
  • ios/Cove/Flows/TapSignerFlow/TapSignerConfirmPinView.swift
  • ios/Cove/Flows/TapSignerFlow/TapSignerEnterPinView.swift
  • ios/Cove/WalletManager.swift
  • ios/CoveCore/Sources/CoveCore/CoveCore.swift
  • rust/crates/cove-types/src/color_scheme.rs
  • rust/crates/cove-types/src/network.rs
  • rust/crates/cove-types/src/utxo.rs
  • rust/src/bootstrap.rs
  • rust/src/fiat.rs
  • rust/src/manager/coin_control_manager.rs
  • rust/src/manager/wallet_manager.rs
  • rust/src/mnemonic/ffi.rs
  • rust/src/multi_format.rs
  • rust/src/node_connect.rs
  • rust/src/router.rs
  • rust/src/signed_import.rs
  • rust/src/tap_card.rs
  • rust/src/tap_card/tap_signer_reader.rs
  • rust/src/wallet.rs
  • rust/src/wallet/metadata.rs
💤 Files with no reviewable changes (3)
  • ios/Cove/Extention/ColorSchemeSelection+Ext.swift
  • android/app/src/main/java/org/bitcoinppl/cove/utils/BootstrapStepExt.kt
  • rust/crates/cove-types/src/network.rs

Convert standalone FFI functions to impl methods on their respective
types where UniFFI supports it. This moves functions like
fiatCurrencyEmoji() to FiatCurrency.emojiString(), hashRoute() to
Route.hashValue(), walletMetadataIsEqual() to WalletMetadata.isEqual(),
etc. Update Swift and Kotlin callers to use the new method syntax,
remove wrapper extensions that are no longer needed, and regenerate
bindings for both platforms.
Bump Android app versionCode to 16. Regenerate UniFFI-generated iOS bindings (ios/CoveCore/Sources/CoveCore/generated/*): rename/replace several functions to match updated Rust API (e.g. addressErrorToAlertState, signedTransactionOrPsbtTryFromBytes/FromNfcMessage/Parse, defaultWalletColors, walletMetadataPreview, allUnits/allNetworks/allColorSchemes), add createTransportErrorFromCode, and update the corresponding checksum constants. These are generated binding updates to keep the iOS API in sync with the Rust changes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ios/Cove/Extention/SignedTransactionOrPsbt`+Ext.swift:
- Around line 12-21: The helper wrappers tryFromNfcMessage, tryParse and
tryFromBytes call non-existent symbols; update their call sites to match the
generated CoveCore API names (replace signedTransactionOrPsbtTryParseNfcMessage
with signedTransactionOrPsbtTryFromNfcMessage,
signedTransactionOrPsbtTryParseString with signedTransactionOrPsbtTryParse, and
signedTransactionOrPsbtTryParseBytes with signedTransactionOrPsbtTryFromBytes)
or alternatively regenerate the CoveCore bindings so the helper calls match;
ensure you update the calls inside the static methods tryFromNfcMessage,
tryParse and tryFromBytes accordingly.

In `@ios/CoveCore/Sources/CoveCore/CoveCore.swift`:
- Around line 208-211: The init in extension SendFlowAlertState is calling a
non-existent symbol sendFlowAlertStateFromAddressError; change that call to the
generated Swift bridge function addressErrorToAlertState(error:address:) (or
rename the Rust export to match if you control native bindings). Update the
initializer in SendFlowAlertState to call addressErrorToAlertState(error:
addressError, address: address) so it uses the existing Rust-exported symbol.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a08c47c7-a433-488a-b596-05e58779c552

📥 Commits

Reviewing files that changed from the base of the PR and between c47aa7e and a36f614.

⛔ Files ignored due to path filters (2)
  • ios/CoveCore/Sources/CoveCore/generated/cove.swift is excluded by !**/generated/**
  • ios/CoveCore/Sources/CoveCore/generated/cove_types.swift is excluded by !**/generated/**
📒 Files selected for processing (44)
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/AppearanceSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/FiatCurrencySettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NetworkSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove/flows/TapSignerFlow/TapSignerEnterPinView.kt
  • android/app/src/main/java/org/bitcoinppl/cove/utils/BootstrapStepExt.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/types/cove_types.kt
  • ios/Cove/CoveApp.swift
  • ios/Cove/Extention/Color+Ext.swift
  • ios/Cove/Extention/ColorSchemeSelection+Ext.swift
  • ios/Cove/Extention/Enum+Ext.swift
  • ios/Cove/Extention/Error+Ext.swift
  • ios/Cove/Extention/NodeSelection+Ext.swift
  • ios/Cove/Extention/Routes+Ext.swift
  • ios/Cove/Extention/SignedTransactionOrPsbt+Ext.swift
  • ios/Cove/Extention/String+Ext.swift
  • ios/Cove/Extention/StringOrData+Ext.swift
  • ios/Cove/Extention/WalletAddressType+Ext.swift
  • ios/Cove/Extention/WalletMetadata+Ext.swift
  • ios/Cove/Flows/CoinControlFlow/UtxoListScreen.swift
  • ios/Cove/Flows/CoinControlFlow/UtxoRowPreview.swift
  • ios/Cove/Flows/SendFlow/Common/SendFlowUtxoCustomAmountSheetView.swift
  • ios/Cove/Flows/SettingsFlow/SettingsPicker.swift
  • ios/Cove/Flows/SettingsFlow/WalletSettings/WalletSettingsView.swift
  • ios/Cove/Flows/TapSignerFlow/TapSignerConfirmPinView.swift
  • ios/Cove/Flows/TapSignerFlow/TapSignerEnterPinView.swift
  • ios/Cove/WalletManager.swift
  • ios/CoveCore/Sources/CoveCore/CoveCore.swift
  • rust/crates/cove-types/src/color_scheme.rs
  • rust/crates/cove-types/src/utxo.rs
  • rust/src/bootstrap.rs
  • rust/src/fiat.rs
  • rust/src/manager/coin_control_manager.rs
  • rust/src/manager/wallet_manager.rs
  • rust/src/mnemonic/ffi.rs
  • rust/src/multi_format.rs
  • rust/src/node_connect.rs
  • rust/src/router.rs
  • rust/src/signed_import.rs
  • rust/src/tap_card.rs
  • rust/src/tap_card/tap_signer_reader.rs
  • rust/src/wallet.rs
  • rust/src/wallet/metadata.rs
💤 Files with no reviewable changes (2)
  • android/app/src/main/java/org/bitcoinppl/cove/utils/BootstrapStepExt.kt
  • ios/Cove/Extention/ColorSchemeSelection+Ext.swift
🚧 Files skipped from review as they are similar to previous changes (21)
  • ios/Cove/WalletManager.swift
  • rust/src/manager/wallet_manager.rs
  • rust/src/manager/coin_control_manager.rs
  • ios/Cove/CoveApp.swift
  • android/app/src/main/java/org/bitcoinppl/cove/flows/TapSignerFlow/TapSignerEnterPinView.kt
  • rust/crates/cove-types/src/utxo.rs
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NetworkSettingsScreen.kt
  • ios/Cove/Flows/CoinControlFlow/UtxoListScreen.swift
  • ios/Cove/Flows/TapSignerFlow/TapSignerEnterPinView.swift
  • rust/src/mnemonic/ffi.rs
  • ios/Cove/Flows/SettingsFlow/WalletSettings/WalletSettingsView.swift
  • rust/src/wallet/metadata.rs
  • ios/Cove/Flows/TapSignerFlow/TapSignerConfirmPinView.swift
  • rust/src/router.rs
  • ios/Cove/Extention/WalletAddressType+Ext.swift
  • rust/src/signed_import.rs
  • ios/Cove/Flows/CoinControlFlow/UtxoRowPreview.swift
  • ios/Cove/Extention/Color+Ext.swift
  • android/app/src/main/java/org/bitcoinppl/cove/MainActivity.kt
  • rust/src/multi_format.rs
  • ios/Cove/Extention/Error+Ext.swift

Corrects a grammatical error in AfterPinAction::Sign in rust/src/router.rs by replacing "you need must enter" with "you must enter" so the security prompt before signing a transaction reads clearly.
Rename Rust FFI function and fix Swift call sites that referenced
wrong generated binding names after the standalone-to-methods refactor.
Detect database key mismatch early in bootstrap before the panic in
Database::global(). When the keychain master key doesn't match the
encrypted database (e.g. after backup/restore, Xcode reinstall, or
certificate re-provisioning), return AppInitError::DatabaseKeyMismatch
instead of panicking with "HMAC mismatch".

- Add verify_database_key() for lightweight header-only HMAC check
- Add DatabaseKeyMismatch variant to AppInitError
- Show blocking error screen on iOS with recovery contact info
- Add keychain master key lookup logging to diagnose future key loss
- Add V1→V2 header auto-upgrade support
@praveenperera
Copy link
Contributor Author

@greptile-apps re-review

@praveenperera praveenperera merged commit 79e4a30 into master Mar 11, 2026
10 checks passed
@praveenperera praveenperera deleted the use-methods branch March 11, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant