@piprail/sdk 2.9.0 → 2.11.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
@@ -1,5 +1,5 @@
1
- import { C as Caip2, X as X402AcceptEntry, r as X402AnyAccept, t as X402ExactAcceptEntry, c as ExactPaymentPayloadAny, q as VerifyResult, p as SpendSummary, s as X402Challenge, v as X402Receipt, S as SettleOutcome, o as SpendStore, m as SpendLedger, n as SpendRecord, a as AssetId, A as AddressId, V as VerifyErrorCode, P as PaidReceipt } from './ledger-BtzrfO-3.cjs';
2
- export { E as ExactAuthorizationWire, b as ExactPaymentPayload, H as HEADER_REQUIRED, d as HEADER_RESPONSE, e as HEADER_RESPONSE_V1, f as HEADER_SIGNATURE, g as HEADER_SIGNATURE_V1, h as ParsedExactPayment, i as Permit2Authorization, j as Permit2PaymentPayload, k as SpendAssetTotal, l as SpendDenomTotal, u as X402PaymentSignature, w as X402ResourceObject, x as buildChallengeHeader, y as buildExactSignatureHeader, z as buildReceiptHeader, B as buildSignatureHeader, D as memorySpendStore, F as parseChallenge, G as parseExactPaymentHeader, I as parseReceipt, J as parseSettleResponse, K as parseSignatureHeader, L as pickAccept } from './ledger-BtzrfO-3.cjs';
1
+ import { C as Caip2, X as X402AcceptEntry, x as X402AnyAccept, z as X402ExactAcceptEntry, d as ExactPaymentPayloadAny, p as SignedReceipt, w as VerifyResult, G as X402UptoAcceptEntry, n as Permit2UptoPaymentPayload, v as SpendSummary, y as X402Challenge, D as X402Receipt, S as SettleOutcome, u as SpendStore, s as SpendLedger, t as SpendRecord, o as PipRailReceipt, V as VerifyErrorCode, a as AssetId, A as AddressId, P as PaidReceipt } from './ledger-OQos-tmj.cjs';
2
+ export { E as EXT_OFFER_RECEIPT, b as ExactAuthorizationWire, c as ExactPaymentPayload, H as HEADER_REQUIRED, e as HEADER_RESPONSE, f as HEADER_RESPONSE_V1, g as HEADER_SIGNATURE, h as HEADER_SIGNATURE_V1, i as ParsedExactPayment, j as ParsedUptoPayment, k as Permit2Authorization, l as Permit2PaymentPayload, m as Permit2UptoAuthorization, q as SpendAssetTotal, r as SpendDenomTotal, B as X402PaymentSignature, F as X402ResourceObject, I as buildChallengeHeader, J as buildExactSignatureHeader, K as buildReceiptExtension, L as buildReceiptHeader, M as buildSignatureHeader, N as buildUptoSignatureHeader, O as decodeBase64Json, Q as memorySpendStore, R as parseChallenge, T as parseExactObject, U as parseExactPaymentHeader, W as parseReceipt, Y as parseReceiptExtension, Z as parseSettleResponse, _ as parseSignatureHeader, $ as parseSignatureObject, a0 as parseUptoObject, a1 as parseUptoPaymentHeader, a2 as pickAccept } from './ledger-OQos-tmj.cjs';
3
3
  import * as viem_zksync from 'viem/zksync';
4
4
  import * as abitype from 'abitype';
5
5
  import * as viem_chains from 'viem/chains';
@@ -3863,6 +3863,32 @@ interface DiscoverySigner {
3863
3863
  /** Sign an arbitrary UTF-8 message (EVM: eip191) — for proofs/SIWX only. */
3864
3864
  signMessage(message: string): Promise<string>;
3865
3865
  }
3866
+ /**
3867
+ * The official x402 `offer-receipt` §5.2 signed-field set a merchant attests over in
3868
+ * Tier-2 — the SMALLER official payload (NOT PipRail's full {@link X402Receipt}),
3869
+ * consumed by the optional EVM-only {@link ResolvedNetwork.signReceipt}. The gate
3870
+ * maps PipRail's settlement data into it. `payTo` rides ALONGSIDE the signed fields
3871
+ * purely so a verifier knows the expected signer (`recover === payTo`); it is NOT
3872
+ * part of the EIP-712 message.
3873
+ */
3874
+ interface ReceiptInput {
3875
+ /** The merchant `payTo` wallet — the signer a verifier checks `recover ===` against. NOT signed. */
3876
+ payTo: string;
3877
+ /** CAIP-2 network the settlement happened on (signed `network`). */
3878
+ network: string;
3879
+ /** The paid resource URL (signed `resourceUrl`). */
3880
+ resourceUrl: string;
3881
+ /** The payer identifier — the on-chain sender (signed `payer`). */
3882
+ payer: string;
3883
+ /** Unix SECONDS the receipt was issued (signed `issuedAt`). */
3884
+ issuedAt: number;
3885
+ /**
3886
+ * The settlement tx hash, or the empty string `''` when suppressed
3887
+ * (`includeTxHash:false`). §5.3: the signed EIP-712 message MUST carry `''`,
3888
+ * NEVER an omitted key — a verifier treats `''` as absence. Default `''`.
3889
+ */
3890
+ transaction?: string;
3891
+ }
3866
3892
  /**
3867
3893
  * How a family advertises a standard `exact` rail for one asset — returned by
3868
3894
  * {@link ResolvedNetwork.resolveExactRail} and consumed by the gate to build the
@@ -3880,6 +3906,21 @@ interface ExactRailInfo {
3880
3906
  * Algorand/Aptos/NEAR). */
3881
3907
  extra?: Record<string, unknown>;
3882
3908
  }
3909
+ /**
3910
+ * How a family advertises a standard `upto` (metered) rail for one asset — the metered
3911
+ * sibling of {@link ExactRailInfo}, returned by {@link ResolvedNetwork.resolveUptoRail}
3912
+ * and consumed by the gate to build the `X402UptoAcceptEntry`. The `method` is always the
3913
+ * PipRail-internal `'permit2-upto'` (upto is EVM-Permit2 only); `extra` is merged VERBATIM
3914
+ * into the accept's `extra`, carrying `{ facilitatorAddress, name?, version? }` — the
3915
+ * relayer address the buyer signs into `witness.facilitator` plus the token's EIP-712
3916
+ * domain bits. Keeping the chain-specific shape behind this descriptor is what lets
3917
+ * `server.ts` stay chain-agnostic — it never names a family, it just merges `extra`.
3918
+ */
3919
+ interface UptoRailInfo {
3920
+ method: 'permit2-upto';
3921
+ /** Family-specific `extra` keys merged into the upto accept: `{ facilitatorAddress, name?, version? }`. */
3922
+ extra?: Record<string, unknown>;
3923
+ }
3883
3924
  /**
3884
3925
  * A driver bound to one concrete network — what the gate and client hold. Each
3885
3926
  * method's error behaviour is fixed by the SDK error standard (see ERRORS.md §5):
@@ -3996,6 +4037,20 @@ interface ResolvedNetwork {
3996
4037
  * REQUIRED methods. Returns `null` if the bound wallet can't sign.
3997
4038
  */
3998
4039
  discoverySigner?(wallet: WalletHandle): DiscoverySigner | null;
4040
+ /**
4041
+ * OPTIONAL (EVM-only today) — Tier-2 service-delivery attestation. Sign the
4042
+ * official x402 `offer-receipt` EIP-712 `RECEIPT_TYPES` (the SMALLER official
4043
+ * §5.2 payload) with the bound wallet — typically the merchant's existing `payTo`
4044
+ * key — so a buyer can prove the resource was SERVED, the one thing the chain
4045
+ * can't attest. A verifier ({@link PipRailClient.verifyAttestation}) re-recovers
4046
+ * and checks `recover === payTo`. The signed domain is hardcoded `chainId:1` for
4047
+ * EVERY network (uniform signing), so this is chain-independent and EVM-only by
4048
+ * the optional `?` gate — non-EVM families omit it (no all-families mirror),
4049
+ * exactly like {@link discoverySigner}/{@link payExact}. The gate calls it after
4050
+ * settle when `receipts.attest` is set + the rail is EVM; the result rides in
4051
+ * `extensions['offer-receipt'].info.attestation`. NEVER part of the payment path.
4052
+ */
4053
+ signReceipt?(wallet: WalletHandle, input: ReceiptInput): Promise<SignedReceipt>;
3999
4054
  /** Verify `ref` satisfies `accept`, RPC-only, in-process. */
4000
4055
  verify(ref: string, accept: X402AcceptEntry): Promise<VerifyResult>;
