Update README.md

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michilis
2026-02-17 03:50:03 +00:00
parent 50e5787ec2
commit bd18271957

270
README.md
View File

@@ -1,26 +1,28 @@
# Cashu Redeem API 🪙⚡
# Cashu Redeem API
API for redeeming Cashu tokens (ecash) to Lightning addresses using the cashu-ts library and LNURLp protocol.
A production-grade API for redeeming Cashu tokens (ecash) to Lightning addresses using the [cashu-ts](https://github.com/cashubtc/cashu-ts) library and LNURLp protocol.
## 🚀 Features
## Features
- **Decode Cashu tokens** - Parse and validate token content
- **Redeem to Lightning addresses** - Convert ecash to Lightning payments via LNURLp
- **Security features** - Domain restrictions, rate limiting, input validation
- **Robust error handling** - Comprehensive error messages
- **Interactive API Documentation** - Complete Swagger/OpenAPI documentation at `/docs`
- **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
## 📖 API Documentation
Interactive Swagger documentation is available at `/docs` when the server is running.
**Interactive Swagger Documentation**: Visit `/docs` when running the server for a complete, interactive API reference.
- Local: `http://localhost:3000/docs`
- OpenAPI spec: `http://localhost:3000/openapi.json`
Example: `https://cashu-redeem.azzamo.net/docs/`
## API Endpoints
## 📡 API Endpoints
### `POST /api/decode`
### 1. `POST /api/decode`
Decode a Cashu token and return its content. Supports both v1 and v3 token formats.
Decode a Cashu token and return its content. Supports both v3 (`cashuB`) and v1 (`cashuA`) token formats. Checks spendability against the mint.
**Request:**
```json
@@ -34,25 +36,33 @@ Decode a Cashu token and return its content. Supports both v1 and v3 token forma
{
"success": true,
"decoded": {
"mint": "https://mint.azzamo.net",
"totalAmount": 21000,
"numProofs": 3,
"denominations": [1000, 10000, 10000],
"format": "cashuA",
"mint": "https://kashu.me",
"totalAmount": 16,
"numProofs": 5,
"denominations": [8, 4, 2, 1, 1],
"format": "cashuB",
"spent": false
},
"mint_url": "https://mint.azzamo.net"
"mint_url": "https://kashu.me"
}
```
### 2. `POST /api/redeem`
Redeem a Cashu token to a Lightning address. Lightning address is optional - if not provided, uses the default address from configuration.
### `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:**
```json
{
"token": "cashuB...",
"lightningAddress": "user@ln.tips"
"lightningAddress": "user@twentyone.tips"
}
```
@@ -68,50 +78,36 @@ Redeem a Cashu token to a Lightning address. Lightning address is optional - if
{
"success": true,
"paid": true,
"amount": 21000,
"invoiceAmount": 20580,
"to": "user@ln.tips",
"fee": 1000,
"actualFee": 420,
"netAmount": 20000,
"mint_url": "https://mint.azzamo.net",
"format": "cashuA",
"preimage": "abc123..."
"amount": 16,
"invoiceAmount": 14,
"to": "user@twentyone.tips",
"fee": 2,
"netAmount": 14,
"mint_url": "https://kashu.me",
"format": "cashuB",
"preimage": "d5af74a3..."
}
```
**Success Response (using default address):**
```json
{
"success": true,
"paid": true,
"amount": 21000,
"invoiceAmount": 20580,
"to": "admin@your-domain.com",
"fee": 1000,
"actualFee": 420,
"netAmount": 20000,
"mint_url": "https://mint.azzamo.net",
"format": "cashuA",
"usingDefaultAddress": true,
"message": "Redeemed to default Lightning address: admin@your-domain.com"
}
```
**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 |
**Payment Verification**:
The API uses multiple indicators to verify payment success:
- `paid` flag from mint response
- Presence of payment preimage
- Payment state indicators
### `POST /api/validate-address`
### 3. `POST /api/validate-address`
Validate a Lightning address without redemption.
Validate a Lightning address without performing a redemption. Tests LNURLp resolution and returns address capabilities.
**Request:**
```json
{
"lightningAddress": "user@ln.tips"
"lightningAddress": "user@twentyone.tips"
}
```
@@ -120,48 +116,54 @@ Validate a Lightning address without redemption.
{
"success": true,
"valid": true,
"domain": "ln.tips",
"domain": "twentyone.tips",
"minSendable": 1,
"maxSendable": 100000000,
"commentAllowed": 144
"maxSendable": 1000000,
"commentAllowed": 2000
}
```
### 4. `GET /api/health`
Health check endpoint.
### `GET /api/health`
Health check endpoint returning server status, uptime, and memory usage.
**Response:**
```json
{
"status": "ok",
"timestamp": "2025-01-14T12:00:00Z",
"uptime": 3600,
"memory": {...},
"version": "1.0.0"
"timestamp": "2026-02-17T03:36:40.987Z",
"uptime": 170.23,
"memory": { "rss": 83873792, "heapTotal": 20520960, "heapUsed": 17170824 },
"version": "2.0.0"
}
```
## 🛠 Setup & Installation
### `GET /openapi.json`
Returns the full OpenAPI 3.0 specification as JSON.
## Setup & Installation
### Prerequisites
- Node.js >= 18.0.0
- npm or yarn
- npm >= 8.0.0
### Installation
1. **Clone and install dependencies:**
```bash
git clone <your-repo>
git clone https://github.com/Michilis/cashu-redeem-api.git
cd cashu-redeem-api
npm install
```
2. **Setup environment variables:**
2. **Configure environment variables:**
```bash
cp env.example .env
```
Edit `.env` file:
Edit `.env`:
```bash
# Server Configuration
PORT=3000
@@ -171,108 +173,148 @@ NODE_ENV=development
API_DOMAIN=localhost:3000
# Security Configuration
ALLOW_REDEEM_DOMAINS=ln.tips,getalby.com,wallet.mutinywallet.com
API_SECRET=your-secret-key-here
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)
RATE_LIMIT=100
# Rate Limiting (requests per minute per IP)
RATE_LIMIT=30
# Logging
LOG_LEVEL=info
# CORS Configuration
ALLOWED_ORIGINS=http://localhost:3000,https://yourdomain.com
ALLOWED_ORIGINS=*
```
3. **Start the server:**
```bash
# Development
# Development (with auto-reload)
npm run dev
# Production
npm start
```
## 🔧 Configuration
## Configuration
### Environment Variables
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `PORT` | Server port | `3000` | No |
| `NODE_ENV` | Environment | `development` | No |
| `ALLOW_REDEEM_DOMAINS` | Comma-separated allowed domains | All allowed | 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 |
| `ALLOWED_ORIGINS` | CORS allowed origins | `http://localhost:3000` | No |
| `LOG_LEVEL` | Logging level | `info` | No |
| `ALLOWED_ORIGINS` | CORS allowed origins (`*` for all) | `http://localhost:3000` | No |
### Domain Restrictions
To restrict redemptions to specific Lightning address domains, set:
Restrict redemptions to specific Lightning address domains:
```bash
ALLOW_REDEEM_DOMAINS=ln.tips,getalby.com,wallet.mutinywallet.com
ALLOW_REDEEM_DOMAINS=twentyone.tips,getalby.com,walletofsatoshi.com
```
If not set, all domains are allowed.
If set to `*` or not set, all domains are allowed.
### Default Lightning Address
To set a default Lightning address that will be used when no address is provided in redemption requests:
Set a fallback address used when no address is provided in redemption requests:
```bash
DEFAULT_LIGHTNING_ADDRESS=admin@your-domain.com
```
This allows users to redeem tokens without specifying a Lightning address - the tokens will automatically be sent to your configured default address. If no default is set, Lightning address becomes required for all redemption requests.
If no default is configured, the `lightningAddress` field becomes required for all redemption requests.
## Project Structure
### Data Flow
```
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
```
1. **Token Validation** - Parse and validate Cashu token structure
2. **Address Resolution** - Resolve Lightning address to LNURLp endpoint
3. **Invoice Generation** - Create Lightning invoice for the amount
4. **Token Melting** - Use cashu-ts to melt token and pay invoice
## Redemption Flow
## 🔒 Security Features
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
- **Input validation** - All inputs are sanitized and validated
- **Rate limiting** - 100 requests per minute per IP (configurable)
- **Domain restrictions** - Limit allowed Lightning address domains
- **CORS protection** - Configurable allowed origins
- **Error handling** - Comprehensive error messages without data leaks
## 🚦 Status Codes
## Internal Status Codes
| Status | Description |
|--------|-------------|
| `processing` | Redemption is in progress |
| `processing` | Redemption initiated |
| `parsing_token` | Validating and parsing the token |
| `resolving_invoice` | Resolving Lightning address to invoice |
| `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 paid and completed |
| `paid` | Successfully completed |
| `failed` | Redemption failed (see error details) |
## Security Features
## 🧪 Testing
- **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
### Interactive Testing with Swagger
## Testing
The easiest way to test the API is using the interactive Swagger documentation at `/docs`:
- Visit `http://localhost:3000/docs`
- Click "Try it out" on any endpoint
- Fill in the request parameters
- Execute the request directly from the browser
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:
```bash
# Health check
curl http://localhost:3000/api/health
## 🤝 Contributing
# 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. Add tests if applicable
5. Submit a pull request
4. Submit a pull request
## 📝 License
## License
MIT License - see LICENSE file for details.