@piprail/sdk 1.15.1 → 1.17.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
@@ -82,8 +82,12 @@ interface X402ExactAcceptEntry {
82
82
  payTo: AddressId;
83
83
  maxTimeoutSeconds: number;
84
84
  extra: {
85
- /** The exact-EVM transfer method. PipRail self-settles EIP-3009 today. */
86
- assetTransferMethod: 'eip3009';
85
+ /** The exact-EVM transfer method, per the x402 `exact` EVM scheme: `'eip3009'`
86
+ * for tokens with native `transferWithAuthorization`, or `'permit2'` for tokens
87
+ * WITHOUT it (e.g. Binance-Peg USDC on BNB) — the payer signs a Permit2 witness
88
+ * transfer whose `spender` is the canonical x402ExactPermit2Proxy and whose
89
+ * `witness.to` binds the recipient. PipRail self-settles BOTH. */
90
+ assetTransferMethod: 'eip3009' | 'permit2';
87
91
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
88
92
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
89
93
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -154,22 +158,65 @@ interface ExactPaymentPayload {
154
158
  authorization: ExactAuthorizationWire;
155
159
  }
156
160
  /**
157
- * What {@link parseExactPaymentHeader} extracts from an inbound `exact` payment,
158
- * normalised across the v1 (`X-PAYMENT`, flat `{scheme,network,payload}`, network
159
- * slug) and v2 (`PAYMENT-SIGNATURE`, `{accepted,payload}`, CAIP-2 network) wire
160
- * shapes. `network`/`asset` are the CLIENT's claim used only to MATCH an offered
161
- * rail; the gate re-derives every verified field from its own trusted rail.
161
+ * The `permit2Authorization` a payer signs for the `permit2` variant of the x402
162
+ * `exact` EVM scheme (tokens without EIP-3009 e.g. Binance-Peg USDC on BNB). It is
163
+ * an EIP-712 `PermitWitnessTransferFrom` over the canonical Permit2 contract, whose
164
+ * `spender` is the canonical **x402ExactPermit2Proxy** and whose **witness** binds the
165
+ * recipient (`to`) + an activation time (`validAfter`). All numeric fields are DECIMAL
166
+ * strings on the wire (`permitted.amount`, `nonce`, `deadline`, `witness.validAfter`).
162
167
  */
163
- interface ParsedExactPayment {
168
+ interface Permit2Authorization {
169
+ /** What may be pulled: the ERC-20 token + the exact base-unit amount. */
170
+ permitted: {
171
+ token: string;
172
+ amount: string;
173
+ };
174
+ /** The payer (token owner). */
175
+ from: string;
176
+ /** The signature's allowed spender — the canonical x402ExactPermit2Proxy. */
177
+ spender: string;
178
+ /** Permit2 unordered nonce (a uint256, decimal string). Single-use via its bitmap. */
179
+ nonce: string;
180
+ /** Unix-seconds signature expiry. */
181
+ deadline: string;
182
+ /** The proxy-enforced witness: funds go ONLY to `to`, and not before `validAfter`. */
183
+ witness: {
184
+ to: string;
185
+ validAfter: string;
186
+ };
187
+ }
188
+ /** The `payload` a client sends for the `permit2` exact variant: a signature + its Permit2 authorization. */
189
+ interface Permit2PaymentPayload {
190
+ signature: string;
191
+ permit2Authorization: Permit2Authorization;
192
+ }
193
+ /** Either `exact`-rail payload shape — EIP-3009 (`authorization`) or Permit2 (`permit2Authorization`). */
194
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload;
195
+ interface ParsedExactBase {
164
196
  x402Version: number;
165
197
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
166
198
  network: string;
167
199
  /** The client's claimed asset, if present (v2 `accepted.asset`). */
168
200
  asset?: string;
169
- payload: ExactPaymentPayload;
170
201
  /** The full decoded PaymentPayload, for verbatim forwarding to a facilitator (Mode B). */
171
202
  raw: Record<string, unknown>;
172
203
  }
204
+ /**
205
+ * What {@link parseExactPaymentHeader} extracts from an inbound `exact` payment,
206
+ * normalised across the v1 (`X-PAYMENT`, flat `{scheme,network,payload}`, network slug)
207
+ * and v2 (`PAYMENT-SIGNATURE`, `{accepted,payload}`, CAIP-2 network) wire shapes.
208
+ * `network`/`asset` are the CLIENT's claim — used only to MATCH an offered rail; the gate
209
+ * re-derives every verified field from its own trusted rail. A discriminated union on
210
+ * `method`, so narrowing on `method` narrows `payload`: `'eip3009'` → {@link ExactPaymentPayload}
211
+ * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`).
212
+ */
213
+ type ParsedExactPayment = (ParsedExactBase & {
214
+ method: 'eip3009';
215
+ payload: ExactPaymentPayload;
216
+ }) | (ParsedExactBase & {
217
+ method: 'permit2';
218
+ payload: Permit2PaymentPayload;
219
+ });
173
220
  interface X402Receipt {
174
221
  scheme: 'onchain-proof' | 'exact';
175
222
  /**
@@ -192,6 +239,37 @@ interface X402Receipt {
192
239
  payTo: AddressId;
193
240
  verifiedAt: string;
194
241
  }
242
+ /**
243
+ * The settled-payment record handed to a gate's `onPaid` hook — the wire
244
+ * {@link X402Receipt} plus the merchant-facing extras the gate already computed
245
+ * for the challenge, so a receipt handler never needs a second lookup to display
246
+ * or reconcile it: the token's `decimals`/`symbol`, the human `amountFormatted`
247
+ * (derived from the SETTLED base-unit `amount`, not the requested price), and a
248
+ * stable `idempotencyKey`.
249
+ *
250
+ * **Delivery contract — read this before persisting receipts.** `onPaid` is
251
+ * **at-least-once**: with a single in-memory replay store it fires exactly once
252
+ * per proof, but across instances sharing a custom `isUsed`/`markUsed` store two
253
+ * nodes can settle the same proof in a race and each fire once. Always **dedupe on
254
+ * `idempotencyKey`** (a unique index / upsert). It is also fire-and-forget by
255
+ * default — the gate does not block the response on it and a process crash between
256
+ * settlement and your side-effect drops that receipt. For durability either set
257
+ * `awaitOnPaid` (record before the 200) or push to a durable queue inside the hook;
258
+ * for a webhook, use {@link deliverReceipt} (signed, retried, idempotent).
259
+ */
260
+ interface PaidReceipt extends X402Receipt {
261
+ /** The token's on-chain decimals — pairs with `amount` so you can format without a lookup. */
262
+ decimals: number;
263
+ /** The token symbol when the gate knows it (e.g. `USDC`, `FDUSD`). */
264
+ symbol?: string;
265
+ /** Human-readable settled amount, e.g. `"0.05"` — `amount` / 10**`decimals`. */
266
+ amountFormatted: string;
267
+ /**
268
+ * A stable, unique key for this settlement (the settled `transaction` id). `onPaid`
269
+ * is at-least-once across instances — dedupe persistence and webhook delivery on this.
270
+ */
271
+ idempotencyKey: string;
272
+ }
195
273
  /**
196
274
  * Why a verification failed — a closed, chain-agnostic vocabulary. Every code a
197
275
  * driver returns is in this union; a client/agent branches on it rather than
@@ -236,7 +314,7 @@ declare function buildSignatureHeader(signature: X402PaymentSignature): string;
236
314
  */
237
315
  declare function buildExactSignatureHeader(input: {
238
316
  accepted: X402ExactAcceptEntry;
239
- payload: ExactPaymentPayload;
317
+ payload: ExactPaymentPayloadAny;
240
318
  }): string;
241
319
  /**
242
320
  * Parse the PAYMENT-REQUIRED challenge from a 402 response. Prefers the
@@ -610,7 +688,7 @@ declare const CHAINS: {
610
688
  value: bigint;
611
689
  yParity: number;
612
690
  accessList: viem.AccessList;
613
- authorizationList? /** EVM chain id, e.g. 5000 for Mantle. */: undefined | undefined;
691
+ authorizationList?: undefined | undefined;
614
692
  blobVersionedHashes?: undefined | undefined;
615
693
  chainId: number;
616
694
  type: "eip1559";
@@ -619,7 +697,7 @@ declare const CHAINS: {
619
697
  maxFeePerGas: bigint;
620
698
  maxPriorityFeePerGas: bigint;
621
699
  isSystemTx?: undefined | undefined;
622
- mint? /** Known tokens on this chain (empty for unknown custom chains). */: undefined | undefined;
700
+ mint?: undefined | undefined;
623
701
  sourceHash?: undefined | undefined;
624
702
  } | {
625
703
  blockHash: `0x${string}` | null;
@@ -1019,11 +1097,13 @@ declare const CHAINS: {
1019
1097
  maxPriorityFeePerGas: bigint;
1020
1098
  isSystemTx?: undefined | undefined;
1021
1099
  mint?: undefined | undefined;
1022
- sourceHash? /** Known tokens on this chain (empty for unknown custom chains). */: undefined | undefined;
1100
+ sourceHash?: undefined | undefined;
1023
1101
  } | {
1024
1102
  blockHash: `0x${string}` | null;
1025
1103
  blockNumber: bigint | null;
1026
- blockTimestamp?: bigint | undefined;
1104
+ blockTimestamp
1105
+ /** EVM chain id, e.g. 5000 for Mantle. */
1106
+ ? /** EVM chain id, e.g. 5000 for Mantle. */: bigint | undefined;
1027
1107
  from: abitype.Address;
1028
1108
  gas: bigint;
1029
1109
  hash: viem.Hash;
@@ -1257,6 +1337,16 @@ declare const CHAINS: {
1257
1337
  decimals: number;
1258
1338
  symbol: string;
1259
1339
  };
1340
+ FDUSD: {
1341
+ address: "0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409";
1342
+ decimals: number;
1343
+ symbol: string;
1344
+ };
1345
+ USD1: {
1346
+ address: "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d";
1347
+ decimals: number;
1348
+ symbol: string;
1349
+ };
1260
1350
  };
1261
1351
  };
1262
1352
  avalanche: {
@@ -2725,7 +2815,9 @@ declare const CHAINS: {
2725
2815
  chainId: number;
2726
2816
  type: "eip7702";
2727
2817
  gasPrice?: undefined | undefined;
2728
- maxFeePerBlobGas?: undefined | undefined;
2818
+ maxFeePerBlobGas
2819
+ /** JSON-RPC endpoint. */
2820
+ ? /** JSON-RPC endpoint. */: undefined | undefined;
2729
2821
  maxFeePerGas: bigint;
2730
2822
  maxPriorityFeePerGas: bigint;
2731
2823
  l1BatchNumber: bigint | null;
@@ -4230,7 +4322,7 @@ interface ResolvedNetwork {
4230
4322
  * and the nonce (for the client's spend record + a re-present-the-same-auth retry).
4231
4323
  */
4232
4324
  payExact?(wallet: WalletHandle, accept: X402ExactAcceptEntry): Promise<{
4233
- payload: ExactPaymentPayload;
4325
+ payload: ExactPaymentPayloadAny;
4234
4326
  accepted: X402ExactAcceptEntry;
4235
4327
  payerFrom: string;
4236
4328
  nonce: string;
@@ -4280,7 +4372,7 @@ interface ResolvedNetwork {
4280
4372
  */
4281
4373
  settleExactSelf?(input: {
4282
4374
  relayer: WalletHandle;
4283
- payload: ExactPaymentPayload;
4375
+ payload: ExactPaymentPayloadAny;
4284
4376
  accept: X402ExactAcceptEntry;
4285
4377
  }): Promise<VerifyResult>;
4286
4378
  }
@@ -5627,16 +5719,18 @@ interface AcceptOption {
5627
5719
  rpcUrl?: string;
5628
5720
  }
5629
5721
  /**
5630
- * Opt into ALSO advertising a standard x402 `exact` rail (EIP-3009) beside the
5631
- * default `onchain-proof` rail, so ANY standard x402 client can pay this gate
5632
- * (dual-advertise). EVM + EIP-3009 tokens only (USDC, EURC NOT USDT, NOT native).
5633
- * Omitting `exact` leaves the gate byte-identical to today (onchain-proof only).
5722
+ * Opt into ALSO advertising a standard x402 `exact` rail beside the default
5723
+ * `onchain-proof` rail, so ANY standard x402 client can pay this gate (dual-advertise).
5724
+ * EVM ERC-20 only **EIP-3009** (USDC, EURC) or, for tokens without it, **Permit2**
5725
+ * (any ERC-20 e.g. Binance-Peg USDC on BNB, settled via the canonical
5726
+ * x402ExactPermit2Proxy). NOT native coins, NOT non-EVM chains. Omitting `exact` leaves
5727
+ * the gate byte-identical to today (onchain-proof only).
5634
5728
  *
5635
5729
  * Two settlement modes, both backendless (PipRail hosts nothing):
5636
- * - `settle: 'self'` — your own `relayer` key broadcasts `transferWithAuthorization`.
5637
- * You pay gas to RECEIVE (the inverse of onchain-proof, where the payer pays gas)
5638
- * and must keep the relayer funded. The signature binds `to`, so there's no
5639
- * redirect risk. This is the on-brand default for the rail.
5730
+ * - `settle: 'self'` — your own `relayer` key broadcasts the settle (EIP-3009's
5731
+ * `transferWithAuthorization`, or the proxy's `settle` for Permit2). You pay gas to
5732
+ * RECEIVE (the inverse of onchain-proof) and keep the relayer funded. The signature
5733
+ * binds the recipient, so there's no redirect risk. The on-brand default for the rail.
5640
5734
  * - `settle: { facilitator }` — delegate verify+settle to a third-party x402
5641
5735
  * facilitator YOU choose (Coinbase CDP, x402.org, …). No relayer key needed; the
5642
5736
  * facilitator pays gas. Also the only path onto Coinbase's Bazaar directory.
@@ -5649,6 +5743,10 @@ interface ExactRailOption {
5649
5743
  /** Required for `settle: 'self'` — the gas-paying relayer wallet: EVM `{ privateKey }`
5650
5744
  * or a bring-your-own `{ walletClient }`. (Distinct from `payTo`, the receive address.) */
5651
5745
  relayer?: unknown;
5746
+ /** Which exact-EVM transfer method to advertise. `'auto'` (default) uses EIP-3009 when the
5747
+ * token supports it, else Permit2 — so a non-EIP-3009 token like Binance-Peg USDC on BNB
5748
+ * "just works". Force `'eip3009'` or `'permit2'` to pin one. */
5749
+ method?: 'eip3009' | 'permit2' | 'auto';
5652
5750
  }
5653
5751
  interface RequirePaymentOptions {
5654
5752
  /**
@@ -5696,8 +5794,28 @@ interface RequirePaymentOptions {
5696
5794
  isUsed?: (ref: string) => boolean | Promise<boolean>;
5697
5795
  /** Replay hook — record a redeemed proof. */
5698
5796
  markUsed?: (ref: string) => void | Promise<void>;
5699
- /** Fired when a payment verifies successfully. */
5700
- onPaid?: (receipt: X402Receipt) => void;
5797
+ /**
5798
+ * Fired when a payment verifies successfully, with the enriched {@link PaidReceipt}.
5799
+ * May be **sync or async** — a throw OR a rejected promise is isolated (routed to
5800
+ * `onPaidError`), so the hook can never break the request or crash the process.
5801
+ * Fire-and-forget by default (the response is not blocked on it); set `awaitOnPaid`
5802
+ * to record the receipt before the resource is served. `onPaid` is **at-least-once**
5803
+ * across instances — dedupe on `receipt.idempotencyKey`. See {@link PaidReceipt}.
5804
+ */
5805
+ onPaid?: (receipt: PaidReceipt) => void | Promise<void>;
5806
+ /**
5807
+ * Observe a failure inside `onPaid` (sync throw or async rejection). Without it,
5808
+ * a failing receipt hook is swallowed silently — set this to log/alert/queue the
5809
+ * dropped receipt. Its own throws are also swallowed (it can never break a request).
5810
+ */
5811
+ onPaidError?: (error: unknown, receipt: PaidReceipt) => void;
5812
+ /**
5813
+ * Await `onPaid` before returning the paid result (and thus before the gated
5814
+ * resource is served), so "receipt recorded" is guaranteed on the happy path.
5815
+ * Default `false` (fire-and-forget — lower latency). A rejection is still isolated
5816
+ * via `onPaidError`; it never turns a settled payment into a 402.
5817
+ */
5818
+ awaitOnPaid?: boolean;
5701
5819
  /**
5702
5820
  * ALSO advertise a standard x402 `exact` rail (EIP-3009) so any standard x402
5703
5821
  * client can pay this gate — opt-in, EVM/EIP-3009 only. See {@link ExactRailOption}.
@@ -5867,6 +5985,85 @@ interface SettleViaFacilitatorInput extends FacilitatorConfig {
5867
5985
  */
5868
5986
  declare function settleViaFacilitator(input: SettleViaFacilitatorInput): Promise<VerifyResult>;
5869
5987
 
5988
+ /**
5989
+ * Reliable receipt delivery — the durable webhook a stateless gate can't be.
5990
+ *
5991
+ * `deliverReceipt(receipt, { url, secret })` POSTs a settled {@link PaidReceipt} to
5992
+ * YOUR OWN endpoint, with retries + exponential backoff, an HMAC-SHA256 signature,
5993
+ * and an idempotency key. It is the recommended body of an `onPaid` hook when you
5994
+ * want at-least-once delivery to a webhook instead of a fire-and-forget callback:
5995
+ *
5996
+ * createPaymentGate({
5997
+ * chain, token, amount, payTo,
5998
+ * awaitOnPaid: true, // record before serving
5999
+ * onPaid: (r) => deliverReceipt(r, {
6000
+ * url: process.env.RECEIPTS_WEBHOOK,
6001
+ * secret: process.env.RECEIPTS_SECRET, // signs the body
6002
+ * }),
6003
+ * })
6004
+ *
6005
+ * Charter note: PipRail hosts nothing — `url` is **your** endpoint. This is a pure
6006
+ * transport primitive (no chain libraries), isomorphic (global `fetch` + Web Crypto),
6007
+ * and it **never throws**: failures come back as `{ delivered: false, … }`, because a
6008
+ * delivery helper that threw would reintroduce the very crash `onPaid` isolation
6009
+ * prevents. The receiver verifies the signature and dedupes on the idempotency key.
6010
+ */
6011
+
6012
+ interface DeliverReceiptOptions {
6013
+ /** Your receiving endpoint. PipRail hosts nothing — this is your server. */
6014
+ url: string;
6015
+ /**
6016
+ * Shared secret. When set, the raw JSON body is signed HMAC-SHA256 and sent as
6017
+ * `<signatureHeader>: sha256=<hex>` so the receiver can verify authenticity.
6018
+ */
6019
+ secret?: string;
6020
+ /** Extra retry attempts after the first send (default 5 → up to 6 POSTs total). */
6021
+ retries?: number;
6022
+ /** Per-attempt timeout in ms (default 10000). An attempt that exceeds it is aborted + retried. */
6023
+ timeoutMs?: number;
6024
+ /** Extra request headers (merged; never override the signature/idempotency headers). */
6025
+ headers?: Record<string, string>;
6026
+ /** Header carrying the signature. Default `piprail-signature`. */
6027
+ signatureHeader?: string;
6028
+ /** Header carrying the dedupe key (= `receipt.idempotencyKey`). Default `idempotency-key`. */
6029
+ idempotencyHeader?: string;
6030
+ /** Backoff before retry N (1-based) in ms. Default jittered exponential (cap 30s). */
6031
+ backoff?: (attempt: number) => number;
6032
+ /** Injected `fetch` (tests / non-global-fetch runtimes). Defaults to the global. */
6033
+ fetchImpl?: typeof fetch;
6034
+ /** Observe each attempt (logging/metrics). Its own throws are ignored. */
6035
+ onAttempt?: (info: DeliverAttempt) => void;
6036
+ }
6037
+ /** One delivery attempt's outcome (passed to `onAttempt`). */
6038
+ interface DeliverAttempt {
6039
+ /** 1-based attempt number. */
6040
+ attempt: number;
6041
+ /** Did the endpoint return a 2xx? */
6042
+ ok: boolean;
6043
+ /** HTTP status, when a response was received. */
6044
+ status?: number;
6045
+ /** Transport/abort error message, when no response was received. */
6046
+ error?: string;
6047
+ /** Will another attempt follow? */
6048
+ willRetry: boolean;
6049
+ }
6050
+ /** The terminal result of `deliverReceipt` — it never throws, so always inspect this. */
6051
+ interface DeliverResult {
6052
+ /** True iff the endpoint returned a 2xx within the attempt budget. */
6053
+ delivered: boolean;
6054
+ /** Total POSTs made (1 + retries used). */
6055
+ attempts: number;
6056
+ /** Final HTTP status, when the last attempt got a response. */
6057
+ status?: number;
6058
+ /** Final error, when delivery failed (last transport error or a non-2xx summary). */
6059
+ error?: string;
6060
+ }
6061
+ /**
6062
+ * POST a settled receipt to your endpoint with retries, a timeout, an HMAC signature,
6063
+ * and an idempotency key. Never throws — returns a {@link DeliverResult}.
6064
+ */
6065
+ declare function deliverReceipt(receipt: PaidReceipt, options: DeliverReceiptOptions): Promise<DeliverResult>;
6066
+
5870
6067
  /**
5871
6068
  * The driver registry — the ONLY place the families meet. Routing decides a
5872
6069
  * family from the `chain` value (synchronously), then asks that family's
@@ -6157,8 +6354,10 @@ declare class UnsupportedNetworkError extends PipRailError {
6157
6354
  * the same funds to the same payTo and waste their own gas — no redirect risk.
6158
6355
  */
6159
6356
 
6160
- /** x402 network slug → EVM chain id, for the chains PipRail ships with EIP-3009
6161
- * USDC. Extend as needed; an unknown slug just won't be selected. */
6357
+ /** x402 network slug → EVM chain id, for the chains PipRail ships an exact-payable
6358
+ * stablecoin on EIP-3009 USDC/EURC on most, and **Permit2** on BNB (Binance-Peg
6359
+ * USDC isn't EIP-3009). Extend as needed; an unknown slug just won't be selected.
6360
+ * (Matching uses CAIP-2 via `net.supports`; this is the public slug helper.) */
6162
6361
  declare const EXACT_NETWORK_SLUGS: Readonly<Record<string, number>>;
6163
6362
  /** Resolve an x402 `exact` network slug (e.g. "base") to its EVM chain id. */
6164
6363
  declare function chainIdForExactNetwork(slug: string): number | null;
@@ -6359,22 +6558,109 @@ declare const eip3009Abi: readonly [{
6359
6558
  readonly outputs: readonly [{
6360
6559
  readonly type: "string";
6361
6560
  }];
6561
+ }, {
6562
+ readonly type: "function";
6563
+ readonly name: "DOMAIN_SEPARATOR";
6564
+ readonly stateMutability: "view";
6565
+ readonly inputs: readonly [];
6566
+ readonly outputs: readonly [{
6567
+ readonly type: "bytes32";
6568
+ }];
6362
6569
  }];
6363
6570
  /**
6364
- * Read an EIP-3009 token's true EIP-712 domain `{ name, version }` from the
6365
- * contract — what a payer must sign over. Returns `null` if the asset is NOT an
6366
- * EIP-3009 token (no `authorizationState`/`version` — e.g. USDT, native coin, a
6367
- * plain ERC-20), so the gate refuses to advertise a standard `exact` rail for it.
6571
+ * Read an EIP-3009 token's true EIP-712 domain `{ name, version }` from the contract — what a
6572
+ * payer must sign over. Returns `null` if the asset is NOT an EIP-3009 token (no
6573
+ * `authorizationState` — e.g. USDT, native coin, a plain ERC-20), so the caller falls back to
6574
+ * permit2 / onchain-proof.
6575
+ *
6576
+ * The name is NEVER assumed from the symbol: canonical USDC's domain name is "USD Coin" (not
6577
+ * "USDC"), and EURC's is "Euro Coin" on Ethereum/Avalanche but "EURC" on Base — only the on-chain
6578
+ * read is authoritative.
6368
6579
  *
6369
- * The name is NEVER assumed from the symbol: canonical USDC's domain name is
6370
- * "USD Coin" (not "USDC"), and EURC's is "Euro Coin" on Ethereum/Avalanche but "EURC"
6371
- * on Base proof that only the on-chain read is authoritative. `eip712Domain()`
6372
- * (EIP-5267) reverts on these proxies, so we read `name()`+`version()` and probe
6373
- * `authorizationState` to confirm EIP-3009 support.
6580
+ * The version comes from `version()` when the token exposes it (canonical FiatToken USDC is
6581
+ * "2"). Many EIP-3009 tokens HARDCODE the domain version and DON'T expose `version()` — e.g.
6582
+ * **FDUSD and USD1 on BNB Chain** (both "1"). For those we DERIVE the version by matching the
6583
+ * token's on-chain `DOMAIN_SEPARATOR()` against the standard 4-field domain for a small set of
6584
+ * common versions; a token with a non-standard / salted domain returns `null` (→ permit2 fallback).
6374
6585
  */
6375
6586
  declare function readExactDomain(publicClient: PublicClient, asset: string): Promise<{
6376
6587
  name: string;
6377
6588
  version: string;
6378
6589
  } | null>;
6379
6590
 
6380
- export { type AcceptOption, type AddressId, type AgentTool, type AlgorandToken, type AptosToken, type AssetId, type BazaarExtension, type BuildExactParams, CHAINS, type Caip2, type ChainFamily, type ChainInput, type ChainName, type ChainPreset, type ChainSelector, type ChallengeTriage, type ChallengeVerdict, type ConfirmInfo, ConfirmationTimeoutError, type CostEstimate, DIRECTORY_INFO, type DeclineReasonCode, type DirectoryInfo, type DiscoverOptions, type DiscoveredRail, type DiscoveredResource, type DiscoveryDescriptor, type DiscoverySigner, type DiscoverySource, type DomainClaim, type DomainVerification, EIP3009_TYPES, EXACT_NETWORK_SLUGS, type EvmToken, type ExactAccept, type ExactAuthorization, type ExactAuthorizationWire, type ExactPaymentPayload, type ExactRailOption, type ExpressLikeMiddleware, type ExpressLikeNext, type ExpressLikeRequest, type ExpressLikeResponse, type FacilitatorConfig, type FacilitatorPaymentRequirements, GENERATOR, HEADER_REQUIRED, HEADER_RESPONSE, HEADER_RESPONSE_V1, HEADER_SIGNATURE, HEADER_SIGNATURE_V1, InsufficientFundsError, InvalidEnvelopeError, type ListingVisibility, type ManifestInput, MaxRetriesExceededError, MissingDriverError, type NearToken, NoCompatibleAcceptError, NonReplayableBodyError, type OpenApiDocument, type OpenApiOperation, PIPRAIL_AGENT_GUIDE, type ParsedExactPayment, type PayBlocker, type PayOption, type PayWarning, PaymentDeclinedError, type PaymentDriver, type PaymentGate, type PaymentIntent, type PaymentPlan, type PaymentPolicy, type PaymentRail, type PaymentScheme, PaymentTimeoutError, PipRailClient, type PipRailClientOptions, type PipRailCostQuote, PipRailError, type PipRailEvent, type PipRailQuote, type PolicyDecision, type PolicyDenyCode, RecipientNotReadyError, type RecipientReason, type RegisterInput, type RegisterOptions, type RegisterOutcome, type RequirePaymentOptions, type ResolveOptions, type ResolvedChain, type ResolvedNetwork, type ResolvedToken, type ResourceDescription, type SearchOpenIndexesOptions, type SessionBudget, type SettleOutcome, type SettleViaFacilitatorInput, SettlementError, type SolanaToken, type SpendAssetTotal, type SpendRecord, type SpendRemaining, type SpendSummary, type StellarToken, type SuiToken, type TokenInfo, type TokenInput, type TonToken, type ToolAnnotations, type TronToken, UnknownTokenError, UnsupportedNetworkError, UnsupportedSchemeError, type VerifyErrorCode, type VerifyPaymentResult, type VerifyResult, type WalletBalance, type WalletHandle, type WalletInput, type WellKnownX402, WrongChainError, WrongFamilyError, type X402AcceptEntry, type X402AnyAccept, type X402Challenge, type X402DnsRecord, type X402ExactAcceptEntry, type X402InvalidBody, type X402PaymentSignature, type X402Receipt, type X402ResourceObject, type XrplToken, agentGuide, buildBazaarExtension, buildChallengeHeader, buildExactAuthorization, buildExactSignatureHeader, buildOpenApi, buildReceiptHeader, buildSignatureHeader, buildWellKnownX402, buildX402DnsTxt, chainIdForExactNetwork, claim402IndexDomain, classifyChallenge, createPaymentGate, decorateOutcome, eip3009Abi, encodeXPaymentHeader, evaluatePolicy, explainDecline, formatSpendReport, getDirectoryInfo, normalizeNetwork, parseChallenge, parseExactPaymentHeader, parseExactRequirements, parseReceipt, parseSettleResponse, parseSignatureHeader, paymentTools, pickAccept, planAcross, readExactDomain, register402Index, registerDriver, registerX402Scan, requirePayment, resolveChain, searchOpenIndexes, settleViaFacilitator, summarizePlan, toInsufficientFundsError, toInvalidBody, verify402IndexDomain };
6591
+ /**
6592
+ * ── EVM SECTION: x402 `exact` scheme, `permit2` variant — BUYER + SELLER ──────
6593
+ *
6594
+ * The companion to `exact.ts` for ERC-20 tokens that do NOT implement EIP-3009
6595
+ * `transferWithAuthorization` — most notably **Binance-Peg USDC/USDT on BNB Chain**
6596
+ * (no native Circle USDC exists on BNB). The x402 `exact` EVM scheme defines a second
6597
+ * `assetTransferMethod`, `"permit2"`, for exactly these tokens:
6598
+ *
6599
+ * • The payer signs an EIP-712 **`PermitWitnessTransferFrom`** over the canonical
6600
+ * **Permit2** contract, with `spender` = the canonical **x402ExactPermit2Proxy**
6601
+ * and a **witness** that binds the recipient (`to`) + an activation time
6602
+ * (`validAfter`). The buyer never broadcasts (and, after a one-time Permit2 approval,
6603
+ * spends ~0 gas) — the merchant/facilitator broadcasts.
6604
+ * • The merchant/facilitator settles by calling the **proxy's `settle(...)`**, which
6605
+ * calls `Permit2.permitWitnessTransferFrom`. Because the signed `spender` is the
6606
+ * proxy and the proxy forces `transferDetails.to == witness.to`, a relayer can only
6607
+ * push the signed funds to the signed recipient — no redirect risk (same guarantee
6608
+ * EIP-3009's `to`-binding gives us).
6609
+ *
6610
+ * Spec: github.com/coinbase/x402 `specs/schemes/exact/scheme_exact_evm.md` (the Permit2
6611
+ * method). Both contracts are canonical CREATE2 deployments (same address every EVM
6612
+ * chain) and are verified deployed on BNB. This module mirrors `exact.ts` file-for-file
6613
+ * (buyer {@link payPermit2Evm}; seller {@link verifyAndSettlePermit2Evm}); the EVM
6614
+ * driver routes to it on `accept.extra.assetTransferMethod === 'permit2'`.
6615
+ *
6616
+ * One-time setup: the payer must `approve(Permit2, max)` on the token ONCE
6617
+ * ({@link ensurePermit2Allowance} does this lazily) — after that, every payment is a
6618
+ * gasless signature. This is the only way `permit2` differs operationally from EIP-3009.
6619
+ */
6620
+
6621
+ /** Canonical Permit2 (Uniswap), same address on every EVM chain incl. BNB. */
6622
+ declare const PERMIT2_ADDRESS: "0x000000000022D473030F116dDEE9F6B43aC78BA3";
6623
+ /** Canonical x402ExactPermit2Proxy (CREATE2), same address on every EVM chain incl. BNB.
6624
+ * It is the `spender` the buyer signs over, and the contract the seller settles through;
6625
+ * it enforces `transferDetails.to == witness.to`, so funds can only reach the signed payTo. */
6626
+ declare const X402_EXACT_PERMIT2_PROXY: "0x402085c248EeA27D92E8b30b2C58ed07f9E20001";
6627
+ /**
6628
+ * EIP-712 type set for the x402 `permit2` exact method. MUST encode to exactly the type
6629
+ * string Permit2 reconstructs for `permitWitnessTransferFrom`:
6630
+ * `PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,uint256 validAfter)`
6631
+ * (viem orders referenced structs alphabetically → TokenPermissions before Witness ✓.)
6632
+ */
6633
+ declare const PERMIT2_WITNESS_TYPES: {
6634
+ readonly PermitWitnessTransferFrom: readonly [{
6635
+ readonly name: "permitted";
6636
+ readonly type: "TokenPermissions";
6637
+ }, {
6638
+ readonly name: "spender";
6639
+ readonly type: "address";
6640
+ }, {
6641
+ readonly name: "nonce";
6642
+ readonly type: "uint256";
6643
+ }, {
6644
+ readonly name: "deadline";
6645
+ readonly type: "uint256";
6646
+ }, {
6647
+ readonly name: "witness";
6648
+ readonly type: "Witness";
6649
+ }];
6650
+ readonly TokenPermissions: readonly [{
6651
+ readonly name: "token";
6652
+ readonly type: "address";
6653
+ }, {
6654
+ readonly name: "amount";
6655
+ readonly type: "uint256";
6656
+ }];
6657
+ readonly Witness: readonly [{
6658
+ readonly name: "to";
6659
+ readonly type: "address";
6660
+ }, {
6661
+ readonly name: "validAfter";
6662
+ readonly type: "uint256";
6663
+ }];
6664
+ };
6665
+
6666
+ export { type AcceptOption, type AddressId, type AgentTool, type AlgorandToken, type AptosToken, type AssetId, type BazaarExtension, type BuildExactParams, CHAINS, type Caip2, type ChainFamily, type ChainInput, type ChainName, type ChainPreset, type ChainSelector, type ChallengeTriage, type ChallengeVerdict, type ConfirmInfo, ConfirmationTimeoutError, type CostEstimate, DIRECTORY_INFO, type DeclineReasonCode, type DeliverAttempt, type DeliverReceiptOptions, type DeliverResult, type DirectoryInfo, type DiscoverOptions, type DiscoveredRail, type DiscoveredResource, type DiscoveryDescriptor, type DiscoverySigner, type DiscoverySource, type DomainClaim, type DomainVerification, EIP3009_TYPES, EXACT_NETWORK_SLUGS, type EvmToken, type ExactAccept, type ExactAuthorization, type ExactAuthorizationWire, type ExactPaymentPayload, type ExactPaymentPayloadAny, type ExactRailOption, type ExpressLikeMiddleware, type ExpressLikeNext, type ExpressLikeRequest, type ExpressLikeResponse, type FacilitatorConfig, type FacilitatorPaymentRequirements, GENERATOR, HEADER_REQUIRED, HEADER_RESPONSE, HEADER_RESPONSE_V1, HEADER_SIGNATURE, HEADER_SIGNATURE_V1, InsufficientFundsError, InvalidEnvelopeError, type ListingVisibility, type ManifestInput, MaxRetriesExceededError, MissingDriverError, type NearToken, NoCompatibleAcceptError, NonReplayableBodyError, type OpenApiDocument, type OpenApiOperation, PERMIT2_ADDRESS, PERMIT2_WITNESS_TYPES, PIPRAIL_AGENT_GUIDE, type PaidReceipt, type ParsedExactPayment, type PayBlocker, type PayOption, type PayWarning, PaymentDeclinedError, type PaymentDriver, type PaymentGate, type PaymentIntent, type PaymentPlan, type PaymentPolicy, type PaymentRail, type PaymentScheme, PaymentTimeoutError, type Permit2Authorization, type Permit2PaymentPayload, PipRailClient, type PipRailClientOptions, type PipRailCostQuote, PipRailError, type PipRailEvent, type PipRailQuote, type PolicyDecision, type PolicyDenyCode, RecipientNotReadyError, type RecipientReason, type RegisterInput, type RegisterOptions, type RegisterOutcome, type RequirePaymentOptions, type ResolveOptions, type ResolvedChain, type ResolvedNetwork, type ResolvedToken, type ResourceDescription, type SearchOpenIndexesOptions, type SessionBudget, type SettleOutcome, type SettleViaFacilitatorInput, SettlementError, type SolanaToken, type SpendAssetTotal, type SpendRecord, type SpendRemaining, type SpendSummary, type StellarToken, type SuiToken, type TokenInfo, type TokenInput, type TonToken, type ToolAnnotations, type TronToken, UnknownTokenError, UnsupportedNetworkError, UnsupportedSchemeError, type VerifyErrorCode, type VerifyPaymentResult, type VerifyResult, type WalletBalance, type WalletHandle, type WalletInput, type WellKnownX402, WrongChainError, WrongFamilyError, type X402AcceptEntry, type X402AnyAccept, type X402Challenge, type X402DnsRecord, type X402ExactAcceptEntry, type X402InvalidBody, type X402PaymentSignature, type X402Receipt, type X402ResourceObject, X402_EXACT_PERMIT2_PROXY, type XrplToken, agentGuide, buildBazaarExtension, buildChallengeHeader, buildExactAuthorization, buildExactSignatureHeader, buildOpenApi, buildReceiptHeader, buildSignatureHeader, buildWellKnownX402, buildX402DnsTxt, chainIdForExactNetwork, claim402IndexDomain, classifyChallenge, createPaymentGate, decorateOutcome, deliverReceipt, eip3009Abi, encodeXPaymentHeader, evaluatePolicy, explainDecline, formatSpendReport, getDirectoryInfo, normalizeNetwork, parseChallenge, parseExactPaymentHeader, parseExactRequirements, parseReceipt, parseSettleResponse, parseSignatureHeader, paymentTools, pickAccept, planAcross, readExactDomain, register402Index, registerDriver, registerX402Scan, requirePayment, resolveChain, searchOpenIndexes, settleViaFacilitator, summarizePlan, toInsufficientFundsError, toInvalidBody, verify402IndexDomain };