@piprail/sdk 1.20.1 → 1.21.1
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/CHANGELOG.md +71 -0
- package/dist/index.cjs +165 -65
- package/dist/index.d.cts +118 -37
- package/dist/index.d.ts +118 -37
- package/dist/index.js +156 -56
- package/dist/solana-IBVUZS54.js +724 -0
- package/dist/solana-WG7RGDSI.cjs +724 -0
- package/package.json +1 -1
- package/dist/solana-MPPE6K24.cjs +0 -364
- package/dist/solana-WDKWWF33.js +0 -364
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
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
|
|
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
|
-
/**
|
|
194
|
-
|
|
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
|
|
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
|
|
5068
|
-
*
|
|
5069
|
-
* `onchain-proof`. The agent signs
|
|
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
|
|
5326
|
+
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
|
|
5255
5327
|
*/
|
|
5256
5328
|
discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
|
|
5257
5329
|
/**
|
|
@@ -5473,7 +5545,7 @@ declare function formatSpendReport(summary: SpendSummary): string;
|
|
|
5473
5545
|
* literally, so a wrong name or order actively misleads. A test pins the load-
|
|
5474
5546
|
* bearing phrases.
|
|
5475
5547
|
*/
|
|
5476
|
-
declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend.\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
|
|
5548
|
+
declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to two rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM + Solana, and the on-chain method (EIP-3009 / Permit2 / SVM) is picked automatically.\nWhen the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest\nsettleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is\nidentical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);\nyou can't enable it yourself, but you can report when a 402 needs it (see UNSUPPORTED_SCHEME below).\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend. On a gasless\n exact rail `.ref` is the authorization NONCE, not a tx hash: re-present the SAME\n signed authorization, never sign a fresh one (that would risk a double-spend).\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n If it's a standard x402 server offering an exact rail, that's a config fix the operator makes\n once (enable the exact scheme); report it, don't retry the same call blindly.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
|
|
5477
5549
|
/** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
|
|
5478
5550
|
declare function agentGuide(): string;
|
|
5479
5551
|
|
|
@@ -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
|
|
5748
|
-
* (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical
|
|
5749
|
-
*
|
|
5750
|
-
* the
|
|
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
|
|
5755
|
-
* RECEIVE (the inverse of onchain-proof)
|
|
5756
|
-
* binds the recipient, so there's no redirect risk.
|
|
5757
|
-
*
|
|
5758
|
-
*
|
|
5759
|
-
* facilitator pays gas
|
|
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
|
|
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
|
|
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
|
|
5844
|
-
*
|
|
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
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
|
|
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
|
-
/**
|
|
194
|
-
|
|
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
|
|
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
|
|
5068
|
-
*
|
|
5069
|
-
* `onchain-proof`. The agent signs
|
|
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
|
|
5326
|
+
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
|
|
5255
5327
|
*/
|
|
5256
5328
|
discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
|
|
5257
5329
|
/**
|
|
@@ -5473,7 +5545,7 @@ declare function formatSpendReport(summary: SpendSummary): string;
|
|
|
5473
5545
|
* literally, so a wrong name or order actively misleads. A test pins the load-
|
|
5474
5546
|
* bearing phrases.
|
|
5475
5547
|
*/
|
|
5476
|
-
declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend.\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
|
|
5548
|
+
declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to two rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM + Solana, and the on-chain method (EIP-3009 / Permit2 / SVM) is picked automatically.\nWhen the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest\nsettleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is\nidentical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);\nyou can't enable it yourself, but you can report when a 402 needs it (see UNSUPPORTED_SCHEME below).\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend. On a gasless\n exact rail `.ref` is the authorization NONCE, not a tx hash: re-present the SAME\n signed authorization, never sign a fresh one (that would risk a double-spend).\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n If it's a standard x402 server offering an exact rail, that's a config fix the operator makes\n once (enable the exact scheme); report it, don't retry the same call blindly.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left, per\n(network, asset), plus your spend so far. Read-only; moves no funds. Use it in\nMode A to self-check before paying.\n\n## Two modes\n- Mode A (headless, default): you run FREE inside a pre-set budget + time\n envelope. The policy IS the consent \u2014 there is no per-payment prompt. Stay\n inside it; piprail_budget shows what's left.\n- Mode B (supervised): the host may ask a human to approve each payment. A\n decline/cancel/timeout comes back as declined:true (reasonCode:'APPROVAL') \u2014\n do NOT retry it as if it were a transient error.\n\n## Hard facts\n- Spend caps are PER (network, asset). There is no single cross-token dollar cap \u2014\n budgets aren't summed across tokens (no price oracle).\n- Spend totals and the time envelope live IN-MEMORY for THIS process; they reset on restart\n (a convenience, not a durable ledger).\n";
|
|
5477
5549
|
/** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
|
|
5478
5550
|
declare function agentGuide(): string;
|
|
5479
5551
|
|
|
@@ -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
|
|
5748
|
-
* (any ERC-20 — e.g. Binance-Peg USDC on BNB, settled via the canonical
|
|
5749
|
-
*
|
|
5750
|
-
* the
|
|
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
|
|
5755
|
-
* RECEIVE (the inverse of onchain-proof)
|
|
5756
|
-
* binds the recipient, so there's no redirect risk.
|
|
5757
|
-
*
|
|
5758
|
-
*
|
|
5759
|
-
* facilitator pays gas
|
|
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
|
|
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
|
|
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
|
|
5844
|
-
*
|
|
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 {
|