Files
Cashu-redeem-api/README.md
Michilis bd18271957 Update README.md
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 03:50:03 +00:00

8.4 KiB

Cashu Redeem API

A production-grade API for redeeming Cashu tokens (ecash) to Lightning addresses using the cashu-ts library and LNURLp protocol.

Features

  • Decode Cashu tokens - Parse and validate token content, check spendability at the mint
  • Redeem to Lightning addresses - Convert ecash to Lightning payments via LNURLp with exact fee calculation
  • Lightning address validation - Verify addresses and query LNURLp capabilities
  • Duplicate detection - In-memory tracking prevents double-spend attempts
  • Security - Domain restrictions, rate limiting, input validation, CORS protection
  • Interactive API docs - Complete Swagger/OpenAPI documentation at /docs

API Documentation

Interactive Swagger documentation is available at /docs when the server is running.

  • Local: http://localhost:3000/docs
  • OpenAPI spec: http://localhost:3000/openapi.json

API Endpoints

POST /api/decode

Decode a Cashu token and return its content. Supports both v3 (cashuB) and v1 (cashuA) token formats. Checks spendability against the mint.

Request:

{
  "token": "cashuB..."
}

Response:

{
  "success": true,
  "decoded": {
    "mint": "https://kashu.me",
    "totalAmount": 16,
    "numProofs": 5,
    "denominations": [8, 4, 2, 1, 1],
    "format": "cashuB",
    "spent": false
  },
  "mint_url": "https://kashu.me"
}

POST /api/redeem

Redeem a Cashu token to a Lightning address. The Lightning address is optional if a default is configured.

The redemption process:

  1. Token validation and parsing
  2. Spendability check at the mint
  3. Melt quote to determine exact fees
  4. Invoice creation for the net amount (token amount minus fees)
  5. Token melting and Lightning payment

Request:

{
  "token": "cashuB...",
  "lightningAddress": "user@twentyone.tips"
}

Request (using default address):

{
  "token": "cashuB..."
}

Success Response:

{
  "success": true,
  "paid": true,
  "amount": 16,
  "invoiceAmount": 14,
  "to": "user@twentyone.tips",
  "fee": 2,
  "netAmount": 14,
  "mint_url": "https://kashu.me",
  "format": "cashuB",
  "preimage": "d5af74a3..."
}

Response fields:

Field Description
amount Total token amount in sats
invoiceAmount Amount sent to the Lightning address (after fees)
fee Exact fee charged by the mint (from melt quote)
netAmount Net amount received
preimage Lightning payment preimage (proof of payment)
usingDefaultAddress Present and true when the default address was used

POST /api/validate-address

Validate a Lightning address without performing a redemption. Tests LNURLp resolution and returns address capabilities.

Request:

{
  "lightningAddress": "user@twentyone.tips"
}

Response:

{
  "success": true,
  "valid": true,
  "domain": "twentyone.tips",
  "minSendable": 1,
  "maxSendable": 1000000,
  "commentAllowed": 2000
}

GET /api/health

Health check endpoint returning server status, uptime, and memory usage.

Response:

{
  "status": "ok",
  "timestamp": "2026-02-17T03:36:40.987Z",
  "uptime": 170.23,
  "memory": { "rss": 83873792, "heapTotal": 20520960, "heapUsed": 17170824 },
  "version": "2.0.0"
}

GET /openapi.json

Returns the full OpenAPI 3.0 specification as JSON.

Setup & Installation

Prerequisites

  • Node.js >= 18.0.0
  • npm >= 8.0.0

Installation

  1. Clone and install dependencies:
git clone https://github.com/Michilis/cashu-redeem-api.git
cd cashu-redeem-api
npm install
  1. Configure environment variables:
cp env.example .env

Edit .env:

# Server Configuration
PORT=3000
NODE_ENV=development

# API Domain/IP Configuration (for Swagger docs and CORS)
API_DOMAIN=localhost:3000

# Security Configuration
ALLOW_REDEEM_DOMAINS=*

