Skip to main content

Coco-Cashu Overview

Sovran uses Coco-Cashu as its core Cashu implementation. Coco is a modular, TypeScript-native library built on top of @cashu/cashu-ts.

Architecture

Never import from @cashu/cashu-ts directly. Always use coco packages. Coco wraps cashu-ts with better error handling, TypeScript types, and repository abstractions.

CocoManager Singleton

The CocoManager class is a singleton wrapper around Coco’s Manager that handles initialization, cleanup, and database management. helper/coco/manager.ts:38-749

Initialization Flow

The manager initializes in two phases: Phase 1: Blocking (happens during app startup) helper/coco/manager.ts:91-166
  1. Open SQLite database (coco.db or coco-N.db)
  2. Initialize repositories
  3. Create seed getter (lazy - no crypto work yet)
  4. Create NPC plugin (constructor only - no network)
  5. Instantiate Manager
Phase 2: Non-blocking (happens after app is visible) helper/coco/manager.ts:173-227
  1. Run initial NPC sync (fetch Lightning addresses from npubx.cash)
  2. Enable mint quote watcher
  3. Enable mint quote processor
  4. Enable proof state watcher
This two-phase approach ensures the app becomes interactive quickly (less than 1 second) while background tasks continue.

Database Per Profile

Each profile gets its own SQLite database:
helper/coco/manager.ts:59-67 Each database contains:
  • Proofs table - Ecash proofs with state (ready, reserved, inflight, spent)
  • Mint quotes table - Lightning → Cashu mint operations
  • Melt quotes table - Cashu → Lightning melt operations
  • Keysets table - Mint public keys for each unit (sat, usd, eur, etc.)
  • Mint info table - Cached mint metadata

Cleanup & Profile Switching

When switching profiles, the manager must be cleaned up: helper/coco/manager.ts:250-289 This is called from the drawer layout before switching profiles: app/(drawer)/_layout.tsx:102-102

Proof Lifecycle

Proofs flow through several states:

State Definitions

Proof State Watcher

The proof state watcher monitors inflight proofs and updates their state based on mint responses:
This prevents “stuck balance” where proofs remain inflight forever after a failed transaction.

Manual Proof Recovery

If proofs get stuck (e.g., due to a crash), users can manually free them: helper/coco/manager.ts:510-707 This is exposed in Settings → Storage → “Free Reserved Balance”.

Mint Operations

Adding a Mint

hooks/coco/useMintManagement.ts:33-51 Under the hood:
  1. manager.mint.trustMint(url) fetches mint info
  2. Stores keyset data in SQLite
  3. Adds mint URL to trusted mints list
  4. Returns mint metadata (name, icon, supported units)

Mint Info

Mint metadata is cached in SQLite:

Keyset Management

Keysets define the denominations and units a mint supports:
Keysets are automatically refreshed on mint operations.

Receiving Ecash

Token Parsing

Receiving Flow

P2PK (Pay-to-Public-Key)

Sovran supports P2PK tokens that require a private key to unlock:
P2PK keys are managed in Settings → Keyring.

Sending Ecash

Send Operation

hooks/coco/useSendWithHistory.ts creates a send operation:

Send States

Pending Ecash Sweeper

Unredeemed sent tokens can be reclaimed:
This is used in app/pendingEcash.tsx to sweep unclaimed sent tokens.

Lightning Operations

Minting (Lightning → Cashu)

The mint quote watcher automatically checks pending quotes every 5 seconds and mints proofs when paid.

Melting (Cashu → Lightning)

hooks/coco/useMeltWithHistory.ts handles melt operations:

Lightning Addresses

Lightning addresses (user@domain.com) are resolved via LNURL-pay:

Payment Requests (NUT-18)

hooks/coco/useProcessPaymentString.ts:216-331 Payment requests allow requesting ecash over Nostr without Lightning:

Mint Swapping & Rebalancing

Swap Operation

Rebalance Planning

components/blocks/rebalance/rebalancePlanner.ts calculates optimal rebalance steps:

Middleman Routing

If two mints don’t support direct swaps, Sovran can route through intermediary mints:
components/blocks/rebalance/routing.ts implements the routing algorithm.

NPC Plugin (npubx.cash)

The NPC plugin integrates with npubx.cash for Lightning addresses:
NPC sync runs in the non-blocking initialization phase.

React Hooks

coco-cashu-react provides hooks for common operations:
Sovran wraps these in custom hooks in hooks/coco/:

Best Practices

Never call Manager methods directly in components - use hooks:
Always handle rollback when operations fail:
Ensure the mint supports the unit you want to use:
Don’t assume quotes succeed immediately:

State Management

Learn about stores that complement Coco’s SQLite storage

Nostr Integration

See how Nostr payment requests integrate with Cashu