@thecryptodonkey/toll-booth 3.7.1 → 3.8.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/dist/core/x402-rail.js +73 -16
- package/dist/core/x402-types.d.ts +41 -0
- package/dist/core/x402-types.js +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/core/x402-rail.js
CHANGED
|
@@ -1,7 +1,52 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { DEFAULT_USDC_ASSETS } from './x402-types.js';
|
|
2
|
+
import { DEFAULT_USDC_ASSETS, X402_VERSION } from './x402-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Normalise an inbound x402 v2 PAYMENT-SIGNATURE payload to the flat
|
|
5
|
+
* internal X402Payment format used by the facilitator interface.
|
|
6
|
+
*/
|
|
7
|
+
function normaliseV2Payload(wire) {
|
|
8
|
+
const auth = wire.payload?.authorization;
|
|
9
|
+
if (!auth)
|
|
10
|
+
return undefined;
|
|
11
|
+
const amount = Number(auth.value);
|
|
12
|
+
if (!Number.isFinite(amount))
|
|
13
|
+
return undefined;
|
|
14
|
+
return {
|
|
15
|
+
signature: wire.payload.signature,
|
|
16
|
+
sender: auth.from,
|
|
17
|
+
amount,
|
|
18
|
+
network: wire.accepted?.network ?? '',
|
|
19
|
+
nonce: auth.nonce,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Try to parse the payment from either the v2 PAYMENT-SIGNATURE header
|
|
24
|
+
* (base64-encoded JSON) or the legacy X-Payment header (raw JSON).
|
|
25
|
+
*/
|
|
26
|
+
function parsePayment(req) {
|
|
27
|
+
// v2: PAYMENT-SIGNATURE (base64-encoded JSON)
|
|
28
|
+
const sigHeader = req.headers['payment-signature'];
|
|
29
|
+
if (sigHeader && sigHeader.length <= 8192) {
|
|
30
|
+
try {
|
|
31
|
+
const decoded = JSON.parse(Buffer.from(sigHeader, 'base64').toString());
|
|
32
|
+
if (decoded.x402Version >= 2)
|
|
33
|
+
return normaliseV2Payload(decoded);
|
|
34
|
+
}
|
|
35
|
+
catch { /* fall through to legacy */ }
|
|
36
|
+
}
|
|
37
|
+
// Legacy: X-Payment (raw JSON)
|
|
38
|
+
const raw = req.headers['x-payment'];
|
|
39
|
+
if (!raw || raw.length > 4096)
|
|
40
|
+
return undefined;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(raw);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
3
48
|
export function createX402Rail(config) {
|
|
4
|
-
const { receiverAddress, network, asset = DEFAULT_USDC_ASSETS[network], facilitator, creditMode = true, facilitatorUrl, storage, } = config;
|
|
49
|
+
const { receiverAddress, network, asset = DEFAULT_USDC_ASSETS[network], facilitator, creditMode = true, facilitatorUrl, maxTimeoutSeconds = 3600, storage, } = config;
|
|
5
50
|
return {
|
|
6
51
|
type: 'x402',
|
|
7
52
|
creditSupported: true,
|
|
@@ -9,13 +54,33 @@ export function createX402Rail(config) {
|
|
|
9
54
|
return price.usd !== undefined;
|
|
10
55
|
},
|
|
11
56
|
detect(req) {
|
|
12
|
-
return req.headers['
|
|
57
|
+
return req.headers['payment-signature'] !== undefined
|
|
58
|
+
|| req.headers['x-payment'] !== undefined;
|
|
13
59
|
},
|
|
14
|
-
async challenge(
|
|
60
|
+
async challenge(route, price) {
|
|
61
|
+
const requirements = {
|
|
62
|
+
x402Version: X402_VERSION,
|
|
63
|
+
accepts: [{
|
|
64
|
+
scheme: 'exact',
|
|
65
|
+
network,
|
|
66
|
+
amount: String(price.usd),
|
|
67
|
+
asset: asset ?? '',
|
|
68
|
+
payTo: receiverAddress,
|
|
69
|
+
maxTimeoutSeconds,
|
|
70
|
+
extra: {
|
|
71
|
+
...(facilitatorUrl && { facilitatorUrl }),
|
|
72
|
+
},
|
|
73
|
+
}],
|
|
74
|
+
resource: { url: route },
|
|
75
|
+
};
|
|
76
|
+
const encoded = Buffer.from(JSON.stringify(requirements)).toString('base64');
|
|
15
77
|
return {
|
|
16
|
-
headers: {
|
|
78
|
+
headers: {
|
|
79
|
+
'Payment-Required': encoded,
|
|
80
|
+
},
|
|
17
81
|
body: {
|
|
18
82
|
x402: {
|
|
83
|
+
version: X402_VERSION,
|
|
19
84
|
receiver: receiverAddress,
|
|
20
85
|
network,
|
|
21
86
|
asset,
|
|
@@ -26,20 +91,12 @@ export function createX402Rail(config) {
|
|
|
26
91
|
};
|
|
27
92
|
},
|
|
28
93
|
async verify(req) {
|
|
29
|
-
const
|
|
30
|
-
if (!
|
|
31
|
-
return { authenticated: false, paymentId: '', mode: 'per-request', currency: 'usd' };
|
|
32
|
-
}
|
|
33
|
-
let payload;
|
|
34
|
-
try {
|
|
35
|
-
payload = JSON.parse(raw);
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
94
|
+
const payload = parsePayment(req);
|
|
95
|
+
if (!payload) {
|
|
38
96
|
return { authenticated: false, paymentId: '', mode: 'per-request', currency: 'usd' };
|
|
39
97
|
}
|
|
40
98
|
// Validate required fields before passing to facilitator
|
|
41
|
-
if (typeof payload !== '
|
|
42
|
-
typeof payload.signature !== 'string' || !payload.signature ||
|
|
99
|
+
if (typeof payload.signature !== 'string' || !payload.signature ||
|
|
43
100
|
typeof payload.sender !== 'string' || !payload.sender ||
|
|
44
101
|
typeof payload.amount !== 'number' || !Number.isFinite(payload.amount) || payload.amount <= 0 ||
|
|
45
102
|
typeof payload.network !== 'string' || !payload.network ||
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** Internal normalised payment (flat structure passed to facilitator). */
|
|
1
2
|
export interface X402Payment {
|
|
2
3
|
signature: string;
|
|
3
4
|
sender: string;
|
|
@@ -21,9 +22,49 @@ export interface X402RailConfig {
|
|
|
21
22
|
facilitator: X402Facilitator;
|
|
22
23
|
creditMode?: boolean;
|
|
23
24
|
facilitatorUrl?: string;
|
|
25
|
+
/** Max seconds before payment authorisation expires. Default 3600. */
|
|
26
|
+
maxTimeoutSeconds?: number;
|
|
24
27
|
/** Storage backend — required for credit mode to persist balances. Injected by Booth. */
|
|
25
28
|
storage?: import('../storage/interface.js').StorageBackend;
|
|
26
29
|
}
|
|
27
30
|
/** Default USDC contract addresses by network */
|
|
28
31
|
export declare const DEFAULT_USDC_ASSETS: Record<string, string>;
|
|
32
|
+
export declare const X402_VERSION = 2;
|
|
33
|
+
export interface X402PaymentRequirements {
|
|
34
|
+
scheme: string;
|
|
35
|
+
network: string;
|
|
36
|
+
amount: string;
|
|
37
|
+
asset: string;
|
|
38
|
+
payTo: string;
|
|
39
|
+
maxTimeoutSeconds: number;
|
|
40
|
+
extra: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export interface X402Resource {
|
|
43
|
+
url: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
mimeType?: string;
|
|
46
|
+
}
|
|
47
|
+
/** PAYMENT-REQUIRED header (base64-encoded JSON). */
|
|
48
|
+
export interface X402ChallengeWire {
|
|
49
|
+
x402Version: number;
|
|
50
|
+
accepts: X402PaymentRequirements[];
|
|
51
|
+
resource?: X402Resource;
|
|
52
|
+
}
|
|
53
|
+
/** PAYMENT-SIGNATURE header (base64-encoded JSON). */
|
|
54
|
+
export interface X402PaymentWire {
|
|
55
|
+
x402Version: number;
|
|
56
|
+
resource?: X402Resource;
|
|
57
|
+
accepted?: X402PaymentRequirements;
|
|
58
|
+
payload: {
|
|
59
|
+
signature: string;
|
|
60
|
+
authorization: {
|
|
61
|
+
from: string;
|
|
62
|
+
to: string;
|
|
63
|
+
value: string;
|
|
64
|
+
validAfter: string;
|
|
65
|
+
validBefore: string;
|
|
66
|
+
nonce: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
}
|
|
29
70
|
//# sourceMappingURL=x402-types.d.ts.map
|
package/dist/core/x402-types.js
CHANGED
|
@@ -4,4 +4,6 @@ export const DEFAULT_USDC_ASSETS = {
|
|
|
4
4
|
'base-sepolia': '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
5
5
|
'polygon': '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
|
|
6
6
|
};
|
|
7
|
+
// ── x402 v2 wire format types ──────────────────────────────────────
|
|
8
|
+
export const X402_VERSION = 2;
|
|
7
9
|
//# sourceMappingURL=x402-types.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -25,8 +25,8 @@ export { normalisePricing, normalisePricingTable, isTieredPricing } from './core
|
|
|
25
25
|
export { createL402Rail } from './core/l402-rail.js';
|
|
26
26
|
export type { L402RailConfig } from './core/l402-rail.js';
|
|
27
27
|
export { createX402Rail } from './core/x402-rail.js';
|
|
28
|
-
export type { X402RailConfig, X402Facilitator, X402Payment, X402VerifyResult } from './core/x402-types.js';
|
|
29
|
-
export { DEFAULT_USDC_ASSETS } from './core/x402-types.js';
|
|
28
|
+
export type { X402RailConfig, X402Facilitator, X402Payment, X402VerifyResult, X402ChallengeWire, X402PaymentWire, X402PaymentRequirements } from './core/x402-types.js';
|
|
29
|
+
export { DEFAULT_USDC_ASSETS, X402_VERSION } from './core/x402-types.js';
|
|
30
30
|
export { createXCashuRail } from './core/xcashu-rail.js';
|
|
31
31
|
export type { XCashuConfig } from './types.js';
|
|
32
32
|
export { meltToLightning } from './core/melt-to-lightning.js';
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export { createWebStandardMiddleware, createWebStandardInvoiceStatusHandler, cre
|
|
|
16
16
|
export { normalisePricing, normalisePricingTable, isTieredPricing } from './core/payment-rail.js';
|
|
17
17
|
export { createL402Rail } from './core/l402-rail.js';
|
|
18
18
|
export { createX402Rail } from './core/x402-rail.js';
|
|
19
|
-
export { DEFAULT_USDC_ASSETS } from './core/x402-types.js';
|
|
19
|
+
export { DEFAULT_USDC_ASSETS, X402_VERSION } from './core/x402-types.js';
|
|
20
20
|
export { createXCashuRail } from './core/xcashu-rail.js';
|
|
21
21
|
export { meltToLightning } from './core/melt-to-lightning.js';
|
|
22
22
|
// Utilities
|
package/package.json
CHANGED