Skip to content

refactor(wallet)!: unify resumable Rust and FFI workflows - #2479

Draft
asmogo wants to merge 2 commits into
cashubtc:mainfrom
asmogo:feat/wallet-workflows-cleanup
Draft

asmogo wants to merge 2 commits into
cashubtc:mainfrom
asmogo:feat/wallet-workflows-cleanup

Conversation

@asmogo

@asmogo asmogo commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Description

Reshape the real wallet API around shared, resumable application workflows, with the same model in Rust and the generated language bindings.

  • Organize requests, sessions/plans, receipts, history, operations, and events into their owning wallet domains.
  • Use Wallet for one mint/unit and WalletManager for discovery, portfolios, payment requests, and cross-mint transfers. Keep construction local and network synchronization explicit.
  • Keep protocol-level controls behind advanced() and the opt-in advanced-wallet FFI feature. Remove the duplicated wallet trait/repository surfaces and redundant bridge layers.
  • Migrate the CLI, examples, integration tests, language-binding tests, and documentation together.
  • Harden persisted-operation recovery, send ownership and receipts, quote reservation concurrency, reusable mint claims, cross-mint retries, synchronization reporting, and FFI runtime handling.

Notes to the reviewers

This is an intentional breaking wallet API change, without compatibility aliases. The protocol engines remain available through the advanced boundary; the FFI layer delegates business logic to Rust.

Start with the architecture and migration guide and the API reference, then the domain implementations in crates/cdk/src/wallet and the normal/advanced FFI bridges.

Existing reserved send/payment saga records written by main remain recoverable. No database schema migration is introduced. The wallet database contract now requires melt-quote updates to compare both the quote version and its reservation owner; SQLite/Postgres, Redb, Supabase, and the custom FFI database contract are updated together.

This is one consolidated commit on top of upstream main at 1c6f683a.

Validation

Rechecked on the final branch:

  • cargo fmt --all -- --check
  • cargo +nightly fmt --all -- --check
  • git diff --check upstream/main...HEAD
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --lib --workspace --exclude cdk-postgres --quiet

The unit-test suite requires localhost access for its mock servers and was run outside the restricted network sandbox.

Stable rustfmt emits warnings about the repository's nightly-only formatting options, but exits successfully with no formatting errors. The nightly check also passes.

Additional checks completed during the preceding review:

  • PostgreSQL unit tests against a temporary local server.
  • Memory and SQLite integration suites: integration_tests_pure, test_swap_flow, wallet_saga, and nwc_e2e.
  • Core/FFI doc tests and FFI tests with advanced-wallet enabled.
  • Default, no-default-feature, wallet-only, and mint-only WASM checks in the pinned Nix environment.
  • Default and advanced UniFFI binding generation; Python, Swift, Kotlin, Go, and Dart binding tests.
  • typos.

Not run: the full Bitcoin/Lightning regtest environment or a live Supabase service. Dart's optional live-mint test was skipped.

Suggested CHANGELOG Updates

CHANGED

  • Replace the legacy wallet/repository API with domain-oriented, resumable Rust and FFI workflows.
  • Make synchronization explicit and distinguish unresolved pending value from spendable balance.

ADDED

  • Reviewable plans, durable resume entry points, operation discovery, receipts, and application events.
  • Wallet API architecture, migration, and reference documentation.

REMOVED

  • Duplicated wallet traits, repository bindings, and obsolete public API forwarding surfaces.

FIXED

  • Recovery of pre-redesign reserved sends/payments; wallet-scoped send status and accurate send receipts.
  • On-chain quote selection/reservation races, repeated claims on reusable mint quotes, and paid-source cross-mint claim retries.
  • Final-state synchronization reporting and synchronous FFI construction inside single-threaded Tokio runtimes.

Checklist

  • I followed the code style guidelines
  • I ran just quick-check before committing — individual checks are listed above; the aggregate recipe was not run.
  • If the Wallet API was modified (added/removed/changed), I have reflected those changes in the FFI bindings (crates/cdk-ffi)

Organize the wallet API by domain and expose request, session, plan, and receipt workflows with an explicit advanced boundary. Keep business logic in Rust and synchronize the UniFFI bridges, language tests, CLI, examples, and migration documentation.

Preserve recovery of existing persisted operations and harden send ownership, quote reservation concurrency, reusable mint claims, cross-mint retries, synchronization reporting, and FFI runtime handling.

BREAKING CHANGE: replace the legacy wallet and repository API with Wallet, WalletManager, domain workflows, and the opt-in advanced FFI surface. See docs/wallet-api.md and docs/wallet-api-reference.md for migration guidance.
@github-project-automation github-project-automation Bot moved this to Backlog in CDK Sep 6, 2026
Estimate the selected reserved proofs before confirming an offline send, preserving the receiver redemption-fee check. Keep the known one-sat fake Lightning fee separate from the estimated input fee and verify the payment receipt against both.

Validated both test_fees cases against the Nutshell CI image with a 100-ppk input fee; stable/nightly formatting and targeted Clippy checks pass.
@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 19.01249% with 1427 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.23%. Comparing base (1c6f683) to head (c55a56a).

Files with missing lines Patch % Lines
crates/cdk-ffi/src/wallet_api.rs 4.42% 1254 Missing ⚠️
crates/cdk-integration-tests/src/lib.rs 0.00% 37 Missing ⚠️
crates/cdk-ffi/src/wallet.rs 16.66% 25 Missing ⚠️
crates/cdk-ffi/src/types/nostr_backup.rs 0.00% 15 Missing ⚠️
crates/cdk-ffi/src/types/transaction.rs 0.00% 15 Missing ⚠️
...k-integration-tests/src/bin/start_regtest_mints.rs 0.00% 11 Missing ⚠️
crates/cdk-ffi/src/types/bip321.rs 0.00% 8 Missing ⚠️
crates/cdk-ffi/src/types/quote.rs 11.11% 8 Missing ⚠️
crates/cdk-ffi/src/types/wallet.rs 0.00% 8 Missing ⚠️
crates/cdk-ffi/src/database.rs 0.00% 7 Missing ⚠️
... and 10 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2479      +/-   ##
==========================================
- Coverage   79.05%   78.23%   -0.82%     
==========================================
  Files         387      393       +6     
  Lines      105617   109636    +4019     
==========================================
+ Hits        83494    85774    +2280     
- Misses      22123    23862    +1739     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Amperstrand

Copy link
Copy Markdown

While recovery is being reshaped here, one wallet-side cost profile worth having on the radar: long-lived wallets accumulate one Send/TokenCreated row per send (by design — revoke window), and today's boot-time recovery re-resumes each sequentially with an individual NUT-07 check (~3s/row measured against a LAN mint; multi-minute passes at a few thousand rows — #2631). Not a blocker or a request for this PR — just flagging it since the loop shape is being reworked; the current branch keeps the per-saga sequential checks. A sketch of one batching shape exists in the #2631 discussion as context if it ever helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants