@lunora/x402 1.0.0-alpha.3 → 1.0.0-alpha.5

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.
@@ -1,5 +1,5 @@
1
- import { F as FacilitatorConfig, c as X402ChargeConfig, f as X402Price } from "../packem_shared/config.d-D8gKQLAq.mjs";
2
- export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, type a as EvmAddress, type P as PaymentEventRow, type d as X402Network, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2, x as toPaymentEventRow, y as toReceipt } from "../packem_shared/config.d-D8gKQLAq.mjs";
1
+ import { F as FacilitatorConfig, c as X402ChargeConfig, f as X402Price } from "../packem_shared/config.d-B-NYmHgG.mjs";
2
+ export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, type a as EvmAddress, type P as PaymentEventRow, type d as X402Network, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2, x as toPaymentEventRow, y as toReceipt } from "../packem_shared/config.d-B-NYmHgG.mjs";
3
3
  import { HTTPFacilitatorClient } from '@x402/core/server';
4
4
  import { RouteConfig } from '@x402/core/http';
5
5
  import '@x402/evm';
@@ -7,68 +7,106 @@ import '@x402/svm';
7
7
  import '@x402/core/client';
8
8
  import '@x402/core/types';
9
9
  /**
10
- * Build an `@x402/core` facilitator client from Lunora's {@link FacilitatorConfig}.
11
- *
12
- * `config.headers` (e.g. a CDP bearer token) are applied to every facilitator
13
- * call — `@x402/core` splits auth per endpoint (`verify` / `settle` /
14
- * `supported`), so the same header map is handed to each. With no config the
15
- * client points at the public {@link resolveFacilitatorUrl default} and sends no
16
- * auth headers.
17
- * @experimental
18
- */
10
+ * Build an `@x402/core` facilitator client from Lunora's {@link FacilitatorConfig}.
11
+ *
12
+ * `config.headers` (e.g. a CDP bearer token) are applied to every facilitator
13
+ * call — `@x402/core` splits auth per endpoint (`verify` / `settle` /
14
+ * `supported`), so the same header map is handed to each. With no config the
15
+ * client points at the public {@link resolveFacilitatorUrl default} and sends no
16
+ * auth headers.
17
+ * @experimental
18
+ */
19
19
  declare const createFacilitatorClient: (config?: FacilitatorConfig) => HTTPFacilitatorClient;
20
20
  /**
21
- * A handler shaped like a Lunora HTTP action: `(context, request) => Response`.
22
- * @experimental
23
- */
21
+ * A handler shaped like a Lunora HTTP action: `(context, request) => Response`.
22
+ * @experimental
23
+ */
24
24
  type HttpActionHandler<Context> = (context: Context, request: Request) => Promise<Response> | Response;
25
25
  /**
26
- * Gate `handler` behind an x402 paywall described by `config`. Returns a handler
27
- * of the same shape, ready to pass to `httpAction`.
28
- * @experimental
29
- */
26
+ * Gate `handler` behind an x402 paywall described by `config`. Returns a handler
27
+ * of the same shape, ready to pass to `httpAction`.
28
+ * @experimental
29
+ */
30
30
  declare const withX402: <Context>(config: X402ChargeConfig, handler: HttpActionHandler<Context>) => HttpActionHandler<Context>;
31
31
  /**
32
- * Runs the protected resource handler, producing the Response to gate.
33
- * @experimental
34
- */
32
+ * Runs the protected resource handler, producing the Response to gate.
33
+ * @experimental
34
+ */
35
35
  type ChargeHandler = () => Promise<Response> | Response;
