@piprail/sdk 2.15.0 → 2.16.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 (35) hide show
  1. package/CHANGELOG.md +260 -0
  2. package/README.md +2 -2
  3. package/dist/{algorand-CSEUTWNW.js → algorand-25FMBCT3.js} +13 -4
  4. package/dist/{algorand-I2O24RSM.cjs → algorand-Q3TUQLPK.cjs} +49 -40
  5. package/dist/{aptos-J7QGCWNW.js → aptos-SBV6SGDP.js} +3 -3
  6. package/dist/{aptos-GA5AEYYL.cjs → aptos-VBJONBFY.cjs} +36 -36
  7. package/dist/chunk-2CX7XRZK.js +649 -0
  8. package/dist/chunk-C52H5TYB.js +474 -0
  9. package/dist/chunk-OXEFPLZA.cjs +474 -0
  10. package/dist/{chunk-3FR22M3O.cjs → chunk-QONQSZHJ.cjs} +2 -2
  11. package/dist/{chunk-3ZWM3DKM.js → chunk-QU25LSVS.js} +2 -2
  12. package/dist/chunk-V2IJ5HUW.cjs +649 -0
  13. package/dist/index.cjs +507 -1347
  14. package/dist/index.d.cts +39 -6
  15. package/dist/index.d.ts +39 -6
  16. package/dist/index.js +192 -1032
  17. package/dist/{ledger-uFtXlIHY.d.cts → ledger-Crc1bZox.d.cts} +164 -10
  18. package/dist/{ledger-uFtXlIHY.d.ts → ledger-Crc1bZox.d.ts} +164 -10
  19. package/dist/{near-NDQLGI4U.cjs → near-5LTTDU6G.cjs} +27 -27
  20. package/dist/{near-YA4Y4IGC.js → near-OLKCMTBI.js} +1 -1
  21. package/dist/node.d.cts +2 -2
  22. package/dist/node.d.ts +2 -2
  23. package/dist/{solana-OU6IUMQM.cjs → solana-AI2G7V33.cjs} +73 -52
  24. package/dist/{solana-MB6G3OA5.js → solana-HTKDRTD3.js} +32 -11
  25. package/dist/{stellar-RSNVOIKL.cjs → stellar-E2KWEV2E.cjs} +20 -20
  26. package/dist/{stellar-WDWSYOED.js → stellar-EUFZLX6J.js} +1 -1
  27. package/dist/{sui-GVSFNNJX.js → sui-KCIITCYH.js} +6 -2
  28. package/dist/{sui-MVC46BFJ.cjs → sui-Q3NJOJZS.cjs} +21 -17
  29. package/dist/{ton-MYOI3U3H.cjs → ton-J7TQWRN4.cjs} +16 -16
  30. package/dist/{ton-EJMGM3YI.js → ton-WH2JVQOO.js} +1 -1
  31. package/dist/{tron-VAPVMGJK.js → tron-FXBXDNEY.js} +1 -1
  32. package/dist/{tron-42X5N4GQ.cjs → tron-HIPMOX7S.cjs} +25 -25
  33. package/dist/{xrpl-Q2UWPCTJ.js → xrpl-RUOB37QH.js} +283 -5
  34. package/dist/{xrpl-MGUBUNSZ.cjs → xrpl-SVVS445B.cjs} +312 -34
  35. package/package.json +1 -1
