@bosonprotocol/x402-server 0.1.0-alpha-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.
Files changed (53) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +65 -0
  3. package/dist/cjs/challenge/index.d.ts +64 -0
  4. package/dist/cjs/challenge/index.js +96 -0
  5. package/dist/cjs/challenge/index.js.map +1 -0
  6. package/dist/cjs/client-tnrpqVMW.d.ts +36 -0
  7. package/dist/cjs/config-CBr9qMps.d.ts +419 -0
  8. package/dist/cjs/facilitator/index.d.ts +26 -0
  9. package/dist/cjs/facilitator/index.js +136 -0
  10. package/dist/cjs/facilitator/index.js.map +1 -0
  11. package/dist/cjs/handlers/index.d.ts +267 -0
  12. package/dist/cjs/handlers/index.js +1182 -0
  13. package/dist/cjs/handlers/index.js.map +1 -0
  14. package/dist/cjs/index.d.ts +72 -0
  15. package/dist/cjs/index.js +1643 -0
  16. package/dist/cjs/index.js.map +1 -0
  17. package/dist/cjs/onchain/index.d.ts +73 -0
  18. package/dist/cjs/onchain/index.js +87 -0
  19. package/dist/cjs/onchain/index.js.map +1 -0
  20. package/dist/cjs/package.json +3 -0
  21. package/dist/cjs/validate/index.d.ts +67 -0
  22. package/dist/cjs/validate/index.js +429 -0
  23. package/dist/cjs/validate/index.js.map +1 -0
  24. package/dist/esm/challenge/index.js +3 -0
  25. package/dist/esm/challenge/index.js.map +1 -0
  26. package/dist/esm/chunk-4NQ3VKC3.js +84 -0
  27. package/dist/esm/chunk-4NQ3VKC3.js.map +1 -0
  28. package/dist/esm/chunk-CGVXQX5V.js +426 -0
  29. package/dist/esm/chunk-CGVXQX5V.js.map +1 -0
  30. package/dist/esm/chunk-DJMCSCBE.js +3 -0
  31. package/dist/esm/chunk-DJMCSCBE.js.map +1 -0
  32. package/dist/esm/chunk-EAKQ4EFZ.js +124 -0
  33. package/dist/esm/chunk-EAKQ4EFZ.js.map +1 -0
  34. package/dist/esm/chunk-GBPU373M.js +93 -0
  35. package/dist/esm/chunk-GBPU373M.js.map +1 -0
  36. package/dist/esm/chunk-PU5Y7FZG.js +14 -0
  37. package/dist/esm/chunk-PU5Y7FZG.js.map +1 -0
  38. package/dist/esm/chunk-WU7QJ7YP.js +3 -0
  39. package/dist/esm/chunk-WU7QJ7YP.js.map +1 -0
  40. package/dist/esm/chunk-Y5HFLCAT.js +657 -0
  41. package/dist/esm/chunk-Y5HFLCAT.js.map +1 -0
  42. package/dist/esm/facilitator/index.js +4 -0
  43. package/dist/esm/facilitator/index.js.map +1 -0
  44. package/dist/esm/handlers/index.js +6 -0
  45. package/dist/esm/handlers/index.js.map +1 -0
  46. package/dist/esm/index.js +261 -0
  47. package/dist/esm/index.js.map +1 -0
  48. package/dist/esm/onchain/index.js +4 -0
  49. package/dist/esm/onchain/index.js.map +1 -0
  50. package/dist/esm/package.json +3 -0
  51. package/dist/esm/validate/index.js +4 -0
  52. package/dist/esm/validate/index.js.map +1 -0
  53. package/package.json +88 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/facilitator/client.ts"],"names":[],"mappings":"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","file":"chunk-EAKQ4EFZ.js","sourcesContent":["// HTTP client for the Boson facilitator service. The facilitator runs\n// as a remote process implementing the three endpoints in\n// docs/boson-impl-07-facilitator.md (`/verify`, `/settle`,\n// `/perform-action?action=<action>`); this module wraps `fetch` with the typed\n// request/response shapes exported by `@bosonprotocol/x402-facilitator`.\n//\n// Domain results (`{ ok: true, ... }` or `{ ok: false, code, reason }`)\n// are returned verbatim — both shapes are answers the caller branches\n// on. The facilitator-express adapter emits domain failures over HTTP\n// 400 (so curl users still see a 4xx), but the wire body is still a\n// well-formed result; we recognise that shape on HTTP 400 responses and\n// hand it back rather than throwing. HTTP-transport failures (network\n// down, non-JSON body, schema-mismatched body) throw\n// `FacilitatorHttpError` so the composition layer can distinguish\n// \"facilitator said no\" from \"we couldn't reach the facilitator\".\n\nimport type {\n FacilitatorErrorCode,\n FacilitatorPerformActionInput,\n FacilitatorPerformActionResult,\n FacilitatorSettleInput,\n FacilitatorSettleResult,\n FacilitatorVerifyInput,\n FacilitatorVerifyResult,\n} from \"@bosonprotocol/x402-facilitator\";\n\nimport { FacilitatorHttpError } from \"./errors.js\";\n\nexport type FetchLike = (\n input: string,\n init?: { method?: string; headers?: Record<string, string>; body?: string },\n) => Promise<{\n ok: boolean;\n status: number;\n text: () => Promise<string>;\n json?: () => Promise<unknown>;\n}>;\n\nexport interface CreateFacilitatorClientOptions {\n /** Base URL of the facilitator service (no trailing slash needed). */\n url: string;\n /** Optional `fetch` override — defaults to the global `fetch`. Useful for tests + non-`fetch` runtimes. */\n fetch?: FetchLike;\n /** Optional headers attached to every request — e.g. an `Authorization` for hosted facilitators. */\n headers?: Record<string, string>;\n}\n\nexport interface FacilitatorClient {\n verify(input: FacilitatorVerifyInput): Promise<FacilitatorVerifyResult>;\n settle(input: FacilitatorSettleInput): Promise<FacilitatorSettleResult>;\n performAction(input: FacilitatorPerformActionInput): Promise<FacilitatorPerformActionResult>;\n}\n\n/**\n * Construct a typed HTTP client for the facilitator. The returned\n * methods stringify the input as JSON and POST to the matching path\n * on the configured URL. Bodies matching the well-formed result shape\n * (whether HTTP 2xx success or HTTP 400 domain rejection) are returned\n * verbatim; transport failures (network, non-JSON body,\n * schema-mismatched body) raise `FacilitatorHttpError`.\n */\nexport function createFacilitatorClient(opts: CreateFacilitatorClientOptions): FacilitatorClient {\n const fetchImpl = opts.fetch ?? (globalThis.fetch as FetchLike | undefined);\n if (fetchImpl === undefined) {\n throw new Error(\n \"createFacilitatorClient: no `fetch` implementation available. Pass `opts.fetch` explicitly.\",\n );\n }\n const baseUrl = opts.url.replace(/\\/+$/, \"\");\n const baseHeaders = { \"content-type\": \"application/json\", ...(opts.headers ?? {}) };\n\n const post = async <Req, Res>(\n path: string,\n body: Req,\n validate: (parsed: unknown) => parsed is Res,\n ): Promise<Res> => {\n let res: Awaited<ReturnType<FetchLike>>;\n try {\n res = await fetchImpl(`${baseUrl}${path}`, {\n method: \"POST\",\n headers: baseHeaders,\n body: JSON.stringify(body),\n });\n } catch (cause) {\n throw new FacilitatorHttpError(`facilitator network error (${path})`, {\n code: \"NETWORK_ERROR\",\n cause,\n });\n }\n\n let text: string;\n try {\n text = await res.text();\n } catch (cause) {\n throw new FacilitatorHttpError(`facilitator response body could not be read (${path})`, {\n code: \"BAD_RESPONSE_BODY\",\n status: res.status,\n cause,\n });\n }\n\n let parsed: unknown;\n try {\n parsed = text.length === 0 ? null : JSON.parse(text);\n } catch (cause) {\n throw new FacilitatorHttpError(`facilitator returned non-JSON body (${path})`, {\n code: \"BAD_RESPONSE_BODY\",\n status: res.status,\n cause,\n });\n }\n\n if (!res.ok) {\n // The facilitator-express adapter returns domain failures as\n // HTTP 400 with the `{ok:false, code, reason}` body. Detect that\n // shape and surface it as the typed result — every endpoint's\n // `Res` union includes the same `{ok:false, code, reason}`\n // variant, so the cast through `validate` (which also accepts\n // that shape) preserves type-safety. Any other non-2xx status is\n // a genuine transport failure even if its body happens to look\n // like a facilitator result.\n if (res.status === 400 && isFailureBranch(parsed) && validate(parsed)) {\n return parsed;\n }\n const facilitatorCode = extractFacilitatorCode(parsed);\n throw new FacilitatorHttpError(\n `facilitator HTTP ${res.status} (${path}): ${reasonString(parsed) ?? text}`,\n {\n code: \"BAD_HTTP_STATUS\",\n status: res.status,\n ...(facilitatorCode !== undefined ? { facilitatorCode } : {}),\n },\n );\n }\n\n if (!validate(parsed)) {\n throw new FacilitatorHttpError(`facilitator returned unexpected body shape (${path})`, {\n code: \"BAD_RESPONSE_BODY\",\n status: res.status,\n });\n }\n return parsed;\n };\n\n return {\n verify: (input) =>\n post<FacilitatorVerifyInput, FacilitatorVerifyResult>(\"/verify\", input, isVerifyResult),\n settle: (input) =>\n post<FacilitatorSettleInput, FacilitatorSettleResult>(\"/settle\", input, isSettleResult),\n performAction: (input) =>\n post<FacilitatorPerformActionInput, FacilitatorPerformActionResult>(\n `/perform-action?action=${encodeURIComponent(input.action)}`,\n input,\n isPerformActionResult,\n ),\n };\n}\n\n// --- Response-shape type guards ----------------------------------------\n//\n// A buggy or malicious facilitator could return any 2xx JSON; without a\n// runtime check, `parsed as Res` would silently slip an unexpected shape\n// past the type system and the convenience handlers (PR 4) would\n// dereference fields that aren't there. These guards mirror the\n// discriminated unions in `@bosonprotocol/x402-facilitator`'s types and\n// fail any response that doesn't fit — surfaced as\n// `BAD_RESPONSE_BODY` so the caller treats it as a transport-layer\n// failure rather than a domain answer.\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === \"object\";\n}\n\n/**\n * Failure branch is identical across all three endpoints. Accepts\n * `unknown` so the non-2xx path can pre-check the parsed body without\n * narrowing first.\n */\nfunction isFailureBranch(v: unknown): v is { ok: false; code: string; reason: string } {\n return (\n isObject(v) && v.ok === false && typeof v.code === \"string\" && typeof v.reason === \"string\"\n );\n}\n\nfunction isVerifyResult(parsed: unknown): parsed is FacilitatorVerifyResult {\n if (!isObject(parsed)) return false;\n if (parsed.ok === true) return true; // `{ ok: true }` carries no further fields\n return isFailureBranch(parsed);\n}\n\nfunction isSettleResult(parsed: unknown): parsed is FacilitatorSettleResult {\n if (!isObject(parsed)) return false;\n if (parsed.ok === true) {\n return typeof parsed.exchangeId === \"string\" && typeof parsed.txHash === \"string\";\n }\n return isFailureBranch(parsed);\n}\n\nfunction isPerformActionResult(parsed: unknown): parsed is FacilitatorPerformActionResult {\n if (!isObject(parsed)) return false;\n if (parsed.ok === true) {\n if (typeof parsed.txHash !== \"string\") return false;\n // Entity-keyed actions (e.g. `boson-withdrawFunds`) return just\n // `{ ok: true, txHash }` — no exchange state transition. Accept\n // that shape; only require `newExchangeState` when present.\n if (parsed.newExchangeState !== undefined && typeof parsed.newExchangeState !== \"string\") {\n return false;\n }\n if (parsed.newDisputeState !== undefined && typeof parsed.newDisputeState !== \"string\") {\n return false;\n }\n return true;\n }\n return isFailureBranch(parsed);\n}\n\nfunction extractFacilitatorCode(body: unknown): FacilitatorErrorCode | undefined {\n if (body === null || typeof body !== \"object\") return undefined;\n const code = (body as { code?: unknown }).code;\n return typeof code === \"string\" ? (code as FacilitatorErrorCode) : undefined;\n}\n\nfunction reasonString(body: unknown): string | undefined {\n if (body === null || typeof body !== \"object\") return undefined;\n const reason = (body as { reason?: unknown }).reason;\n return typeof reason === \"string\" ? reason : undefined;\n}\n"]}