36
36
  /**
37
- * A prepared, initialised paywall. Build once (it fetches facilitator support), reuse per request.
38
- * @experimental
39
- */
37
+ * Per-request platform seams `handle` can use, beyond the request/handler pair.
38
+ * @experimental
39
+ */
40
+ interface ChargeHandlerDeps {
41
+ /**
42
+ * Keep background work (the receipt sink) alive past the response — the
43
+ * request's `ctx.waitUntil`. Absent on paths with no platform execution
44
+ * context reaching the middleware (e.g. today's HTTP-action rail).
45
+ */
46
+ readonly waitUntil?: (promise: Promise<unknown>) => void;
47
+ }
48
+ /**
49
+ * A prepared, initialised paywall. Build once (it fetches facilitator support), reuse per request.
50
+ * @experimental
51
+ */
40
52
  interface ChargeMiddleware {
41
53
  /** Gate `request`: challenge / verify / settle around `runHandler`. */
42
- handle: (request: Request, runHandler: ChargeHandler) => Promise<Response>;
54
+ handle: (request: Request, runHandler: ChargeHandler, deps?: ChargeHandlerDeps) => Promise<Response>;
43
55
  }
44
56
  /**
45
- * Route metadata a caller can layer onto the generated catch-all route. The
46
- * procedure gate sets `resource` to the `functionPath` so the x402 challenge
47
- * names the paid function (x402 core falls back to the request URL otherwise —
48
- * every RPC POSTs to the same `/_lunora/rpc`, so the URL can't tell two paid
49
- * procedures apart).
50
- * @experimental
51
- */
57
+ * Route metadata a caller can layer onto the generated catch-all route. The
58
+ * procedure gate sets `resource` to the `functionPath` so the x402 challenge
59
+ * names the paid function (x402 core falls back to the request URL otherwise —
60
+ * every RPC POSTs to the same `/_lunora/rpc`, so the URL can't tell two paid
61
+ * procedures apart).
62
+ * @experimental
63
+ */
52
64
  type ChargeRouteOverrides = Pick<RouteConfig, "description" | "resource">;
53
65
  /**
54
- * Build and initialise a {@link ChargeMiddleware} for `config`. Fetches
55
- * facilitator support once (via `initialize()`), so call this once per config
56
- * and reuse the result across requests. `routeOverrides` layers extra route
57
- * metadata (e.g. `resource`) onto the generated catch-all route.
58
- * @experimental
59
- */
60
- declare const createChargeMiddleware: (config: X402ChargeConfig, routeOverrides?: ChargeRouteOverrides) => Promise<ChargeMiddleware>;
66
+ * Behaviour knobs for {@link createChargeMiddleware} beyond route metadata.
67
+ * @experimental
68
+ */
69
+ interface ChargeMiddlewareOptions {
70
+ /**
71
+ * Settle the verified payment **before** dispatching `runHandler`, instead
72
+ * of after. Use this for a mutation/procedure gate: a settlement failure
73
+ * then means the handler never runs at all, so a paid mutation's writes can
74
+ * never be committed without payment (the free-execution gap X402-04
75
+ * closes). Once settlement succeeds the payment is final (on-chain) — a
76
+ * handler failure after that point is a normal application error, not a
77
+ * payment to unwind: there is nothing left to cancel, so it is not caught
78
+ * here and simply propagates.
79
+ *
80
+ * Default `false` (settle-after, the historical behaviour): the handler's
81
+ * response is passed to settlement as transport context (`responseHeaders`
82
+ * — read by some schemes for settlement overrides), and a handler throw
83
+ * still releases the verified-but-unsettled payment via
84
+ * `cancellationDispatcher.cancel`. Because settlement can still fail after
85
+ * the handler already ran on this path, `.x402()` handlers gated this way
86
+ * MUST be idempotent or compensatable — see the `@lunora/x402` charge docs.
87
+ */
88
+ readonly settleBeforeHandler?: boolean;
89
+ }
90
+ /**
91
+ * Build and initialise a {@link ChargeMiddleware} for `config`. Fetches
92
+ * facilitator support once (via `initialize()`), so call this once per config
93
+ * and reuse the result across requests. `routeOverrides` layers extra route
94
+ * metadata (e.g. `resource`) onto the generated catch-all route; `options`
95
+ * controls settlement ordering (see {@link ChargeMiddlewareOptions}).
96
+ * @experimental
97
+ */
98
+ declare const createChargeMiddleware: (config: X402ChargeConfig, routeOverrides?: ChargeRouteOverrides, options?: ChargeMiddlewareOptions) => Promise<ChargeMiddleware>;
61
99
  /**
62
- * Charge config for the procedure gate: the worker-level settlement vocabulary
63
- * (network, recipient, facilitator) minus `price` — price is per-procedure and
64
- * arrives with each {@link X402ProcedureSpec}.
65
- * @experimental
66
- */
100
+ * Charge config for the procedure gate: the worker-level settlement vocabulary
101
+ * (network, recipient, facilitator) minus `price` — price is per-procedure and
102
+ * arrives with each {@link X402ProcedureSpec}.
103
+ * @experimental
104
+ */
67
105
  type X402ProcedureChargeConfig = Omit<X402ChargeConfig, "price">;
