run402 4.10.2 → 4.11.1

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.
@@ -165,7 +165,7 @@ interface TrackedPaidFetchOptions {
165
165
  createAttemptId?: () => string;
166
166
  now?: () => string;
167
167
  fetch?: FetchFn;
168
- classifyPaymentResponse?: (response: Response) => Promise<"completed" | "failed" | "already_settled" | "ambiguous">;
168
+ classifyPaymentResponse?: (response: Response) => Promise<"completed" | "failed" | "already_settled" | "intent_pending" | "ambiguous">;
169
169
  }
170
170
  /** @internal Exported only for deterministic source-level tests; not re-exported by the package. */
171
171
  export declare function checkBalanceAcrossProviders(clients: readonly RpcClient[], tokenAddress: string, walletAddress: string, network: string, options?: BalanceRetryOptions): Promise<bigint>;
@@ -185,6 +185,25 @@ export declare const __paidFetchInternals: {
185
185
  };
186
186
  interface X402BuyerFetchOptions extends TrackedPaidFetchOptions {
187
187
  supportedNetworks: readonly string[];
188
+ payerAddresses?: readonly string[];
189
+ offerReceipt?: X402OfferReceiptRuntime;
190
+ verifyAtSeconds?: () => number;
191
+ }
192
+ interface X402OfferReceiptRuntime {
193
+ extractOffersFromPaymentRequired: (required: unknown) => unknown[];
194
+ decodeSignedOffers: (offers: unknown[]) => unknown[];
195
+ findAcceptsObjectFromSignedOffer: (offer: unknown, accepts: unknown[]) => unknown | undefined;
196
+ isEIP712SignedOffer: (offer: unknown) => boolean;
197
+ isEIP712SignedReceipt: (receipt: unknown) => boolean;
198
+ verifyOfferSignatureEIP712: (offer: unknown) => Promise<{
199
+ signer: `0x${string}`;
200
+ payload: Record<string, unknown>;
201
+ }>;
202
+ verifyReceiptSignatureEIP712: (receipt: unknown) => Promise<{
203
+ signer: `0x${string}`;
204
+ payload: Record<string, unknown>;
205
+ }>;
206
+ extractReceiptFromResponse: (response: Response) => unknown | undefined;
188
207
  }
