Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cashu eCash

The module supports Cashu eCash tokens as an alternative payment method to Lightning invoices.


Standard Mode vs P2PK Mode

Standard ModeP2PK Mode
How it worksCalls wallet.receive() → contacts mint to swap tokensVerifies token locked to proxy’s public key locally
SpeedSlower (blocks on mint API call per request)Fast (milliseconds — no mint call!)
Best forLow-traffic or simple setupsHigh-traffic production deployments
Extra requirementNoneCASHU_WHITELISTED_MINTS is required

Standard Mode Setup

Environment=CASHU_ECASH_SUPPORT=true
Environment=CASHU_DB_PATH=/var/lib/nginx/cashu_tokens.db
# BIP39 wallet mnemonic (NUT-13 backup phrase); unset = auto-generated on first run
Environment=CASHU_WALLET_MNEMONIC="word1 word2 ... word12"

# Optional: Whitelist specific mints (comma-separated)
Environment=CASHU_WHITELISTED_MINTS=https://mint1.example.com,https://mint2.example.com

# Optional: Auto-redeem to Lightning
Environment=CASHU_REDEEM_ON_LIGHTNING=true
Environment=CASHU_REDEMPTION_INTERVAL_SECS=3600

⚠️ Security: CASHU_WALLET_MNEMONIC is the BIP39 phrase that derives the wallet seed (NUT-13) — the only backup of your wallet. Anyone with it can steal your tokens, and losing it loses the funds. It’s a 12/24-word phrase (not a hex secret); leave it unset to auto-generate and persist one on first run, and never commit it to Git. On startup the module records a seed fingerprint next to the DB and refuses to start if a later mnemonic doesn’t match — delete wallet.fingerprint to switch wallets intentionally.


P2PK Mode Setup (High Performance)

Environment=CASHU_P2PK_MODE=true
Environment=CASHU_P2PK_PRIVATE_KEY=<your-private-key-hex>
# CASHU_WHITELISTED_MINTS is REQUIRED in P2PK mode
Environment=CASHU_WHITELISTED_MINTS=https://mint1.example.com

⚠️ Security: CASHU_P2PK_PRIVATE_KEY is equally critical. Anyone with this key can spend tokens locked to your public key. Generate with openssl rand -hex 32.

How P2PK mode works per request:

  1. Proxy derives a public key from CASHU_P2PK_PRIVATE_KEY and sends it to clients via the X-Cashu header (NUT-24)
  2. Client creates P2PK-locked tokens to that public key
  3. Proxy verifies tokens are locked to its public key (NUT-11) — local check, no network call
  4. Proxy unlocks proofs with private key (local cryptographic operation)
  5. Unlocked proofs are stored directly in CDK database via wallet.receive_proofs()
  6. Background redemption task finds proofs via wallet.get_unspent_proofs() and redeems to Lightning via wallet.melt()

Redemption Fee Configuration

# Minimum balance to attempt melting (default: 10 sats)
Environment=CASHU_MELT_MIN_BALANCE_SATS=10

# Percentage to reserve for fees (default: 1%)
Environment=CASHU_MELT_FEE_RESERVE_PERCENT=1

# Minimum fee reserve when percentage is small (default: 4 sats)
Environment=CASHU_MELT_MIN_FEE_RESERVE_SATS=4

# Maximum proofs per melt operation (default: 0 = unlimited)
# Use this if your mint has a per-melt proof limit (e.g. mint.coinos.io = 1000)
Environment=CASHU_MAX_PROOFS_PER_MELT=1000

Fee calculation: fee_reserve = max(total_amount × percent/100, min_fee_sats)

Example 1 — Large balance (500 sats) with 1% fee reserve:

  • Percentage fee: 500 × 1% = 5 sats
  • Minimum fee: 4 sats
  • Used reserve: max(5, 4) = 5 sats
  • Redeemable: 500 - 5 = 495 sats

Example 2 — Small balance (50 sats) with 1% fee reserve:

  • Percentage fee: 50 × 1% = 0.5 sats
  • Minimum fee: 4 sats
  • Used reserve: max(0.5, 4) = 4 sats ← Minimum kicks in!
  • Redeemable: 50 - 4 = 46 sats

Example 3 — Proof count limiting when exceeding mint limit (CASHU_MAX_PROOFS_PER_MELT=1000):

  • Scenario: 1282 proofs worth 13,588 sats total
  • Check: 1282 proofs > 1000 limit → Limiting triggered
  • Action: Select first 1000 proofs worth ~10,600 sats
  • Invoice: Generate invoice for 10,600 sats
  • Remaining: 282 proofs (~2,988 sats) stay for next cycle
  • Next cycle: 282 proofs < 1000 limit → all remaining proofs melted

Actual melt quote fees are verified against the reserve; warnings appear if the reserve was insufficient.

Note on CASHU_WHITELISTED_MINTS: If not configured, all mints are accepted in standard mode. In P2PK mode, whitelisted mints are REQUIRED for security and the payment request (NUT-24).


SQLite Database Setup

# One-time setup — persists across restarts
sudo mkdir -p /var/lib/nginx
sudo chown nginx:nginx /var/lib/nginx
sudo chmod 750 /var/lib/nginx

The cdk-sqlite crate automatically creates the database file and tables. Database location: /var/lib/nginx/cashu_tokens.db

Note

This directory holds the token database and, when the mnemonic is auto-generated, wallet.mnemonic (mode 0600). Keep it owned by the nginx user, and include both files in your encrypted backups.