68
106
  /**
69
- * The per-RPC charge spec the runtime passes the gate for each paid dispatch.
70
- * @experimental
71
- */
107
+ * The per-RPC charge spec the runtime passes the gate for each paid dispatch.
108
+ * @experimental
109
+ */
72
110
  interface X402ProcedureSpec {
73
111
  /** The `file:function` id of the paid procedure; becomes the x402 challenge `resource`. */
74
112
  readonly functionPath: string;
@@ -76,20 +114,26 @@ interface X402ProcedureSpec {
76
114
  readonly price: X402Price;
77
115
  }
78
116
  /**
79
- * Gate one paid RPC. Returns a real `402` + `PAYMENT-REQUIRED` challenge when the
80
- * request is unpaid, or the dispatched response (with `X-PAYMENT-RESPONSE`
81
- * attached) once the client's `X-PAYMENT` is verified and settled. `dispatch`
82
- * runs the actual shard forward — it is only invoked after payment is verified.
83
- * @experimental
84
- */
85
- type X402ProcedureChargeGate = (request: Request, spec: X402ProcedureSpec, dispatch: () => Promise<Response>) => Promise<Response>;
117
+ * Gate one paid RPC. Returns a real `402` + `PAYMENT-REQUIRED` challenge when the
118
+ * request is unpaid, or the dispatched response (with `X-PAYMENT-RESPONSE`
119
+ * attached) once the client's `X-PAYMENT` is verified and settled. `dispatch`
120
+ * runs the actual shard forward — settlement happens **before** `dispatch` is
121
+ * invoked (settle-first), so a settlement failure means the shard forward
122
+ * (the mutation's commit) never runs at all — no committed-but-unpaid write is
123
+ * possible. `deps.waitUntil`, when supplied (the request's `ctx.waitUntil`),
124
+ * keeps the opt-in receipt sink alive past the response.
125
+ * @experimental
126
+ */
127
+ type X402ProcedureChargeGate = (request: Request, spec: X402ProcedureSpec, dispatch: () => Promise<Response>, deps?: ChargeHandlerDeps) => Promise<Response>;
86
128
  /**
87
- * Build the injectable procedure charge gate for `config`. One initialised
88
- * {@link ChargeMiddleware} is memoised per `functionPath` (each bakes that
89
- * function's price + `resource`), since `createChargeMiddleware` fetches
90
- * facilitator support on first use. A failed init is not cached, so a transient
91
- * facilitator outage retries on the next request.
92
- * @experimental
93
- */
129
+ * Build the injectable procedure charge gate for `config`. One initialised
130
+ * {@link ChargeMiddleware} is memoised per `functionPath` (each bakes that
131
+ * function's price + `resource`), since `createChargeMiddleware` fetches
132
+ * facilitator support on first use. A failed init is not cached, so a transient
133
+ * facilitator outage retries on the next request. Settlement runs before
134
+ * `dispatch` (`settleBeforeHandler: true`) since `dispatch` commits the
135
+ * procedure's real mutation — see `createChargeMiddleware`'s `ChargeMiddlewareOptions`.
136
+ * @experimental
137
+ */
94
138
  declare const createProcedureChargeGate: (config: X402ProcedureChargeConfig) => X402ProcedureChargeGate;
95
- export { type ChargeHandler, type ChargeMiddleware, type ChargeRouteOverrides, type FacilitatorConfig, type HttpActionHandler, type X402ChargeConfig, type X402Price, type X402ProcedureChargeConfig, type X402ProcedureChargeGate, type X402ProcedureSpec, createChargeMiddleware, createFacilitatorClient, createProcedureChargeGate, withX402 };
139
+ export { type ChargeHandler, type ChargeHandlerDeps, type ChargeMiddleware, type ChargeMiddlewareOptions, type ChargeRouteOverrides, type FacilitatorConfig, type HttpActionHandler, type X402ChargeConfig, type X402Price, type X402ProcedureChargeConfig, type X402ProcedureChargeGate, type X402ProcedureSpec, createChargeMiddleware, createFacilitatorClient, createProcedureChargeGate, withX402 };
@@ -1,5 +1,5 @@
1
- import { F as FacilitatorConfig, c as X402ChargeConfig, f as X402Price } from "../packem_shared/config.d-D8gKQLAq.js";
2
- export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, type a as EvmAddress, type P as PaymentEventRow, type d as X402Network, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2, x as toPaymentEventRow, y as toReceipt } from "../packem_shared/config.d-D8gKQLAq.js";
1
+ import { F as FacilitatorConfig, c as X402ChargeConfig, f as X402Price } from "../packem_shared/config.d-B-NYmHgG.js";
2
+ export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, type a as EvmAddress, type P as PaymentEventRow, type d as X402Network, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2, x as toPaymentEventRow, y as toReceipt } from "../packem_shared/config.d-B-NYmHgG.js";
3
3
  import { HTTPFacilitatorClient } from '@x402/core/server';
4
4
  import { RouteConfig } from '@x402/core/http';
5
5
  import '@x402/evm';
@@ -7,68 +7,106 @@ import '@x402/svm';
7
7
  import '@x402/core/client';
8
8
  import '@x402/core/types';
9
9
  /**
10
- * Build an `@x402/core` facilitator client from Lunora's {@link FacilitatorConfig}.
11
- *
12
- * `config.headers` (e.g. a CDP bearer token) are applied to every facilitator
13
- * call — `@x402/core` splits auth per endpoint (`verify` / `settle` /
14
- * `supported`), so the same header map is handed to each. With no config the
15
- * client points at the public {@link resolveFacilitatorUrl default} and sends no
16
- * auth headers.
17
- * @experimental
18
- */
10
+ * Build an `@x402/core` facilitator client from Lunora's {@link FacilitatorConfig}.
11
+ *
12
+ * `config.headers` (e.g. a CDP bearer token) are applied to every facilitator
13
+ * call — `@x402/core` splits auth per endpoint (`verify` / `settle` /
14
+ * `supported`), so the same header map is handed to each. With no config the
15
+ * client points at the public {@link resolveFacilitatorUrl default} and sends no
16
+ * auth headers.
17
+ * @experimental
18
+ */
19
19
  declare const createFacilitatorClient: (config?: FacilitatorConfig) => HTTPFacilitatorClient;
20
20
  /**
21
- * A handler shaped like a Lunora HTTP action: `(context, request) => Response`.
22
- * @experimental
23
- */
21
+ * A handler shaped like a Lunora HTTP action: `(context, request) => Response`.
22
+ * @experimental
23
+ */
24
24
  type HttpActionHandler<Context> = (context: Context, request: Request) => Promise<Response> | Response;
25
25
  /**
26
- * Gate `handler` behind an x402 paywall described by `config`. Returns a handler
27
- * of the same shape, ready to pass to `httpAction`.
28
- * @experimental
29
- */
26
+ * Gate `handler` behind an x402 paywall described by `config`. Returns a handler
27
+ * of the same shape, ready to pass to `httpAction`.
28
+ * @experimental
29
+ */
30
30
  declare const withX402: <Context>(config: X402ChargeConfig, handler: HttpActionHandler<Context>) => HttpActionHandler<Context>;
31
31
  /**
32
- * Runs the protected resource handler, producing the Response to gate.
33
- * @experimental
34
- */
32
+ * Runs the protected resource handler, producing the Response to gate.
33
+ * @experimental
34
+ */
35
35
  type ChargeHandler = () => Promise<Response> | Response;
36
36
  /**
37
- * A prepared, initialised paywall. Build once (it fetches facilitator support), reuse per request.
38
- * @experimental
39
- */
37
+ * Per-request platform seams `handle` can use, beyond the request/handler pair.
38
+ * @experimental
39
+ */
40
+ interface ChargeHandlerDeps {
41
+ /**
42
+ * Keep background work (the receipt sink) alive past the response — the
43
+ * request's `ctx.waitUntil`. Absent on paths with no platform execution
44
+ * context reaching the middleware (e.g. today's HTTP-action rail).
45
+ */
46
+ readonly waitUntil?: (promise: Promise<unknown>) => void;
47
+ }
48
+ /**
49
+ * A prepared, initialised paywall. Build once (it fetches facilitator support), reuse per request.
50
+ * @experimental
51
+ */
40
52
  interface ChargeMiddleware {
41
53
  /** Gate `request`: challenge / verify / settle around `runHandler`. */
42
- handle: (request: Request, runHandler: ChargeHandler) => Promise<Response>;
54
+ handle: (request: Request, runHandler: ChargeHandler, deps?: ChargeHandlerDeps) => Promise<Response>;
43
55
  }
44
56
  /**
45
- * Route metadata a caller can layer onto the generated catch-all route. The
46
- * procedure gate sets `resource` to the `functionPath` so the x402 challenge
47
- * names the paid function (x402 core falls back to the request URL otherwise —
48
- * every RPC POSTs to the same `/_lunora/rpc`, so the URL can't tell two paid
49
- * procedures apart).
50
- * @experimental
51
- */
57
+ * Route metadata a caller can layer onto the generated catch-all route. The
58
+ * procedure gate sets `resource` to the `functionPath` so the x402 challenge
59
+ * names the paid function (x402 core falls back to the request URL otherwise —
60
+ * every RPC POSTs to the same `/_lunora/rpc`, so the URL can't tell two paid
61
+ * procedures apart).
62
+ * @experimental
63
+ */
52
64
  type ChargeRouteOverrides = Pick<RouteConfig, "description" | "resource">;
53
65
  /**
54
- * Build and initialise a {@link ChargeMiddleware} for `config`. Fetches
55
- * facilitator support once (via `initialize()`), so call this once per config
56
- * and reuse the result across requests. `routeOverrides` layers extra route
57
- * metadata (e.g. `resource`) onto the generated catch-all route.
58
- * @experimental
59
- */
60
- declare const createChargeMiddleware: (config: X402ChargeConfig, routeOverrides?: ChargeRouteOverrides) => Promise<ChargeMiddleware>;
66
+ * Behaviour knobs for {@link createChargeMiddleware} beyond route metadata.
67
+ * @experimental
68
+ */
69
+ interface ChargeMiddlewareOptions {
70
+ /**
71
+ * Settle the verified payment **before** dispatching `runHandler`, instead
72
+ * of after. Use this for a mutation/procedure gate: a settlement failure
73
+ * then means the handler never runs at all, so a paid mutation's writes can
74
+ * never be committed without payment (the free-execution gap X402-04
75
+ * closes). Once settlement succeeds the payment is final (on-chain) — a
76
+ * handler failure after that point is a normal application error, not a
77
+ * payment to unwind: there is nothing left to cancel, so it is not caught
78
+ * here and simply propagates.
79
+ *
80
+ * Default `false` (settle-after, the historical behaviour): the handler's
81
+ * response is passed to settlement as transport context (`responseHeaders`
82
+ * — read by some schemes for settlement overrides), and a handler throw
83
+ * still releases the verified-but-unsettled payment via
84
+ * `cancellationDispatcher.cancel`. Because settlement can still fail after
85
+ * the handler already ran on this path, `.x402()` handlers gated this way
86
+ * MUST be idempotent or compensatable — see the `@lunora/x402` charge docs.
87
+ */
88
+ readonly settleBeforeHandler?: boolean;
89
+ }
90
+ /**
91
+ * Build and initialise a {@link ChargeMiddleware} for `config`. Fetches
92
+ * facilitator support once (via `initialize()`), so call this once per config
93
+ * and reuse the result across requests. `routeOverrides` layers extra route
94
+ * metadata (e.g. `resource`) onto the generated catch-all route; `options`
95
+ * controls settlement ordering (see {@link ChargeMiddlewareOptions}).
96
+ * @experimental
97
+ */
98
+ declare const createChargeMiddleware: (config: X402ChargeConfig, routeOverrides?: ChargeRouteOverrides, options?: ChargeMiddlewareOptions) => Promise<ChargeMiddleware>;
61
99
  /**
62
- * Charge config for the procedure gate: the worker-level settlement vocabulary
63
- * (network, recipient, facilitator) minus `price` — price is per-procedure and
64
- * arrives with each {@link X402ProcedureSpec}.
65
- * @experimental
66
- */
100
+ * Charge config for the procedure gate: the worker-level settlement vocabulary
101
+ * (network, recipient, facilitator) minus `price` — price is per-procedure and
102
+ * arrives with each {@link X402ProcedureSpec}.
103
+ * @experimental
104
+ */
67
105
  type X402ProcedureChargeConfig = Omit<X402ChargeConfig, "price">;
68
106
  /**
69
- * The per-RPC charge spec the runtime passes the gate for each paid dispatch.
70
- * @experimental
71
- */
107
+ * The per-RPC charge spec the runtime passes the gate for each paid dispatch.
108
+ * @experimental
109
+ */
72
110
  interface X402ProcedureSpec {
73
111
  /** The `file:function` id of the paid procedure; becomes the x402 challenge `resource`. */
74
112
  readonly functionPath: string;
@@ -76,20 +114,26 @@ interface X402ProcedureSpec {
76
114
  readonly price: X402Price;
77
115
  }
78
116
  /**
79
- * Gate one paid RPC. Returns a real `402` + `PAYMENT-REQUIRED` challenge when the
80
- * request is unpaid, or the dispatched response (with `X-PAYMENT-RESPONSE`
81
- * attached) once the client's `X-PAYMENT` is verified and settled. `dispatch`
82
- * runs the actual shard forward — it is only invoked after payment is verified.
83
- * @experimental
84
- */
85
- type X402ProcedureChargeGate = (request: Request, spec: X402ProcedureSpec, dispatch: () => Promise<Response>) => Promise<Response>;
117
+ * Gate one paid RPC. Returns a real `402` + `PAYMENT-REQUIRED` challenge when the
118
+ * request is unpaid, or the dispatched response (with `X-PAYMENT-RESPONSE`
119
+ * attached) once the client's `X-PAYMENT` is verified and settled. `dispatch`
120
+ * runs the actual shard forward — settlement happens **before** `dispatch` is
121
+ * invoked (settle-first), so a settlement failure means the shard forward
122
+ * (the mutation's commit) never runs at all — no committed-but-unpaid write is
123
+ * possible. `deps.waitUntil`, when supplied (the request's `ctx.waitUntil`),
124
+ * keeps the opt-in receipt sink alive past the response.
125
+ * @experimental
126
+ */
127
+ type X402ProcedureChargeGate = (request: Request, spec: X402ProcedureSpec, dispatch: () => Promise<Response>, deps?: ChargeHandlerDeps) => Promise<Response>;
86
128
  /**
87
- * Build the injectable procedure charge gate for `config`. One initialised
88
- * {@link ChargeMiddleware} is memoised per `functionPath` (each bakes that
89
- * function's price + `resource`), since `createChargeMiddleware` fetches
90
- * facilitator support on first use. A failed init is not cached, so a transient
91
- * facilitator outage retries on the next request.
92
- * @experimental
93
- */
129
+ * Build the injectable procedure charge gate for `config`. One initialised
130
+ * {@link ChargeMiddleware} is memoised per `functionPath` (each bakes that
131
+ * function's price + `resource`), since `createChargeMiddleware` fetches
132
+ * facilitator support on first use. A failed init is not cached, so a transient
133
+ * facilitator outage retries on the next request. Settlement runs before
134
+ * `dispatch` (`settleBeforeHandler: true`) since `dispatch` commits the
135
+ * procedure's real mutation — see `createChargeMiddleware`'s `ChargeMiddlewareOptions`.
136
+ * @experimental
137
+ */
94
138
  declare const createProcedureChargeGate: (config: X402ProcedureChargeConfig) => X402ProcedureChargeGate;
95
- export { type ChargeHandler, type ChargeMiddleware, type ChargeRouteOverrides, type FacilitatorConfig, type HttpActionHandler, type X402ChargeConfig, type X402Price, type X402ProcedureChargeConfig, type X402ProcedureChargeGate, type X402ProcedureSpec, createChargeMiddleware, createFacilitatorClient, createProcedureChargeGate, withX402 };
139
+ export { type ChargeHandler, type ChargeHandlerDeps, type ChargeMiddleware, type ChargeMiddlewareOptions, type ChargeRouteOverrides, type FacilitatorConfig, type HttpActionHandler, type X402ChargeConfig, type X402Price, type X402ProcedureChargeConfig, type X402ProcedureChargeGate, type X402ProcedureSpec, createChargeMiddleware, createFacilitatorClient, createProcedureChargeGate, withX402 };
@@ -1,7 +1,7 @@
1
1
  export { DEFAULT_FACILITATOR_URL, resolveFacilitatorUrl } from '../packem_shared/DEFAULT_FACILITATOR_URL-Cbz6kIqa.mjs';
2
2
  export { createFacilitatorClient } from '../packem_shared/createFacilitatorClient-rXHBnCZm.mjs';
3
3
  export { isEvmNetwork, isSvmNetwork, toCaip2 } from '../packem_shared/EVM_NETWORKS-BhnYWUQ4.mjs';
4
- export { withX402 } from '../packem_shared/withX402-SOW47gf3.mjs';
5
- export { createChargeMiddleware } from '../packem_shared/createChargeMiddleware-CARkBOyH.mjs';
6
- export { createProcedureChargeGate } from '../packem_shared/createProcedureChargeGate-MaMhu9L9.mjs';
4
+ export { withX402 } from '../packem_shared/withX402-DILL2DvD.mjs';
5
+ export { createChargeMiddleware } from '../packem_shared/createChargeMiddleware-D3yhOpFs.mjs';
6
+ export { createProcedureChargeGate } from '../packem_shared/createProcedureChargeGate-eh9yv36U.mjs';
7
7
  export { toPaymentEventRow, toReceipt } from '../packem_shared/toPaymentEventRow-DW4O9N7Y.mjs';
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, E as EVM_NETWORKS, type a as EvmAddress, type F as FacilitatorConfig, type b as FriendlyNetwork, N as NETWORK_TO_CAIP2, S as SVM_NETWORKS, type X as X402CdpSignerConfig, type c as X402ChargeConfig, type d as X402Network, type e as X402PayConfig, type f as X402Price, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, type j as X402SignerConfig, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2 } from "./packem_shared/config.d-D8gKQLAq.mjs";
1
+ export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, E as EVM_NETWORKS, type a as EvmAddress, type F as FacilitatorConfig, type b as FriendlyNetwork, N as NETWORK_TO_CAIP2, S as SVM_NETWORKS, type X as X402CdpSignerConfig, type c as X402ChargeConfig, type d as X402Network, type e as X402PayConfig, type f as X402Price, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, type j as X402SignerConfig, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2 } from "./packem_shared/config.d-B-NYmHgG.mjs";
2
2
  import '@x402/evm';
3
3
  import '@x402/svm';
4
4
  import '@x402/core/http';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, E as EVM_NETWORKS, type a as EvmAddress, type F as FacilitatorConfig, type b as FriendlyNetwork, N as NETWORK_TO_CAIP2, S as SVM_NETWORKS, type X as X402CdpSignerConfig, type c as X402ChargeConfig, type d as X402Network, type e as X402PayConfig, type f as X402Price, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, type j as X402SignerConfig, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2 } from "./packem_shared/config.d-D8gKQLAq.js";
1
+ export { type C as Caip2, D as DEFAULT_FACILITATOR_URL, E as EVM_NETWORKS, type a as EvmAddress, type F as FacilitatorConfig, type b as FriendlyNetwork, N as NETWORK_TO_CAIP2, S as SVM_NETWORKS, type X as X402CdpSignerConfig, type c as X402ChargeConfig, type d as X402Network, type e as X402PayConfig, type f as X402Price, type g as X402Receipt, type h as X402ReceiptSink, type i as X402Recipient, type j as X402SignerConfig, k as isEvmNetwork, l as isSvmNetwork, r as resolveFacilitatorUrl, t as toCaip2 } from "./packem_shared/config.d-B-NYmHgG.js";
2
2
  import '@x402/evm';
3
3
  import '@x402/svm';
4
4
  import '@x402/core/http';
@@ -10,6 +10,9 @@ const createSpendState = () => {
10
10
  add: (amount) => {
11
11
  spent += amount;
12
12
  },
13
+ release: (amount) => {
14
+ spent = spent > amount ? spent - amount : 0n;
15
+ },
13
16
  get spentAtomic() {
14
17
  return spent;
15
18
  }
@@ -59,27 +62,29 @@ const buildPaymentGuard = (policy, state) => {
59
62
  reason: `x402 policy: this payment (${requirement.amount}) would exceed the per-run cap (already spent ${state.spentAtomic.toString()}, cap ${maxPerRun.toString()}, in atomic base units).`
60
63
  };
61
64
  }
65
+ state.add(amount);
62
66
  if (policy.onPaymentRequired !== void 0) {
63
67
  const approved = await policy.onPaymentRequired(requirement);
64
68
  if (!approved) {
69
+ state.release(amount);
65
70
  return { abort: true, reason: "x402 policy: payment was declined by onPaymentRequired." };
66
71
  }
67
72
  }
68
73
  return void 0;
69
74
  };
70
75
  };
71
- const recordSpend = (state) => (context) => {
72
- state.add(BigInt(context.selectedRequirements.amount));
76
+ const releaseSpendOnFailure = (state) => (context) => {
77
+ state.release(BigInt(context.selectedRequirements.amount));
73
78
  return Promise.resolve();
74
79
  };
75
80
  const assertBoundedPolicy = (policy) => {
76
- const bounded = policy.maxPerCall !== void 0 || policy.maxPerRun !== void 0 || (policy.allowedRecipients?.length ?? 0) > 0 || (policy.allowedNetworks?.length ?? 0) > 0 || policy.onPaymentRequired !== void 0;
81
+ const bounded = policy.maxPerCall !== void 0 || policy.maxPerRun !== void 0 || policy.onPaymentRequired !== void 0;
77
82
  if (!bounded) {
78
83
  throw new LunoraError(
79
84
  "FORBIDDEN",
80
- "x402 pay: refusing to build a wallet with an unbounded spend policy. Set at least one of maxPerCall, maxPerRun, allowedRecipients, allowedNetworks, or onPaymentRequired."
85
+ "x402 pay: refusing to build a wallet with an unbounded spend policy. Set at least one of maxPerCall, maxPerRun, or onPaymentRequired (allowedNetworks/allowedRecipients narrow but do not bound spend)."
81
86
  );
82
87
  }
83
88
  };
84
89
 
85
- export { DEFAULT_STABLECOIN_DECIMALS, assertBoundedPolicy, buildPaymentGuard, buildSpendPolicy, createSpendState, recordSpend, usdToAtomic };
90
+ export { DEFAULT_STABLECOIN_DECIMALS, assertBoundedPolicy, buildPaymentGuard, buildSpendPolicy, createSpendState, releaseSpendOnFailure, usdToAtomic };