@piprail/sdk 1.20.1 → 1.21.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.cts CHANGED
@@ -82,12 +82,14 @@ interface X402ExactAcceptEntry {
82
82
  payTo: AddressId;
83
83
  maxTimeoutSeconds: number;
84
84
  extra: {
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';
85
+ /** The exact transfer method. EVM: `'eip3009'` for tokens with native
86
+ * `transferWithAuthorization`, or `'permit2'` for tokens WITHOUT it (e.g.
87
+ * Binance-Peg USDC on BNB) — the payer signs a Permit2 witness transfer whose
88
+ * `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
89
+ * recipient. **Solana (SVM): `'svm'`** the payer partial-signs an SPL
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
93
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
92
94
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
93
95
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -95,6 +97,20 @@ interface X402ExactAcceptEntry {
95
97
  name?: string;
96
98
  /** EIP-712 domain version of the token (USDC: "2"). OPTIONAL (see `name`); read/re-derived on-chain. */
97
99
  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). */
105
+ feePayer?: string;
106
+ /** **SVM only, OPTIONAL** — a ≤256-byte reconciliation memo the buyer attaches to the
107
+ * transaction (the SVM scheme's optional `extra.memo`). */
108
+ memo?: string;
109
+ /** **SVM only** — which SPL token program the mint belongs to, so both the buyer and
110
+ * the gate derive the SAME associated-token-account address (an ATA's address depends
111
+ * on the token program). Defaults to `'spl-token'` (classic) when absent — the
112
+ * built-in USDC/USDT are classic. */
113
+ tokenProgram?: 'spl-token' | 'token-2022';
98
114
  /** Confirmations the gate waits for before granting access — mirrors the gate's
99
115
  * `minConfirmations`, so the exact rail honours the same reorg safety as onchain-proof.
100
116
  * A PipRail convenience (standard clients ignore unknown keys). */
@@ -190,8 +206,19 @@ interface Permit2PaymentPayload {
190
206
  signature: string;
191
207
  permit2Authorization: Permit2Authorization;
192
208
  }
193
- /** Either `exact`-rail payload shape — EIP-3009 (`authorization`) or Permit2 (`permit2Authorization`). */
194
- type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload;
209
+ /**
210
+ * The `payload` a client sends for the **SVM (Solana) `exact`** variant: a base64-encoded,
211
+ * serialized, **partially-signed** versioned Solana transaction (the buyer's `TransferChecked`
212
+ * with the merchant as fee payer; the fee-payer signature slot is left empty for the gate to
213
+ * fill). Per `scheme_exact_svm.md`. The transaction itself IS the proof — there's no separate
214
+ * authorization object (the SVM analogue of EIP-3009's `authorization`).
215
+ */
216
+ interface ExactSvmPaymentPayload {
217
+ transaction: string;
218
+ }
219
+ /** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
220
+ * or SVM (`transaction`). */
221
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload;
195
222
  interface ParsedExactBase {
196
223
  x402Version: number;
197
224
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
@@ -208,7 +235,8 @@ interface ParsedExactBase {
208
235
  * `network`/`asset` are the CLIENT's claim — used only to MATCH an offered rail; the gate
209
236
  * re-derives every verified field from its own trusted rail. A discriminated union on
210
237
  * `method`, so narrowing on `method` narrows `payload`: `'eip3009'` → {@link ExactPaymentPayload}
211
- * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`).
238
+ * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`),
239
+ * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`).
212
240
  */
213
241
  type ParsedExactPayment = (ParsedExactBase & {
214
242
  method: 'eip3009';
@@ -216,6 +244,9 @@ type ParsedExactPayment = (ParsedExactBase & {
216
244
  }) | (ParsedExactBase & {
217
245
  method: 'permit2';
218
246
  payload: Permit2PaymentPayload;
247
+ }) | (ParsedExactBase & {
248
+ method: 'svm';
249
+ payload: ExactSvmPaymentPayload;
219
250
  });
220
251
  interface X402Receipt {
221
252
  scheme: 'onchain-proof' | 'exact';
@@ -4224,6 +4255,22 @@ interface DiscoverySigner {
4224
4255
  /** Sign an arbitrary UTF-8 message (EVM: eip191) — for proofs/SIWX only. */
4225
4256
  signMessage(message: string): Promise<string>;
4226
4257
  }
4258
+ /**
4259
+ * How a family advertises a standard `exact` rail for one asset — returned by
4260
+ * {@link ResolvedNetwork.resolveExactRail} and consumed by the gate to build the
4261
+ * `X402ExactAcceptEntry`. The `method` is the family's transfer method (EVM:
4262
+ * `'eip3009'`/`'permit2'`, Solana: `'svm'`); `extra` is merged VERBATIM into the
4263
+ * accept's `extra`, carrying the family-specific bits a payer needs (EVM: the EIP-712
4264
+ * `name`/`version`; Solana: the merchant `feePayer` + `tokenProgram`). Keeping the
4265
+ * chain-specific shape behind this descriptor is what lets `server.ts` stay
4266
+ * chain-agnostic — it never names a family, it just merges `extra`.
4267
+ */
4268
+ interface ExactRailInfo {
4269
+ method: 'eip3009' | 'permit2' | 'svm';
4270
+ /** Family-specific `extra` keys merged into the exact accept (e.g. `{ name, version }`
4271
+ * for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana). */
4272
+ extra?: Record<string, unknown>;
4273
+ }
4227
4274
  /**
4228
4275
  * A driver bound to one concrete network — what the gate and client hold. Each
4229
4276
  * method's error behaviour is fixed by the SDK error standard (see ERRORS.md §5):
@@ -4342,6 +4389,30 @@ interface ResolvedNetwork {
4342
4389
  discoverySigner?(wallet: WalletHandle): DiscoverySigner | null;
4343
4390
  /** Verify `ref` satisfies `accept`, RPC-only, in-process. */
4344
4391
  verify(ref: string, accept: X402AcceptEntry): Promise<VerifyResult>;
4392
+ /**
4393
+ * OPTIONAL — resolve a standard `exact` rail for `asset` on this network, or `null`
4394
+ * when this asset/chain can't carry one (a native coin, an unsupported token, or a
4395
+ * family with no `exact` settlement). This is the gate's rail-ADVERTISEMENT SPI: the
4396
+ * chain-agnostic `server.ts` calls it to decide whether to dual-advertise an `exact`
4397
+ * rail beside `onchain-proof`, and uses the returned {@link ExactRailInfo} to build the
4398
+ * `X402ExactAcceptEntry` — so the gate never special-cases a family.
4399
+ *
4400
+ * `method` is the merchant's preference (`'auto'` lets the family pick — EVM auto-selects
4401
+ * EIP-3009 over Permit2; Solana ignores it and always uses `'svm'`). The fee payer for a
4402
+ * family that needs one (Solana) comes from EITHER `feePayer` (a facilitator-provided
4403
+ * sponsor pubkey, in facilitator mode — so neither buyer nor merchant pays gas) OR `relayer`
4404
+ * (the merchant's own bound self-settle wallet, in self mode); `feePayer` takes precedence.
4405
+ * RPC-read (EVM reads the token's EIP-712 domain; Solana reads the mint's token program); MAY
4406
+ * 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).
4408
+ */
4409
+ resolveExactRail?(input: {
4410
+ asset: string;
4411
+ method: 'eip3009' | 'permit2' | 'svm' | 'auto';
4412
+ relayer?: WalletHandle;
4413
+ /** A facilitator-provided fee-payer pubkey (facilitator mode); overrides the relayer's. */
4414
+ feePayer?: string;
4415
+ }): Promise<ExactRailInfo | null>;
4345
4416
  /**
4346
4417
  * OPTIONAL (EVM-only today) — the on-chain EIP-712 domain `{ name, version }` of an
4347
4418
  * EIP-3009 token `asset`, read from the contract (`name()`/`version()`). Returns
@@ -4763,7 +4834,7 @@ interface SpendSummary {
4763
4834
  }
4764
4835
 
4765
4836
  /** The payment schemes a client can settle: PipRail's native `onchain-proof` (the
4766
- * default) and the standard x402 `exact` rail (EVM + EIP-3009 only, opt-in). */
4837
+ * default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM, opt-in). */
4767
4838
  type PaymentScheme = 'onchain-proof' | 'exact';
4768
4839
 
4769
4840
  /** Observability events. `ref` is the proof — a chain-specific id (EVM tx hash, Solana signature, TON locator, Stellar tx hash). */
@@ -5064,9 +5135,10 @@ interface PipRailClientOptions {
5064
5135
  *
5065
5136
  * new PipRailClient({ chain: 'base', wallet, schemes: ['onchain-proof', 'exact'] })
5066
5137
  *
5067
- * `exact` is **EVM + EIP-3009 only** (USDC/EURC); it's silently ignored on a
5068
- * non-EVM chain, for USDT/native, or for a token the SDK can't price — those keep
5069
- * `onchain-proof`. The agent signs an EIP-3009 authorization with its OWN wallet
5138
+ * `exact` is **EVM (EIP-3009/Permit2) + Solana (SVM)** today (USDC/EURC); it's
5139
+ * silently ignored on a family without an `exact` rail, for native, or for a token the
5140
+ * SDK can't price — those keep `onchain-proof`. The agent signs the authorization (an
5141
+ * EIP-3009 message on EVM, a partial-signed transaction on Solana) with its OWN wallet
5070
5142
  * and the server / merchant-chosen facilitator broadcasts it (the buyer pays ~0
5071
5143
  * gas; PipRail hosts/settles nothing). The same `policy` + `onBeforePay` gate it
5072
5144
  * BEFORE signing. **Verify against your target facilitator before production.**
@@ -5251,7 +5323,7 @@ declare class PipRailClient {
5251
5323
  * before publishing, so retry with a brief backoff if a fresh listing is missing.
5252
5324
  * - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
5253
5325
  * `onchain-proof` rails by default, and standard `exact` rails too once you opt in
5254
- * with `schemes: ['onchain-proof', 'exact']` (EVM + EIP-3009 USDC/EURC).
5326
+ * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
5255
5327
  */
5256
5328
  discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
5257
5329
  /**
@@ -5744,31 +5816,41 @@ interface AcceptOption {
5744
5816
  /**
5745
5817
  * Opt into ALSO advertising a standard x402 `exact` rail beside the default
5746
5818
  * `onchain-proof` rail, so ANY standard x402 client can pay this gate (dual-advertise).
5747
- * EVM ERC-20 only — **EIP-3009** (USDC, EURC) or, for tokens without it, **Permit2**
5748
- * (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical
5749
- * x402ExactPermit2Proxy). NOT native coins, NOT non-EVM chains. Omitting `exact` leaves
5750
- * the gate byte-identical to today (onchain-proof only).
5819
+ * Supported on **EVM ERC-20** — **EIP-3009** (USDC, EURC) or, for tokens without it, **Permit2**
5820
+ * (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical x402ExactPermit2Proxy) —
5821
+ * and on **Solana** (any SPL token; the buyer partial-signs a `TransferChecked` and your relayer
5822
+ * is the fee payer). NOT native coins, NOT families without a standard `exact` scheme. Omitting
5823
+ * `exact` leaves the gate byte-identical to today (onchain-proof only).
5751
5824
  *
5752
5825
  * Two settlement modes, both backendless (PipRail hosts nothing):
5753
- * - `settle: 'self'` — your own `relayer` key broadcasts the settle (EIP-3009's
5754
- * `transferWithAuthorization`, or the proxy's `settle` for Permit2). You pay gas to
5755
- * RECEIVE (the inverse of onchain-proof) and keep the relayer funded. The signature
5756
- * binds the recipient, so there's no redirect risk. The on-brand default for the rail.
5757
- * - `settle: { facilitator }` — delegate verify+settle to a third-party x402
5758
- * facilitator YOU choose (Coinbase CDP, x402.org, …). No relayer key needed; the
5759
- * facilitator pays gas. Also the only path onto Coinbase's Bazaar directory.
5826
+ * - `settle: 'self'` — your own `relayer` key broadcasts the settle (EVM EIP-3009's
5827
+ * `transferWithAuthorization` / the proxy's `settle` for Permit2; on Solana, co-signing the
5828
+ * buyer's transaction as the fee payer). You pay gas to RECEIVE (the inverse of onchain-proof)
5829
+ * and keep the relayer funded. The signature binds the recipient, so there's no redirect risk.
5830
+ * The on-brand backendless default for the rail.
5831
+ * - `settle: { facilitator }` delegate verify+settle to a third-party x402 facilitator YOU
5832
+ * choose. **The facilitator pays the gas, so neither the buyer nor the merchant pays any** —
5833
+ * fully gasless end to end. On **EVM** use Coinbase CDP, x402.org, PayAI, …; on **Solana** use a
5834
+ * facilitator that sponsors the fee payer (e.g. PayAI's `https://facilitator.payai.network`,
5835
+ * no API key) — the gate reads its fee-payer pubkey from `GET /supported` automatically. No
5836
+ * relayer key needed. (EVM facilitators are also the path onto Coinbase's Bazaar directory.)
5760
5837
  */
5761
5838
  interface ExactRailOption {
5762
5839
  settle: 'self' | {
5763
5840
  facilitator: string;
5764
5841
  authHeaders?: () => Promise<Record<string, string>>;
5842
+ /** Solana only — the facilitator's fee-payer pubkey, if you'd rather set it than have the
5843
+ * gate read it from the facilitator's `GET /supported`. Optional: omitted, the gate
5844
+ * discovers it automatically (e.g. PayAI). Ignored on EVM. */
5845
+ feePayer?: string;
5765
5846
  };
5766
- /** Required for `settle: 'self'` — the gas-paying relayer wallet: EVM `{ privateKey }`
5767
- * or a bring-your-own `{ walletClient }`. (Distinct from `payTo`, the receive address.) */
5847
+ /** Required for `settle: 'self'` — the gas-paying relayer wallet: EVM `{ privateKey }` /
5848
+ * `{ walletClient }`, or Solana `{ secretKey }` / `{ signer }`. (Distinct from `payTo`, the
5849
+ * receive address — on Solana they MUST be different keys, a scheme MUST-rule.) */
5768
5850
  relayer?: unknown;
5769
- /** Which exact-EVM transfer method to advertise. `'auto'` (default) uses EIP-3009 when the
5851
+ /** Which exact transfer method to advertise (EVM). `'auto'` (default) uses EIP-3009 when the
5770
5852
  * token supports it, else Permit2 — so a non-EIP-3009 token like Binance-Peg USDC on BNB
5771
- * "just works". Force `'eip3009'` or `'permit2'` to pin one. */
5853
+ * "just works". Force `'eip3009'` or `'permit2'` to pin one. Ignored on Solana (always SVM). */
5772
5854
  method?: 'eip3009' | 'permit2' | 'auto';
5773
5855
  }
5774
5856
  interface RequirePaymentOptions {
@@ -5840,8 +5922,8 @@ interface RequirePaymentOptions {
5840
5922
  */
5841
5923
  awaitOnPaid?: boolean;
5842
5924
  /**
5843
- * ALSO advertise a standard x402 `exact` rail (EIP-3009) so any standard x402
5844
- * client can pay this gate — opt-in, EVM/EIP-3009 only. See {@link ExactRailOption}.
5925
+ * ALSO advertise a standard x402 `exact` rail so any standard x402 client can pay this
5926
+ * gate — opt-in, EVM (EIP-3009/Permit2) + Solana (SVM). See {@link ExactRailOption}.
5845
5927
  * Omit to keep the gate exactly as today (`onchain-proof` only).
5846
5928
  */
5847
5929
  exact?: ExactRailOption;
@@ -5963,7 +6045,9 @@ declare function requirePayment(options: RequirePaymentOptions): ExpressLikeMidd
5963
6045
  * SELF-settling merchant must guard replay itself (the gate's used-proof set does).
5964
6046
  */
5965
6047
 
5966
- /** Standard x402 `exact` PaymentRequirements, built from the gate's TRUSTED rail. */
6048
+ /** Standard x402 `exact` PaymentRequirements, built from the gate's TRUSTED rail. `extra`
6049
+ * carries the scheme's chain-specific fields: EVM EIP-3009 → `{ name, version }` (the token's
6050
+ * EIP-712 domain), Solana SVM → `{ feePayer }` (the facilitator's fee-payer pubkey). */
5967
6051
  interface FacilitatorPaymentRequirements {
5968
6052
  scheme: 'exact';
5969
6053
  network: string;
@@ -5971,10 +6055,7 @@ interface FacilitatorPaymentRequirements {
5971
6055
  amount: string;
5972
6056
  payTo: string;
5973
6057
  maxTimeoutSeconds: number;
5974
- extra: {
5975
- name: string;
5976
- version: string;
5977
- };
6058
+ extra: Record<string, unknown>;
5978
6059
  }
5979
6060
  /** A merchant-chosen facilitator: its base URL + optional per-request auth headers. */
5980
6061
  interface FacilitatorConfig {
package/dist/index.d.ts CHANGED
@@ -82,12 +82,14 @@ interface X402ExactAcceptEntry {
82
82
  payTo: AddressId;
83
83
  maxTimeoutSeconds: number;
84
84
  extra: {
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';
85
+ /** The exact transfer method. EVM: `'eip3009'` for tokens with native
86
+ * `transferWithAuthorization`, or `'permit2'` for tokens WITHOUT it (e.g.
87
+ * Binance-Peg USDC on BNB) — the payer signs a Permit2 witness transfer whose
88
+ * `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
89
+ * recipient. **Solana (SVM): `'svm'`** the payer partial-signs an SPL
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
93
  /** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
92
94
  * `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
93
95
  * from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
@@ -95,6 +97,20 @@ interface X402ExactAcceptEntry {
95
97
  name?: string;
96
98
  /** EIP-712 domain version of the token (USDC: "2"). OPTIONAL (see `name`); read/re-derived on-chain. */
97
99
  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). */
105
+ feePayer?: string;
106
+ /** **SVM only, OPTIONAL** — a ≤256-byte reconciliation memo the buyer attaches to the
107
+ * transaction (the SVM scheme's optional `extra.memo`). */
108
+ memo?: string;
109
+ /** **SVM only** — which SPL token program the mint belongs to, so both the buyer and
110
+ * the gate derive the SAME associated-token-account address (an ATA's address depends
111
+ * on the token program). Defaults to `'spl-token'` (classic) when absent — the
112
+ * built-in USDC/USDT are classic. */
113
+ tokenProgram?: 'spl-token' | 'token-2022';
98
114
  /** Confirmations the gate waits for before granting access — mirrors the gate's
99
115
  * `minConfirmations`, so the exact rail honours the same reorg safety as onchain-proof.
100
116
  * A PipRail convenience (standard clients ignore unknown keys). */
@@ -190,8 +206,19 @@ interface Permit2PaymentPayload {
190
206
  signature: string;
191
207
  permit2Authorization: Permit2Authorization;
192
208
  }
193
- /** Either `exact`-rail payload shape — EIP-3009 (`authorization`) or Permit2 (`permit2Authorization`). */
194
- type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload;
209
+ /**
210
+ * The `payload` a client sends for the **SVM (Solana) `exact`** variant: a base64-encoded,
211
+ * serialized, **partially-signed** versioned Solana transaction (the buyer's `TransferChecked`
212
+ * with the merchant as fee payer; the fee-payer signature slot is left empty for the gate to
213
+ * fill). Per `scheme_exact_svm.md`. The transaction itself IS the proof — there's no separate
214
+ * authorization object (the SVM analogue of EIP-3009's `authorization`).
215
+ */
216
+ interface ExactSvmPaymentPayload {
217
+ transaction: string;
218
+ }
219
+ /** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
220
+ * or SVM (`transaction`). */
221
+ type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload;
195
222
  interface ParsedExactBase {
196
223
  x402Version: number;
197
224
  /** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
@@ -208,7 +235,8 @@ interface ParsedExactBase {
208
235
  * `network`/`asset` are the CLIENT's claim — used only to MATCH an offered rail; the gate
209
236
  * re-derives every verified field from its own trusted rail. A discriminated union on
210
237
  * `method`, so narrowing on `method` narrows `payload`: `'eip3009'` → {@link ExactPaymentPayload}
211
- * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`).
238
+ * (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`),
239
+ * `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`).
212
240
  */
213
241
  type ParsedExactPayment = (ParsedExactBase & {
214
242
  method: 'eip3009';
@@ -216,6 +244,9 @@ type ParsedExactPayment = (ParsedExactBase & {
216
244
  }) | (ParsedExactBase & {
217
245
  method: 'permit2';
218
246
  payload: Permit2PaymentPayload;
247
+ }) | (ParsedExactBase & {
248
+ method: 'svm';
249
+ payload: ExactSvmPaymentPayload;
219
250
  });
220
251
  interface X402Receipt {
221
252
  scheme: 'onchain-proof' | 'exact';
@@ -4224,6 +4255,22 @@ interface DiscoverySigner {
4224
4255
  /** Sign an arbitrary UTF-8 message (EVM: eip191) — for proofs/SIWX only. */
4225
4256
  signMessage(message: string): Promise<string>;
4226
4257
  }
4258
+ /**
4259
+ * How a family advertises a standard `exact` rail for one asset — returned by
4260
+ * {@link ResolvedNetwork.resolveExactRail} and consumed by the gate to build the
4261
+ * `X402ExactAcceptEntry`. The `method` is the family's transfer method (EVM:
4262
+ * `'eip3009'`/`'permit2'`, Solana: `'svm'`); `extra` is merged VERBATIM into the
4263
+ * accept's `extra`, carrying the family-specific bits a payer needs (EVM: the EIP-712
4264
+ * `name`/`version`; Solana: the merchant `feePayer` + `tokenProgram`). Keeping the
4265
+ * chain-specific shape behind this descriptor is what lets `server.ts` stay
4266
+ * chain-agnostic — it never names a family, it just merges `extra`.
4267
+ */
4268
+ interface ExactRailInfo {
4269
+ method: 'eip3009' | 'permit2' | 'svm';
4270
+ /** Family-specific `extra` keys merged into the exact accept (e.g. `{ name, version }`
4271
+ * for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana). */
4272
+ extra?: Record<string, unknown>;
4273
+ }
4227
4274
  /**
4228
4275
  * A driver bound to one concrete network — what the gate and client hold. Each
4229
4276
  * method's error behaviour is fixed by the SDK error standard (see ERRORS.md §5):
@@ -4342,6 +4389,30 @@ interface ResolvedNetwork {
4342
4389
  discoverySigner?(wallet: WalletHandle): DiscoverySigner | null;
4343
4390
  /** Verify `ref` satisfies `accept`, RPC-only, in-process. */
4344
4391
  verify(ref: string, accept: X402AcceptEntry): Promise<VerifyResult>;
4392
+ /**
4393
+ * OPTIONAL — resolve a standard `exact` rail for `asset` on this network, or `null`
4394
+ * when this asset/chain can't carry one (a native coin, an unsupported token, or a
4395
+ * family with no `exact` settlement). This is the gate's rail-ADVERTISEMENT SPI: the
4396
+ * chain-agnostic `server.ts` calls it to decide whether to dual-advertise an `exact`
4397
+ * rail beside `onchain-proof`, and uses the returned {@link ExactRailInfo} to build the
4398
+ * `X402ExactAcceptEntry` — so the gate never special-cases a family.
4399
+ *
4400
+ * `method` is the merchant's preference (`'auto'` lets the family pick — EVM auto-selects
4401
+ * EIP-3009 over Permit2; Solana ignores it and always uses `'svm'`). The fee payer for a
4402
+ * family that needs one (Solana) comes from EITHER `feePayer` (a facilitator-provided
4403
+ * sponsor pubkey, in facilitator mode — so neither buyer nor merchant pays gas) OR `relayer`
4404
+ * (the merchant's own bound self-settle wallet, in self mode); `feePayer` takes precedence.
4405
+ * RPC-read (EVM reads the token's EIP-712 domain; Solana reads the mint's token program); MAY
4406
+ * 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).
4408
+ */
4409
+ resolveExactRail?(input: {
4410
+ asset: string;
4411
+ method: 'eip3009' | 'permit2' | 'svm' | 'auto';
4412
+ relayer?: WalletHandle;
4413
+ /** A facilitator-provided fee-payer pubkey (facilitator mode); overrides the relayer's. */
4414
+ feePayer?: string;
4415
+ }): Promise<ExactRailInfo | null>;
4345
4416
  /**
4346
4417
  * OPTIONAL (EVM-only today) — the on-chain EIP-712 domain `{ name, version }` of an
4347
4418
  * EIP-3009 token `asset`, read from the contract (`name()`/`version()`). Returns
@@ -4763,7 +4834,7 @@ interface SpendSummary {
4763
4834
  }
4764
4835
 
4765
4836
  /** The payment schemes a client can settle: PipRail's native `onchain-proof` (the
4766
- * default) and the standard x402 `exact` rail (EVM + EIP-3009 only, opt-in). */
4837
+ * default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM, opt-in). */
4767
4838
  type PaymentScheme = 'onchain-proof' | 'exact';
4768
4839
 
4769
4840
  /** Observability events. `ref` is the proof — a chain-specific id (EVM tx hash, Solana signature, TON locator, Stellar tx hash). */
@@ -5064,9 +5135,10 @@ interface PipRailClientOptions {
5064
5135
  *
5065
5136
  * new PipRailClient({ chain: 'base', wallet, schemes: ['onchain-proof', 'exact'] })
5066
5137
  *
5067
- * `exact` is **EVM + EIP-3009 only** (USDC/EURC); it's silently ignored on a
5068
- * non-EVM chain, for USDT/native, or for a token the SDK can't price — those keep
5069
- * `onchain-proof`. The agent signs an EIP-3009 authorization with its OWN wallet
5138
+ * `exact` is **EVM (EIP-3009/Permit2) + Solana (SVM)** today (USDC/EURC); it's
5139
+ * silently ignored on a family without an `exact` rail, for native, or for a token the
5140
+ * SDK can't price — those keep `onchain-proof`. The agent signs the authorization (an
5141
+ * EIP-3009 message on EVM, a partial-signed transaction on Solana) with its OWN wallet
5070
5142
  * and the server / merchant-chosen facilitator broadcasts it (the buyer pays ~0
5071
5143
  * gas; PipRail hosts/settles nothing). The same `policy` + `onBeforePay` gate it
5072
5144
  * BEFORE signing. **Verify against your target facilitator before production.**
@@ -5251,7 +5323,7 @@ declare class PipRailClient {
5251
5323
  * before publishing, so retry with a brief backoff if a fresh listing is missing.
5252
5324
  * - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
5253
5325
  * `onchain-proof` rails by default, and standard `exact` rails too once you opt in
5254
- * with `schemes: ['onchain-proof', 'exact']` (EVM + EIP-3009 USDC/EURC).
5326
+ * with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
5255
5327
  */
5256
5328
  discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
5257
5329
  /**
@@ -5744,31 +5816,41 @@ interface AcceptOption {
5744
5816
  /**
5745
5817
  * Opt into ALSO advertising a standard x402 `exact` rail beside the default
5746
5818
  * `onchain-proof` rail, so ANY standard x402 client can pay this gate (dual-advertise).
5747
- * EVM ERC-20 only — **EIP-3009** (USDC, EURC) or, for tokens without it, **Permit2**
5748
- * (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical
5749
- * x402ExactPermit2Proxy). NOT native coins, NOT non-EVM chains. Omitting `exact` leaves
5750
- * the gate byte-identical to today (onchain-proof only).
5819
+ * Supported on **EVM ERC-20** — **EIP-3009** (USDC, EURC) or, for tokens without it, **Permit2**
5820
+ * (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical x402ExactPermit2Proxy) —
5821
+ * and on **Solana** (any SPL token; the buyer partial-signs a `TransferChecked` and your relayer
5822
+ * is the fee payer). NOT native coins, NOT families without a standard `exact` scheme. Omitting
5823
+ * `exact` leaves the gate byte-identical to today (onchain-proof only).
5751
5824
  *
5752
5825
  * Two settlement modes, both backendless (PipRail hosts nothing):
5753
- * - `settle: 'self'` — your own `relayer` key broadcasts the settle (EIP-3009's
5754
- * `transferWithAuthorization`, or the proxy's `settle` for Permit2). You pay gas to
5755
- * RECEIVE (the inverse of onchain-proof) and keep the relayer funded. The signature
5756
- * binds the recipient, so there's no redirect risk. The on-brand default for the rail.
5757
- * - `settle: { facilitator }` — delegate verify+settle to a third-party x402
5758
- * facilitator YOU choose (Coinbase CDP, x402.org, …). No relayer key needed; the
5759
- * facilitator pays gas. Also the only path onto Coinbase's Bazaar directory.
5826
+ * - `settle: 'self'` — your own `relayer` key broadcasts the settle (EVM EIP-3009's
5827
+ * `transferWithAuthorization` / the proxy's `settle` for Permit2; on Solana, co-signing the
5828
+ * buyer's transaction as the fee payer). You pay gas to RECEIVE (the inverse of onchain-proof)
5829
+ * and keep the relayer funded. The signature binds the recipient, so there's no redirect risk.
5830
+ * The on-brand backendless default for the rail.
5831
+ * - `settle: { facilitator }` delegate verify+settle to a third-party x402 facilitator YOU
5832
+ * choose. **The facilitator pays the gas, so neither the buyer nor the merchant pays any** —
5833
+ * fully gasless end to end. On **EVM** use Coinbase CDP, x402.org, PayAI, …; on **Solana** use a
5834
+ * facilitator that sponsors the fee payer (e.g. PayAI's `https://facilitator.payai.network`,
5835
+ * no API key) — the gate reads its fee-payer pubkey from `GET /supported` automatically. No
5836
+ * relayer key needed. (EVM facilitators are also the path onto Coinbase's Bazaar directory.)
5760
5837
  */
5761
5838
  interface ExactRailOption {
5762
5839
  settle: 'self' | {
5763
5840
  facilitator: string;
5764
5841
  authHeaders?: () => Promise<Record<string, string>>;
5842
+ /** Solana only — the facilitator's fee-payer pubkey, if you'd rather set it than have the
5843
+ * gate read it from the facilitator's `GET /supported`. Optional: omitted, the gate
5844
+ * discovers it automatically (e.g. PayAI). Ignored on EVM. */
5845
+ feePayer?: string;
5765
5846
  };
5766
- /** Required for `settle: 'self'` — the gas-paying relayer wallet: EVM `{ privateKey }`
5767
- * or a bring-your-own `{ walletClient }`. (Distinct from `payTo`, the receive address.) */
5847
+ /** Required for `settle: 'self'` — the gas-paying relayer wallet: EVM `{ privateKey }` /
5848
+ * `{ walletClient }`, or Solana `{ secretKey }` / `{ signer }`. (Distinct from `payTo`, the
5849
+ * receive address — on Solana they MUST be different keys, a scheme MUST-rule.) */
5768
5850
  relayer?: unknown;
5769
- /** Which exact-EVM transfer method to advertise. `'auto'` (default) uses EIP-3009 when the
5851
+ /** Which exact transfer method to advertise (EVM). `'auto'` (default) uses EIP-3009 when the
5770
5852
  * token supports it, else Permit2 — so a non-EIP-3009 token like Binance-Peg USDC on BNB
5771
- * "just works". Force `'eip3009'` or `'permit2'` to pin one. */
5853
+ * "just works". Force `'eip3009'` or `'permit2'` to pin one. Ignored on Solana (always SVM). */
5772
5854
  method?: 'eip3009' | 'permit2' | 'auto';
5773
5855
  }
5774
5856
  interface RequirePaymentOptions {
@@ -5840,8 +5922,8 @@ interface RequirePaymentOptions {
5840
5922
  */
5841
5923
  awaitOnPaid?: boolean;
5842
5924
  /**
5843
- * ALSO advertise a standard x402 `exact` rail (EIP-3009) so any standard x402
5844
- * client can pay this gate — opt-in, EVM/EIP-3009 only. See {@link ExactRailOption}.
5925
+ * ALSO advertise a standard x402 `exact` rail so any standard x402 client can pay this
5926
+ * gate — opt-in, EVM (EIP-3009/Permit2) + Solana (SVM). See {@link ExactRailOption}.
5845
5927
  * Omit to keep the gate exactly as today (`onchain-proof` only).
5846
5928
  */
5847
5929
  exact?: ExactRailOption;
@@ -5963,7 +6045,9 @@ declare function requirePayment(options: RequirePaymentOptions): ExpressLikeMidd
5963
6045
  * SELF-settling merchant must guard replay itself (the gate's used-proof set does).
5964
6046
  */
5965
6047
 
5966
- /** Standard x402 `exact` PaymentRequirements, built from the gate's TRUSTED rail. */
6048
+ /** Standard x402 `exact` PaymentRequirements, built from the gate's TRUSTED rail. `extra`
6049
+ * carries the scheme's chain-specific fields: EVM EIP-3009 → `{ name, version }` (the token's
6050
+ * EIP-712 domain), Solana SVM → `{ feePayer }` (the facilitator's fee-payer pubkey). */
5967
6051
  interface FacilitatorPaymentRequirements {
5968
6052
  scheme: 'exact';
5969
6053
  network: string;
@@ -5971,10 +6055,7 @@ interface FacilitatorPaymentRequirements {
5971
6055
  amount: string;
5972
6056
  payTo: string;
5973
6057
  maxTimeoutSeconds: number;
5974
- extra: {
5975
- name: string;
5976
- version: string;
5977
- };
6058
+ extra: Record<string, unknown>;
5978
6059
  }
5979
6060
  /** A merchant-chosen facilitator: its base URL + optional per-request auth headers. */
5980
6061
  interface FacilitatorConfig {