4001
4056
  /**
@@ -4066,6 +4121,54 @@ interface ResolvedNetwork {
4066
4121
  payload: ExactPaymentPayloadAny;
4067
4122
  accept: X402ExactAcceptEntry;
4068
4123
  }): Promise<VerifyResult>;
4124
+ /**
4125
+ * OPTIONAL (EVM-Permit2 ONLY) — advertise a standard `upto` (metered) rail for `asset`,
4126
+ * or `null` when this asset/chain can't carry one (a native coin, a non-Permit2-proxy
4127
+ * chain, a non-Permit2 token). The gate's rail-advertisement SPI for the metered rail —
4128
+ * the parallel of {@link resolveExactRail}. The `relayer` becomes the bound
4129
+ * `witness.facilitator` (upto is self-settle only in v1, no facilitator mode), so the
4130
+ * returned `extra.facilitatorAddress` is the relayer's own address. The optional `?` IS
4131
+ * the EVM-only gate — every non-EVM family omits it, so the gate never offers upto there.
4132
+ * RPC-read (EVM reads the token's EIP-712 domain); never throws for a transient read.
4133
+ */
4134
+ resolveUptoRail?(input: {
4135
+ asset: string;
4136
+ relayer: WalletHandle;
4137
+ }): Promise<UptoRailInfo | null>;
4138
+ /**
4139
+ * OPTIONAL (EVM-Permit2 ONLY) — BUYER side: sign a Permit2 `PermitWitnessTransferFrom`
4140
+ * authorization for the MAX (`accept.amount`), binding `witness.facilitator =
4141
+ * accept.extra.facilitatorAddress` as the MIDDLE witness field. Re-derives the proxy +
4142
+ * witness types internally; never trusts a server-supplied domain. The metered counterpart
4143
+ * to {@link payExact}. The client frames the returned `payload` + `accepted` echo into the
4144
+ * `PAYMENT-SIGNATURE` header; the merchant self-settles the actual. Returns the signed
4145
+ * payload, the chosen-rail echo, the payer address, and the Permit2 nonce. THROWS a typed
4146
+ * `PipRailError` when the signer is a contract / EIP-1271 / EIP-7702 account.
4147
+ */
4148
+ payUpto?(wallet: WalletHandle, accept: X402UptoAcceptEntry): Promise<{
4149
+ payload: Permit2UptoPaymentPayload;
4150
+ accepted: X402UptoAcceptEntry;
4151
+ payerFrom: string;
4152
+ nonce: string;
4153
+ }>;
4154
+ /**
4155
+ * OPTIONAL (EVM-Permit2 ONLY) — SELLER side: verify a standard x402 `upto` payment
4156
+ * locally, then SELF-SETTLE the ACTUAL (`settleAmount`, ≤ the signed max) through the upto
4157
+ * proxy from the merchant's `relayer`. The metered counterpart to {@link settleExactSelf}.
4158
+ * Re-verifies the signature against `permitted.amount` (the signed MAX, NEVER the metered
4159
+ * actual — verifying against the actual would reject every partial settle); guards
4160
+ * `witness.facilitator === relayer.address`; clamps/rejects `settleAmount > max` with
4161
+ * `upto_settle_exceeds_max`; SKIPS the on-chain tx when `settleAmount === 0n` (a synthetic
4162
+ * zero-charge receipt with `transaction: ""`). RETURNS a `VerifyResult` for a client-fixable
4163
+ * fault; THROWS {@link SettlementError} on a broadcast failure of a valid auth. Re-derives
4164
+ * every checked field from the trusted `accept`, never the client echo.
4165
+ */
4166
+ settleUptoSelf?(input: {
4167
+ relayer: WalletHandle;
4168
+ payload: Permit2UptoPaymentPayload;
4169
+ accept: X402UptoAcceptEntry;
4170
+ settleAmount: bigint;
4171
+ }): Promise<VerifyResult>;
4069
4172
  }
