@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 CHANGED
@@ -3,33 +3,117 @@
3
3
  [![MIT licence](https://img.shields.io/badge/licence-MIT-blue.svg)](./LICENSE)
4
4
  [![Nostr](https://img.shields.io/badge/Nostr-Zap%20me-purple)](https://primal.net/p/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)
5
5
 
6
- L402 Lightning payment middleware for Node.js. Gate any HTTP API behind a paywall with a single function call.
6
+ **Any API becomes a Lightning toll booth in one line.**
7
7
 
8
- Supports **Express 5**, **Deno**, **Bun**, and **Cloudflare Workers** via the Web Standard adapter.
8
+ ![toll-booth demo](demo/toll-booth-demo.gif)
9
9
 
10
- **[Why L402?](docs/vision.md)** the case for permissionless, machine-to-machine payments on the web.
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** industry-standard HTTP 402 payment flow with macaroon credentials
15
- - **Multiple Lightning backends** Phoenixd, LND, CLN, LNbits, Alby
16
- - **Alternative payment methods** Nostr Wallet Connect (NWC) and Cashu ecash tokens
17
- - **Cashu-only mode** no Lightning node required
18
- - **Credit system** pre-paid balance with volume discount tiers
19
- - **Free tier** configurable daily allowance per IP
20
- - **Self-service payment page** QR codes, tier selector, wallet adapter buttons
21
- - **SQLite persistence** WAL mode, automatic invoice expiry pruning
22
- - **Framework-agnostic core** use the \`Booth\` facade or wire handlers directly
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
- \`\`\`bash
110
+ ```bash
27
111
  npm install @thecryptodonkey/toll-booth
28
- \`\`\`
112
+ ```
29
113
 
30
114
  ### Express
31
115
 
32
- \`\`\`typescript
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
- \`\`\`typescript
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
- \`\`\`typescript
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
- ## Configuration
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
- \`\`\`typescript
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 self-hosted or hosted |
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
- ## Subpath exports
210
+ ---
149
211
 
150
- Tree-shakeable imports for bundlers:
212
+ ## Why not Aperture?
151
213
 
152
- \`\`\`typescript
153
- import { Booth } from '@thecryptodonkey/toll-booth'
154
- import { phoenixdBackend } from '@thecryptodonkey/toll-booth/backends/phoenixd'
155
- import { sqliteStorage } from '@thecryptodonkey/toll-booth/storage/sqlite'
156
- import { memoryStorage } from '@thecryptodonkey/toll-booth/storage/memory'
157
- import { createExpressMiddleware } from '@thecryptodonkey/toll-booth/adapters/express'
158
- import { createWebStandardMiddleware } from '@thecryptodonkey/toll-booth/adapters/web-standard'
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 if allowance remains, request passes through
189
- 3. If exhausted **402** response with BOLT-11 invoice + macaroon
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 \`Authorization: L402 <macaroon>:<preimage>\`
335
+ 5. Client sends `Authorization: L402 <macaroon>:<preimage>`
192
336
  6. Macaroon verified, credit deducted, request proxied upstream
193
337
 
194
- ## Why not Aperture?
338
+ ---
195
339
 
196
- [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.
340
+ ## Configuration
197
341
 
198
- | | Aperture | toll-booth |
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
- ## Production checklist
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
- - Set a persistent `rootKey` (64 hex chars / 32 bytes), otherwise tokens are invalidated on restart.
209
- - Use a persistent `dbPath` (default: `./toll-booth.db`).
210
- - Enable `strictPricing: true` to prevent unpriced routes from bypassing billing.
211
- - Ensure your `pricing` keys match the paths the middleware actually sees (after mounting).
212
- - Set `trustProxy: true` when behind a reverse proxy, or provide a `getClientIp` callback for per-client free-tier isolation.
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
- ## Example deployment
358
+ **[Why L402?](docs/vision.md)** - the case for permissionless, machine-to-machine payments on the web.
217
359
 
218
- See [`examples/valhalla-proxy/`](examples/valhalla-proxy/) for a complete Docker Compose setup gating a [Valhalla](https://github.com/valhalla/valhalla) routing engine behind Lightning payments.
360
+ ---
219
361
 
220
362
  ## Support
221
363
 
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -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
@@ -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"}
@@ -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":"AAAA,yBAAyB;AACzB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAU1C,MAAM,UAAU,eAAe,CAAC,MAA2B;IACzD,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB,IAAI,IAAI,CAAA;IACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAEtF,OAAO;QACL,QAAQ;QACR,QAAQ;QAER,KAAK,CAAC,MAAM,CAAC,GAAqB;YAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAA;YACrB,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAEvC,gEAAgE;YAChE,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;gBACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAA;YAClD,CAAC;YAED,+EAA+E;YAC/E,MAAM,IAAI,GAAG,UAAU,IAAI,aAAa,CAAA;YAExC,sCAAsC;YACtC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;YAC/E,IAAI,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAA;gBAC9F,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;oBACtB,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;wBAC1B,MAAM,CAAC,SAAS,EAAE,CAAC;4BACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;4BACnC,WAAW,EAAE,MAAM,CAAC,WAAY;4BAChC,UAAU,EAAE,MAAM,CAAC,cAAc;yBAClC,CAAC,CAAA;oBACJ,CAAC;oBACD,MAAM,CAAC,SAAS,EAAE,CAAC;wBACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,QAAQ,EAAE,IAAI;wBACd,YAAY,EAAE,IAAI;wBAClB,gBAAgB,EAAE,MAAM,CAAC,SAAS;wBAClC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;wBAC7B,aAAa,EAAE,IAAI;wBACnB,QAAQ,EAAE,GAAG,CAAC,EAAE;qBACjB,CAAC,CAAA;oBACF,OAAO;wBACL,MAAM,EAAE,OAAO;wBACf,QAAQ;wBACR,OAAO,EAAE,EAAE,kBAAkB,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;wBACzD,aAAa,EAAE,MAAM,CAAC,SAAS;qBAChC,CAAA;gBACH,CAAC;gBACD,gEAAgE;YAClE,CAAC;YAED,kBAAkB;YAClB,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;gBACpC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAClB,MAAM,CAAC,SAAS,EAAE,CAAC;wBACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,QAAQ,EAAE,IAAI;wBACd,YAAY,EAAE,CAAC;wBACf,gBAAgB,EAAE,CAAC;wBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;wBAC7B,aAAa,EAAE,KAAK;wBACpB,QAAQ,EAAE,GAAG,CAAC,EAAE;qBACjB,CAAC,CAAA;oBACF,OAAO;wBACL,MAAM,EAAE,OAAO;wBACf,QAAQ;wBACR,OAAO,EAAE,EAAE,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;wBACxD,aAAa,EAAE,KAAK,CAAC,SAAS;qBAC/B,CAAA;gBACH,CAAC;YACH,CAAC;YAED,uBAAuB;YACvB,IAAI,WAAmB,CAAA;YACvB,IAAI,MAA0B,CAAA;YAE9B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,aAAa,CAChD,aAAa,EACb,eAAe,aAAa,cAAc,CAC3C,CAAA;gBACD,WAAW,GAAG,OAAO,CAAC,WAAW,CAAA;gBACjC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;YACzB,CAAC;iBAAM,CAAC;gBACN,iEAAiE;gBACjE,WAAW,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC/C,CAAC;YAED,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,CAAC,CAAA;YACzE,MAAM,WAAW,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YAEnD,sEAAsE;YACtE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;YAE5F,MAAM,CAAC,WAAW,EAAE,CAAC;gBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,QAAQ,EAAE,IAAI;gBACd,UAAU,EAAE,aAAa;gBACzB,QAAQ,EAAE,GAAG,CAAC,EAAE;aACjB,CAAC,CAAA;YAEF,MAAM,OAAO,GAA2B,MAAM;gBAC5C,CAAC,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,QAAQ,eAAe,MAAM,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE;gBAC1G,CAAC,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,QAAQ,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,CAAA;YAEvF,MAAM,IAAI,GAA4B;gBACpC,KAAK,EAAE,kBAAkB;gBACzB,QAAQ;gBACR,YAAY,EAAE,WAAW;gBACzB,WAAW,EAAE,mBAAmB,WAAW,UAAU,WAAW,EAAE;gBAClE,WAAW,EAAE,aAAa;aAC3B,CAAA;YACD,IAAI,MAAM;gBAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;YAEjC,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,MAAM,EAAE,GAAG;gBACX,OAAO;gBACP,IAAI;aACL,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CACrB,UAAkB,EAClB,OAAe,EACf,OAAuB,EACvB,IAAY,EACZ,aAAqB;IAErB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA,CAAC,iBAAiB;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QACvC,IAAI,QAAQ,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;QAE/D,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAA;QAE1C,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;QACtD,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;QAEpF,uBAAuB;QACvB,mFAAmF;QACnF,+EAA+E;QAC/E,MAAM,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACxE,MAAM,yBAAyB,GAAG,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;QACxF,MAAM,wBAAwB,GAAG,gBAAgB,KAAK,SAAS;eAC1D,QAAQ,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM;eAC3C,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;QAE1E,IAAI,CAAC,yBAAyB,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAC5D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;QAC5C,CAAC;QAED,2EAA2E;QAC3E,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QAE5D,IAAI,cAAkC,CAAA;QACtC,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,wEAAwE;YACxE,IAAI,CAAC,yBAAyB;gBAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;YAE1E,0EAA0E;YAC1E,4EAA4E;YAC5E,iEAAiE;YACjE,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,IAAI,aAAa,CAAA;YACpD,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACnE,cAAc,GAAG,MAAM,CAAA;YACzB,CAAC;QACH,CAAC;QAED,gCAAgC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;QACrD,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAA;QAE5E,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,cAAc,EAAE,CAAA;IAC1G,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACxF,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAgB,EAAE,WAAmB;IACrE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAClD,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC;SACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;SACpC,MAAM,EAAE,CAAA;IACX,OAAO,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;AACvE,CAAC"}
package/dist/demo.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function startDemo(): Promise<void>;
2
+ //# sourceMappingURL=demo.d.ts.map
@@ -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
@@ -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
- > APIs gate access through accounts, API keys, and credit cards mechanisms that assume a human on the other end. Machines and AI agents can't sign up for accounts. toll-booth is L402 payment middleware that lets any HTTP API accept instant payments Lightning, Cashu ecash, or Nostr Wallet Connect — with no accounts, no API keys, and no PII exchanged.
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",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
- "description": "L402 Lightning payment middleware for any Node.js framework Express, Deno, Bun",
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", "lightning", "paywall", "micropayments", "middleware",
9
- "cashu", "ecash", "nostr", "nwc", "bitcoin",
10
- "express", "deno", "bun", "cloudflare-workers", "serverless",
11
- "macaroon", "http-402", "api-monetisation", "payment-gateway"
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",