@piprail/sdk 1.22.1 → 1.24.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/CHANGELOG.md +83 -0
- package/README.md +28 -1
- package/dist/index.cjs +472 -27
- package/dist/index.d.cts +437 -6
- package/dist/index.d.ts +437 -6
- package/dist/index.js +460 -15
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5204,6 +5204,22 @@ interface RegisterOptions {
|
|
|
5204
5204
|
*/
|
|
5205
5205
|
attribution?: boolean;
|
|
5206
5206
|
}
|
|
5207
|
+
/**
|
|
5208
|
+
* The read-+-pay surface an agent toolkit needs — the methods {@link paymentTools}
|
|
5209
|
+
* calls. BOTH {@link PipRailClient} (one chain) and {@link MultiChainPayer} (many
|
|
5210
|
+
* chains, one per wallet) satisfy it, so `paymentTools` wraps either unchanged:
|
|
5211
|
+
* point an MCP/LLM at one wallet or at a whole bundle without touching the tools.
|
|
5212
|
+
*/
|
|
5213
|
+
interface PayingClient {
|
|
5214
|
+
discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
|
|
5215
|
+
quote(url: string, init?: RequestInit): Promise<PipRailQuote | null>;
|
|
5216
|
+
planPayment(url: string, init?: RequestInit): Promise<PaymentPlan | null>;
|
|
5217
|
+
get(url: string, init?: RequestInit): Promise<Response>;
|
|
5218
|
+
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
5219
|
+
register(url: string, opts?: RegisterOptions): Promise<RegisterOutcome[]>;
|
|
5220
|
+
spent(): SpendSummary;
|
|
5221
|
+
budget(): SessionBudget;
|
|
5222
|
+
}
|
|
5207
5223
|
declare class PipRailClient {
|
|
5208
5224
|
private readonly opts;
|
|
5209
5225
|
private readonly maxRetries;
|
|
@@ -5453,11 +5469,188 @@ declare class PipRailClient {
|
|
|
5453
5469
|
* A {@link PipRailClient} is bound to one chain (its wallet); give this one client
|
|
5454
5470
|
* per chain the agent funds and it runs each client's {@link PipRailClient.planPayment}
|
|
5455
5471
|
* in parallel and merges the rails into one plan, ranked payable-first. `best` is a
|
|
5456
|
-
* payable rail
|
|
5457
|
-
*
|
|
5458
|
-
*
|
|
5472
|
+
* payable rail. Across different native coins there's no oracle to compare gas costs,
|
|
5473
|
+
* so it does NOT rank chains by fee against each other: `best` is the FIRST chain you
|
|
5474
|
+
* pass in `clients` that can settle (your preference order); within a single chain it
|
|
5475
|
+
* still prefers the cheapest-gas rail. Returns `null` only if the URL isn't gated for
|
|
5476
|
+
* any client. Throws only if EVERY client fails to reach the resource (a total outage),
|
|
5477
|
+
* mirroring a single client — a single chain being down just drops that chain.
|
|
5459
5478
|
*/
|
|
5460
5479
|
declare function planAcross(clients: PipRailClient[], url: string, init?: RequestInit): Promise<PaymentPlan | null>;
|
|
5480
|
+
/**
|
|
5481
|
+
* PAY across several single-chain clients — the EXECUTION counterpart to
|
|
5482
|
+
* {@link planAcross}. Plans the URL on every client in parallel (keeping which
|
|
5483
|
+
* client owns which rail), picks the rail `planAcross` names as `best` (the first
|
|
5484
|
+
* funded chain you listed that can settle RIGHT NOW), and pays it on its owning
|
|
5485
|
+
* client. So an agent that holds one wallet
|
|
5486
|
+
* per chain pays whichever chain/token the merchant's 402 asks for — with no
|
|
5487
|
+
* manual routing — while every payment still goes through that client's own
|
|
5488
|
+
* spend policy, `onBeforePay` hook, retries, and replay-protection (this just
|
|
5489
|
+
* calls the chosen client's {@link PipRailClient.fetch}).
|
|
5490
|
+
*
|
|
5491
|
+
* - A URL that needs no payment (no 402) is returned straight through.
|
|
5492
|
+
* - When NO funded chain can settle it, throws {@link PaymentDeclinedError} with a
|
|
5493
|
+
* merged, per-chain funding hint — BEFORE any on-chain send.
|
|
5494
|
+
*
|
|
5495
|
+
* Selection matches {@link planAcross}: payable-first, and across different native
|
|
5496
|
+
* coins (no price oracle) the FIRST chain you pass in `clients` that can settle wins
|
|
5497
|
+
* (your preference); within a chain, the cheapest-gas rail. It normally pays the rail
|
|
5498
|
+
* `planAcross` reports as `best`, but on a BEST-EFFORT basis — the owning client
|
|
5499
|
+
* re-reads its balances/gas at pay time, so a change between planning and paying (a
|
|
5500
|
+
* concurrent payment, RPC drift, the merchant returning a different 402) can make it
|
|
5501
|
+
* pick another settleable rail ON THE SAME CHAIN, or decline; its spend policy +
|
|
5502
|
+
* `onBeforePay` still gate whatever is actually paid. For the ergonomic object form,
|
|
5503
|
+
* see {@link MultiChainPayer}.
|
|
5504
|
+
*
|
|
5505
|
+
* NOTE: this PROBES the URL with the caller's `init` (method + body) on each client to
|
|
5506
|
+
* read the 402, so prefer it for GET / idempotent requests — a non-idempotent POST is
|
|
5507
|
+
* sent once per client before the pay leg (the x402 gate returns 402 without acting,
|
|
5508
|
+
* but the body is re-sent).
|
|
5509
|
+
*/
|
|
5510
|
+
declare function fetchAcross(clients: PipRailClient[], url: string, init?: RequestInit): Promise<Response>;
|
|
5511
|
+
|
|
5512
|
+
/**
|
|
5513
|
+
* MultiChainPayer — one buyer, many wallets, pay whatever the merchant asks.
|
|
5514
|
+
*
|
|
5515
|
+
* A {@link PipRailClient} is bound to exactly ONE chain and ONE wallet (an EVM key
|
|
5516
|
+
* can't sign a Solana tx, and vice-versa — that's enforced at bind time). So a
|
|
5517
|
+
* buyer who wants to pay a 402 *whatever chain/token it demands* holds one key per
|
|
5518
|
+
* chain. This is the ergonomic object that carries that bundle: give it a
|
|
5519
|
+
* `{ chain → wallet }` map and it builds one client per chain, then exposes a single
|
|
5520
|
+
* `fetch`/`get`/`post`/`plan`/`quote` that auto-routes to the first funded chain that
|
|
5521
|
+
* can settle — no manual "which client owns this rail?" plumbing.
|
|
5522
|
+
*
|
|
5523
|
+
* It is a thin, chain-agnostic composition over the existing primitives — it adds
|
|
5524
|
+
* NO new payment logic:
|
|
5525
|
+
* - `planPayment` → {@link planAcross} (merge every chain's plan, payable-first)
|
|
5526
|
+
* - `fetch`/`get`/`post` → {@link fetchAcross} (pay on the first chain that can settle)
|
|
5527
|
+
* Every payment still runs through its owning client's own spend policy,
|
|
5528
|
+
* `onBeforePay` hook, retries, and replay-protection. There is no cross-chain
|
|
5529
|
+
* custody, no price oracle, and no backend: across chains it pays the FIRST one you
|
|
5530
|
+
* list that can settle (your preference order — gas isn't comparable across coins);
|
|
5531
|
+
* within a chain it picks the cheapest-gas rail.
|
|
5532
|
+
*
|
|
5533
|
+
* Because it implements {@link PayingClient}, the agent toolkit ({@link paymentTools})
|
|
5534
|
+
* and the MCP server wrap it byte-identically to a single client.
|
|
5535
|
+
*/
|
|
5536
|
+
|
|
5537
|
+
/**
|
|
5538
|
+
* One wallet per chain you fund, keyed by chain selector. The KEY is a chain
|
|
5539
|
+
* string (an EVM preset like `'base'`/`'bnb'`, or a non-EVM family
|
|
5540
|
+
* `'solana'|'ton'|'tron'|'near'|'sui'|'aptos'|'algorand'|'stellar'|'xrpl'`); the
|
|
5541
|
+
* VALUE is that family's {@link WalletInput}:
|
|
5542
|
+
*
|
|
5543
|
+
* base/bnb/… → { privateKey } solana → { secretKey } ton/algorand → { mnemonic }
|
|
5544
|
+
* stellar → { secret } xrpl → { seed } near → { accountId, privateKey }
|
|
5545
|
+
*
|
|
5546
|
+
* One key per family — this map is how a single buyer carries the keys for every
|
|
5547
|
+
* chain it's willing to pay on. (For a CUSTOM EVM chain configured by a viem
|
|
5548
|
+
* `Chain` object, build the {@link PipRailClient} yourself and use
|
|
5549
|
+
* `new MultiChainPayer([...clients])`.)
|
|
5550
|
+
*/
|
|
5551
|
+
interface MultiChainPayerOptions {
|
|
5552
|
+
/** `{ chain → wallet }`. Iteration order is your chain PREFERENCE: across chains the
|
|
5553
|
+
* first one that can settle wins (there's no oracle to compare gas across coins). */
|
|
5554
|
+
wallets: Record<string, WalletInput>;
|
|
5555
|
+
/** Spend policy applied to EVERY chain's client. Each client still keeps its own
|
|
5556
|
+
* per-(network,asset) ledger — there is no cross-token sum (no price oracle). */
|
|
5557
|
+
policy?: PaymentPolicy;
|
|
5558
|
+
/** Per-chain RPC overrides, keyed by the same chain selector as `wallets`. */
|
|
5559
|
+
rpcUrls?: Record<string, string>;
|
|
5560
|
+
/** Which schemes every client may settle. Default `['onchain-proof']` (unchanged). */
|
|
5561
|
+
schemes?: PaymentScheme[];
|
|
5562
|
+
/** Final approval hook applied to every chain's client (fires before any send). */
|
|
5563
|
+
onBeforePay?: (quote: PipRailQuote) => boolean | Promise<boolean>;
|
|
5564
|
+
/** Observability hook applied to every chain's client. */
|
|
5565
|
+
onEvent?: (event: PipRailEvent) => void;
|
|
5566
|
+
/** Retry budget for the post-broadcast leg, per client. Default 3. */
|
|
5567
|
+
maxPaymentRetries?: number;
|
|
5568
|
+
/** Timeout (ms) for the retry leg, per client. Default 30_000. */
|
|
5569
|
+
retryTimeoutMs?: number;
|
|
5570
|
+
}
|
|
5571
|
+
declare class MultiChainPayer implements PayingClient {
|
|
5572
|
+
private readonly _clients;
|
|
5573
|
+
/**
|
|
5574
|
+
* Wrap an explicit, ordered set of single-chain clients — use this when a client
|
|
5575
|
+
* needs full control (e.g. a custom EVM chain configured by a viem `Chain`). The
|
|
5576
|
+
* ORDER is your chain preference: across chains the first that can settle wins. Pass
|
|
5577
|
+
* at MOST one client per chain — two clients on the SAME network would double-count in
|
|
5578
|
+
* `spent()`/`budget()` and waste a plan round-trip (`fromWallets` can't produce this).
|
|
5579
|
+
* For the common case, prefer {@link MultiChainPayer.fromWallets}.
|
|
5580
|
+
*/
|
|
5581
|
+
constructor(clients: PipRailClient[]);
|
|
5582
|
+
/**
|
|
5583
|
+
* Build one client per funded chain from a `{ chain → wallet }` map — the
|
|
5584
|
+
* ergonomic path. The shared `policy`/`schemes`/`onBeforePay`/`onEvent` apply to
|
|
5585
|
+
* every client; `rpcUrls` are matched per chain. Iteration order of `wallets` is
|
|
5586
|
+
* the chain preference.
|
|
5587
|
+
*
|
|
5588
|
+
* ```ts
|
|
5589
|
+
* const payer = MultiChainPayer.fromWallets({
|
|
5590
|
+
* wallets: {
|
|
5591
|
+
* base: { privateKey: process.env.EVM_KEY! },
|
|
5592
|
+
* solana: { secretKey: process.env.SOLANA_SECRET! },
|
|
5593
|
+
* xrpl: { seed: process.env.XRPL_SEED! },
|
|
5594
|
+
* },
|
|
5595
|
+
* policy: { maxAmount: '1.00', maxTotal: '20.00', tokens: ['USDC', 'USDT'] },
|
|
5596
|
+
* })
|
|
5597
|
+
* const res = await payer.get('https://api.example.com/paid') // pays on the first funded chain that can settle
|
|
5598
|
+
* ```
|
|
5599
|
+
*/
|
|
5600
|
+
static fromWallets(opts: MultiChainPayerOptions): MultiChainPayer;
|
|
5601
|
+
/** The underlying single-chain clients, in preference order. Reach for one of
|
|
5602
|
+
* these for chain-specific reads (`estimateCost`, `discoverySigner`, per-chain
|
|
5603
|
+
* `budget()`) that don't make sense merged. */
|
|
5604
|
+
get clients(): readonly PipRailClient[];
|
|
5605
|
+
/** Plan a 402 across every funded chain — merged + ranked payable-first. `null`
|
|
5606
|
+
* when the URL needs no payment. (Delegates to {@link planAcross}.) */
|
|
5607
|
+
planPayment(url: string, init?: RequestInit): Promise<PaymentPlan | null>;
|
|
5608
|
+
/** Can ANY funded chain settle this URL right now? (A free resource is trivially
|
|
5609
|
+
* "affordable".) No funds move. */
|
|
5610
|
+
canAfford(url: string, init?: RequestInit): Promise<boolean>;
|
|
5611
|
+
/** Price a gated URL across funded chains — the chosen rail's quote (the first
|
|
5612
|
+
* funded chain that can settle), else the first offered rail's. `null` when the URL
|
|
5613
|
+
* needs no payment. When it IS
|
|
5614
|
+
* gated but none of your chains are offered, surfaces the same informative
|
|
5615
|
+
* `NoCompatibleAcceptError` a single client would (it names the chains the 402 is
|
|
5616
|
+
* payable on) rather than a misleading `null`. No funds move. */
|
|
5617
|
+
quote(url: string, init?: RequestInit): Promise<PipRailQuote | null>;
|
|
5618
|
+
/** Pay the first funded chain (in your listed order) that can settle this URL.
|
|
5619
|
+
* Delegates to {@link fetchAcross} — full policy / approval / retry / replay path on
|
|
5620
|
+
* the owning client. The owner re-reads balances at pay time, so the rail paid is the
|
|
5621
|
+
* surfaced `best` on a best-effort basis (it can pick another rail on the SAME chain,
|
|
5622
|
+
* or decline, if balances shift between plan and pay). PROBES the URL with `init`
|
|
5623
|
+
* (method + body) per client — prefer GET / idempotent requests. */
|
|
5624
|
+
fetch(url: string, init?: RequestInit): Promise<Response>;
|
|
5625
|
+
/** GET that auto-pays across chains. */
|
|
5626
|
+
get(url: string, init?: RequestInit): Promise<Response>;
|
|
5627
|
+
/**
|
|
5628
|
+
* POST that auto-pays across chains. `body` is a string/FormData/URLSearchParams/
|
|
5629
|
+
* ArrayBuffer/Blob (sent as-is) or a plain object (serialised as JSON) — mirrors
|
|
5630
|
+
* {@link PipRailClient.post}.
|
|
5631
|
+
*/
|
|
5632
|
+
post(url: string, body?: BodyInit | object | undefined, init?: RequestInit): Promise<Response>;
|
|
5633
|
+
/**
|
|
5634
|
+
* Find payable resources across every funded chain. With the default
|
|
5635
|
+
* `network: 'self'`, each chain's own results are merged + deduped by URL (so
|
|
5636
|
+
* "self" means "any chain I can pay"). A network-scoped query (a CAIP-2 id or
|
|
5637
|
+
* `'any'`) is chain-independent, so one client answers it. Never throws for a
|
|
5638
|
+
* read problem; moves no funds.
|
|
5639
|
+
*/
|
|
5640
|
+
discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
|
|
5641
|
+
/** List a resource YOU run on the open indexes. Registration is a merchant action
|
|
5642
|
+
* independent of which chain you pay FROM, so it goes through your first chain's
|
|
5643
|
+
* client; pass `opts.network` to advertise a specific chain. Moves no funds. */
|
|
5644
|
+
register(url: string, opts?: RegisterOptions): Promise<RegisterOutcome[]>;
|
|
5645
|
+
/** Aggregate spend across every chain — counts summed; per-(network,asset) rows
|
|
5646
|
+
* and records concatenated (no cross-chain collisions, never a cross-token sum). */
|
|
5647
|
+
spent(): SpendSummary;
|
|
5648
|
+
/** A merged budget view: every chain's per-(network,asset) remaining rows, plus the
|
|
5649
|
+
* MOST-RESTRICTIVE session time envelope across chains (the soonest deadline wins).
|
|
5650
|
+
* Mirrors {@link PipRailClient.budget}'s shape so the agent toolkit reads it
|
|
5651
|
+
* unchanged; per-chain session detail is on each `clients[i].budget()`. */
|
|
5652
|
+
budget(): SessionBudget;
|
|
5653
|
+
}
|
|
5461
5654
|
|
|
5462
5655
|
/**
|
|
5463
5656
|
* MCP-style tool annotations — optional, advisory hints that let an MCP client or
|
|
@@ -5514,7 +5707,7 @@ interface AgentTool {
|
|
|
5514
5707
|
* declined? }`) — never a thrown error — so the model reasons about it (and never
|
|
5515
5708
|
* re-pays a broadcast-but-unconfirmed payment) instead of crashing.
|
|
5516
5709
|
*/
|
|
5517
|
-
declare function paymentTools(client:
|
|
5710
|
+
declare function paymentTools(client: PayingClient): AgentTool[];
|
|
5518
5711
|
|
|
5519
5712
|
/**
|
|
5520
5713
|
* One line summarising a {@link PaymentPlan} for a model: what's payable, on which
|
|
@@ -5538,6 +5731,15 @@ declare function explainDecline(err: unknown): string;
|
|
|
5538
5731
|
* convenience, not a durable ledger.
|
|
5539
5732
|
*/
|
|
5540
5733
|
declare function formatSpendReport(summary: SpendSummary): string;
|
|
5734
|
+
/**
|
|
5735
|
+
* One line a human or model can act on for a 402 challenge: what it is, the first
|
|
5736
|
+
* rail's amount/token/chain + recipient, and how to pay it programmatically. Composes
|
|
5737
|
+
* only shipped challenge fields (same `amountFormatted ?? amount` / `symbol ?? asset`
|
|
5738
|
+
* convention as the renderers above) — pure, no I/O. Used as the human `instruction`
|
|
5739
|
+
* inside the self-describe block and as a landing page's headline. An empty `accepts`
|
|
5740
|
+
* (shouldn't happen for a valid v2 challenge) degrades to a generic pointer.
|
|
5741
|
+
*/
|
|
5742
|
+
declare function describeChallenge(challenge: X402Challenge): string;
|
|
5541
5743
|
|
|
5542
5744
|
/**
|
|
5543
5745
|
* The PipRail agent contract, distilled into one string an LLM can read once and
|
|
@@ -5550,7 +5752,7 @@ declare function formatSpendReport(summary: SpendSummary): string;
|
|
|
5550
5752
|
* literally, so a wrong name or order actively misleads. A test pins the load-
|
|
5551
5753
|
* bearing phrases.
|
|
5552
5754
|
*/
|
|
5553
|
-
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";
|
|
5755
|
+
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, 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";
|
|
5554
5756
|
/** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
|
|
5555
5757
|
declare function agentGuide(): string;
|
|
5556
5758
|
|
|
@@ -5588,6 +5790,104 @@ declare function classifyChallenge(challenge: X402Challenge, opts: {
|
|
|
5588
5790
|
schemes: readonly PaymentScheme[];
|
|
5589
5791
|
}): ChallengeTriage;
|
|
5590
5792
|
|
|
5793
|
+
/**
|
|
5794
|
+
* Self-description — make a PipRail 402 announce WHAT it is and HOW to pay it, to
|
|
5795
|
+
* humans, AI agents, and crawlers alike, on BOTH schemes. PURE: a builder that turns
|
|
5796
|
+
* the `accepts[]` a gate already resolved into an inert, additive metadata block; it
|
|
5797
|
+
* does NO I/O and imports NO chain library (protocol layer — STANDARDS §1, viem-free).
|
|
5798
|
+
*
|
|
5799
|
+
* The block rides at `challenge.extensions.piprail`, ALONGSIDE the rejection
|
|
5800
|
+
* `{ code, detail }` (the gate deep-merges so neither clobbers the other). x402 v2
|
|
5801
|
+
* treats `extensions` as an opaque bag a standard client ignores, so this is
|
|
5802
|
+
* purely-additive: the pay path, `accepts[]`, headers, and status stay byte-identical.
|
|
5803
|
+
*
|
|
5804
|
+
* Its whole point: even an `onchain-proof`-only endpoint that a stock x402 client
|
|
5805
|
+
* CANNOT pay is no longer invisible — a stranger reads `sdk.install`, runs
|
|
5806
|
+
* `npm i @piprail/sdk`, pastes the snippet, and pays. For the non-EVM families that
|
|
5807
|
+
* have NO standard `exact` rail, this block is the ENTIRE interop story, so the
|
|
5808
|
+
* `onchain-proof` instruction is deliberately chain-agnostic.
|
|
5809
|
+
*
|
|
5810
|
+
* NOT WIRED here — this is the pure builder (discoverability plan, Phase 1). The gate
|
|
5811
|
+
* wires it into every challenge in Phase 5 (default-on, with a `selfDescribe:false`
|
|
5812
|
+
* opt-out that restores the byte-identical default).
|
|
5813
|
+
*/
|
|
5814
|
+
|
|
5815
|
+
/**
|
|
5816
|
+
* The canonical PipRail brand strings — the SINGLE source of truth for the install
|
|
5817
|
+
* command, the paste-ready snippet, and the docs links, read by the self-describe
|
|
5818
|
+
* block here, and (later phases) the landing page, the `llms.txt` entry, and the
|
|
5819
|
+
* agent guide. `<your-chain>` / `<this-url>` are deliberate placeholders — never guess
|
|
5820
|
+
* the reader's chain or URL.
|
|
5821
|
+
*/
|
|
5822
|
+
declare const BRAND: {
|
|
5823
|
+
readonly name: "PipRail";
|
|
5824
|
+
readonly home: "https://piprail.com";
|
|
5825
|
+
readonly docs: "https://docs.piprail.com";
|
|
5826
|
+
readonly payDocs: "https://docs.piprail.com/paying";
|
|
5827
|
+
readonly sdkInstall: "npm i @piprail/sdk";
|
|
5828
|
+
readonly sdkSnippet: string;
|
|
5829
|
+
readonly mcpRun: "npx -y @piprail/mcp";
|
|
5830
|
+
};
|
|
5831
|
+
/**
|
|
5832
|
+
* One payable rail as the self-describe block presents it — the static, agent- and
|
|
5833
|
+
* human-readable view of an `accepts[]` entry (no nonce; this is long-lived metadata).
|
|
5834
|
+
*/
|
|
5835
|
+
interface SelfDescribeRail {
|
|
5836
|
+
scheme: 'onchain-proof' | 'exact';
|
|
5837
|
+
network: string;
|
|
5838
|
+
asset: string;
|
|
5839
|
+
payTo: string;
|
|
5840
|
+
/** Amount in the token's base units (already scaled by decimals). */
|
|
5841
|
+
amount: string;
|
|
5842
|
+
/** Human-readable amount, e.g. "0.01", when the gate resolved one. */
|
|
5843
|
+
amountFormatted?: string;
|
|
5844
|
+
symbol?: string;
|
|
5845
|
+
/** A one-line instruction for paying THIS rail — chain-agnostic for `onchain-proof`. */
|
|
5846
|
+
how: string;
|
|
5847
|
+
}
|
|
5848
|
+
/** The `extensions.piprail` self-description block. Inert, purely-additive metadata. */
|
|
5849
|
+
interface SelfDescription {
|
|
5850
|
+
name: 'PipRail';
|
|
5851
|
+
protocol: 'x402';
|
|
5852
|
+
version: '2';
|
|
5853
|
+
/** One sentence: what this endpoint is. */
|
|
5854
|
+
what: string;
|
|
5855
|
+
/** Every rail the 402 offers, in the same order as `accepts[]`. */
|
|
5856
|
+
pay: SelfDescribeRail[];
|
|
5857
|
+
/** How to pay programmatically with the SDK. */
|
|
5858
|
+
sdk: {
|
|
5859
|
+
install: string;
|
|
5860
|
+
snippet: string;
|
|
5861
|
+
};
|
|
5862
|
+
/** How to pay via the MCP server (for AI agents). */
|
|
5863
|
+
mcp: {
|
|
5864
|
+
run: string;
|
|
5865
|
+
tool: string;
|
|
5866
|
+
};
|
|
5867
|
+
docs: {
|
|
5868
|
+
home: string;
|
|
5869
|
+
agents: string;
|
|
5870
|
+
pay: string;
|
|
5871
|
+
};
|
|
5872
|
+
/** Where the open discovery artifacts live on this origin. */
|
|
5873
|
+
discovery: {
|
|
5874
|
+
openapi: string;
|
|
5875
|
+
wellKnown: string;
|
|
5876
|
+
};
|
|
5877
|
+
/** A one-line human summary (the gate sets it from `describeChallenge`). */
|
|
5878
|
+
instruction?: string;
|
|
5879
|
+
}
|
|
5880
|
+
/**
|
|
5881
|
+
* Build the `extensions.piprail` self-describe block from a challenge's resolved
|
|
5882
|
+
* `accepts[]`. PURE — every rail is derived from data the gate already has (no new
|
|
5883
|
+
* data, no I/O). `instruction` is the optional one-line human summary the gate computes
|
|
5884
|
+
* via `describeChallenge` (in `render.ts`) and passes in.
|
|
5885
|
+
*/
|
|
5886
|
+
declare function buildSelfDescription(input: {
|
|
5887
|
+
accepts: X402AnyAccept[];
|
|
5888
|
+
instruction?: string;
|
|
5889
|
+
}): SelfDescription;
|
|
5890
|
+
|
|
5591
5891
|
/**
|
|
5592
5892
|
* Discovery — make a gated resource FINDABLE, by emitting the open-standard
|
|
5593
5893
|
* artifacts a crawler/index reads. PURE: this file turns the config a gate
|
|
@@ -5670,6 +5970,28 @@ interface ManifestInput {
|
|
|
5670
5970
|
}
|
|
5671
5971
|
/** What `x-generator` stamps when attribution is on — see {@link ManifestInput.attribution}. */
|
|
5672
5972
|
declare const GENERATOR = "@piprail/sdk \u00B7 https://piprail.com";
|
|
5973
|
+
/**
|
|
5974
|
+
* The "powered by" marker for the `x-powered-by` HTTP header — the response-side twin of the
|
|
5975
|
+
* `/openapi.json` {@link GENERATOR} stamp. Inert metadata; opt out with `attribution:false`.
|
|
5976
|
+
* **ASCII-only on purpose:** this is an HTTP header value, and Node's `setHeader` writes header
|
|
5977
|
+
* values as latin1 — a non-ASCII separator (e.g. `·` U+00B7) would arrive mangled (`·`) and is
|
|
5978
|
+
* RFC-7230-discouraged. {@link GENERATOR} keeps its `·` because it only lands in UTF-8 JSON bodies.
|
|
5979
|
+
*/
|
|
5980
|
+
declare const POWERED_BY = "PipRail x402 | https://piprail.com";
|
|
5981
|
+
/**
|
|
5982
|
+
* Machine-readable discovery pointers for a gated endpoint's HTTP responses — a `Link` header
|
|
5983
|
+
* (RFC 8288) pointing crawlers/agents at the discovery docs, plus a tasteful `x-powered-by`
|
|
5984
|
+
* marker. Spread the result into BOTH the 402 challenge response AND the 200 settlement
|
|
5985
|
+
* response, so a payer / agent / crawler learns what served them on every hit (this is also
|
|
5986
|
+
* how the 200 "receipt" self-advertises — no change to the `X402Receipt` body needed). PURE —
|
|
5987
|
+
* returns a header bag the merchant sets; the SDK serves nothing. `attribution:false` omits
|
|
5988
|
+
* `x-powered-by` (parity with the `x-generator` opt-out on the OpenAPI doc). If you already set
|
|
5989
|
+
* a `Link` header, comma-merge it with this one rather than blindly spreading (object spread
|
|
5990
|
+
* would replace it).
|
|
5991
|
+
*/
|
|
5992
|
+
declare function discoveryHeaders(opts?: {
|
|
5993
|
+
attribution?: boolean;
|
|
5994
|
+
}): Record<string, string>;
|
|
5673
5995
|
/** A minimal, valid OpenAPI 3.1 document carrying `x-payment-info` per paid op. */
|
|
5674
5996
|
interface OpenApiDocument {
|
|
5675
5997
|
openapi: '3.1.0';
|
|
@@ -5940,6 +6262,17 @@ interface RequirePaymentOptions {
|
|
|
5940
6262
|
* challenge byte-identical to before.
|
|
5941
6263
|
*/
|
|
5942
6264
|
discovery?: boolean | DiscoveryDescriptor;
|
|
6265
|
+
/**
|
|
6266
|
+
* Self-describe every 402 — stamp an `extensions.piprail` block (identity · per-rail
|
|
6267
|
+
* how-to-pay · `npm i @piprail/sdk` + snippet · MCP · docs + discovery pointers) so the
|
|
6268
|
+
* instant any human, AI agent, or crawler lands on this endpoint — even the default
|
|
6269
|
+
* `onchain-proof` scheme a stock x402 client can't pay — it knows what it is and how to
|
|
6270
|
+
* pay it. **Default `true`.** It is purely-additive metadata a standard client ignores
|
|
6271
|
+
* (the spec treats `extensions` as opaque), so the pay path, `accepts[]`, headers, and
|
|
6272
|
+
* status are byte-identical. Set `false` to omit the block entirely (the literal
|
|
6273
|
+
* byte-identical default of before this feature). See {@link buildSelfDescription}.
|
|
6274
|
+
*/
|
|
6275
|
+
selfDescribe?: boolean;
|
|
5943
6276
|
}
|
|
5944
6277
|
type VerifyPaymentResult = {
|
|
5945
6278
|
kind: 'paid';
|
|
@@ -6003,6 +6336,13 @@ interface PaymentGate {
|
|
|
6003
6336
|
* discovery metadata is long-lived. Read-only — moves nothing on-chain.
|
|
6004
6337
|
*/
|
|
6005
6338
|
describe(resourceUrl?: string): Promise<ResourceDescription>;
|
|
6339
|
+
/**
|
|
6340
|
+
* Render a self-describing HTML page for a challenge — for the HUMAN who opens the gated
|
|
6341
|
+
* URL in a browser. Pass the challenge you already built with {@link PaymentGate.challenge};
|
|
6342
|
+
* serve the result with `content-type: text/html` when the request's `Accept` is `text/html`.
|
|
6343
|
+
* The SDK never serves it itself (headless by charter). Agents/crawlers keep the JSON 402.
|
|
6344
|
+
*/
|
|
6345
|
+
landingPage(challenge: X402Challenge): string;
|
|
6006
6346
|
}
|
|
6007
6347
|
/**
|
|
6008
6348
|
* Framework-agnostic core. Build one gate per gated resource and reuse it
|
|
@@ -6062,6 +6402,28 @@ interface FacilitatorPaymentRequirements {
|
|
|
6062
6402
|
maxTimeoutSeconds: number;
|
|
6063
6403
|
extra: Record<string, unknown>;
|
|
6064
6404
|
}
|
|
6405
|
+
/** One (scheme, network) pair a facilitator's `GET /supported` advertises. */
|
|
6406
|
+
interface FacilitatorSupportedKind {
|
|
6407
|
+
scheme: string;
|
|
6408
|
+
/** As the facilitator reports it — a CAIP-2 id or a slug. */
|
|
6409
|
+
network: string;
|
|
6410
|
+
/** The fee-payer pubkey when the kind carries one (SVM rails). */
|
|
6411
|
+
feePayer?: string;
|
|
6412
|
+
}
|
|
6413
|
+
/**
|
|
6414
|
+
* Parse a facilitator `/supported` body into its advertised (scheme, network) kinds.
|
|
6415
|
+
* PURE + tolerant: a malformed body yields `[]`. Mirrors the `{ kinds: [...] }` shape
|
|
6416
|
+
* {@link fetchFacilitatorFeePayer} reads. Useful for verifying coverage before wiring a gate,
|
|
6417
|
+
* and for generating the coverage doc from live reads.
|
|
6418
|
+
*/
|
|
6419
|
+
declare function parseFacilitatorSupported(body: unknown): FacilitatorSupportedKind[];
|
|
6420
|
+
/**
|
|
6421
|
+
* Read a facilitator's LIVE coverage from `GET /supported`. Best-effort + bounded (an
|
|
6422
|
+
* `AbortController` timeout): NEVER throws — returns `[]` on any failure (same posture as
|
|
6423
|
+
* {@link fetchFacilitatorFeePayer}). Lets an operator/agent ask "does this facilitator
|
|
6424
|
+
* cover my network?" before wiring a gate. Pure `fetch`, no chain libraries (STANDARDS §1).
|
|
6425
|
+
*/
|
|
6426
|
+
declare function facilitatorCoverage(url: string, timeoutMs?: number): Promise<FacilitatorSupportedKind[]>;
|
|
6065
6427
|
/** A merchant-chosen facilitator: its base URL + optional per-request auth headers. */
|
|
6066
6428
|
interface FacilitatorConfig {
|
|
6067
6429
|
/** Base URL, e.g. 'https://x402.org/facilitator' (trailing slash stripped). */
|
|
@@ -6094,6 +6456,51 @@ interface SettleViaFacilitatorInput extends FacilitatorConfig {
|
|
|
6094
6456
|
*/
|
|
6095
6457
|
declare function settleViaFacilitator(input: SettleViaFacilitatorInput): Promise<VerifyResult>;
|
|
6096
6458
|
|
|
6459
|
+
/**
|
|
6460
|
+
* Facilitator coverage — the honest, chain-agnostic DATA map of which third-party x402
|
|
6461
|
+
* facilitators settle the `exact` scheme on which networks. PURE DATA: imports only the
|
|
6462
|
+
* `Caip2` type from `x402.ts` — zero chain libraries (protocol layer, STANDARDS §1).
|
|
6463
|
+
*
|
|
6464
|
+
* Why it exists: the `exact: true` shorthand (discoverability plan, Phase 7) and an
|
|
6465
|
+
* operator picking a facilitator both need to know "is there a known KEYLESS facilitator
|
|
6466
|
+
* for my chain?" — WITHOUT a hosted registry (charter: no backend). This map is the SEED;
|
|
6467
|
+
* the live truth is `facilitatorCoverage(url)` in `facilitator.ts`, which reads a
|
|
6468
|
+
* facilitator's `GET /supported`. The map is grown ONLY from a verified `/supported`
|
|
6469
|
+
* read — every entry carries a dated verification comment, never a guess.
|
|
6470
|
+
*/
|
|
6471
|
+
|
|
6472
|
+
/** One facilitator known to settle `exact` on a given network. */
|
|
6473
|
+
interface KnownFacilitator {
|
|
6474
|
+
/** Base URL (no trailing slash), e.g. `https://facilitator.payai.network`. */
|
|
6475
|
+
url: string;
|
|
6476
|
+
/** True when it needs NO API key — buyer AND merchant pay zero gas (the facilitator sponsors it). */
|
|
6477
|
+
keyless: boolean;
|
|
6478
|
+
/** The x402 schemes it settles (today only `exact`). */
|
|
6479
|
+
schemes: ReadonlyArray<'exact'>;
|
|
6480
|
+
/** The exact transfer methods it can settle on this network. */
|
|
6481
|
+
settles: ReadonlyArray<'eip3009' | 'permit2' | 'svm'>;
|
|
6482
|
+
/** A short human note (who it is / caveat). */
|
|
6483
|
+
note?: string;
|
|
6484
|
+
}
|
|
6485
|
+
/**
|
|
6486
|
+
* Seed map: CAIP-2 network → facilitators that settle `exact` there. Deliberately
|
|
6487
|
+
* CONSERVATIVE — only endpoint-verified entries. Extend it only after a live
|
|
6488
|
+
* `facilitatorCoverage()` read confirms a new (facilitator, network) pair. A merchant on
|
|
6489
|
+
* a network not listed here passes an explicit `exact: { settle: { facilitator } }`.
|
|
6490
|
+
*
|
|
6491
|
+
* NOTE: `x402.org/facilitator` is intentionally ABSENT — it is a Base **Sepolia** testnet
|
|
6492
|
+
* facilitator (verified), not a mainnet rail; seeding it would be a false coverage claim.
|
|
6493
|
+
*/
|
|
6494
|
+
declare const KNOWN_FACILITATORS: Readonly<Record<Caip2, ReadonlyArray<KnownFacilitator>>>;
|
|
6495
|
+
/** Known facilitators for a network — an empty array when none is seeded. */
|
|
6496
|
+
declare function knownFacilitatorsFor(network: Caip2): ReadonlyArray<KnownFacilitator>;
|
|
6497
|
+
/**
|
|
6498
|
+
* The first KEYLESS facilitator that settles `exact` on `network` (optionally for a
|
|
6499
|
+
* specific transfer `method`). Returns `undefined` when none is known — the `exact: true`
|
|
6500
|
+
* shorthand branches on that to throw a coverage-specific guidance error.
|
|
6501
|
+
*/
|
|
6502
|
+
declare function firstKeylessFacilitator(network: Caip2, method?: 'eip3009' | 'permit2' | 'svm'): KnownFacilitator | undefined;
|
|
6503
|
+
|
|
6097
6504
|
/**
|
|
6098
6505
|
* Reliable receipt delivery — the durable webhook a stateless gate can't be.
|
|
6099
6506
|
*
|
|
@@ -6793,4 +7200,28 @@ declare const PERMIT2_WITNESS_TYPES: {
|
|
|
6793
7200
|
}];
|
|
6794
7201
|
};
|
|
6795
7202
|
|
|
6796
|
-
|
|
7203
|
+
/**
|
|
7204
|
+
* Landing page — a tiny, self-contained HTML representation of a 402, for the HUMAN
|
|
7205
|
+
* who opens a gated URL in a browser (agents/crawlers still get the unchanged JSON 402).
|
|
7206
|
+
* PURE string templating; imports only the `SelfDescription` type — zero I/O, zero chain
|
|
7207
|
+
* libraries (protocol layer, STANDARDS §1).
|
|
7208
|
+
*
|
|
7209
|
+
* The SDK NEVER serves this itself (it's headless by charter). The merchant opts in by
|
|
7210
|
+
* branching on the request's `Accept` header in their own handler and returning this
|
|
7211
|
+
* string with `content-type: text/html`. See `gate.landingPage(challenge)`.
|
|
7212
|
+
*
|
|
7213
|
+
* SECURITY: every interpolated field is HTML-escaped (a `payTo` / instruction can be
|
|
7214
|
+
* merchant- or rail-influenced) — global rule: escape all user-/data-influenced content.
|
|
7215
|
+
*/
|
|
7216
|
+
|
|
7217
|
+
/**
|
|
7218
|
+
* Render a self-describing HTML 402 landing page from a {@link SelfDescription}. Leads with the
|
|
7219
|
+
* one-line instruction and a prominent CAUTION — payment must go through an x402 client; a manual
|
|
7220
|
+
* send to the address won't unlock the resource and isn't matched to the request (it lands in the
|
|
7221
|
+
* merchant's wallet uncredited). Then the primary "How to pay" (the `npm i @piprail/sdk` install +
|
|
7222
|
+
* paste-ready snippet + MCP command), and finally the per-rail "Payment details" table (scheme ·
|
|
7223
|
+
* chain · amount · settles-to) for transparency. Fully static — no script, no external asset.
|
|
7224
|
+
*/
|
|
7225
|
+
declare function renderLandingPage(sd: SelfDescription): string;
|
|
7226
|
+
|
|
7227
|
+
export { type AcceptOption, type AddressId, type AgentTool, type AlgorandToken, type AptosToken, type AssetId, BRAND, type BazaarExtension, type BuildExactParams, CHAINS, type Caip2, type ChainFamily, type ChainInput, type ChainName, type ChainPreset, type ChainSelector, type ChallengeTriage, type ChallengeVerdict, type ConfirmInfo, ConfirmationTimeoutError, type CostEstimate, DIRECTORY_INFO, type DeclineReasonCode, type DeliverAttempt, type DeliverReceiptOptions, type DeliverResult, type DirectoryInfo, type DiscoverOptions, type DiscoveredRail, type DiscoveredResource, type DiscoveryDescriptor, type DiscoverySigner, type DiscoverySource, type DomainClaim, type DomainVerification, EIP3009_TYPES, EXACT_NETWORK_SLUGS, type EvmToken, type ExactAccept, type ExactAuthorization, type ExactAuthorizationWire, type ExactPaymentPayload, type ExactPaymentPayloadAny, type ExactRailOption, type ExpressLikeMiddleware, type ExpressLikeNext, type ExpressLikeRequest, type ExpressLikeResponse, type FacilitatorConfig, type FacilitatorPaymentRequirements, type FacilitatorSupportedKind, GENERATOR, HEADER_REQUIRED, HEADER_RESPONSE, HEADER_RESPONSE_V1, HEADER_SIGNATURE, HEADER_SIGNATURE_V1, 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, type PaidReceipt, type ParsedExactPayment, type PayBlocker, type PayOption, type PayWarning, type PayingClient, PaymentDeclinedError, type PaymentDriver, type PaymentGate, type PaymentIntent, type PaymentPlan, type PaymentPolicy, type PaymentRail, type PaymentScheme, PaymentTimeoutError, type Permit2Authorization, type Permit2PaymentPayload, PipRailClient, type PipRailClientOptions, type PipRailCostQuote, PipRailError, type PipRailEvent, type PipRailQuote, type PolicyDecision, type PolicyDenyCode, 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 SelfDescribeRail, type SelfDescription, type SessionBudget, type SettleOutcome, type SettleViaFacilitatorInput, SettlementError, type SolanaToken, type SpendAssetTotal, type SpendRecord, type SpendRemaining, type SpendSummary, type StellarToken, type SuiToken, type TokenInfo, type TokenInput, type TonToken, type ToolAnnotations, type TronToken, UnknownTokenError, UnsupportedNetworkError, UnsupportedSchemeError, type VerifyErrorCode, type VerifyPaymentResult, type VerifyResult, type WalletBalance, type WalletHandle, type WalletInput, WalletRequiredError, type WellKnownX402, WrongChainError, WrongFamilyError, type X402AcceptEntry, type X402AnyAccept, type X402Challenge, type X402DnsRecord, type X402ExactAcceptEntry, type X402InvalidBody, type X402PaymentSignature, type X402Receipt, type X402ResourceObject, X402_EXACT_PERMIT2_PROXY, type XrplToken, agentGuide, appendAttribution, buildBazaarExtension, buildChallengeHeader, buildExactAuthorization, buildExactSignatureHeader, buildOpenApi, buildReceiptHeader, buildSelfDescription, buildSignatureHeader, buildWellKnownX402, buildX402DnsTxt, chainIdForExactNetwork, claim402IndexDomain, classifyChallenge, createPaymentGate, decorateOutcome, deliverReceipt, describeChallenge, discoveryHeaders, eip3009Abi, encodeXPaymentHeader, evaluatePolicy, explainDecline, facilitatorCoverage, fetchAcross, firstKeylessFacilitator, formatSpendReport, getDirectoryInfo, isPermit2ProxyChain, knownFacilitatorsFor, normalizeNetwork, parseChallenge, parseExactPaymentHeader, parseExactRequirements, parseFacilitatorSupported, parseReceipt, parseSettleResponse, parseSignatureHeader, paymentTools, pickAccept, planAcross, readExactDomain, register402Index, registerDriver, registerX402Scan, renderLandingPage, requirePayment, resolveChain, searchOpenIndexes, settleViaFacilitator, summarizePlan, toInsufficientFundsError, toInvalidBody, verify402IndexDomain };
|