# Default Lightning Address (used when no address is provided in redeem requests)
DEFAULT_LIGHTNING_ADDRESS=admin@your-domain.com

# Rate Limiting (requests per minute per IP)
RATE_LIMIT=30

# Logging
LOG_LEVEL=info

# CORS Configuration
ALLOWED_ORIGINS=*
  1. Start the server:
# Development (with auto-reload)
npm run dev

# Production
npm start

Configuration

Environment Variables

Variable Description Default Required
PORT Server port 3000 No
NODE_ENV Environment (development / production) development No
API_DOMAIN Domain for Swagger docs and CORS localhost:3000 No
ALLOW_REDEEM_DOMAINS Comma-separated allowed Lightning address domains (* for all) All allowed No
DEFAULT_LIGHTNING_ADDRESS Default Lightning address for redemptions None No
RATE_LIMIT Requests per minute per IP 100 No
LOG_LEVEL Logging level info No
ALLOWED_ORIGINS CORS allowed origins (* for all) http://localhost:3000 No

Domain Restrictions

Restrict redemptions to specific Lightning address domains:

ALLOW_REDEEM_DOMAINS=twentyone.tips,getalby.com,walletofsatoshi.com

If set to * or not set, all domains are allowed.

Default Lightning Address

Set a fallback address used when no address is provided in redemption requests:

DEFAULT_LIGHTNING_ADDRESS=admin@your-domain.com

If no default is configured, the lightningAddress field becomes required for all redemption requests.

Project Structure

cashu-redeem-api/
  server.js              # Express app, middleware, route mounting
  swagger.config.js      # OpenAPI/Swagger configuration and schemas
  components/
    cashu.js             # Token parsing, spendability checks, melt operations
    lightning.js         # LNURLp resolution, invoice creation, address validation
    redemption.js        # Orchestrates the full redemption flow
  routes/
    cashu.js             # POST /api/decode
    redemption.js        # POST /api/redeem
    lightning.js         # POST /api/validate-address
    health.js            # GET /api/health

Redemption Flow

  1. Token Parsing - Validate and decode the Cashu token structure
  2. Spendability Check - Verify proofs are unspent at the mint
  3. Melt Quote - Get exact fee from the mint before creating the invoice
  4. Address Resolution - Resolve Lightning address via LNURLp
  5. Invoice Generation - Create a Lightning invoice for the net amount (total minus fee)
  6. Token Melting - Melt the token at the mint to pay the invoice

Internal Status Codes

Status Description
processing Redemption initiated
parsing_token Validating and parsing the token
checking_spendability Checking proofs at the mint
getting_melt_quote Requesting fee quote from mint
resolving_invoice Creating Lightning invoice via LNURLp
melting_token Performing the melt operation
paid Successfully completed
failed Redemption failed (see error details)

Security Features

  • Input validation - All inputs are sanitized and validated
  • Rate limiting - Configurable per-IP request limits
  • Domain restrictions - Limit allowed Lightning address domains
  • CORS protection - Configurable allowed origins
  • Duplicate detection - Prevents resubmission of already-redeemed tokens
  • Error handling - Comprehensive error messages without sensitive data leaks

Testing

The easiest way to test the API is using the interactive Swagger documentation:

  1. Start the server: npm run dev
  2. Visit http://localhost:3000/docs
  3. Click "Try it out" on any endpoint
  4. Fill in the request parameters and execute

Or use curl:

# Health check
curl http://localhost:3000/api/health

# Decode a token
curl -X POST http://localhost:3000/api/decode \
  -H "Content-Type: application/json" \
  -d '{"token": "cashuB..."}'

# Validate a Lightning address
curl -X POST http://localhost:3000/api/validate-address \
  -H "Content-Type: application/json" \
  -d '{"lightningAddress": "user@twentyone.tips"}'

# Redeem a token
curl -X POST http://localhost:3000/api/redeem \
  -H "Content-Type: application/json" \
  -d '{"token": "cashuB...", "lightningAddress": "user@twentyone.tips"}'

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

License

MIT License - see LICENSE file for details.