@piprail/sdk 2.3.0 → 2.5.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.d.ts CHANGED
@@ -88,8 +88,17 @@ interface X402ExactAcceptEntry {
88
88
  * `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
89
89
  * recipient. **Solana (SVM): `'svm'`** — the payer partial-signs an SPL
90
90
  * `TransferChecked` transaction whose fee payer is the merchant (`feePayer` below),
91
- * and the gate co-signs as fee payer + broadcasts. PipRail self-settles ALL. */
92
- assetTransferMethod: 'eip3009' | 'permit2' | 'svm';
91
+ * and the gate co-signs as fee payer + broadcasts. **Algorand: `'algorand'`** the payer
92
+ * signs an ASA `axfer` to `payTo` at fee 0, atomically grouped with a 0-ALGO `pay` from
93
+ * the `feePayer` that pools the group fee (per `scheme_exact_algo.md`); the gate (or a
94
+ * keyless facilitator) signs that fee txn + submits. **Aptos: `'aptos'`** — the payer signs a
95
+ * fee-payer (sponsored) `primary_fungible_store::transfer` to `payTo` (per
96
+ * `scheme_exact_aptos.md`); the gate (or a keyless facilitator) adds the fee-payer signature
97
+ * + submits, paying gas. **NEAR: `'near'`** — the payer signs a NEP-366 `SignedDelegateAction`
98
+ * authorizing exactly one NEP-141 `ft_transfer` to `payTo` (per `scheme_exact_near.md`); a
99
+ * facilitator-selected relayer (`feePayer` below) prepays gas + the 1 yoctoNEAR and submits, so
100
+ * the buyer holds zero NEAR. PipRail self-settles ALL. */
101
+ assetTransferMethod: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos' | 'near';
93
102
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
94
103
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
95
104
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -97,11 +106,12 @@ interface X402ExactAcceptEntry {
97
106
  name?: string;
98
107
  /** EIP-712 domain version of the token (USDC: "2"). OPTIONAL (see `name`); read/re-derived on-chain. */
99
108
  version?: string;
100
- /** **SVM only** — the merchant's fee-payer (sponsor) public key (base58), per the
101
- * x402 `exact` SVM scheme. The buyer compiles the transaction with this account as
102
- * the fee payer (so the buyer spends zero SOL on the network fee), leaving its
103
- * signature slot empty; the gate fills it and broadcasts. Distinct from `payTo`
104
- * the fee payer must never appear in any instruction's accounts (a MUST-rule). */
109
+ /** **SVM / Algorand / Aptos** — the fee-payer (gas sponsor) address. The buyer builds the
110
+ * transaction with this account as the gas payer (so the buyer spends ZERO native coin),
111
+ * leaving its signature for whoever sponsors; the gate (self mode) or a keyless facilitator
112
+ * fills it and submits. On **SVM** it must differ from `payTo` (the fee payer must never
113
+ * appear in an instruction a MUST-rule); on **Algorand/Aptos** the fee txn/signature is
114
+ * separate from the transfer, so `feePayer === payTo` is allowed. */
105
115
  feePayer?: string;
106
116
  /** **SVM only, OPTIONAL** — a ≤256-byte reconciliation memo the buyer attaches to the
107
117
  * transaction (the SVM scheme's optional `extra.memo`). */
@@ -216,9 +226,56 @@ interface Permit2PaymentPayload {
216
226
  interface ExactSvmPaymentPayload {
217
227
  transaction: string;
218
228
  }
229
+ /**
230
+ * The `payload` a client sends for the **Algorand `exact`** variant, per
231
+ * `scheme_exact_algo.md`: an atomically-grouped set of base64-encoded msgpack transactions,
232
+ * and the index within it of the transaction that pays the resource server. The buyer's ASA
233
+ * `axfer` (to `payTo`, fee 0) is SIGNED; a 0-ALGO `pay` from the `feePayer` that pools the
234
+ * group fee is left UNSIGNED for whoever sponsors (the gate's relayer in self mode, or a
235
+ * keyless facilitator). The group itself IS the proof — there's no separate authorization
236
+ * object (the Algorand analogue of EIP-3009's `authorization` / SVM's `transaction`).
237
+ */
238
+ interface ExactAlgorandPaymentPayload {
239
+ /** Index into `paymentGroup` of the txn that pays the resource server (the buyer's `axfer`). */
240
+ paymentIndex: number;
241
+ /** The atomic group: each element is a base64-encoded, msgpack-encoded (signed or unsigned)
242
+ * Algorand transaction. ≤ 16 elements (the protocol's atomic-group cap). */
243
+ paymentGroup: string[];
244
+ }
245
+ /**
246
+ * The `payload` a client sends for the **Aptos `exact`** variant, per `scheme_exact_aptos.md`:
247
+ * a fee-payer (sponsored, AIP-39) `primary_fungible_store::transfer`. `transaction` is the base64
248
+ * BCS-serialized `SimpleTransaction` (raw tx + the bound `feePayerAddress`); `senderAuth` is the
249
+ * base64 BCS-serialized buyer (sender) authenticator. The buyer leaves the fee-payer signature for
250
+ * whoever sponsors (the gate's relayer in self mode, or a keyless facilitator), who adds it +
251
+ * submits. The (tx + sender authenticator) IS the proof — there's no separate `authorization`
252
+ * object (the Aptos analogue of EIP-3009's `authorization` / SVM's `transaction`). The two-field
253
+ * shape (a `senderAuth` alongside `transaction`) also distinguishes it from the SVM payload.
254
+ */
255
+ interface ExactAptosPaymentPayload {
256
+ /** Base64 BCS-serialized `SimpleTransaction` (raw transaction + the bound `feePayerAddress`). */
257
+ transaction: string;
258
+ /** Base64 BCS-serialized buyer (sender) `AccountAuthenticator`. */
259
+ senderAuth: string;
260
+ }
261
+ /**
262
+ * The `payload` a client sends for the **NEAR `exact`** variant, per `scheme_exact_near.md`:
263
+ * a base64-encoded, Borsh-serialized NEP-366 `SignedDelegateAction` whose single delegated action
264
+ * is one NEP-141 `ft_transfer` (to `payTo`, the exact `amount`, `deposit: 1` yoctoNEAR). The buyer
265
+ * signs the delegate action with a FULL-ACCESS key (a function-call key can't attach the 1 yocto and
266
+ * is rejected); a facilitator-selected relayer wraps it, prepays gas + the yocto, and submits. The
267
+ * signed delegate action IS the proof — there's no separate authorization object (the NEAR analogue
268
+ * of EIP-3009's `authorization` / SVM's `transaction`). Its single self-contained string field also
269
+ * distinguishes it from every other family's payload shape.
270
+ */
271
+ interface ExactNearPaymentPayload {
272
+ /** Base64 of the Borsh-encoded NEP-366 `SignedDelegateAction` (one `ft_transfer`). */
273
+ signedDelegateAction: string;
274
+ }
219
275
  /** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
220
- * or SVM (`transaction`). */
221
- type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload;
276
+ * SVM (`transaction`), Algorand (`paymentGroup`), Aptos (`transaction` + `senderAuth`), or NEAR
277
+ * (`signedDelegateAction`). */
278
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload | ExactNearPaymentPayload;
222
279
  interface ParsedExactBase {
223
280
  x402Version: number;
224
281
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
@@ -236,7 +293,10 @@ interface ParsedExactBase {
236
293
  * re-derives every verified field from its own trusted rail. A discriminated union on
237
294
  * `method`, so narrowing on `method` narrows `payload`: `'eip3009'` → {@link ExactPaymentPayload}
238
295
  * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`),
