Files
CashumintsAPI/README.md
Michilis 62c9651a5e Update documentation and routes to remove /v1 prefix
- Update all route documentation comments
- Update README, env.example, and starter-docs
- Update install.sh
2025-12-21 01:46:14 -03:00

417 lines
14 KiB
Markdown

# 🌿 Cashumints.space API
A production-ready, decentralized observability, discovery, and reputation API for the Cashu mint ecosystem.
## Features
- **Mint Discovery** - Track and index Cashu mints across the ecosystem
- **Uptime Monitoring** - Continuous probing with full historical data
- **Metadata Tracking** - NUT-06 compliant metadata with version history
- **Nostr Reviews** - NIP-87 based review ingestion from configurable relays
- **Trust Scores** - Transparent, explainable reputation scoring (0-100)
- **Analytics** - Pageviews, trending mints, and popularity metrics
- **Admin API** - Full mint curation and system management
- **OpenAPI Docs** - Interactive Swagger UI documentation
## Quick Start
```bash
# Clone and install
git clone <repo>
cd cashumints-api
npm install
# Configure
cp env.example .env
openssl rand -hex 32 # Generate admin key, add to .env
# Initialize database
npm run migrate
# Start API server
npm start
# View documentation
open http://localhost:3000/docs
```
## Production Deployment
### Prerequisites
- Node.js 18+
- Nginx (reverse proxy)
- systemd (process management)
- Let's Encrypt (SSL)
### Installation
```bash
# Create user
sudo useradd -r -s /bin/false cashumints
# Clone to /opt
sudo git clone <repo> /opt/cashumints-api
cd /opt/cashumints-api
# Install dependencies
sudo npm install --production
# Configure
sudo cp env.example .env
sudo openssl rand -hex 32 # Add to .env as ADMIN_API_KEY
sudo nano .env
# Create data directory
sudo mkdir -p data
sudo chown cashumints:cashumints data
# Initialize database
sudo -u cashumints npm run migrate
```
### Systemd Services
```bash
# Install service files
sudo cp deploy/cashumints-api.service /etc/systemd/system/
sudo cp deploy/cashumints-workers.service /etc/systemd/system/
# Reload and enable
sudo systemctl daemon-reload
sudo systemctl enable cashumints-api cashumints-workers
# Start services
sudo systemctl start cashumints-api
sudo systemctl start cashumints-workers
# Check status
sudo systemctl status cashumints-api
sudo systemctl status cashumints-workers
# View logs
sudo journalctl -u cashumints-api -f
sudo journalctl -u cashumints-workers -f
```
### Nginx Setup
```bash
# Install nginx config
sudo cp deploy/nginx.conf /etc/nginx/sites-available/cashumints-api
sudo ln -s /etc/nginx/sites-available/cashumints-api /etc/nginx/sites-enabled/
# Get SSL certificate
sudo certbot --nginx -d api.cashumints.space
# Test and reload
sudo nginx -t
sudo systemctl reload nginx
```
## API Documentation
Interactive API documentation is available at:
- **Swagger UI**: `http://localhost:3000/docs`
- **OpenAPI JSON**: `http://localhost:3000/openapi.json`
## API Endpoints
### System
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/health` | Health check |
| GET | `/stats` | System statistics |
| GET | `/reviews` | Global reviews feed (filterable) |
| GET | `/analytics/uptime` | Ecosystem uptime analytics |
| GET | `/analytics/versions` | Mint version distribution |
| GET | `/analytics/nuts` | NUT support analytics |
### Admin (requires `X-Admin-Api-Key` header)
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/admin/mints` | Manually add a mint |
| POST | `/admin/mints/{id}/urls` | Add URL to mint |
| POST | `/admin/mints/merge` | Merge two mints |
| POST | `/admin/mints/split` | Undo a merge |
| POST | `/admin/mints/{id}/disable` | Hide from listings |
| POST | `/admin/mints/{id}/enable` | Re-enable mint |
| POST | `/admin/mints/{id}/metadata/refresh` | Force metadata fetch |
| POST | `/admin/mints/{id}/trust/recompute` | Force trust recalc |
| POST | `/admin/mints/{id}/status/reset` | Reset stuck state |
| POST | `/admin/mints/{id}/probe` | Force immediate probe |
| GET | `/admin/mints/{id}/visibility` | Get visibility status |
| GET | `/admin/jobs` | View job queue |
| GET | `/admin/system/metrics` | System health |
| GET | `/admin/audit` | Audit log (filter by mint_id) |
Admin endpoints also support `/admin/mints/by-url?url=` variants for all operations.
### Mints
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/mints` | List all mints (paginated, filterable) |
| GET | `/mints/trending` | Get trending mints by popularity |
| GET | `/mints/{mint_id}` | Get mint by ID |
| GET | `/mints/by-url?url=` | Get mint by URL |
| POST | `/mints/submit` | Submit new mint for tracking |
### Mint Details
All endpoints support both `/{mint_id}` and `/by-url?url=` variants:
| Endpoint | Description |
|----------|-------------|
| `/urls` | All URLs for mint (clearnet, Tor, mirrors) |
| `/metadata` | NUT-06 metadata |
| `/metadata/history` | Metadata change history |
| `/status` | Lightweight current status |
| `/uptime?window=24h\|7d\|30d` | Uptime statistics |
| `/uptime/timeseries?window=&bucket=` | Timeseries for charting |
| `/incidents` | Downtime incidents |
| `/trust` | Trust score with breakdown |
| `/reviews` | Nostr reviews (NIP-87) |
| `/views` | Pageview statistics |
| `/features` | Derived features (NUTs, Bolt11, etc.) |
## Configuration
Copy `env.example` to `.env` and configure:
```bash
# Server
PORT=3000
HOST=0.0.0.0
NODE_ENV=production
# Admin (REQUIRED - generate with: openssl rand -hex 32)
ADMIN_API_KEY=your-secure-key-here
# Database (SQLite)
DATABASE_PATH=./data/cashumints.db
# Probing
PROBE_TIMEOUT_MS=10000
PROBE_INTERVAL_ONLINE_MS=300000 # 5 minutes
PROBE_INTERVAL_OFFLINE_MS=900000 # 15 minutes
CONSECUTIVE_FAILURES_OFFLINE=3
ABANDONED_AFTER_DAYS=30
# Nostr Relays (comma-separated)
NOSTR_RELAYS=wss://relay.damus.io,wss://relay.nostr.band,wss://nos.lol
# Trust Score Weights (out of 100)
TRUST_WEIGHT_UPTIME=40
TRUST_WEIGHT_SPEED=25
TRUST_WEIGHT_REVIEWS=20
TRUST_WEIGHT_IDENTITY=10
TRUST_PENALTY_MAX=15
# Rate Limiting
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=100
```
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Nginx (Reverse Proxy) │
│ • SSL termination • Rate limiting • Caching │
└────────────────────────────┬────────────────────────────────┘
┌────────────────────────────┴────────────────────────────────┐
│ HTTP API (Express.js) │
│ • REST endpoints • Swagger UI • Admin API │
│ • CORS enabled • Compression • Helmet security │
└────────────────────────────┬────────────────────────────────┘
┌────────────────────────────┴────────────────────────────────┐
│ SQLite Database │
│ mints │ mint_urls │ probes │ metadata │ reviews │ scores │
│ incidents │ pageviews │ jobs │ uptime_rollups │ audit_log │
└────────────────────────────┬────────────────────────────────┘
┌────────────────────────────┴────────────────────────────────┐
│ Background Workers │
│ Probe │ Metadata │ Nostr │ Rollup │ Trust │ Cleanup │
└─────────────────────────────────────────────────────────────┘
```
## Trust Score
Trust scores (0-100) are computed from:
| Component | Max Points | Based On |
|-----------|------------|----------|
| Uptime | 40 | 30-day uptime percentage |
| Speed | 25 | Average response time (RTT) |
| Reviews | 20 | Nostr review quantity & rating |
| Identity | 10 | Metadata completeness |
| Penalties | -15 | Offline status, incidents, instability |
**Trust Levels:**
- **Excellent**: 85-100
- **High**: 70-84
- **Medium**: 50-69
- **Low**: 25-49
- **Unknown**: 0-24
## Mint Lifecycle
```
┌─────────────┐
Discovery ───▶ │ unknown │
└──────┬──────┘
│ successful probe
┌──────▼──────┐
│ online │ ◀──────────┐
└──────┬──────┘ │
│ slow response │ recovery
┌──────▼──────┐ │
│ degraded │ ───────────┤
└──────┬──────┘ │
│ consecutive │
│ failures │
┌──────▼──────┐ │
│ offline │ ───────────┘
└──────┬──────┘
│ > 30 days
┌──────▼──────┐
│ abandoned │
└─────────────┘
```
## Nostr Integration (NIP-87)
The API ingests these event kinds from configured relays:
| Kind | Description |
|------|-------------|
| 38172 | Cashu mint announcements (self-published by mints) |
| 38173 | Fedimint announcements |
| 38000 | Recommendations/reviews (with `#k` tag referencing 38172) |
Reviews are parsed for:
- Mint URL (from `u` or `d` tags, with or without protocol)
- Rating 1-5 (from `rating` tag or `quality` tag like `"1/1"` recommend / `"0/1"` not recommend)
- Content (review text)
## Admin API
All admin actions are audited. Never deletes raw data.
```bash
# Add a mint manually
curl -X POST http://localhost:3000/admin/mints \
-H "X-Admin-Api-Key: $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"mint_url": "https://mint.example.com", "notes": "Trusted operator"}'
# Get system metrics
curl http://localhost:3000/admin/system/metrics \
-H "X-Admin-Api-Key: $ADMIN_API_KEY"
# Force trust recalculation
curl -X POST http://localhost:3000/admin/mints/{mint_id}/trust/recompute \
-H "X-Admin-Api-Key: $ADMIN_API_KEY"
# View audit log
curl http://localhost:3000/admin/audit \
-H "X-Admin-Api-Key: $ADMIN_API_KEY"
```
## Project Structure
```
cashumints-api/
├── src/
│ ├── index.js # Server entry point
│ ├── config.js # Configuration
│ ├── db/
│ │ ├── connection.js # Database connection
│ │ ├── migrate.js # Migration runner
│ │ ├── schema.sql # Main schema
│ │ └── schema-admin.sql # Admin schema
│ ├── docs/
│ │ └── openapi.js # OpenAPI specification
│ ├── middleware/
│ │ ├── adminAuth.js # Admin authentication
│ │ ├── errorHandler.js # Error handling
│ │ └── rateLimit.js # Rate limiting
│ ├── routes/
│ │ ├── admin.js # Admin endpoints
│ │ ├── mints.js # Mint endpoints
│ │ └── system.js # System endpoints
│ ├── services/
│ │ ├── AdminService.js # Admin operations
│ │ ├── MintService.js # Mint CRUD
│ │ ├── ProbeService.js # HTTP probing
│ │ ├── MetadataService.js # NUT-06 metadata
│ │ ├── UptimeService.js # Uptime rollups
│ │ ├── TrustService.js # Trust scoring
│ │ ├── ReviewService.js # Nostr reviews
│ │ ├── PageviewService.js # Analytics
│ │ └── JobService.js # Background jobs
│ ├── utils/
│ │ ├── url.js # URL normalization
│ │ ├── crypto.js # Hashing
│ │ └── time.js # Time utilities
│ └── workers/
│ ├── index.js # Combined runner
│ ├── probe.js # Mint probing
│ ├── metadata.js # Metadata fetching
│ ├── nostr.js # Nostr ingestion
│ ├── rollup.js # Uptime aggregation
│ └── trust.js # Trust calculation
├── deploy/
│ ├── cashumints-api.service # API systemd service
│ ├── cashumints-workers.service # Workers systemd service
│ └── nginx.conf # Nginx configuration
├── data/ # SQLite database (auto-created)
├── env.example # Configuration template
├── package.json # Dependencies
└── README.md # This file
```
## Development
```bash
# Install dependencies
npm install
# Run in development mode (auto-reload)
npm run dev
# Run specific worker
npm run worker:probe
npm run worker:metadata
npm run worker:nostr
npm run worker:rollup
npm run worker:trust
```
## Design Principles
1. **History is never erased** - All raw data is stored and aggregated. Nothing is overwritten.
2. **Offline ≠ dead** - Mints transition through states. Recovery is always possible.
3. **URL ≠ identity** - Mint identity is stable. Multiple URLs can point to the same mint.
4. **Trust is derived** - Every trust signal is computed from stored data with full breakdown.
5. **Self-hostable** - SQLite by default. No Redis or external queues required.
6. **Admin transparency** - Every admin action is audited. No hidden mutations.
## License
MIT
## Links
- [Cashu Protocol](https://cashu.space)
- [Cashu Documentation](https://docs.cashu.space)
- [NIP-87 Specification](https://github.com/nostr-protocol/nips/blob/master/87.md)
- [Cashu-TS Library](https://cashu-ts.dev)