@piprail/sdk 1.5.0 → 1.6.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/CHAINS.md +2 -2
- package/CHANGELOG.md +41 -0
- package/ERRORS.md +4 -3
- package/README.md +10 -2
- package/dist/index.cjs +7 -2
- package/dist/index.d.cts +27 -16
- package/dist/index.d.ts +27 -16
- package/dist/index.js +7 -2
- package/package.json +2 -2
package/CHAINS.md
CHANGED
|
@@ -13,7 +13,7 @@ read those sections before you ship them.
|
|
|
13
13
|
|
|
14
14
|
| Chain(s) | Pay in native coin? | Built-in stablecoins | Receiver needs setup? | Wallet input |
|
|
15
15
|
|---|:--:|---|---|---|
|
|
16
|
-
| **EVM** (Ethereum, Base, Arbitrum, Optimism, Polygon, BNB, Avalanche, Mantle, Sonic, Linea, Scroll, Celo, zkSync, Unichain, World Chain, Sei, Injective, + any EVM chain) | ✅ ETH/BNB/POL/… | USDC (all) · USDT (all **except Base, World Chain, Sei**) | No | `{ privateKey }` |
|
|
16
|
+
| **EVM** (Ethereum, Base, Arbitrum, Optimism, Polygon, BNB, Avalanche, Mantle, Sonic, Linea, Scroll, Celo, zkSync, Unichain, World Chain, Sei, Injective, HyperEVM, Monad, + any EVM chain) | ✅ ETH/BNB/POL/… | USDC (all) · USDT (all **except Base, World Chain, Sei, HyperEVM, Monad**) | No | `{ privateKey }` |
|
|
17
17
|
| **Solana** | ✅ SOL | USDC · USDT | No (payer creates the recipient's token account) | `{ secretKey }` |
|
|
18
18
|
| **Sui** | ✅ SUI | USDC (no USDT) | No | `{ privateKey }` (`suiprivkey1…`) |
|
|
19
19
|
| **Aptos** | ✅ APT | USDC · USDT | No (primary FA store auto-creates) | `{ privateKey }` (`ed25519-priv-0x…`) |
|
|
@@ -45,7 +45,7 @@ read those sections before you ship them.
|
|
|
45
45
|
|
|
46
46
|
### EVM — Ethereum, Base, Arbitrum, Optimism, Polygon, BNB, Avalanche, …
|
|
47
47
|
- **Pay in:** native coin (`'native'`), `'USDC'`, `'USDT'`, or a custom `{ address, decimals }`.
|
|
48
|
-
- **USDT gap:** built in on every preset **except Base, World Chain, and
|
|
48
|
+
- **USDT gap:** built in on every preset **except Base, World Chain, Sei, HyperEVM, and Monad** (USDC only there).
|
|
49
49
|
- **Decimals:** on **BNB Chain**, Binance-Peg USDC/USDT are **18 decimals**, not 6 (the SDK handles it; don't hardcode 6).
|
|
50
50
|
- **USDT branding:** on **Arbitrum, Polygon, and Unichain** the canonical Tether is the omnichain **USD₮0 / USDT0** (LayerZero), and on **Celo** it's native **USD₮** — all genuine, Tether-issued, 6-decimal USDT at the addresses shipped (verified live on-chain by symbol/decimals/supply). You still ask for it as `token: 'USDT'`; only the on-chain `symbol()` string differs from the plain `USDT` your wallet may show elsewhere.
|
|
51
51
|
- **Receiver setup:** none — any `0x…` address receives ERC-20 or native immediately.
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,39 @@ All notable changes to `@piprail/sdk` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
5
|
versions follow [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [1.6.0] — 2026-06-05
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **`policy.tokens` accepts `'native'`** — a chain-agnostic alias that allows the chain's native coin
|
|
11
|
+
(ETH/BNB/TRX/XLM/…) by the same word the accept side already uses (`token: 'native'`), without naming
|
|
12
|
+
the per-chain ticker. It's matched on the asset (not the symbol), so it works on every family; symbol
|
|
13
|
+
matching is unchanged (the real ticker still works), and `'native'` only ever matches a genuinely
|
|
14
|
+
native asset — it never loosens a stablecoin allowlist. Closes a terminology gap where allowing native
|
|
15
|
+
payments previously required knowing the coin's symbol. `@piprail/mcp`'s `PIPRAIL_TOKENS` inherits this.
|
|
16
|
+
Additive + non-breaking (next release is a minor).
|
|
17
|
+
|
|
18
|
+
## [1.5.1] — 2026-06-04
|
|
19
|
+
|
|
20
|
+
**Cosmetic polish — docs & comments only, zero behavior change.** A repo-wide tidy pass so the
|
|
21
|
+
in-code docs match the SDK as it actually ships (10 families / 28 chains). No runtime, API, type,
|
|
22
|
+
or wire change — every existing program behaves identically.
|
|
23
|
+
|
|
24
|
+
- **JSDoc parity across the public surface.** The `chain` / `token` / `payTo` / wallet docs on
|
|
25
|
+
`RequirePaymentOptions`, `AcceptOption`, and `PipRailClientOptions` now enumerate all 10 families
|
|
26
|
+
(Aptos + Algorand were missing); the typed error JSDoc (`WrongFamilyError`, `UnknownTokenError`,
|
|
27
|
+
`MissingDriverError`, `RecipientNotReadyError`) lists every family + install command + custom-token form.
|
|
28
|
+
- **Stale comments corrected.** Native TRX and native NEAR are documented as the payment assets they've
|
|
29
|
+
been since 1.1.0 (the old "not a payment asset" / "`'native'` is rejected" notes were removed); the
|
|
30
|
+
`'native'` coin list, the barrel header, the tsup code-split note, and the lazy-mount docs now name all
|
|
31
|
+
9 non-EVM families; the `paymentTools` doc says "three tools" (quote · plan · pay).
|
|
32
|
+
- **Driver-family symmetry.** `evm/wallet.ts` gained the `── EVM SECTION: wallet ──` banner the other 9
|
|
33
|
+
families carry, and `evm/index.ts`'s `recipientReady()` comment now uses the shared "No receive
|
|
34
|
+
prerequisite —" lead-in.
|
|
35
|
+
- **Docs:** README contract-method list adds `balanceOf` / `recipientReady`; README custom-token examples
|
|
36
|
+
add Aptos + Algorand; CHAINS.md lists HyperEVM + Monad (and their USDT gap); ERRORS.md + AGENTS.md list
|
|
37
|
+
all 10 families; CHANGELOG version footer links restored.
|
|
38
|
+
- **Packaging:** `algosdk` moved to its alphabetical slot in `peerDependencies` (no dependency change).
|
|
39
|
+
|
|
7
40
|
## [1.5.0] — 2026-06-04
|
|
8
41
|
|
|
9
42
|
**The killer agent feature — `client.planPayment(url)`.** A read-only call that surveys a 402
|
|
@@ -384,6 +417,14 @@ straight into your wallet. The API is small and self-contained.
|
|
|
384
417
|
to your wallet; PipRail never holds funds.
|
|
385
418
|
- `viem ^2.21` is a peer dependency. Node 20+ or a modern browser.
|
|
386
419
|
|
|
420
|
+
[1.6.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
421
|
+
[1.5.1]: https://www.npmjs.com/package/@piprail/sdk
|
|
422
|
+
[1.5.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
423
|
+
[1.4.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
424
|
+
[1.3.1]: https://www.npmjs.com/package/@piprail/sdk
|
|
425
|
+
[1.3.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
426
|
+
[1.2.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
427
|
+
[1.1.1]: https://www.npmjs.com/package/@piprail/sdk
|
|
387
428
|
[1.1.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
388
429
|
[1.0.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
389
430
|
[0.1.0]: https://www.npmjs.com/package/@piprail/sdk
|
package/ERRORS.md
CHANGED
|
@@ -205,9 +205,10 @@ the reader, full raw detail for the debugger — both, always. Chains with no re
|
|
|
205
205
|
|
|
206
206
|
## 7. Registry / loader pattern
|
|
207
207
|
|
|
208
|
-
- EVM is registered eagerly (`viem` is the one hard peer dep).
|
|
209
|
-
lazily via a single dynamic
|
|
210
|
-
first time
|
|
208
|
+
- EVM is registered eagerly (`viem` is the one hard peer dep). Every non-EVM family (Solana,
|
|
209
|
+
TON, Tron, NEAR, Sui, Stellar, XRPL, Aptos, Algorand) mounts lazily via a single dynamic
|
|
210
|
+
`import()` in [`drivers/index.ts`](src/drivers/index.ts) the first time its `chain` is
|
|
211
|
+
named — no setup call.
|
|
211
212
|
- A failed lazy `import()` → `MissingDriverError` naming the exact `npm install` + `{ cause }`.
|
|
212
213
|
The in-flight promise isn't cached on failure, so a later call can retry.
|
|
213
214
|
- No driver for the family, or `resolve()` → `null` → `UnsupportedNetworkError`.
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ const client = new PipRailClient({
|
|
|
52
52
|
maxAmount: '0.10', // never pay more than $0.10 for one call
|
|
53
53
|
maxTotal: '5.00', // never spend more than $5 total (per token)
|
|
54
54
|
chains: ['base'], // only on Base
|
|
55
|
-
tokens: ['USDC'], // only in USDC
|
|
55
|
+
tokens: ['USDC'], // only in USDC (use 'native' to also allow the chain's coin)
|
|
56
56
|
hosts: ['*.example.com'], // only these hosts
|
|
57
57
|
},
|
|
58
58
|
onBeforePay: (q) => Number(q.amountFormatted) <= 0.05, // final say on each payment
|
|
@@ -75,6 +75,8 @@ client.spent() // → { count, byAsset: [{ symbol:'USDC', totalFormatted:'0.05',
|
|
|
75
75
|
|
|
76
76
|
**The budget can't be fooled.** `maxAmount`/`maxTotal` are enforced against the token's **true** decimals (the SDK's own, via the driver) — a server can't slip past a cap by understating the price, and an asset the SDK can't recognise is refused unless you set `allowUnknownTokens`. `quote()` even flags a `symbolMismatch` when a challenge's stated symbol disagrees with the real token.
|
|
77
77
|
|
|
78
|
+
**`policy.tokens` takes symbols *or* `'native'`.** List stablecoin symbols (`'USDC'`, `'USDT'`, …) and/or the chain-agnostic alias **`'native'`** to allow the chain's own coin (ETH/BNB/TRX/XLM/…) on any family — the same word the accept side uses (`token: 'native'`), so you never name per-chain tickers (the real ticker works too). It only ever matches a genuinely native asset, so it never loosens a stablecoin-only list. The MCP server's `PIPRAIL_TOKENS` is the same allowlist.
|
|
79
|
+
|
|
78
80
|
**Know the gas before you pay.** `client.estimateCost(url)` returns the quote **and** a `CostEstimate` — the network fee in the chain's **native coin** (you pay in USDC but burn ETH / SOL / TON / XLM / XRP / TRX on gas, a separate balance the agent must keep topped up). It's best-effort and labelled (`cost.basis`): a live-RPC read where cheap (`'estimated'` — EVM gas price, XRPL fee), a typical-cost constant otherwise (`'heuristic'`), and it never throws. Most valuable on **Tron**, where a USD₮ transfer can cost real TRX. So an agent can budget the *total* — payment **+** gas — before any funds move. Every driver implements it; the math is extracted per-chain and shaped uniformly by one shared `nativeCost()` helper.
|
|
79
81
|
|
|
80
82
|
### Plan before you pay — `planPayment()` (never fumble a payment)
|
|
@@ -276,6 +278,12 @@ requirePayment({ chain: 'near', token: { contractId: 'token.near', decimals: 6 }
|
|
|
276
278
|
|
|
277
279
|
// On Sui, a custom coin is { coinType, decimals }:
|
|
278
280
|
requirePayment({ chain: 'sui', token: { coinType: '0x…::usdc::USDC', decimals: 6 }, amount: '0.05', payTo })
|
|
281
|
+
|
|
282
|
+
// On Aptos, a custom Fungible Asset is { metadata, decimals }:
|
|
283
|
+
requirePayment({ chain: 'aptos', token: { metadata: '0x…', decimals: 6 }, amount: '0.05', payTo })
|
|
284
|
+
|
|
285
|
+
// On Algorand, a custom ASA is { assetId, decimals }:
|
|
286
|
+
requirePayment({ chain: 'algorand', token: { assetId: 12345678, decimals: 6 }, amount: '0.05', payTo })
|
|
279
287
|
```
|
|
280
288
|
|
|
281
289
|
> **Production:** the built-in chains use public RPCs (rate-limited). Pass your own `rpcUrl` for real traffic.
|
|
@@ -603,7 +611,7 @@ Methods: `fetch` · `get` · `post` (return the gated `Response` after settlemen
|
|
|
603
611
|
|
|
604
612
|
**Hand an LLM a wallet:** `paymentTools(client)` → framework-agnostic tool descriptors (MCP / AI SDK / function-calling), budget enforced by the client.
|
|
605
613
|
|
|
606
|
-
**Bring your own chain family:** the SDK is built on a tiny `PaymentDriver` contract — `resolve(chain)` returns a bound network with `resolveToken` / `describeAsset` / `assertValidPayTo` / `bindWallet` / `send` / `confirm` / `estimateCost` / `verify`. Register your own with `registerDriver(...)`; the protocol layer never changes (see [Architecture](#architecture-under-the-hood)).
|
|
614
|
+
**Bring your own chain family:** the SDK is built on a tiny `PaymentDriver` contract — `resolve(chain)` returns a bound network with `resolveToken` / `describeAsset` / `assertValidPayTo` / `bindWallet` / `send` / `confirm` / `estimateCost` / `balanceOf` / `recipientReady` / `verify`. Register your own with `registerDriver(...)`; the protocol layer never changes (see [Architecture](#architecture-under-the-hood)).
|
|
607
615
|
|
|
608
616
|
**Universal x402 (experimental):** building blocks to pay servers on the mainstream x402 `exact` scheme (EIP-3009 + facilitator) — `parseExactRequirements`, `buildExactAuthorization`, `encodeXPaymentHeader`. EVM-only; validate against your target facilitator before production.
|
|
609
617
|
|
package/dist/index.cjs
CHANGED
|
@@ -733,7 +733,7 @@ function makeEvmNetwork(resolved) {
|
|
|
733
733
|
}
|
|
734
734
|
return { token, native };
|
|
735
735
|
},
|
|
736
|
-
//
|
|
736
|
+
// No receive prerequisite — any 0x address receives native or ERC-20 immediately.
|
|
737
737
|
async recipientReady() {
|
|
738
738
|
return { ready: "n/a" };
|
|
739
739
|
},
|
|
@@ -923,7 +923,12 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
|
923
923
|
}
|
|
924
924
|
if (policy.tokens) {
|
|
925
925
|
const sym = intent.recognized ? intent.symbol : void 0;
|
|
926
|
-
|
|
926
|
+
const isNative = intent.asset === "native";
|
|
927
|
+
const matches = policy.tokens.some((t) => {
|
|
928
|
+
if (isNative && t.toUpperCase() === "NATIVE") return true;
|
|
929
|
+
return sym ? t.toUpperCase() === sym.toUpperCase() : false;
|
|
930
|
+
});
|
|
931
|
+
if (!matches) {
|
|
927
932
|
return deny(
|
|
928
933
|
`token ${_nullishCoalesce(intent.symbol, () => ( intent.asset))} is not in the allowed set (policy.tokens).`
|
|
929
934
|
);
|
package/dist/index.d.cts
CHANGED
|
@@ -3845,7 +3845,7 @@ interface AlgorandToken {
|
|
|
3845
3845
|
}
|
|
3846
3846
|
/**
|
|
3847
3847
|
* What to be paid in. Each driver validates the forms it accepts:
|
|
3848
|
-
* - 'native' the chain's native coin (ETH, BNB, SOL, TON, XLM, XRP)
|
|
3848
|
+
* - 'native' the chain's native coin (ETH, BNB, SOL, TON, XLM, XRP, TRX, NEAR, SUI, APT, ALGO)
|
|
3849
3849
|
* - 'USDC' (string) a symbol resolved against the chosen chain
|
|
3850
3850
|
* - EvmToken any ERC-20 (EVM chains)
|
|
3851
3851
|
* - SolanaToken any SPL token (Solana)
|
|
@@ -4014,8 +4014,11 @@ interface PaymentPolicy {
|
|
|
4014
4014
|
/** Allowlist of chains the agent may pay on. A 402 on any other chain is
|
|
4015
4015
|
* declined. Strings match the configured selector; objects match by id. */
|
|
4016
4016
|
chains?: ChainSelector[];
|
|
4017
|
-
/** Allowlist of token symbols (matched against the TRUE symbol).
|
|
4018
|
-
*
|
|
4017
|
+
/** Allowlist of token symbols (matched against the TRUE symbol). The special
|
|
4018
|
+
* value `'native'` is a chain-agnostic alias for the chain's native coin — it
|
|
4019
|
+
* matches the native asset on ANY family (ETH/BNB/TRX/XLM/…) without naming
|
|
4020
|
+
* the ticker, mirroring the merchant-side `token: 'native'`. An asset the SDK
|
|
4021
|
+
* can't recognise never satisfies this list. */
|
|
4019
4022
|
tokens?: string[];
|
|
4020
4023
|
/** Allowlist of hosts. Exact (`api.example.com`) or wildcard (`*.example.com`). */
|
|
4021
4024
|
hosts?: string[];
|
|
@@ -4130,6 +4133,8 @@ type PipRailEvent = {
|
|
|
4130
4133
|
* - Stellar → `{ secret }` (S… seed) or a ready `{ keypair }`
|
|
4131
4134
|
* - XRPL → `{ seed }` (s… seed) or a ready `{ wallet }`
|
|
4132
4135
|
* - NEAR → `{ accountId, privateKey }` (privateKey = ed25519:… secret)
|
|
4136
|
+
* - Aptos → `{ privateKey }` (AIP-80 `ed25519-priv-0x…` / raw `0x…` hex) or `{ account }`
|
|
4137
|
+
* - Algorand→ `{ mnemonic }` (25 words) or a ready `{ account }`
|
|
4133
4138
|
*/
|
|
4134
4139
|
type WalletInput = {
|
|
4135
4140
|
privateKey: string;
|
|
@@ -4263,7 +4268,7 @@ interface PipRailClientOptions {
|
|
|
4263
4268
|
/** Wallet for the chosen chain family. */
|
|
4264
4269
|
wallet: WalletInput;
|
|
4265
4270
|
/** Which chain to pay on. EVM ('bnb'|'base'|…), 'solana', 'ton', 'stellar',
|
|
4266
|
-
* 'xrpl', 'tron', 'sui', or '
|
|
4271
|
+
* 'xrpl', 'tron', 'sui', 'near', 'aptos', or 'algorand'. */
|
|
4267
4272
|
chain: ChainSelector;
|
|
4268
4273
|
/** Override the chain's default RPC URL (recommended in production). */
|
|
4269
4274
|
rpcUrl?: string;
|
|
@@ -4441,8 +4446,10 @@ interface AgentTool {
|
|
|
4441
4446
|
invoke: (args: Record<string, unknown>) => Promise<unknown>;
|
|
4442
4447
|
}
|
|
4443
4448
|
/**
|
|
4444
|
-
*
|
|
4449
|
+
* Three tools wrapping a configured {@link PipRailClient}:
|
|
4445
4450
|
* - `piprail_quote_payment(url)` — price a gated URL WITHOUT paying.
|
|
4451
|
+
* - `piprail_plan_payment(url)` — check you CAN pay (balance + gas + recipient
|
|
4452
|
+
* readiness) across every rail the URL offers, WITHOUT paying.
|
|
4446
4453
|
* - `piprail_pay_request(url, method?, body?)` — pay if needed and return the result.
|
|
4447
4454
|
*
|
|
4448
4455
|
* A policy/approval refusal comes back as a structured `{ declined: true, reason }`
|
|
@@ -4478,7 +4485,7 @@ declare function paymentTools(client: PipRailClient): AgentTool[];
|
|
|
4478
4485
|
*/
|
|
4479
4486
|
interface AcceptOption {
|
|
4480
4487
|
/** Which chain. EVM ('bnb'|'base'|…), 'solana', 'ton', 'stellar', 'xrpl',
|
|
4481
|
-
* 'tron', 'near', or '
|
|
4488
|
+
* 'tron', 'near', 'sui', 'aptos', or 'algorand'. */
|
|
4482
4489
|
chain: ChainSelector;
|
|
4483
4490
|
/** Token to be paid in (symbol / 'native' / custom descriptor). */
|
|
4484
4491
|
token: TokenInput;
|
|
@@ -4492,8 +4499,9 @@ interface AcceptOption {
|
|
|
4492
4499
|
interface RequirePaymentOptions {
|
|
4493
4500
|
/**
|
|
4494
4501
|
* Single-chain form: which chain to accept payment on. EVM ('bnb'|'base'|…),
|
|
4495
|
-
* 'solana', 'ton', 'stellar', 'xrpl', 'tron', 'near',
|
|
4496
|
-
* `chain` + `token` + `amount`, OR use the multi-chain
|
|
4502
|
+
* 'solana', 'ton', 'stellar', 'xrpl', 'tron', 'near', 'sui', 'aptos', or
|
|
4503
|
+
* 'algorand'. Provide `chain` + `token` + `amount`, OR use the multi-chain
|
|
4504
|
+
* `accept` array below.
|
|
4497
4505
|
*/
|
|
4498
4506
|
chain?: ChainSelector;
|
|
4499
4507
|
/** Override the chain's default RPC URL (recommended in production). */
|
|
@@ -4504,9 +4512,10 @@ interface RequirePaymentOptions {
|
|
|
4504
4512
|
* `{ address, decimals }` on EVM/Tron, `{ mint, decimals }` on Solana,
|
|
4505
4513
|
* `{ master, decimals }` on TON, `{ issuer, code, decimals }` on Stellar,
|
|
4506
4514
|
* `{ issuer, currencyHex, decimals }` on XRPL, `{ contractId, decimals }` on
|
|
4507
|
-
* NEAR, `{ coinType, decimals }` on Sui
|
|
4515
|
+
* NEAR, `{ coinType, decimals }` on Sui, `{ metadata, decimals }` on Aptos, or
|
|
4516
|
+
* `{ assetId, decimals }` on Algorand. You name the token; the SDK fills in
|
|
4508
4517
|
* the contract + decimals for built-in symbols. (Note: native USDC doesn't
|
|
4509
|
-
* exist on TON/Tron — USDT does; NEAR is
|
|
4518
|
+
* exist on TON/Tron — USDT does; native NEAR is supported via `'native'`.)
|
|
4510
4519
|
*/
|
|
4511
4520
|
token?: TokenInput;
|
|
4512
4521
|
/** Human-readable amount, e.g. "0.05" (single-chain form). */
|
|
@@ -4518,8 +4527,8 @@ interface RequirePaymentOptions {
|
|
|
4518
4527
|
*/
|
|
4519
4528
|
accept?: AcceptOption[];
|
|
4520
4529
|
/** Address that receives the payment (0x… EVM/Sui, base58 Solana, EQ…/UQ… TON,
|
|
4521
|
-
* G… Stellar, r… XRPL, T… Tron, account id on NEAR
|
|
4522
|
-
* form; the per-option fallback for the multi form. */
|
|
4530
|
+
* G… Stellar, r… XRPL, T… Tron, account id on NEAR, 0x… Aptos, base32 Algorand).
|
|
4531
|
+
* Required for the single form; the per-option fallback for the multi form. */
|
|
4523
4532
|
payTo?: AddressId;
|
|
4524
4533
|
/** Shown to the agent in the challenge. */
|
|
4525
4534
|
description?: string;
|
|
@@ -4669,7 +4678,7 @@ declare class InsufficientFundsError extends PipRailError {
|
|
|
4669
4678
|
* The message states the requirement and the fix in plain language **and echoes
|
|
4670
4679
|
* the raw chain code** (e.g. `(XRPL: tecNO_DST_INSUF_XRP)`), while the untouched
|
|
4671
4680
|
* chain error is preserved on `.cause` for deeper debugging. Chains with no
|
|
4672
|
-
* receive prerequisite (EVM, Solana, Sui, Tron, and native TON/NEAR) never throw it.
|
|
4681
|
+
* receive prerequisite (EVM, Solana, Sui, Aptos, Tron, and native TON/NEAR) never throw it.
|
|
4673
4682
|
*/
|
|
4674
4683
|
declare class RecipientNotReadyError extends PipRailError {
|
|
4675
4684
|
readonly code = "RECIPIENT_NOT_READY";
|
|
@@ -4766,7 +4775,7 @@ declare class NonReplayableBodyError extends PipRailError {
|
|
|
4766
4775
|
}
|
|
4767
4776
|
/**
|
|
4768
4777
|
* The chosen chain belongs to one family (EVM, Solana, TON, Stellar, XRPL, Tron,
|
|
4769
|
-
* Sui, NEAR) but the wallet, payTo, or token was given in another family's form
|
|
4778
|
+
* Sui, NEAR, Aptos, Algorand) but the wallet, payTo, or token was given in another family's form
|
|
4770
4779
|
* (e.g. an `0x…` payTo on Solana, or a `{ mint }` token on a Stellar chain).
|
|
4771
4780
|
*/
|
|
4772
4781
|
declare class WrongFamilyError extends PipRailError {
|
|
@@ -4778,7 +4787,8 @@ declare class WrongFamilyError extends PipRailError {
|
|
|
4778
4787
|
* token by full descriptor ({ address, decimals } EVM/Tron · { mint, decimals }
|
|
4779
4788
|
* Solana · { master, decimals } TON · { issuer, code, decimals } Stellar ·
|
|
4780
4789
|
* { issuer, currencyHex, decimals } XRPL · { coinType, decimals } Sui ·
|
|
4781
|
-
* { contractId, decimals } NEAR
|
|
4790
|
+
* { contractId, decimals } NEAR · { metadata, decimals } Aptos ·
|
|
4791
|
+
* { assetId, decimals } Algorand).
|
|
4782
4792
|
*/
|
|
4783
4793
|
declare class UnknownTokenError extends PipRailError {
|
|
4784
4794
|
readonly code = "UNKNOWN_TOKEN";
|
|
@@ -4790,7 +4800,8 @@ declare class UnknownTokenError extends PipRailError {
|
|
|
4790
4800
|
* `npm install @ton/ton @ton/core @ton/crypto`; Stellar:
|
|
4791
4801
|
* `npm install @stellar/stellar-sdk`; XRPL: `npm install xrpl`; Tron:
|
|
4792
4802
|
* `npm install tronweb`; Sui: `npm install @mysten/sui`; NEAR:
|
|
4793
|
-
* `npm install near-api-js
|
|
4803
|
+
* `npm install near-api-js`; Aptos: `npm install @aptos-labs/ts-sdk`;
|
|
4804
|
+
* Algorand: `npm install algosdk`.
|
|
4794
4805
|
*/
|
|
4795
4806
|
declare class MissingDriverError extends PipRailError {
|
|
4796
4807
|
readonly code = "MISSING_DRIVER";
|
package/dist/index.d.ts
CHANGED
|
@@ -3845,7 +3845,7 @@ interface AlgorandToken {
|
|
|
3845
3845
|
}
|
|
3846
3846
|
/**
|
|
3847
3847
|
* What to be paid in. Each driver validates the forms it accepts:
|
|
3848
|
-
* - 'native' the chain's native coin (ETH, BNB, SOL, TON, XLM, XRP)
|
|
3848
|
+
* - 'native' the chain's native coin (ETH, BNB, SOL, TON, XLM, XRP, TRX, NEAR, SUI, APT, ALGO)
|
|
3849
3849
|
* - 'USDC' (string) a symbol resolved against the chosen chain
|
|
3850
3850
|
* - EvmToken any ERC-20 (EVM chains)
|
|
3851
3851
|
* - SolanaToken any SPL token (Solana)
|
|
@@ -4014,8 +4014,11 @@ interface PaymentPolicy {
|
|
|
4014
4014
|
/** Allowlist of chains the agent may pay on. A 402 on any other chain is
|
|
4015
4015
|
* declined. Strings match the configured selector; objects match by id. */
|
|
4016
4016
|
chains?: ChainSelector[];
|
|
4017
|
-
/** Allowlist of token symbols (matched against the TRUE symbol).
|
|
4018
|
-
*
|
|
4017
|
+
/** Allowlist of token symbols (matched against the TRUE symbol). The special
|
|
4018
|
+
* value `'native'` is a chain-agnostic alias for the chain's native coin — it
|
|
4019
|
+
* matches the native asset on ANY family (ETH/BNB/TRX/XLM/…) without naming
|
|
4020
|
+
* the ticker, mirroring the merchant-side `token: 'native'`. An asset the SDK
|
|
4021
|
+
* can't recognise never satisfies this list. */
|
|
4019
4022
|
tokens?: string[];
|
|
4020
4023
|
/** Allowlist of hosts. Exact (`api.example.com`) or wildcard (`*.example.com`). */
|
|
4021
4024
|
hosts?: string[];
|
|
@@ -4130,6 +4133,8 @@ type PipRailEvent = {
|
|
|
4130
4133
|
* - Stellar → `{ secret }` (S… seed) or a ready `{ keypair }`
|
|
4131
4134
|
* - XRPL → `{ seed }` (s… seed) or a ready `{ wallet }`
|
|
4132
4135
|
* - NEAR → `{ accountId, privateKey }` (privateKey = ed25519:… secret)
|
|
4136
|
+
* - Aptos → `{ privateKey }` (AIP-80 `ed25519-priv-0x…` / raw `0x…` hex) or `{ account }`
|
|
4137
|
+
* - Algorand→ `{ mnemonic }` (25 words) or a ready `{ account }`
|
|
4133
4138
|
*/
|
|
4134
4139
|
type WalletInput = {
|
|
4135
4140
|
privateKey: string;
|
|
@@ -4263,7 +4268,7 @@ interface PipRailClientOptions {
|
|
|
4263
4268
|
/** Wallet for the chosen chain family. */
|
|
4264
4269
|
wallet: WalletInput;
|
|
4265
4270
|
/** Which chain to pay on. EVM ('bnb'|'base'|…), 'solana', 'ton', 'stellar',
|
|
4266
|
-
* 'xrpl', 'tron', 'sui', or '
|
|
4271
|
+
* 'xrpl', 'tron', 'sui', 'near', 'aptos', or 'algorand'. */
|
|
4267
4272
|
chain: ChainSelector;
|
|
4268
4273
|
/** Override the chain's default RPC URL (recommended in production). */
|
|
4269
4274
|
rpcUrl?: string;
|
|
@@ -4441,8 +4446,10 @@ interface AgentTool {
|
|
|
4441
4446
|
invoke: (args: Record<string, unknown>) => Promise<unknown>;
|
|
4442
4447
|
}
|
|
4443
4448
|
/**
|
|
4444
|
-
*
|
|
4449
|
+
* Three tools wrapping a configured {@link PipRailClient}:
|
|
4445
4450
|
* - `piprail_quote_payment(url)` — price a gated URL WITHOUT paying.
|
|
4451
|
+
* - `piprail_plan_payment(url)` — check you CAN pay (balance + gas + recipient
|
|
4452
|
+
* readiness) across every rail the URL offers, WITHOUT paying.
|
|
4446
4453
|
* - `piprail_pay_request(url, method?, body?)` — pay if needed and return the result.
|
|
4447
4454
|
*
|
|
4448
4455
|
* A policy/approval refusal comes back as a structured `{ declined: true, reason }`
|
|
@@ -4478,7 +4485,7 @@ declare function paymentTools(client: PipRailClient): AgentTool[];
|
|
|
4478
4485
|
*/
|
|
4479
4486
|
interface AcceptOption {
|
|
4480
4487
|
/** Which chain. EVM ('bnb'|'base'|…), 'solana', 'ton', 'stellar', 'xrpl',
|
|
4481
|
-
* 'tron', 'near', or '
|
|
4488
|
+
* 'tron', 'near', 'sui', 'aptos', or 'algorand'. */
|
|
4482
4489
|
chain: ChainSelector;
|
|
4483
4490
|
/** Token to be paid in (symbol / 'native' / custom descriptor). */
|
|
4484
4491
|
token: TokenInput;
|
|
@@ -4492,8 +4499,9 @@ interface AcceptOption {
|
|
|
4492
4499
|
interface RequirePaymentOptions {
|
|
4493
4500
|
/**
|
|
4494
4501
|
* Single-chain form: which chain to accept payment on. EVM ('bnb'|'base'|…),
|
|
4495
|
-
* 'solana', 'ton', 'stellar', 'xrpl', 'tron', 'near',
|
|
4496
|
-
* `chain` + `token` + `amount`, OR use the multi-chain
|
|
4502
|
+
* 'solana', 'ton', 'stellar', 'xrpl', 'tron', 'near', 'sui', 'aptos', or
|
|
4503
|
+
* 'algorand'. Provide `chain` + `token` + `amount`, OR use the multi-chain
|
|
4504
|
+
* `accept` array below.
|
|
4497
4505
|
*/
|
|
4498
4506
|
chain?: ChainSelector;
|
|
4499
4507
|
/** Override the chain's default RPC URL (recommended in production). */
|
|
@@ -4504,9 +4512,10 @@ interface RequirePaymentOptions {
|
|
|
4504
4512
|
* `{ address, decimals }` on EVM/Tron, `{ mint, decimals }` on Solana,
|
|
4505
4513
|
* `{ master, decimals }` on TON, `{ issuer, code, decimals }` on Stellar,
|
|
4506
4514
|
* `{ issuer, currencyHex, decimals }` on XRPL, `{ contractId, decimals }` on
|
|
4507
|
-
* NEAR, `{ coinType, decimals }` on Sui
|
|
4515
|
+
* NEAR, `{ coinType, decimals }` on Sui, `{ metadata, decimals }` on Aptos, or
|
|
4516
|
+
* `{ assetId, decimals }` on Algorand. You name the token; the SDK fills in
|
|
4508
4517
|
* the contract + decimals for built-in symbols. (Note: native USDC doesn't
|
|
4509
|
-
* exist on TON/Tron — USDT does; NEAR is
|
|
4518
|
+
* exist on TON/Tron — USDT does; native NEAR is supported via `'native'`.)
|
|
4510
4519
|
*/
|
|
4511
4520
|
token?: TokenInput;
|
|
4512
4521
|
/** Human-readable amount, e.g. "0.05" (single-chain form). */
|
|
@@ -4518,8 +4527,8 @@ interface RequirePaymentOptions {
|
|
|
4518
4527
|
*/
|
|
4519
4528
|
accept?: AcceptOption[];
|
|
4520
4529
|
/** Address that receives the payment (0x… EVM/Sui, base58 Solana, EQ…/UQ… TON,
|
|
4521
|
-
* G… Stellar, r… XRPL, T… Tron, account id on NEAR
|
|
4522
|
-
* form; the per-option fallback for the multi form. */
|
|
4530
|
+
* G… Stellar, r… XRPL, T… Tron, account id on NEAR, 0x… Aptos, base32 Algorand).
|
|
4531
|
+
* Required for the single form; the per-option fallback for the multi form. */
|
|
4523
4532
|
payTo?: AddressId;
|
|
4524
4533
|
/** Shown to the agent in the challenge. */
|
|
4525
4534
|
description?: string;
|
|
@@ -4669,7 +4678,7 @@ declare class InsufficientFundsError extends PipRailError {
|
|
|
4669
4678
|
* The message states the requirement and the fix in plain language **and echoes
|
|
4670
4679
|
* the raw chain code** (e.g. `(XRPL: tecNO_DST_INSUF_XRP)`), while the untouched
|
|
4671
4680
|
* chain error is preserved on `.cause` for deeper debugging. Chains with no
|
|
4672
|
-
* receive prerequisite (EVM, Solana, Sui, Tron, and native TON/NEAR) never throw it.
|
|
4681
|
+
* receive prerequisite (EVM, Solana, Sui, Aptos, Tron, and native TON/NEAR) never throw it.
|
|
4673
4682
|
*/
|
|
4674
4683
|
declare class RecipientNotReadyError extends PipRailError {
|
|
4675
4684
|
readonly code = "RECIPIENT_NOT_READY";
|
|
@@ -4766,7 +4775,7 @@ declare class NonReplayableBodyError extends PipRailError {
|
|
|
4766
4775
|
}
|
|
4767
4776
|
/**
|
|
4768
4777
|
* The chosen chain belongs to one family (EVM, Solana, TON, Stellar, XRPL, Tron,
|
|
4769
|
-
* Sui, NEAR) but the wallet, payTo, or token was given in another family's form
|
|
4778
|
+
* Sui, NEAR, Aptos, Algorand) but the wallet, payTo, or token was given in another family's form
|
|
4770
4779
|
* (e.g. an `0x…` payTo on Solana, or a `{ mint }` token on a Stellar chain).
|
|
4771
4780
|
*/
|
|
4772
4781
|
declare class WrongFamilyError extends PipRailError {
|
|
@@ -4778,7 +4787,8 @@ declare class WrongFamilyError extends PipRailError {
|
|
|
4778
4787
|
* token by full descriptor ({ address, decimals } EVM/Tron · { mint, decimals }
|
|
4779
4788
|
* Solana · { master, decimals } TON · { issuer, code, decimals } Stellar ·
|
|
4780
4789
|
* { issuer, currencyHex, decimals } XRPL · { coinType, decimals } Sui ·
|
|
4781
|
-
* { contractId, decimals } NEAR
|
|
4790
|
+
* { contractId, decimals } NEAR · { metadata, decimals } Aptos ·
|
|
4791
|
+
* { assetId, decimals } Algorand).
|
|
4782
4792
|
*/
|
|
4783
4793
|
declare class UnknownTokenError extends PipRailError {
|
|
4784
4794
|
readonly code = "UNKNOWN_TOKEN";
|
|
@@ -4790,7 +4800,8 @@ declare class UnknownTokenError extends PipRailError {
|
|
|
4790
4800
|
* `npm install @ton/ton @ton/core @ton/crypto`; Stellar:
|
|
4791
4801
|
* `npm install @stellar/stellar-sdk`; XRPL: `npm install xrpl`; Tron:
|
|
4792
4802
|
* `npm install tronweb`; Sui: `npm install @mysten/sui`; NEAR:
|
|
4793
|
-
* `npm install near-api-js
|
|
4803
|
+
* `npm install near-api-js`; Aptos: `npm install @aptos-labs/ts-sdk`;
|
|
4804
|
+
* Algorand: `npm install algosdk`.
|
|
4794
4805
|
*/
|
|
4795
4806
|
declare class MissingDriverError extends PipRailError {
|
|
4796
4807
|
readonly code = "MISSING_DRIVER";
|
package/dist/index.js
CHANGED
|
@@ -733,7 +733,7 @@ function makeEvmNetwork(resolved) {
|
|
|
733
733
|
}
|
|
734
734
|
return { token, native };
|
|
735
735
|
},
|
|
736
|
-
//
|
|
736
|
+
// No receive prerequisite — any 0x address receives native or ERC-20 immediately.
|
|
737
737
|
async recipientReady() {
|
|
738
738
|
return { ready: "n/a" };
|
|
739
739
|
},
|
|
@@ -923,7 +923,12 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
|
|
|
923
923
|
}
|
|
924
924
|
if (policy.tokens) {
|
|
925
925
|
const sym = intent.recognized ? intent.symbol : void 0;
|
|
926
|
-
|
|
926
|
+
const isNative = intent.asset === "native";
|
|
927
|
+
const matches = policy.tokens.some((t) => {
|
|
928
|
+
if (isNative && t.toUpperCase() === "NATIVE") return true;
|
|
929
|
+
return sym ? t.toUpperCase() === sym.toUpperCase() : false;
|
|
930
|
+
});
|
|
931
|
+
if (!matches) {
|
|
927
932
|
return deny(
|
|
928
933
|
`token ${intent.symbol ?? intent.asset} is not in the allowed set (policy.tokens).`
|
|
929
934
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Accept x402 crypto payments across 28 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",
|
|
@@ -82,13 +82,13 @@
|
|
|
82
82
|
"peerDependencies": {
|
|
83
83
|
"@aptos-labs/ts-sdk": ">=2 <8",
|
|
84
84
|
"@mysten/sui": ">=2 <3",
|
|
85
|
-
"algosdk": ">=3 <4",
|
|
86
85
|
"@solana/spl-token": "^0.4.0",
|
|
87
86
|
"@solana/web3.js": "^1.95.0",
|
|
88
87
|
"@stellar/stellar-sdk": ">=13 <16",
|
|
89
88
|
"@ton/core": ">=0.59 <1",
|
|
90
89
|
"@ton/crypto": ">=3 <4",
|
|
91
90
|
"@ton/ton": ">=15 <17",
|
|
91
|
+
"algosdk": ">=3 <4",
|
|
92
92
|
"bs58": "^5.0.0",
|
|
93
93
|
"near-api-js": ">=7 <8",
|
|
94
94
|
"tronweb": ">=6 <7",
|