@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/dist/hono.js CHANGED
@@ -1,5 +1,5 @@
1
- import { raceTimeout, HANDLER_TIMEOUT } from './chunk-2UEAVMCH.js';
2
- import { createPaymentMiddleware } from './chunk-75GLDK7L.js';
1
+ import { isJsonContentType, raceTimeout, HANDLER_TIMEOUT, jsonFromResponse, createPaymentMiddleware } from './chunk-AENXD4OC.js';
2
+ import './chunk-AFRDHGDT.js';
3
3
 
4
4
  // src/hono/adapter.ts
5
5
  var TIMEOUT_BODY = JSON.stringify({
@@ -25,13 +25,26 @@ var HonoAdapter = class {
25
25
  getUrl() {
26
26
  return this.c.req.url;
27
27
  }
28
- async runHandler() {
29
- const outcome = await raceTimeout(this.next());
28
+ // Hono caches the parsed body on the request, so the handler can still read
29
+ // it after the price function did.
30
+ async getBody() {
31
+ if (!isJsonContentType(this.c.req.header("content-type"))) return void 0;
32
+ try {
33
+ return await this.c.req.json();
34
+ } catch {
35
+ return void 0;
36
+ }
37
+ }
38
+ async runHandler(options) {
39
+ const outcome = await raceTimeout(this.next(), options?.timeoutMs);
30
40
  if (outcome === HANDLER_TIMEOUT) {
31
41
  return {
32
42
  status: 504,
33
43
  setResponseHeader: () => {
34
44
  },
45
+ getResponseHeader: () => void 0,
46
+ removeResponseHeader: () => {
47
+ },
35
48
  sendResponse: () => {
36
49
  this.c.res = new Response(TIMEOUT_BODY, {
37
50
  status: 504,
@@ -46,9 +59,17 @@ var HonoAdapter = class {
46
59
  return {
47
60
  status: res.status,
48
61
  setResponseHeader: (name, value) => res.headers.set(name, value),
62
+ getResponseHeader: (name) => res.headers.get(name) ?? void 0,
63
+ removeResponseHeader: (name) => res.headers.delete(name),
64
+ // Read from a clone: the response body streams once, to the client.
65
+ getResponseBody: () => jsonFromResponse(res),
49
66
  sendResponse: () => {
50
67
  },
68
+ // The response is replaced: release its body (and whatever upstream
69
+ // stream feeds it) instead of leaving it open until collected.
51
70
  discardResponse: () => {
71
+ res.body?.cancel().catch(() => {
72
+ });
52
73
  }
53
74
  };
54
75
  }
package/dist/index.cjs CHANGED
@@ -1,54 +1,75 @@
1
1
  'use strict';
2
2
 
3
- var chunkKQPIZ6SZ_cjs = require('./chunk-KQPIZ6SZ.cjs');
3
+ var chunkPOU7EH3E_cjs = require('./chunk-POU7EH3E.cjs');
4
+ var chunkJPMK5YBU_cjs = require('./chunk-JPMK5YBU.cjs');
4
5
 
5
6
 
6
7
 
7
8
  Object.defineProperty(exports, "FacilitatorClient", {
8
9
  enumerable: true,
9
- get: function () { return chunkKQPIZ6SZ_cjs.FacilitatorClient; }
10
+ get: function () { return chunkPOU7EH3E_cjs.FacilitatorClient; }
10
11
  });
11
12
  Object.defineProperty(exports, "PARALLEL_TOKENS", {
12
13
  enumerable: true,
13
- get: function () { return chunkKQPIZ6SZ_cjs.PARALLEL_TOKENS; }
14
+ get: function () { return chunkPOU7EH3E_cjs.PARALLEL_TOKENS; }
14
15
  });
15
- Object.defineProperty(exports, "X402ConfigError", {
16
- enumerable: true,
17
- get: function () { return chunkKQPIZ6SZ_cjs.X402ConfigError; }
18
- });
19
- Object.defineProperty(exports, "X402RuntimeError", {
20
- enumerable: true,
21
- get: function () { return chunkKQPIZ6SZ_cjs.X402RuntimeError; }
22
- });
23
- Object.defineProperty(exports, "X402_ERROR_CODES", {
16
+ Object.defineProperty(exports, "SETTLE_AMOUNT_HEADER", {
24
17
  enumerable: true,
25
- get: function () { return chunkKQPIZ6SZ_cjs.X402_ERROR_CODES; }
18
+ get: function () { return chunkPOU7EH3E_cjs.SETTLE_AMOUNT_HEADER; }
26
19
  });
27
20
  Object.defineProperty(exports, "createPaymentGate", {
28
21
  enumerable: true,
29
- get: function () { return chunkKQPIZ6SZ_cjs.createPaymentGate; }
22
+ get: function () { return chunkPOU7EH3E_cjs.createPaymentGate; }
30
23
  });
31
24
  Object.defineProperty(exports, "createPaymentMiddleware", {
32
25
  enumerable: true,
33
- get: function () { return chunkKQPIZ6SZ_cjs.createPaymentMiddleware; }
26
+ get: function () { return chunkPOU7EH3E_cjs.createPaymentMiddleware; }
34
27
  });
35
28
  Object.defineProperty(exports, "encodeBase64", {
36
29
  enumerable: true,
37
- get: function () { return chunkKQPIZ6SZ_cjs.encodeBase64; }
30
+ get: function () { return chunkPOU7EH3E_cjs.encodeBase64; }
38
31
  });
39
32
  Object.defineProperty(exports, "getDefaultAcceptedTokens", {
40
33
  enumerable: true,
41
- get: function () { return chunkKQPIZ6SZ_cjs.getDefaultAcceptedTokens; }
34
+ get: function () { return chunkPOU7EH3E_cjs.getDefaultAcceptedTokens; }
42
35
  });
43
36
  Object.defineProperty(exports, "parsePrice", {
44
37
  enumerable: true,
45
- get: function () { return chunkKQPIZ6SZ_cjs.parsePrice; }
38
+ get: function () { return chunkPOU7EH3E_cjs.parsePrice; }
39
+ });
40
+ Object.defineProperty(exports, "resolveCharge", {
41
+ enumerable: true,
42
+ get: function () { return chunkPOU7EH3E_cjs.resolveCharge; }
43
+ });
44
+ Object.defineProperty(exports, "resolveSettleAmount", {
45
+ enumerable: true,
46
+ get: function () { return chunkPOU7EH3E_cjs.resolveSettleAmount; }
46
47
  });
47
48
  Object.defineProperty(exports, "toEip155Network", {
48
49
  enumerable: true,
49
- get: function () { return chunkKQPIZ6SZ_cjs.toEip155Network; }
50
+ get: function () { return chunkPOU7EH3E_cjs.toEip155Network; }
50
51
  });
51
52
  Object.defineProperty(exports, "validateAddress", {
52
53
  enumerable: true,
53
- get: function () { return chunkKQPIZ6SZ_cjs.validateAddress; }
54
+ get: function () { return chunkPOU7EH3E_cjs.validateAddress; }
55
+ });
56
+ Object.defineProperty(exports, "X402ConfigError", {
57
+ enumerable: true,
58
+ get: function () { return chunkJPMK5YBU_cjs.X402ConfigError; }
59
+ });
60
+ Object.defineProperty(exports, "X402PriceRejectedError", {
61
+ enumerable: true,
62
+ get: function () { return chunkJPMK5YBU_cjs.X402PriceRejectedError; }
63
+ });
64
+ Object.defineProperty(exports, "X402RuntimeError", {
65
+ enumerable: true,
66
+ get: function () { return chunkJPMK5YBU_cjs.X402RuntimeError; }
67
+ });
68
+ Object.defineProperty(exports, "X402_ERROR_CODES", {
69
+ enumerable: true,
70
+ get: function () { return chunkJPMK5YBU_cjs.X402_ERROR_CODES; }
71
+ });
72
+ Object.defineProperty(exports, "isPriceRejection", {
73
+ enumerable: true,
74
+ get: function () { return chunkJPMK5YBU_cjs.isPriceRejection; }
54
75
  });
package/dist/index.d.cts CHANGED
@@ -1,12 +1,12 @@
1
- import { F as FacilitatorConfig, a as FacilitatorPaymentRequirements, b as FacilitatorResponse, P as PaymentMiddlewareConfig, H as HTTPAdapter, c as PaymentGateResult, M as MiddlewareResult, d as PassResult } from './types-CUi55YSx.cjs';
2
- export { e as PaymentConfirmation, f as PaymentFailure, g as PaymentRequired, h as PaymentRequirements, i as ResourceInfo, j as RouteConfig, R as RunHandlerResult } from './types-CUi55YSx.cjs';
1
+ import { F as FacilitatorConfig, b as FacilitatorPaymentRequirements, S as SettleOptions, c as FacilitatorResponse, P as PaymentMiddlewareConfig, H as HTTPAdapter, d as PaymentGateResult, M as MiddlewareResult, e as PassResult, V as VerifiedPayment } from './types-q_gu5wjz.cjs';
2
+ export { f as MeterContext, g as MeterFunction, h as PaymentConfirmation, i as PaymentFailure, j as PaymentRequired, k as PaymentRequirements, l as PriceContext, m as PriceFunction, n as ResourceInfo, o as RouteConfig, R as RunHandlerOptions, a as RunHandlerResult } from './types-q_gu5wjz.cjs';
3
3
  import { Address } from 'viem';
4
4
 
5
5
  declare class FacilitatorClient {
6
6
  private readonly config;
7
7
  constructor(config: FacilitatorConfig);
8
8
  verify(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements): Promise<void>;
9
- settle(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements): Promise<FacilitatorResponse>;
9
+ settle(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements, options?: SettleOptions): Promise<FacilitatorResponse>;
10
10
  pay(paymentHeader: string): Promise<FacilitatorResponse>;
11
11
  private buildHeaders;
12
12
  }
@@ -24,8 +24,67 @@ declare class X402RuntimeError extends Error {
24
24
  readonly code: string;
25
25
  constructor(code: string);
26
26
  }
27
+ /**
28
+ * Thrown by a per-request price function to refuse a request before anything
29
+ * is invoiced or signed: the middleware answers with `status` and a JSON body
30
+ * `{ error: code, message }`. For requests the route will not serve (an
31
+ * unknown model, an unsupported option) rather than merchant bugs.
32
+ */
33
+ declare class X402PriceRejectedError extends Error {
34
+ readonly code: string;
35
+ readonly status: number;
36
+ constructor(code: string, message: string, status?: number);
37
+ }
38
+ /**
39
+ * Recognises a price refusal by shape rather than by class identity, so a
40
+ * refusal thrown from another copy of this package (a nested install, the
41
+ * CommonJS build next to the ESM one) is still answered as a refusal.
42
+ */
43
+ declare function isPriceRejection(error: unknown): error is X402PriceRejectedError;
27
44
 
28
- declare function createPaymentGate(config: PaymentMiddlewareConfig): (adapter: Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod">) => Promise<PaymentGateResult>;
45
+ type GateAdapter = Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod" | "getBody">;
46
+ /**
47
+ * Response header a handler on a metered (`upto`) route sets to the amount it
48
+ * actually charges, in whole token units like `price` ("0.75"). Read and
49
+ * stripped by the middleware before the response leaves. Absent → the cap is
50
+ * charged; "0" → the request is served for free (no settlement).
51
+ */
52
+ declare const SETTLE_AMOUNT_HEADER = "payment-settle-amount";
53
+ type SettleAmountResolution = {
54
+ kind: "settle";
55
+ amount: string;
56
+ } | {
57
+ kind: "skip";
58
+ } | {
59
+ kind: "invalid";
60
+ reason: "malformed" | "precision" | "above-cap" | "meter";
61
+ };
62
+ /**
63
+ * Turns the handler's `payment-settle-amount` header into a settle decision.
64
+ * A malformed value, one carrying more decimals than the token has, or one
65
+ * above the signed cap is a merchant bug: the payment fails closed rather than
66
+ * charging something the handler did not mean. Only an explicit zero skips
67
+ * the settlement — a positive amount the token cannot represent is never
68
+ * silently served for free.
69
+ */
70
+ declare function resolveSettleAmount(raw: string | undefined, maxAmount: bigint, decimals: number): SettleAmountResolution;
71
+ /** What the middleware can read from the handler's response. */
72
+ interface ChargeResponse {
73
+ status: number;
74
+ header(name: string): string | undefined;
75
+ body(): Promise<unknown>;
76
+ }
77
+ /**
78
+ * The amount a metered route settles, once the handler answered with a 2xx.
79
+ * A `meter` function on the route decides first, from the response: its
80
+ * amount is bounded by the cap (an overrun is the merchant's loss, not a
81
+ * refused response), zero serves for free, and no amount hands over to the
82
+ * `payment-settle-amount` header, which keeps its rules (absent charges the
83
+ * cap, above the cap is refused). A meter that throws or returns something
84
+ * that is not an amount fails closed like an invalid header.
85
+ */
86
+ declare function resolveCharge(verified: VerifiedPayment, settleHeader: string | undefined, response: ChargeResponse): Promise<SettleAmountResolution>;
87
+ declare function createPaymentGate(config: PaymentMiddlewareConfig): (adapter: GateAdapter) => Promise<PaymentGateResult>;
29
88
  declare function createPaymentMiddleware(config: PaymentMiddlewareConfig): (adapter: HTTPAdapter) => Promise<MiddlewareResult | PassResult>;
30
89
 
31
90
  type ParallelNetwork = "ethereum" | "base" | "avalanche" | "hyperevm";
@@ -49,4 +108,4 @@ declare function validateAddress(address: string): address is Address;
49
108
  declare function toEip155Network(network: string): string;
50
109
  declare function encodeBase64(obj: unknown): string;
51
110
 
52
- export { FacilitatorClient, FacilitatorConfig, FacilitatorPaymentRequirements, FacilitatorResponse, HTTPAdapter, MiddlewareResult, PARALLEL_TOKENS, type ParallelNetwork, PassResult, PaymentGateResult, PaymentMiddlewareConfig, X402ConfigError, type X402ErrorCode, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, toEip155Network, validateAddress };
111
+ export { type ChargeResponse, FacilitatorClient, FacilitatorConfig, FacilitatorPaymentRequirements, FacilitatorResponse, HTTPAdapter, MiddlewareResult, PARALLEL_TOKENS, type ParallelNetwork, PassResult, PaymentGateResult, PaymentMiddlewareConfig, SETTLE_AMOUNT_HEADER, type SettleAmountResolution, SettleOptions, VerifiedPayment, X402ConfigError, type X402ErrorCode, X402PriceRejectedError, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, isPriceRejection, parsePrice, resolveCharge, resolveSettleAmount, toEip155Network, validateAddress };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { F as FacilitatorConfig, a as FacilitatorPaymentRequirements, b as FacilitatorResponse, P as PaymentMiddlewareConfig, H as HTTPAdapter, c as PaymentGateResult, M as MiddlewareResult, d as PassResult } from './types-CUi55YSx.js';
2
- export { e as PaymentConfirmation, f as PaymentFailure, g as PaymentRequired, h as PaymentRequirements, i as ResourceInfo, j as RouteConfig, R as RunHandlerResult } from './types-CUi55YSx.js';
1
+ import { F as FacilitatorConfig, b as FacilitatorPaymentRequirements, S as SettleOptions, c as FacilitatorResponse, P as PaymentMiddlewareConfig, H as HTTPAdapter, d as PaymentGateResult, M as MiddlewareResult, e as PassResult, V as VerifiedPayment } from './types-q_gu5wjz.js';
2
+ export { f as MeterContext, g as MeterFunction, h as PaymentConfirmation, i as PaymentFailure, j as PaymentRequired, k as PaymentRequirements, l as PriceContext, m as PriceFunction, n as ResourceInfo, o as RouteConfig, R as RunHandlerOptions, a as RunHandlerResult } from './types-q_gu5wjz.js';
3
3
  import { Address } from 'viem';
4
4
 
5
5
  declare class FacilitatorClient {
6
6
  private readonly config;
7
7
  constructor(config: FacilitatorConfig);
8
8
  verify(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements): Promise<void>;
9
- settle(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements): Promise<FacilitatorResponse>;
9
+ settle(paymentHeader: string, paymentRequirements: FacilitatorPaymentRequirements, options?: SettleOptions): Promise<FacilitatorResponse>;
10
10
  pay(paymentHeader: string): Promise<FacilitatorResponse>;
11
11
  private buildHeaders;
12
12
  }
@@ -24,8 +24,67 @@ declare class X402RuntimeError extends Error {
24
24
  readonly code: string;
25
25
  constructor(code: string);
26
26
  }
27
+ /**
28
+ * Thrown by a per-request price function to refuse a request before anything
29
+ * is invoiced or signed: the middleware answers with `status` and a JSON body
30
+ * `{ error: code, message }`. For requests the route will not serve (an
31
+ * unknown model, an unsupported option) rather than merchant bugs.
32
+ */
33
+ declare class X402PriceRejectedError extends Error {
34
+ readonly code: string;
35
+ readonly status: number;
36
+ constructor(code: string, message: string, status?: number);
37
+ }
38
+ /**
39
+ * Recognises a price refusal by shape rather than by class identity, so a
40
+ * refusal thrown from another copy of this package (a nested install, the
41
+ * CommonJS build next to the ESM one) is still answered as a refusal.
42
+ */
43
+ declare function isPriceRejection(error: unknown): error is X402PriceRejectedError;
27
44
 
28
- declare function createPaymentGate(config: PaymentMiddlewareConfig): (adapter: Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod">) => Promise<PaymentGateResult>;
45
+ type GateAdapter = Pick<HTTPAdapter, "getHeader" | "getPath" | "getUrl" | "getMethod" | "getBody">;
46
+ /**
47
+ * Response header a handler on a metered (`upto`) route sets to the amount it
48
+ * actually charges, in whole token units like `price` ("0.75"). Read and
49
+ * stripped by the middleware before the response leaves. Absent → the cap is
50
+ * charged; "0" → the request is served for free (no settlement).
51
+ */
52
+ declare const SETTLE_AMOUNT_HEADER = "payment-settle-amount";
53
+ type SettleAmountResolution = {
54
+ kind: "settle";
55
+ amount: string;
56
+ } | {
57
+ kind: "skip";
58
+ } | {
59
+ kind: "invalid";
60
+ reason: "malformed" | "precision" | "above-cap" | "meter";
61
+ };
62
+ /**
63
+ * Turns the handler's `payment-settle-amount` header into a settle decision.
64
+ * A malformed value, one carrying more decimals than the token has, or one
65
+ * above the signed cap is a merchant bug: the payment fails closed rather than
66
+ * charging something the handler did not mean. Only an explicit zero skips
67
+ * the settlement — a positive amount the token cannot represent is never
68
+ * silently served for free.
69
+ */
70
+ declare function resolveSettleAmount(raw: string | undefined, maxAmount: bigint, decimals: number): SettleAmountResolution;
71
+ /** What the middleware can read from the handler's response. */
72
+ interface ChargeResponse {
73
+ status: number;
74
+ header(name: string): string | undefined;
75
+ body(): Promise<unknown>;
76
+ }
77
+ /**
78
+ * The amount a metered route settles, once the handler answered with a 2xx.
79
+ * A `meter` function on the route decides first, from the response: its
80
+ * amount is bounded by the cap (an overrun is the merchant's loss, not a
81
+ * refused response), zero serves for free, and no amount hands over to the
82
+ * `payment-settle-amount` header, which keeps its rules (absent charges the
83
+ * cap, above the cap is refused). A meter that throws or returns something
84
+ * that is not an amount fails closed like an invalid header.
85
+ */
86
+ declare function resolveCharge(verified: VerifiedPayment, settleHeader: string | undefined, response: ChargeResponse): Promise<SettleAmountResolution>;
87
+ declare function createPaymentGate(config: PaymentMiddlewareConfig): (adapter: GateAdapter) => Promise<PaymentGateResult>;
29
88
  declare function createPaymentMiddleware(config: PaymentMiddlewareConfig): (adapter: HTTPAdapter) => Promise<MiddlewareResult | PassResult>;
30
89
 
31
90
  type ParallelNetwork = "ethereum" | "base" | "avalanche" | "hyperevm";
@@ -49,4 +108,4 @@ declare function validateAddress(address: string): address is Address;
49
108
  declare function toEip155Network(network: string): string;
50
109
  declare function encodeBase64(obj: unknown): string;
51
110
 
52
- export { FacilitatorClient, FacilitatorConfig, FacilitatorPaymentRequirements, FacilitatorResponse, HTTPAdapter, MiddlewareResult, PARALLEL_TOKENS, type ParallelNetwork, PassResult, PaymentGateResult, PaymentMiddlewareConfig, X402ConfigError, type X402ErrorCode, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, toEip155Network, validateAddress };
111
+ export { type ChargeResponse, FacilitatorClient, FacilitatorConfig, FacilitatorPaymentRequirements, FacilitatorResponse, HTTPAdapter, MiddlewareResult, PARALLEL_TOKENS, type ParallelNetwork, PassResult, PaymentGateResult, PaymentMiddlewareConfig, SETTLE_AMOUNT_HEADER, type SettleAmountResolution, SettleOptions, VerifiedPayment, X402ConfigError, type X402ErrorCode, X402PriceRejectedError, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, isPriceRejection, parsePrice, resolveCharge, resolveSettleAmount, toEip155Network, validateAddress };
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- export { FacilitatorClient, PARALLEL_TOKENS, X402ConfigError, X402RuntimeError, X402_ERROR_CODES, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, toEip155Network, validateAddress } from './chunk-75GLDK7L.js';
1
+ export { FacilitatorClient, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, resolveCharge, resolveSettleAmount, toEip155Network, validateAddress } from './chunk-AENXD4OC.js';
2
+ export { X402ConfigError, X402PriceRejectedError, X402RuntimeError, X402_ERROR_CODES, isPriceRejection } from './chunk-AFRDHGDT.js';