toll-proxy
v0.1.1
Published
Reverse proxy that adds L402 Lightning paywalls to any HTTP service. YAML config, per-route pricing, ai.wot trust tiers.
Downloads
202
Maintainers
Readme
toll-proxy
Reverse proxy that adds L402 Lightning paywalls to any HTTP service. No code changes. YAML config. Per-route pricing. Trust discounts via ai.wot.
The Idea
You have an API. You want to charge for it. Instead of integrating payment logic into your app:
Client → toll-proxy (:8080) → your service (:3000)toll-proxy sits in front, handles L402 challenges, collects Lightning payments, and forwards authenticated requests. Your service never knows it's behind a paywall.
Install
npm install -g toll-proxyOr with Docker:
docker run -v ./config.yml:/app/toll-proxy.yml -p 8080:8080 toll-proxyQuick Start
# Paywall any local service at 10 sats per request
toll-proxy --upstream http://localhost:3000 --price 10
# With a real Lightning wallet
toll-proxy --upstream http://localhost:3000 --price 10 --nwc-url "$NWC_URL"
# With a YAML config
toll-proxy config.ymlConfig
listen: 8080
upstream: http://localhost:3000
nwc_url: ${NWC_URL}
secret: ${TOLL_SECRET}
default_price: 10 # sats
routes:
- path: /api/expensive
price: 100
- path: /api/data
price: 5
methods: [GET]
- path: /api/data
price: 25
methods: [POST, PUT]
- path: /api/premium/*
price: 50
- path: /api/health
price: 0 # free
- path: /api/partner
price: 20
min_trust: 30 # free if ai.wot trust ≥ 30
trust:
enabled: true
free_above: 50
discount_above: 25
discount_percent: 50
macaroon:
expiry: 3600
bind_ip: false
stats:
enabled: true
path: /__toll-statsEnvironment variables (${VAR} syntax) are interpolated in all string values.
How L402 Works
- Client requests
/api/expensive - toll-proxy returns
402 Payment Requiredwith:WWW-Authenticate: L402 macaroon="...", invoice="lnbc..."- JSON body with price, invoice, and macaroon
- Client pays the Lightning invoice
- Client retries with:
Authorization: L402 <macaroon>:<preimage> - toll-proxy verifies macaroon + preimage → forwards to upstream
GET /api/expensive
→ 402 { price: 100, invoice: "lnbc...", macaroon: "..." }
[client pays invoice, gets preimage]
GET /api/expensive
Authorization: L402 eyJ...:abc123...
→ 200 (forwarded to upstream)Trust Tiers
With ai-wot installed:
- Trust ≥ 50: Free access everywhere
- Trust ≥ 25: 50% discount
- Per-route thresholds:
min_trust: 30on any route
Agents send their Nostr pubkey via X-Nostr-Pubkey header. Scores are cached (5min TTL) to avoid relay spam.
# Install trust features
npm install ai-wotStats Dashboard
Visit /__toll-stats for a live dashboard showing:
- Request counts (total, forwarded, challenged, paid)
- Revenue in sats
- Per-route breakdown
- Uptime
JSON available via Accept: application/json header.
Optional basic auth: set stats.auth in config.
Programmatic API
const { createProxy, createConfig } = require('toll-proxy');
const config = createConfig({
upstream: 'http://localhost:3000',
secret: 'my-hmac-secret',
default_price: 10,
routes: [
{ path: '/free', price: 0 },
{ path: '/premium/*', price: 50 }
]
});
const proxy = createProxy(config);
proxy.listen(8080, () => console.log('Ready'));Macaroon Security
- HMAC-SHA256 signatures (tamper-proof)
- Caveats: expiry, endpoint, method, optional IP binding
- Preimage verification: proves the invoice was actually paid
- Set a persistent
secretin config (random secret won't survive restarts)
Interop
Works with the agent economy stack:
- lightning-toll — L402 for Express apps (code-level)
- lightning-agent — Client-side
tollFetch()auto-pays L402 - ai-wot — Trust scoring for free/discounted access
- agent-escrow — Marketplace for hiring agents
License
MIT
