Initial commit
This commit is contained in:
418
README.md
Normal file
418
README.md
Normal file
@@ -0,0 +1,418 @@
|
||||
# 🌿 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
|
||||
|
||||
Base URL: `/v1`
|
||||
|
||||
### 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/v1/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/v1/admin/system/metrics \
|
||||
-H "X-Admin-Api-Key: $ADMIN_API_KEY"
|
||||
|
||||
# Force trust recalculation
|
||||
curl -X POST http://localhost:3000/v1/admin/mints/{mint_id}/trust/recompute \
|
||||
-H "X-Admin-Api-Key: $ADMIN_API_KEY"
|
||||
|
||||
# View audit log
|
||||
curl http://localhost:3000/v1/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)
|
||||
Reference in New Issue
Block a user