Skip to content

feat(wallet): rebuild Cashu ecash end to end, with Lightning and recovery - #7

Merged
areebahmeddd merged 2 commits into
mainfrom
feat/wallet-integration
Jul 25, 2026
Merged

feat(wallet): rebuild Cashu ecash end to end, with Lightning and recovery#7
areebahmeddd merged 2 commits into
mainfrom
feat/wallet-integration

Conversation

@areebahmeddd

Copy link
Copy Markdown
Owner

The wallet held real money but could lose it. Sending deleted proofs before
delivery, so a dismissed sheet or a DM that never routed destroyed the value
with no trace. Proofs sat in plaintext MMKV. DLEQ verification was dead code
that could only ever return true, so the receive path credited the balance
from any well-formed token. Nutzaps were unreadable by any other client, and
incoming ones were never subscribed to at all.

Money safety

  • Sending reserves proofs instead of deleting them. An undelivered token stays
    reclaimable across app restarts, and reconcile settles it from proof state.
  • Proofs move to an AES-256 MMKV file keyed from the Keychain/Keystore. If the
    key is unavailable the wallet locks rather than falling back to plaintext.
  • NUT-12 DLEQ now actually runs, against per-mint cached keysets. A forged
    token is refused and never reaches the store; missing keys report unchecked,
    never valid.
  • Offline receipts are tracked as unverified and shown separately, since DLEQ
    proves the mint signed a proof but never that it is unspent.
  • Balances are keyed per (mint, unit), so sat and usd from one mint can no
    longer be summed into one number.
  • Sends are fee-aware, so "send 100" means the recipient can claim 100.

New capabilities

  • Lightning deposit and withdrawal (NUT-04/05), quoted before spending, with
    unused routing reserve returned as change.
  • Opt-in 12-word recovery phrase (NUT-13/NUT-09), off by default, with the
    uncovered remainder shown rather than hidden.
  • Consolidate a split balance onto one mint over Lightning.
  • Transaction history, and reclaim/re-share for pending sends.

Correctness

  • NIP-61 rewritten to spec: kind 10019 published so others can pay us, kind
    9321 with per-proof tags, P2PK locked to a 33-byte key rather than an
    unspendable x-only Nostr key, and a watcher that redeems incoming zaps.
  • Token detection matched byte-for-byte to bitchat's regex, fixing duplicate
    cards for the cashu: URI form.
  • Mint calls refused while Tor is on with iOS, where Arti only wraps
    WebSockets, with an explicit opt-in under Privacy & Security.
  • One shared send path behind services/ecash-transfer, replacing three
    divergent copies in the Wallet, Mesh and Chat screens.

Store schema migrates v1 to v2 on first launch; the legacy plaintext file is
read once and wiped. Wire protocol, Noise, packet codec and Nostr transport
are untouched, so bitchat compatibility is unchanged.

Tests: 777 passing (payments 17 -> 70).

… state

- Added `sendingEcash` state to `MessageThread` to disable the send button during the sending process.
- Updated `handleSendEcash` to check for ongoing sends and prevent multiple submissions.
- Similar changes made in `PeerList` for sending sats, ensuring a smooth user experience.
- Enhanced wallet service to handle mint request timeouts and improve error handling for concurrent sends.
- Updated wallet store to ensure reservations are atomic and prevent double spending of proofs.
- Added tests to verify that reservations are respected and prevent concurrent sends from using the same proof.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying airhop-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: d1b74e5
Status:⚡️  Build in progress...

View logs

@areebahmeddd
areebahmeddd marked this pull request as ready for review July 25, 2026 23:06
@areebahmeddd
areebahmeddd merged commit aaaa15a into main Jul 25, 2026
2 of 3 checks passed
@areebahmeddd
areebahmeddd deleted the feat/wallet-integration branch July 25, 2026 23:06
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