@@ -0,0 +1,93 @@
1
+ import { exchanges } from '@bosonprotocol/core-sdk';
2
+ import { deriveInitialNextActions } from '@bosonprotocol/x402-actions';
3
+ import { escrowPaymentRequirementsSchema } from '@bosonprotocol/x402-core/schemes/escrow';
4
+
5
+ // src/challenge/sign-full-offer.ts
6
+ var STUB_CALLER_TAG = "@bosonprotocol/x402-server:sign-full-offer";
7
+ async function signFullOffer({
8
+ fullOffer,
9
+ signer,
10
+ escrow,
11
+ chainId
12
+ }) {
13
+ const web3Lib = buildForwardingAdapter(signer, chainId);
14
+ const result = await exchanges.handler.signFullOffer({
15
+ fullOfferArgsUnsigned: fullOffer,
16
+ contractAddress: escrow,
17
+ chainId,
18
+ web3Lib
19
+ });
20
+ return {
21
+ fullOffer,
22
+ sellerSig: result.signature,
23
+ creator: signer.address
24
+ };
25
+ }
26
+ function buildForwardingAdapter(signer, chainId) {
27
+ const unreachable = (method) => Promise.reject(
28
+ new Error(
29
+ `${STUB_CALLER_TAG}: Web3LibAdapter.${method}() called unexpectedly \u2014 sign-full-offer is a signing-only path.`
30
+ )
31
+ );
32
+ return {
33
+ uuid: `${STUB_CALLER_TAG}:forward`,
34
+ getSignerAddress: () => Promise.resolve(signer.address),
35
+ isSignerContract: () => Promise.resolve(false),
36
+ getChainId: () => Promise.resolve(chainId),
37
+ send: async (method, params) => {
38
+ if (method !== "eth_signTypedData_v4") {
39
+ throw new Error(`${STUB_CALLER_TAG}: unexpected RPC method: ${method}`);
40
+ }
41
+ const [, json] = params;
42
+ if (typeof json !== "string") {
43
+ throw new Error(`${STUB_CALLER_TAG}: eth_signTypedData_v4 payload is not a JSON string`);
44
+ }
45
+ const td = JSON.parse(json);
46
+ return signer.signTypedData({
47
+ domain: td.domain,
48
+ types: td.types,
49
+ primaryType: td.primaryType,
50
+ message: td.message
51
+ });
52
+ },
53
+ getBalance: () => unreachable("getBalance"),
54
+ estimateGas: () => unreachable("estimateGas"),
55
+ sendTransaction: () => unreachable("sendTransaction"),
56
+ call: () => unreachable("call"),
57
+ getTransactionReceipt: () => unreachable("getTransactionReceipt"),
58
+ getCurrentTimeMs: () => unreachable("getCurrentTimeMs")
59
+ };
60
+ }
61
+ function buildPaymentRequirements(args) {
62
+ const {
63
+ offer,
64
+ asset,
65
+ amount,
66
+ tokenAuthStrategies,
67
+ recipientId,
68
+ maxTimeoutSeconds,
69
+ fulfillment,
70
+ network,
71
+ escrow,
72
+ channelRegistry
73
+ } = args;
74
+ const actions = deriveInitialNextActions(channelRegistry);
75
+ const requirements = {
76
+ scheme: "escrow",
77
+ network,
78
+ asset,
79
+ amount,
80
+ escrowAddress: escrow,
81
+ recipientId,
82
+ maxTimeoutSeconds,
83
+ offer,
84
+ tokenAuthStrategies: [...tokenAuthStrategies],
85
+ ...fulfillment !== void 0 ? { fulfillment } : {},
86
+ actions
87
+ };
88
+ return escrowPaymentRequirementsSchema.parse(requirements);
89
+ }
90
+
91
+ export { buildPaymentRequirements, signFullOffer };
92
+ //# sourceMappingURL=chunk-GBPU373M.js.map
93
+ //# sourceMappingURL=chunk-GBPU373M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/challenge/sign-full-offer.ts","../../src/challenge/build-requirements.ts"],"names":[],"mappings":"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","file":"chunk-GBPU373M.js","sourcesContent":["// FullOffer signer hook — produces the seller's `BosonOfferRef` from\n// an unsigned FullOffer. Delegates directly to\n// `@bosonprotocol/core-sdk`'s `exchanges.handler.signFullOffer`,\n// supplying a forwarding `Web3LibAdapter` that routes the inner\n// `eth_signTypedData_v4` RPC call to the configured `SellerSigner`.\n//\n// Routing through core-sdk keeps the typed-data shape, EIP-712 domain\n// (salt-based `Boson Protocol` / `V2`), and offer-struct\n// canonicalisation in lock-step with the deployed protocol — we don't\n// re-derive the FullOffer EIP-712 type-list on our side.\n\nimport { exchanges } from \"@bosonprotocol/core-sdk\";\nimport type { Web3LibAdapter } from \"@bosonprotocol/common\";\nimport type { UnsignedFullOffer } from \"@bosonprotocol/x402-core/eip712\";\nimport type {\n Address,\n BosonOfferRef,\n FullOffer,\n Hex,\n} from \"@bosonprotocol/x402-core/schemes/escrow\";\n\nimport type { SellerSigner } from \"../config.js\";\n\nconst STUB_CALLER_TAG = \"@bosonprotocol/x402-server:sign-full-offer\";\n\nexport interface SignFullOfferArgs {\n fullOffer: UnsignedFullOffer;\n signer: SellerSigner;\n /** Boson Diamond address — the EIP-712 `verifyingContract`. */\n escrow: Address;\n chainId: number;\n}\n\n/**\n * Sign a FullOffer via `@bosonprotocol/core-sdk`'s `signFullOffer`\n * and return a `BosonOfferRef` ready to embed in\n * `EscrowPaymentRequirements.offer`. The seller signer is plugged\n * into core-sdk via a forwarding `Web3LibAdapter` so any viem\n * `LocalAccount` / HSM / KMS signer drops in without exposing\n * core-sdk's adapter shape in this package's public API.\n *\n * ERC-1271 contract-wallet sellers: pass the wallet's address as\n * `signer.address` and route `signer.signTypedData` to whatever\n * surface the wallet exposes — the protocol's on-chain `verifyOffer`\n * runs via `EIP712Lib.verify` which already handles both ECDSA and\n * ERC-1271 recovery.\n */\nexport async function signFullOffer({\n fullOffer,\n signer,\n escrow,\n chainId,\n}: SignFullOfferArgs): Promise<BosonOfferRef> {\n const web3Lib = buildForwardingAdapter(signer, chainId);\n const result = await exchanges.handler.signFullOffer({\n fullOfferArgsUnsigned: fullOffer as unknown as Parameters<\n typeof exchanges.handler.signFullOffer\n >[0][\"fullOfferArgsUnsigned\"],\n contractAddress: escrow,\n chainId,\n web3Lib,\n });\n return {\n fullOffer: fullOffer as unknown as FullOffer,\n sellerSig: result.signature as Hex,\n creator: signer.address,\n };\n}\n\n/**\n * Build a `Web3LibAdapter` whose `send(\"eth_signTypedData_v4\", [from, json])`\n * routes to `signer.signTypedData(...)`. core-sdk's `signFullOffer`\n * path only touches `getSignerAddress`, `getChainId`, and that one\n * `send` invocation — every other adapter method rejects so a future\n * leak into a non-signing-only path is loud rather than silent.\n */\nfunction buildForwardingAdapter(signer: SellerSigner, chainId: number): Web3LibAdapter {\n const unreachable = (method: string): Promise<never> =>\n Promise.reject(\n new Error(\n `${STUB_CALLER_TAG}: Web3LibAdapter.${method}() called unexpectedly — sign-full-offer is a signing-only path.`,\n ),\n );\n\n return {\n uuid: `${STUB_CALLER_TAG}:forward`,\n getSignerAddress: () => Promise.resolve(signer.address),\n isSignerContract: () => Promise.resolve(false),\n getChainId: () => Promise.resolve(chainId),\n send: async (method, params) => {\n if (method !== \"eth_signTypedData_v4\") {\n throw new Error(`${STUB_CALLER_TAG}: unexpected RPC method: ${method}`);\n }\n const [, json] = params as [unknown, string];\n if (typeof json !== \"string\") {\n throw new Error(`${STUB_CALLER_TAG}: eth_signTypedData_v4 payload is not a JSON string`);\n }\n const td = JSON.parse(json) as {\n domain: Record<string, unknown>;\n types: Record<string, readonly { name: string; type: string }[]>;\n primaryType: string;\n message: Record<string, unknown>;\n };\n return signer.signTypedData({\n domain: td.domain,\n types: td.types,\n primaryType: td.primaryType,\n message: td.message,\n });\n },\n getBalance: () => unreachable(\"getBalance\"),\n estimateGas: () => unreachable(\"estimateGas\"),\n sendTransaction: () => unreachable(\"sendTransaction\"),\n call: () => unreachable(\"call\"),\n getTransactionReceipt: () => unreachable(\"getTransactionReceipt\"),\n getCurrentTimeMs: () => unreachable(\"getCurrentTimeMs\"),\n };\n}\n","// 402 challenge builder — assembles an `EscrowPaymentRequirements`\n// from per-offer inputs (asset, amount, fulfillment, etc.) plus the\n// signed `BosonOfferRef` and the server's channel registry. The\n// initial `nextActions` envelope is filled via\n// `deriveInitialNextActions(registry)` so the legal transitions out\n// of `PRE_COMMIT` are always populated consistently.\n//\n// Source of truth: docs/boson-impl-01-escrow-scheme.md §2.\n\nimport { deriveInitialNextActions, type ChannelRegistry } from \"@bosonprotocol/x402-actions\";\nimport {\n escrowPaymentRequirementsSchema,\n type Address,\n type BosonOfferRef,\n type EscrowPaymentRequirements,\n type EvmNetwork,\n type FulfillmentRequirements,\n type TokenAuthStrategy,\n} from \"@bosonprotocol/x402-core/schemes/escrow\";\n\nexport interface BuildPaymentRequirementsArgs {\n /** Signed offer reference — usually from `signFullOffer`. */\n offer: BosonOfferRef;\n /** ERC-20 token address the buyer pays in. */\n asset: Address;\n /** Atomic amount as a decimal string (e.g. wei). */\n amount: string;\n /** Token-auth strategies the server is willing to accept. */\n tokenAuthStrategies: readonly TokenAuthStrategy[];\n /** Routing-only seller identifier — numeric sellerId, `did:boson:seller:N`, or wallet address. */\n recipientId: string;\n /** Upper bound for `validBefore` / `deadline` in token-auth payloads. */\n maxTimeoutSeconds: number;\n /** Optional fulfillment channel options. Absent or `{required: false}` means the server treats payment as fully atomic. */\n fulfillment?: FulfillmentRequirements;\n /** CAIP-2 network identifier (e.g. `eip155:8453`). */\n network: EvmNetwork;\n /** Boson Diamond address — same as `config.escrow`. */\n escrow: Address;\n /** Per-seller channel registry consumed by `deriveInitialNextActions`. */\n channelRegistry: ChannelRegistry;\n}\n\n/**\n * Build an `EscrowPaymentRequirements` body (the entry that lives\n * inside the 402 response's `accepts[]` array). The result is\n * round-tripped through `escrowPaymentRequirementsSchema` to fail\n * loudly if any caller-provided field violates the wire format.\n */\nexport function buildPaymentRequirements(\n args: BuildPaymentRequirementsArgs,\n): EscrowPaymentRequirements {\n const {\n offer,\n asset,\n amount,\n tokenAuthStrategies,\n recipientId,\n maxTimeoutSeconds,\n fulfillment,\n network,\n escrow,\n channelRegistry,\n } = args;\n\n const actions = deriveInitialNextActions(channelRegistry);\n\n const requirements: EscrowPaymentRequirements = {\n scheme: \"escrow\",\n network,\n asset,\n amount,\n escrowAddress: escrow,\n recipientId,\n maxTimeoutSeconds,\n offer,\n tokenAuthStrategies: [...tokenAuthStrategies],\n ...(fulfillment !== undefined ? { fulfillment } : {}),\n actions,\n };\n\n return escrowPaymentRequirementsSchema.parse(requirements) as EscrowPaymentRequirements;\n}\n"]}
@@ -0,0 +1,14 @@
1
+ // src/facilitator/errors.ts
2
+ var FacilitatorHttpError = class extends Error {
3
+ constructor(message, init) {
4
+ super(message, init.cause !== void 0 ? { cause: init.cause } : void 0);
5
+ this.name = "FacilitatorHttpError";
6
+ this.code = init.code;
7
+ if (init.status !== void 0) this.status = init.status;
8
+ if (init.facilitatorCode !== void 0) this.facilitatorCode = init.facilitatorCode;
9
+ }
10
+ };
11
+
12
+ export { FacilitatorHttpError };
13
+ //# sourceMappingURL=chunk-PU5Y7FZG.js.map
14
+ //# sourceMappingURL=chunk-PU5Y7FZG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/facilitator/errors.ts"],"names":[],"mappings":";AAqBO,IAAM,oBAAA,GAAN,cAAmC,KAAA,CAAM;AAAA,EAM9C,WAAA,CACE,SACA,IAAA,EAMA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,KAAK,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM,GAAI,MAAS,CAAA;AAC3E,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AACZ,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AAClD,IAAA,IAAI,IAAA,CAAK,eAAA,KAAoB,MAAA,EAAW,IAAA,CAAK,kBAAkB,IAAA,CAAK,eAAA;AAAA,EACtE;AACF","file":"chunk-PU5Y7FZG.js","sourcesContent":["// Typed error class for HTTP-level facilitator failures. Distinct from\n// the `{ ok: false, code }` shape the facilitator itself returns —\n// those are domain errors and surface in the typed result. This class\n// is thrown only when the HTTP transport fails (network error,\n// non-2xx response with an unparseable body, etc.).\n\nimport type { FacilitatorErrorCode } from \"@bosonprotocol/x402-facilitator\";\n\n/**\n * Stable, x402-server-side codes for HTTP-transport failures.\n * Distinct from the facilitator-side `FacilitatorErrorCode` enum so\n * callers can branch on \"the facilitator answered with X\" vs \"we\n * never reached the facilitator\".\n */\nexport type FacilitatorHttpErrorCode =\n | \"NETWORK_ERROR\"\n | \"BAD_HTTP_STATUS\"\n | \"BAD_RESPONSE_BODY\"\n | \"TIMEOUT\";\n\n/** Network- or transport-layer failure when calling the facilitator. */\nexport class FacilitatorHttpError extends Error {\n readonly code: FacilitatorHttpErrorCode;\n readonly status?: number;\n /** Original facilitator-side error code, if the body parsed cleanly. */\n readonly facilitatorCode?: FacilitatorErrorCode;\n\n constructor(\n message: string,\n init: {\n code: FacilitatorHttpErrorCode;\n status?: number;\n facilitatorCode?: FacilitatorErrorCode;\n cause?: unknown;\n },\n ) {\n super(message, init.cause !== undefined ? { cause: init.cause } : undefined);\n this.name = \"FacilitatorHttpError\";\n this.code = init.code;\n if (init.status !== undefined) this.status = init.status;\n if (init.facilitatorCode !== undefined) this.facilitatorCode = init.facilitatorCode;\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-WU7QJ7YP.js.map
3
+ //# sourceMappingURL=chunk-WU7QJ7YP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-WU7QJ7YP.js"}