@piprail/sdk 1.22.1 → 1.24.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/index.cjs CHANGED
@@ -511,7 +511,6 @@ function sumTransfersTo(logs, asset, payTo) {
511
511
  var EXACT_NETWORK_SLUGS = {
512
512
  ethereum: 1,
513
513
  base: 8453,
514
- "base-sepolia": 84532,
515
514
  arbitrum: 42161,
516
515
  optimism: 10,
517
516
  polygon: 137,
@@ -983,8 +982,6 @@ var PERMIT2_PROXY_CHAIN_IDS = /* @__PURE__ */ new Set([
983
982
  // Ethereum
984
983
  8453,
985
984
  // Base
986
- 84532,
987
- // Base Sepolia
988
985
  42161,
989
986
  // Arbitrum
990
987
  10,
@@ -3496,6 +3493,33 @@ function rankOptions(options) {
3496
3493
  return 0;
3497
3494
  });
3498
3495
  }
3496
+ function rankAcross(plans) {
3497
+ const rank = { payable: 0, unknown: 1, blocked: 2 };
3498
+ return plans.flatMap((p) => p.options).sort((a, b) => rank[a.state] - rank[b.state]);
3499
+ }
3500
+ async function planEachClient(clients, url, init) {
3501
+ const settled = await Promise.allSettled(clients.map((c) => c.planPayment(url, init)));
3502
+ const live = [];
3503
+ let anyReached = false;
3504
+ let firstError;
3505
+ settled.forEach((s, i) => {
3506
+ if (s.status === "fulfilled") {
3507
+ anyReached = true;
3508
+ if (s.value != null) live.push({ client: clients[i], plan: s.value });
3509
+ } else if (firstError === void 0) {
3510
+ firstError = s.reason;
3511
+ }
3512
+ });
3513
+ if (live.length === 0 && !anyReached) {
3514
+ throw _nullishCoalesce(firstError, () => ( new Error("planAcross: every client failed to reach the resource.")));
3515
+ }
3516
+ return live;
3517
+ }
3518
+ function mergeDeclineHint(plans) {
3519
+ const actionable = plans.filter((p) => p.options.length > 0 && p.fundingHint).map((p) => p.fundingHint);
3520
+ const chosen = actionable.length ? actionable : plans.map((p) => p.fundingHint).filter(Boolean);
3521
+ return chosen.length ? [...new Set(chosen)].join(" \xB7 ") : null;
3522
+ }
3499
3523
  function buildFundingHint(options, chainLabel) {
3500
3524
  if (options.length === 0) return null;
3501
3525
  const target = [...options].sort((a, b) => a.blockers.length - b.blockers.length)[0];
@@ -3522,10 +3546,10 @@ function buildFundingHint(options, chainLabel) {
3522
3546
  return parts.length ? `Can't settle on ${chainLabel}: ${parts.join(" and ")} (to pay ${target.quote.amountFormatted} ${sym}).` : `Can't settle on ${chainLabel} for ${target.quote.amountFormatted} ${sym}.`;
3523
3547
  }
3524
3548
  async function planAcross(clients, url, init) {
3525
- const plans = await Promise.all(clients.map((c) => c.planPayment(url, init).catch(() => null)));
3526
- const live = plans.filter((p) => p != null);
3549
+ if (clients.length === 0) return null;
3550
+ const live = (await planEachClient(clients, url, init)).map((p) => p.plan);
3527
3551
  if (live.length === 0) return null;
3528
- const options = rankOptions(live.flatMap((p) => p.options));
3552
+ const options = rankAcross(live);
3529
3553
  const best = _nullishCoalesce(options.find((o) => o.state === "payable"), () => ( null));
3530
3554
  const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
3531
3555
  return {
@@ -3535,10 +3559,25 @@ async function planAcross(clients, url, init) {
3535
3559
  payable: best !== null,
3536
3560
  best,
3537
3561
  options,
3538
- // First non-null hint across clients each already names its chain.
3539
- fundingHint: best ? null : _nullishCoalesce(live.map((p) => p.fundingHint).find(Boolean), () => ( null))
3562
+ // Merge EVERY funded chain's blocker into one clear sentence (not just the first) —
3563
+ // see mergeDeclineHint. `null` when a rail is payable.
3564
+ fundingHint: best ? null : mergeDeclineHint(live)
3540
3565
  };
3541
3566
  }
3567
+ async function fetchAcross(clients, url, init) {
3568
+ if (clients.length === 0) {
3569
+ throw new TypeError("fetchAcross needs at least one PipRailClient.");
3570
+ }
3571
+ const live = await planEachClient(clients, url, init);
3572
+ if (live.length === 0) return clients[0].fetch(url, init);
3573
+ const best = rankAcross(live.map((p) => p.plan)).find((o) => o.state === "payable");
3574
+ if (!best) {
3575
+ const hint = mergeDeclineHint(live.map((p) => p.plan));
3576
+ throw new (0, _chunkU35MG4TFcjs.PaymentDeclinedError)(hint || "No funded chain can settle this payment right now.");
3577
+ }
3578
+ const owner = live.find((p) => p.plan.options.includes(best)).client;
3579
+ return owner.fetch(url, { ..._nullishCoalesce(init, () => ( {})), autoRoute: true });
3580
+ }
3542
3581
  function railOnNetwork(rail, matches) {
3543
3582
  const n = normalizeNetwork(rail.network);
3544
3583
  return !n.includes(":") || matches(n);
@@ -3604,6 +3643,229 @@ async function readInvalidReason(response) {
3604
3643
  return null;
3605
3644
  }
3606
3645
 
3646
+ // src/payer.ts
3647
+ var MultiChainPayer = class _MultiChainPayer {
3648
+
3649
+ /**
3650
+ * Wrap an explicit, ordered set of single-chain clients — use this when a client
3651
+ * needs full control (e.g. a custom EVM chain configured by a viem `Chain`). The
3652
+ * ORDER is your chain preference: across chains the first that can settle wins. Pass
3653
+ * at MOST one client per chain — two clients on the SAME network would double-count in
3654
+ * `spent()`/`budget()` and waste a plan round-trip (`fromWallets` can't produce this).
3655
+ * For the common case, prefer {@link MultiChainPayer.fromWallets}.
3656
+ */
3657
+ constructor(clients) {
3658
+ if (clients.length === 0) {
3659
+ throw new TypeError("MultiChainPayer needs at least one PipRailClient.");
3660
+ }
3661
+ this._clients = [...clients];
3662
+ }
3663
+ /**
3664
+ * Build one client per funded chain from a `{ chain → wallet }` map — the
3665
+ * ergonomic path. The shared `policy`/`schemes`/`onBeforePay`/`onEvent` apply to
3666
+ * every client; `rpcUrls` are matched per chain. Iteration order of `wallets` is
3667
+ * the chain preference.
3668
+ *
3669
+ * ```ts
3670
+ * const payer = MultiChainPayer.fromWallets({
3671
+ * wallets: {
3672
+ * base: { privateKey: process.env.EVM_KEY! },
3673
+ * solana: { secretKey: process.env.SOLANA_SECRET! },
3674
+ * xrpl: { seed: process.env.XRPL_SEED! },
3675
+ * },
3676
+ * policy: { maxAmount: '1.00', maxTotal: '20.00', tokens: ['USDC', 'USDT'] },
3677
+ * })
3678
+ * const res = await payer.get('https://api.example.com/paid') // pays on the first funded chain that can settle
3679
+ * ```
3680
+ */
3681
+ static fromWallets(opts) {
3682
+ const entries = Object.entries(opts.wallets);
3683
+ if (entries.length === 0) {
3684
+ throw new TypeError("MultiChainPayer.fromWallets needs at least one wallet.");
3685
+ }
3686
+ const clients = entries.map(
3687
+ ([chain, wallet]) => new PipRailClient({
3688
+ chain,
3689
+ wallet,
3690
+ ...opts.policy ? { policy: opts.policy } : {},
3691
+ ...opts.schemes ? { schemes: opts.schemes } : {},
3692
+ ..._optionalChain([opts, 'access', _64 => _64.rpcUrls, 'optionalAccess', _65 => _65[chain]]) ? { rpcUrl: opts.rpcUrls[chain] } : {},
3693
+ ...opts.onBeforePay ? { onBeforePay: opts.onBeforePay } : {},
3694
+ ...opts.onEvent ? { onEvent: opts.onEvent } : {},
3695
+ ...opts.maxPaymentRetries != null ? { maxPaymentRetries: opts.maxPaymentRetries } : {},
3696
+ ...opts.retryTimeoutMs != null ? { retryTimeoutMs: opts.retryTimeoutMs } : {}
3697
+ })
3698
+ );
3699
+ return new _MultiChainPayer(clients);
3700
+ }
3701
+ /** The underlying single-chain clients, in preference order. Reach for one of
3702
+ * these for chain-specific reads (`estimateCost`, `discoverySigner`, per-chain
3703
+ * `budget()`) that don't make sense merged. */
3704
+ get clients() {
3705
+ return this._clients;
3706
+ }
3707
+ /** Plan a 402 across every funded chain — merged + ranked payable-first. `null`
3708
+ * when the URL needs no payment. (Delegates to {@link planAcross}.) */
3709
+ planPayment(url, init) {
3710
+ return planAcross(this._clients, url, init);
3711
+ }
3712
+ /** Can ANY funded chain settle this URL right now? (A free resource is trivially
3713
+ * "affordable".) No funds move. */
3714
+ async canAfford(url, init) {
3715
+ const plan = await this.planPayment(url, init);
3716
+ return plan == null ? true : plan.payable;
3717
+ }
3718
+ /** Price a gated URL across funded chains — the chosen rail's quote (the first
3719
+ * funded chain that can settle), else the first offered rail's. `null` when the URL
3720
+ * needs no payment. When it IS
3721
+ * gated but none of your chains are offered, surfaces the same informative
3722
+ * `NoCompatibleAcceptError` a single client would (it names the chains the 402 is
3723
+ * payable on) rather than a misleading `null`. No funds move. */
3724
+ async quote(url, init) {
3725
+ const plan = await this.planPayment(url, init);
3726
+ if (plan == null) return null;
3727
+ const opt = _nullishCoalesce(plan.best, () => ( plan.options[0]));
3728
+ if (opt) return opt.quote;
3729
+ return this._clients[0].quote(url, init);
3730
+ }
3731
+ /** Pay the first funded chain (in your listed order) that can settle this URL.
3732
+ * Delegates to {@link fetchAcross} — full policy / approval / retry / replay path on
3733
+ * the owning client. The owner re-reads balances at pay time, so the rail paid is the
3734
+ * surfaced `best` on a best-effort basis (it can pick another rail on the SAME chain,
3735
+ * or decline, if balances shift between plan and pay). PROBES the URL with `init`
3736
+ * (method + body) per client — prefer GET / idempotent requests. */
3737
+ fetch(url, init) {
3738
+ return fetchAcross(this._clients, url, init);
3739
+ }
3740
+ /** GET that auto-pays across chains. */
3741
+ get(url, init) {
3742
+ return this.fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: "GET" });
3743
+ }
3744
+ /**
3745
+ * POST that auto-pays across chains. `body` is a string/FormData/URLSearchParams/
3746
+ * ArrayBuffer/Blob (sent as-is) or a plain object (serialised as JSON) — mirrors
3747
+ * {@link PipRailClient.post}.
3748
+ */
3749
+ post(url, body, init) {
3750
+ const headers = new Headers(_optionalChain([init, 'optionalAccess', _66 => _66.headers]));
3751
+ let payload;
3752
+ if (body === void 0 || body === null) {
3753
+ payload = void 0;
3754
+ } else if (isBodyInit(body)) {
3755
+ payload = body;
3756
+ } else if (typeof body === "object") {
3757
+ payload = JSON.stringify(body);
3758
+ if (!headers.has("content-type")) headers.set("content-type", "application/json");
3759
+ } else {
3760
+ payload = String(body);
3761
+ }
3762
+ return this.fetch(url, { ..._nullishCoalesce(init, () => ( {})), method: "POST", headers, body: payload });
3763
+ }
3764
+ /**
3765
+ * Find payable resources across every funded chain. With the default
3766
+ * `network: 'self'`, each chain's own results are merged + deduped by URL (so
3767
+ * "self" means "any chain I can pay"). A network-scoped query (a CAIP-2 id or
3768
+ * `'any'`) is chain-independent, so one client answers it. Never throws for a
3769
+ * read problem; moves no funds.
3770
+ */
3771
+ async discover(opts = {}) {
3772
+ if (opts.network && opts.network !== "self") {
3773
+ return this._clients[0].discover(opts);
3774
+ }
3775
+ const perChain = await Promise.all(
3776
+ this._clients.map((c) => c.discover({ ...opts, network: "self" }).catch(() => []))
3777
+ );
3778
+ const seen = /* @__PURE__ */ new Set();
3779
+ const merged = [];
3780
+ for (const r of perChain.flat()) {
3781
+ if (seen.has(r.resource)) continue;
3782
+ seen.add(r.resource);
3783
+ merged.push(r);
3784
+ }
3785
+ return merged;
3786
+ }
3787
+ /** List a resource YOU run on the open indexes. Registration is a merchant action
3788
+ * independent of which chain you pay FROM, so it goes through your first chain's
3789
+ * client; pass `opts.network` to advertise a specific chain. Moves no funds. */
3790
+ register(url, opts = {}) {
3791
+ return this._clients[0].register(url, opts);
3792
+ }
3793
+ /** Aggregate spend across every chain — counts summed; per-(network,asset) rows
3794
+ * and records concatenated (no cross-chain collisions, never a cross-token sum). */
3795
+ spent() {
3796
+ const summaries = this._clients.map((c) => c.spent());
3797
+ return {
3798
+ count: summaries.reduce((n, s) => n + s.count, 0),
3799
+ byAsset: summaries.flatMap((s) => s.byAsset),
3800
+ records: summaries.flatMap((s) => s.records)
3801
+ };
3802
+ }
3803
+ /** A merged budget view: every chain's per-(network,asset) remaining rows, plus the
3804
+ * MOST-RESTRICTIVE session time envelope across chains (the soonest deadline wins).
3805
+ * Mirrors {@link PipRailClient.budget}'s shape so the agent toolkit reads it
3806
+ * unchanged; per-chain session detail is on each `clients[i].budget()`. */
3807
+ budget() {
3808
+ const budgets = this._clients.map((c) => c.budget());
3809
+ const session = budgets.map((b) => b.session).reduce((soonest, s) => {
3810
+ if (soonest.secondsRemaining == null) return s;
3811
+ if (s.secondsRemaining == null) return soonest;
3812
+ return s.secondsRemaining < soonest.secondsRemaining ? s : soonest;
3813
+ });
3814
+ return { session, byAsset: budgets.flatMap((b) => b.byAsset) };
3815
+ }
3816
+ };
3817
+ function isBodyInit(value) {
3818
+ if (typeof value === "string") return true;
3819
+ if (value instanceof ArrayBuffer) return true;
3820
+ if (ArrayBuffer.isView(value)) return true;
3821
+ if (typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams) return true;
3822
+ if (typeof FormData !== "undefined" && value instanceof FormData) return true;
3823
+ if (typeof Blob !== "undefined" && value instanceof Blob) return true;
3824
+ return false;
3825
+ }
3826
+
3827
+ // src/selfdescribe.ts
3828
+ var BRAND = {
3829
+ name: "PipRail",
3830
+ home: "https://piprail.com",
3831
+ docs: "https://docs.piprail.com",
3832
+ payDocs: "https://docs.piprail.com/paying",
3833
+ sdkInstall: "npm i @piprail/sdk",
3834
+ sdkSnippet: "import { PipRailClient } from '@piprail/sdk'\nconst client = new PipRailClient({ chain: '<your-chain>', wallet })\nawait client.fetch('<this-url>')",
3835
+ mcpRun: "npx -y @piprail/mcp"
3836
+ };
3837
+ var WHAT = 'This is an x402 "402 Payment Required" endpoint. Pay one of the offered rails to access it.';
3838
+ function howFor(scheme) {
3839
+ return scheme === "exact" ? "Standard x402 exact rail \u2014 sign an EIP-3009 / Permit2 / SVM authorization; any stock x402 client (e.g. @x402/fetch) can pay this." : "Pay this amount on-chain to payTo, then resubmit with a payment-signature header carrying the proof ref + nonce. Easiest with @piprail/sdk (see sdk.install).";
3840
+ }
3841
+ function railOf(a) {
3842
+ const extra = _nullishCoalesce(a.extra, () => ( {}));
3843
+ return {
3844
+ scheme: a.scheme,
3845
+ network: a.network,
3846
+ asset: a.asset,
3847
+ payTo: a.payTo,
3848
+ amount: a.amount,
3849
+ ...extra.amountFormatted ? { amountFormatted: extra.amountFormatted } : {},
3850
+ ...extra.symbol ? { symbol: extra.symbol } : {},
3851
+ how: howFor(a.scheme)
3852
+ };
3853
+ }
3854
+ function buildSelfDescription(input) {
3855
+ return {
3856
+ name: "PipRail",
3857
+ protocol: "x402",
3858
+ version: "2",
3859
+ what: WHAT,
3860
+ pay: input.accepts.map(railOf),
3861
+ sdk: { install: BRAND.sdkInstall, snippet: BRAND.sdkSnippet },
3862
+ mcp: { run: BRAND.mcpRun, tool: "piprail_pay_request" },
3863
+ docs: { home: BRAND.home, agents: BRAND.docs, pay: BRAND.payDocs },
3864
+ discovery: { openapi: "/openapi.json", wellKnown: "/.well-known/x402" },
3865
+ ...input.instruction ? { instruction: input.instruction } : {}
3866
+ };
3867
+ }
3868
+
3607
3869
  // src/render.ts
3608
3870
  function summarizePlan(plan) {
3609
3871
  if (plan == null) return "No payment required \u2014 the URL is not payment-gated.";
@@ -3644,6 +3906,18 @@ function formatSpendReport(summary) {
3644
3906
  (a) => `${a.totalFormatted} ${_nullishCoalesce(a.symbol, () => ( a.asset))} on ${a.network} (${a.count} payment${a.count === 1 ? "" : "s"})`
3645
3907
  ).join("; ");
3646
3908
  }
3909
+ function describeChallenge(challenge) {
3910
+ const first = challenge.accepts[0];
3911
+ if (!first) {
3912
+ return `${BRAND.name} x402 payment endpoint. Pay with @piprail/sdk (${BRAND.sdkInstall}). Docs: ${BRAND.home}.`;
3913
+ }
3914
+ const extra = _nullishCoalesce(first.extra, () => ( {}));
3915
+ const amount = _nullishCoalesce(extra.amountFormatted, () => ( first.amount));
3916
+ const token = _nullishCoalesce(extra.symbol, () => ( first.asset));
3917
+ const hasExact = challenge.accepts.some((a) => a.scheme === "exact");
3918
+ const standard = hasExact ? "; or any standard x402 client (an exact rail is offered)" : "";
3919
+ return `${BRAND.name} x402 payment endpoint \u2014 pay ${amount} ${token} on ${first.network} to ${first.payTo}. Programmatic: ${BRAND.sdkInstall} then client.fetch(url)${standard}. Docs: ${BRAND.home}.`;
3920
+ }
3647
3921
 
3648
3922
  // src/agentGuide.ts
3649
3923
  var PIPRAIL_AGENT_GUIDE = `# Paying with PipRail \u2014 the agent contract
@@ -3651,6 +3925,13 @@ var PIPRAIL_AGENT_GUIDE = `# Paying with PipRail \u2014 the agent contract
3651
3925
  You can pay for x402 "402 Payment Required" resources autonomously. Money moves
3652
3926
  straight from your wallet to the server; PipRail custodies nothing. Follow this.
3653
3927
 
3928
+ ## Landing cold \u2014 read the self-description
3929
+ Every PipRail 402 self-describes. Read challenge.extensions.piprail for { name, what, pay[]
3930
+ (each rail's how-to-pay), sdk.install, mcp, docs } \u2014 never guess what an endpoint is. If your
3931
+ tooling can't pay a rail (e.g. a stock x402 client can't pay the onchain-proof scheme), the
3932
+ block says how: install @piprail/sdk (npm i @piprail/sdk) or run the MCP (npx -y @piprail/mcp)
3933
+ and pay with the tools below.
3934
+
3654
3935
  ## The loop: quote \u2192 plan \u2192 pay
3655
3936
  1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and
3656
3937
  whether it is within your spend policy. No funds move. Use it to decide if a
@@ -3945,7 +4226,12 @@ function paymentTools(client) {
3945
4226
  url: { type: "string", description: "Full URL of the resource to list." },
3946
4227
  name: { type: "string", description: "Display name (defaults to the host)." },
3947
4228
  description: { type: "string", description: "What the resource offers." },
3948
- priceUsd: { type: "number", description: "Advertised price in USD (metadata)." }
4229
+ priceUsd: { type: "number", description: "Advertised price in USD (metadata)." },
4230
+ network: {
4231
+ type: "string",
4232
+ description: "Network slug to advertise, e.g. 'base' (defaults to the paying chain). Set it when registering from a multi-chain wallet so the listing names the right chain."
4233
+ },
4234
+ asset: { type: "string", description: "Payment asset symbol, e.g. 'USDC' (metadata)." }
3949
4235
  },
3950
4236
  required: ["url"],
3951
4237
  additionalProperties: false
@@ -3955,6 +4241,8 @@ function paymentTools(client) {
3955
4241
  if (typeof args.name === "string") opts.name = args.name;
3956
4242
  if (typeof args.description === "string") opts.description = args.description;
3957
4243
  if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
4244
+ if (typeof args.network === "string") opts.network = args.network;
4245
+ if (typeof args.asset === "string") opts.asset = args.asset;
3958
4246
  const outcomes = await client.register(String(args.url), opts);
3959
4247
  return { outcomes };
3960
4248
  }
@@ -4011,6 +4299,13 @@ function classifyChallenge(challenge, opts) {
4011
4299
 
4012
4300
  // src/discovery.ts
4013
4301
  var GENERATOR = "@piprail/sdk \xB7 https://piprail.com";
4302
+ var POWERED_BY = "PipRail x402 | https://piprail.com";
4303
+ function discoveryHeaders(opts = {}) {
4304
+ return {
4305
+ link: '</openapi.json>; rel="service-desc", </.well-known/x402>; rel="x402-discovery"',
4306
+ ...opts.attribution === false ? {} : { "x-powered-by": POWERED_BY }
4307
+ };
4308
+ }
4014
4309
  function buildBazaarExtension(descriptor = {}) {
4015
4310
  const method = (_nullishCoalesce(descriptor.method, () => ( "GET"))).toUpperCase();
4016
4311
  const queryParams = _nullishCoalesce(descriptor.queryParams, () => ( {}));
@@ -4090,6 +4385,57 @@ function buildX402DnsTxt(input) {
4090
4385
  };
4091
4386
  }
4092
4387
 
4388
+ // src/landing.ts
4389
+ function esc(s) {
4390
+ return String(_nullishCoalesce(s, () => ( ""))).replace(
4391
+ /[&<>"']/g,
4392
+ (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : c === ">" ? "&gt;" : c === '"' ? "&quot;" : "&#39;"
4393
+ );
4394
+ }
4395
+ var STYLE = `:root{color-scheme:dark}
4396
+ *{box-sizing:border-box}
4397
+ body{margin:0;background:#0a0e0f;color:#e6edf0;font:16px/1.6 ui-sans-serif,system-ui,-apple-system,Inter,sans-serif}
4398
+ main{max-width:680px;margin:0 auto;padding:48px 24px}
4399
+ h1{font-size:1.6rem;margin:0 0 .25rem}
4400
+ .lede{color:#9fb0b5;margin:.25rem 0 2rem}
4401
+ h2{font-size:1rem;text-transform:uppercase;letter-spacing:.05em;color:#34d399;margin:2rem 0 .75rem}
4402
+ table{width:100%;border-collapse:collapse;font-size:.92rem}
4403
+ th,td{text-align:left;padding:.5rem .6rem;border-bottom:1px solid #1c2426;vertical-align:top}
4404
+ th{color:#9fb0b5;font-weight:600}
4405
+ code,pre{font-family:ui-monospace,JetBrains Mono,monospace;font-size:.85rem}
4406
+ pre{background:#11181a;border:1px solid #1c2426;border-radius:8px;padding:14px;overflow-x:auto;color:#cfe9df}
4407
+ a{color:#34d399}
4408
+ .mono{font-family:ui-monospace,monospace;word-break:break-all}
4409
+ .warn{margin:0 0 2rem;padding:14px 16px;border:1px solid #5a4a1f;background:#17130a;border-radius:8px;color:#e8d9a8;font-size:.92rem;line-height:1.55}
4410
+ .warn strong{color:#f5d77a}
4411
+ .muted{color:#5b6b6f;font-weight:400;text-transform:none;letter-spacing:0;font-size:.8rem}
4412
+ footer{margin-top:2.5rem;color:#5b6b6f;font-size:.8rem}`;
4413
+ function renderLandingPage(sd) {
4414
+ const lede = esc(_nullishCoalesce(sd.instruction, () => ( sd.what)));
4415
+ const rows = sd.pay.map(
4416
+ (r) => `<tr><td><code>${esc(r.scheme)}</code></td><td>${esc(r.network)}</td><td>${esc(_nullishCoalesce(r.amountFormatted, () => ( r.amount)))} ${esc(_nullishCoalesce(r.symbol, () => ( r.asset)))}</td><td class="mono">${esc(r.payTo)}</td></tr>`
4417
+ ).join("");
4418
+ return `<!doctype html>
4419
+ <html lang="en"><head><meta charset="utf-8">
4420
+ <meta name="viewport" content="width=device-width,initial-scale=1">
4421
+ <title>${esc(sd.name)} \xB7 x402 payment required</title>
4422
+ <style>${STYLE}</style>
4423
+ </head><body><main>
4424
+ <h1>402 \u2014 Payment Required</h1>
4425
+ <p class="lede">${lede}</p>
4426
+ <div class="warn"><strong>Pay with an x402 client \u2014 not by hand.</strong> This endpoint is paid programmatically: an x402 client (the ${esc(sd.name)} SDK or MCP below, or any x402-compatible wallet) makes the payment <em>and proves it</em>, which is what unlocks the resource. Sending funds straight to the address below from an ordinary wallet will reach the merchant but <strong>will NOT unlock this resource and won't be matched to your request</strong> \u2014 there is no custody and no manual-payment desk. Use one of the methods below.</div>
4427
+ <h2>How to pay</h2>
4428
+ <pre>${esc(sd.sdk.install)}</pre>
4429
+ <pre>${esc(sd.sdk.snippet)}</pre>
4430
+ <p>For AI agents (MCP): <code>${esc(sd.mcp.run)}</code> &rarr; tool <code>${esc(sd.mcp.tool)}</code></p>
4431
+ <h2>Payment details <span class="muted">\u2014 what the client pays, NOT a manual-send address</span></h2>
4432
+ <table><thead><tr><th>Scheme</th><th>Chain</th><th>Amount</th><th>Settles to</th></tr></thead>
4433
+ <tbody>${rows}</tbody></table>
4434
+ <p>Docs: <a href="${esc(sd.docs.pay)}">paying</a> &middot; <a href="${esc(sd.docs.home)}">${esc(sd.docs.home)}</a> &middot; <a href="${esc(sd.discovery.openapi)}">${esc(sd.discovery.openapi)}</a></p>
4435
+ <footer>Powered by ${esc(sd.name)} &middot; x402 &middot; no backend, no fee, settled straight to the merchant's wallet (no custody).</footer>
4436
+ </main></body></html>`;
4437
+ }
4438
+
4093
4439
  // src/facilitator.ts
4094
4440
  async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
4095
4441
  const base2 = url.replace(/\/+$/, "");
@@ -4099,9 +4445,10 @@ async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
4099
4445
  const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
4100
4446
  if (!res.ok) return void 0;
4101
4447
  const body = await res.json();
4102
- const kinds = Array.isArray(_optionalChain([body, 'optionalAccess', _64 => _64.kinds])) ? body.kinds : [];
4103
- const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess', _65 => _65.scheme]) === "exact" && _optionalChain([k, 'optionalAccess', _66 => _66.network]) === network);
4104
- const fp = _optionalChain([kind, 'optionalAccess', _67 => _67.extra, 'optionalAccess', _68 => _68.feePayer]);
4448
+ const kinds = Array.isArray(_optionalChain([body, 'optionalAccess', _67 => _67.kinds])) ? body.kinds : [];
4449
+ const want = normalizeNetwork(network);
4450
+ const kind = kinds.find((k) => _optionalChain([k, 'optionalAccess', _68 => _68.scheme]) === "exact" && normalizeNetwork(String(_nullishCoalesce(_optionalChain([k, 'optionalAccess', _69 => _69.network]), () => ( "")))) === want);
4451
+ const fp = _optionalChain([kind, 'optionalAccess', _70 => _70.extra, 'optionalAccess', _71 => _71.feePayer]);
4105
4452
  return typeof fp === "string" ? fp : void 0;
4106
4453
  } catch (e32) {
4107
4454
  return void 0;
@@ -4109,6 +4456,33 @@ async function fetchFacilitatorFeePayer(url, network, timeoutMs = 8e3) {
4109
4456
  clearTimeout(timer);
4110
4457
  }
4111
4458
  }
4459
+ function parseFacilitatorSupported(body) {
4460
+ const kinds = _optionalChain([body, 'optionalAccess', _72 => _72.kinds]);
4461
+ if (!Array.isArray(kinds)) return [];
4462
+ const out = [];
4463
+ for (const k of kinds) {
4464
+ if (!k || typeof k !== "object") continue;
4465
+ const o = k;
4466
+ if (typeof o.scheme !== "string" || typeof o.network !== "string") continue;
4467
+ const fp = _optionalChain([o, 'access', _73 => _73.extra, 'optionalAccess', _74 => _74.feePayer]);
4468
+ out.push({ scheme: o.scheme, network: o.network, ...typeof fp === "string" ? { feePayer: fp } : {} });
4469
+ }
4470
+ return out;
4471
+ }
4472
+ async function facilitatorCoverage(url, timeoutMs = 8e3) {
4473
+ const base2 = url.replace(/\/+$/, "");
4474
+ const ctrl = new AbortController();
4475
+ const timer = setTimeout(() => ctrl.abort(), timeoutMs);
4476
+ try {
4477
+ const res = await fetch(`${base2}/supported`, { signal: ctrl.signal });
4478
+ if (!res.ok) return [];
4479
+ return parseFacilitatorSupported(await res.json());
4480
+ } catch (e33) {
4481
+ return [];
4482
+ } finally {
4483
+ clearTimeout(timer);
4484
+ }
4485
+ }
4112
4486
  function safeStringify(value) {
4113
4487
  return JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v);
4114
4488
  }
@@ -4132,7 +4506,7 @@ async function post(url, body, headers) {
4132
4506
  let json = null;
4133
4507
  try {
4134
4508
  json = await res.json();
4135
- } catch (e33) {
4509
+ } catch (e34) {
4136
4510
  }
4137
4511
  return { status: res.status, json };
4138
4512
  }
@@ -4386,22 +4760,47 @@ function createPaymentGate(options) {
4386
4760
  const specs = await ready();
4387
4761
  const nonce = genNonce();
4388
4762
  const bazaar = options.discovery ? { bazaar: buildBazaarExtension(options.discovery === true ? {} : options.discovery) } : void 0;
4389
- const extensions = { ...bazaar, ..._optionalChain([opts, 'optionalAccess', _69 => _69.extensions]) };
4763
+ const accepts = buildAccepts(specs, nonce);
4764
+ const selfDescribe = options.selfDescribe === false ? void 0 : buildSelfDescription({
4765
+ accepts,
4766
+ instruction: describeChallenge({ x402Version: 2, resource: { url: resourceUrl }, accepts })
4767
+ });
4768
+ const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _75 => _75.extensions]), () => ( {}));
4769
+ const rejectionPiprail = _nullishCoalesce(rejectionExt.piprail, () => ( {}));
4770
+ const bodyPiprail = { ..._nullishCoalesce(selfDescribe, () => ( {})), ...rejectionPiprail };
4771
+ const bodyExtensions = {
4772
+ ...bazaar,
4773
+ ...rejectionExt,
4774
+ ...Object.keys(bodyPiprail).length > 0 ? { piprail: bodyPiprail } : {}
4775
+ };
4776
+ const headerExtensions = {
4777
+ ...bazaar,
4778
+ ...Object.keys(rejectionPiprail).length > 0 ? { piprail: rejectionPiprail } : {}
4779
+ };
4390
4780
  const challenge2 = {
4391
4781
  x402Version: 2,
4392
4782
  resource: {
4393
4783
  url: resourceUrl,
4394
4784
  ...options.description ? { description: options.description } : {}
4395
4785
  },
4396
- accepts: buildAccepts(specs, nonce),
4397
- ..._optionalChain([opts, 'optionalAccess', _70 => _70.error]) ? { error: opts.error } : {},
4398
- ...Object.keys(extensions).length > 0 ? { extensions } : {}
4786
+ accepts,
4787
+ ..._optionalChain([opts, 'optionalAccess', _76 => _76.error]) ? { error: opts.error } : {},
4788
+ ...Object.keys(bodyExtensions).length > 0 ? { extensions: bodyExtensions } : {}
4399
4789
  };
4400
- return { challenge: challenge2, requiredHeader: buildChallengeHeader(challenge2) };
4790
+ const headerChallenge = {
4791
+ ...challenge2,
4792
+ ...Object.keys(headerExtensions).length > 0 ? { extensions: headerExtensions } : { extensions: void 0 }
4793
+ };
4794
+ return { challenge: challenge2, requiredHeader: buildChallengeHeader(headerChallenge) };
4401
4795
  }
4402
4796
  async function challenge(resourceUrl = "") {
4403
4797
  return makeChallenge(resourceUrl);
4404
4798
  }
4799
+ function landingPage(ch) {
4800
+ return renderLandingPage(
4801
+ buildSelfDescription({ accepts: ch.accepts, instruction: describeChallenge(ch) })
4802
+ );
4803
+ }
4405
4804
  async function asChallenge() {
4406
4805
  const { challenge: c, requiredHeader } = await makeChallenge("");
4407
4806
  return { kind: "challenge", challenge: c, requiredHeader, statusCode: 402 };
@@ -4417,7 +4816,7 @@ function createPaymentGate(options) {
4417
4816
  let amountFormatted = receipt.amount;
4418
4817
  try {
4419
4818
  amountFormatted = _chunkU35MG4TFcjs.formatUnits.call(void 0, BigInt(receipt.amount), spec.decimals);
4420
- } catch (e34) {
4819
+ } catch (e35) {
4421
4820
  }
4422
4821
  return {
4423
4822
  ...receipt,
@@ -4431,7 +4830,7 @@ function createPaymentGate(options) {
4431
4830
  if (!options.onPaidError) return;
4432
4831
  try {
4433
4832
  options.onPaidError(error, receipt);
4434
- } catch (e35) {
4833
+ } catch (e36) {
4435
4834
  }
4436
4835
  }
4437
4836
  function fireOnPaid(receipt) {
@@ -4528,7 +4927,7 @@ function createPaymentGate(options) {
4528
4927
  if ("transaction" in exact.payload) {
4529
4928
  try {
4530
4929
  nonce = Buffer.from(exact.payload.transaction, "base64").toString("base64");
4531
- } catch (e36) {
4930
+ } catch (e37) {
4532
4931
  nonce = exact.payload.transaction;
4533
4932
  }
4534
4933
  } else if ("permit2Authorization" in exact.payload) {
@@ -4597,7 +4996,7 @@ function createPaymentGate(options) {
4597
4996
  if (exact) return verifyExact(exact);
4598
4997
  return asChallenge();
4599
4998
  }
4600
- return { challenge, verify, describe };
4999
+ return { challenge, verify, describe, landingPage };
4601
5000
  }
4602
5001
  function requirePayment(options) {
4603
5002
  const gate = createPaymentGate(options);
@@ -4637,6 +5036,39 @@ function normaliseHeader(value) {
4637
5036
  return value;
4638
5037
  }
4639
5038
 
5039
+ // src/facilitators.ts
5040
+ var KNOWN_FACILITATORS = {
5041
+ // PayAI — keyless (no API key), sponsors the gas. Verified 2026-06-14 against
5042
+ // https://facilitator.payai.network/supported (exact · eip155:8453) + the live demo.
5043
+ "eip155:8453": [
5044
+ {
5045
+ url: "https://facilitator.payai.network",
5046
+ keyless: true,
5047
+ schemes: ["exact"],
5048
+ settles: ["eip3009"],
5049
+ note: "PayAI \u2014 keyless, sponsors gas (Base USDC EIP-3009)"
5050
+ }
5051
+ ],
5052
+ // PayAI on Solana — keyless fee-payer sponsor for the SVM exact rail. Verified 2026-06-14.
5053
+ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": [
5054
+ {
5055
+ url: "https://facilitator.payai.network",
5056
+ keyless: true,
5057
+ schemes: ["exact"],
5058
+ settles: ["svm"],
5059
+ note: "PayAI \u2014 keyless fee-payer sponsor (Solana SPL SVM)"
5060
+ }
5061
+ ]
5062
+ };
5063
+ function knownFacilitatorsFor(network) {
5064
+ return _nullishCoalesce(KNOWN_FACILITATORS[network], () => ( []));
5065
+ }
5066
+ function firstKeylessFacilitator(network, method) {
5067
+ return knownFacilitatorsFor(network).find(
5068
+ (f) => f.keyless && f.schemes.includes("exact") && (method === void 0 || f.settles.includes(method))
5069
+ );
5070
+ }
5071
+
4640
5072
  // src/receipts.ts
4641
5073
  var DEFAULT_RETRIES = 5;
4642
5074
  var DEFAULT_TIMEOUT_MS = 1e4;
@@ -4649,7 +5081,7 @@ function isRetryableStatus(status) {
4649
5081
  }
4650
5082
  var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
4651
5083
  async function signBody(secret, body) {
4652
- const subtle = _optionalChain([globalThis, 'access', _71 => _71.crypto, 'optionalAccess', _72 => _72.subtle]);
5084
+ const subtle = _optionalChain([globalThis, 'access', _77 => _77.crypto, 'optionalAccess', _78 => _78.subtle]);
4653
5085
  if (!subtle) return null;
4654
5086
  try {
4655
5087
  const enc = new TextEncoder();
@@ -4659,7 +5091,7 @@ async function signBody(secret, body) {
4659
5091
  const sig = await subtle.sign("HMAC", key, enc.encode(body));
4660
5092
  const hex = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
4661
5093
  return `sha256=${hex}`;
4662
- } catch (e37) {
5094
+ } catch (e38) {
4663
5095
  return null;
4664
5096
  }
4665
5097
  }
@@ -4719,8 +5151,8 @@ async function deliverReceipt(receipt, options) {
4719
5151
  const retryable = status === void 0 ? true : isRetryableStatus(status);
4720
5152
  const willRetry = !ok && retryable && attempt < maxAttempts;
4721
5153
  try {
4722
- _optionalChain([onAttempt, 'optionalCall', _73 => _73({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
4723
- } catch (e38) {
5154
+ _optionalChain([onAttempt, 'optionalCall', _79 => _79({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
5155
+ } catch (e39) {
4724
5156
  }
4725
5157
  if (ok) return { delivered: true, attempts: attempt, status };
4726
5158
  if (!willRetry) {
@@ -4822,4 +5254,17 @@ async function deliverReceipt(receipt, options) {
4822
5254
 
4823
5255
 
4824
5256
 
4825
- exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkU35MG4TFcjs.ConfirmationTimeoutError; exports.DIRECTORY_INFO = DIRECTORY_INFO; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.GENERATOR = GENERATOR; exports.HEADER_REQUIRED = HEADER_REQUIRED; exports.HEADER_RESPONSE = HEADER_RESPONSE; exports.HEADER_RESPONSE_V1 = HEADER_RESPONSE_V1; exports.HEADER_SIGNATURE = HEADER_SIGNATURE; exports.HEADER_SIGNATURE_V1 = HEADER_SIGNATURE_V1; exports.InsufficientFundsError = _chunkU35MG4TFcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkU35MG4TFcjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkU35MG4TFcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkU35MG4TFcjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkU35MG4TFcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkU35MG4TFcjs.NonReplayableBodyError; exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS; exports.PERMIT2_PROXY_CHAIN_IDS = PERMIT2_PROXY_CHAIN_IDS; exports.PERMIT2_WITNESS_TYPES = PERMIT2_WITNESS_TYPES; exports.PIPRAIL_AGENT_GUIDE = PIPRAIL_AGENT_GUIDE; exports.PaymentDeclinedError = _chunkU35MG4TFcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkU35MG4TFcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkU35MG4TFcjs.PipRailError; exports.REGISTER_ATTRIBUTION = REGISTER_ATTRIBUTION; exports.RecipientNotReadyError = _chunkU35MG4TFcjs.RecipientNotReadyError; exports.SettlementError = _chunkU35MG4TFcjs.SettlementError; exports.UnknownTokenError = _chunkU35MG4TFcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkU35MG4TFcjs.UnsupportedNetworkError; exports.UnsupportedSchemeError = _chunkU35MG4TFcjs.UnsupportedSchemeError; exports.WalletRequiredError = _chunkU35MG4TFcjs.WalletRequiredError; exports.WrongChainError = _chunkU35MG4TFcjs.WrongChainError; exports.WrongFamilyError = _chunkU35MG4TFcjs.WrongFamilyError; exports.X402_EXACT_PERMIT2_PROXY = X402_EXACT_PERMIT2_PROXY; exports.agentGuide = agentGuide; exports.appendAttribution = appendAttribution; exports.buildBazaarExtension = buildBazaarExtension; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildExactSignatureHeader = buildExactSignatureHeader; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.claim402IndexDomain = claim402IndexDomain; exports.classifyChallenge = classifyChallenge; exports.createPaymentGate = createPaymentGate; exports.decorateOutcome = decorateOutcome; exports.deliverReceipt = deliverReceipt; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.explainDecline = explainDecline; exports.formatSpendReport = formatSpendReport; exports.getDirectoryInfo = getDirectoryInfo; exports.isPermit2ProxyChain = isPermit2ProxyChain; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSettleResponse = parseSettleResponse; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.summarizePlan = summarizePlan; exports.toInsufficientFundsError = _chunkU35MG4TFcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody; exports.verify402IndexDomain = verify402IndexDomain;
5257
+
5258
+
5259
+
5260
+
5261
+
5262
+
5263
+
5264
+
5265
+
5266
+
5267
+
5268
+
5269
+
5270
+ exports.BRAND = BRAND; exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkU35MG4TFcjs.ConfirmationTimeoutError; exports.DIRECTORY_INFO = DIRECTORY_INFO; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.GENERATOR = GENERATOR; exports.HEADER_REQUIRED = HEADER_REQUIRED; exports.HEADER_RESPONSE = HEADER_RESPONSE; exports.HEADER_RESPONSE_V1 = HEADER_RESPONSE_V1; exports.HEADER_SIGNATURE = HEADER_SIGNATURE; exports.HEADER_SIGNATURE_V1 = HEADER_SIGNATURE_V1; exports.InsufficientFundsError = _chunkU35MG4TFcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkU35MG4TFcjs.InvalidEnvelopeError; exports.KNOWN_FACILITATORS = KNOWN_FACILITATORS; exports.MaxRetriesExceededError = _chunkU35MG4TFcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkU35MG4TFcjs.MissingDriverError; exports.MultiChainPayer = MultiChainPayer; exports.NoCompatibleAcceptError = _chunkU35MG4TFcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkU35MG4TFcjs.NonReplayableBodyError; exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS; exports.PERMIT2_PROXY_CHAIN_IDS = PERMIT2_PROXY_CHAIN_IDS; exports.PERMIT2_WITNESS_TYPES = PERMIT2_WITNESS_TYPES; exports.PIPRAIL_AGENT_GUIDE = PIPRAIL_AGENT_GUIDE; exports.POWERED_BY = POWERED_BY; exports.PaymentDeclinedError = _chunkU35MG4TFcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkU35MG4TFcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkU35MG4TFcjs.PipRailError; exports.REGISTER_ATTRIBUTION = REGISTER_ATTRIBUTION; exports.RecipientNotReadyError = _chunkU35MG4TFcjs.RecipientNotReadyError; exports.SettlementError = _chunkU35MG4TFcjs.SettlementError; exports.UnknownTokenError = _chunkU35MG4TFcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkU35MG4TFcjs.UnsupportedNetworkError; exports.UnsupportedSchemeError = _chunkU35MG4TFcjs.UnsupportedSchemeError; exports.WalletRequiredError = _chunkU35MG4TFcjs.WalletRequiredError; exports.WrongChainError = _chunkU35MG4TFcjs.WrongChainError; exports.WrongFamilyError = _chunkU35MG4TFcjs.WrongFamilyError; exports.X402_EXACT_PERMIT2_PROXY = X402_EXACT_PERMIT2_PROXY; exports.agentGuide = agentGuide; exports.appendAttribution = appendAttribution; exports.buildBazaarExtension = buildBazaarExtension; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildExactSignatureHeader = buildExactSignatureHeader; exports.buildOpenApi = buildOpenApi; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSelfDescription = buildSelfDescription; exports.buildSignatureHeader = buildSignatureHeader; exports.buildWellKnownX402 = buildWellKnownX402; exports.buildX402DnsTxt = buildX402DnsTxt; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.claim402IndexDomain = claim402IndexDomain; exports.classifyChallenge = classifyChallenge; exports.createPaymentGate = createPaymentGate; exports.decorateOutcome = decorateOutcome; exports.deliverReceipt = deliverReceipt; exports.describeChallenge = describeChallenge; exports.discoveryHeaders = discoveryHeaders; exports.eip3009Abi = eip3009Abi; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.explainDecline = explainDecline; exports.facilitatorCoverage = facilitatorCoverage; exports.fetchAcross = fetchAcross; exports.firstKeylessFacilitator = firstKeylessFacilitator; exports.formatSpendReport = formatSpendReport; exports.getDirectoryInfo = getDirectoryInfo; exports.isPermit2ProxyChain = isPermit2ProxyChain; exports.knownFacilitatorsFor = knownFacilitatorsFor; exports.normalizeNetwork = normalizeNetwork; exports.parseChallenge = parseChallenge; exports.parseExactPaymentHeader = parseExactPaymentHeader; exports.parseExactRequirements = parseExactRequirements; exports.parseFacilitatorSupported = parseFacilitatorSupported; exports.parseReceipt = parseReceipt; exports.parseSettleResponse = parseSettleResponse; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.planAcross = planAcross; exports.readExactDomain = readExactDomain; exports.register402Index = register402Index; exports.registerDriver = registerDriver; exports.registerX402Scan = registerX402Scan; exports.renderLandingPage = renderLandingPage; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.searchOpenIndexes = searchOpenIndexes; exports.settleViaFacilitator = settleViaFacilitator; exports.summarizePlan = summarizePlan; exports.toInsufficientFundsError = _chunkU35MG4TFcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody; exports.verify402IndexDomain = verify402IndexDomain;