189
208
  /**
190
209
  * Receipt-bearing buyer orchestration over an already-configured x402 client.
@@ -1 +1 @@
1
- {"version":3,"file":"paid-fetch.d.ts","sourceRoot":"","sources":["../../src/node/paid-fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paid-fetch.d.ts","sourceRoot":"","sources":["../../src/node/paid-fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAiB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAGL,WAAW,EAEZ,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAEL,iBAAiB,EAWjB,KAAK,WAAW,EAMjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAQL,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,KAAK,OAAO,GAAG,OAAO,UAAU,CAAC,KAAK,CAAC;AAGvC,UAAU,SAAS;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClD;AAQD,UAAU,mBAAmB;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACvB;AAED,UAAU,sBAAsB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,EAAE,uBAAuB,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClF;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,KAAK,YAAY,GAAG,YAAY,GAAG,cAAc,CAAC;AAClD,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAC5B,kBAAkB,GAClB,uBAAuB,GACvB,sBAAsB,GACtB,yBAAyB,CAAC;AAE9B;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAU;IACvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBAGvB,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,KAAK,CAAC,EAAE,OAAO;CAuClB;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,cAAc,CAAC;AAEhE,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IAChC,aAAa,CAAC,OAAO,EAAE;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IAC3B,YAAY,CAAC,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,eAAe,CAAC,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IACxD,mBAAmB,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,KAAK,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,kBAAkB,CAAC,IAAI,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxF;AAED,kFAAkF;AAClF,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,OAAO,EAAE;QACjB,OAAO,EAAE,kBAAkB,CAAC;QAC5B,YAAY,EAAE,mBAAmB,CAAC;KACnC,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CACtC;AAED,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,mBAAmB,CAAC;AAExB,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;KACvC,EAAE,CAAC;CACL;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG;IAC1C,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAC3B,+EAA+E;IAC/E,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,0FAA0F;IAC1F,QAAQ,IAAI,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACnD,4DAA4D;IAC5D,GAAG,EAAE,WAAW,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,WAAW,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACzD,0EAA0E;IAC1E,aAAa,CAAC,EAAE,wBAAwB,CAAC;CAC1C;AAsCD,oEAAoE;AACpE,wBAAgB,2BAA2B,CAAC,OAAO,CAAC,EAAE;IACpD,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC/B,GAAG,IAAI,CAKP;AAmBD,UAAU,uBAAuB;IAC/B,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB,CAAC,EAAE,CACxB,QAAQ,EAAE,QAAQ,KACf,OAAO,CAAC,WAAW,GAAG,QAAQ,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,WAAW,CAAC,CAAC;CAC3F;AAoDD,oGAAoG;AACpG,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,SAAS,SAAS,EAAE,EAC7B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CA4CjB;AAWD,oGAAoG;AACpG,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,sBAAsB,EAAE,EACtC,QAAQ,EAAE,aAAa,GACtB,sBAAsB,EAAE,CA6C1B;AAkDD,wBAAsB,cAAc,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAqIxG;AAmBD,iBAAS,uBAAuB,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,CA4B9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,gBAAqB,GAAG,aAAa,CAwEjF;AAmED,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB;;CAEhC,CAAC;AAEF,UAAU,qBAAsB,SAAQ,uBAAuB;IAC7D,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;CAChC;AAED,UAAU,uBAAuB;IAC/B,gCAAgC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,EAAE,CAAC;IACnE,kBAAkB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;IACrD,gCAAgC,EAAE,CAChC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,OAAO,EAAE,KACf,OAAO,GAAG,SAAS,CAAC;IACzB,mBAAmB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACjD,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;IACrD,0BAA0B,EAAE,CAC1B,KAAK,EAAE,OAAO,KACX,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1E,4BAA4B,EAAE,CAC5B,OAAO,EAAE,OAAO,KACb,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC1E,0BAA0B,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,GAAG,SAAS,CAAC;CACzE;AA+BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,qBAAqB,GAC7B,WAAW,CA0Nb;AA8gBD,wBAAgB,8BAA8B,CAC5C,sBAAsB,EAAE,MAAM,EAAE,EAChC,mBAAmB,EAAE,MAAM,EAAE,EAC7B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAClC,iBAAiB,CAiBnB;AAwGD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,EAClE,MAAM,EAAE,OAAO,EACf,IAAI,GAAE,uBAA4B,GACjC,OAAO,CA0PT"}
@@ -20,7 +20,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
20
20
  import { createHash } from "node:crypto";
21
21
  import { LocalError, PaymentAttemptError, Run402Error, } from "../errors.js";
22
22
  import { PaidStackUnavailable, loadMppStack, loadX402Stack } from "./_paid-stack.js";
23
- import { DEFAULT_PAYMENT_MAX_USD_MICROS, PaymentBuyerError, paymentExceedsMaxError, responseSignalsReplay, walletUnavailableError, } from "../namespaces/pay.js";
23
+ import { DEFAULT_PAYMENT_MAX_USD_MICROS, PaymentBuyerError, PaymentPolicyError, gatewayPaymentBuyerError, isTrustedRun402PaymentUrl, isTrustedRun402PendingResponse, payResponseMetadata, merchantReceiptRequiredError, paymentExceedsMaxError, readPaymentErrorEnvelope, responseSignalsReplay, walletUnavailableError, } from "../namespaces/pay.js";
24
24
  import { attemptIdFromRequest, createFilePaymentAttemptStore, createPaymentAttemptId, hasPaymentAuthorization, requestSummary, withPaymentAttemptHeader, } from "./payment-attempts.js";
25
25
  /**
26
26
  * A machine-readable x402 balance-preflight failure.
@@ -369,6 +369,11 @@ export async function setupPaidFetch(options = {}) {
369
369
  ];
370
370
  const buyer = createX402BuyerFetch(client, {
371
371
  supportedNetworks,
372
+ payerAddresses: [
373
+ ...(mainnetSigner ? [mainnetSigner.address] : []),
374
+ ...(sepoliaSigner ? [sepoliaSigner.address] : []),
375
+ ],
376
+ offerReceipt: stack.offerReceipt,
372
377
  });
373
378
  return withPayer(trackedFetch, {
374
379
  source: options.paymentSigner ? "payment_signer" : resolvedAllowance.source,
@@ -499,6 +504,7 @@ export function createLazyPaidFetch(options = {}) {
499
504
  payment: null,
500
505
  outcome: "not_required",
501
506
  replay: await responseSignalsReplay(response, payOptions.idempotencyKey !== undefined),
507
+ ...payResponseMetadata(response),
502
508
  };
503
509
  }
504
510
  if (configured?.payer.rail === "mpp") {
@@ -582,7 +588,7 @@ export function createX402BuyerFetch(client, options) {
582
588
  if (firstResponse.status !== 402)
583
589
  return firstResponse;
584
590
  const required = await decodePaymentRequired(firstResponse);
585
- const guarded = guardPaymentRequired(required, options.supportedNetworks, call.maxUsdMicros, request.url);
591
+ const guarded = await guardPaymentRequired(required, options.supportedNetworks, call.maxUsdMicros, request.url, call.requireReceipt, options.offerReceipt, options.verifyAtSeconds?.() ?? Math.floor(Date.now() / 1000));
586
592
  let pending = creatingProofs.get(call.fingerprint);
587
593
  if (!pending) {
588
594
  pending = createProof(client, guarded)
@@ -600,6 +606,20 @@ export function createX402BuyerFetch(client, options) {
600
606
  fetch: options.fetch,
601
607
  async classifyPaymentResponse(response) {
602
608
  const call = calls.getStore();
609
+ const envelope = await readPaymentErrorEnvelope(response);
610
+ if (call && isTrustedRun402PendingResponse({
611
+ requestUrl: call.requestUrl,
612
+ response,
613
+ envelope,
614
+ paymentBearing: true,
615
+ redirectsDisabled: true,
616
+ })) {
617
+ return "intent_pending";
618
+ }
619
+ if (call && envelope && trustedRun402ResponseOrigin(call.requestUrl, response) &&
620
+ gatewayPaymentBuyerError(response, envelope)) {
621
+ return "failed";
622
+ }
603
623
  const failure = await upstreamFailure(response);
604
624
  if (call?.replayedProof && isAlreadyUsedFailure(failure)) {
605
625
  call.alreadySettled = true;
@@ -610,12 +630,15 @@ export function createX402BuyerFetch(client, options) {
610
630
  });
611
631
  return async (url, init, payOptions) => {
612
632
  const maxUsdMicros = payOptions.maxUsdMicros ?? DEFAULT_PAYMENT_MAX_USD_MICROS;
613
- const fingerprint = await paymentRequestFingerprint(url, init, maxUsdMicros);
633
+ const requireReceipt = payOptions.requireReceipt === true;
634
+ const fingerprint = await paymentRequestFingerprint(url, init, maxUsdMicros, requireReceipt);
614
635
  const call = {
615
636
  fingerprint,
637
+ requestUrl: url,
616
638
  maxUsdMicros,
617
639
  replayedProof: false,
618
640
  alreadySettled: false,
641
+ requireReceipt,
619
642
  };
620
643
  try {
621
644
  const response = await calls.run(call, () => tracked(url, init));
@@ -625,6 +648,7 @@ export function createX402BuyerFetch(client, options) {
625
648
  payment: null,
626
649
  outcome: "not_required",
627
650
  replay: await responseSignalsReplay(response, payOptions.idempotencyKey !== undefined),
651
+ ...payResponseMetadata(response),
628
652
  };
629
653
  }
630
654
  if (call.alreadySettled) {
@@ -634,9 +658,16 @@ export function createX402BuyerFetch(client, options) {
634
658
  payment: null,
635
659
  outcome: "already_settled",
636
660
  replay: true,
661
+ ...payResponseMetadata(response),
637
662
  };
638
663
  }
639
664
  if (!response.ok) {
665
+ const envelope = await readPaymentErrorEnvelope(response);
666
+ if (envelope && trustedRun402ResponseOrigin(url, response)) {
667
+ const gatewayError = gatewayPaymentBuyerError(response, envelope);
668
+ if (gatewayError)
669
+ throw gatewayError;
670
+ }
640
671
  const failure = await upstreamFailure(response);
641
672
  proofs.delete(fingerprint);
642
673
  if (failure.code === "payment_insufficient_funds") {
@@ -650,14 +681,30 @@ export function createX402BuyerFetch(client, options) {
650
681
  ...(failure.x402Error ? { x402_error: failure.x402Error } : {}),
651
682
  });
652
683
  }
653
- const payment = receiptFromResponse(response, call.proof.accepted, url);
684
+ const payment = await receiptFromResponse(response, call.proof, url, requireReceipt, options.offerReceipt, options.payerAddresses ?? []);
654
685
  proofs.delete(fingerprint);
655
- return {
686
+ const result = {
656
687
  response,
657
688
  payment,
658
689
  outcome: "settled",
659
690
  replay: call.replayedProof,
691
+ nextActions: [],
692
+ ...payResponseMetadata(response),
660
693
  };
694
+ if (requireReceipt &&
695
+ payment.merchantReceipt.status !== "verified") {
696
+ const recovery = receiptRecovery(url, response, payOptions.idempotencyKey);
697
+ throw new PaymentPolicyError({
698
+ response,
699
+ result,
700
+ message: "The payment settled, but the promised merchant receipt could not be verified.",
701
+ fundsMoved: payment.fundsMoved,
702
+ mutationState: payment.delivery.status === "fulfilled" ? "committed" : "unknown",
703
+ safeToRetry: recovery.safeToRetry,
704
+ nextActions: recovery.nextActions,
705
+ });
706
+ }
707
+ return result;
661
708
  }
662
709
  catch (cause) {
663
710
  if (cause instanceof PaymentBuyerError)
@@ -683,11 +730,12 @@ export function createX402BuyerFetch(client, options) {
683
730
  }
684
731
  };
685
732
  }
686
- async function createProof(client, required) {
733
+ async function createProof(client, guarded) {
687
734
  try {
688
- const payload = await client.createPaymentPayload(required);
735
+ const payload = await client.createPaymentPayload(guarded.required);
689
736
  return {
690
737
  accepted: payload.accepted,
738
+ offer: guarded.verifiedOffers.find((offer) => sameRequirement(offer.requirement, payload.accepted)) ?? null,
691
739
  headers: {
692
740
  [payload.x402Version === 1 ? "X-PAYMENT" : "PAYMENT-SIGNATURE"]: encodeBase64Json(payload),
693
741
  },
@@ -697,7 +745,7 @@ async function createProof(client, required) {
697
745
  throw unwrapPolicyError(cause) ?? cause;
698
746
  }
699
747
  }
700
- function guardPaymentRequired(required, supportedNetworks, maxUsdMicros, requestUrl) {
748
+ async function guardPaymentRequired(required, supportedNetworks, maxUsdMicros, requestUrl, requireReceipt, offerReceipt, verifyAtSeconds) {
701
749
  let challengeUrl;
702
750
  try {
703
751
  challengeUrl = new URL(required.resource.url).toString();
@@ -731,7 +779,23 @@ function guardPaymentRequired(required, supportedNetworks, maxUsdMicros, request
731
779
  const challenged = Math.min(...valid.map(({ amount }) => amount));
732
780
  throw paymentExceedsMaxError(challenged, maxUsdMicros);
733
781
  }
734
- return { ...required, accepts: withinLimit.map(({ accept }) => accept) };
782
+ const accepted = withinLimit.map(({ accept }) => accept);
783
+ const verifiedOffers = offerReceipt
784
+ ? await verifyDirectOffers(required, accepted, requestUrl, verifyAtSeconds, offerReceipt)
785
+ : [];
786
+ if (requireReceipt && verifiedOffers.length === 0) {
787
+ throw merchantReceiptRequiredError({
788
+ offered_requirements: accepted.length,
789
+ valid_wallet_rooted_offers: 0,
790
+ });
791
+ }
792
+ const eligible = requireReceipt
793
+ ? accepted.filter((requirement) => verifiedOffers.some((offer) => sameRequirement(offer.requirement, requirement)))
794
+ : accepted;
795
+ return {
796
+ required: { ...required, accepts: eligible },
797
+ verifiedOffers,
798
+ };
735
799
  }
736
800
  function supportedPaymentAsset(network) {
737
801
  if (network === "eip155:8453")
@@ -740,6 +804,83 @@ function supportedPaymentAsset(network) {
740
804
  return USDC_SEPOLIA;
741
805
  return null;
742
806
  }
807
+ async function verifyDirectOffers(required, eligibleRequirements, requestUrl, verifyAtSeconds, runtime) {
808
+ let decoded;
809
+ try {
810
+ decoded = runtime.decodeSignedOffers(runtime.extractOffersFromPaymentRequired(required));
811
+ }
812
+ catch {
813
+ return [];
814
+ }
815
+ const verified = [];
816
+ for (const value of decoded) {
817
+ const offer = asRecord(value);
818
+ const signed = offer.signedOffer;
819
+ if (!runtime.isEIP712SignedOffer(signed))
820
+ continue;
821
+ const requirement = runtime.findAcceptsObjectFromSignedOffer(offer, eligibleRequirements);
822
+ if (!requirement)
823
+ continue;
824
+ try {
825
+ const checked = await runtime.verifyOfferSignatureEIP712(signed);
826
+ const payload = checked.payload;
827
+ const validUntil = safeInteger(payload.validUntil);
828
+ if (payload.version !== 1 ||
829
+ normalizedUrl(payload.resourceUrl) !== normalizedUrl(requestUrl) ||
830
+ payload.scheme !== requirement.scheme ||
831
+ payload.network !== requirement.network ||
832
+ !sameAddressOrText(payload.asset, requirement.asset) ||
833
+ payload.amount !== requirement.amount ||
834
+ !sameAddressOrText(payload.payTo, requirement.payTo) ||
835
+ validUntil === null ||
836
+ validUntil <= verifyAtSeconds ||
837
+ !sameAddressOrText(checked.signer, requirement.payTo)) {
838
+ continue;
839
+ }
840
+ verified.push({
841
+ signed,
842
+ decoded: offer,
843
+ requirement,
844
+ signer: checked.signer,
845
+ relationship: "direct",
846
+ });
847
+ }
848
+ catch {
849
+ // A malformed, invalid, delegated, or untrusted offer is ineligible.
850
+ }
851
+ }
852
+ return verified;
853
+ }
854
+ function sameRequirement(left, right) {
855
+ return (left.scheme === right.scheme &&
856
+ left.network === right.network &&
857
+ sameAddressOrText(left.asset, right.asset) &&
858
+ left.amount === right.amount &&
859
+ sameAddressOrText(left.payTo, right.payTo));
860
+ }
861
+ function sameAddressOrText(left, right) {
862
+ if (typeof left !== "string" || typeof right !== "string")
863
+ return false;
864
+ return /^0x[0-9a-fA-F]{40}$/.test(left) &&
865
+ /^0x[0-9a-fA-F]{40}$/.test(right)
866
+ ? left.toLowerCase() === right.toLowerCase()
867
+ : left === right;
868
+ }
869
+ function normalizedUrl(value) {
870
+ if (typeof value !== "string")
871
+ return null;
872
+ try {
873
+ return new URL(value).toString();
874
+ }
875
+ catch {
876
+ return null;
877
+ }
878
+ }
879
+ function safeInteger(value) {
880
+ return typeof value === "number" && Number.isSafeInteger(value)
881
+ ? value
882
+ : null;
883
+ }
743
884
  function atomicAmount(value) {
744
885
  if (!/^\d+$/.test(value))
745
886
  return null;
@@ -783,7 +924,8 @@ function isPaymentRequired(value) {
783
924
  typeof accept.amount === "string" &&
784
925
  typeof accept.payTo === "string"));
785
926
  }
786
- function receiptFromResponse(response, accepted, url) {
927
+ async function receiptFromResponse(response, proof, url, requireReceipt, runtime, payerAddresses) {
928
+ const accepted = proof.accepted;
787
929
  const header = response.headers.get("PAYMENT-RESPONSE") ?? response.headers.get("X-PAYMENT-RESPONSE");
788
930
  if (!header) {
789
931
  throw settlementError("The paid response omitted the standard PAYMENT-RESPONSE settlement receipt, so settlement cannot be reported faithfully.", "unknown", { response_status: response.status });
@@ -810,12 +952,148 @@ function receiptFromResponse(response, accepted, url) {
810
952
  if (amount === null) {
811
953
  throw settlementError("The selected payment amount cannot be represented as usd_micros.", "unknown");
812
954
  }
955
+ const metadata = payResponseMetadata(response);
956
+ const settlementPayer = typeof record.payer === "string" && record.payer.length > 0
957
+ ? record.payer
958
+ : null;
959
+ let receiptStatus = proof.offer
960
+ ? "unavailable"
961
+ : "absent";
962
+ let signedReceipt = null;
963
+ let receiptIssuedAt = null;
964
+ let receiptSigner = null;
965
+ if (runtime) {
966
+ try {
967
+ signedReceipt = runtime.extractReceiptFromResponse(response) ?? null;
968
+ if (signedReceipt && !proof.offer) {
969
+ receiptStatus = "untrusted";
970
+ }
971
+ else if (signedReceipt && !runtime.isEIP712SignedReceipt(signedReceipt)) {
972
+ receiptStatus = "untrusted";
973
+ }
974
+ else if (signedReceipt && proof.offer) {
975
+ const checked = await runtime.verifyReceiptSignatureEIP712(signedReceipt);
976
+ const payload = checked.payload;
977
+ const issuedAt = safeInteger(payload.issuedAt);
978
+ const payerMatches = typeof payload.payer === "string" &&
979
+ [
980
+ ...(settlementPayer ? [settlementPayer] : []),
981
+ ...payerAddresses,
982
+ ].some((payer) => sameAddressOrText(payload.payer, payer));
983
+ const transactionMatches = typeof payload.transaction === "string" &&
984
+ payload.transaction === record.transaction;
985
+ if (payload.version === 1 &&
986
+ normalizedUrl(payload.resourceUrl) === normalizedUrl(url) &&
987
+ payload.network === accepted.network &&
988
+ payerMatches &&
989
+ transactionMatches &&
990
+ issuedAt !== null &&
991
+ sameAddressOrText(checked.signer, proof.offer.signer) &&
992
+ sameAddressOrText(checked.signer, accepted.payTo)) {
993
+ receiptStatus = "verified";
994
+ receiptSigner = checked.signer;
995
+ receiptIssuedAt = new Date(issuedAt * 1000).toISOString();
996
+ }
997
+ else {
998
+ receiptStatus = "invalid";
999
+ }
1000
+ }
1001
+ }
1002
+ catch {
1003
+ receiptStatus = signedReceipt ? "invalid" : receiptStatus;
1004
+ }
1005
+ }
1006
+ const fundsMoved = metadata.fundsMoved ?? true;
1007
+ const deliveryReplay = metadata.delivery === "replay" || metadata.deduplicated === true;
1008
+ const offerPayload = proof.offer?.decoded ?? null;
1009
+ const offerValidUntil = safeInteger(offerPayload?.validUntil);
1010
+ const noSignerAuthorizationExpiry = null;
813
1011
  return {
814
1012
  amount_usd_micros: amount,
815
1013
  pay_to: accepted.payTo,
816
1014
  network: record.network,
817
1015
  tx_ref: record.transaction,
818
1016
  url,
1017
+ paymentId: metadata.paymentId,
1018
+ amountUsdMicros: amount,
1019
+ asset: accepted.asset,
1020
+ payer: settlementPayer,
1021
+ payTo: accepted.payTo,
1022
+ transaction: record.transaction,
1023
+ resourceUrl: url,
1024
+ settlement: { status: "verified" },
1025
+ fundsMoved,
1026
+ deduplicated: metadata.deduplicated ?? false,
1027
+ delivery: {
1028
+ status: response.ok ? "fulfilled" : "failed",
1029
+ replay: deliveryReplay,
1030
+ },
1031
+ offer: {
1032
+ status: proof.offer ? "verified" : "absent",
1033
+ resourceUrl: typeof offerPayload?.resourceUrl === "string"
1034
+ ? offerPayload.resourceUrl
1035
+ : null,
1036
+ validUntil: offerValidUntil === null
1037
+ ? null
1038
+ : new Date(offerValidUntil * 1000).toISOString(),
1039
+ },
1040
+ merchantReceipt: {
1041
+ status: receiptStatus,
1042
+ claim: receiptStatus === "verified" ? "service_delivered" : null,
1043
+ issuedAt: receiptIssuedAt,
1044
+ },
1045
+ signerRelationship: {
1046
+ kind: receiptStatus === "verified"
1047
+ ? proof.offer?.relationship ?? null
1048
+ : proof.offer
1049
+ ? "unverified"
1050
+ : null,
1051
+ merchantRoot: proof.offer?.relationship === "direct" ? accepted.payTo : null,
1052
+ signer: receiptSigner ?? proof.offer?.signer ?? null,
1053
+ authorizationExpiresAt: noSignerAuthorizationExpiry,
1054
+ },
1055
+ policy: {
1056
+ requireReceipt,
1057
+ status: requireReceipt
1058
+ ? receiptStatus === "verified"
1059
+ ? "satisfied"
1060
+ : "unsatisfied"
1061
+ : "not_required",
1062
+ },
1063
+ evidence: {
1064
+ offer: proof.offer?.signed ?? null,
1065
+ merchantReceipt: signedReceipt,
1066
+ signerAuthorization: null,
1067
+ },
1068
+ };
1069
+ }
1070
+ function receiptRecovery(url, response, idempotencyKey) {
1071
+ const recoverable = Boolean(idempotencyKey) &&
1072
+ isTrustedRun402PaymentUrl(url, { allowTestLocalhost: true }) &&
1073
+ response.headers.get("x-run402-merchant-evidence-state") ===
1074
+ "unavailable";
1075
+ if (recoverable) {
1076
+ return {
1077
+ safeToRetry: true,
1078
+ nextActions: [
1079
+ {
1080
+ type: "retry",
1081
+ request: "repeat_identical",
1082
+ reusePayer: true,
1083
+ reuseIdempotencyKey: true,
1084
+ why: "Repeat the identical request with the same payer and idempotency key to recover the original receipt without another settlement.",
1085
+ },
1086
+ ],
1087
+ };
1088
+ }
1089
+ return {
1090
+ safeToRetry: false,
1091
+ nextActions: [
1092
+ {
1093
+ type: "reconcile_payment",
1094
+ why: "Reconcile the existing settlement with the merchant; do not authorize a second payment.",
1095
+ },
1096
+ ],
819
1097
  };
820
1098
  }
821
1099
  async function upstreamFailure(response) {
@@ -917,7 +1195,7 @@ function challengeNetworks(response) {
917
1195
  return [];
918
1196
  }
919
1197
  }
920
- async function paymentRequestFingerprint(url, init, maxUsdMicros) {
1198
+ async function paymentRequestFingerprint(url, init, maxUsdMicros, requireReceipt) {
921
1199
  let request;
922
1200
  try {
923
1201
  request = new Request(url, init);
@@ -943,7 +1221,14 @@ async function paymentRequestFingerprint(url, init, maxUsdMicros) {
943
1221
  throw settlementError("The paid request body cannot be replayed safely.", false, {}, cause);
944
1222
  }
945
1223
  return createHash("sha256")
946
- .update(JSON.stringify({ method: request.method, url: request.url, headers, bodyHash, maxUsdMicros }))
1224
+ .update(JSON.stringify({
1225
+ method: request.method,
1226
+ url: request.url,
1227
+ headers,
1228
+ bodyHash,
1229
+ maxUsdMicros,
1230
+ requireReceipt,
1231
+ }))
947
1232
  .digest("hex");
948
1233
  }
949
1234
  function encodeBase64Json(value) {
@@ -1111,11 +1396,23 @@ export function createTrackedX402Fetch(wrapFetchWithPayment, client, opts = {})
1111
1396
  : await opts.classifyPaymentResponse?.(response) ?? "ambiguous";
1112
1397
  const completed = classification === "completed" || classification === "already_settled";
1113
1398
  const failed = classification === "failed";
1399
+ const intentPending = classification === "intent_pending";
1400
+ const retryAfter = retryAfterSeconds(response);
1114
1401
  writeRecordBestEffort(context, store, {
1115
- state: completed ? "completed" : failed ? "failed" : "ambiguous",
1402
+ state: completed ? "completed" : failed ? "failed" : intentPending ? "intent_pending" : "ambiguous",
1116
1403
  mutation_state: completed ? "completed" : failed ? "not_started" : "ambiguous",
1117
1404
  response_status: response.status,
1405
+ ...(intentPending ? {
1406
+ last_error_code: "PAYMENT_INTENT_PENDING",
1407
+ ...(nonEmptyHeader(response, "x-run402-payment-id")
1408
+ ? { payment_id: nonEmptyHeader(response, "x-run402-payment-id") }
1409
+ : {}),
1410
+ intent_state: "pending",
1411
+ ...(retryAfter !== null ? { retry_after_seconds: retryAfter } : {}),
1412
+ } : {}),
1118
1413
  });
1414
+ if (intentPending)
1415
+ return response;
1119
1416
  if (!completed && !failed) {
1120
1417
  throw new PaymentAttemptError({
1121
1418
  code: "X402_PAYMENT_OUTCOME_AMBIGUOUS",
@@ -1225,6 +1522,9 @@ function claimIntent(context, store, now) {
1225
1522
  method: context.request.method,
1226
1523
  origin: context.request.origin,
1227
1524
  path_sha256: context.request.path_sha256,
1525
+ ...(context.request.caller_key_sha256
1526
+ ? { caller_key_sha256: context.request.caller_key_sha256 }
1527
+ : {}),
1228
1528
  created_at: context.createdAt,
1229
1529
  updated_at: updatedAt,
1230
1530
  };
@@ -1239,6 +1539,29 @@ function claimIntent(context, store, now) {
1239
1539
  throw new AttemptJournalWriteError(cause);
1240
1540
  }
1241
1541
  }
1542
+ function trustedRun402ResponseOrigin(requestUrl, response) {
1543
+ if (!response.url || response.redirected)
1544
+ return false;
1545
+ try {
1546
+ const request = new URL(requestUrl);
1547
+ const returned = new URL(response.url);
1548
+ return request.origin === returned.origin && isTrustedRun402PaymentUrl(request);
1549
+ }
1550
+ catch {
1551
+ return false;
1552
+ }
1553
+ }
1554
+ function retryAfterSeconds(response) {
1555
+ const raw = response.headers.get("retry-after");
1556
+ if (!raw || !/^\d+$/.test(raw))
1557
+ return null;
1558
+ const seconds = Number(raw);
1559
+ return Number.isSafeInteger(seconds) ? seconds : null;
1560
+ }
1561
+ function nonEmptyHeader(response, name) {
1562
+ const value = response.headers.get(name)?.trim();
1563
+ return value ? value : null;
1564
+ }
1242
1565
  function writeRecord(context, store, patch) {
1243
1566
  if (!context.record)
1244
1567
  throw new AttemptJournalWriteError("payment intent missing");