239
- * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`).
296
+ * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`), `'algorand'` →
297
+ * {@link ExactAlgorandPaymentPayload} (`paymentGroup`); `'aptos'` →
298
+ * {@link ExactAptosPaymentPayload} (`transaction` + `senderAuth`); `'near'` →
299
+ * {@link ExactNearPaymentPayload} (`signedDelegateAction`).
240
300
  */
241
301
  type ParsedExactPayment = (ParsedExactBase & {
242
302
  method: 'eip3009';
@@ -247,6 +307,15 @@ type ParsedExactPayment = (ParsedExactBase & {
247
307
  }) | (ParsedExactBase & {
248
308
  method: 'svm';
249
309
  payload: ExactSvmPaymentPayload;
310
+ }) | (ParsedExactBase & {
311
+ method: 'algorand';
312
+ payload: ExactAlgorandPaymentPayload;
313
+ }) | (ParsedExactBase & {
314
+ method: 'aptos';
315
+ payload: ExactAptosPaymentPayload;
316
+ }) | (ParsedExactBase & {
317
+ method: 'near';
318
+ payload: ExactNearPaymentPayload;
250
319
  });
251
320
  interface X402Receipt {
252
321
  scheme: 'onchain-proof' | 'exact';
@@ -4266,9 +4335,10 @@ interface DiscoverySigner {
4266
4335
  * chain-agnostic — it never names a family, it just merges `extra`.
4267
4336
  */
4268
4337
  interface ExactRailInfo {
4269
- method: 'eip3009' | 'permit2' | 'svm';
4338
+ method: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos' | 'near';
4270
4339
  /** Family-specific `extra` keys merged into the exact accept (e.g. `{ name, version }`
4271
- * for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana). */
4340
+ * for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana, `{ feePayer }` for
4341
+ * Algorand/Aptos/NEAR). */
4272
4342
  extra?: Record<string, unknown>;
4273
4343
  }
4274
4344
  /**
@@ -4349,7 +4419,7 @@ interface ResolvedNetwork {
4349
4419
  reason?: RecipientReason;
4350
4420
  }>;
4351
4421
  /**
4352
- * OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM) — the BUYER counterpart to {@link settleExactSelf}.
4422
+ * OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM + Algorand + Aptos) — the BUYER counterpart to {@link settleExactSelf}.
4353
4423
  * Build + EIP-712-sign an EIP-3009 `transferWithAuthorization` for a standard x402
4354
4424
  * `exact` rail, so a PipRail agent can PAY any standard x402 server (not just PipRail's
4355
4425
  * own `onchain-proof` gates). The client frames the returned `payload` + `accepted` echo
@@ -4404,7 +4474,7 @@ interface ResolvedNetwork {
4404
4474
  * (the merchant's own bound self-settle wallet, in self mode); `feePayer` takes precedence.
4405
4475
  * RPC-read (EVM reads the token's EIP-712 domain; Solana reads the mint's token program); MAY
4406
4476
  * throw a typed config error for an explicitly-requested-but-unsupported method (EVM does). A
4407
- * family that omits this method offers no `exact` rail (today: every non-EVM, non-Solana family).
4477
+ * family that omits this method offers no `exact` rail (today: every family except EVM, Solana, Algorand, and Aptos).
4408
4478
  */
4409
4479
  resolveExactRail?(input: {
4410
4480
  asset: string;
@@ -4438,10 +4508,12 @@ interface ResolvedNetwork {
4438
4508
  */
4439
4509
  exactPermit2Supported?(): boolean;
4440
4510
  /**
4441
- * OPTIONAL (EVM-only today) — verify a standard x402 `exact` (EIP-3009) payment
4442
- * locally, then SELF-SETTLE it by broadcasting `transferWithAuthorization` from the
4443
- * merchant's own `relayer` wallet (the merchant pays gas to receive; the signature
4444
- * binds `to`, so no redirect risk). RETURNS a `VerifyResult`:
4511
+ * OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM + Algorand + Aptos) — verify a standard x402 `exact`
4512
+ * payment locally, then SELF-SETTLE it by broadcasting from the merchant's own `relayer`
4513
+ * wallet (the merchant pays the network fee to receive; EVM broadcasts
4514
+ * `transferWithAuthorization`, Solana co-signs the fee payer, Algorand signs the pooled fee
4515
+ * txn + submits the group, Aptos adds the fee-payer signature + submits — the transfer
4516
+ * binds `payTo`, so no redirect risk). RETURNS a `VerifyResult`:
4445
4517
  * - `{ ok:false, error }` for a CLIENT-fixable fault (bad signature, expired,
4446
4518
  * wrong recipient/amount, used nonce, simulation revert) → gate replies 402;
4447
4519
  * - `{ ok:true, receipt }` once the settle tx is mined.
@@ -4930,7 +5002,7 @@ interface SpendSummary {
4930
5002
  }
4931
5003
 
4932
5004
  /** The payment schemes a client can settle: PipRail's native `onchain-proof` (the
4933
- * default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM, opt-in). */
5005
+ * default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM + Algorand, opt-in). */
4934
5006
  type PaymentScheme = 'onchain-proof' | 'exact';
4935
5007
 
4936
5008
  /** Observability events. `ref` is the proof — a chain-specific id (EVM tx hash, Solana signature, TON locator, Stellar tx hash). */
@@ -5485,7 +5557,7 @@ declare class PipRailClient {
5485
5557
  * before publishing, so retry with a brief backoff if a fresh listing is missing.
5486
5558
  * - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
5487
5559
  * `onchain-proof` rails by default, and standard `exact` rails too once you opt in
5488
- * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
5560
+ * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM + Algorand).
5489
5561
  */
5490
5562
  discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
5491
5563
  /**
@@ -5902,7 +5974,7 @@ declare function describeChallenge(challenge: X402Challenge): string;
5902
5974
  * literally, so a wrong name or order actively misleads. A test pins the load-
5903
5975
  * bearing phrases.
5904
5976
  */
5905
- declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## Landing cold \u2014 read the self-description\nEvery PipRail 402 self-describes. Read challenge.extensions.piprail for { name, what, pay[]\n(each rail's how-to-pay), sdk.install, mcp, docs } \u2014 never guess what an endpoint is. If your\ntooling can't pay a rail (e.g. a stock x402 client can't pay the onchain-proof scheme), the\nblock says how: install @piprail/sdk (npm i @piprail/sdk) or run the MCP (npx -y @piprail/mcp)\nand pay with the tools below.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to two rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM + Solana, and the on-chain method (EIP-3009 / Permit2 / SVM) is picked automatically.\nWhen the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest\nsettleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is\nidentical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);\nyou can't enable it yourself, but you can report when a 402 needs it (see UNSUPPORTED_SCHEME below).\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend. On a gasless\n exact rail `.ref` is the authorization NONCE, not a tx hash: re-present the SAME\n signed authorization, never sign a fresh one (that would risk a double-spend).\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n If it's a standard x402 server offering an exact rail, that's a config fix the operator makes\n once (enable the exact scheme); report it, don't retry the same call blindly.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
5977
+ declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## Landing cold \u2014 read the self-description\nEvery PipRail 402 self-describes. Read challenge.extensions.piprail for { name, what, pay[]\n(each rail's how-to-pay), sdk.install, mcp, docs } \u2014 never guess what an endpoint is. If your\ntooling can't pay a rail (e.g. a stock x402 client can't pay the onchain-proof scheme), the\nblock says how: install @piprail/sdk (npm i @piprail/sdk) or run the MCP (npx -y @piprail/mcp)\nand pay with the tools below.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to two rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand\n fee-pooled group) is picked automatically.\nWhen the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest\nsettleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is\nidentical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);\nyou can't enable it yourself, but you can report when a 402 needs it (see UNSUPPORTED_SCHEME below).\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend. On a gasless\n exact rail `.ref` is the authorization NONCE, not a tx hash: re-present the SAME\n signed authorization, never sign a fresh one (that would risk a double-spend).\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n If it's a standard x402 server offering an exact rail, that's a config fix the operator makes\n once (enable the exact scheme); report it, don't retry the same call blindly.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
5906
5978
  /** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
5907
5979
  declare function agentGuide(): string;
5908
5980
 
@@ -6709,7 +6781,7 @@ interface KnownFacilitator {
6709
6781
  /** The x402 schemes it settles (today only `exact`). */
6710
6782
  schemes: ReadonlyArray<'exact'>;
6711
6783
  /** The exact transfer methods it can settle on this network. */
6712
- settles: ReadonlyArray<'eip3009' | 'permit2' | 'svm'>;
6784
+ settles: ReadonlyArray<'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos' | 'near'>;
6713
6785
  /** A short human note (who it is / caveat). */
6714
6786
  note?: string;
6715
6787
  }
@@ -6730,7 +6802,7 @@ declare function knownFacilitatorsFor(network: Caip2): ReadonlyArray<KnownFacili
6730
6802
  * specific transfer `method`). Returns `undefined` when none is known — the `exact: true`
6731
6803
  * shorthand branches on that to throw a coverage-specific guidance error.
6732
6804
  */
6733
- declare function firstKeylessFacilitator(network: Caip2, method?: 'eip3009' | 'permit2' | 'svm'): KnownFacilitator | undefined;
6805
+ declare function firstKeylessFacilitator(network: Caip2, method?: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos' | 'near'): KnownFacilitator | undefined;
6734
6806
 
6735
6807
  /**
6736
6808
  * Reliable receipt delivery — the durable webhook a stateless gate can't be.
package/dist/index.js CHANGED
@@ -1396,7 +1396,7 @@ function chainIdFromNetwork(network) {
1396
1396
  const match = /^eip155:(\d+)$/.exec(network);
1397
1397
  if (!match || !match[1]) return null;
1398
1398
  const n = Number(match[1]);
1399
- return Number.isSafeInteger(n) ? n : null;
1399
+ return Number.isSafeInteger(n) && n > 0 ? n : null;
1400
1400
  }
1401
1401
  function buildChallengeHeader(challenge) {
1402
1402
  return toBase64Json(challenge);
@@ -1469,9 +1469,27 @@ function parseExactPaymentHeader(value) {
1469
1469
  const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
1470
1470
  const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
1471
1471
  const base2 = { x402Version, network, ...asset ? { asset } : {}, raw: v };
1472
+ if (typeof payload.signedDelegateAction === "string") {
1473
+ return { ...base2, method: "near", payload: { signedDelegateAction: payload.signedDelegateAction } };
1474
+ }
1475
+ if (typeof payload.transaction === "string" && typeof payload.senderAuth === "string") {
1476
+ return { ...base2, method: "aptos", payload: { transaction: payload.transaction, senderAuth: payload.senderAuth } };
1477
+ }
1472
1478
  if (typeof payload.transaction === "string") {
1473
1479
  return { ...base2, method: "svm", payload: { transaction: payload.transaction } };
1474
1480
  }
1481
+ if (Array.isArray(payload.paymentGroup)) {
1482
+ const group = payload.paymentGroup;
1483
+ const index = payload.paymentIndex;
1484
+ if (group.length === 0 || group.length > 16 || !group.every((t) => typeof t === "string") || typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= group.length) {
1485
+ return null;
1486
+ }
1487
+ return {
1488
+ ...base2,
1489
+ method: "algorand",
1490
+ payload: { paymentIndex: index, paymentGroup: group }
1491
+ };
1492
+ }
1475
1493
  const signature = payload.signature;
1476
1494
  if (typeof signature !== "string") return null;
1477
1495
  const authorization = payload.authorization;
@@ -1792,6 +1810,12 @@ function makeEvmNetwork(resolved) {
1792
1810
  if ("transaction" in payload) {
1793
1811
  return { ok: false, error: "signature_invalid", detail: "An SVM (Solana) payload was submitted to an EVM exact rail." };
1794
1812
  }
1813
+ if ("paymentGroup" in payload) {
1814
+ return { ok: false, error: "signature_invalid", detail: "An Algorand payload was submitted to an EVM exact rail." };
1815
+ }
1816
+ if ("signedDelegateAction" in payload) {
1817
+ return { ok: false, error: "signature_invalid", detail: "A NEAR payload was submitted to an EVM exact rail." };
1818
+ }
1795
1819
  return verifyAndSettleExactEvm({
1796
1820
  publicClient,
1797
1821
  walletClient: a.walletClient,
@@ -1816,7 +1840,7 @@ var loaders = {
1816
1840
  solana: async () => {
1817
1841
  let mod;
1818
1842
  try {
1819
- mod = await import("./solana-E4MD6JJ6.js");
1843
+ mod = await import("./solana-3FMCWSEE.js");
1820
1844
  } catch (cause) {
1821
1845
  throw new MissingDriverError(
1822
1846
  `Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
@@ -1888,7 +1912,7 @@ var loaders = {
1888
1912
  near: async () => {
1889
1913
  let mod;
1890
1914
  try {
1891
- mod = await import("./near-MTYBCUYM.js");
1915
+ mod = await import("./near-OTPQD6BI.js");
1892
1916
  } catch (cause) {
1893
1917
  throw new MissingDriverError(
1894
1918
  `NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
@@ -1900,7 +1924,7 @@ var loaders = {
1900
1924
  aptos: async () => {
1901
1925
  let mod;
1902
1926
  try {
1903
- mod = await import("./aptos-RIL56C7L.js");
1927
+ mod = await import("./aptos-QAAXIUY3.js");
1904
1928
  } catch (cause) {
1905
1929
  throw new MissingDriverError(
1906
1930
  `Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
@@ -1912,7 +1936,7 @@ var loaders = {
1912
1936
  algorand: async () => {
1913
1937
  let mod;
1914
1938
  try {
1915
- mod = await import("./algorand-GSFVZTBF.js");
1939
+ mod = await import("./algorand-WB6PBJU4.js");
1916
1940
  } catch (cause) {
1917
1941
  throw new MissingDriverError(
1918
1942
  `Algorand selected, but its package isn't installed. Run: npm install algosdk`,
@@ -2008,7 +2032,7 @@ var SLUG_TO_CAIP2 = {
2008
2032
  near: "near:mainnet",
2009
2033
  sui: "sui:mainnet",
2010
2034
  aptos: "aptos:1",
2011
- algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k",
2035
+ algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
2012
2036
  stellar: "stellar:pubnet",
2013
2037
  xrpl: "xrpl:0"
2014
2038
  };
@@ -3026,7 +3050,7 @@ var PipRailClient = class {
3026
3050
  * before publishing, so retry with a brief backoff if a fresh listing is missing.
3027
3051
  * - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
3028
3052
  * `onchain-proof` rails by default, and standard `exact` rails too once you opt in
3029
- * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
3053
+ * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM + Algorand).
3030
3054
  */
3031
3055
  async discover(opts = {}) {
3032
3056
  const found = await searchOpenIndexes({
@@ -3224,7 +3248,7 @@ var PipRailClient = class {
3224
3248
  );
3225
3249
  if (schemes.includes("exact") && exactOnNet && typeof net.payExact !== "function") {
3226
3250
  throw new UnsupportedSchemeError(
3227
- `This 402 offers a standard 'exact' rail on ${net.network}, but the ${net.family} family can't pay 'exact' (supported on EVM + Solana today), and no 'onchain-proof' rail was offered.`
3251
+ `This 402 offers a standard 'exact' rail on ${net.network}, but the ${net.family} family can't pay 'exact' (supported on EVM, Solana, Algorand + NEAR today), and no 'onchain-proof' rail was offered.`
3228
3252
  );
3229
3253
  }
3230
3254
  if (!schemes.includes("exact") && exactOnNet && typeof net.payExact === "function") {
@@ -3620,7 +3644,7 @@ var PipRailClient = class {
3620
3644
  async payExactRail(net, wallet, accept, url, init, quote) {
3621
3645
  if (!net.payExact) {
3622
3646
  throw new UnsupportedSchemeError(
3623
- `the ${net.family} family can't pay a standard 'exact' rail (supported on EVM + Solana today).`
3647
+ `the ${net.family} family can't pay a standard 'exact' rail (supported on EVM, Solana, Algorand + NEAR today).`
3624
3648
  );
3625
3649
  }
3626
3650
  throwIfAborted(init?.signal);
@@ -4189,7 +4213,8 @@ A 402 may offer up to two rails; you don't choose per payment \u2014 the client
4189
4213
  (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.
4190
4214
  - exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose
4191
4215
  (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It
4192
- works on EVM + Solana, and the on-chain method (EIP-3009 / Permit2 / SVM) is picked automatically.
4216
+ works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand
4217
+ fee-pooled group) is picked automatically.
4193
4218
  When the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest
4194
4219
  settleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is
4195
4220
  identical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);
@@ -4909,6 +4934,110 @@ var KNOWN_FACILITATORS = {
4909
4934
  schemes: ["exact"],
4910
4935
  settles: ["eip3009"],
4911
4936
  note: "xpay \u2014 keyless, zero-fee, sponsors gas. LIVE-settled on Base 2026-06-15 (tx 0x2273d5\u2026)."
4937
+ },
4938
+ {
4939
+ url: "https://facilitator.ultravioletadao.xyz",
4940
+ keyless: true,
4941
+ schemes: ["exact"],
4942
+ settles: ["eip3009"],
4943
+ note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x58a69042a4129be649c5642456752ede95a5ff921daddfd30560ae70ae5907ff). 2nd UVD validation chain (after HyperEVM)."
4944
+ },
4945
+ {
4946
+ url: "https://x402.dexter.cash",
4947
+ keyless: true,
4948
+ schemes: ["exact"],
4949
+ settles: ["eip3009"],
4950
+ note: "Dexter \u2014 keyless, gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0xdf030e4d5bf41a88c5a3bfe73bb433dfbb90b058d3b8ded63b68e026eedb9de8). Note: ~$0.001 dynamic floor on Base."
4951
+ },
4952
+ {
4953
+ url: "https://facilitator.corbits.dev",
4954
+ keyless: true,
4955
+ schemes: ["exact"],
4956
+ settles: ["eip3009"],
4957
+ note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x2e41c581af023100429ada81f1371bef82d41dd577ed438d72ddc18676d4213d). Also seeded on Monad + Solana."
4958
+ },
4959
+ {
4960
+ url: "https://facilitator.goplausible.xyz",
4961
+ keyless: true,
4962
+ schemes: ["exact"],
4963
+ settles: ["eip3009"],
4964
+ note: "GoPlausible \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x9bcbc1f01fe1fd1aed2a79e5582555164cc4185e9800189df378a6b46eb9c59e). 2nd GoPlausible validation chain (after Algorand)."
4965
+ }
4966
+ ],
4967
+ // Monad (eip155:143). Corbits + Ultravioleta DAO each keyless-settle the EVM EIP-3009 exact rail
4968
+ // (Monad's native Circle USDC), buyer paid zero gas — real LIVE settles, not just /supported reads.
4969
+ // Makes `exact: true` zero-config gasless on Monad.
4970
+ "eip155:143": [
4971
+ {
4972
+ url: "https://facilitator.corbits.dev",
4973
+ keyless: true,
4974
+ schemes: ["exact"],
4975
+ settles: ["eip3009"],
4976
+ note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x7797be27ce22c17f7433a0389bd22d46e338899b1faac505fffd068174428ae6)."
4977
+ },
4978
+ {
4979
+ url: "https://facilitator.ultravioletadao.xyz",
4980
+ keyless: true,
4981
+ schemes: ["exact"],
4982
+ settles: ["eip3009"],
4983
+ note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0xb107576effbaceb5586c07a9ddc996ef2b6d455f1858314995ef83a7c6e64d11). 3rd UVD validation chain."
4984
+ },
4985
+ {
4986
+ url: "https://facilitator.pieverse.io",
4987
+ keyless: true,
4988
+ schemes: ["exact"],
4989
+ settles: ["eip3009"],
4990
+ note: "Pieverse \u2014 keyless, sponsors gas (Monad USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x00cfeb93876e5ef57dcb002510038b7304913233ca286d7ab33c72a8b119eb0d)."
4991
+ }
4992
+ ],
4993
+ // BNB Chain (eip155:56). Dexter keyless-settles the EVM EIP-3009 exact rail — but ONLY for BNB's
4994
+ // EIP-3009 tokens (FDUSD / USD1); BNB's USDC/USDT are Binance-Peg (Permit2), which no facilitator
4995
+ // settles. Dexter also enforces a ~$0.003 dynamic settlement floor on BNB, so a sub-$0.003 payment
4996
+ // is rejected (amount_too_low) — fine for real prices, but the floor is real. LIVE-settled with
4997
+ // FDUSD, buyer paid zero BNB — this beats the BNB token-overlap wall that blocked AEON/Pieverse.
4998
+ "eip155:56": [
4999
+ {
5000
+ url: "https://x402.dexter.cash",
5001
+ keyless: true,
5002
+ schemes: ["exact"],
5003
+ settles: ["eip3009"],
5004
+ note: "Dexter \u2014 keyless, gas-sponsored. BNB EIP-3009 tokens FDUSD/USD1 ONLY (Binance-Peg USDC/USDT are Permit2 \u2192 not facilitator-settleable); ~$0.003 dynamic floor. LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0x6d9eb4e4939f3f3c74cb19424cc7822d66ec8ed5c5c7c330d9f88a5f9ad59e9e)."
5005
+ },
5006
+ {
5007
+ url: "https://facilitator.pieverse.io",
5008
+ keyless: true,
5009
+ schemes: ["exact"],
5010
+ settles: ["eip3009"],
5011
+ note: "Pieverse \u2014 keyless, sponsors gas. BNB EIP-3009 tokens FDUSD/USD1 (same Binance-Peg caveat as Dexter). LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0xb9c76affc45bd07a51559efd813ca71516fc30625478724476c2cf42fc2203d3) \u2014 a 2nd keyless BNB facilitator (failover for Dexter)."
5012
+ }
5013
+ ],
5014
+ // HyperEVM (eip155:999). Ultravioleta DAO keyless-settles the EVM EIP-3009 exact rail (HyperEVM's
5015
+ // native Circle USDC), buyer paid zero gas — a real LIVE settle. UVD is the broadest keyless
5016
+ // facilitator (it also lists Celo/Unichain/Optimism/Scroll + many non-EVM); only HyperEVM is
5017
+ // seeded here because THE RULE requires a per-chain live settle, and that's the one we proved.
5018
+ "eip155:999": [
5019
+ {
5020
+ url: "https://facilitator.ultravioletadao.xyz",
5021
+ keyless: true,
5022
+ schemes: ["exact"],
5023
+ settles: ["eip3009"],
5024
+ note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (HyperEVM native USDC EIP-3009). LIVE-settled on HyperEVM 2026-06-17 (tx 0x56af8148a92a291f0ce362e250919f7742074e5464ac0f315ad68abaec93bd0a)."
5025
+ }
5026
+ ],
5027
+ // Algorand (mainnet, CAIP-2 = full base64 genesis hash). GoPlausible keyless-settles the ratified
5028
+ // x402 Algorand `exact` rail (atomic-group fee pooling): its sponsor pools the whole group fee and
5029
+ // submits, so NEITHER the buyer NOR the merchant pays ALGO — both-sides gasless. LIVE-settled by us
5030
+ // (a real USDCa exact payment; buyer 0 ALGO AND merchant 0 ALGO) — beyond a /supported read. This
5031
+ // makes Algorand a keyless chain (the first non-EVM/non-Solana one). GoPlausible authored the
5032
+ // ratified Algorand scheme; PipRail's group is byte-compatible (the gate sends `amount` + the full
5033
+ // genesis-hash network, which is all GoPlausible needs).
5034
+ "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=": [
5035
+ {
5036
+ url: "https://facilitator.goplausible.xyz",
5037
+ keyless: true,
5038
+ schemes: ["exact"],
5039
+ settles: ["algorand"],
5040
+ note: "GoPlausible \u2014 keyless, 100% gas-sponsored (Algorand USDCa, atomic-group fee pooling; both buyer AND merchant pay 0 ALGO). LIVE-settled on Algorand mainnet 2026-06-17 (tx PDVDVRFGJAG2K6AJ7L26OTSCSRL7AURVKEX4D4KHBAOLNSCYENXA). The only keyless Algorand x402 facilitator."
4912
5041
  }
4913
5042
  ],
4914
5043
  // Solana (mainnet-beta). Keyless fee-payer sponsors for the SVM exact rail, each LIVE-settled
@@ -4938,6 +5067,17 @@ var KNOWN_FACILITATORS = {
4938
5067
  note: "Corbits \u2014 keyless, Solana-first fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx BCreYer\u2026)."
4939
5068
  }
4940
5069
  ]
5070
+ // NEAR (near:mainnet) — DELIBERATELY UNSEEDED: no x402 facilitator settles NEAR yet.
5071
+ // The NEAR `exact` BUYER payload PipRail builds (drivers/near/exact.ts) is LIVE-PROVEN on mainnet —
5072
+ // a real NEP-366 meta-transaction settles a USDC/USDT ft_transfer gaslessly (buyer 0 NEAR, single-use
5073
+ // via the access-key nonce; relay txs CMnQJzrLvwk… USDT + BCCnVHbSCMY… USDC, 2026-06-18). What's
5074
+ // missing is the FACILITATOR side: the public x402-rs (which Ultravioleta DAO runs) has NO NEAR chain
5075
+ // crate (only eip155/solana/aptos), and UVD's `/verify` 400s on a near:mainnet request even though its
5076
+ // `/supported` ADVERTISES `near:mainnet` + feePayer `uvd-facilitator.near` — i.e. the listing is
5077
+ // aspirational, not settle-capable (verified 2026-06-18). So `exact: true` must NOT auto-pick a NEAR
5078
+ // facilitator. Seed here ONLY after a real keyless settle through a facilitator that actually
5079
+ // implements scheme_exact_near.md (THE RULE). Merchants can still pass an explicit
5080
+ // `exact: { settle: { facilitator } }` for any facilitator they've confirmed settles near:mainnet.
4941
5081
  };
4942
5082
  function knownFacilitatorsFor(network) {
4943
5083
  return KNOWN_FACILITATORS[network] ?? [];
@@ -5070,7 +5210,7 @@ function createPaymentGate(options) {
5070
5210
  if (settle !== "self" && info.method === "permit2") {
5071
5211
  if (cfg.method === "permit2") {
5072
5212
  throw new Error(
5073
- "requirePayment: exact `method: 'permit2'` can't be settled by a third-party facilitator \u2014 facilitators settle the standard EIP-3009 (EVM) / SVM (Solana) schemes, not PipRail\u2019s Permit2 proxy. Use an EIP-3009 token (USDC / EURC) with the facilitator, or `settle: 'self'` (your own relayer) to settle Permit2 yourself."
5213
+ "requirePayment: exact `method: 'permit2'` can't be settled by a third-party facilitator \u2014 facilitators settle the standard EIP-3009 (EVM) / SVM (Solana) / Algorand schemes, not PipRail\u2019s Permit2 proxy. Use an EIP-3009 token (USDC / EURC) with the facilitator, or `settle: 'self'` (your own relayer) to settle Permit2 yourself."
5074
5214
  );
5075
5215
  }
5076
5216
  return {
@@ -5315,7 +5455,7 @@ function createPaymentGate(options) {
5315
5455
  if (exactSpecs.length === 0) {
5316
5456
  return rejection("transfer_not_found", "This resource offers no standard `exact` rail.");
5317
5457
  }
5318
- const isCaip = exact.network.startsWith("eip155:");
5458
+ const isCaip = exact.network.includes(":");
5319
5459
  let candidates = isCaip ? exactSpecs.filter((s) => s.net.network === exact.network) : exactSpecs;
5320
5460
  if (exact.asset) {
5321
5461
  candidates = candidates.filter((s) => s.asset.toLowerCase() === exact.asset.toLowerCase());
@@ -5331,12 +5471,34 @@ function createPaymentGate(options) {
5331
5471
  }
5332
5472
  let nonce;
5333
5473
  let evmAuth = null;
5334
- if ("transaction" in exact.payload) {
5474
+ if ("senderAuth" in exact.payload && "transaction" in exact.payload) {
5475
+ nonce = [exact.payload.transaction, exact.payload.senderAuth].map((t) => {
5476
+ try {
5477
+ return Buffer.from(t, "base64").toString("base64");
5478
+ } catch {
5479
+ return t;
5480
+ }
5481
+ }).join("|");
5482
+ } else if ("transaction" in exact.payload) {
5335
5483
  try {
5336
5484
  nonce = Buffer.from(exact.payload.transaction, "base64").toString("base64");
5337
5485
  } catch {
5338
5486
  nonce = exact.payload.transaction;
5339
5487
  }
5488
+ } else if ("paymentGroup" in exact.payload) {
5489
+ nonce = exact.payload.paymentGroup.map((t) => {
5490
+ try {
5491
+ return Buffer.from(t, "base64").toString("base64");
5492
+ } catch {
5493
+ return t;
5494
+ }
5495
+ }).join("|");
5496
+ } else if ("signedDelegateAction" in exact.payload) {
5497
+ try {
5498
+ nonce = Buffer.from(exact.payload.signedDelegateAction, "base64").toString("base64");
5499
+ } catch {
5500
+ nonce = exact.payload.signedDelegateAction;
5501
+ }
5340
5502
  } else if ("permit2Authorization" in exact.payload) {
5341
5503
  evmAuth = exact.payload.permit2Authorization;
5342
5504
  nonce = evmAuth.nonce;
@@ -5354,6 +5516,13 @@ function createPaymentGate(options) {
5354
5516
  if (mode.kind === "self") {
5355
5517
  result = await spec.net.settleExactSelf({ relayer: mode.relayer, payload: exact.payload, accept });
5356
5518
  } else {
5519
+ const ftMethod = accept.extra.assetTransferMethod;
5520
+ const needsFeePayer = ftMethod === "svm" || ftMethod === "algorand" || ftMethod === "aptos" || ftMethod === "near";
5521
+ if (needsFeePayer && !accept.extra.feePayer) {
5522
+ throw new SettlementError(
5523
+ `exact settle: the ${ftMethod} facilitator rail is missing extra.feePayer (the gas sponsor) \u2014 cannot settle.`
5524
+ );
5525
+ }
5357
5526
  result = await settleViaFacilitator({
5358
5527
  url: mode.url,
5359
5528
  ...mode.authHeaders ? { authHeaders: mode.authHeaders } : {},
@@ -5370,9 +5539,7 @@ function createPaymentGate(options) {
5370
5539
  amount: accept.amount,
5371
5540
  payTo: accept.payTo,
5372
5541
  maxTimeoutSeconds: accept.maxTimeoutSeconds,
5373
- // The scheme's chain-specific `extra`, from the gate's OWN trusted rail: SVM forwards the
5374
- // facilitator's `feePayer` (the gas sponsor); EVM forwards the token's EIP-712 domain.
5375
- extra: accept.extra.assetTransferMethod === "svm" ? { feePayer: accept.extra.feePayer ?? "" } : { name: accept.extra.name ?? "", version: accept.extra.version ?? "" }
5542
+ extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: accept.extra.name ?? "", version: accept.extra.version ?? "" }
5376
5543
  },
5377
5544
  receipt: { network: accept.network, asset: accept.asset, payTo: accept.payTo, amount: accept.amount },
5378
5545
  // The buyer address, for the receipt's `payer` fallback. EVM carries it in the