@thecryptodonkey/toll-booth 3.4.0 → 3.6.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 +22 -1
- package/dist/booth.js +8 -2
- package/dist/core/melt-to-lightning.d.ts +24 -0
- package/dist/core/melt-to-lightning.js +43 -0
- package/dist/core/toll-booth.js +9 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/xcashu-rail.d.ts +5 -0
- package/dist/core/xcashu-rail.js +123 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +28 -2
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# toll-booth
|
|
2
2
|
|
|
3
|
+
[](https://github.com/TheCryptoDonkey/toll-booth/actions/workflows/ci.yml)
|
|
3
4
|
[](./LICENSE)
|
|
4
5
|
[](https://primal.net/p/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)
|
|
5
6
|
[](https://www.npmjs.com/package/@thecryptodonkey/toll-booth)
|
|
@@ -110,7 +111,7 @@ curl -H "Authorization: L402 <macaroon>:<preimage>" https://jokes.trotters.dev/a
|
|
|
110
111
|
|
|
111
112
|
- **L402 protocol** - industry-standard HTTP 402 payment flow with macaroon credentials
|
|
112
113
|
- **Multiple Lightning backends** - Phoenixd, LND, CLN, LNbits, NWC (any Nostr Wallet Connect wallet)
|
|
113
|
-
- **Alternative payment methods** - Cashu ecash tokens
|
|
114
|
+
- **Alternative payment methods** - Cashu ecash tokens and xcashu (NUT-24) direct-header payments
|
|
114
115
|
- **Cashu-only mode** - no Lightning node required; ideal for serverless and edge deployments
|
|
115
116
|
- **Credit system** - pre-paid balance with volume discount tiers
|
|
116
117
|
- **Free tier** - configurable daily allowance (IP-hashed, no PII stored)
|
|
@@ -241,6 +242,26 @@ const booth = new Booth({
|
|
|
241
242
|
|
|
242
243
|
No Lightning node, no channels, no liquidity management. Ideal for serverless and edge deployments.
|
|
243
244
|
|
|
245
|
+
### xcashu (Cashu ecash via NUT-24)
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { Booth } from '@thecryptodonkey/toll-booth'
|
|
249
|
+
|
|
250
|
+
const booth = new Booth({
|
|
251
|
+
adapter: 'web-standard',
|
|
252
|
+
xcashu: {
|
|
253
|
+
mints: ['https://mint.minibits.cash'],
|
|
254
|
+
unit: 'sat',
|
|
255
|
+
},
|
|
256
|
+
pricing: { '/api': 10 },
|
|
257
|
+
upstream: 'http://localhost:3000',
|
|
258
|
+
})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Clients pay by sending `X-Cashu: cashuB...` tokens in the request header. Proofs are verified and swapped at the configured mint(s) using cashu-ts.
|
|
262
|
+
|
|
263
|
+
Unlike the `redeemCashu` callback (which integrates Cashu into the L402 payment-and-redeem flow), `xcashu` is a self-contained payment rail: the client attaches a token directly to the API request and gets access in one step — no separate redeem endpoint required. Both rails can run simultaneously; the 402 challenge will include both `WWW-Authenticate` (L402) and `X-Cashu` headers.
|
|
264
|
+
|
|
244
265
|
---
|
|
245
266
|
|
|
246
267
|
## Lightning backends
|
package/dist/booth.js
CHANGED
|
@@ -2,6 +2,7 @@ import { normalisePricingTable } from './core/payment-rail.js';
|
|
|
2
2
|
import { createTollBooth } from './core/toll-booth.js';
|
|
3
3
|
import { createL402Rail } from './core/l402-rail.js';
|
|
4
4
|
import { createX402Rail } from './core/x402-rail.js';
|
|
5
|
+
import { createXCashuRail } from './core/xcashu-rail.js';
|
|
5
6
|
import { sqliteStorage } from './storage/sqlite.js';
|
|
6
7
|
import { StatsCollector } from './stats.js';
|
|
7
8
|
import { randomBytes } from 'node:crypto';
|
|
@@ -56,8 +57,8 @@ export class Booth {
|
|
|
56
57
|
pruneTimer;
|
|
57
58
|
closed = false;
|
|
58
59
|
constructor(config) {
|
|
59
|
-
if (!config.backend && !config.redeemCashu && !config.x402) {
|
|
60
|
-
throw new Error('At least one payment method required: provide a Lightning backend, redeemCashu callback, or
|
|
60
|
+
if (!config.backend && !config.redeemCashu && !config.x402 && !config.xcashu) {
|
|
61
|
+
throw new Error('At least one payment method required: provide a Lightning backend, redeemCashu callback, x402 config, or xcashu config');
|
|
61
62
|
}
|
|
62
63
|
let rootKeyInput;
|
|
63
64
|
if (config.rootKey) {
|
|
@@ -97,6 +98,9 @@ export class Booth {
|
|
|
97
98
|
if (config.x402) {
|
|
98
99
|
rails.push(createX402Rail({ ...config.x402, storage: this.storage }));
|
|
99
100
|
}
|
|
101
|
+
if (config.xcashu) {
|
|
102
|
+
rails.push(createXCashuRail(config.xcashu, this.storage));
|
|
103
|
+
}
|
|
100
104
|
this.engine = createTollBooth({
|
|
101
105
|
backend: config.backend,
|
|
102
106
|
storage: this.storage,
|
|
@@ -108,6 +112,8 @@ export class Booth {
|
|
|
108
112
|
freeTier: config.freeTier,
|
|
109
113
|
strictPricing: config.strictPricing,
|
|
110
114
|
creditTiers: config.creditTiers,
|
|
115
|
+
serviceName: config.serviceName,
|
|
116
|
+
description: config.description,
|
|
111
117
|
rails,
|
|
112
118
|
onPayment: (event) => {
|
|
113
119
|
stats.recordPayment(event);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Proof } from '@cashu/cashu-ts';
|
|
2
|
+
export type MeltResult = {
|
|
3
|
+
paid: true;
|
|
4
|
+
amountSats: number;
|
|
5
|
+
preimage?: string;
|
|
6
|
+
} | {
|
|
7
|
+
paid: false;
|
|
8
|
+
error: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Melts Cashu proofs to pay a Lightning invoice on the operator's node.
|
|
12
|
+
* Handles the full flow: invoice creation → melt quote → coin selection → melt.
|
|
13
|
+
* Discards change proofs (fee overpayment donated to mint).
|
|
14
|
+
*
|
|
15
|
+
* @param opts.mintUrl - The mint that issued the proofs
|
|
16
|
+
* @param opts.proofs - Server-side proofs from wallet.receive()
|
|
17
|
+
* @param opts.createInvoice - Callback to create a BOLT11 invoice on the operator's node
|
|
18
|
+
*/
|
|
19
|
+
export declare function meltToLightning(opts: {
|
|
20
|
+
mintUrl: string;
|
|
21
|
+
proofs: Proof[];
|
|
22
|
+
createInvoice: (amountSats: number) => Promise<string>;
|
|
23
|
+
}): Promise<MeltResult>;
|
|
24
|
+
//# sourceMappingURL=melt-to-lightning.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Wallet } from '@cashu/cashu-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Melts Cashu proofs to pay a Lightning invoice on the operator's node.
|
|
4
|
+
* Handles the full flow: invoice creation → melt quote → coin selection → melt.
|
|
5
|
+
* Discards change proofs (fee overpayment donated to mint).
|
|
6
|
+
*
|
|
7
|
+
* @param opts.mintUrl - The mint that issued the proofs
|
|
8
|
+
* @param opts.proofs - Server-side proofs from wallet.receive()
|
|
9
|
+
* @param opts.createInvoice - Callback to create a BOLT11 invoice on the operator's node
|
|
10
|
+
*/
|
|
11
|
+
export async function meltToLightning(opts) {
|
|
12
|
+
const { mintUrl, proofs, createInvoice } = opts;
|
|
13
|
+
const totalSats = proofs.reduce((sum, p) => sum + p.amount, 0);
|
|
14
|
+
if (totalSats <= 0) {
|
|
15
|
+
return { paid: false, error: 'No proofs to melt' };
|
|
16
|
+
}
|
|
17
|
+
const wallet = new Wallet(mintUrl, { unit: 'sat' });
|
|
18
|
+
// Create invoice for the full proof amount
|
|
19
|
+
const invoice = await createInvoice(totalSats);
|
|
20
|
+
// Get melt quote to learn fee_reserve
|
|
21
|
+
const meltQuote = await wallet.createMeltQuoteBolt11(invoice);
|
|
22
|
+
const needed = meltQuote.amount + meltQuote.fee_reserve;
|
|
23
|
+
if (needed > totalSats) {
|
|
24
|
+
return {
|
|
25
|
+
paid: false,
|
|
26
|
+
error: `Proofs insufficient for fees (have ${totalSats}, need ${needed} including ${meltQuote.fee_reserve} fee reserve)`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Coin selection
|
|
30
|
+
const { send } = await wallet.send(needed, proofs, { includeFees: true });
|
|
31
|
+
// Melt — pay the Lightning invoice via the mint
|
|
32
|
+
const meltResponse = await wallet.meltProofsBolt11(meltQuote, send);
|
|
33
|
+
if (meltResponse.quote.state === 'PAID') {
|
|
34
|
+
// Discard change proofs (keep + change) — bearer instruments not retained
|
|
35
|
+
return {
|
|
36
|
+
paid: true,
|
|
37
|
+
amountSats: meltQuote.amount,
|
|
38
|
+
preimage: meltResponse.quote.payment_preimage ?? undefined,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { paid: false, error: `Melt state: ${meltResponse.quote.state}` };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=melt-to-lightning.js.map
|
package/dist/core/toll-booth.js
CHANGED
|
@@ -81,6 +81,15 @@ export function createTollBooth(config) {
|
|
|
81
81
|
if (config.creditTiers && config.creditTiers.length > 0) {
|
|
82
82
|
challengeBody.credit_tiers = config.creditTiers;
|
|
83
83
|
}
|
|
84
|
+
// Agent-friendly service metadata (only when serviceName is configured).
|
|
85
|
+
// auth_hint is L402-specific; x402/xcashu have different auth mechanisms.
|
|
86
|
+
if (config.serviceName) {
|
|
87
|
+
challengeBody.booth = {
|
|
88
|
+
name: config.serviceName,
|
|
89
|
+
...(config.description && { description: config.description }),
|
|
90
|
+
};
|
|
91
|
+
challengeBody.auth_hint = 'Pay the invoice, then send header \u2014 Authorization: L402 <macaroon>:<preimage>';
|
|
92
|
+
}
|
|
84
93
|
// Store invoice data from L402 rail if present
|
|
85
94
|
const l402Data = challengeBody.l402;
|
|
86
95
|
if (l402Data?.payment_hash) {
|
package/dist/core/types.d.ts
CHANGED
|
@@ -60,6 +60,8 @@ export interface TollBoothCoreConfig {
|
|
|
60
60
|
normalisedPricing?: Record<string, PriceInfo>;
|
|
61
61
|
/** Human-readable service name for invoice descriptions. Defaults to 'toll-booth'. */
|
|
62
62
|
serviceName?: string;
|
|
63
|
+
/** Service description for 402 response bodies. */
|
|
64
|
+
description?: string;
|
|
63
65
|
onPayment?: (event: PaymentEvent) => void;
|
|
64
66
|
onRequest?: (event: RequestEvent) => void;
|
|
65
67
|
onChallenge?: (event: ChallengeEvent) => void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PaymentRail } from './payment-rail.js';
|
|
2
|
+
import type { XCashuConfig } from '../types.js';
|
|
3
|
+
import type { StorageBackend } from '../storage/interface.js';
|
|
4
|
+
export declare function createXCashuRail(config: XCashuConfig, storage?: StorageBackend): PaymentRail;
|
|
5
|
+
//# sourceMappingURL=xcashu-rail.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { Wallet, getDecodedToken } from '@cashu/cashu-ts';
|
|
3
|
+
const FAIL = { authenticated: false, paymentId: '', mode: 'credit', currency: 'sat' };
|
|
4
|
+
/**
|
|
5
|
+
* Encode a NUT-18-style payment request for the X-Cashu header.
|
|
6
|
+
* Simplified JSON encoding — full CBOR encoding can be added later
|
|
7
|
+
* if cashu-ts exposes a PaymentRequest builder.
|
|
8
|
+
*/
|
|
9
|
+
function encodePaymentRequest(amount, unit, mints) {
|
|
10
|
+
const payload = JSON.stringify({ a: amount, u: unit, m: mints });
|
|
11
|
+
return 'creqA' + Buffer.from(payload).toString('base64url');
|
|
12
|
+
}
|
|
13
|
+
export function createXCashuRail(config, storage) {
|
|
14
|
+
const unit = config.unit ?? 'sat';
|
|
15
|
+
const mintUrls = config.mints;
|
|
16
|
+
// Lazily initialised wallets per mint (loadMint is async, done on first use)
|
|
17
|
+
const wallets = new Map();
|
|
18
|
+
const walletReady = new Map();
|
|
19
|
+
async function getWallet(mintUrl) {
|
|
20
|
+
const existing = walletReady.get(mintUrl);
|
|
21
|
+
if (existing)
|
|
22
|
+
return existing;
|
|
23
|
+
const promise = (async () => {
|
|
24
|
+
const wallet = new Wallet(mintUrl, { unit });
|
|
25
|
+
await wallet.loadMint();
|
|
26
|
+
wallets.set(mintUrl, wallet);
|
|
27
|
+
return wallet;
|
|
28
|
+
})();
|
|
29
|
+
walletReady.set(mintUrl, promise);
|
|
30
|
+
return promise;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
type: 'xcashu',
|
|
34
|
+
creditSupported: true,
|
|
35
|
+
canChallenge(price) {
|
|
36
|
+
return price.sats !== undefined;
|
|
37
|
+
},
|
|
38
|
+
detect(req) {
|
|
39
|
+
const header = req.headers['x-cashu'];
|
|
40
|
+
return typeof header === 'string' && header.startsWith('cashuB');
|
|
41
|
+
},
|
|
42
|
+
async challenge(_route, price) {
|
|
43
|
+
const amount = price.sats;
|
|
44
|
+
const encoded = encodePaymentRequest(amount, unit, mintUrls);
|
|
45
|
+
return {
|
|
46
|
+
headers: { 'X-Cashu': encoded },
|
|
47
|
+
body: {
|
|
48
|
+
xcashu: { amount, unit, mints: mintUrls },
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
async verify(req) {
|
|
53
|
+
const header = req.headers['x-cashu'];
|
|
54
|
+
if (typeof header !== 'string' || !header.startsWith('cashuB')) {
|
|
55
|
+
return FAIL;
|
|
56
|
+
}
|
|
57
|
+
let decoded;
|
|
58
|
+
try {
|
|
59
|
+
decoded = getDecodedToken(header);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return FAIL;
|
|
63
|
+
}
|
|
64
|
+
// Validate mint is accepted
|
|
65
|
+
const tokenMint = decoded.mint;
|
|
66
|
+
if (!tokenMint || !mintUrls.includes(tokenMint)) {
|
|
67
|
+
return FAIL;
|
|
68
|
+
}
|
|
69
|
+
// Validate unit matches
|
|
70
|
+
if (decoded.unit && decoded.unit !== unit) {
|
|
71
|
+
return FAIL;
|
|
72
|
+
}
|
|
73
|
+
// Get or initialise wallet for this mint
|
|
74
|
+
let wallet;
|
|
75
|
+
try {
|
|
76
|
+
wallet = await getWallet(tokenMint);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return FAIL;
|
|
80
|
+
}
|
|
81
|
+
// Swap proofs at the mint to verify and claim them
|
|
82
|
+
let receivedProofs;
|
|
83
|
+
try {
|
|
84
|
+
receivedProofs = await wallet.receive(header);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Mint unreachable, proofs already spent, or other error
|
|
88
|
+
return FAIL;
|
|
89
|
+
}
|
|
90
|
+
const creditedAmount = receivedProofs.reduce((sum, p) => sum + p.amount, 0);
|
|
91
|
+
if (creditedAmount <= 0) {
|
|
92
|
+
return FAIL;
|
|
93
|
+
}
|
|
94
|
+
// Fire onProofsReceived callback (non-blocking, fire-and-forget)
|
|
95
|
+
if (config.onProofsReceived) {
|
|
96
|
+
try {
|
|
97
|
+
const cbResult = config.onProofsReceived(receivedProofs, tokenMint, creditedAmount);
|
|
98
|
+
if (cbResult && typeof cbResult.catch === 'function') {
|
|
99
|
+
cbResult.catch(() => { });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Callback errors silently discarded — never block the payment flow
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Generate payment ID and settlement secret
|
|
107
|
+
const paymentId = randomBytes(32).toString('hex');
|
|
108
|
+
const settlementSecret = randomBytes(32).toString('hex');
|
|
109
|
+
// Settle credit if storage available
|
|
110
|
+
if (storage && !storage.isSettled(paymentId)) {
|
|
111
|
+
storage.settleWithCredit(paymentId, creditedAmount, settlementSecret, unit);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
authenticated: true,
|
|
115
|
+
paymentId,
|
|
116
|
+
mode: 'credit',
|
|
117
|
+
currency: unit,
|
|
118
|
+
creditBalance: creditedAmount,
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=xcashu-rail.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ export type { L402RailConfig } from './core/l402-rail.js';
|
|
|
27
27
|
export { createX402Rail } from './core/x402-rail.js';
|
|
28
28
|
export type { X402RailConfig, X402Facilitator, X402Payment, X402VerifyResult } from './core/x402-types.js';
|
|
29
29
|
export { DEFAULT_USDC_ASSETS } from './core/x402-types.js';
|
|
30
|
+
export { createXCashuRail } from './core/xcashu-rail.js';
|
|
31
|
+
export type { XCashuConfig } from './types.js';
|
|
32
|
+
export { meltToLightning } from './core/melt-to-lightning.js';
|
|
33
|
+
export type { MeltResult } from './core/melt-to-lightning.js';
|
|
30
34
|
export { mintMacaroon, verifyMacaroon, parseCaveats } from './macaroon.js';
|
|
31
35
|
export type { VerifyContext, VerifyResult } from './macaroon.js';
|
|
32
36
|
export { FreeTier, CreditFreeTier } from './free-tier.js';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,8 @@ export { normalisePricing, normalisePricingTable, isTieredPricing } from './core
|
|
|
17
17
|
export { createL402Rail } from './core/l402-rail.js';
|
|
18
18
|
export { createX402Rail } from './core/x402-rail.js';
|
|
19
19
|
export { DEFAULT_USDC_ASSETS } from './core/x402-types.js';
|
|
20
|
+
export { createXCashuRail } from './core/xcashu-rail.js';
|
|
21
|
+
export { meltToLightning } from './core/melt-to-lightning.js';
|
|
20
22
|
// Utilities
|
|
21
23
|
export { mintMacaroon, verifyMacaroon, parseCaveats } from './macaroon.js';
|
|
22
24
|
export { FreeTier, CreditFreeTier } from './free-tier.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export interface LightningBackend {
|
|
|
43
43
|
*/
|
|
44
44
|
checkInvoice(paymentHash: string): Promise<InvoiceStatus>;
|
|
45
45
|
}
|
|
46
|
+
import type { Proof } from '@cashu/cashu-ts';
|
|
46
47
|
import type { Currency, PricingEntry } from './core/payment-rail.js';
|
|
47
48
|
import type { X402RailConfig } from './core/x402-types.js';
|
|
48
49
|
/**
|
|
@@ -66,12 +67,27 @@ export interface CreditTier {
|
|
|
66
67
|
creditSats: number;
|
|
67
68
|
/** Human-readable label for this tier. */
|
|
68
69
|
label: string;
|
|
69
|
-
/** Pricing tier this credit tier belongs to (e.g. 'default', 'premium'). */
|
|
70
|
-
tier?: string;
|
|
71
70
|
/** x402 tier amount in cents (USD). */
|
|
72
71
|
amountUsd?: number;
|
|
73
72
|
/** x402 tier credit in cents (USD). */
|
|
74
73
|
creditUsd?: number;
|
|
74
|
+
/** What the agent gets for this tier, e.g. "1 request", "10 minutes access". */
|
|
75
|
+
yields?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Configuration for the xcashu (NUT-24) payment rail.
|
|
79
|
+
*/
|
|
80
|
+
export interface XCashuConfig {
|
|
81
|
+
/** Accepted Cashu mint URLs (1+) */
|
|
82
|
+
mints: string[];
|
|
83
|
+
/** Currency unit, default 'sat' */
|
|
84
|
+
unit?: Currency;
|
|
85
|
+
/**
|
|
86
|
+
* Called after successful token swap with the server-side proofs.
|
|
87
|
+
* Fire-and-forget — the rail does NOT await this callback.
|
|
88
|
+
* Use for melting, persisting, or forwarding received ecash.
|
|
89
|
+
*/
|
|
90
|
+
onProofsReceived?: (proofs: Proof[], mintUrl: string, amount: number) => void | Promise<void>;
|
|
75
91
|
}
|
|
76
92
|
/**
|
|
77
93
|
* Configuration for a toll-booth instance.
|
|
@@ -158,12 +174,22 @@ export interface BoothConfig {
|
|
|
158
174
|
redeemCashu?: (token: string, paymentHash: string) => Promise<number>;
|
|
159
175
|
/** x402 stablecoin payment rail configuration. */
|
|
160
176
|
x402?: X402RailConfig;
|
|
177
|
+
/**
|
|
178
|
+
* xcashu (NUT-24) config — accept Cashu ecash via X-Cashu header.
|
|
179
|
+
* Proofs are swapped at the configured mint(s) using cashu-ts.
|
|
180
|
+
*/
|
|
181
|
+
xcashu?: XCashuConfig;
|
|
161
182
|
/**
|
|
162
183
|
* Human-readable service name used in Lightning invoice descriptions.
|
|
163
184
|
* Defaults to `'toll-booth'`. Example: `'satgate'` produces invoices
|
|
164
185
|
* like `"satgate: 1000 sats credit"`.
|
|
165
186
|
*/
|
|
166
187
|
serviceName?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Service description shown in 402 response bodies.
|
|
190
|
+
* Only included when `serviceName` is also set.
|
|
191
|
+
*/
|
|
192
|
+
description?: string;
|
|
167
193
|
/**
|
|
168
194
|
* Timeout in milliseconds for upstream proxy requests.
|
|
169
195
|
* Defaults to 30000 (30 seconds).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thecryptodonkey/toll-booth",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monetise any API with HTTP 402 payments. Payment-rail agnostic middleware for Express, Hono, Deno, Bun, and Workers.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
"prepare": "patch-package"
|
|
104
104
|
},
|
|
105
105
|
"dependencies": {
|
|
106
|
+
"@cashu/cashu-ts": "^3.6.0",
|
|
106
107
|
"better-sqlite3": "^11.8.0",
|
|
107
108
|
"macaroon": "^3.0.4",
|
|
108
109
|
"nostr-core": "^0.4.0",
|
|
@@ -121,7 +122,6 @@
|
|
|
121
122
|
}
|
|
122
123
|
},
|
|
123
124
|
"devDependencies": {
|
|
124
|
-
"@cashu/cashu-ts": "^3.5.0",
|
|
125
125
|
"@hono/node-server": "^1.19.11",
|
|
126
126
|
"@semantic-release/changelog": "^6.0.3",
|
|
127
127
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -136,6 +136,5 @@
|
|
|
136
136
|
"tsx": "^4.21.0",
|
|
137
137
|
"typescript": "^5.7.0",
|
|
138
138
|
"vitest": "^3.0.0"
|
|
139
|
-
}
|
|
140
|
-
"optionalDependencies": {}
|
|
139
|
+
}
|
|
141
140
|
}
|