@piprail/sdk 2.3.0 → 2.4.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 +99 -0
- package/dist/algorand-TMA62DN2.cjs +678 -0
- package/dist/algorand-WB6PBJU4.js +678 -0
- package/dist/aptos-JQMZNTMD.cjs +673 -0
- package/dist/aptos-QAAXIUY3.js +673 -0
- package/dist/index.cjs +161 -17
- package/dist/index.d.cts +73 -23
- package/dist/index.d.ts +73 -23
- package/dist/index.js +158 -14
- package/dist/{solana-E4MD6JJ6.js → solana-3FMCWSEE.js} +20 -0
- package/dist/{solana-TLHL2KNY.cjs → solana-M3VOHCMO.cjs} +20 -0
- package/package.json +1 -1
- package/dist/algorand-GSFVZTBF.js +0 -389
- package/dist/algorand-HZS43N4P.cjs +0 -389
- package/dist/aptos-RIL56C7L.js +0 -352
- package/dist/aptos-TRCCJRZA.cjs +0 -352
package/dist/index.d.ts
CHANGED
|
@@ -88,8 +88,14 @@ interface X402ExactAcceptEntry {
|
|
|
88
88
|
* `spender` is the canonical x402ExactPermit2Proxy and whose `witness.to` binds the
|
|
89
89
|
* recipient. **Solana (SVM): `'svm'`** — the payer partial-signs an SPL
|
|
90
90
|
* `TransferChecked` transaction whose fee payer is the merchant (`feePayer` below),
|
|
91
|
-
* and the gate co-signs as fee payer + broadcasts.
|
|
92
|
-
|
|
91
|
+
* and the gate co-signs as fee payer + broadcasts. **Algorand: `'algorand'`** — the payer
|
|
92
|
+
* signs an ASA `axfer` to `payTo` at fee 0, atomically grouped with a 0-ALGO `pay` from
|
|
93
|
+
* the `feePayer` that pools the group fee (per `scheme_exact_algo.md`); the gate (or a
|
|
94
|
+
* keyless facilitator) signs that fee txn + submits. **Aptos: `'aptos'`** — the payer signs a
|
|
95
|
+
* fee-payer (sponsored) `primary_fungible_store::transfer` to `payTo` (per
|
|
96
|
+
* `scheme_exact_aptos.md`); the gate (or a keyless facilitator) adds the fee-payer signature
|
|
97
|
+
* + submits, paying gas. PipRail self-settles ALL. */
|
|
98
|
+
assetTransferMethod: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos';
|
|
93
99
|
/** EIP-712 domain name of the token. OPTIONAL per the exact-EVM scheme (only
|
|
94
100
|
* `assetTransferMethod` is required) — a foreign rail may omit it. NEVER assumed
|
|
95
101
|
* from the symbol (USDC's on-chain name() is "USD Coin", not "USDC"); a PipRail gate
|
|
@@ -97,11 +103,12 @@ interface X402ExactAcceptEntry {
|
|
|
97
103
|
name?: string;
|
|
98
104
|
/** EIP-712 domain version of the token (USDC: "2"). OPTIONAL (see `name`); read/re-derived on-chain. */
|
|
99
105
|
version?: string;
|
|
100
|
-
/** **SVM
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
106
|
+
/** **SVM / Algorand / Aptos** — the fee-payer (gas sponsor) address. The buyer builds the
|
|
107
|
+
* transaction with this account as the gas payer (so the buyer spends ZERO native coin),
|
|
108
|
+
* leaving its signature for whoever sponsors; the gate (self mode) or a keyless facilitator
|
|
109
|
+
* fills it and submits. On **SVM** it must differ from `payTo` (the fee payer must never
|
|
110
|
+
* appear in an instruction — a MUST-rule); on **Algorand/Aptos** the fee txn/signature is
|
|
111
|
+
* separate from the transfer, so `feePayer === payTo` is allowed. */
|
|
105
112
|
feePayer?: string;
|
|
106
113
|
/** **SVM only, OPTIONAL** — a ≤256-byte reconciliation memo the buyer attaches to the
|
|
107
114
|
* transaction (the SVM scheme's optional `extra.memo`). */
|
|
@@ -216,9 +223,41 @@ interface Permit2PaymentPayload {
|
|
|
216
223
|
interface ExactSvmPaymentPayload {
|
|
217
224
|
transaction: string;
|
|
218
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* The `payload` a client sends for the **Algorand `exact`** variant, per
|
|
228
|
+
* `scheme_exact_algo.md`: an atomically-grouped set of base64-encoded msgpack transactions,
|
|
229
|
+
* and the index within it of the transaction that pays the resource server. The buyer's ASA
|
|
230
|
+
* `axfer` (to `payTo`, fee 0) is SIGNED; a 0-ALGO `pay` from the `feePayer` that pools the
|
|
231
|
+
* group fee is left UNSIGNED for whoever sponsors (the gate's relayer in self mode, or a
|
|
232
|
+
* keyless facilitator). The group itself IS the proof — there's no separate authorization
|
|
233
|
+
* object (the Algorand analogue of EIP-3009's `authorization` / SVM's `transaction`).
|
|
234
|
+
*/
|
|
235
|
+
interface ExactAlgorandPaymentPayload {
|
|
236
|
+
/** Index into `paymentGroup` of the txn that pays the resource server (the buyer's `axfer`). */
|
|
237
|
+
paymentIndex: number;
|
|
238
|
+
/** The atomic group: each element is a base64-encoded, msgpack-encoded (signed or unsigned)
|
|
239
|
+
* Algorand transaction. ≤ 16 elements (the protocol's atomic-group cap). */
|
|
240
|
+
paymentGroup: string[];
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* The `payload` a client sends for the **Aptos `exact`** variant, per `scheme_exact_aptos.md`:
|
|
244
|
+
* a fee-payer (sponsored, AIP-39) `primary_fungible_store::transfer`. `transaction` is the base64
|
|
245
|
+
* BCS-serialized `SimpleTransaction` (raw tx + the bound `feePayerAddress`); `senderAuth` is the
|
|
246
|
+
* base64 BCS-serialized buyer (sender) authenticator. The buyer leaves the fee-payer signature for
|
|
247
|
+
* whoever sponsors (the gate's relayer in self mode, or a keyless facilitator), who adds it +
|
|
248
|
+
* submits. The (tx + sender authenticator) IS the proof — there's no separate `authorization`
|
|
249
|
+
* object (the Aptos analogue of EIP-3009's `authorization` / SVM's `transaction`). The two-field
|
|
250
|
+
* shape (a `senderAuth` alongside `transaction`) also distinguishes it from the SVM payload.
|
|
251
|
+
*/
|
|
252
|
+
interface ExactAptosPaymentPayload {
|
|
253
|
+
/** Base64 BCS-serialized `SimpleTransaction` (raw transaction + the bound `feePayerAddress`). */
|
|
254
|
+
transaction: string;
|
|
255
|
+
/** Base64 BCS-serialized buyer (sender) `AccountAuthenticator`. */
|
|
256
|
+
senderAuth: string;
|
|
257
|
+
}
|
|
219
258
|
/** Any `exact`-rail payload shape — EIP-3009 (`authorization`), Permit2 (`permit2Authorization`),
|
|
220
|
-
* or
|
|
221
|
-
type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload;
|
|
259
|
+
* SVM (`transaction`), Algorand (`paymentGroup`), or Aptos (`transaction` + `senderAuth`). */
|
|
260
|
+
type ExactPaymentPayloadAny = ExactPaymentPayload | Permit2PaymentPayload | ExactSvmPaymentPayload | ExactAlgorandPaymentPayload | ExactAptosPaymentPayload;
|
|
222
261
|
interface ParsedExactBase {
|
|
223
262
|
x402Version: number;
|
|
224
263
|
/** The client's claimed network (slug or CAIP-2) — for matching, not trust. */
|
|
@@ -236,7 +275,9 @@ interface ParsedExactBase {
|
|
|
236
275
|
* re-derives every verified field from its own trusted rail. A discriminated union on
|
|
237
276
|
* `method`, so narrowing on `method` narrows `payload`: `'eip3009'` → {@link ExactPaymentPayload}
|
|
238
277
|
* (`authorization`), `'permit2'` → {@link Permit2PaymentPayload} (`permit2Authorization`),
|
|
239
|
-
* `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`)
|
|
278
|
+
* `'svm'` → {@link ExactSvmPaymentPayload} (`transaction`), `'algorand'` →
|
|
279
|
+
* {@link ExactAlgorandPaymentPayload} (`paymentGroup`); `'aptos'` →
|
|
280
|
+
* {@link ExactAptosPaymentPayload} (`transaction` + `senderAuth`).
|
|
240
281
|
*/
|
|
241
282
|
type ParsedExactPayment = (ParsedExactBase & {
|
|
242
283
|
method: 'eip3009';
|
|
@@ -247,6 +288,12 @@ type ParsedExactPayment = (ParsedExactBase & {
|
|
|
247
288
|
}) | (ParsedExactBase & {
|
|
248
289
|
method: 'svm';
|
|
249
290
|
payload: ExactSvmPaymentPayload;
|
|
291
|
+
}) | (ParsedExactBase & {
|
|
292
|
+
method: 'algorand';
|
|
293
|
+
payload: ExactAlgorandPaymentPayload;
|
|
294
|
+
}) | (ParsedExactBase & {
|
|
295
|
+
method: 'aptos';
|
|
296
|
+
payload: ExactAptosPaymentPayload;
|
|
250
297
|
});
|
|
251
298
|
interface X402Receipt {
|
|
252
299
|
scheme: 'onchain-proof' | 'exact';
|
|
@@ -4266,9 +4313,10 @@ interface DiscoverySigner {
|
|
|
4266
4313
|
* chain-agnostic — it never names a family, it just merges `extra`.
|
|
4267
4314
|
*/
|
|
4268
4315
|
interface ExactRailInfo {
|
|
4269
|
-
method: 'eip3009' | 'permit2' | 'svm';
|
|
4316
|
+
method: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos';
|
|
4270
4317
|
/** Family-specific `extra` keys merged into the exact accept (e.g. `{ name, version }`
|
|
4271
|
-
* for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana
|
|
4318
|
+
* for EVM EIP-3009, `{ feePayer, tokenProgram }` for Solana, `{ feePayer }` for
|
|
4319
|
+
* Algorand/Aptos). */
|
|
4272
4320
|
extra?: Record<string, unknown>;
|
|
4273
4321
|
}
|
|
4274
4322
|
/**
|
|
@@ -4349,7 +4397,7 @@ interface ResolvedNetwork {
|
|
|
4349
4397
|
reason?: RecipientReason;
|
|
4350
4398
|
}>;
|
|
4351
4399
|
/**
|
|
4352
|
-
* OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM) — the BUYER counterpart to {@link settleExactSelf}.
|
|
4400
|
+
* OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM + Algorand + Aptos) — the BUYER counterpart to {@link settleExactSelf}.
|
|
4353
4401
|
* Build + EIP-712-sign an EIP-3009 `transferWithAuthorization` for a standard x402
|
|
4354
4402
|
* `exact` rail, so a PipRail agent can PAY any standard x402 server (not just PipRail's
|
|
4355
4403
|
* own `onchain-proof` gates). The client frames the returned `payload` + `accepted` echo
|
|
@@ -4404,7 +4452,7 @@ interface ResolvedNetwork {
|
|
|
4404
4452
|
* (the merchant's own bound self-settle wallet, in self mode); `feePayer` takes precedence.
|
|
4405
4453
|
* RPC-read (EVM reads the token's EIP-712 domain; Solana reads the mint's token program); MAY
|
|
4406
4454
|
* throw a typed config error for an explicitly-requested-but-unsupported method (EVM does). A
|
|
4407
|
-
* family that omits this method offers no `exact` rail (today: every
|
|
4455
|
+
* family that omits this method offers no `exact` rail (today: every family except EVM, Solana, Algorand, and Aptos).
|
|
4408
4456
|
*/
|
|
4409
4457
|
resolveExactRail?(input: {
|
|
4410
4458
|
asset: string;
|
|
@@ -4438,10 +4486,12 @@ interface ResolvedNetwork {
|
|
|
4438
4486
|
*/
|
|
4439
4487
|
exactPermit2Supported?(): boolean;
|
|
4440
4488
|
/**
|
|
4441
|
-
* OPTIONAL (EVM-
|
|
4442
|
-
* locally, then SELF-SETTLE it by broadcasting
|
|
4443
|
-
*
|
|
4444
|
-
*
|
|
4489
|
+
* OPTIONAL (EVM EIP-3009/Permit2 + Solana SVM + Algorand + Aptos) — verify a standard x402 `exact`
|
|
4490
|
+
* payment locally, then SELF-SETTLE it by broadcasting from the merchant's own `relayer`
|
|
4491
|
+
* wallet (the merchant pays the network fee to receive; EVM broadcasts
|
|
4492
|
+
* `transferWithAuthorization`, Solana co-signs the fee payer, Algorand signs the pooled fee
|
|
4493
|
+
* txn + submits the group, Aptos adds the fee-payer signature + submits — the transfer
|
|
4494
|
+
* binds `payTo`, so no redirect risk). RETURNS a `VerifyResult`:
|
|
4445
4495
|
* - `{ ok:false, error }` for a CLIENT-fixable fault (bad signature, expired,
|
|
4446
4496
|
* wrong recipient/amount, used nonce, simulation revert) → gate replies 402;
|
|
4447
4497
|
* - `{ ok:true, receipt }` once the settle tx is mined.
|
|
@@ -4930,7 +4980,7 @@ interface SpendSummary {
|
|
|
4930
4980
|
}
|
|
4931
4981
|
|
|
4932
4982
|
/** The payment schemes a client can settle: PipRail's native `onchain-proof` (the
|
|
4933
|
-
* default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM, opt-in). */
|
|
4983
|
+
* default) and the standard x402 `exact` rail (EVM EIP-3009/Permit2 + Solana SVM + Algorand, opt-in). */
|
|
4934
4984
|
type PaymentScheme = 'onchain-proof' | 'exact';
|
|
4935
4985
|
|
|
4936
4986
|
/** Observability events. `ref` is the proof — a chain-specific id (EVM tx hash, Solana signature, TON locator, Stellar tx hash). */
|
|
@@ -5485,7 +5535,7 @@ declare class PipRailClient {
|
|
|
5485
5535
|
* before publishing, so retry with a brief backoff if a fresh listing is missing.
|
|
5486
5536
|
* - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
|
|
5487
5537
|
* `onchain-proof` rails by default, and standard `exact` rails too once you opt in
|
|
5488
|
-
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
|
|
5538
|
+
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM + Algorand).
|
|
5489
5539
|
*/
|
|
5490
5540
|
discover(opts?: DiscoverOptions): Promise<DiscoveredResource[]>;
|
|
5491
5541
|
/**
|
|
@@ -5902,7 +5952,7 @@ declare function describeChallenge(challenge: X402Challenge): string;
|
|
|
5902
5952
|
* literally, so a wrong name or order actively misleads. A test pins the load-
|
|
5903
5953
|
* bearing phrases.
|
|
5904
5954
|
*/
|
|
5905
|
-
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 +
|
|
5955
|
+
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\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";
|
|
5906
5956
|
/** Returns {@link PIPRAIL_AGENT_GUIDE} (a parity accessor for callers that prefer a function). */
|
|
5907
5957
|
declare function agentGuide(): string;
|
|
5908
5958
|
|
|
@@ -6709,7 +6759,7 @@ interface KnownFacilitator {
|
|
|
6709
6759
|
/** The x402 schemes it settles (today only `exact`). */
|
|
6710
6760
|
schemes: ReadonlyArray<'exact'>;
|
|
6711
6761
|
/** The exact transfer methods it can settle on this network. */
|
|
6712
|
-
settles: ReadonlyArray<'eip3009' | 'permit2' | 'svm'>;
|
|
6762
|
+
settles: ReadonlyArray<'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos'>;
|
|
6713
6763
|
/** A short human note (who it is / caveat). */
|
|
6714
6764
|
note?: string;
|
|
6715
6765
|
}
|
|
@@ -6730,7 +6780,7 @@ declare function knownFacilitatorsFor(network: Caip2): ReadonlyArray<KnownFacili
|
|
|
6730
6780
|
* specific transfer `method`). Returns `undefined` when none is known — the `exact: true`
|
|
6731
6781
|
* shorthand branches on that to throw a coverage-specific guidance error.
|
|
6732
6782
|
*/
|
|
6733
|
-
declare function firstKeylessFacilitator(network: Caip2, method?: 'eip3009' | 'permit2' | 'svm'): KnownFacilitator | undefined;
|
|
6783
|
+
declare function firstKeylessFacilitator(network: Caip2, method?: 'eip3009' | 'permit2' | 'svm' | 'algorand' | 'aptos'): KnownFacilitator | undefined;
|
|
6734
6784
|
|
|
6735
6785
|
/**
|
|
6736
6786
|
* Reliable receipt delivery — the durable webhook a stateless gate can't be.
|
package/dist/index.js
CHANGED
|
@@ -1469,9 +1469,24 @@ function parseExactPaymentHeader(value) {
|
|
|
1469
1469
|
const x402Version = typeof v.x402Version === "number" ? v.x402Version : 2;
|
|
1470
1470
|
const asset = accepted && typeof accepted.asset === "string" ? accepted.asset : void 0;
|
|
1471
1471
|
const base2 = { x402Version, network, ...asset ? { asset } : {}, raw: v };
|
|
1472
|
+
if (typeof payload.transaction === "string" && typeof payload.senderAuth === "string") {
|
|
1473
|
+
return { ...base2, method: "aptos", payload: { transaction: payload.transaction, senderAuth: payload.senderAuth } };
|
|
1474
|
+
}
|
|
1472
1475
|
if (typeof payload.transaction === "string") {
|
|
1473
1476
|
return { ...base2, method: "svm", payload: { transaction: payload.transaction } };
|
|
1474
1477
|
}
|
|
1478
|
+
if (Array.isArray(payload.paymentGroup)) {
|
|
1479
|
+
const group = payload.paymentGroup;
|
|
1480
|
+
const index = payload.paymentIndex;
|
|
1481
|
+
if (group.length === 0 || group.length > 16 || !group.every((t) => typeof t === "string") || typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= group.length) {
|
|
1482
|
+
return null;
|
|
1483
|
+
}
|
|
1484
|
+
return {
|
|
1485
|
+
...base2,
|
|
1486
|
+
method: "algorand",
|
|
1487
|
+
payload: { paymentIndex: index, paymentGroup: group }
|
|
1488
|
+
};
|
|
1489
|
+
}
|
|
1475
1490
|
const signature = payload.signature;
|
|
1476
1491
|
if (typeof signature !== "string") return null;
|
|
1477
1492
|
const authorization = payload.authorization;
|
|
@@ -1792,6 +1807,9 @@ function makeEvmNetwork(resolved) {
|
|
|
1792
1807
|
if ("transaction" in payload) {
|
|
1793
1808
|
return { ok: false, error: "signature_invalid", detail: "An SVM (Solana) payload was submitted to an EVM exact rail." };
|
|
1794
1809
|
}
|
|
1810
|
+
if ("paymentGroup" in payload) {
|
|
1811
|
+
return { ok: false, error: "signature_invalid", detail: "An Algorand payload was submitted to an EVM exact rail." };
|
|
1812
|
+
}
|
|
1795
1813
|
return verifyAndSettleExactEvm({
|
|
1796
1814
|
publicClient,
|
|
1797
1815
|
walletClient: a.walletClient,
|
|
@@ -1816,7 +1834,7 @@ var loaders = {
|
|
|
1816
1834
|
solana: async () => {
|
|
1817
1835
|
let mod;
|
|
1818
1836
|
try {
|
|
1819
|
-
mod = await import("./solana-
|
|
1837
|
+
mod = await import("./solana-3FMCWSEE.js");
|
|
1820
1838
|
} catch (cause) {
|
|
1821
1839
|
throw new MissingDriverError(
|
|
1822
1840
|
`Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
|
|
@@ -1900,7 +1918,7 @@ var loaders = {
|
|
|
1900
1918
|
aptos: async () => {
|
|
1901
1919
|
let mod;
|
|
1902
1920
|
try {
|
|
1903
|
-
mod = await import("./aptos-
|
|
1921
|
+
mod = await import("./aptos-QAAXIUY3.js");
|
|
1904
1922
|
} catch (cause) {
|
|
1905
1923
|
throw new MissingDriverError(
|
|
1906
1924
|
`Aptos selected, but its package isn't installed. Run: npm install @aptos-labs/ts-sdk`,
|
|
@@ -1912,7 +1930,7 @@ var loaders = {
|
|
|
1912
1930
|
algorand: async () => {
|
|
1913
1931
|
let mod;
|
|
1914
1932
|
try {
|
|
1915
|
-
mod = await import("./algorand-
|
|
1933
|
+
mod = await import("./algorand-WB6PBJU4.js");
|
|
1916
1934
|
} catch (cause) {
|
|
1917
1935
|
throw new MissingDriverError(
|
|
1918
1936
|
`Algorand selected, but its package isn't installed. Run: npm install algosdk`,
|
|
@@ -2008,7 +2026,7 @@ var SLUG_TO_CAIP2 = {
|
|
|
2008
2026
|
near: "near:mainnet",
|
|
2009
2027
|
sui: "sui:mainnet",
|
|
2010
2028
|
aptos: "aptos:1",
|
|
2011
|
-
algorand: "algorand:
|
|
2029
|
+
algorand: "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
|
|
2012
2030
|
stellar: "stellar:pubnet",
|
|
2013
2031
|
xrpl: "xrpl:0"
|
|
2014
2032
|
};
|
|
@@ -3026,7 +3044,7 @@ var PipRailClient = class {
|
|
|
3026
3044
|
* before publishing, so retry with a brief backoff if a fresh listing is missing.
|
|
3027
3045
|
* - Results are cross-scheme (mostly the mainstream `exact` scheme); `fetch()` pays
|
|
3028
3046
|
* `onchain-proof` rails by default, and standard `exact` rails too once you opt in
|
|
3029
|
-
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM).
|
|
3047
|
+
* with `schemes: ['onchain-proof', 'exact']` (EVM EIP-3009/Permit2 + Solana SVM + Algorand).
|
|
3030
3048
|
*/
|
|
3031
3049
|
async discover(opts = {}) {
|
|
3032
3050
|
const found = await searchOpenIndexes({
|
|
@@ -3224,7 +3242,7 @@ var PipRailClient = class {
|
|
|
3224
3242
|
);
|
|
3225
3243
|
if (schemes.includes("exact") && exactOnNet && typeof net.payExact !== "function") {
|
|
3226
3244
|
throw new UnsupportedSchemeError(
|
|
3227
|
-
`This 402 offers a standard 'exact' rail on ${net.network}, but the ${net.family} family can't pay 'exact' (supported on EVM +
|
|
3245
|
+
`This 402 offers a standard 'exact' rail on ${net.network}, but the ${net.family} family can't pay 'exact' (supported on EVM, Solana + Algorand today), and no 'onchain-proof' rail was offered.`
|
|
3228
3246
|
);
|
|
3229
3247
|
}
|
|
3230
3248
|
if (!schemes.includes("exact") && exactOnNet && typeof net.payExact === "function") {
|
|
@@ -3620,7 +3638,7 @@ var PipRailClient = class {
|
|
|
3620
3638
|
async payExactRail(net, wallet, accept, url, init, quote) {
|
|
3621
3639
|
if (!net.payExact) {
|
|
3622
3640
|
throw new UnsupportedSchemeError(
|
|
3623
|
-
`the ${net.family} family can't pay a standard 'exact' rail (supported on EVM +
|
|
3641
|
+
`the ${net.family} family can't pay a standard 'exact' rail (supported on EVM, Solana + Algorand today).`
|
|
3624
3642
|
);
|
|
3625
3643
|
}
|
|
3626
3644
|
throwIfAborted(init?.signal);
|
|
@@ -4189,7 +4207,8 @@ A 402 may offer up to two rails; you don't choose per payment \u2014 the client
|
|
|
4189
4207
|
(the native coin \u2014 ETH/SOL/\u2026). Works on every chain.
|
|
4190
4208
|
- exact (the ratified x402 rail, opt-in): you only SIGN; the server \u2014 or a facilitator it chose
|
|
4191
4209
|
(e.g. PayAI) \u2014 broadcasts it, so you pay ZERO gas (you need only the token, no native coin). It
|
|
4192
|
-
works on EVM +
|
|
4210
|
+
works on EVM, Solana + Algorand, and the on-chain method (EIP-3009 / Permit2 / SVM / Algorand
|
|
4211
|
+
fee-pooled group) is picked automatically.
|
|
4193
4212
|
When the exact scheme is enabled AND balance-aware routing is on, paying picks the cheapest
|
|
4194
4213
|
settleable rail \u2014 i.e. the gasless exact one. Nothing changes in your loop: quote \u2192 plan \u2192 pay is
|
|
4195
4214
|
identical. The exact scheme is OPT-IN by the operator (MCP: PIPRAIL_SCHEMES=onchain-proof,exact);
|
|
@@ -4909,6 +4928,110 @@ var KNOWN_FACILITATORS = {
|
|
|
4909
4928
|
schemes: ["exact"],
|
|
4910
4929
|
settles: ["eip3009"],
|
|
4911
4930
|
note: "xpay \u2014 keyless, zero-fee, sponsors gas. LIVE-settled on Base 2026-06-15 (tx 0x2273d5\u2026)."
|
|
4931
|
+
},
|
|
4932
|
+
{
|
|
4933
|
+
url: "https://facilitator.ultravioletadao.xyz",
|
|
4934
|
+
keyless: true,
|
|
4935
|
+
schemes: ["exact"],
|
|
4936
|
+
settles: ["eip3009"],
|
|
4937
|
+
note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x58a69042a4129be649c5642456752ede95a5ff921daddfd30560ae70ae5907ff). 2nd UVD validation chain (after HyperEVM)."
|
|
4938
|
+
},
|
|
4939
|
+
{
|
|
4940
|
+
url: "https://x402.dexter.cash",
|
|
4941
|
+
keyless: true,
|
|
4942
|
+
schemes: ["exact"],
|
|
4943
|
+
settles: ["eip3009"],
|
|
4944
|
+
note: "Dexter \u2014 keyless, gas-sponsored (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0xdf030e4d5bf41a88c5a3bfe73bb433dfbb90b058d3b8ded63b68e026eedb9de8). Note: ~$0.001 dynamic floor on Base."
|
|
4945
|
+
},
|
|
4946
|
+
{
|
|
4947
|
+
url: "https://facilitator.corbits.dev",
|
|
4948
|
+
keyless: true,
|
|
4949
|
+
schemes: ["exact"],
|
|
4950
|
+
settles: ["eip3009"],
|
|
4951
|
+
note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x2e41c581af023100429ada81f1371bef82d41dd577ed438d72ddc18676d4213d). Also seeded on Monad + Solana."
|
|
4952
|
+
},
|
|
4953
|
+
{
|
|
4954
|
+
url: "https://facilitator.goplausible.xyz",
|
|
4955
|
+
keyless: true,
|
|
4956
|
+
schemes: ["exact"],
|
|
4957
|
+
settles: ["eip3009"],
|
|
4958
|
+
note: "GoPlausible \u2014 keyless, sponsors gas (Base USDC EIP-3009). LIVE-settled on Base 2026-06-17 (tx 0x9bcbc1f01fe1fd1aed2a79e5582555164cc4185e9800189df378a6b46eb9c59e). 2nd GoPlausible validation chain (after Algorand)."
|
|
4959
|
+
}
|
|
4960
|
+
],
|
|
4961
|
+
// Monad (eip155:143). Corbits + Ultravioleta DAO each keyless-settle the EVM EIP-3009 exact rail
|
|
4962
|
+
// (Monad's native Circle USDC), buyer paid zero gas — real LIVE settles, not just /supported reads.
|
|
4963
|
+
// Makes `exact: true` zero-config gasless on Monad.
|
|
4964
|
+
"eip155:143": [
|
|
4965
|
+
{
|
|
4966
|
+
url: "https://facilitator.corbits.dev",
|
|
4967
|
+
keyless: true,
|
|
4968
|
+
schemes: ["exact"],
|
|
4969
|
+
settles: ["eip3009"],
|
|
4970
|
+
note: "Corbits (Faremeter) \u2014 keyless, sponsors gas (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x7797be27ce22c17f7433a0389bd22d46e338899b1faac505fffd068174428ae6)."
|
|
4971
|
+
},
|
|
4972
|
+
{
|
|
4973
|
+
url: "https://facilitator.ultravioletadao.xyz",
|
|
4974
|
+
keyless: true,
|
|
4975
|
+
schemes: ["exact"],
|
|
4976
|
+
settles: ["eip3009"],
|
|
4977
|
+
note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (Monad native USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0xb107576effbaceb5586c07a9ddc996ef2b6d455f1858314995ef83a7c6e64d11). 3rd UVD validation chain."
|
|
4978
|
+
},
|
|
4979
|
+
{
|
|
4980
|
+
url: "https://facilitator.pieverse.io",
|
|
4981
|
+
keyless: true,
|
|
4982
|
+
schemes: ["exact"],
|
|
4983
|
+
settles: ["eip3009"],
|
|
4984
|
+
note: "Pieverse \u2014 keyless, sponsors gas (Monad USDC EIP-3009). LIVE-settled on Monad 2026-06-17 (tx 0x00cfeb93876e5ef57dcb002510038b7304913233ca286d7ab33c72a8b119eb0d)."
|
|
4985
|
+
}
|
|
4986
|
+
],
|
|
4987
|
+
// BNB Chain (eip155:56). Dexter keyless-settles the EVM EIP-3009 exact rail — but ONLY for BNB's
|
|
4988
|
+
// EIP-3009 tokens (FDUSD / USD1); BNB's USDC/USDT are Binance-Peg (Permit2), which no facilitator
|
|
4989
|
+
// settles. Dexter also enforces a ~$0.003 dynamic settlement floor on BNB, so a sub-$0.003 payment
|
|
4990
|
+
// is rejected (amount_too_low) — fine for real prices, but the floor is real. LIVE-settled with
|
|
4991
|
+
// FDUSD, buyer paid zero BNB — this beats the BNB token-overlap wall that blocked AEON/Pieverse.
|
|
4992
|
+
"eip155:56": [
|
|
4993
|
+
{
|
|
4994
|
+
url: "https://x402.dexter.cash",
|
|
4995
|
+
keyless: true,
|
|
4996
|
+
schemes: ["exact"],
|
|
4997
|
+
settles: ["eip3009"],
|
|
4998
|
+
note: "Dexter \u2014 keyless, gas-sponsored. BNB EIP-3009 tokens FDUSD/USD1 ONLY (Binance-Peg USDC/USDT are Permit2 \u2192 not facilitator-settleable); ~$0.003 dynamic floor. LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0x6d9eb4e4939f3f3c74cb19424cc7822d66ec8ed5c5c7c330d9f88a5f9ad59e9e)."
|
|
4999
|
+
},
|
|
5000
|
+
{
|
|
5001
|
+
url: "https://facilitator.pieverse.io",
|
|
5002
|
+
keyless: true,
|
|
5003
|
+
schemes: ["exact"],
|
|
5004
|
+
settles: ["eip3009"],
|
|
5005
|
+
note: "Pieverse \u2014 keyless, sponsors gas. BNB EIP-3009 tokens FDUSD/USD1 (same Binance-Peg caveat as Dexter). LIVE-settled on BNB 2026-06-17 with FDUSD (tx 0xb9c76affc45bd07a51559efd813ca71516fc30625478724476c2cf42fc2203d3) \u2014 a 2nd keyless BNB facilitator (failover for Dexter)."
|
|
5006
|
+
}
|
|
5007
|
+
],
|
|
5008
|
+
// HyperEVM (eip155:999). Ultravioleta DAO keyless-settles the EVM EIP-3009 exact rail (HyperEVM's
|
|
5009
|
+
// native Circle USDC), buyer paid zero gas — a real LIVE settle. UVD is the broadest keyless
|
|
5010
|
+
// facilitator (it also lists Celo/Unichain/Optimism/Scroll + many non-EVM); only HyperEVM is
|
|
5011
|
+
// seeded here because THE RULE requires a per-chain live settle, and that's the one we proved.
|
|
5012
|
+
"eip155:999": [
|
|
5013
|
+
{
|
|
5014
|
+
url: "https://facilitator.ultravioletadao.xyz",
|
|
5015
|
+
keyless: true,
|
|
5016
|
+
schemes: ["exact"],
|
|
5017
|
+
settles: ["eip3009"],
|
|
5018
|
+
note: "Ultravioleta DAO \u2014 keyless, 100% gas-sponsored (HyperEVM native USDC EIP-3009). LIVE-settled on HyperEVM 2026-06-17 (tx 0x56af8148a92a291f0ce362e250919f7742074e5464ac0f315ad68abaec93bd0a)."
|
|
5019
|
+
}
|
|
5020
|
+
],
|
|
5021
|
+
// Algorand (mainnet, CAIP-2 = full base64 genesis hash). GoPlausible keyless-settles the ratified
|
|
5022
|
+
// x402 Algorand `exact` rail (atomic-group fee pooling): its sponsor pools the whole group fee and
|
|
5023
|
+
// submits, so NEITHER the buyer NOR the merchant pays ALGO — both-sides gasless. LIVE-settled by us
|
|
5024
|
+
// (a real USDCa exact payment; buyer 0 ALGO AND merchant 0 ALGO) — beyond a /supported read. This
|
|
5025
|
+
// makes Algorand a keyless chain (the first non-EVM/non-Solana one). GoPlausible authored the
|
|
5026
|
+
// ratified Algorand scheme; PipRail's group is byte-compatible (the gate sends `amount` + the full
|
|
5027
|
+
// genesis-hash network, which is all GoPlausible needs).
|
|
5028
|
+
"algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=": [
|
|
5029
|
+
{
|
|
5030
|
+
url: "https://facilitator.goplausible.xyz",
|
|
5031
|
+
keyless: true,
|
|
5032
|
+
schemes: ["exact"],
|
|
5033
|
+
settles: ["algorand"],
|
|
5034
|
+
note: "GoPlausible \u2014 keyless, 100% gas-sponsored (Algorand USDCa, atomic-group fee pooling; both buyer AND merchant pay 0 ALGO). LIVE-settled on Algorand mainnet 2026-06-17 (tx PDVDVRFGJAG2K6AJ7L26OTSCSRL7AURVKEX4D4KHBAOLNSCYENXA). The only keyless Algorand x402 facilitator."
|
|
4912
5035
|
}
|
|
4913
5036
|
],
|
|
4914
5037
|
// Solana (mainnet-beta). Keyless fee-payer sponsors for the SVM exact rail, each LIVE-settled
|
|
@@ -5070,7 +5193,7 @@ function createPaymentGate(options) {
|
|
|
5070
5193
|
if (settle !== "self" && info.method === "permit2") {
|
|
5071
5194
|
if (cfg.method === "permit2") {
|
|
5072
5195
|
throw new Error(
|
|
5073
|
-
"requirePayment: exact `method: 'permit2'` can't be settled by a third-party facilitator \u2014 facilitators settle the standard EIP-3009 (EVM) / SVM (Solana) schemes, not PipRail\u2019s Permit2 proxy. Use an EIP-3009 token (USDC / EURC) with the facilitator, or `settle: 'self'` (your own relayer) to settle Permit2 yourself."
|
|
5196
|
+
"requirePayment: exact `method: 'permit2'` can't be settled by a third-party facilitator \u2014 facilitators settle the standard EIP-3009 (EVM) / SVM (Solana) / Algorand schemes, not PipRail\u2019s Permit2 proxy. Use an EIP-3009 token (USDC / EURC) with the facilitator, or `settle: 'self'` (your own relayer) to settle Permit2 yourself."
|
|
5074
5197
|
);
|
|
5075
5198
|
}
|
|
5076
5199
|
return {
|
|
@@ -5315,7 +5438,7 @@ function createPaymentGate(options) {
|
|
|
5315
5438
|
if (exactSpecs.length === 0) {
|
|
5316
5439
|
return rejection("transfer_not_found", "This resource offers no standard `exact` rail.");
|
|
5317
5440
|
}
|
|
5318
|
-
const isCaip = exact.network.
|
|
5441
|
+
const isCaip = exact.network.includes(":");
|
|
5319
5442
|
let candidates = isCaip ? exactSpecs.filter((s) => s.net.network === exact.network) : exactSpecs;
|
|
5320
5443
|
if (exact.asset) {
|
|
5321
5444
|
candidates = candidates.filter((s) => s.asset.toLowerCase() === exact.asset.toLowerCase());
|
|
@@ -5331,12 +5454,28 @@ function createPaymentGate(options) {
|
|
|
5331
5454
|
}
|
|
5332
5455
|
let nonce;
|
|
5333
5456
|
let evmAuth = null;
|
|
5334
|
-
if ("transaction" in exact.payload) {
|
|
5457
|
+
if ("senderAuth" in exact.payload && "transaction" in exact.payload) {
|
|
5458
|
+
nonce = [exact.payload.transaction, exact.payload.senderAuth].map((t) => {
|
|
5459
|
+
try {
|
|
5460
|
+
return Buffer.from(t, "base64").toString("base64");
|
|
5461
|
+
} catch {
|
|
5462
|
+
return t;
|
|
5463
|
+
}
|
|
5464
|
+
}).join("|");
|
|
5465
|
+
} else if ("transaction" in exact.payload) {
|
|
5335
5466
|
try {
|
|
5336
5467
|
nonce = Buffer.from(exact.payload.transaction, "base64").toString("base64");
|
|
5337
5468
|
} catch {
|
|
5338
5469
|
nonce = exact.payload.transaction;
|
|
5339
5470
|
}
|
|
5471
|
+
} else if ("paymentGroup" in exact.payload) {
|
|
5472
|
+
nonce = exact.payload.paymentGroup.map((t) => {
|
|
5473
|
+
try {
|
|
5474
|
+
return Buffer.from(t, "base64").toString("base64");
|
|
5475
|
+
} catch {
|
|
5476
|
+
return t;
|
|
5477
|
+
}
|
|
5478
|
+
}).join("|");
|
|
5340
5479
|
} else if ("permit2Authorization" in exact.payload) {
|
|
5341
5480
|
evmAuth = exact.payload.permit2Authorization;
|
|
5342
5481
|
nonce = evmAuth.nonce;
|
|
@@ -5354,6 +5493,13 @@ function createPaymentGate(options) {
|
|
|
5354
5493
|
if (mode.kind === "self") {
|
|
5355
5494
|
result = await spec.net.settleExactSelf({ relayer: mode.relayer, payload: exact.payload, accept });
|
|
5356
5495
|
} else {
|
|
5496
|
+
const ftMethod = accept.extra.assetTransferMethod;
|
|
5497
|
+
const needsFeePayer = ftMethod === "svm" || ftMethod === "algorand" || ftMethod === "aptos";
|
|
5498
|
+
if (needsFeePayer && !accept.extra.feePayer) {
|
|
5499
|
+
throw new SettlementError(
|
|
5500
|
+
`exact settle: the ${ftMethod} facilitator rail is missing extra.feePayer (the gas sponsor) \u2014 cannot settle.`
|
|
5501
|
+
);
|
|
5502
|
+
}
|
|
5357
5503
|
result = await settleViaFacilitator({
|
|
5358
5504
|
url: mode.url,
|
|
5359
5505
|
...mode.authHeaders ? { authHeaders: mode.authHeaders } : {},
|
|
@@ -5370,9 +5516,7 @@ function createPaymentGate(options) {
|
|
|
5370
5516
|
amount: accept.amount,
|
|
5371
5517
|
payTo: accept.payTo,
|
|
5372
5518
|
maxTimeoutSeconds: accept.maxTimeoutSeconds,
|
|
5373
|
-
|
|
5374
|
-
// facilitator's `feePayer` (the gas sponsor); EVM forwards the token's EIP-712 domain.
|
|
5375
|
-
extra: accept.extra.assetTransferMethod === "svm" ? { feePayer: accept.extra.feePayer ?? "" } : { name: accept.extra.name ?? "", version: accept.extra.version ?? "" }
|
|
5519
|
+
extra: needsFeePayer ? { feePayer: accept.extra.feePayer } : { name: accept.extra.name ?? "", version: accept.extra.version ?? "" }
|
|
5376
5520
|
},
|
|
5377
5521
|
receipt: { network: accept.network, asset: accept.asset, payTo: accept.payTo, amount: accept.amount },
|
|
5378
5522
|
// The buyer address, for the receipt's `payer` fallback. EVM carries it in the
|
|
@@ -221,6 +221,10 @@ import {
|
|
|
221
221
|
import bs58 from "bs58";
|
|
222
222
|
var COMPUTE_UNIT_LIMIT = 2e4;
|
|
223
223
|
var COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
|
|
224
|
+
var MAX_COMPUTE_UNIT_LIMIT = 300000n;
|
|
225
|
+
var MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 100000n;
|
|
226
|
+
var CB_SET_UNIT_LIMIT = 2;
|
|
227
|
+
var CB_SET_UNIT_PRICE = 3;
|
|
224
228
|
function tokenProgramFor(accept) {
|
|
225
229
|
return accept.extra.tokenProgram === "token-2022" ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
|
|
226
230
|
}
|
|
@@ -380,6 +384,22 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
380
384
|
}
|
|
381
385
|
}
|
|
382
386
|
}
|
|
387
|
+
for (const ix of message.compiledInstructions) {
|
|
388
|
+
const ixProgram = keys.get(ix.programIdIndex);
|
|
389
|
+
if (!ixProgram || !ixProgram.equals(ComputeBudgetProgram.programId)) continue;
|
|
390
|
+
const data = Buffer.from(ix.data);
|
|
391
|
+
if (data.length >= 5 && data[0] === CB_SET_UNIT_LIMIT) {
|
|
392
|
+
const limit = BigInt(data.readUInt32LE(1));
|
|
393
|
+
if (limit > MAX_COMPUTE_UNIT_LIMIT) {
|
|
394
|
+
return fail("signature_invalid", `Compute-unit limit ${limit} exceeds the ${MAX_COMPUTE_UNIT_LIMIT} cap (fee-payer drain guard).`);
|
|
395
|
+
}
|
|
396
|
+
} else if (data.length >= 9 && data[0] === CB_SET_UNIT_PRICE) {
|
|
397
|
+
const price = data.readBigUInt64LE(1);
|
|
398
|
+
if (price > MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS) {
|
|
399
|
+
return fail("signature_invalid", `Compute-unit price ${price} \xB5lamports exceeds the ${MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS} cap (fee-payer drain guard).`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
383
403
|
const isSignedSigner = (pubkey) => {
|
|
384
404
|
const idx = message.staticAccountKeys.findIndex((k) => k.equals(pubkey));
|
|
385
405
|
return idx >= 1 && idx < message.header.numRequiredSignatures && !isEmptySig(tx.signatures[idx]);
|
|
@@ -221,6 +221,10 @@ function notFound(signature) {
|
|
|
221
221
|
var _bs58 = require('bs58'); var _bs582 = _interopRequireDefault(_bs58);
|
|
222
222
|
var COMPUTE_UNIT_LIMIT = 2e4;
|
|
223
223
|
var COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;
|
|
224
|
+
var MAX_COMPUTE_UNIT_LIMIT = 300000n;
|
|
225
|
+
var MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 100000n;
|
|
226
|
+
var CB_SET_UNIT_LIMIT = 2;
|
|
227
|
+
var CB_SET_UNIT_PRICE = 3;
|
|
224
228
|
function tokenProgramFor(accept) {
|
|
225
229
|
return accept.extra.tokenProgram === "token-2022" ? _spltoken.TOKEN_2022_PROGRAM_ID : _spltoken.TOKEN_PROGRAM_ID;
|
|
226
230
|
}
|
|
@@ -380,6 +384,22 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
380
384
|
}
|
|
381
385
|
}
|
|
382
386
|
}
|
|
387
|
+
for (const ix of message.compiledInstructions) {
|
|
388
|
+
const ixProgram = keys.get(ix.programIdIndex);
|
|
389
|
+
if (!ixProgram || !ixProgram.equals(_web3js.ComputeBudgetProgram.programId)) continue;
|
|
390
|
+
const data = Buffer.from(ix.data);
|
|
391
|
+
if (data.length >= 5 && data[0] === CB_SET_UNIT_LIMIT) {
|
|
392
|
+
const limit = BigInt(data.readUInt32LE(1));
|
|
393
|
+
if (limit > MAX_COMPUTE_UNIT_LIMIT) {
|
|
394
|
+
return fail("signature_invalid", `Compute-unit limit ${limit} exceeds the ${MAX_COMPUTE_UNIT_LIMIT} cap (fee-payer drain guard).`);
|
|
395
|
+
}
|
|
396
|
+
} else if (data.length >= 9 && data[0] === CB_SET_UNIT_PRICE) {
|
|
397
|
+
const price = data.readBigUInt64LE(1);
|
|
398
|
+
if (price > MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS) {
|
|
399
|
+
return fail("signature_invalid", `Compute-unit price ${price} \xB5lamports exceeds the ${MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS} cap (fee-payer drain guard).`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
383
403
|
const isSignedSigner = (pubkey) => {
|
|
384
404
|
const idx = message.staticAccountKeys.findIndex((k) => k.equals(pubkey));
|
|
385
405
|
return idx >= 1 && idx < message.header.numRequiredSignatures && !isEmptySig(tx.signatures[idx]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Accept x402 crypto payments across 29 chains — every major EVM chain plus Solana, TON, Tron, NEAR, Sui, Aptos, Algorand, Stellar & XRPL — in a couple of lines. No backend, no database, no fee; payments settle straight to your wallet.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|