4070
4173
  interface ResolveOptions {
4071
4174
  /** The developer-supplied `chain` selector. */
@@ -4705,7 +4808,11 @@ interface PaymentPolicy {
4705
4808
  /** Lifetime ceiling for this client, PER DISTINCT ASSET (network+asset).
4706
4809
  * Summing across different tokens is unit-meaningless without a price
4707
4810
  * oracle (which the SDK deliberately doesn't add), so each token gets its
4708
- * own running cap. Pair with `tokens: ['USDC']` for a single-currency budget. */
4811
+ * own running cap. Pair with `tokens: ['USDC']` for a single-currency budget.
4812
+ * NOTE — the metered `upto` rail debits this (and `maxTotalPerDenom`/`windowTotal`)
4813
+ * by the authorized **MAX**, not the merchant's claimed settled actual, so an
4814
+ * under-reporting merchant can never loosen the leash; the settled actual is
4815
+ * surfaced on each spend record's `settledBase` for reconciliation. */
4709
4816
  maxTotal?: string;
4710
4817
  /** Allowlist of chains the agent may pay on. A 402 on any other chain is
4711
4818
  * declined. Strings match the configured selector; objects match by id. */
@@ -4874,8 +4981,9 @@ interface PolicyContext {
4874
4981
  declare function evaluatePolicy(intent: PaymentIntent, policy: PaymentPolicy | undefined, spentForAssetBase: bigint, ctx?: PolicyContext): PolicyDecision;
4875
4982
 
4876
4983
  /** The payment schemes a client can settle: PipRail's native `onchain-proof` (the
4877
- * default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM + Algorand, opt-in). */
4878
- type PaymentScheme = 'onchain-proof' | 'exact';
4984
+ * default), the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM + Algorand,
4985
+ * opt-in), and the standard x402 `upto` (metered) rail (EVM-Permit2, opt-in). */
4986
+ type PaymentScheme = 'onchain-proof' | 'exact' | 'upto';
4879
4987
 
4880
4988
  /** Observability events. `ref` is the proof — a chain-specific id (EVM tx hash, Solana signature, TON locator, Stellar tx hash). */
4881
4989
  type PipRailEvent = {
@@ -5421,6 +5529,39 @@ interface PayingClient {
5421
5529
  * without hitting a decline). `undefined` when no policy is set. */
5422
5530
  policy(): PaymentPolicy | undefined;
5423
5531
  }
5532
+ /**
5533
+ * The verdict from {@link PipRailClient.verifyReceipt} — a {@link PipRailReceipt}
5534
+ * re-verified against the chain, never trusting the receipt's claims. `ok` is the
5535
+ * chain's confirmation that the settlement is real (≥`amount` of `asset` moved to
5536
+ * `payTo`); `onChain` is RE-DERIVED from the tx (`payer` genuinely so; `amount` is a
5537
+ * VERIFIED LOWER BOUND — drivers threshold-check `paid >= required` then echo the
5538
+ * accept amount); `matchesClaims` is whether the re-derived `payer` equals the
5539
+ * receipt's claimed `payer` (a forged payer → `false` even when `ok` is `true`).
5540
+ *
5541
+ * Re-verification is **durable** for digest-bound (Template-B) families (EVM, Solana,
5542
+ * Tron, Sui, Aptos, native coins — the driver reads the tx by hash/digest) and
5543
+ * **recency-bounded / best-effort** for the account-watch families (Stellar, XRPL,
5544
+ * Algorand, TON), whose drivers scan only recent merchant-account history — an old
5545
+ * receipt there can return `transfer_not_found` even though it once settled.
5546
+ */
5547
+ interface ReceiptVerification {
5548
+ /** The chain confirms the settlement (≥`amount` moved to `payTo`). */
5549
+ ok: boolean;
5550
+ /** Fields RE-DERIVED from the on-chain tx. `payer` is genuinely re-derived; `amount`
5551
+ * is a verified LOWER BOUND (the chain confirms at least this much moved). */
5552
+ onChain: {
5553
+ payTo: string;
5554
+ asset: string;
5555
+ amount: string;
5556
+ payer: string;
5557
+ };
5558
+ /** Does the re-derived on-chain `payer` match the receipt's claimed `payer`? */
5559
+ matchesClaims: boolean;
5560
+ /** Informational age of the receipt (seconds since `verifiedAt`); NOT a validity gate. */
5561
+ ageSeconds: number;
5562
+ /** The closed verification code when `ok` is false (reuses the driver vocabulary). */
5563
+ error?: VerifyErrorCode;
5564
+ }
5424
5565
  declare class PipRailClient {
5425
5566
  private readonly opts;
5426
5567
  private readonly maxRetries;
@@ -5428,6 +5569,7 @@ declare class PipRailClient {
5428
5569
  private readonly onEvent;
5429
5570
  private readonly ledger;
5430
5571
  private bound?;
5572
+ private lastReceiptValue;
5431
5573
  constructor(opts: PipRailClientOptions);
5432
5574
  /**
5433
5575
  * Fail LOUDLY at construction on a malformed amount cap — a security boundary
@@ -5458,6 +5600,55 @@ declare class PipRailClient {
5458
5600
  /** Emit an observability event, never letting a throwing handler break the
5459
5601
  * payment flow (mirrors the server gate's `onPaid` isolation). */
5460
5602
  private safeEmit;
5603
+ /**
5604
+ * Capture the verifiable receipt from a settled response (pure — no chain read), stamping
5605
+ * the resource URL this client actually fetched (authoritative over the gate's default ''). A
5606
+ * settled fetch with no receipt extension sets it to `null` so {@link lastReceipt} reflects the
5607
+ * latest fetch. Never throws — a malformed header just yields `null`.
5608
+ */
5609
+ private captureReceipt;
5610
+ /**
5611
+ * The verifiable {@link PipRailReceipt} from the most recent settled `fetch` — the
5612
+ * self-contained record the buyer KEEPS and anyone re-verifies against the chain
5613
+ * (see {@link PipRailClient.verifyReceipt}). `null` when the last settled fetch carried
5614
+ * no receipt (the gate's `receipts` option was off) or no payment has settled yet. Pure.
5615
+ */
5616
+ lastReceipt(): PipRailReceipt | null;
5617
+ /**
5618
+ * Re-verify ANY {@link PipRailReceipt} against the chain — the anyone-can-run primitive.
5619
+ * Re-reads `receipt.transaction` via the receipt's own network driver and re-derives
5620
+ * `payTo`/`asset`/`payer` from the tx, **never trusting the receipt's claims**: a forged
5621
+ * `payTo`/`asset`/over-stated `amount` makes the driver's `verify()` fail (`ok:false`); a
5622
+ * forged `payer` surfaces as `matchesClaims:false`. Static + WALLET-FREE — a third party
5623
+ * verifies with only a chain + RPC, no PipRail account. **Never throws** (an RPC error or a
5624
+ * malformed receipt → `{ ok:false, error }`). Viem-free here — the chain read happens inside
5625
+ * the lazily-mounted family driver (the protocol layer pulls no chain libs). Durable for
5626
+ * digest-bound families; recency-bounded for the account-watch families (see
5627
+ * {@link ReceiptVerification}).
5628
+ */
5629
+ static verifyReceipt(receipt: PipRailReceipt, opts?: {
5630
+ rpcUrl?: string;
5631
+ }): Promise<ReceiptVerification>;
5632
+ /**
5633
+ * Verify the OPTIONAL Tier-2 service-delivery attestation on a {@link PipRailReceipt}
5634
+ * — the merchant's signed proof that the resource was actually SERVED (the one thing
5635
+ * the chain can't attest). For an EVM EIP-712 attestation this re-recovers the signer
5636
+ * from the signature over the official `offer-receipt` typed data and checks
5637
+ * `recover === receipt.payTo` (spec §4.5.1 / §5.5) — the classic EIP-712 footgun made
5638
+ * safe (`recoverTypedDataAddress` returns a WRONG address rather than throwing on a bad
5639
+ * signature, so the equality check is the real verification). A tampered signature →
5640
+ * `{ ok:false }`, never a throw.
5641
+ *
5642
+ * Static + wallet-free. **Never throws** (a malformed/absent attestation, an unsupported
5643
+ * format, or a recovery fault → `{ ok:false, reason }`). Viem-free HERE — the recover runs
5644
+ * inside the lazily-imported EVM receipt driver (a lazy chunk), so the protocol layer pulls
5645
+ * no chain libs. The JWS format defers to R3 (`{ ok:false, reason:'jws-not-loaded' }`).
5646
+ */
5647
+ static verifyAttestation(receipt: PipRailReceipt): Promise<{
5648
+ ok: boolean;
5649
+ signer?: string;
5650
+ reason?: string;
5651
+ }>;
5461
5652
  /** Auto-mount the chain's driver, resolve the network, and bind the wallet — once. */
5462
5653
  private ensure;
5463
5654
  /** Resolve the effective scheme set: a per-call override, else the constructor's
@@ -5698,7 +5889,17 @@ declare class PipRailClient {
5698
5889
  * denomination it counts toward in the grand total). Then fire the `onSpend` callback
5699
5890
  * with the record + the post-payment budget, and emit any `warnAtFraction` thresholds
5700
5891
  * this payment just crossed. All observability is isolated — a throwing hook never
5701
- * affects the (already-settled) payment. */
5892
+ * affects the (already-settled) payment.
5893
+ *
5894
+ * `settledAmountBase` is the SINGLE upto ledger-reconciliation seam: the quote (and thus
5895
+ * the policy/budget) gates on the MAX, and for the metered `upto` rail the budgeted amount
5896
+ * RECORDED is ALSO the authorized MAX — the only buyer-provable bound. The merchant's
5897
+ * claimed actual is UNTRUSTED (a malicious merchant can settle the MAX on-chain yet report
5898
+ * a tiny `SettleOutcome.amount`); recording it would let an under-report silently loosen a
5899
+ * cumulative cap (`maxTotal`/`maxTotalPerDenom`/`windowTotal`) past the buyer's real on-chain
5900
+ * spend (POL-1). So the cap-bearing `amountBase` is the MAX; the clamped actual is surfaced
5901
+ * separately on `settledBase`/`settledFormatted` for transparency (it equals the receipt's
5902
+ * amount). When absent (onchain-proof/exact) this is byte-identical to before. */
5702
5903
  private recordSpend;
5703
5904
  /**
5704
5905
  * Emit a `budget-threshold` event for each cap whose used-fraction just reached
@@ -5728,6 +5929,16 @@ declare class PipRailClient {
5728
5929
  * • the spend is recorded EXACTLY ONCE, on an affirmative settlement only.
5729
5930
  */
5730
5931
  private payExactRail;
5932
+ /**
5933
+ * The standard `upto` (metered) buyer path — a near-clone of {@link payExactRail} with TWO
5934
+ * deltas: (1) it signs a Permit2-upto authorization for the MAX via `payUpto` + frames it
5935
+ * with `buildUptoSignatureHeader`; (2) it records the ACTUAL settled amount (read off the
5936
+ * SettleResponse's required `amount` field, via `recordSpend(quote, ref, settle.amount)`) in
5937
+ * the ledger — the budget gated on the MAX, the ledger records the ACTUAL. A server that omits
5938
+ * `settle.amount` FAILS SAFE to the MAX (over-counts, never under-counts). The buyer SIGNS, the
5939
+ * merchant self-settles — the buyer never broadcasts.
5940
+ */
5941
+ private payUptoRail;
5731
5942
  }
5732
5943
  /**
5733
5944
  * Plan a payment ACROSS several single-chain clients — the cross-chain brain.
@@ -5988,7 +6199,7 @@ interface AgentTool {
5988
6199
  invoke: (args: Record<string, unknown>) => Promise<unknown>;
5989
6200
  }
5990
6201
  /**
5991
- * Seven tools wrapping a configured {@link PipRailClient}:
6202
+ * Eight tools wrapping a configured {@link PipRailClient}:
5992
6203
  * - `piprail_discover(query?)` — FIND payable resources on the open x402
5993
6204
  * indexes, WITHOUT paying (the phone book — solves "what can I buy?").
5994
6205
  * - `piprail_quote_payment(url)` — price a gated URL WITHOUT paying.
@@ -5999,8 +6210,10 @@ interface AgentTool {
5999
6210
  * other agents can find it (402 Index, no signature).
6000
6211
  * - `piprail_budget()` — read the remaining spend budget + time leash (Mode A self-check).
6001
6212
  * - `piprail_guide()` — read the agent contract (how to quote/plan/pay + read a refusal).
6213
+ * - `piprail_verify_receipt(receipt, rpcUrl?)` — re-verify a verifiable receipt against the
6214
+ * chain WITHOUT a wallet (anyone-verifiable; never throws — returns a structured verdict).
6002
6215
  *
6003
- * The first five are byte-identical in name + order to before; the two read-only
6216
+ * The first five are byte-identical in name + order to before; the three read-only
6004
6217
  * tools are appended LAST. EVERY failure the pay tool sees comes back as a
6005
6218
  * STRUCTURED object (`{ ok:false, code, reason, explain, ref?, reasonCode?,
6006
6219
  * declined? }`) — never a thrown error — so the model reasons about it (and never
@@ -6053,7 +6266,7 @@ declare function describeChallenge(challenge: X402Challenge): string;
6053
6266
  * literally, so a wrong name or order actively misleads. A test pins the load-
6054
6267
  * bearing phrases.
6055
6268
  */
6056
- declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## Landing cold \u2014 read the self-description\nEvery PipRail 402 self-describes. Read challenge.extensions.piprail for { name, what, pay[]\n(each rail's how-to-pay), sdk.install, mcp, docs } \u2014 never guess what an endpoint is. If your\ntooling can't pay a rail (e.g. a stock x402 client can't pay the onchain-proof scheme), the\nblock says how: install @piprail/sdk (npm i @piprail/sdk) or run the MCP (npx -y @piprail/mcp)\nand pay with the tools below.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to two rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand\n fee-pooled group) is picked automatically.\nWhen the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest\nsettleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is\nidentical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);\nyou can't enable it yourself, but you can report when a 402 needs it (see UNSUPPORTED_SCHEME below).\n\n## Reading a refusal \u2014 never crash, never double-spend\nA failed pay returns a STRUCTURED object, never a thrown error you must catch:\n { ok:false, code, reason, explain, ref?, reasonCode?, declined? }\nBranch on `code` (always reliable). Key cases:\n- declined:true with reasonCode:'SESSION_EXPIRED' \u2014 your time budget is over. This\n is TERMINAL: STOP. Do not retry ANY payment this process; it cannot be undone\n without a restart / a longer TTL.\n- declined:true with reasonCode:'APPROVAL' \u2014 a human (or hook) declined this\n payment. Terminal for this pay: do NOT auto-retry \u2014 they said no, or no one\n answered.\n- declined:true with reasonCode:'OUTSIDE_WINDOW' \u2014 your rolling rate-limit is\n exhausted. Wait for it to free, then retry; do not raise the amount.\n- declined:true with reasonCode:'POLICY' or 'BUDGET' \u2014 a spend cap or allowlist\n refused it. Don't retry the same payment; pick a cheaper/allowed one.\n- code:'INSUFFICIENT_FUNDS' \u2014 top up the wallet (token and/or native gas), retry.\n- code:'PAYMENT_TIMEOUT' / 'MAX_RETRIES_EXCEEDED' / 'CONFIRMATION_TIMEOUT' \u2014 the\n payment may ALREADY be on-chain. Recover using the proof on `.ref` (re-verify\n or re-submit it); never re-pay \u2014 a fresh payment would double-spend. On a gasless\n exact rail `.ref` is the authorization NONCE, not a tx hash: re-present the SAME\n signed authorization, never sign a fresh one (that would risk a double-spend).\n- code:'NO_COMPATIBLE_ACCEPT' / 'UNSUPPORTED_SCHEME' \u2014 the 402 isn't payable on\n your chain/scheme; `explain` says whether it's the wrong chain or a scheme to enable.\n If it's a standard x402 server offering an exact rail, that's a config fix the operator makes\n once (enable the exact scheme); report it, don't retry the same call blindly.\n\n## Knowing your leash \u2014 call piprail_budget\npiprail_budget tells you how much budget and time you have left: per (network,\nasset) remaining, the cross-token GRAND TOTAL per denomination (e.g. how much\nUSD you can still spend across every stablecoin and chain), the payment-count\nleash, the session time envelope, your spend so far, and the configured policy\nread back. Read-only; moves no funds. Use it in Mode 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- Per-payment + per-(network, asset) caps always apply. A cross-token GRAND TOTAL per\n denomination (maxTotalPerDenom, e.g. \"$20 across every USD stablecoin + chain\") is\n OPTIONAL \u2014 it sums tokens declared as one unit, each 1:1; it is NOT a price oracle and\n never prices a volatile native coin. Payment-COUNT caps (maxPayments / per-window) also\n span every chain + token.\n- The time envelope lives IN-MEMORY for THIS process (resets on restart). The money + count\n totals also reset on restart UNLESS a durable spend store is configured \u2014 then they resume.\n- A refusal arrives as declined:true with a reasonCode; 'BUDGET' covers the lifetime, denom,\n and count caps; 'OUTSIDE_WINDOW' covers both the rolling money and rolling count windows.\n";
6269
+ declare const PIPRAIL_AGENT_GUIDE = "# Paying with PipRail \u2014 the agent contract\n\nYou can pay for x402 \"402 Payment Required\" resources autonomously. Money moves\nstraight from your wallet to the server; PipRail custodies nothing. Follow this.\n\n## Landing cold \u2014 read the self-description\nEvery PipRail 402 self-describes. Read challenge.extensions.piprail for { name, what, pay[]\n(each rail's how-to-pay), sdk.install, mcp, docs } \u2014 never guess what an endpoint is. If your\ntooling can't pay a rail (e.g. a stock x402 client can't pay the onchain-proof scheme), the\nblock says how: install @piprail/sdk (npm i @piprail/sdk) or run the MCP (npx -y @piprail/mcp)\nand pay with the tools below.\n\n## The loop: quote \u2192 plan \u2192 pay\n1. piprail_quote_payment(url) \u2014 PRICE it. Returns the amount, token, chain, and\n whether it is within your spend policy. No funds move. Use it to decide if a\n resource is worth buying.\n2. piprail_plan_payment(url) \u2014 can I afford it NOW? Reads your balance, native gas,\n and recipient-readiness across every rail, and returns { payable, best,\n fundingHint, session? }. If payable is false, do NOT attempt the payment \u2014\n fundingHint says exactly what to fix.\n3. piprail_pay_request(url, method?, body?) \u2014 PAY (only if the plan was payable)\n and return the result.\nAlways plan before you pay so you never commit to a payment you cannot finish.\n\n## Gasless \u2014 the exact rail (zero gas for you)\nA 402 may offer up to three rails; you don't choose per payment \u2014 the client does, automatically:\n- onchain-proof (PipRail's default): you broadcast the payment yourself and pay the network gas\n (the native coin \u2014 ETH/SOL/\u2026). Works on every chain.\n- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose\n (e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It\n works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand\n fee-pooled group) is picked automatically.\n- upto (the metered/variable x402 rail, opt-in, EVM): the amount you see is a MAXIMUM \u2014 you sign\n a ceiling, the server meters real usage and settles the ACTUAL (<= the max). BUDGET AGAINST THE MAX:\n the plan/policy treat the ceiling as the spend (a server may charge up to it), so a payable plan\n means the MAX fits your budget; the settled actual is recorded for reconciliation.\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/upto schemes are OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact,upto);\nyou can't enable them yourself, but you can report when a 402 needs one (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 (network,\nasset) remaining, the cross-token GRAND TOTAL per denomination (e.g. how much\nUSD you can still spend across every stablecoin and chain), the payment-count\nleash, the session time envelope, your spend so far, and the configured policy\nread back. Read-only; moves no funds. Use it in Mode 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- Per-payment + per-(network, asset) caps always apply. A cross-token GRAND TOTAL per\n denomination (maxTotalPerDenom, e.g. \"$20 across every USD stablecoin + chain\") is\n OPTIONAL \u2014 it sums tokens declared as one unit, each 1:1; it is NOT a price oracle and\n never prices a volatile native coin. Payment-COUNT caps (maxPayments / per-window) also\n span every chain + token.\n- The time envelope lives IN-MEMORY for THIS process (resets on restart). The money + count\n totals also reset on restart UNLESS a durable spend store is configured \u2014 then they resume.\n- A refusal arrives as declined:true with a reasonCode; 'BUDGET' covers the lifetime, denom,\n and count caps; 'OUTSIDE_WINDOW' covers both the rolling money and rolling count windows.\n";
6057
6270
  /** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
6058
6271
  declare function agentGuide(): string;
6059
6272
 
@@ -6134,7 +6347,7 @@ declare const BRAND: {
6134
6347
  * human-readable view of an `accepts[]` entry (no nonce; this is long-lived metadata).
6135
6348
  */
6136
6349
  interface SelfDescribeRail {
6137
- scheme: 'onchain-proof' | 'exact';
6350
+ scheme: 'onchain-proof' | 'exact' | 'upto';
6138
6351
  network: string;
6139
6352
  asset: string;
6140
6353
  payTo: string;
@@ -6201,6 +6414,10 @@ interface SelfDescription {
6201
6414
  openapi: string;
6202
6415
  wellKnown: string;
6203
6416
  };
6417
+ /** Present (and `true`) ONLY when this gate issues verifiable receipts (`receipts` on) —
6418
+ * so a crawler/agent reading the 402 knows the 200 will carry a self-verifiable
6419
+ * `extensions['offer-receipt']` receipt. Absent by default (byte-identical). */
6420
+ verifiableReceipts?: true;
6204
6421
  /** A one-line human summary (the gate sets it from `describeChallenge`). */
6205
6422
  instruction?: string;
6206
6423
  }
@@ -6217,6 +6434,9 @@ declare function buildSelfDescription(input: {
6217
6434
  * byte-identical). Built from the gate's `description`/`mimeType`/`discovery` descriptor
6218
6435
  * via {@link buildEndpointInfo}. */
6219
6436
  endpoint?: SelfDescribeEndpoint;
6437
+ /** True when the gate's `receipts` option is on — stamps the additive `verifiableReceipts`
6438
+ * flag so a reader knows the 200 will carry a self-verifiable receipt. */
6439
+ verifiableReceipts?: boolean;
6220
6440
  }): SelfDescription;
6221
6441
  /**
6222
6442
  * Assemble a {@link SelfDescribeEndpoint} from the pieces a gate knows — its
@@ -6269,8 +6489,9 @@ declare function buildEndpointInfo(input: {
6269
6489
  * consumed by every emitter below.
6270
6490
  */
6271
6491
  interface PaymentRail {
6272
- /** `onchain-proof` (PipRail's default) or the standard `exact` rail (dual-advertise). */
6273
- scheme: 'onchain-proof' | 'exact';
6492
+ /** `onchain-proof` (PipRail's default), the standard `exact` rail, or the standard `upto`
6493
+ * (metered) rail (dual-advertise). */
6494
+ scheme: 'onchain-proof' | 'exact' | 'upto';
6274
6495
  network: Caip2;
6275
6496
  asset: AssetId;
6276
6497
  payTo: AddressId;
@@ -6281,6 +6502,11 @@ interface PaymentRail {
6281
6502
  decimals: number;
6282
6503
  symbol?: string;
6283
6504
  maxTimeoutSeconds: number;
6505
+ /** Rail-IDENTITY extra a discoverer needs to reconstruct/route the rail, mirrored from the
6506
+ * live 402's `accept.extra` — the `upto` rail's MANDATORY `facilitatorAddress`, the `exact`
6507
+ * rail's EIP-712 domain (`name`/`version`), and the `assetTransferMethod`. Omitted for the
6508
+ * `onchain-proof` rail (it needs none). The base pricing fields stay top-level on the rail. */
6509
+ extra?: Record<string, unknown>;
6284
6510
  }
6285
6511
  /** One discoverable resource: its URL, how to call it, and how to pay it. */
6286
6512
  interface ResourceDescription {
@@ -6542,6 +6768,43 @@ interface ExactRailOption {
6542
6768
  * "just works". Force `'eip3009'` or `'permit2'` to pin one. Ignored on Solana (always SVM). */
6543
6769
  method?: 'eip3009' | 'permit2' | 'auto';
6544
6770
  }
6771
+ /**
6772
+ * Opt into ALSO advertising a standard x402 `upto` (metered / variable-amount) rail beside the
6773
+ * default `onchain-proof` rail — for usage-billed APIs (pay-per-LLM-token, per-byte, per-query).
6774
+ * The buyer signs a Permit2 authorization for `amount` as a **MAXIMUM**; the merchant serves the
6775
+ * resource, meters the **actual** usage, then **self-settles** `actual ≤ max` through the
6776
+ * canonical `x402UptoPermit2Proxy` from its own `relayer` (which IS the bound `witness.facilitator`
6777
+ * — backendless, no third-party facilitator). **EVM-Permit2 ONLY** (the upto spec bans EIP-3009 and
6778
+ * has no non-EVM variant); native coins and non-Permit2 chains never carry it. Self-settle ONLY in
6779
+ * v1 (no facilitator mode). Omitting `upto` leaves the gate byte-identical to today.
6780
+ *
6781
+ * **⚠ UNSUPPORTED through the Express `requirePayment` middleware** — it settles BEFORE the route
6782
+ * handler serves, so the metered usage isn't known yet; constructing `requirePayment({ upto })`
6783
+ * THROWS. The supported handler shape is a **direct `gate.verify(header)` call** where the metering
6784
+ * happens INSIDE the `settleAmount` callback: serve/compute enough to know usage → `await
6785
+ * gate.verify(header)` whose `settleAmount` returns that usage → write the body + the receipt header.
6786
+ */
6787
+ interface UptoRailOption {
6788
+ /** REQUIRED — the gas-paying relayer wallet that settles AND is the bound `witness.facilitator`
6789
+ * (a `{ key }` or a bring-your-own EVM `{ walletClient }`). Distinct from `payTo`, the receive
6790
+ * address — though here they MAY be the same key (the proxy binds `witness.to` separately). */
6791
+ relayer: unknown;
6792
+ /**
6793
+ * REQUIRED — the merchant callback that picks the ACTUAL charge AFTER serving (the
6794
+ * deferred-settle lifecycle). Called with the metered context; return a `bigint` (base units),
6795
+ * or a string in the x402 SettlementOverrides forms — raw atomic (`"1858"`), `"NN%"` of the max
6796
+ * (floored), or `"$X"` (rounded to the token's decimals). `"0"`/`0n` ⇒ a zero-charge receipt with
6797
+ * NO on-chain tx. The gate clamps to ≤ the advertised max and rejects-over-max defensively
6798
+ * (`upto_settle_exceeds_max`). On the direct `gate.verify()` path this is where you meter usage.
6799
+ */
6800
+ settleAmount: (ctx: {
6801
+ maxAmount: bigint;
6802
+ asset: string;
6803
+ network: Caip2;
6804
+ decimals: number;
6805
+ request?: unknown;
6806
+ }) => bigint | string | Promise<bigint | string>;
6807
+ }
6545
6808
  /**
6546
6809
  * The merchant-side mirror of {@link PaidReceipt}: what an {@link RequirePaymentOptions.onFailed}
6547
6810
  * hook receives when a SUBMITTED payment proof is REJECTED. It carries the SAME machine-readable
@@ -6681,6 +6944,15 @@ interface RequirePaymentOptions {
6681
6944
  * byte-identical).
6682
6945
  */
6683
6946
  exact?: boolean | ExactRailOption;
6947
+ /**
6948
+ * ALSO advertise a standard x402 `upto` (metered / variable-amount) rail — for usage-billed
6949
+ * APIs (pay-per-LLM-token, per-byte, …). Opt-in, EVM-Permit2 ONLY, self-settle ONLY. See
6950
+ * {@link UptoRailOption}. The buyer signs for a MAX; you meter + settle the ACTUAL after serving
6951
+ * via the `settleAmount` callback. **UNSUPPORTED through `requirePayment` (the Express middleware
6952
+ * settles before the route handler serves) — constructing `requirePayment({ upto })` THROWS;** use
6953
+ * a direct `gate.verify()` call and meter inside `settleAmount`. Omitted ⇒ byte-identical to today.
6954
+ */
6955
+ upto?: UptoRailOption;
6684
6956
  /**
6685
6957
  * Make this gate's 402 self-describing for the open indexes — **x402scan REQUIRES
6686
6958
  * an input schema or it won't list the resource.** Set `true` for a no-input GET,
@@ -6700,6 +6972,65 @@ interface RequirePaymentOptions {
6700
6972
  * byte-identical default of before this feature). See {@link buildSelfDescription}.
6701
6973
  */
6702
6974
  selfDescribe?: boolean;
6975
+ /**
6976
+ * Emit a **verifiable receipt** on every settled payment — a self-contained
6977
+ * {@link PipRailReceipt} that the buyer keeps and **anyone** re-verifies against the
6978
+ * chain with only an RPC (no key, no backend, no PipRail account). It rides in an
6979
+ * `extensions['offer-receipt'].info` block on the `PAYMENT-RESPONSE` header (the
6980
+ * chain-grounded record at `info.settlement`; the optional Tier-2 SignedReceipt at the
6981
+ * spec's `info.receipt` slot) and stamps the challenge `nonce` onto the receipt so the five Template-A
6982
+ * (memo/nonce-bound) families re-verify off-chain. **Default off → byte-identical.**
6983
+ *
6984
+ * - `true` / `{}` → Tier-1 chain-grounded receipt (the settlement tx is the
6985
+ * authority — re-verified via the driver's own `verify()`).
6986
+ * - `{ includeTxHash }` → see {@link ReceiptOption}. Default `true` (PipRail inverts
6987
+ * the official privacy-default; the open chain is the pitch).
6988
+ *
6989
+ * Purely additive metadata a standard x402 client ignores; the `accepts[]`, status,
6990
+ * and pay path are unchanged. {@link PipRailClient.verifyReceipt} re-verifies it.
6991
+ */
6992
+ receipts?: boolean | ReceiptOption;
6993
+ }
6994
+ /** Tuning for the {@link RequirePaymentOptions.receipts} verifiable-receipt emission. */
6995
+ interface ReceiptOption {
6996
+ /**
6997
+ * Put the settlement tx hash in the receipt. **Default `true`** — PipRail inverts the
6998
+ * official x402 privacy-default (which omits it) because the whole pitch is the open,
6999
+ * self-verifiable chain. Set `false` for a privacy-minded merchant: the wire
7000
+ * `transaction` becomes the empty string `''` (per spec §5.3, never a missing key) and
7001
+ * the Tier-1 receipt is no longer third-party on-chain-verifiable (it carries no tx to
7002
+ * re-read) — use Tier-2 attestation for that case.
7003
+ */
7004
+ includeTxHash?: boolean;
7005
+ /**
7006
+ * The canonical resource URL to embed in the merchant-emitted receipt (what was paid
7007
+ * for). The buyer's {@link PipRailClient.lastReceipt} also fills this from the URL it
7008
+ * fetched, so set it here only to ground the raw header a third party reads directly.
7009
+ * Default `''` (the buyer's client fills it).
7010
+ */
7011
+ resource?: string;
7012
+ /**
7013
+ * **Tier-2 — service-delivery attestation (OPTIONAL, EVM-only).** When set, the gate
7014
+ * ALSO signs the official x402 `offer-receipt` EIP-712 receipt with the merchant's own
7015
+ * wallet, attesting the one thing the chain can't: that the resource was actually
7016
+ * **served**. A verifier checks `recover(sig) === payTo` — zero new infra, the
7017
+ * merchant's existing `payTo` key. The {@link SignedReceipt} rides at the official
7018
+ * spec slot `extensions['offer-receipt'].info.receipt` (so a stock `@x402/extensions`
7019
+ * reader reads it unchanged); verify with {@link PipRailClient.verifyAttestation}.
7020
+ *
7021
+ * - `{ wallet }` → the merchant's existing payTo key (EIP-712). EVM-only: on a non-EVM
7022
+ * rail it **degrades to Tier-1 + a one-time warning**, never throws.
7023
+ * - `{ jws }` → a managed JWS signer (did:web/key) — **R3, not yet implemented**
7024
+ * (the type slot is reserved). Supplying it today degrades to Tier-1 + a warning.
7025
+ *
7026
+ * Signing failures degrade to the unsigned Tier-1 receipt (isolated exactly like
7027
+ * `onPaid`) — they never fail the 200.
7028
+ */
7029
+ attest?: {
7030
+ wallet: unknown;
7031
+ } | {
7032
+ jws: unknown;
7033
+ };
6703
7034
  }
6704
7035
  type VerifyPaymentResult = {
6705
7036
  kind: 'paid';
@@ -6754,6 +7085,16 @@ interface PaymentGate {
6754
7085
  }>;
6755
7086
  /** Verify an incoming `payment-signature` header value. */
6756
7087
  verify(paymentSignature: string | string[] | undefined): Promise<VerifyPaymentResult>;
7088
+ /**
7089
+ * Verify an already-decoded PaymentPayload OBJECT (raw JSON, not base64) — the
7090
+ * additive seam for non-HTTP transports (A2A carries the payload as raw JSON
7091
+ * `metadata`, never a base64 header). Runs the EXACT SAME dispatch as {@link verify}
7092
+ * (upto → exact → onchain-proof), reading `sig.payload.nonce` from the object exactly
7093
+ * as the HTTP path does — so it adds ZERO new verification state and shares the gate's
7094
+ * one replay set. `verify(b64)` is the base64 path and stays byte-identical; this only
7095
+ * skips the decode. The same `onPaid`/`onFailed` hooks fire.
7096
+ */
7097
+ verifyObject(payload: unknown): Promise<VerifyPaymentResult>;
6757
7098
  /**
6758
7099
  * Describe this gate's payment options as static, nonce-free discovery
6759
7100
  * metadata — feed it to the emitters in `discovery.ts` (`buildOpenApi` /
@@ -7364,6 +7705,101 @@ declare const PERMIT2_WITNESS_TYPES: {
7364
7705
  }];
7365
7706
  };
7366
7707
 
7708
+ /**
7709
+ * ── EVM SECTION: x402 `upto` scheme (Permit2) — BUYER + SELLER ────────────────
7710
+ *
7711
+ * The metered / variable-amount counterpart to `permit2.ts`. The x402 `upto` scheme lets
7712
+ * a buyer authorize a MAXIMUM (sign a Permit2 `PermitWitnessTransferFrom` for the ceiling),
7713
+ * and the merchant settle the ACTUAL (≤ max) AFTER serving — billing exactly what was
7714
+ * consumed (LLM tokens, bytes, compute). EVM-Permit2 ONLY (the spec bans EIP-3009, which
7715
+ * fixes the amount at sign time, and has no non-EVM variant).
7716
+ *
7717
+ * • The payer signs an EIP-712 `PermitWitnessTransferFrom` over the canonical **Permit2**
7718
+ * contract, with `spender` = the canonical **x402UptoPermit2Proxy** and a **witness**
7719
+ * `{ to, facilitator, validAfter }` — `facilitator` is the **MIDDLE** field, the one
7720
+ * delta from the exact Permit2 witness. The buyer never broadcasts (and, after a
7721
+ * one-time Permit2 approval, spends ~0 gas) — the merchant broadcasts.
7722
+ * • The merchant SELF-SETTLES by calling the proxy's `settle(permit, amount, owner,
7723
+ * witness, signature)` — `amount` (position 1) is the ACTUAL (≤ the signed max), and the
7724
+ * proxy enforces `msg.sender == witness.facilitator` on-chain (`UnauthorizedFacilitator`)
7725
+ * PLUS `amount <= permit.permitted.amount` (`AmountExceedsPermitted`). So the merchant's
7726
+ * own relayer IS the bound facilitator — backendless, no third-party facilitator.
7727
+ *
7728
+ * Spec: `specs/schemes/upto/scheme_upto_evm.md` + `contracts/evm/src/x402UptoPermit2Proxy.sol`
7729
+ * (witness type string `Witness(address to,address facilitator,uint256 validAfter)` and the
7730
+ * `settle(...)` arg order both verdict-confirmed against the cloned source). This module
7731
+ * mirrors `permit2.ts` file-for-file (buyer {@link payUptoEvm}; seller
7732
+ * {@link verifyAndSettleUptoEvm}); the EVM driver routes to it via the new upto SPI trio.
7733
+ *
7734
+ * One-time setup is identical to the exact Permit2 rail — the payer `approve(Permit2, max)`
7735
+ * ONCE ({@link ensurePermit2Allowance}, re-used from `permit2.ts`).
7736
+ *
7737
+ * NOT the sponsor-fee-drain class (the relayer broadcasts on EVM and sets gas at broadcast;
7738
+ * the buyer's signed witness carries NO fee field) — add NO MAX_FEE cap, exactly like the
7739
+ * exact-EIP-3009 / exact-Permit2 rails.
7740
+ */
7741
+
7742
+ /** Canonical x402UptoPermit2Proxy — the SAME CREATE2 address on every chain where it's been
7743
+ * deployed (see {@link UPTO_PROXY_CHAIN_IDS}; vanity `…0002`, vs the exact proxy's `…0001`).
7744
+ * It is the `spender` the buyer signs over and the contract the seller settles through; it
7745
+ * enforces `transferDetails.to == witness.to`, `msg.sender == witness.facilitator`, and
7746
+ * `amount <= permit.permitted.amount` on-chain. */
7747
+ declare const X402_UPTO_PERMIT2_PROXY: "0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002";
7748
+ /** EVM chain ids where BOTH the canonical Permit2 AND the x402UptoPermit2Proxy are deployed —
7749
+ * i.e. where the `upto` scheme can actually settle. Verdict-confirmed on-chain (`eth_getCode`,
7750
+ * ~3142-byte byte-identical code, 2026-06-20): Ethereum / Base / Arbitrum / Optimism / Polygon
7751
+ * / BNB. **Avalanche (43114) is NOT deployed (`0x`)** — deliberately OUT. This is INDEPENDENT of
7752
+ * the exact `PERMIT2_PROXY_CHAIN_IDS` (a separate proxy). The proxy is a permissionless CREATE2
7753
+ * deploy, so extend this as it lands on more chains (re-verify each with `eth_getCode` first). */
7754
+ declare const UPTO_PROXY_CHAIN_IDS: ReadonlySet<number>;
7755
+ /** Whether a chain has the x402UptoPermit2Proxy deployed (→ can settle the `upto` scheme). */
7756
+ declare function isUptoProxyChain(chainId: number): boolean;
7757
+ /**
7758
+ * EIP-712 type set for the x402 `upto` scheme. Identical to {@link PERMIT2_WITNESS_TYPES}
7759
+ * (the exact Permit2 rail) EXCEPT the `Witness` struct carries a `facilitator` field as its
7760
+ * **MIDDLE** member. MUST encode to exactly the type string the proxy reconstructs:
7761
+ * `PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,address facilitator,uint256 validAfter)`
7762
+ * (viem orders referenced structs alphabetically → TokenPermissions before Witness ✓.)
7763
+ * **`facilitator` is the MIDDLE field** — get the order wrong and `recoverTypedDataAddress`
7764
+ * silently returns the wrong address → every signature rejects. Verdict-confirmed against
7765
+ * `x402UptoPermit2Proxy.sol` WITNESS_TYPEHASH + the reference `uptoPermit2WitnessTypes`.
7766
+ */
7767
+ declare const PERMIT2_UPTO_WITNESS_TYPES: {
7768
+ readonly PermitWitnessTransferFrom: readonly [{
7769
+ readonly name: "permitted";
7770
+ readonly type: "TokenPermissions";
7771
+ }, {
7772
+ readonly name: "spender";
7773
+ readonly type: "address";
7774
+ }, {
7775
+ readonly name: "nonce";
7776
+ readonly type: "uint256";
7777
+ }, {
7778
+ readonly name: "deadline";
7779
+ readonly type: "uint256";
7780
+ }, {
7781
+ readonly name: "witness";
7782
+ readonly type: "Witness";
7783
+ }];
7784
+ readonly TokenPermissions: readonly [{
7785
+ readonly name: "token";
7786
+ readonly type: "address";
7787
+ }, {
7788
+ readonly name: "amount";
7789
+ readonly type: "uint256";
7790
+ }];
7791
+ readonly Witness: readonly [{
7792
+ readonly name: "to";
7793
+ readonly type: "address";
7794
+ }, {
7795
+ readonly name: "facilitator";
7796
+ readonly type: "address";
7797
+ }, {
7798
+ readonly name: "validAfter";
7799
+ readonly type: "uint256";
7800
+ }];
7801
+ };
7802
+
7367
7803
  /**
7368
7804
  * Landing page — a tiny, self-contained HTML representation of a 402, for the HUMAN
7369
7805
  * who opens a gated URL in a browser (agents/crawlers still get the unchanged JSON 402).
@@ -7388,4 +7824,278 @@ declare const PERMIT2_WITNESS_TYPES: {
7388
7824
  */
7389
7825
  declare function renderLandingPage(sd: SelfDescription): string;
7390
7826
 
7391
- export { type AcceptOption, AddressId, type AgentTool, type AlgorandToken, type AptosToken, AssetId, BRAND, BUILTIN_DENOMS, type BazaarExtension, type BuildExactParams, CHAINS, Caip2, type ChainFamily, type ChainInput, type ChainName, type ChainPreset, type ChainSelector, type ChallengeTriage, type ChallengeVerdict, type ConfirmInfo, ConfirmationTimeoutError, type CostEstimate, type CountStatus, DENOM_PRECISION, DIRECTORY_INFO, type DeclineReasonCode, type DeliverAttempt, type DeliverReceiptOptions, type DeliverResult, type DenomRemaining, type DirectoryInfo, type DiscoverOptions, type DiscoveredRail, type DiscoveredResource, type DiscoveryDescriptor, type DiscoverySigner, type DiscoverySort, type DiscoverySource, type DomainClaim, type DomainVerification, EIP3009_TYPES, EXACT_NETWORK_SLUGS, type EvmToken, type ExactAccept, type ExactAuthorization, ExactPaymentPayloadAny, type ExactRailOption, type ExpressLikeMiddleware, type ExpressLikeNext, type ExpressLikeRequest, type ExpressLikeResponse, type FacilitatorConfig, type FacilitatorPaymentRequirements, type FacilitatorSupportedKind, type FailedPayment, GENERATOR, InsufficientFundsError, InvalidEnvelopeError, KNOWN_FACILITATORS, type KnownFacilitator, type ListingVisibility, type ManifestInput, MaxRetriesExceededError, MissingDriverError, MultiChainPayer, type MultiChainPayerOptions, type NearToken, NoCompatibleAcceptError, NonReplayableBodyError, type OpenApiDocument, type OpenApiOperation, PERMIT2_ADDRESS, PERMIT2_PROXY_CHAIN_IDS, PERMIT2_WITNESS_TYPES, PIPRAIL_AGENT_GUIDE, POWERED_BY, PaidReceipt, type PayBlocker, type PayOption, type PayWarning, type PayingClient, 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, REGISTER_ATTRIBUTION, RecipientNotReadyError, type RecipientReason, type RegisterInput, type RegisterOptions, type RegisterOutcome, type RequirePaymentOptions, type ResolveOptions, type ResolvedChain, type ResolvedNetwork, type ResolvedToken, type ResourceDescription, type SearchOpenIndexesOptions, type SelfDescribeEndpoint, type SelfDescribeRail, type SelfDescription, type SessionBudget, SettleOutcome, type SettleViaFacilitatorInput, SettlementError, type SolanaToken, SpendLedger, SpendRecord, type SpendRemaining, SpendStore, SpendSummary, type StellarToken, type SuiToken, type TokenInfo, type TokenInput, type TonToken, type ToolAnnotations, type TronToken, UnknownTokenError, UnsupportedNetworkError, UnsupportedSchemeError, VerifyErrorCode, type VerifyPaymentResult, VerifyResult, type WalletBalance, type WalletHandle, type WalletInput, WalletRequiredError, type WellKnownX402, WrongChainError, WrongFamilyError, X402AcceptEntry, X402AnyAccept, X402Challenge, type X402DnsRecord, X402ExactAcceptEntry, type X402InvalidBody, X402Receipt, X402_EXACT_PERMIT2_PROXY, type XrplToken, agentGuide, appendAttribution, appendKeywords, buildBazaarExtension, buildEndpointInfo, buildExactAuthorization, buildOpenApi, buildSelfDescription, buildWellKnownX402, buildX402DnsTxt, chainIdForExactNetwork, claim402IndexDomain, classifyChallenge, createPaymentGate, decorateOutcome, deliverReceipt, denomOf, describeChallenge, discoveryHeaders, eip3009Abi, encodeXPaymentHeader, evaluatePolicy, explainDecline, facilitatorCoverage, fetchAcross, firstKeylessFacilitator, formatSpendReport, getDirectoryInfo, isPermit2ProxyChain, knownFacilitatorsFor, normalizeNetwork, parseExactRequirements, parseFacilitatorSupported, paymentTools, planAcross, rankResources, readExactDomain, register402Index, registerDriver, registerX402Scan, renderLandingPage, requirePayment, resolveChain, scoreResource, searchOpenIndexes, settleViaFacilitator, summarizePlan, toInsufficientFundsError, toInvalidBody, verify402IndexDomain };
7827
+ /**
7828
+ * Minimal, DUCK-TYPED Google Agent2Agent (A2A) shapes — the structural surface the
7829
+ * PipRail A2A transport reads/writes, and NOTHING more. Like `ExpressLikeRequest` in
7830
+ * `server.ts`, these declare only the fields the adapter touches, so any A2A runtime's
7831
+ * objects (the official `@a2a-js/sdk`, ADK, or a hand-rolled JSON-RPC handler) satisfy
7832
+ * them structurally — **with ZERO `@a2a` dependency**.
7833
+ *
7834
+ * x402-over-A2A carries PipRail's existing `PaymentRequired`/`PaymentPayload`/
7835
+ * `SettlementResponse` envelopes inside A2A `Task`/`Message` `metadata`, keyed off five
7836
+ * namespaced keys (`x402.payment.{status,required,payload,receipts,error}`), so a
7837
+ * standard A2A reader ignores them and they coexist with any other metadata.
7838
+ *
7839
+ * Verified verbatim against the upstream reference `x402_a2a/types/state.py` and the
7840
+ * x402-foundation `specs/transports-v2/a2a.md` mapping table.
7841
+ */
7842
+
7843
+ /** The coarse A2A Task state (the A2A framework's own lifecycle). */
7844
+ type A2ATaskState = 'submitted' | 'working' | 'input-required' | 'completed' | 'failed' | 'canceled';
7845
+ /** The granular `x402.payment.status` lifecycle field (the payment state machine atop the
7846
+ * Task state). Per `transports-v2/a2a.md:217-224` + the reference `PaymentStatus` enum. */
7847
+ type A2APaymentStatus = 'payment-required' | 'payment-submitted' | 'payment-verified' | 'payment-completed' | 'payment-failed' | 'payment-rejected';
7848
+ /** A part of an A2A Message — text, data, or file. Only the fields the adapter reads/writes. */
7849
+ interface A2APart {
7850
+ kind?: 'text' | 'data' | 'file' | string;
7851
+ text?: string;
7852
+ data?: unknown;
7853
+ [extra: string]: unknown;
7854
+ }
7855
+ /** An A2A Artifact — the merchant's served work attached to a completed Task. The adapter
7856
+ * attaches `fulfill()`'s output here, plus (B7) an optional post-settle error annotation. */
7857
+ interface A2AArtifact {
7858
+ artifactId?: string;
7859
+ name?: string;
7860
+ parts?: A2APart[];
7861
+ /** Free-form annotation bag. The B7 fulfill-throws-after-settle edge stamps a post-settle
7862
+ * error here (NEVER re-challenge / failed) so the buyer sees the work failed AFTER paying. */
7863
+ metadata?: Record<string, unknown>;
7864
+ [extra: string]: unknown;
7865
+ }
7866
+ /**
7867
+ * The five canonical x402 metadata keys (namespaced `x402.payment.*`) plus structural
7868
+ * tolerance for any other A2A metadata. The shapes are PipRail's EXISTING wire objects —
7869
+ * `x402.payment.required` is a raw `X402Challenge` (NOT base64), `x402.payment.payload` is
7870
+ * a raw PaymentPayload object (fed to the tolerant object-cores via `gate.verifyObject`),
7871
+ * and `x402.payment.receipts` is the append-only history.
7872
+ */
7873
+ interface A2AMetadata {
7874
+ 'x402.payment.status'?: A2APaymentStatus;
7875
+ 'x402.payment.required'?: X402Challenge;
7876
+ /** A raw `X402PaymentSignature` / exact / upto payload object — fed straight into
7877
+ * `gate.verifyObject` (the tolerant object-cores absorb v1+v2). */
7878
+ 'x402.payment.payload'?: unknown;
7879
+ /**
7880
+ * B7: append-only settlement history. The element type is the UNION because the array
7881
+ * MUST include FAILED attempts (`spec v0.1:281`) — and `X402Receipt.success` is the literal
7882
+ * `true`, so a failed entry can only be a `SettleOutcome { success:false, errorReason }`.
7883
+ */
7884
+ 'x402.payment.receipts'?: (X402Receipt | SettleOutcome)[];
7885
+ /** The error code on a settlement-side failure (`x402.payment.error`). */
7886
+ 'x402.payment.error'?: string;
7887
+ [extra: string]: unknown;
7888
+ }
7889
+ /** An inbound/outbound A2A Message. The submission carries the payload + the original
7890
+ * `taskId` for correlation (`v0.1 spec.md:163`). Only the fields the adapter touches. */
7891
+ interface A2AMessage {
7892
+ kind?: 'message';
7893
+ role?: string;
7894
+ /** Correlates a follow-up payment submission to its in-flight payment Task. */
7895
+ taskId?: string;
7896
+ messageId?: string;
7897
+ parts?: A2APart[];
7898
+ metadata?: A2AMetadata;
7899
+ [extra: string]: unknown;
7900
+ }
7901
+ /** An A2A Task — the merchant's response carrying the payment state in `status.message.metadata`. */
7902
+ interface A2ATask {
7903
+ kind?: 'task';
7904
+ id: string;
7905
+ status: {
7906
+ state: A2ATaskState;
7907
+ message?: A2AMessage;
7908
+ };
7909
+ artifacts?: A2AArtifact[];
7910
+ [extra: string]: unknown;
7911
+ }
7912
+ /**
7913
+ * An AgentCard extension declaration — what the merchant stamps into its
7914
+ * `AgentCard.capabilities.extensions[]` to advertise the x402 extension (§2.4). A client
7915
+ * opts in by sending `X-A2A-Extensions: <uri>`; `required: true` rejects un-activated callers.
7916
+ */
7917
+ interface A2AExtensionDeclaration {
7918
+ uri: string;
7919
+ description?: string;
7920
+ required?: boolean;
7921
+ params?: Record<string, unknown>;
7922
+ }
7923
+ /**
7924
+ * A bounded, pluggable TRANSPORT-LIFECYCLE store — NOT a backend, NOT on the verification
7925
+ * path, holds NO security state (B4). It correlates a follow-up `message/send` to its
7926
+ * in-flight Task and accumulates the append-only `receipts[]` history. The buyer carries
7927
+ * the challenge nonce in its payload; `gate.verify`/`gate.verifyObject` re-derive every
7928
+ * trusted field from the merchant's own config (`server.ts` client-echoed nonce), so even
7929
+ * a poisoned/empty store can never redirect funds or reject a valid payment. Same posture
7930
+ * as the gate's in-memory replay set — a bounded Map inside the merchant's own process.
7931
+ */
7932
+ interface A2ATaskStore {
7933
+ get(taskId: string): A2ATaskRecord | undefined;
7934
+ set(taskId: string, value: A2ATaskRecord, ttlMs: number): void;
7935
+ }
7936
+ /** What a {@link A2ATaskStore} holds per task — the receipt history ONLY (no nonce-as-security). */
7937
+ interface A2ATaskRecord {
7938
+ receipts?: (X402Receipt | SettleOutcome)[];
7939
+ }
7940
+
7941
+ /**
7942
+ * x402-over-A2A — the SELLER-side transport adapter (Google Agent2Agent).
7943
+ *
7944
+ * A2A is x402's third official transport (alongside HTTP and MCP). It carries PipRail's
7945
+ * BYTE-IDENTICAL `PaymentRequired`/`PaymentPayload`/`SettlementResponse` envelopes inside
7946
+ * A2A `Task`/`Message` JSON-RPC `metadata` (five namespaced `x402.payment.*` keys) keyed
7947
+ * off a coarse A2A Task state — instead of base64 HTTP headers. It is a thin codec + adapter
7948
+ * ABOVE the `PaymentDriver` boundary: ZERO driver changes, ZERO scheme changes, ZERO chain
7949
+ * changes — all 10 chain families work over A2A for free, exactly as they work over HTTP.
7950
+ *
7951
+ * This module imports ONLY `server.ts`/`x402.ts` types + `errors.ts` (the same surface as
7952
+ * the Express adapter) — NO `viem`, NO chain SDK. It never touches a chain.
7953
+ *
7954
+ * ── Charter-critical invariants ───────────────────────────────────────────────
7955
+ * • Defaults byte-identical: a root install that never imports A2A loads nothing extra.
7956
+ * • B4 — NO new verification state: the buyer carries the challenge nonce in its payload;
7957
+ * `gate.verifyObject` reads `sig.payload.nonce` exactly as HTTP does, and the gate
7958
+ * re-derives every trusted field from the merchant's own config. The `A2ATaskStore` is
7959
+ * transport task-lifecycle ONLY (receipt history), never on the verification path.
7960
+ * • B5 — HTTP and A2A MUST share ONE replay set: `createA2APaymentHandler` takes an
7961
+ * EXISTING `PaymentGate` (the primary, ergonomic form). A co-resident HTTP gate that
7962
+ * builds a SEPARATE gate must share `isUsed`/`markUsed`, or a proof settled over one
7963
+ * transport can be replayed over the other.
7964
+ * • B7 — `receipts[]` is the UNION `(X402Receipt | SettleOutcome)[]` (it carries FAILED
7965
+ * attempts); a fulfill-throws-AFTER-settle ends the Task `completed` with the successful
7966
+ * receipt + an error annotation (NEVER re-challenge / failed — the money already moved).
7967
+ * • Emit `x402Version: 2` — RESOLVED 2026-06-21: v2 IS the live x402 standard. A live cross-check
7968
+ * against Google's official libs (reproducible harness in `examples/a2a-interop/`) showed the canonical
7969
+ * `x402` lib (2.13.1, V2: `amount` / CAIP-2 / nested `accepted`) parses our PaymentRequired +
7970
+ * PaymentPayload byte-identically, while the legacy v0.1 `x402_a2a` package (x402Version 1,
7971
+ * `maxAmountRequired`, chain slugs) is bitrotted. Inbound v1 object-cores are absorbed for the
7972
+ * standard `exact` scheme; PipRail-native `onchain-proof` is always v2 (never sent v1-flat).
7973
+ * • Merchant statuses are spec-bounded: `payment-required` (incl. a retryable re-challenge of a
7974
+ * rejected proof) / `payment-completed` / `payment-failed`. `payment-rejected` + `payment-submitted`
7975
+ * are CLIENT→merchant statuses we never emit.
7976
+ *
7977
+ * ── DEFERRED (NOT built here — see the x402-parity/03-a2a-transport plan) ──────
7978
+ * • Phase 4 — the A2A BUYER (`A2APayer`): the HTTP buyer mints the payload that rides A2A today.
7979
+ * • Phase 5 — AP2 `CartMandate`/`PaymentMandate` carriage (the Embedded Flow; no mandate-trust machinery).
7980
+ * • B8 ship-gate — RESOLVED at the wire level (above). A live `adk-demo` AGENT run is blocked by that
7981
+ * package's dependency bitrot (won't import on current `x402`/`a2a-sdk`), not by PipRail.
7982
+ */
7983
+
7984
+ /** The x402 A2A extension URI the x402-foundation doc + ALL Google reference code cite
7985
+ * (`config.py:23`, `version="0.1"`). The seller's default — activation is exact-string match. */
7986
+ declare const A2A_X402_EXTENSION_URI_V01 = "https://github.com/google-a2a/a2a-x402/v0.1";
7987
+ /** The newer v0.2 URI (`spec/v0.2/spec.md:11`) — for AP2 Embedded-Flow targets (Phase 5, deferred). */
7988
+ declare const A2A_X402_EXTENSION_URI_V02 = "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2";
7989
+ /** The five canonical metadata keys (verbatim from `x402_a2a/types/state.py:33-37`). */
7990
+ declare const A2A_STATUS_KEY = "x402.payment.status";
7991
+ declare const A2A_REQUIRED_KEY = "x402.payment.required";
7992
+ declare const A2A_PAYLOAD_KEY = "x402.payment.payload";
7993
+ declare const A2A_RECEIPTS_KEY = "x402.payment.receipts";
7994
+ declare const A2A_ERROR_KEY = "x402.payment.error";
7995
+ /** The HTTP activation header a client sends to opt into the extension (§2.4). */
7996
+ declare const A2A_EXTENSIONS_HEADER = "X-A2A-Extensions";
7997
+ /**
7998
+ * Map PipRail's lowercase {@link VerifyErrorCode} to the spec's screaming-snake error enum
7999
+ * (`errors.py:148-157` / spec §8.1) for `x402.payment.error`. We ALSO emit the raw PipRail
8000
+ * code (in the re-challenge's `extensions.piprail`), so nothing is lost and a buyer agent
8001
+ * branches identically across transports. Codes with no spec analogue map to `SETTLEMENT_FAILED`
8002
+ * only when they're settlement-side; rejection codes keep their nearest enum member.
8003
+ */
8004
+ declare const VERIFY_CODE_TO_A2A_ERROR: Record<string, string>;
8005
+ /** Translate a PipRail verify/settle code to the A2A error enum (falls back to the raw code). */
8006
+ declare function toA2AErrorCode(code: string): string;
8007
+ /**
8008
+ * Build the `input-required` payment-request Task carrying the challenge as RAW JSON
8009
+ * (NOT base64) in `x402.payment.required` + `x402.payment.status = 'payment-required'`.
8010
+ * `parts` are any human-readable message parts the merchant wants alongside it.
8011
+ */
8012
+ declare function toA2APaymentRequired(taskId: string, challenge: X402Challenge, parts?: A2APart[]): A2ATask;
8013
+ /** Build the `x402.payment.receipts` metadata block (an ARRAY, append-only, B7 union). */
8014
+ declare function toA2APaymentReceipts(receipts: (X402Receipt | SettleOutcome)[]): A2AMetadata;
8015
+ /**
8016
+ * Build the `payment-failed` metadata for a SETTLEMENT-side failure (the money never moved):
8017
+ * the A2A error code + a `{ success:false, errorReason }` receipt appended to the history (B7).
8018
+ */
8019
+ declare function toA2APaymentFailed(code: VerifyErrorCode | string, detail: string, receipts?: (X402Receipt | SettleOutcome)[], network?: string): A2AMetadata;
8020
+ /** Read the `X402Challenge` back out of a payment-request Task's metadata (raw JSON). */
8021
+ declare function fromA2APaymentRequired(task: A2ATask): X402Challenge | null;
8022
+ /**
8023
+ * Read the inbound RAW payment payload object + its correlating `taskId` out of a
8024
+ * `message/send`. The raw object is fed straight into `gate.verifyObject` (the tolerant
8025
+ * object-cores absorb v1+v2). Returns `null` when there's no payload metadata.
8026
+ */
8027
+ declare function fromA2APaymentPayload(message: A2AMessage): {
8028
+ raw: unknown;
8029
+ taskId: string;
8030
+ } | null;
8031
+ /** Options for {@link createA2APaymentHandler}. */
8032
+ interface A2APaymentHandlerOptions extends Partial<RequirePaymentOptions> {
8033
+ /**
8034
+ * B5 (MANDATORY cross-transport replay): pass the SAME {@link PaymentGate} instance the
8035
+ * HTTP path uses, so both transports share ONE replay set (`localUsed` / injected
8036
+ * `isUsed`/`markUsed`). This is the PRIMARY, ergonomic form. If omitted, a fresh gate is
8037
+ * built from the inline `RequirePaymentOptions` — and a co-resident HTTP gate MUST then
8038
+ * share `isUsed`/`markUsed`, or a proof settled over one transport can be replayed over
8039
+ * the other.
8040
+ */
8041
+ gate?: PaymentGate;
8042
+ /**
8043
+ * A bounded, pluggable TRANSPORT-lifecycle store (B4) — correlate a follow-up
8044
+ * `message/send` to its in-flight Task + accumulate the append-only `receipts[]`. It is
8045
+ * NOT on the verification path and holds NO nonce-as-security-state (the buyer carries the
8046
+ * nonce in its payload). Default = an in-memory TTL Map (same bound as the replay set).
8047
+ * NOT a backend PipRail hosts.
8048
+ */
8049
+ taskStore?: A2ATaskStore;
8050
+ /** TTL (ms) for the default task store. Default = `maxTimeoutSeconds * 1000` (the replay window). */
8051
+ taskTtlMs?: number;
8052
+ /**
8053
+ * Produce the served result Artifact(s) for a settled task — the merchant's own work (the
8054
+ * image, the JSON, …). Charter-safe: like an Express route handler that runs after `next()`.
8055
+ * Omit for a metadata-only "payment accepted" completion. **B7: if this THROWS after a
8056
+ * successful settle, the Task still completes `completed` carrying the success receipt + an
8057
+ * error annotation — the buyer is NEVER told to re-pay an already-settled proof.**
8058
+ */
8059
+ fulfill?: (ctx: {
8060
+ taskId: string;
8061
+ receipt: X402Receipt;
8062
+ message: A2AMessage;
8063
+ }) => Promise<A2AArtifact[]> | A2AArtifact[];
8064
+ }
8065
+ /** The seller handler returned by {@link createA2APaymentHandler}. */
8066
+ interface A2APaymentHandler {
8067
+ /**
8068
+ * Process one inbound A2A message and return the next Task. Outcomes mirror
8069
+ * `gate.verify()`'s `VerifyPaymentResult` exactly:
8070
+ * - no payload yet → Task `input-required` + `x402.payment.required`
8071
+ * - payload, verified+settled → Task `completed` + `x402.payment.receipts` + artifacts
8072
+ * - payload, rejected → Task `input-required` re-challenge (RETRYABLE)
8073
+ * - settle threw (relayer) → Task `failed` + `x402.payment.error` (NOT retryable)
8074
+ * - settle OK but fulfill threw → Task `completed` + receipt + error annotation (B7)
8075
+ */
8076
+ handleMessage(message: A2AMessage, taskId?: string): Promise<A2ATask>;
8077
+ /** Stamp the x402 extension into an AgentCard's `capabilities.extensions` (§2.4). */
8078
+ agentCardExtension(opts?: {
8079
+ required?: boolean;
8080
+ version?: 'v0.1' | 'v0.2';
8081
+ }): A2AExtensionDeclaration;
8082
+ /** The underlying gate — escape hatch for advanced flows (`describe()`, `landingPage()`). */
8083
+ readonly gate: PaymentGate;
8084
+ }
8085
+ /**
8086
+ * The A2A analogue of `requirePayment` — wrap a {@link PaymentGate} and map A2A messages ⇄
8087
+ * x402 task metadata. The merchant plugs `handleMessage` into their A2A agent's
8088
+ * `message/send` handler and pushes `agentCardExtension()` into their AgentCard.
8089
+ *
8090
+ * @example
8091
+ * ```ts
8092
+ * import { createPaymentGate, createA2APaymentHandler } from '@piprail/sdk'
8093
+ *
8094
+ * const gate = createPaymentGate({ chain: 'base', token: 'USDC', amount: '0.05', payTo: '0x…' })
8095
+ * const pay = createA2APaymentHandler({ gate, fulfill: async () => [{ name: 'result', parts: [{ kind: 'text', text: 'done' }] }] })
8096
+ * a2aAgent.on('message/send', ({ message, taskId }) => pay.handleMessage(message, taskId))
8097
+ * ```
8098
+ */
8099
+ declare function createA2APaymentHandler(options: A2APaymentHandlerOptions): A2APaymentHandler;
8100
+
8101
+ export { type A2AArtifact, type A2AExtensionDeclaration, type A2AMessage, type A2AMetadata, type A2APart, type A2APaymentHandler, type A2APaymentHandlerOptions, type A2APaymentStatus, type A2ATask, type A2ATaskRecord, type A2ATaskState, type A2ATaskStore, A2A_ERROR_KEY, A2A_EXTENSIONS_HEADER, A2A_PAYLOAD_KEY, A2A_RECEIPTS_KEY, A2A_REQUIRED_KEY, A2A_STATUS_KEY, A2A_X402_EXTENSION_URI_V01, A2A_X402_EXTENSION_URI_V02, type AcceptOption, AddressId, type AgentTool, type AlgorandToken, type AptosToken, AssetId, BRAND, BUILTIN_DENOMS, type BazaarExtension, type BuildExactParams, CHAINS, Caip2, type ChainFamily, type ChainInput, type ChainName, type ChainPreset, type ChainSelector, type ChallengeTriage, type ChallengeVerdict, type ConfirmInfo, ConfirmationTimeoutError, type CostEstimate, type CountStatus, DENOM_PRECISION, DIRECTORY_INFO, type DeclineReasonCode, type DeliverAttempt, type DeliverReceiptOptions, type DeliverResult, type DenomRemaining, type DirectoryInfo, type DiscoverOptions, type DiscoveredRail, type DiscoveredResource, type DiscoveryDescriptor, type DiscoverySigner, type DiscoverySort, type DiscoverySource, type DomainClaim, type DomainVerification, EIP3009_TYPES, EXACT_NETWORK_SLUGS, type EvmToken, type ExactAccept, type ExactAuthorization, ExactPaymentPayloadAny, type ExactRailOption, type ExpressLikeMiddleware, type ExpressLikeNext, type ExpressLikeRequest, type ExpressLikeResponse, type FacilitatorConfig, type FacilitatorPaymentRequirements, type FacilitatorSupportedKind, type FailedPayment, GENERATOR, InsufficientFundsError, InvalidEnvelopeError, KNOWN_FACILITATORS, type KnownFacilitator, type ListingVisibility, type ManifestInput, MaxRetriesExceededError, MissingDriverError, MultiChainPayer, type MultiChainPayerOptions, type NearToken, NoCompatibleAcceptError, NonReplayableBodyError, type OpenApiDocument, type OpenApiOperation, PERMIT2_ADDRESS, PERMIT2_PROXY_CHAIN_IDS, PERMIT2_UPTO_WITNESS_TYPES, PERMIT2_WITNESS_TYPES, PIPRAIL_AGENT_GUIDE, POWERED_BY, PaidReceipt, type PayBlocker, type PayOption, type PayWarning, type PayingClient, PaymentDeclinedError, type PaymentDriver, type PaymentGate, type PaymentIntent, type PaymentPlan, type PaymentPolicy, type PaymentRail, type PaymentScheme, PaymentTimeoutError, Permit2UptoPaymentPayload, PipRailClient, type PipRailClientOptions, type PipRailCostQuote, PipRailError, type PipRailEvent, type PipRailQuote, PipRailReceipt, type PolicyDecision, type PolicyDenyCode, REGISTER_ATTRIBUTION, type ReceiptInput, type ReceiptOption, type ReceiptVerification, RecipientNotReadyError, type RecipientReason, type RegisterInput, type RegisterOptions, type RegisterOutcome, type RequirePaymentOptions, type ResolveOptions, type ResolvedChain, type ResolvedNetwork, type ResolvedToken, type ResourceDescription, type SearchOpenIndexesOptions, type SelfDescribeEndpoint, type SelfDescribeRail, type SelfDescription, type SessionBudget, SettleOutcome, type SettleViaFacilitatorInput, SettlementError, SignedReceipt, type SolanaToken, SpendLedger, SpendRecord, type SpendRemaining, SpendStore, SpendSummary, type StellarToken, type SuiToken, type TokenInfo, type TokenInput, type TonToken, type ToolAnnotations, type TronToken, UPTO_PROXY_CHAIN_IDS, UnknownTokenError, UnsupportedNetworkError, UnsupportedSchemeError, type UptoRailOption, VERIFY_CODE_TO_A2A_ERROR, VerifyErrorCode, type VerifyPaymentResult, VerifyResult, type WalletBalance, type WalletHandle, type WalletInput, WalletRequiredError, type WellKnownX402, WrongChainError, WrongFamilyError, X402AcceptEntry, X402AnyAccept, X402Challenge, type X402DnsRecord, X402ExactAcceptEntry, type X402InvalidBody, X402Receipt, X402UptoAcceptEntry, X402_EXACT_PERMIT2_PROXY, X402_UPTO_PERMIT2_PROXY, type XrplToken, agentGuide, appendAttribution, appendKeywords, buildBazaarExtension, buildEndpointInfo, buildExactAuthorization, buildOpenApi, buildSelfDescription, buildWellKnownX402, buildX402DnsTxt, chainIdForExactNetwork, claim402IndexDomain, classifyChallenge, createA2APaymentHandler, createPaymentGate, decorateOutcome, deliverReceipt, denomOf, describeChallenge, discoveryHeaders, eip3009Abi, encodeXPaymentHeader, evaluatePolicy, explainDecline, facilitatorCoverage, fetchAcross, firstKeylessFacilitator, formatSpendReport, fromA2APaymentPayload, fromA2APaymentRequired, getDirectoryInfo, isPermit2ProxyChain, isUptoProxyChain, knownFacilitatorsFor, normalizeNetwork, parseExactRequirements, parseFacilitatorSupported, paymentTools, planAcross, rankResources, readExactDomain, register402Index, registerDriver, registerX402Scan, renderLandingPage, requirePayment, resolveChain, scoreResource, searchOpenIndexes, settleViaFacilitator, summarizePlan, toA2AErrorCode, toA2APaymentFailed, toA2APaymentReceipts, toA2APaymentRequired, toInsufficientFundsError, toInvalidBody, verify402IndexDomain };