@thecryptodonkey/toll-booth 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -78
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/toll-booth.js +2 -2
- package/dist/core/toll-booth.js.map +1 -1
- package/dist/demo.d.ts +2 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +216 -0
- package/dist/demo.js.map +1 -0
- package/llms.txt +5 -1
- package/package.json +24 -6
package/README.md
CHANGED
|
@@ -3,33 +3,117 @@
|
|
|
3
3
|
[](./LICENSE)
|
|
4
4
|
[](https://primal.net/p/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Any API becomes a Lightning toll booth in one line.**
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+

|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[Live demo](https://jokes.trotters.dev/api/joke) - pay 10 sats, get a joke. No account. No sign-up.
|
|
11
|
+
|
|
12
|
+
### Try it now
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @thecryptodonkey/toll-booth demo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Spins up a fully working L402-gated joke API on localhost. Mock Lightning backend, in-memory storage, zero configuration. Scan the QR code from your terminal when the free tier runs out.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Minimal example
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import express from 'express'
|
|
26
|
+
import { Booth } from '@thecryptodonkey/toll-booth'
|
|
27
|
+
import { phoenixdBackend } from '@thecryptodonkey/toll-booth/backends/phoenixd'
|
|
28
|
+
|
|
29
|
+
const app = express()
|
|
30
|
+
const booth = new Booth({
|
|
31
|
+
adapter: 'express',
|
|
32
|
+
backend: phoenixdBackend({ url: 'http://localhost:9740', password: process.env.PHOENIXD_PASSWORD! }),
|
|
33
|
+
pricing: { '/api': 10 }, // 10 sats per request
|
|
34
|
+
upstream: 'http://localhost:8080', // your existing API
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
app.get('/invoice-status/:paymentHash', booth.invoiceStatusHandler as express.RequestHandler)
|
|
38
|
+
app.post('/create-invoice', booth.createInvoiceHandler as express.RequestHandler)
|
|
39
|
+
app.use('/', booth.middleware as express.RequestHandler)
|
|
40
|
+
|
|
41
|
+
app.listen(3000)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The old way vs toll-booth
|
|
47
|
+
|
|
48
|
+
| | The old way | With toll-booth |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **Step 1** | Create a Stripe account | `npm install @thecryptodonkey/toll-booth` |
|
|
51
|
+
| **Step 2** | Verify your identity (KYC) | Set your pricing: `{ '/api': 10 }` |
|
|
52
|
+
| **Step 3** | Integrate billing SDK | `app.use(booth.middleware)` |
|
|
53
|
+
| **Step 4** | Build a sign-up page | Done. No sign-up page needed. |
|
|
54
|
+
| **Step 5** | Handle webhooks, refunds, chargebacks | Done. Payments are final. |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Five zeroes
|
|
59
|
+
|
|
60
|
+
Zero accounts. Zero API keys. Zero chargebacks. Zero KYC. Zero vendor lock-in.
|
|
61
|
+
|
|
62
|
+
Your API earns sats the moment it receives a request. Clients pay with any Lightning wallet, no relationship with you required. Payments settle instantly and are cryptographically final - no disputes, no reversals, no Stripe risk reviews.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Let AI agents pay for your API with Lightning
|
|
67
|
+
|
|
68
|
+
toll-booth is the **server side** of a two-part stack for machine-to-machine payments.
|
|
69
|
+
[l402-mcp](https://github.com/TheCryptoDonkey/l402-mcp) is the **client side** - an MCP server that gives AI agents the ability to discover, pay, and consume L402-gated APIs autonomously.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
AI Agent -> l402-mcp -> toll-booth -> Your API
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
An agent using Claude, GPT, or any MCP-capable model can call your API, receive a 402 payment challenge, pay the Lightning invoice from its wallet, and retry - all without human intervention. No OAuth dance, no API key rotation, no billing portal.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Live demo
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Get a free joke (1 free per day per IP)
|
|
83
|
+
curl https://jokes.trotters.dev/api/joke
|
|
84
|
+
|
|
85
|
+
# Free tier exhausted - request a Lightning invoice for 10 sats
|
|
86
|
+
curl -X POST https://jokes.trotters.dev/create-invoice
|
|
87
|
+
|
|
88
|
+
# Pay the invoice with any Lightning wallet, then authenticate
|
|
89
|
+
curl -H "Authorization: L402 <macaroon>:<preimage>" https://jokes.trotters.dev/api/joke
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
11
93
|
|
|
12
94
|
## Features
|
|
13
95
|
|
|
14
|
-
- **L402 protocol**
|
|
15
|
-
- **Multiple Lightning backends**
|
|
16
|
-
- **Alternative payment methods**
|
|
17
|
-
- **Cashu-only mode**
|
|
18
|
-
- **Credit system**
|
|
19
|
-
- **Free tier**
|
|
20
|
-
- **Self-service payment page**
|
|
21
|
-
- **SQLite persistence**
|
|
22
|
-
- **Framework-agnostic core**
|
|
96
|
+
- **L402 protocol** - industry-standard HTTP 402 payment flow with macaroon credentials
|
|
97
|
+
- **Multiple Lightning backends** - Phoenixd, LND, CLN, LNbits, Alby
|
|
98
|
+
- **Alternative payment methods** - Nostr Wallet Connect (NWC) and Cashu ecash tokens
|
|
99
|
+
- **Cashu-only mode** - no Lightning node required; ideal for serverless and edge deployments
|
|
100
|
+
- **Credit system** - pre-paid balance with volume discount tiers
|
|
101
|
+
- **Free tier** - configurable daily allowance per IP
|
|
102
|
+
- **Self-service payment page** - QR codes, tier selector, wallet adapter buttons
|
|
103
|
+
- **SQLite persistence** - WAL mode, automatic invoice expiry pruning
|
|
104
|
+
- **Framework-agnostic core** - use the `Booth` facade or wire handlers directly
|
|
105
|
+
|
|
106
|
+
---
|
|
23
107
|
|
|
24
108
|
## Quick start
|
|
25
109
|
|
|
26
|
-
|
|
110
|
+
```bash
|
|
27
111
|
npm install @thecryptodonkey/toll-booth
|
|
28
|
-
|
|
112
|
+
```
|
|
29
113
|
|
|
30
114
|
### Express
|
|
31
115
|
|
|
32
|
-
|
|
116
|
+
```typescript
|
|
33
117
|
import express from 'express'
|
|
34
118
|
import { Booth } from '@thecryptodonkey/toll-booth'
|
|
35
119
|
import { phoenixdBackend } from '@thecryptodonkey/toll-booth/backends/phoenixd'
|
|
@@ -53,11 +137,11 @@ app.post('/create-invoice', booth.createInvoiceHandler as express.RequestHandler
|
|
|
53
137
|
app.use('/', booth.middleware as express.RequestHandler)
|
|
54
138
|
|
|
55
139
|
app.listen(3000)
|
|
56
|
-
|
|
140
|
+
```
|
|
57
141
|
|
|
58
142
|
### Web Standard (Deno / Bun / Workers)
|
|
59
143
|
|
|
60
|
-
|
|
144
|
+
```typescript
|
|
61
145
|
import { Booth } from '@thecryptodonkey/toll-booth'
|
|
62
146
|
import { lndBackend } from '@thecryptodonkey/toll-booth/backends/lnd'
|
|
63
147
|
|
|
@@ -80,11 +164,11 @@ Deno.serve({ port: 3000 }, async (req: Request) => {
|
|
|
80
164
|
return booth.createInvoiceHandler(req)
|
|
81
165
|
return booth.middleware(req)
|
|
82
166
|
})
|
|
83
|
-
|
|
167
|
+
```
|
|
84
168
|
|
|
85
169
|
### Cashu-only (no Lightning node)
|
|
86
170
|
|
|
87
|
-
|
|
171
|
+
```typescript
|
|
88
172
|
import { Booth } from '@thecryptodonkey/toll-booth'
|
|
89
173
|
|
|
90
174
|
const booth = new Booth({
|
|
@@ -97,43 +181,21 @@ const booth = new Booth({
|
|
|
97
181
|
pricing: { '/api': 5 },
|
|
98
182
|
upstream: 'http://localhost:8080',
|
|
99
183
|
})
|
|
100
|
-
|
|
184
|
+
```
|
|
101
185
|
|
|
102
186
|
No Lightning node, no channels, no liquidity management. Ideal for serverless and edge deployments.
|
|
103
187
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
The \`Booth\` constructor accepts:
|
|
107
|
-
|
|
108
|
-
| Option | Type | Description |
|
|
109
|
-
|--------|------|-------------|
|
|
110
|
-
| \`adapter\` | \`'express' \| 'web-standard'\` | Framework integration to use |
|
|
111
|
-
| \`backend\` | \`LightningBackend\` | Lightning node (optional if using Cashu-only) |
|
|
112
|
-
| \`pricing\` | \`Record<string, number>\` | Route pattern → cost in sats |
|
|
113
|
-
| \`upstream\` | \`string\` | URL to proxy authorised requests to |
|
|
114
|
-
| \`rootKey\` | \`string\` | Macaroon signing key (64 hex chars). Random if omitted |
|
|
115
|
-
| \`dbPath\` | \`string\` | SQLite path. Default: \`./toll-booth.db\` |
|
|
116
|
-
| \`storage\` | \`StorageBackend\` | Custom storage (alternative to \`dbPath\`) |
|
|
117
|
-
| \`freeTier\` | \`{ requestsPerDay: number }\` | Daily free allowance per IP |
|
|
118
|
-
| \`strictPricing\` | \`boolean\` | Challenge unpriced routes instead of passing through |
|
|
119
|
-
| \`creditTiers\` | \`CreditTier[]\` | Volume discount tiers |
|
|
120
|
-
| \`trustProxy\` | \`boolean\` | Trust \`X-Forwarded-For\` / \`X-Real-IP\` |
|
|
121
|
-
| \`getClientIp\` | \`(req) => string\` | Custom IP resolver for non-standard runtimes |
|
|
122
|
-
| \`responseHeaders\` | \`Record<string, string>\` | Extra headers on every response |
|
|
123
|
-
| \`nwcPayInvoice\` | \`(uri, bolt11) => Promise<string>\` | NWC payment callback |
|
|
124
|
-
| \`redeemCashu\` | \`(token, hash) => Promise<number>\` | Cashu redemption callback |
|
|
125
|
-
| \`invoiceMaxAgeMs\` | \`number\` | Invoice pruning age. Default: 24h. \`0\` to disable |
|
|
126
|
-
| \`upstreamTimeout\` | \`number\` | Proxy timeout in ms. Default: 30s |
|
|
188
|
+
---
|
|
127
189
|
|
|
128
190
|
## Lightning backends
|
|
129
191
|
|
|
130
|
-
|
|
192
|
+
```typescript
|
|
131
193
|
import { phoenixdBackend } from '@thecryptodonkey/toll-booth/backends/phoenixd'
|
|
132
194
|
import { lndBackend } from '@thecryptodonkey/toll-booth/backends/lnd'
|
|
133
195
|
import { clnBackend } from '@thecryptodonkey/toll-booth/backends/cln'
|
|
134
196
|
import { lnbitsBackend } from '@thecryptodonkey/toll-booth/backends/lnbits'
|
|
135
197
|
import { albyBackend } from '@thecryptodonkey/toll-booth/backends/alby'
|
|
136
|
-
|
|
198
|
+
```
|
|
137
199
|
|
|
138
200
|
Each backend implements the `LightningBackend` interface (`createInvoice` + `checkInvoice`).
|
|
139
201
|
|
|
@@ -142,21 +204,103 @@ Each backend implements the `LightningBackend` interface (`createInvoice` + `che
|
|
|
142
204
|
| Phoenixd | Stable | Simplest self-hosted option |
|
|
143
205
|
| LND | Stable | Industry standard |
|
|
144
206
|
| CLN | Stable | Core Lightning REST API |
|
|
145
|
-
| LNbits | Stable | Any LNbits instance
|
|
207
|
+
| LNbits | Stable | Any LNbits instance - self-hosted or hosted |
|
|
146
208
|
| Alby (NWC) | Experimental | JSON relay transport is unauthenticated; only enable with `allowInsecureRelay: true` for local testing or a fully trusted relay |
|
|
147
209
|
|
|
148
|
-
|
|
210
|
+
---
|
|
149
211
|
|
|
150
|
-
|
|
212
|
+
## Why not Aperture?
|
|
151
213
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
214
|
+
[Aperture](https://github.com/lightninglabs/aperture) is Lightning Labs' production L402 reverse proxy. It's battle-tested and feature-rich. Use it if you can.
|
|
215
|
+
|
|
216
|
+
| | Aperture | toll-booth |
|
|
217
|
+
|---|---|---|
|
|
218
|
+
| **Language** | Go binary | TypeScript middleware |
|
|
219
|
+
| **Deployment** | Standalone reverse proxy | Embeds in your app, or runs as a gateway in front of any HTTP service |
|
|
220
|
+
| **Lightning node** | Requires LND | Phoenixd, LND, CLN, LNbits, or none (Cashu-only) |
|
|
221
|
+
| **Serverless** | No - long-running process | Yes - Web Standard adapter runs on Cloudflare Workers, Deno, Bun |
|
|
222
|
+
| **Configuration** | YAML file | Programmatic (code) |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Why not x402?
|
|
227
|
+
|
|
228
|
+
[x402](https://x402.org) is Coinbase's HTTP 402 payment protocol for on-chain stablecoins. It validates the same idea - machines paying for APIs - but makes different trade-offs.
|
|
229
|
+
|
|
230
|
+
| | x402 | toll-booth |
|
|
231
|
+
|---|---|---|
|
|
232
|
+
| **Settlement** | On-chain (Base, Ethereum) | Lightning Network - sub-second, final |
|
|
233
|
+
| **Settlement time** | Block confirmations (seconds to minutes) | Milliseconds |
|
|
234
|
+
| **Transaction fees** | Gas fees (variable) | Routing fees (fractions of a sat) |
|
|
235
|
+
| **Currency** | USDC on Base | Bitcoin (sats), with stablecoin compatibility via USDT-over-LN bridges |
|
|
236
|
+
| **Infrastructure** | Requires Coinbase Commerce or on-chain wallet | Any of 5 Lightning backends, Cashu ecash, or NWC - self-hosted or hosted |
|
|
237
|
+
| **Vendor lock-in** | Coinbase ecosystem | None - open protocol, open source, any Lightning wallet |
|
|
238
|
+
| **Serverless** | Yes | Yes - Web Standard adapter for Workers, Deno, Bun |
|
|
239
|
+
| **Offline/edge** | No - requires chain access | Yes - Cashu-only mode needs no node at all |
|
|
240
|
+
|
|
241
|
+
x402 is doing valuable work normalising HTTP 402 as a payment primitive. If your clients already hold USDC on Base, it's a reasonable choice. If you want sub-second settlement, self-sovereign infrastructure, and a protocol that works with any Lightning wallet on earth, toll-booth is the answer.
|
|
242
|
+
|
|
243
|
+
**Stablecoin compatibility:** toll-booth doesn't care how an invoice gets paid. As USDT-over-Lightning bridges (UTEXO and others) go live, your gated APIs automatically accept stablecoins with zero code changes. The best of both worlds: stablecoin UX on Bitcoin rails.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Using toll-booth with any API
|
|
248
|
+
|
|
249
|
+
toll-booth works as a **reverse proxy gateway**, so the upstream API can be written in any language - C#, Go, Python, Ruby, Java, or anything else that speaks HTTP. The upstream service doesn't need to know about L402 or Lightning; it just receives normal requests.
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
Client ---> toll-booth (Node.js) ---> Your API (any language)
|
|
253
|
+
| |
|
|
254
|
+
L402 payment gating Plain HTTP requests
|
|
255
|
+
Macaroon verification X-Credit-Balance header added
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Point `upstream` at your existing service:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const booth = new Booth({
|
|
262
|
+
adapter: 'express',
|
|
263
|
+
backend: phoenixdBackend({ url: '...', password: '...' }),
|
|
264
|
+
pricing: { '/api/search': 5, '/api/generate': 20 },
|
|
265
|
+
upstream: 'http://my-dotnet-api:5000', // ASP.NET, FastAPI, Gin, Rails...
|
|
266
|
+
})
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Deploy toll-booth as a sidecar (Docker Compose, Kubernetes) or as a standalone gateway in front of multiple services. See [`examples/valhalla-proxy/`](examples/valhalla-proxy/) for a complete Docker Compose reference - the Valhalla routing engine it gates is a C++ service.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Production checklist
|
|
274
|
+
|
|
275
|
+
- Set a persistent `rootKey` (64 hex chars / 32 bytes), otherwise tokens are invalidated on restart.
|
|
276
|
+
- Use a persistent `dbPath` (default: `./toll-booth.db`).
|
|
277
|
+
- Enable `strictPricing: true` to prevent unpriced routes from bypassing billing.
|
|
278
|
+
- Ensure your `pricing` keys match the paths the middleware actually sees (after mounting).
|
|
279
|
+
- Set `trustProxy: true` when behind a reverse proxy, or provide a `getClientIp` callback for per-client free-tier isolation.
|
|
280
|
+
- If you implement `redeemCashu`, make it idempotent for the same `paymentHash` - crash recovery depends on it.
|
|
281
|
+
- Rate-limit `/create-invoice` at your reverse proxy - each call creates a real Lightning invoice.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Example deployments
|
|
286
|
+
|
|
287
|
+
### sats-for-laughs - build your own paid API
|
|
288
|
+
|
|
289
|
+
[`examples/sats-for-laughs/`](examples/sats-for-laughs/) is the fastest path from "I have an API" to "my API earns sats". It's the same code that runs the [live demo](https://jokes.trotters.dev/api/joke). Clone it, change three env vars, deploy.
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
cd examples/sats-for-laughs
|
|
293
|
+
cp .env.example .env # add your Phoenixd credentials
|
|
294
|
+
docker compose up -d # or: MOCK=true npm start
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Includes mock mode for local development (auto-settles invoices, no Lightning node needed), Docker Compose with Phoenixd, and a pre-generated pool of 100+ jokes across six topics.
|
|
298
|
+
|
|
299
|
+
### valhalla-proxy - production reference
|
|
300
|
+
|
|
301
|
+
[`examples/valhalla-proxy/`](examples/valhalla-proxy/) gates the [Valhalla](https://github.com/valhalla/valhalla) routing engine (a C++ service) behind Lightning payments. Full Docker Compose setup demonstrating toll-booth as a sidecar proxy in front of non-JavaScript infrastructure.
|
|
302
|
+
|
|
303
|
+
---
|
|
160
304
|
|
|
161
305
|
## Payment flow
|
|
162
306
|
|
|
@@ -185,37 +329,35 @@ sequenceDiagram
|
|
|
185
329
|
```
|
|
186
330
|
|
|
187
331
|
1. Client requests a priced endpoint without credentials
|
|
188
|
-
2. Free tier checked
|
|
189
|
-
3. If exhausted
|
|
332
|
+
2. Free tier checked - if allowance remains, request passes through
|
|
333
|
+
3. If exhausted - **402** response with BOLT-11 invoice + macaroon
|
|
190
334
|
4. Client pays via Lightning, NWC, or Cashu
|
|
191
|
-
5. Client sends
|
|
335
|
+
5. Client sends `Authorization: L402 <macaroon>:<preimage>`
|
|
192
336
|
6. Macaroon verified, credit deducted, request proxied upstream
|
|
193
337
|
|
|
194
|
-
|
|
338
|
+
---
|
|
195
339
|
|
|
196
|
-
|
|
340
|
+
## Configuration
|
|
197
341
|
|
|
198
|
-
|
|
199
|
-
|---|---|---|
|
|
200
|
-
| **Language** | Go binary | TypeScript middleware |
|
|
201
|
-
| **Deployment** | Standalone reverse proxy | Embeds in your existing app |
|
|
202
|
-
| **Lightning node** | Requires LND | Phoenixd, LND, CLN, LNbits, or none (Cashu-only) |
|
|
203
|
-
| **Serverless** | No — long-running process | Yes — Web Standard adapter runs on Cloudflare Workers, Deno, Bun |
|
|
204
|
-
| **Configuration** | YAML file | Programmatic (code) |
|
|
342
|
+
The five most common options:
|
|
205
343
|
|
|
206
|
-
|
|
344
|
+
| Option | Type | Description |
|
|
345
|
+
|--------|------|-------------|
|
|
346
|
+
| `adapter` | `'express' \| 'web-standard'` | Framework integration to use |
|
|
347
|
+
| `backend` | `LightningBackend` | Lightning node (optional if using Cashu-only) |
|
|
348
|
+
| `pricing` | `Record<string, number>` | Route pattern to cost in sats |
|
|
349
|
+
| `upstream` | `string` | URL to proxy authorised requests to |
|
|
350
|
+
| `freeTier` | `{ requestsPerDay: number }` | Daily free allowance per IP |
|
|
207
351
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
- If you implement `redeemCashu`, make it idempotent for the same `paymentHash` — crash recovery depends on it.
|
|
214
|
-
- Rate-limit `/create-invoice` at your reverse proxy — each call creates a real Lightning invoice.
|
|
352
|
+
See [docs/configuration.md](docs/configuration.md) for the full reference including `rootKey`, `creditTiers`, `trustProxy`, `nwcPayInvoice`, `redeemCashu`, and all other options.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Vision
|
|
215
357
|
|
|
216
|
-
|
|
358
|
+
**[Why L402?](docs/vision.md)** - the case for permissionless, machine-to-machine payments on the web.
|
|
217
359
|
|
|
218
|
-
|
|
360
|
+
---
|
|
219
361
|
|
|
220
362
|
## Support
|
|
221
363
|
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// src/cli.ts
|
|
3
|
+
const command = process.argv[2];
|
|
4
|
+
if (command === 'demo') {
|
|
5
|
+
const { startDemo } = await import('./demo.js');
|
|
6
|
+
await startDemo();
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
console.log('Usage: toll-booth <command>');
|
|
10
|
+
console.log('');
|
|
11
|
+
console.log('Commands:');
|
|
12
|
+
console.log(' demo Start a self-contained demo server with mock Lightning');
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log('Example:');
|
|
15
|
+
console.log(' npx @thecryptodonkey/toll-booth demo');
|
|
16
|
+
process.exit(command === undefined || command === '--help' || command === '-h' ? 0 : 1);
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,aAAa;AAEb,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAE/B,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;IAC/C,MAAM,SAAS,EAAE,CAAA;AACnB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAA;IAC/E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACvB,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAA;IACrD,OAAO,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACzF,CAAC"}
|
package/dist/core/toll-booth.js
CHANGED
|
@@ -93,8 +93,8 @@ export function createTollBooth(config) {
|
|
|
93
93
|
clientIp: req.ip,
|
|
94
94
|
});
|
|
95
95
|
const headers = bolt11
|
|
96
|
-
? { 'WWW-Authenticate': `L402 macaroon="${macaroon}", invoice="${bolt11}"
|
|
97
|
-
: { 'WWW-Authenticate': `L402 macaroon="${macaroon}"
|
|
96
|
+
? { 'WWW-Authenticate': `L402 macaroon="${macaroon}", invoice="${bolt11}"`, 'X-Powered-By': 'toll-booth' }
|
|
97
|
+
: { 'WWW-Authenticate': `L402 macaroon="${macaroon}"`, 'X-Powered-By': 'toll-booth' };
|
|
98
98
|
const body = {
|
|
99
99
|
error: 'Payment required',
|
|
100
100
|
macaroon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toll-booth.js","sourceRoot":"","sources":["../../src/core/toll-booth.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"toll-booth.js","sourceRoot":"","sources":["../../src/core/toll-booth.ts"],"names":[],"mappings":"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"}
|
package/dist/demo.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAyGA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAuI/C"}
|
package/dist/demo.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// src/demo.ts
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { randomBytes, createHash } from 'node:crypto';
|
|
4
|
+
import QRCode from 'qrcode';
|
|
5
|
+
import { memoryStorage } from './storage/memory.js';
|
|
6
|
+
import { createTollBooth } from './core/toll-booth.js';
|
|
7
|
+
import { createWebStandardMiddleware, createWebStandardCreateInvoiceHandler, createWebStandardInvoiceStatusHandler, } from './adapters/web-standard.js';
|
|
8
|
+
// -- Colours ------------------------------------------------------------------
|
|
9
|
+
const GREEN = '\x1b[32m';
|
|
10
|
+
const CYAN = '\x1b[36m';
|
|
11
|
+
const YELLOW = '\x1b[33m';
|
|
12
|
+
const RED = '\x1b[31m';
|
|
13
|
+
const DIM = '\x1b[2m';
|
|
14
|
+
const BOLD = '\x1b[1m';
|
|
15
|
+
const RESET = '\x1b[0m';
|
|
16
|
+
// -- Mock Lightning backend ---------------------------------------------------
|
|
17
|
+
function createMockBackend(storage) {
|
|
18
|
+
return {
|
|
19
|
+
async createInvoice(amountSats, memo) {
|
|
20
|
+
const preimage = randomBytes(32);
|
|
21
|
+
const paymentHash = createHash('sha256').update(preimage).digest('hex');
|
|
22
|
+
const bolt11 = `lnbc${amountSats}n1demo${randomBytes(20).toString('hex')}`;
|
|
23
|
+
console.log(` ${GREEN}[payment]${RESET} invoice created: ${amountSats} sats ${DIM}(${memo})${RESET}`);
|
|
24
|
+
// Auto-settle after ~1s to simulate instant payment
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
storage.settleWithCredit(paymentHash, amountSats, preimage.toString('hex'));
|
|
27
|
+
console.log(` ${GREEN}[payment]${RESET} invoice settled: ${paymentHash.slice(0, 16)}...`);
|
|
28
|
+
}, 1_000);
|
|
29
|
+
return { bolt11, paymentHash };
|
|
30
|
+
},
|
|
31
|
+
async checkInvoice(paymentHash) {
|
|
32
|
+
const settled = storage.isSettled(paymentHash);
|
|
33
|
+
const preimage = storage.getSettlementSecret(paymentHash);
|
|
34
|
+
return { paid: settled, preimage };
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// -- Joke API -----------------------------------------------------------------
|
|
39
|
+
const jokes = [
|
|
40
|
+
{ setup: 'Why do programmers prefer dark mode?', punchline: 'Because light attracts bugs.' },
|
|
41
|
+
{ setup: 'Why was the JavaScript developer sad?', punchline: "Because he didn't Node how to Express himself." },
|
|
42
|
+
{ setup: "What is a Lightning node's favourite dance?", punchline: 'The channel shuffle.' },
|
|
43
|
+
{ setup: 'How do you comfort a JavaScript bug?', punchline: 'You console it.' },
|
|
44
|
+
{ setup: 'Why did the developer go broke?', punchline: 'Because he used up all his cache.' },
|
|
45
|
+
{ setup: 'Why do Bitcoin maximalists make terrible comedians?', punchline: 'They only accept one punchline.' },
|
|
46
|
+
{ setup: 'What did the sat say to the dollar?', punchline: "You're not my type; I only do peer-to-peer." },
|
|
47
|
+
{ setup: 'How many Lightning devs does it take to change a light bulb?', punchline: 'None; they just open a channel to one that works.' },
|
|
48
|
+
];
|
|
49
|
+
// -- Node http <-> Web Standard bridge ----------------------------------------
|
|
50
|
+
function toWebRequest(nodeReq, body) {
|
|
51
|
+
const host = nodeReq.headers.host ?? 'localhost';
|
|
52
|
+
const url = new URL(nodeReq.url ?? '/', `http://${host}`);
|
|
53
|
+
const headers = new Headers();
|
|
54
|
+
for (const [key, value] of Object.entries(nodeReq.headers)) {
|
|
55
|
+
if (value !== undefined) {
|
|
56
|
+
headers.set(key, Array.isArray(value) ? value.join(', ') : value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const init = { method: nodeReq.method, headers };
|
|
60
|
+
if (nodeReq.method !== 'GET' && nodeReq.method !== 'HEAD' && body.length > 0) {
|
|
61
|
+
init.body = body;
|
|
62
|
+
}
|
|
63
|
+
return new Request(url, init);
|
|
64
|
+
}
|
|
65
|
+
async function sendWebResponse(webRes, nodeRes) {
|
|
66
|
+
nodeRes.statusCode = webRes.status;
|
|
67
|
+
for (const [key, value] of webRes.headers.entries()) {
|
|
68
|
+
nodeRes.setHeader(key, value);
|
|
69
|
+
}
|
|
70
|
+
if (webRes.body) {
|
|
71
|
+
const reader = webRes.body.getReader();
|
|
72
|
+
try {
|
|
73
|
+
while (true) {
|
|
74
|
+
const { done, value } = await reader.read();
|
|
75
|
+
if (done)
|
|
76
|
+
break;
|
|
77
|
+
nodeRes.write(value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
reader.releaseLock();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
nodeRes.end();
|
|
85
|
+
}
|
|
86
|
+
// -- Main ---------------------------------------------------------------------
|
|
87
|
+
export async function startDemo() {
|
|
88
|
+
const port = parseInt(process.env.PORT ?? '3000', 10);
|
|
89
|
+
const storage = memoryStorage();
|
|
90
|
+
const backend = createMockBackend(storage);
|
|
91
|
+
const rootKey = randomBytes(32).toString('hex');
|
|
92
|
+
// Tiny upstream joke API on an ephemeral port
|
|
93
|
+
const upstreamPort = await new Promise((resolve) => {
|
|
94
|
+
const upstream = createServer((req, res) => {
|
|
95
|
+
if (req.url?.startsWith('/api/joke')) {
|
|
96
|
+
const joke = jokes[Math.floor(Math.random() * jokes.length)];
|
|
97
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
98
|
+
res.end(JSON.stringify(joke));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
102
|
+
res.end(JSON.stringify({ error: 'Not found' }));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
upstream.listen(0, () => {
|
|
106
|
+
const addr = upstream.address();
|
|
107
|
+
resolve(typeof addr === 'object' && addr ? addr.port : 0);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
// Track the current Node request's IP for the getClientIp callback
|
|
111
|
+
let currentClientIp = '127.0.0.1';
|
|
112
|
+
const upstreamUrl = `http://localhost:${upstreamPort}`;
|
|
113
|
+
const engine = createTollBooth({
|
|
114
|
+
backend,
|
|
115
|
+
storage,
|
|
116
|
+
rootKey,
|
|
117
|
+
upstream: upstreamUrl,
|
|
118
|
+
pricing: { '/api/joke': 10 },
|
|
119
|
+
defaultInvoiceAmount: 10,
|
|
120
|
+
freeTier: { requestsPerDay: 3 },
|
|
121
|
+
onRequest: (event) => {
|
|
122
|
+
if (event.authenticated) {
|
|
123
|
+
console.log(` ${CYAN}[L402]${RESET} ${event.endpoint} ${DIM}(-${event.satsDeducted} sats, ${event.remainingBalance} remaining)${RESET}`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.log(` ${YELLOW}[free]${RESET} ${event.endpoint} ${DIM}(${event.remainingBalance} free requests left today)${RESET}`);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
onChallenge: (event) => {
|
|
130
|
+
console.log(` ${RED}[402]${RESET} ${event.endpoint} ${DIM}(${event.amountSats} sats required)${RESET}`);
|
|
131
|
+
},
|
|
132
|
+
onPayment: (event) => {
|
|
133
|
+
console.log(` ${GREEN}[paid]${RESET} credited ${event.amountSats} sats`);
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const middleware = createWebStandardMiddleware({
|
|
137
|
+
engine,
|
|
138
|
+
upstream: upstreamUrl,
|
|
139
|
+
getClientIp: () => currentClientIp,
|
|
140
|
+
});
|
|
141
|
+
const createInvoiceHandler = createWebStandardCreateInvoiceHandler({
|
|
142
|
+
backend,
|
|
143
|
+
storage,
|
|
144
|
+
rootKey,
|
|
145
|
+
tiers: [],
|
|
146
|
+
defaultAmount: 10,
|
|
147
|
+
});
|
|
148
|
+
const invoiceStatusHandler = createWebStandardInvoiceStatusHandler({
|
|
149
|
+
backend,
|
|
150
|
+
storage,
|
|
151
|
+
});
|
|
152
|
+
// Gateway server
|
|
153
|
+
const server = createServer((nodeReq, nodeRes) => {
|
|
154
|
+
const chunks = [];
|
|
155
|
+
nodeReq.on('data', (chunk) => chunks.push(chunk));
|
|
156
|
+
nodeReq.on('end', () => {
|
|
157
|
+
const body = Buffer.concat(chunks);
|
|
158
|
+
const webReq = toWebRequest(nodeReq, body);
|
|
159
|
+
currentClientIp = nodeReq.socket.remoteAddress ?? '127.0.0.1';
|
|
160
|
+
const url = new URL(webReq.url);
|
|
161
|
+
void (async () => {
|
|
162
|
+
try {
|
|
163
|
+
let response;
|
|
164
|
+
if (url.pathname === '/create-invoice' && nodeReq.method === 'POST') {
|
|
165
|
+
response = await createInvoiceHandler(webReq);
|
|
166
|
+
}
|
|
167
|
+
else if (url.pathname.startsWith('/invoice-status/') && nodeReq.method === 'GET') {
|
|
168
|
+
response = await invoiceStatusHandler(webReq);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
response = await middleware(webReq);
|
|
172
|
+
// Print QR code to terminal on 402 so devs can scan with a wallet
|
|
173
|
+
if (response.status === 402) {
|
|
174
|
+
const cloned = response.clone();
|
|
175
|
+
const body = await cloned.json();
|
|
176
|
+
if (body.invoice) {
|
|
177
|
+
const qr = await QRCode.toString(body.invoice.toUpperCase(), { type: 'terminal', small: true });
|
|
178
|
+
console.log('');
|
|
179
|
+
console.log(` ${BOLD}Scan to pay:${RESET}`);
|
|
180
|
+
console.log(qr);
|
|
181
|
+
console.log(` ${DIM}Or open: http://localhost:${port}${body.payment_url}${RESET}`);
|
|
182
|
+
console.log('');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
await sendWebResponse(response, nodeRes);
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
console.error(' [error]', err);
|
|
190
|
+
nodeRes.statusCode = 500;
|
|
191
|
+
nodeRes.end('Internal server error');
|
|
192
|
+
}
|
|
193
|
+
})();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
server.listen(port, () => {
|
|
197
|
+
console.log('');
|
|
198
|
+
console.log(` ${BOLD}⚡ toll-booth demo${RESET}`);
|
|
199
|
+
console.log(` ${'─'.repeat(50)}`);
|
|
200
|
+
console.log('');
|
|
201
|
+
console.log(` ${DIM}Server${RESET} http://localhost:${port}`);
|
|
202
|
+
console.log(` ${DIM}Backend${RESET} Mock Lightning (auto-settles in ~1s)`);
|
|
203
|
+
console.log(` ${DIM}Storage${RESET} In-memory (ephemeral)`);
|
|
204
|
+
console.log('');
|
|
205
|
+
console.log(` ${BOLD}Pricing${RESET}`);
|
|
206
|
+
console.log(` ${DIM}Route${RESET} ${DIM}Cost${RESET} ${DIM}Free tier${RESET}`);
|
|
207
|
+
console.log(` /api/joke 10 sats 3 reqs/day`);
|
|
208
|
+
console.log('');
|
|
209
|
+
console.log(` ${BOLD}Try it:${RESET}`);
|
|
210
|
+
console.log(` ${DIM}$${RESET} curl http://localhost:${port}/api/joke`);
|
|
211
|
+
console.log('');
|
|
212
|
+
console.log(` ${GREEN}Ready.${RESET} Press Ctrl+C to stop.`);
|
|
213
|
+
console.log('');
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# toll-booth
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> toll-booth lets AI agents discover, pay for, and consume any HTTP API using Lightning, Cashu, or NWC - no accounts, no API keys, no human in the loop. It's L402 payment middleware that embeds in your Node.js app as middleware, supporting Express 5, Deno, Bun, and Cloudflare Workers.
|
|
4
4
|
|
|
5
5
|
toll-booth embeds in your existing Node.js application as middleware (not a separate proxy). It supports Express 5, Deno, Bun, and Cloudflare Workers. Five Lightning backends are supported (Phoenixd, LND, Core Lightning, LNbits, Alby), or you can run in Cashu-only mode with no Lightning node at all — ideal for serverless and edge deployments.
|
|
6
6
|
|
|
7
7
|
The closest alternative is Aperture (Lightning Labs), a Go reverse proxy that requires LND. toll-booth is TypeScript middleware that works with any Lightning backend, runs serverless, and supports Cashu ecash payments.
|
|
8
8
|
|
|
9
|
+
Compared to x402 (Coinbase's on-chain stablecoin payment protocol), toll-booth settles in milliseconds over Lightning instead of waiting for block confirmations, charges fractions-of-a-sat routing fees instead of gas, and works with any Lightning wallet - no Coinbase dependency. As USDT-over-Lightning bridges go live, toll-booth APIs automatically accept stablecoins with zero code changes.
|
|
10
|
+
|
|
11
|
+
Try it instantly: `npx @thecryptodonkey/toll-booth demo`
|
|
12
|
+
|
|
9
13
|
## Getting Started
|
|
10
14
|
|
|
11
15
|
```bash
|
package/package.json
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thecryptodonkey/toll-booth",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Any API becomes a Lightning toll booth in one line. L402 middleware for Express, Deno, Bun, and Workers.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"l402",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
8
|
+
"l402",
|
|
9
|
+
"lightning",
|
|
10
|
+
"paywall",
|
|
11
|
+
"micropayments",
|
|
12
|
+
"middleware",
|
|
13
|
+
"cashu",
|
|
14
|
+
"ecash",
|
|
15
|
+
"nostr",
|
|
16
|
+
"nwc",
|
|
17
|
+
"bitcoin",
|
|
18
|
+
"express",
|
|
19
|
+
"deno",
|
|
20
|
+
"bun",
|
|
21
|
+
"cloudflare-workers",
|
|
22
|
+
"serverless",
|
|
23
|
+
"macaroon",
|
|
24
|
+
"http-402",
|
|
25
|
+
"api-monetisation",
|
|
26
|
+
"payment-gateway"
|
|
12
27
|
],
|
|
13
28
|
"repository": {
|
|
14
29
|
"type": "git",
|
|
15
30
|
"url": "git+https://github.com/TheCryptoDonkey/toll-booth.git"
|
|
16
31
|
},
|
|
17
32
|
"homepage": "https://github.com/TheCryptoDonkey/toll-booth#readme",
|
|
33
|
+
"bin": {
|
|
34
|
+
"toll-booth": "dist/cli.js"
|
|
35
|
+
},
|
|
18
36
|
"exports": {
|
|
19
37
|
".": {
|
|
20
38
|
"import": "./dist/index.js",
|