@parallel-protocol/x402 0.5.3 → 0.7.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 +226 -6
- package/dist/{chunk-75GLDK7L.js → chunk-AENXD4OC.js} +338 -81
- package/dist/chunk-AFRDHGDT.js +36 -0
- package/dist/chunk-JPMK5YBU.cjs +42 -0
- package/dist/chunk-POU7EH3E.cjs +755 -0
- package/dist/express.cjs +63 -6
- package/dist/express.d.cts +3 -2
- package/dist/express.d.ts +3 -2
- package/dist/express.js +61 -4
- package/dist/fastify.cjs +88 -14
- package/dist/fastify.d.cts +2 -1
- package/dist/fastify.d.ts +2 -1
- package/dist/fastify.js +86 -12
- package/dist/hono.cjs +27 -6
- package/dist/hono.d.cts +3 -2
- package/dist/hono.d.ts +3 -2
- package/dist/hono.js +25 -4
- package/dist/index.cjs +41 -20
- package/dist/index.d.cts +64 -5
- package/dist/index.d.ts +64 -5
- package/dist/index.js +2 -1
- package/dist/llm.cjs +486 -0
- package/dist/llm.d.cts +203 -0
- package/dist/llm.d.ts +203 -0
- package/dist/llm.js +473 -0
- package/dist/next.cjs +57 -7
- package/dist/next.d.cts +2 -1
- package/dist/next.d.ts +2 -1
- package/dist/next.js +54 -4
- package/dist/types-q_gu5wjz.d.cts +185 -0
- package/dist/types-q_gu5wjz.d.ts +185 -0
- package/package.json +12 -2
- package/dist/chunk-2UEAVMCH.js +0 -17
- package/dist/chunk-KQPIZ6SZ.cjs +0 -491
- package/dist/chunk-XUNNMCO5.cjs +0 -20
- package/dist/types-CUi55YSx.d.cts +0 -95
- package/dist/types-CUi55YSx.d.ts +0 -95
package/dist/next.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
3
|
+
var chunkPOU7EH3E_cjs = require('./chunk-POU7EH3E.cjs');
|
|
4
|
+
require('./chunk-JPMK5YBU.cjs');
|
|
5
5
|
var server = require('next/server');
|
|
6
6
|
|
|
7
7
|
// src/next/adapter.ts
|
|
@@ -22,11 +22,22 @@ var NextAdapter = class {
|
|
|
22
22
|
getUrl() {
|
|
23
23
|
return this.req.url;
|
|
24
24
|
}
|
|
25
|
+
// Read from a clone: a request body is a stream that can be consumed once,
|
|
26
|
+
// and the handler still needs the original.
|
|
27
|
+
async getBody() {
|
|
28
|
+
if (!chunkPOU7EH3E_cjs.isJsonContentType(this.req.headers.get("content-type") ?? void 0))
|
|
29
|
+
return void 0;
|
|
30
|
+
try {
|
|
31
|
+
return await this.req.clone().json();
|
|
32
|
+
} catch {
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
25
36
|
};
|
|
26
37
|
|
|
27
38
|
// src/next/index.ts
|
|
28
39
|
function withPayment(config, handler) {
|
|
29
|
-
const gate =
|
|
40
|
+
const gate = chunkPOU7EH3E_cjs.createPaymentGate(config);
|
|
30
41
|
return async (req) => {
|
|
31
42
|
const gateResult = await gate(new NextAdapter(req));
|
|
32
43
|
if (gateResult.type === "pass") {
|
|
@@ -43,20 +54,57 @@ function withPayment(config, handler) {
|
|
|
43
54
|
}
|
|
44
55
|
let response;
|
|
45
56
|
try {
|
|
46
|
-
const outcome = await
|
|
47
|
-
|
|
57
|
+
const outcome = await chunkPOU7EH3E_cjs.raceTimeout(
|
|
58
|
+
handler(req),
|
|
59
|
+
gateResult.handlerTimeoutMs
|
|
60
|
+
);
|
|
61
|
+
if (outcome === chunkPOU7EH3E_cjs.HANDLER_TIMEOUT) {
|
|
48
62
|
return new server.NextResponse(null, { status: 504 });
|
|
49
63
|
}
|
|
50
64
|
response = outcome;
|
|
51
65
|
} catch {
|
|
52
66
|
return new server.NextResponse(null, { status: 504 });
|
|
53
67
|
}
|
|
68
|
+
let raw;
|
|
69
|
+
if (gateResult.scheme === "upto") {
|
|
70
|
+
raw = response.headers.get(chunkPOU7EH3E_cjs.SETTLE_AMOUNT_HEADER) ?? void 0;
|
|
71
|
+
if (raw !== void 0) {
|
|
72
|
+
const headers = new Headers(response.headers);
|
|
73
|
+
headers.delete(chunkPOU7EH3E_cjs.SETTLE_AMOUNT_HEADER);
|
|
74
|
+
response = new server.NextResponse(response.body, {
|
|
75
|
+
status: response.status,
|
|
76
|
+
headers
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
54
80
|
if (response.status >= 200 && response.status < 300) {
|
|
81
|
+
let settleOptions;
|
|
82
|
+
if (gateResult.scheme === "upto") {
|
|
83
|
+
const handled = response;
|
|
84
|
+
const resolved = await chunkPOU7EH3E_cjs.resolveCharge(gateResult, raw, {
|
|
85
|
+
status: handled.status,
|
|
86
|
+
header: (name) => handled.headers.get(name) ?? void 0,
|
|
87
|
+
// Read from a clone: the body streams once, to the client.
|
|
88
|
+
body: () => chunkPOU7EH3E_cjs.jsonFromResponse(handled)
|
|
89
|
+
});
|
|
90
|
+
if (resolved.kind === "invalid") {
|
|
91
|
+
handled.body?.cancel().catch(() => {
|
|
92
|
+
});
|
|
93
|
+
return server.NextResponse.json(
|
|
94
|
+
chunkPOU7EH3E_cjs.invalidSettleAmountResponse(resolved.reason),
|
|
95
|
+
{
|
|
96
|
+
status: 402
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
if (resolved.kind === "skip") return response;
|
|
101
|
+
settleOptions = { amount: resolved.amount };
|
|
102
|
+
}
|
|
55
103
|
try {
|
|
56
|
-
const settleResponse = await gateResult.settle();
|
|
104
|
+
const settleResponse = settleOptions ? await gateResult.settle(settleOptions) : await gateResult.settle();
|
|
57
105
|
if (settleResponse.success) {
|
|
58
106
|
const headers = new Headers(response.headers);
|
|
59
|
-
headers.set("payment-response",
|
|
107
|
+
headers.set("payment-response", chunkPOU7EH3E_cjs.encodeBase64(settleResponse));
|
|
60
108
|
headers.set("access-control-expose-headers", "payment-response");
|
|
61
109
|
return new server.NextResponse(response.body, {
|
|
62
110
|
status: response.status,
|
|
@@ -65,6 +113,8 @@ function withPayment(config, handler) {
|
|
|
65
113
|
}
|
|
66
114
|
} catch {
|
|
67
115
|
}
|
|
116
|
+
response.body?.cancel().catch(() => {
|
|
117
|
+
});
|
|
68
118
|
return server.NextResponse.json(
|
|
69
119
|
{
|
|
70
120
|
error: "PAYMENT_SETTLEMENT_FAILED",
|
package/dist/next.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-q_gu5wjz.cjs';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class NextAdapter implements HTTPAdapter {
|
|
@@ -9,6 +9,7 @@ declare class NextAdapter implements HTTPAdapter {
|
|
|
9
9
|
getMethod(): string;
|
|
10
10
|
getPath(): string;
|
|
11
11
|
getUrl(): string;
|
|
12
|
+
getBody(): Promise<unknown>;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
type NextHandler = (req: NextRequest) => Promise<NextResponse>;
|
package/dist/next.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-
|
|
2
|
+
import { H as HTTPAdapter, P as PaymentMiddlewareConfig } from './types-q_gu5wjz.js';
|
|
3
3
|
import 'viem';
|
|
4
4
|
|
|
5
5
|
declare class NextAdapter implements HTTPAdapter {
|
|
@@ -9,6 +9,7 @@ declare class NextAdapter implements HTTPAdapter {
|
|
|
9
9
|
getMethod(): string;
|
|
10
10
|
getPath(): string;
|
|
11
11
|
getUrl(): string;
|
|
12
|
+
getBody(): Promise<unknown>;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
type NextHandler = (req: NextRequest) => Promise<NextResponse>;
|
package/dist/next.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { raceTimeout, HANDLER_TIMEOUT } from './chunk-
|
|
2
|
-
import
|
|
1
|
+
import { isJsonContentType, createPaymentGate, raceTimeout, HANDLER_TIMEOUT, SETTLE_AMOUNT_HEADER, resolveCharge, jsonFromResponse, invalidSettleAmountResponse, encodeBase64 } from './chunk-AENXD4OC.js';
|
|
2
|
+
import './chunk-AFRDHGDT.js';
|
|
3
3
|
import { NextResponse } from 'next/server';
|
|
4
4
|
|
|
5
5
|
// src/next/adapter.ts
|
|
@@ -20,6 +20,17 @@ var NextAdapter = class {
|
|
|
20
20
|
getUrl() {
|
|
21
21
|
return this.req.url;
|
|
22
22
|
}
|
|
23
|
+
// Read from a clone: a request body is a stream that can be consumed once,
|
|
24
|
+
// and the handler still needs the original.
|
|
25
|
+
async getBody() {
|
|
26
|
+
if (!isJsonContentType(this.req.headers.get("content-type") ?? void 0))
|
|
27
|
+
return void 0;
|
|
28
|
+
try {
|
|
29
|
+
return await this.req.clone().json();
|
|
30
|
+
} catch {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
23
34
|
};
|
|
24
35
|
|
|
25
36
|
// src/next/index.ts
|
|
@@ -41,7 +52,10 @@ function withPayment(config, handler) {
|
|
|
41
52
|
}
|
|
42
53
|
let response;
|
|
43
54
|
try {
|
|
44
|
-
const outcome = await raceTimeout(
|
|
55
|
+
const outcome = await raceTimeout(
|
|
56
|
+
handler(req),
|
|
57
|
+
gateResult.handlerTimeoutMs
|
|
58
|
+
);
|
|
45
59
|
if (outcome === HANDLER_TIMEOUT) {
|
|
46
60
|
return new NextResponse(null, { status: 504 });
|
|
47
61
|
}
|
|
@@ -49,9 +63,43 @@ function withPayment(config, handler) {
|
|
|
49
63
|
} catch {
|
|
50
64
|
return new NextResponse(null, { status: 504 });
|
|
51
65
|
}
|
|
66
|
+
let raw;
|
|
67
|
+
if (gateResult.scheme === "upto") {
|
|
68
|
+
raw = response.headers.get(SETTLE_AMOUNT_HEADER) ?? void 0;
|
|
69
|
+
if (raw !== void 0) {
|
|
70
|
+
const headers = new Headers(response.headers);
|
|
71
|
+
headers.delete(SETTLE_AMOUNT_HEADER);
|
|
72
|
+
response = new NextResponse(response.body, {
|
|
73
|
+
status: response.status,
|
|
74
|
+
headers
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
52
78
|
if (response.status >= 200 && response.status < 300) {
|
|
79
|
+
let settleOptions;
|
|
80
|
+
if (gateResult.scheme === "upto") {
|
|
81
|
+
const handled = response;
|
|
82
|
+
const resolved = await resolveCharge(gateResult, raw, {
|
|
83
|
+
status: handled.status,
|
|
84
|
+
header: (name) => handled.headers.get(name) ?? void 0,
|
|
85
|
+
// Read from a clone: the body streams once, to the client.
|
|
86
|
+
body: () => jsonFromResponse(handled)
|
|
87
|
+
});
|
|
88
|
+
if (resolved.kind === "invalid") {
|
|
89
|
+
handled.body?.cancel().catch(() => {
|
|
90
|
+
});
|
|
91
|
+
return NextResponse.json(
|
|
92
|
+
invalidSettleAmountResponse(resolved.reason),
|
|
93
|
+
{
|
|
94
|
+
status: 402
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (resolved.kind === "skip") return response;
|
|
99
|
+
settleOptions = { amount: resolved.amount };
|
|
100
|
+
}
|
|
53
101
|
try {
|
|
54
|
-
const settleResponse = await gateResult.settle();
|
|
102
|
+
const settleResponse = settleOptions ? await gateResult.settle(settleOptions) : await gateResult.settle();
|
|
55
103
|
if (settleResponse.success) {
|
|
56
104
|
const headers = new Headers(response.headers);
|
|
57
105
|
headers.set("payment-response", encodeBase64(settleResponse));
|
|
@@ -63,6 +111,8 @@ function withPayment(config, handler) {
|
|
|
63
111
|
}
|
|
64
112
|
} catch {
|
|
65
113
|
}
|
|
114
|
+
response.body?.cancel().catch(() => {
|
|
115
|
+
});
|
|
66
116
|
return NextResponse.json(
|
|
67
117
|
{
|
|
68
118
|
error: "PAYMENT_SETTLEMENT_FAILED",
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
|
|
3
|
+
interface FacilitatorConfig {
|
|
4
|
+
url: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What a per-request price function sees. `body` is the request body as the
|
|
9
|
+
* framework parsed it (JSON), or `undefined` when there is none.
|
|
10
|
+
*/
|
|
11
|
+
interface PriceContext {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
url: string;
|
|
15
|
+
header(name: string): string | undefined;
|
|
16
|
+
body: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Prices one request from its content. Called on the unpaid request to build
|
|
20
|
+
* the 402 and again on the paid retry, so it must be pure: same request, same
|
|
21
|
+
* price. Returns a price in the same format as a fixed `price`.
|
|
22
|
+
*/
|
|
23
|
+
type PriceFunction = (ctx: PriceContext) => string | bigint | Promise<string | bigint>;
|
|
24
|
+
/**
|
|
25
|
+
* What a meter function sees once the handler has answered: the response
|
|
26
|
+
* (`body` is its JSON as parsed by the middleware, `undefined` when it is not
|
|
27
|
+
* JSON) and the request as the price function saw it.
|
|
28
|
+
*/
|
|
29
|
+
interface MeterContext {
|
|
30
|
+
status: number;
|
|
31
|
+
header(name: string): string | undefined;
|
|
32
|
+
body: unknown;
|
|
33
|
+
request: PriceContext;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Names the amount a metered route charges, from the handler's response.
|
|
37
|
+
* Returns an amount in the same format as `price`, bounded by the cap;
|
|
38
|
+
* `"0"` serves the request for free; `undefined` leaves the decision to the
|
|
39
|
+
* `payment-settle-amount` header, then to the cap.
|
|
40
|
+
*/
|
|
41
|
+
type MeterFunction = (ctx: MeterContext) => string | bigint | undefined | null | Promise<string | bigint | undefined | null>;
|
|
42
|
+
interface RouteConfig {
|
|
43
|
+
/**
|
|
44
|
+
* A fixed amount (`"0.01"` or a bigint in the smallest unit), or a function
|
|
45
|
+
* of the request for resources priced per request.
|
|
46
|
+
*/
|
|
47
|
+
price: string | bigint | PriceFunction;
|
|
48
|
+
/**
|
|
49
|
+
* Metered routes only: reads the amount to charge from the handler's
|
|
50
|
+
* response instead of the `payment-settle-amount` header.
|
|
51
|
+
*/
|
|
52
|
+
meter?: MeterFunction;
|
|
53
|
+
decimals?: number;
|
|
54
|
+
network: string;
|
|
55
|
+
payTo: Address;
|
|
56
|
+
acceptedTokens?: Address[];
|
|
57
|
+
description?: string;
|
|
58
|
+
/**
|
|
59
|
+
* `exact` (default) charges `price` as invoiced. `upto` invoices `price` as a
|
|
60
|
+
* cap: the handler decides the actual amount through the
|
|
61
|
+
* `payment-settle-amount` response header and the remainder is refunded.
|
|
62
|
+
*/
|
|
63
|
+
scheme?: "exact" | "upto";
|
|
64
|
+
/**
|
|
65
|
+
* Settlement window the payer signs for, in seconds (default 300). Metered
|
|
66
|
+
* routes announce how long their handler may take; the facilitator caps it
|
|
67
|
+
* at 3600. The handler must finish comfortably before it expires.
|
|
68
|
+
*/
|
|
69
|
+
maxTimeoutSeconds?: number;
|
|
70
|
+
}
|
|
71
|
+
interface PaymentMiddlewareConfig {
|
|
72
|
+
facilitator: FacilitatorConfig;
|
|
73
|
+
routes: Record<string, RouteConfig>;
|
|
74
|
+
}
|
|
75
|
+
interface RunHandlerOptions {
|
|
76
|
+
/** Handler timeout for this request; defaults to the adapter's 30 s. */
|
|
77
|
+
timeoutMs?: number;
|
|
78
|
+
}
|
|
79
|
+
interface RunHandlerResult {
|
|
80
|
+
status: number;
|
|
81
|
+
setResponseHeader(name: string, value: string): void;
|
|
82
|
+
/** Reads a header the handler set on its response (metered routes). */
|
|
83
|
+
getResponseHeader?(name: string): string | undefined;
|
|
84
|
+
/** Strips a header before the response leaves (metered routes). */
|
|
85
|
+
removeResponseHeader?(name: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* The handler's response body as JSON, for routes with a `meter` function;
|
|
88
|
+
* `undefined` when the response is not JSON.
|
|
89
|
+
*/
|
|
90
|
+
getResponseBody?(): Promise<unknown>;
|
|
91
|
+
sendResponse(): void;
|
|
92
|
+
discardResponse(): void;
|
|
93
|
+
}
|
|
94
|
+
interface HTTPAdapter {
|
|
95
|
+
getHeader(name: string): string | undefined;
|
|
96
|
+
getMethod(): string;
|
|
97
|
+
getPath(): string;
|
|
98
|
+
getUrl(): string;
|
|
99
|
+
/** The parsed request body, for routes priced per request. */
|
|
100
|
+
getBody?(): Promise<unknown>;
|
|
101
|
+
runHandler?(options?: RunHandlerOptions): Promise<RunHandlerResult>;
|
|
102
|
+
}
|
|
103
|
+
interface ResourceInfo {
|
|
104
|
+
url: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
mimeType?: string;
|
|
107
|
+
}
|
|
108
|
+
interface PaymentRequirements {
|
|
109
|
+
scheme: string;
|
|
110
|
+
network: string;
|
|
111
|
+
asset: string;
|
|
112
|
+
amount: string;
|
|
113
|
+
payTo: string;
|
|
114
|
+
maxTimeoutSeconds: number;
|
|
115
|
+
extra: Record<string, unknown>;
|
|
116
|
+
}
|
|
117
|
+
interface PaymentRequired {
|
|
118
|
+
x402Version: number;
|
|
119
|
+
error?: string;
|
|
120
|
+
resource: ResourceInfo;
|
|
121
|
+
accepts: PaymentRequirements[];
|
|
122
|
+
extensions?: Record<string, unknown>;
|
|
123
|
+
}
|
|
124
|
+
interface FacilitatorPaymentRequirements {
|
|
125
|
+
maxAmountRequired: string;
|
|
126
|
+
asset: string;
|
|
127
|
+
payTo: string;
|
|
128
|
+
network: string;
|
|
129
|
+
scheme?: "exact" | "upto";
|
|
130
|
+
maxTimeoutSeconds?: number;
|
|
131
|
+
}
|
|
132
|
+
/** Settle-time options — only metered (`upto`) routes use them. */
|
|
133
|
+
interface SettleOptions {
|
|
134
|
+
/** Amount actually charged, in the asset's smallest unit. */
|
|
135
|
+
amount?: string;
|
|
136
|
+
}
|
|
137
|
+
interface PaymentConfirmation {
|
|
138
|
+
success: true;
|
|
139
|
+
txHash: Address;
|
|
140
|
+
route: string;
|
|
141
|
+
chain: string;
|
|
142
|
+
gasSponsored: boolean;
|
|
143
|
+
networkId: string;
|
|
144
|
+
/** Amount actually charged (smallest unit) — metered routes only. */
|
|
145
|
+
amountSettled?: string;
|
|
146
|
+
}
|
|
147
|
+
interface PaymentFailure {
|
|
148
|
+
success: false;
|
|
149
|
+
error: {
|
|
150
|
+
code: string;
|
|
151
|
+
message: string;
|
|
152
|
+
hint?: string;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
type FacilitatorResponse = PaymentConfirmation | PaymentFailure;
|
|
156
|
+
interface MiddlewareResult {
|
|
157
|
+
status: number;
|
|
158
|
+
headers: Record<string, string>;
|
|
159
|
+
body: unknown;
|
|
160
|
+
}
|
|
161
|
+
interface PassResult {
|
|
162
|
+
pass: true;
|
|
163
|
+
handlerRan?: true;
|
|
164
|
+
}
|
|
165
|
+
type VerifiedPayment = {
|
|
166
|
+
type: "verified";
|
|
167
|
+
scheme: "exact" | "upto";
|
|
168
|
+
/** The verified amount (smallest unit): the price, or the cap for `upto`. */
|
|
169
|
+
maxAmount: bigint;
|
|
170
|
+
decimals: number;
|
|
171
|
+
/** How long the handler may run before the middleware gives up on it. */
|
|
172
|
+
handlerTimeoutMs: number;
|
|
173
|
+
settle(options?: SettleOptions): Promise<FacilitatorResponse>;
|
|
174
|
+
/** The route's meter function, and the request it will be shown. */
|
|
175
|
+
meter?: MeterFunction;
|
|
176
|
+
request?: PriceContext;
|
|
177
|
+
};
|
|
178
|
+
type PaymentGateResult = {
|
|
179
|
+
type: "pass";
|
|
180
|
+
} | {
|
|
181
|
+
type: "error";
|
|
182
|
+
result: MiddlewareResult;
|
|
183
|
+
} | VerifiedPayment;
|
|
184
|
+
|
|
185
|
+
export type { FacilitatorConfig as F, HTTPAdapter as H, MiddlewareResult as M, PaymentMiddlewareConfig as P, RunHandlerOptions as R, SettleOptions as S, VerifiedPayment as V, RunHandlerResult as a, FacilitatorPaymentRequirements as b, FacilitatorResponse as c, PaymentGateResult as d, PassResult as e, MeterContext as f, MeterFunction as g, PaymentConfirmation as h, PaymentFailure as i, PaymentRequired as j, PaymentRequirements as k, PriceContext as l, PriceFunction as m, ResourceInfo as n, RouteConfig as o };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { Address } from 'viem';
|
|
2
|
+
|
|
3
|
+
interface FacilitatorConfig {
|
|
4
|
+
url: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What a per-request price function sees. `body` is the request body as the
|
|
9
|
+
* framework parsed it (JSON), or `undefined` when there is none.
|
|
10
|
+
*/
|
|
11
|
+
interface PriceContext {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
url: string;
|
|
15
|
+
header(name: string): string | undefined;
|
|
16
|
+
body: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Prices one request from its content. Called on the unpaid request to build
|
|
20
|
+
* the 402 and again on the paid retry, so it must be pure: same request, same
|
|
21
|
+
* price. Returns a price in the same format as a fixed `price`.
|
|
22
|
+
*/
|
|
23
|
+
type PriceFunction = (ctx: PriceContext) => string | bigint | Promise<string | bigint>;
|
|
24
|
+
/**
|
|
25
|
+
* What a meter function sees once the handler has answered: the response
|
|
26
|
+
* (`body` is its JSON as parsed by the middleware, `undefined` when it is not
|
|
27
|
+
* JSON) and the request as the price function saw it.
|
|
28
|
+
*/
|
|
29
|
+
interface MeterContext {
|
|
30
|
+
status: number;
|
|
31
|
+
header(name: string): string | undefined;
|
|
32
|
+
body: unknown;
|
|
33
|
+
request: PriceContext;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Names the amount a metered route charges, from the handler's response.
|
|
37
|
+
* Returns an amount in the same format as `price`, bounded by the cap;
|
|
38
|
+
* `"0"` serves the request for free; `undefined` leaves the decision to the
|
|
39
|
+
* `payment-settle-amount` header, then to the cap.
|
|
40
|
+
*/
|
|
41
|
+
type MeterFunction = (ctx: MeterContext) => string | bigint | undefined | null | Promise<string | bigint | undefined | null>;
|
|
42
|
+
interface RouteConfig {
|
|
43
|
+
/**
|
|
44
|
+
* A fixed amount (`"0.01"` or a bigint in the smallest unit), or a function
|
|
45
|
+
* of the request for resources priced per request.
|
|
46
|
+
*/
|
|
47
|
+
price: string | bigint | PriceFunction;
|
|
48
|
+
/**
|
|
49
|
+
* Metered routes only: reads the amount to charge from the handler's
|
|
50
|
+
* response instead of the `payment-settle-amount` header.
|
|
51
|
+
*/
|
|
52
|
+
meter?: MeterFunction;
|
|
53
|
+
decimals?: number;
|
|
54
|
+
network: string;
|
|
55
|
+
payTo: Address;
|
|
56
|
+
acceptedTokens?: Address[];
|
|
57
|
+
description?: string;
|
|
58
|
+
/**
|
|
59
|
+
* `exact` (default) charges `price` as invoiced. `upto` invoices `price` as a
|
|
60
|
+
* cap: the handler decides the actual amount through the
|
|
61
|
+
* `payment-settle-amount` response header and the remainder is refunded.
|
|
62
|
+
*/
|
|
63
|
+
scheme?: "exact" | "upto";
|
|
64
|
+
/**
|
|
65
|
+
* Settlement window the payer signs for, in seconds (default 300). Metered
|
|
66
|
+
* routes announce how long their handler may take; the facilitator caps it
|
|
67
|
+
* at 3600. The handler must finish comfortably before it expires.
|
|
68
|
+
*/
|
|
69
|
+
maxTimeoutSeconds?: number;
|
|
70
|
+
}
|
|
71
|
+
interface PaymentMiddlewareConfig {
|
|
72
|
+
facilitator: FacilitatorConfig;
|
|
73
|
+
routes: Record<string, RouteConfig>;
|
|
74
|
+
}
|
|
75
|
+
interface RunHandlerOptions {
|
|
76
|
+
/** Handler timeout for this request; defaults to the adapter's 30 s. */
|
|
77
|
+
timeoutMs?: number;
|
|
78
|
+
}
|
|
79
|
+
interface RunHandlerResult {
|
|
80
|
+
status: number;
|
|
81
|
+
setResponseHeader(name: string, value: string): void;
|
|
82
|
+
/** Reads a header the handler set on its response (metered routes). */
|
|
83
|
+
getResponseHeader?(name: string): string | undefined;
|
|
84
|
+
/** Strips a header before the response leaves (metered routes). */
|
|
85
|
+
removeResponseHeader?(name: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* The handler's response body as JSON, for routes with a `meter` function;
|
|
88
|
+
* `undefined` when the response is not JSON.
|
|
89
|
+
*/
|
|
90
|
+
getResponseBody?(): Promise<unknown>;
|
|
91
|
+
sendResponse(): void;
|
|
92
|
+
discardResponse(): void;
|
|
93
|
+
}
|
|
94
|
+
interface HTTPAdapter {
|
|
95
|
+
getHeader(name: string): string | undefined;
|
|
96
|
+
getMethod(): string;
|
|
97
|
+
getPath(): string;
|
|
98
|
+
getUrl(): string;
|
|
99
|
+
/** The parsed request body, for routes priced per request. */
|
|
100
|
+
getBody?(): Promise<unknown>;
|
|
101
|
+
runHandler?(options?: RunHandlerOptions): Promise<RunHandlerResult>;
|
|
102
|
+
}
|
|
103
|
+
interface ResourceInfo {
|
|
104
|
+
url: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
mimeType?: string;
|
|
107
|
+
}
|
|
108
|
+
interface PaymentRequirements {
|
|
109
|
+
scheme: string;
|
|
110
|
+
network: string;
|
|
111
|
+
asset: string;
|
|
112
|
+
amount: string;
|
|
113
|
+
payTo: string;
|
|
114
|
+
maxTimeoutSeconds: number;
|
|
115
|
+
extra: Record<string, unknown>;
|
|
116
|
+
}
|
|
117
|
+
interface PaymentRequired {
|
|
118
|
+
x402Version: number;
|
|
119
|
+
error?: string;
|
|
120
|
+
resource: ResourceInfo;
|
|
121
|
+
accepts: PaymentRequirements[];
|
|
122
|
+
extensions?: Record<string, unknown>;
|
|
123
|
+
}
|
|
124
|
+
interface FacilitatorPaymentRequirements {
|
|
125
|
+
maxAmountRequired: string;
|
|
126
|
+
asset: string;
|
|
127
|
+
payTo: string;
|
|
128
|
+
network: string;
|
|
129
|
+
scheme?: "exact" | "upto";
|
|
130
|
+
maxTimeoutSeconds?: number;
|
|
131
|
+
}
|
|
132
|
+
/** Settle-time options — only metered (`upto`) routes use them. */
|
|
133
|
+
interface SettleOptions {
|
|
134
|
+
/** Amount actually charged, in the asset's smallest unit. */
|
|
135
|
+
amount?: string;
|
|
136
|
+
}
|
|
137
|
+
interface PaymentConfirmation {
|
|
138
|
+
success: true;
|
|
139
|
+
txHash: Address;
|
|
140
|
+
route: string;
|
|
141
|
+
chain: string;
|
|
142
|
+
gasSponsored: boolean;
|
|
143
|
+
networkId: string;
|
|
144
|
+
/** Amount actually charged (smallest unit) — metered routes only. */
|
|
145
|
+
amountSettled?: string;
|
|
146
|
+
}
|
|
147
|
+
interface PaymentFailure {
|
|
148
|
+
success: false;
|
|
149
|
+
error: {
|
|
150
|
+
code: string;
|
|
151
|
+
message: string;
|
|
152
|
+
hint?: string;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
type FacilitatorResponse = PaymentConfirmation | PaymentFailure;
|
|
156
|
+
interface MiddlewareResult {
|
|
157
|
+
status: number;
|
|
158
|
+
headers: Record<string, string>;
|
|
159
|
+
body: unknown;
|
|
160
|
+
}
|
|
161
|
+
interface PassResult {
|
|
162
|
+
pass: true;
|
|
163
|
+
handlerRan?: true;
|
|
164
|
+
}
|
|
165
|
+
type VerifiedPayment = {
|
|
166
|
+
type: "verified";
|
|
167
|
+
scheme: "exact" | "upto";
|
|
168
|
+
/** The verified amount (smallest unit): the price, or the cap for `upto`. */
|
|
169
|
+
maxAmount: bigint;
|
|
170
|
+
decimals: number;
|
|
171
|
+
/** How long the handler may run before the middleware gives up on it. */
|
|
172
|
+
handlerTimeoutMs: number;
|
|
173
|
+
settle(options?: SettleOptions): Promise<FacilitatorResponse>;
|
|
174
|
+
/** The route's meter function, and the request it will be shown. */
|
|
175
|
+
meter?: MeterFunction;
|
|
176
|
+
request?: PriceContext;
|
|
177
|
+
};
|
|
178
|
+
type PaymentGateResult = {
|
|
179
|
+
type: "pass";
|
|
180
|
+
} | {
|
|
181
|
+
type: "error";
|
|
182
|
+
result: MiddlewareResult;
|
|
183
|
+
} | VerifiedPayment;
|
|
184
|
+
|
|
185
|
+
export type { FacilitatorConfig as F, HTTPAdapter as H, MiddlewareResult as M, PaymentMiddlewareConfig as P, RunHandlerOptions as R, SettleOptions as S, VerifiedPayment as V, RunHandlerResult as a, FacilitatorPaymentRequirements as b, FacilitatorResponse as c, PaymentGateResult as d, PassResult as e, MeterContext as f, MeterFunction as g, PaymentConfirmation as h, PaymentFailure as i, PaymentRequired as j, PaymentRequirements as k, PriceContext as l, PriceFunction as m, ResourceInfo as n, RouteConfig as o };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parallel-protocol/x402",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Parallel Protocol x402 payment middleware — Express, Next.js, Fastify, Hono",
|
|
5
5
|
"author": "Parallel Protocol <contact@parallel.best>",
|
|
6
6
|
"repository": {
|
|
@@ -69,6 +69,16 @@
|
|
|
69
69
|
"default": "./dist/hono.cjs"
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
|
+
"./llm": {
|
|
73
|
+
"import": {
|
|
74
|
+
"types": "./dist/llm.d.ts",
|
|
75
|
+
"default": "./dist/llm.js"
|
|
76
|
+
},
|
|
77
|
+
"require": {
|
|
78
|
+
"types": "./dist/llm.d.cts",
|
|
79
|
+
"default": "./dist/llm.cjs"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
72
82
|
"./package.json": "./package.json"
|
|
73
83
|
},
|
|
74
84
|
"files": [
|
|
@@ -123,7 +133,7 @@
|
|
|
123
133
|
"vitest": "^4.0.14"
|
|
124
134
|
},
|
|
125
135
|
"dependencies": {
|
|
126
|
-
"@parallel-protocol/chains": "^0.
|
|
136
|
+
"@parallel-protocol/chains": "^0.4.0",
|
|
127
137
|
"fastify-plugin": "^6.0.0",
|
|
128
138
|
"zod": "^4.4.3"
|
|
129
139
|
},
|
package/dist/chunk-2UEAVMCH.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// src/timeout.ts
|
|
2
|
-
var HANDLER_TIMEOUT_MS = 3e4;
|
|
3
|
-
var HANDLER_TIMEOUT = /* @__PURE__ */ Symbol("x402:handler-timeout");
|
|
4
|
-
async function raceTimeout(promise, ms = HANDLER_TIMEOUT_MS) {
|
|
5
|
-
let timer;
|
|
6
|
-
const timeout = new Promise((resolve) => {
|
|
7
|
-
timer = setTimeout(() => resolve(HANDLER_TIMEOUT), ms);
|
|
8
|
-
timer.unref?.();
|
|
9
|
-
});
|
|
10
|
-
try {
|
|
11
|
-
return await Promise.race([promise, timeout]);
|
|
12
|
-
} finally {
|
|
13
|
-
clearTimeout(timer);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export { HANDLER_TIMEOUT, raceTimeout };
|