@@ -75,8 +75,28 @@ interface X402ExactAcceptEntry {
75
75
  asset: AssetId;
76
76
  payTo: AddressId;
77
77
  maxTimeoutSeconds: number;
78
- extra: {
79
- /** The exact transfer method. EVM: `'eip3009'` for tokens with native
78
+ /**
79
+ * The network id EXACTLY as an x402 **v1** server wrote it (a slug like `'base'`),
80
+ * preserved by {@link normalizeV1Challenge} because `network` above is canonicalised to
81
+ * CAIP-2 for matching while a v1 server string-compares the slug it sent. Internal to the
82
+ * v1 compat path — absent on every v2 rail, and STRIPPED from every outgoing `accepted`
83
+ * echo by `withoutWireNetwork`, since the merchant never published this key.
84
+ */
85
+ wireNetwork?: string;
86
+ /**
87
+ * Scheme-defined extras. **OPTIONAL when PARSING a foreign 402** — the exact-EVM scheme
88
+ * makes every `extra` key optional (`assetTransferMethod` defaults to `'eip3009'`), and the
89
+ * SVM/Algorand/Aptos/NEAR/Hedera schemes define no `assetTransferMethod` at all, so a
90
+ * conformant rail may ship `extra: {}` or omit the block entirely. A PipRail **gate** always
91
+ * emits it. Every read on the buyer path must optional-chain.
92
+ */
93
+ extra?: {
94
+ /** The exact transfer method. **OPTIONAL** — `scheme_exact_evm.md`: *"If no
95
+ * `assetTransferMethod` is specified in `PaymentRequired.extra`, clients should default
96
+ * to `\"eip3009\"`"* (and only the non-default methods make it required). The SVM,
97
+ * Algorand, Aptos, NEAR and Hedera schemes never define this key. Read it through
98
+ * {@link exactTransferMethod}, never bare — 91% of the deployed x402 web omits it.
99
+ * EVM: `'eip3009'` for tokens with native
80
100
  * `transferWithAuthorization`, or `'permit2'` for tokens WITHOUT it (e.g.
81
101
  * Binance-Peg USDC on BNB) — the payer signs a Permit2 witness transfer whose
82
102
  * `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
@@ -92,13 +112,46 @@ interface X402ExactAcceptEntry {
92
112
  * authorizing exactly one NEP-141 `ft_transfer` to `payTo` (per `scheme_exact_near.md`); a
93
113
  * facilitator-selected relayer (`feePayer` below) prepays gas + the 1 yoctoNEAR and submits, so
94
114
  * the buyer holds zero NEAR. PipRail self-settles ALL. */
95
- assetTransferMethod: 'eip3009' | 'permit2'
115
+ assetTransferMethod?: 'eip3009' | 'permit2'
96
116
  /** A FOREIGN-dialect alias for `'permit2'` — Binance's x402 ("b402") facilitator labels its
97
117
  * EVM-Permit2 exact rail `'permit2-exact'` (the coinbase/x402 spec uses bare `'permit2'`).
98
118
  * PipRail EMITS only `'permit2'`; it TOLERATES `'permit2-exact'` inbound so the buyer pays a
99
119
  * Binance-issued 402 (the buyer treats the two as one rail). NB: settlement still requires the
100
120
  * rail to bind PipRail's canonical x402ExactPermit2Proxy — see the buyer in drivers/evm. */
101
- | 'permit2-exact' | 'svm' | 'algorand' | 'aptos' | 'near';
121
+ | 'permit2-exact' | 'svm' | 'algorand' | 'aptos' | 'near'
122
+ /** **XRPL** — the ledger has exactly ONE way to move value (a `Payment`), so
123
+ * `scheme_exact_xrpl.md` spends this field on SEQUENCING instead of mechanism.
124
+ * `'sequence'` (the DEFAULT, and what all 1,732 live XRPL rails mean by omitting it) uses
125
+ * the payer's account sequence; `'ticketSequence'` sets `Sequence: 0` and supplies a
126
+ * pre-minted `TicketSequence`, letting a payer sign several payments that settle out of
127
+ * order. */
128
+ | 'sequence' | 'ticketSequence';
129
+ /** **XRPL, REQUIRED by the scheme — and absent from 100% of live rails.** The spec says it
130
+ * "must be false" (XRPL charges the fee to the transaction's own `Account`, so the payer
131
+ * always pays). Read it as *false unless present*: REQUIRING it would reject the entire
132
+ * deployed XRPL x402 web, which is exactly the bug class `assetTransferMethod` already caused
133
+ * once. A rail that explicitly says `true` is refused — we cannot honour a sponsor here. */
134
+ areFeesSponsored?: boolean;
135
+ /** **XRPL** — the issuer's classic address for an IOU rail (RLUSD and friends). Required by the
136
+ * scheme for issued currencies, absent for native XRP; present on 869 of the 1,732 live rails,
137
+ * which is precisely the IOU half. Also the discriminator the buyer uses to pick the
138
+ * issued-currency `Amount` object over a bare drops string. */
139
+ issuer?: string;
140
+ /** **XRPL, OPTIONAL** — an opaque invoice identifier. When present the buyer MUST set the
141
+ * transaction's `InvoiceID` to its **SHA-256**, as 32-byte hex; that hash is the challenge
142
+ * binding on this rail (there is no memo — the scheme has facilitators REJECT `Memos`).
143
+ * Present on 1,732 of 1,732 live rails, so treat it as always-on in practice. */
144
+ invoiceId?: string;
145
+ /** **XRPL** — a vendor correlation tag, copied verbatim into the transaction's `SourceTag`.
146
+ * NOT in `scheme_exact_xrpl.md`'s extra table, but present on **1,728 of the 1,732** live XRPL
147
+ * rails: it is how the deployed vendors match a payment back to their own quote. Mirrored
148
+ * because it costs nothing and omitting it is a plausible reason a merchant refuses. */
149
+ sourceTag?: number;
150
+ /** **XRPL, OPTIONAL** — a destination tag the buyer MUST copy verbatim into the transaction
151
+ * when the rail states one (hosted/exchange accounts route deposits by it). Never invented
152
+ * when absent: unlike the onchain-proof path, which derives a tag from the nonce, the exact
153
+ * rail sets `DestinationTag` only if the merchant asked for one. */
154
+ destinationTag?: number;
102
155
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
103
156
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
104
157
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -132,6 +185,42 @@ interface X402ExactAcceptEntry {
132
185
  symbol?: string;
133
186
  };
134
187
  }
188
+ /**
189
+ * The transfer method an `exact` rail uses when it names none.
190
+ *
191
+ * `scheme_exact_evm.md` §0: *"If no `assetTransferMethod` is specified in
192
+ * `PaymentRequired.extra`, clients should default to `"eip3009"`."* §1 restates it per-method:
193
+ * `eip3009` is *"optional in `PaymentRequired`, default"*, while `permit2` and `erc7710` are
194
+ * *"required"*. So an absent marker is not a malformed rail — it is the common case (91% of the
195
+ * deployed web) and it means EIP-3009.
196
+ */
197
+ declare const DEFAULT_EXACT_TRANSFER_METHOD: "eip3009";
198
+ /**
199
+ * Every `assetTransferMethod` a PipRail buyer can actually sign, across all families.
200
+ *
201
+ * Used to SKIP a rail that names a method we don't implement (the spec's `erc7710`, or any
202
+ * future one) rather than sign an EIP-3009 authorization a facilitator built for a different
203
+ * mechanism and will reject. An **absent** marker is not "unknown" — see
204
+ * {@link DEFAULT_EXACT_TRANSFER_METHOD}. Family routing stays in each driver's `payExact`;
205
+ * this set only answers "could any driver of ours settle this?".
206
+ */
207
+ declare const KNOWN_EXACT_TRANSFER_METHODS: ReadonlySet<string>;
208
+ /**
209
+ * The effective transfer method of an `exact` rail: what it names, or the default when it names
210
+ * nothing. THE ONLY sanctioned way to read `extra.assetTransferMethod` — reading it bare is how
211
+ * the buyer came to reject 91% of the x402 web.
212
+ *
213
+ * Pass `family` to get the right default off-EVM: a Solana rail that names nothing means `svm`,
214
+ * not `eip3009`. Without it the EVM default is assumed (correct for the settleability check,
215
+ * since every family's own literal is in {@link KNOWN_EXACT_TRANSFER_METHODS} anyway).
216
+ */
217
+ declare function exactTransferMethod(accept: X402ExactAcceptEntry, family?: string): string;
218
+ /**
219
+ * Can any PipRail driver settle this rail's transfer method? True when the rail names a
220
+ * method we implement, AND when it names none (the spec default `eip3009`). False only for a
221
+ * method we don't implement — the rail is then skipped at gather rather than mis-signed.
222
+ */
223
+ declare function isSettleableExactMethod(accept: X402ExactAcceptEntry): boolean;
135
224
  /**
136
225
  * A standard x402 `upto` rail (EVM / Permit2) — variable-amount / metered billing.
137
226
  * The buyer signs a Permit2 `PermitWitnessTransferFrom` authorization for `amount`
@@ -181,7 +270,13 @@ interface X402UptoAcceptEntry {
181
270
  * rail, or a standard `upto` (metered) rail. */
182
271
  type X402AnyAccept = X402AcceptEntry | X402ExactAcceptEntry | X402UptoAcceptEntry;
183
272
  interface X402Challenge {
184
- x402Version: 2;
273
+ /**
274
+ * `2` for every challenge PipRail EMITS. `1` appears only on the PARSE side, when
275
+ * {@link normalizeV1Challenge} has lifted a still-deployed v1 server's body into this
276
+ * shape — the buyer must then answer on the v1 wire (`X-PAYMENT`, flat payload). See the
277
+ * version-posture note above {@link HEADER_SIGNATURE_V1}.
278
+ */
279
+ x402Version: 1 | 2;
185
280
  /**
186
281
  * Optional human-readable reason (v2 `error?: string`). PipRail EMITS it only on a
187
282
  * rejected-proof re-challenge (omitted on a fresh challenge). Typed to also tolerate
@@ -361,10 +456,25 @@ interface ExactNearPaymentPayload {
361
456
  /** Base64 of the Borsh-encoded NEP-366 `SignedDelegateAction` (one `ft_transfer`). */
362
457
  signedDelegateAction: string;
363
458
  }
459
+ /**
460
+ * The `payload` a client sends for the **XRPL `exact`** variant, per `scheme_exact_xrpl.md`:
461
+ * a **fully signed** XRPL `Payment` transaction, hex-encoded, that the resource server (or its
462
+ * facilitator) submits. The signed blob IS the proof — there is no separate authorization object.
463
+ *
464
+ * XRPL is the one family where **the payer pays the network fee**: the fee is a field inside the
465
+ * signed transaction and the ledger charges it to `Account`. So there is no sponsor, no fee-payer
466
+ * co-signature, and no fee-drain guard to write — the buyer needs XRP for the amount *and* the fee.
467
+ * That also means the buyer signs something immediately submittable, so `LastLedgerSequence` is
468
+ * mandatory: it is the only thing bounding how long the merchant may sit on it.
469
+ */
470
+ interface ExactXrplPaymentPayload {
471
+ /** Hex-encoded, fully signed XRPL `Payment` transaction blob. */
472
+ signedTxBlob: string;
473
+ }
364
474
  /** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
365
- * SVM (`transaction`), Algorand (`paymentGroup`), Aptos (`transaction` + `senderAuth`), or NEAR
366
- * (`signedDelegateAction`). */
367
- type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload | ExactNearPaymentPayload;
475
+ * SVM (`transaction`), Algorand (`paymentGroup`), Aptos (`transaction` + `senderAuth`), NEAR
476
+ * (`signedDelegateAction`), or XRPL (`signedTxBlob`). */
477
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload | ExactNearPaymentPayload | ExactXrplPaymentPayload;
368
478
  interface ParsedExactBase {
369
479
  x402Version: number;
370
480
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
@@ -385,7 +495,9 @@ interface ParsedExactBase {
385
495
  * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`), `'algorand'` →
386
496
  * {@link ExactAlgorandPaymentPayload} (`paymentGroup`); `'aptos'` →
387
497
  * {@link ExactAptosPaymentPayload} (`transaction` + `senderAuth`); `'near'` →
388
- * {@link ExactNearPaymentPayload} (`signedDelegateAction`).
498
+ * {@link ExactNearPaymentPayload} (`signedDelegateAction`); `'sequence'` / `'ticketSequence'` →
499
+ * {@link ExactXrplPaymentPayload} (`signedTxBlob`) — XRPL is the one family whose method literal
500
+ * names the SEQUENCING strategy rather than a transfer mechanism, because it has only one.
389
501
  */
390
502
  type ParsedExactPayment = (ParsedExactBase & {
391
503
  method: 'eip3009';
@@ -405,6 +517,12 @@ type ParsedExactPayment = (ParsedExactBase & {
405
517
  }) | (ParsedExactBase & {
406
518
  method: 'near';
407
519
  payload: ExactNearPaymentPayload;
520
+ }) | (ParsedExactBase & {
521
+ method: 'sequence';
522
+ payload: ExactXrplPaymentPayload;
523
+ }) | (ParsedExactBase & {
524
+ method: 'ticketSequence';
525
+ payload: ExactXrplPaymentPayload;
408
526
  });
409
527
  /**
410
528
  * What {@link parseUptoPaymentHeader} extracts from an inbound `upto` payment — the
@@ -648,6 +766,25 @@ declare function buildUptoSignatureHeader(input: {
648
766
  accepted: X402UptoAcceptEntry;
649
767
  payload: Permit2UptoPaymentPayload;
650
768
  }): string;
769
+ /**
770
+ * Build the **v1** `X-PAYMENT` header value — the flat, pre-v2 payload shape
771
+ * `{ x402Version: 1, scheme, network, payload }`, base64-JSON.
772
+ *
773
+ * This is the `encodeXPaymentHeader` utility the version-posture note above has always
774
+ * described; it had never been written, so the buyer could parse nothing from a v1 server and
775
+ * could answer nothing either. Needed because v2 moved the header `X-PAYMENT` →
776
+ * `PAYMENT-SIGNATURE` and reshaped the payload: a v1 server ignores `PAYMENT-SIGNATURE`
777
+ * entirely (verified live — it just re-challenges) and reads only `X-PAYMENT`.
778
+ *
779
+ * `network` MUST be the slug the v1 server itself sent (`X402ExactAcceptEntry.wireNetwork`),
780
+ * not our canonical CAIP-2: v1 verifiers string-compare it against their own requirement.
781
+ * There is no `accepted` echo in v1 — the chosen rail is identified by these two flat fields.
782
+ */
783
+ declare function buildV1PaymentHeader(input: {
784
+ scheme: string;
785
+ network: string;
786
+ payload: unknown;
787
+ }): string;
651
788
  /**
652
789
  * Parse the PAYMENT-REQUIRED challenge from a 402 response. Prefers the
653
790
  * `payment-required` header, falls back to the JSON body.
@@ -747,6 +884,23 @@ declare function parseUptoPaymentHeader(value: string): ParsedUptoPayment | null
747
884
  * base64 wrapper, byte-identical to before this split on the HTTP path.
748
885
  */
749
886
  declare function parseUptoObject(parsed: unknown): ParsedUptoPayment | null;
887
+ /**
888
+ * Lift an x402 **v1** challenge body into the internal {@link X402Challenge} shape, so the
889
+ * whole buyer path downstream of `parseChallenge` stays v2-only and version-blind.
890
+ *
891
+ * Four v1→v2 skews are absorbed, and nothing else is touched (unknown keys ride along
892
+ * verbatim, so a facilitator's extras survive):
893
+ * 1. `maxAmountRequired` → `amount` (v2's rename). An accept that already has `amount` keeps it.
894
+ * 2. slug `network` (`'base'`) → CAIP-2 (`'eip155:8453'`) so the gather's `supports()` matches,
895
+ * with the ORIGINAL preserved on {@link X402ExactAcceptEntry.wireNetwork} because the v1
896
+ * server string-compares the slug it sent when we echo it back.
897
+ * 3. per-accept `resource` string → a top-level `resource` object (first accept that has one).
898
+ * 4. `x402Version: 1` is KEPT on the result — it is what tells `payExactRail` to answer on the
899
+ * v1 wire (`X-PAYMENT`, flat payload) instead of v2's `PAYMENT-SIGNATURE`.
900
+ *
901
+ * Pure: never mutates `body`, never throws (a caller passing a non-v1 value gets `null`).
902
+ */
903
+ declare function normalizeV1Challenge(body: unknown): X402Challenge | null;
750
904
  /**
751
905
  * Pick the first accepts[] entry on the `onchain-proof` scheme whose network
752
906
  * satisfies `matches` (any chain family). Returns null if none match.
@@ -958,4 +1112,4 @@ declare class SpendLedger {
958
1112
  summary(): SpendSummary;
959
1113
  }
960
1114
 
961
- export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
1115
+ export { normalizeV1Challenge as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, DEFAULT_EXACT_TRANSFER_METHOD as D, EXT_OFFER_RECEIPT as E, type X402PaymentSignature as F, type X402Receipt as G, HEADER_REQUIRED as H, type X402ResourceObject as I, type X402UptoAcceptEntry as J, KNOWN_EXACT_TRANSFER_METHODS as K, buildChallengeHeader as L, buildExactSignatureHeader as M, buildPaymentIdentifierAdvertisement as N, buildReceiptExtension as O, type PaidReceipt as P, buildReceiptHeader as Q, buildSignatureHeader as R, type SettleOutcome as S, buildUptoSignatureHeader as T, buildV1PaymentHeader as U, type VerifyErrorCode as V, decodeBase64Json as W, type X402AcceptEntry as X, exactTransferMethod as Y, isSettleableExactMethod as Z, memorySpendStore as _, type AssetId as a, parseChallenge as a0, parseExactObject as a1, parseExactPaymentHeader as a2, parseReceipt as a3, parseReceiptExtension as a4, parseSettleResponse as a5, parseSignatureHeader as a6, parseSignatureObject as a7, parseUptoObject as a8, parseUptoPaymentHeader as a9, pickAccept as aa, readPaymentIdentifier as ab, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
@@ -75,8 +75,28 @@ interface X402ExactAcceptEntry {
75
75
  asset: AssetId;
76
76
  payTo: AddressId;
77
77
  maxTimeoutSeconds: number;
78
- extra: {
79
- /** The exact transfer method. EVM: `'eip3009'` for tokens with native
78
+ /**
79
+ * The network id EXACTLY as an x402 **v1** server wrote it (a slug like `'base'`),
80
+ * preserved by {@link normalizeV1Challenge} because `network` above is canonicalised to
81
+ * CAIP-2 for matching while a v1 server string-compares the slug it sent. Internal to the
82
+ * v1 compat path — absent on every v2 rail, and STRIPPED from every outgoing `accepted`
83
+ * echo by `withoutWireNetwork`, since the merchant never published this key.
84
+ */
85
+ wireNetwork?: string;
86
+ /**
87
+ * Scheme-defined extras. **OPTIONAL when PARSING a foreign 402** — the exact-EVM scheme
88
+ * makes every `extra` key optional (`assetTransferMethod` defaults to `'eip3009'`), and the
89
+ * SVM/Algorand/Aptos/NEAR/Hedera schemes define no `assetTransferMethod` at all, so a
90
+ * conformant rail may ship `extra: {}` or omit the block entirely. A PipRail **gate** always
91
+ * emits it. Every read on the buyer path must optional-chain.
92
+ */
93
+ extra?: {
94
+ /** The exact transfer method. **OPTIONAL** — `scheme_exact_evm.md`: *"If no
95
+ * `assetTransferMethod` is specified in `PaymentRequired.extra`, clients should default
96
+ * to `\"eip3009\"`"* (and only the non-default methods make it required). The SVM,
97
+ * Algorand, Aptos, NEAR and Hedera schemes never define this key. Read it through
98
+ * {@link exactTransferMethod}, never bare — 91% of the deployed x402 web omits it.
99
+ * EVM: `'eip3009'` for tokens with native
80
100
  * `transferWithAuthorization`, or `'permit2'` for tokens WITHOUT it (e.g.
81
101
  * Binance-Peg USDC on BNB) — the payer signs a Permit2 witness transfer whose
82
102
  * `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
@@ -92,13 +112,46 @@ interface X402ExactAcceptEntry {
92
112
  * authorizing exactly one NEP-141 `ft_transfer` to `payTo` (per `scheme_exact_near.md`); a
93
113
  * facilitator-selected relayer (`feePayer` below) prepays gas + the 1 yoctoNEAR and submits, so
94
114
  * the buyer holds zero NEAR. PipRail self-settles ALL. */
95
- assetTransferMethod: 'eip3009' | 'permit2'
115
+ assetTransferMethod?: 'eip3009' | 'permit2'
96
116
  /** A FOREIGN-dialect alias for `'permit2'` — Binance's x402 ("b402") facilitator labels its
97
117
  * EVM-Permit2 exact rail `'permit2-exact'` (the coinbase/x402 spec uses bare `'permit2'`).
98
118
  * PipRail EMITS only `'permit2'`; it TOLERATES `'permit2-exact'` inbound so the buyer pays a
99
119
  * Binance-issued 402 (the buyer treats the two as one rail). NB: settlement still requires the
100
120
  * rail to bind PipRail's canonical x402ExactPermit2Proxy — see the buyer in drivers/evm. */
101
- | 'permit2-exact' | 'svm' | 'algorand' | 'aptos' | 'near';
121
+ | 'permit2-exact' | 'svm' | 'algorand' | 'aptos' | 'near'
122
+ /** **XRPL** — the ledger has exactly ONE way to move value (a `Payment`), so
123
+ * `scheme_exact_xrpl.md` spends this field on SEQUENCING instead of mechanism.
124
+ * `'sequence'` (the DEFAULT, and what all 1,732 live XRPL rails mean by omitting it) uses
125
+ * the payer's account sequence; `'ticketSequence'` sets `Sequence: 0` and supplies a
126
+ * pre-minted `TicketSequence`, letting a payer sign several payments that settle out of
127
+ * order. */
128
+ | 'sequence' | 'ticketSequence';
129
+ /** **XRPL, REQUIRED by the scheme — and absent from 100% of live rails.** The spec says it
130
+ * "must be false" (XRPL charges the fee to the transaction's own `Account`, so the payer
131
+ * always pays). Read it as *false unless present*: REQUIRING it would reject the entire
132
+ * deployed XRPL x402 web, which is exactly the bug class `assetTransferMethod` already caused
133
+ * once. A rail that explicitly says `true` is refused — we cannot honour a sponsor here. */
134
+ areFeesSponsored?: boolean;
135
+ /** **XRPL** — the issuer's classic address for an IOU rail (RLUSD and friends). Required by the
136
+ * scheme for issued currencies, absent for native XRP; present on 869 of the 1,732 live rails,
137
+ * which is precisely the IOU half. Also the discriminator the buyer uses to pick the
138
+ * issued-currency `Amount` object over a bare drops string. */
139
+ issuer?: string;
140
+ /** **XRPL, OPTIONAL** — an opaque invoice identifier. When present the buyer MUST set the
141
+ * transaction's `InvoiceID` to its **SHA-256**, as 32-byte hex; that hash is the challenge
142
+ * binding on this rail (there is no memo — the scheme has facilitators REJECT `Memos`).
143
+ * Present on 1,732 of 1,732 live rails, so treat it as always-on in practice. */
144
+ invoiceId?: string;
145
+ /** **XRPL** — a vendor correlation tag, copied verbatim into the transaction's `SourceTag`.
146
+ * NOT in `scheme_exact_xrpl.md`'s extra table, but present on **1,728 of the 1,732** live XRPL
147
+ * rails: it is how the deployed vendors match a payment back to their own quote. Mirrored
148
+ * because it costs nothing and omitting it is a plausible reason a merchant refuses. */
149
+ sourceTag?: number;
150
+ /** **XRPL, OPTIONAL** — a destination tag the buyer MUST copy verbatim into the transaction
151
+ * when the rail states one (hosted/exchange accounts route deposits by it). Never invented
152
+ * when absent: unlike the onchain-proof path, which derives a tag from the nonce, the exact
153
+ * rail sets `DestinationTag` only if the merchant asked for one. */
154
+ destinationTag?: number;
102
155
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
103
156
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
104
157
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -132,6 +185,42 @@ interface X402ExactAcceptEntry {
132
185
  symbol?: string;
133
186
  };
134
187
  }
188
+ /**
189
+ * The transfer method an `exact` rail uses when it names none.
190
+ *
191
+ * `scheme_exact_evm.md` §0: *"If no `assetTransferMethod` is specified in
192
+ * `PaymentRequired.extra`, clients should default to `"eip3009"`."* §1 restates it per-method:
193
+ * `eip3009` is *"optional in `PaymentRequired`, default"*, while `permit2` and `erc7710` are
194
+ * *"required"*. So an absent marker is not a malformed rail — it is the common case (91% of the
195
+ * deployed web) and it means EIP-3009.
196
+ */
197
+ declare const DEFAULT_EXACT_TRANSFER_METHOD: "eip3009";
198
+ /**
199
+ * Every `assetTransferMethod` a PipRail buyer can actually sign, across all families.
200
+ *
201
+ * Used to SKIP a rail that names a method we don't implement (the spec's `erc7710`, or any
202
+ * future one) rather than sign an EIP-3009 authorization a facilitator built for a different
203
+ * mechanism and will reject. An **absent** marker is not "unknown" — see
204
+ * {@link DEFAULT_EXACT_TRANSFER_METHOD}. Family routing stays in each driver's `payExact`;
205
+ * this set only answers "could any driver of ours settle this?".
206
+ */
207
+ declare const KNOWN_EXACT_TRANSFER_METHODS: ReadonlySet<string>;
208
+ /**
209
+ * The effective transfer method of an `exact` rail: what it names, or the default when it names
210
+ * nothing. THE ONLY sanctioned way to read `extra.assetTransferMethod` — reading it bare is how
211
+ * the buyer came to reject 91% of the x402 web.
212
+ *
213
+ * Pass `family` to get the right default off-EVM: a Solana rail that names nothing means `svm`,
214
+ * not `eip3009`. Without it the EVM default is assumed (correct for the settleability check,
215
+ * since every family's own literal is in {@link KNOWN_EXACT_TRANSFER_METHODS} anyway).
216
+ */
217
+ declare function exactTransferMethod(accept: X402ExactAcceptEntry, family?: string): string;
218
+ /**
219
+ * Can any PipRail driver settle this rail's transfer method? True when the rail names a
220
+ * method we implement, AND when it names none (the spec default `eip3009`). False only for a
221
+ * method we don't implement — the rail is then skipped at gather rather than mis-signed.
222
+ */
223
+ declare function isSettleableExactMethod(accept: X402ExactAcceptEntry): boolean;
135
224
  /**
136
225
  * A standard x402 `upto` rail (EVM / Permit2) — variable-amount / metered billing.
137
226
  * The buyer signs a Permit2 `PermitWitnessTransferFrom` authorization for `amount`
@@ -181,7 +270,13 @@ interface X402UptoAcceptEntry {
181
270
  * rail, or a standard `upto` (metered) rail. */
182
271
  type X402AnyAccept = X402AcceptEntry | X402ExactAcceptEntry | X402UptoAcceptEntry;
183
272
  interface X402Challenge {
184
- x402Version: 2;
273
+ /**
274
+ * `2` for every challenge PipRail EMITS. `1` appears only on the PARSE side, when
275
+ * {@link normalizeV1Challenge} has lifted a still-deployed v1 server's body into this
276
+ * shape — the buyer must then answer on the v1 wire (`X-PAYMENT`, flat payload). See the
277
+ * version-posture note above {@link HEADER_SIGNATURE_V1}.
278
+ */
279
+ x402Version: 1 | 2;
185
280
  /**
186
281
  * Optional human-readable reason (v2 `error?: string`). PipRail EMITS it only on a
187
282
  * rejected-proof re-challenge (omitted on a fresh challenge). Typed to also tolerate
@@ -361,10 +456,25 @@ interface ExactNearPaymentPayload {
361
456
  /** Base64 of the Borsh-encoded NEP-366 `SignedDelegateAction` (one `ft_transfer`). */
362
457
  signedDelegateAction: string;
363
458
  }
459
+ /**
460
+ * The `payload` a client sends for the **XRPL `exact`** variant, per `scheme_exact_xrpl.md`:
461
+ * a **fully signed** XRPL `Payment` transaction, hex-encoded, that the resource server (or its
462
+ * facilitator) submits. The signed blob IS the proof — there is no separate authorization object.
463
+ *
464
+ * XRPL is the one family where **the payer pays the network fee**: the fee is a field inside the
465
+ * signed transaction and the ledger charges it to `Account`. So there is no sponsor, no fee-payer
466
+ * co-signature, and no fee-drain guard to write — the buyer needs XRP for the amount *and* the fee.
467
+ * That also means the buyer signs something immediately submittable, so `LastLedgerSequence` is
468
+ * mandatory: it is the only thing bounding how long the merchant may sit on it.
469
+ */
470
+ interface ExactXrplPaymentPayload {
471
+ /** Hex-encoded, fully signed XRPL `Payment` transaction blob. */
472
+ signedTxBlob: string;
473
+ }
364
474
  /** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
365
- * SVM (`transaction`), Algorand (`paymentGroup`), Aptos (`transaction` + `senderAuth`), or NEAR
366
- * (`signedDelegateAction`). */
367
- type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload | ExactNearPaymentPayload;
475
+ * SVM (`transaction`), Algorand (`paymentGroup`), Aptos (`transaction` + `senderAuth`), NEAR
476
+ * (`signedDelegateAction`), or XRPL (`signedTxBlob`). */
477
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload | ExactNearPaymentPayload | ExactXrplPaymentPayload;
368
478
  interface ParsedExactBase {
369
479
  x402Version: number;
370
480
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
@@ -385,7 +495,9 @@ interface ParsedExactBase {
385
495
  * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`), `'algorand'` →
386
496
  * {@link ExactAlgorandPaymentPayload} (`paymentGroup`); `'aptos'` →
387
497
  * {@link ExactAptosPaymentPayload} (`transaction` + `senderAuth`); `'near'` →
388
- * {@link ExactNearPaymentPayload} (`signedDelegateAction`).
498
+ * {@link ExactNearPaymentPayload} (`signedDelegateAction`); `'sequence'` / `'ticketSequence'` →
499
+ * {@link ExactXrplPaymentPayload} (`signedTxBlob`) — XRPL is the one family whose method literal
500
+ * names the SEQUENCING strategy rather than a transfer mechanism, because it has only one.
389
501
  */
390
502
  type ParsedExactPayment = (ParsedExactBase & {
391
503
  method: 'eip3009';
@@ -405,6 +517,12 @@ type ParsedExactPayment = (ParsedExactBase & {
405
517
  }) | (ParsedExactBase & {
406
518
  method: 'near';
407
519
  payload: ExactNearPaymentPayload;
520
+ }) | (ParsedExactBase & {
521
+ method: 'sequence';
522
+ payload: ExactXrplPaymentPayload;
523
+ }) | (ParsedExactBase & {
524
+ method: 'ticketSequence';
525
+ payload: ExactXrplPaymentPayload;
408
526
  });
409
527
  /**
410
528
  * What {@link parseUptoPaymentHeader} extracts from an inbound `upto` payment — the
@@ -648,6 +766,25 @@ declare function buildUptoSignatureHeader(input: {
648
766
  accepted: X402UptoAcceptEntry;
649
767
  payload: Permit2UptoPaymentPayload;
650
768
  }): string;
769
+ /**
770
+ * Build the **v1** `X-PAYMENT` header value — the flat, pre-v2 payload shape
771
+ * `{ x402Version: 1, scheme, network, payload }`, base64-JSON.
772
+ *
773
+ * This is the `encodeXPaymentHeader` utility the version-posture note above has always
774
+ * described; it had never been written, so the buyer could parse nothing from a v1 server and
775
+ * could answer nothing either. Needed because v2 moved the header `X-PAYMENT` →
776
+ * `PAYMENT-SIGNATURE` and reshaped the payload: a v1 server ignores `PAYMENT-SIGNATURE`
777
+ * entirely (verified live — it just re-challenges) and reads only `X-PAYMENT`.
778
+ *
779
+ * `network` MUST be the slug the v1 server itself sent (`X402ExactAcceptEntry.wireNetwork`),
780
+ * not our canonical CAIP-2: v1 verifiers string-compare it against their own requirement.
781
+ * There is no `accepted` echo in v1 — the chosen rail is identified by these two flat fields.
782
+ */
783
+ declare function buildV1PaymentHeader(input: {
784
+ scheme: string;
785
+ network: string;
786
+ payload: unknown;
787
+ }): string;
651
788
  /**
652
789
  * Parse the PAYMENT-REQUIRED challenge from a 402 response. Prefers the
653
790
  * `payment-required` header, falls back to the JSON body.
@@ -747,6 +884,23 @@ declare function parseUptoPaymentHeader(value: string): ParsedUptoPayment | null
747
884
  * base64 wrapper, byte-identical to before this split on the HTTP path.
748
885
  */
749
886
  declare function parseUptoObject(parsed: unknown): ParsedUptoPayment | null;
887
+ /**
888
+ * Lift an x402 **v1** challenge body into the internal {@link X402Challenge} shape, so the
889
+ * whole buyer path downstream of `parseChallenge` stays v2-only and version-blind.
890
+ *
891
+ * Four v1→v2 skews are absorbed, and nothing else is touched (unknown keys ride along
892
+ * verbatim, so a facilitator's extras survive):
893
+ * 1. `maxAmountRequired` → `amount` (v2's rename). An accept that already has `amount` keeps it.
894
+ * 2. slug `network` (`'base'`) → CAIP-2 (`'eip155:8453'`) so the gather's `supports()` matches,
895
+ * with the ORIGINAL preserved on {@link X402ExactAcceptEntry.wireNetwork} because the v1
896
+ * server string-compares the slug it sent when we echo it back.
897
+ * 3. per-accept `resource` string → a top-level `resource` object (first accept that has one).
898
+ * 4. `x402Version: 1` is KEPT on the result — it is what tells `payExactRail` to answer on the
899
+ * v1 wire (`X-PAYMENT`, flat payload) instead of v2's `PAYMENT-SIGNATURE`.
900
+ *
901
+ * Pure: never mutates `body`, never throws (a caller passing a non-v1 value gets `null`).
902
+ */
903
+ declare function normalizeV1Challenge(body: unknown): X402Challenge | null;
750
904
  /**
751
905
  * Pick the first accepts[] entry on the `onchain-proof` scheme whose network
752
906
  * satisfies `matches` (any chain family). Returns null if none match.
@@ -958,4 +1112,4 @@ declare class SpendLedger {
958
1112
  summary(): SpendSummary;
959
1113
  }
960
1114
 
961
- export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
1115
+ export { normalizeV1Challenge as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, DEFAULT_EXACT_TRANSFER_METHOD as D, EXT_OFFER_RECEIPT as E, type X402PaymentSignature as F, type X402Receipt as G, HEADER_REQUIRED as H, type X402ResourceObject as I, type X402UptoAcceptEntry as J, KNOWN_EXACT_TRANSFER_METHODS as K, buildChallengeHeader as L, buildExactSignatureHeader as M, buildPaymentIdentifierAdvertisement as N, buildReceiptExtension as O, type PaidReceipt as P, buildReceiptHeader as Q, buildSignatureHeader as R, type SettleOutcome as S, buildUptoSignatureHeader as T, buildV1PaymentHeader as U, type VerifyErrorCode as V, decodeBase64Json as W, type X402AcceptEntry as X, exactTransferMethod as Y, isSettleableExactMethod as Z, memorySpendStore as _, type AssetId as a, parseChallenge as a0, parseExactObject as a1, parseExactPaymentHeader as a2, parseReceipt as a3, parseReceiptExtension as a4, parseSettleResponse as a5, parseSignatureHeader as a6, parseSignatureObject as a7, parseUptoObject as a8, parseUptoPaymentHeader as a9, pickAccept as aa, readPaymentIdentifier as ab, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };