@piprail/sdk 1.23.0 → 1.25.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 +63 -0
- package/README.md +28 -1
- package/dist/index.cjs +277 -21
- package/dist/index.d.cts +198 -5
- package/dist/index.d.ts +198 -5
- package/dist/index.js +267 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3493,6 +3493,33 @@ function rankOptions(options) {
|
|
|
3493
3493
|
return 0;
|
|
3494
3494
|
});
|
|
3495
3495
|
}
|
|
3496
|
+
function rankAcross(plans) {
|
|
3497
|
+
const rank = { payable: 0, unknown: 1, blocked: 2 };
|
|
3498
|
+
return plans.flatMap((p) => p.options).sort((a, b) => rank[a.state] - rank[b.state]);
|
|
3499
|
+
}
|
|
3500
|
+
async function planEachClient(clients, url, init) {
|
|
3501
|
+
const settled = await Promise.allSettled(clients.map((c) => c.planPayment(url, init)));
|
|
3502
|
+
const live = [];
|
|
3503
|
+
let anyReached = false;
|
|
3504
|
+
let firstError;
|
|
3505
|
+
settled.forEach((s, i) => {
|
|
3506
|
+
if (s.status === "fulfilled") {
|
|
3507
|
+
anyReached = true;
|
|
3508
|
+
if (s.value != null) live.push({ client: clients[i], plan: s.value });
|
|
3509
|
+
} else if (firstError === void 0) {
|
|
3510
|
+
firstError = s.reason;
|
|
3511
|
+
}
|
|
3512
|
+
});
|
|
3513
|
+
if (live.length === 0 && !anyReached) {
|
|
3514
|
+
throw firstError ?? new Error("planAcross: every client failed to reach the resource.");
|
|
3515
|
+
}
|
|
3516
|
+
return live;
|
|
3517
|
+
}
|
|
3518
|
+
function mergeDeclineHint(plans) {
|
|
3519
|
+
const actionable = plans.filter((p) => p.options.length > 0 && p.fundingHint).map((p) => p.fundingHint);
|
|
3520
|
+
const chosen = actionable.length ? actionable : plans.map((p) => p.fundingHint).filter(Boolean);
|
|
3521
|
+
return chosen.length ? [...new Set(chosen)].join(" \xB7 ") : null;
|
|
3522
|
+
}
|
|
3496
3523
|
function buildFundingHint(options, chainLabel) {
|
|
3497
3524
|
if (options.length === 0) return null;
|
|
3498
3525
|
const target = [...options].sort((a, b) => a.blockers.length - b.blockers.length)[0];
|
|
@@ -3519,10 +3546,10 @@ function buildFundingHint(options, chainLabel) {
|
|
|
3519
3546
|
return parts.length ? `Can't settle on ${chainLabel}: ${parts.join(" and ")} (to pay ${target.quote.amountFormatted} ${sym}).` : `Can't settle on ${chainLabel} for ${target.quote.amountFormatted} ${sym}.`;
|
|
3520
3547
|
}
|
|
3521
3548
|
async function planAcross(clients, url, init) {
|
|
3522
|
-
|
|
3523
|
-
const live =
|
|
3549
|
+
if (clients.length === 0) return null;
|
|
3550
|
+
const live = (await planEachClient(clients, url, init)).map((p) => p.plan);
|
|
3524
3551
|
if (live.length === 0) return null;
|
|
3525
|
-
const options =
|
|
3552
|
+
const options = rankAcross(live);
|
|
3526
3553
|
const best = options.find((o) => o.state === "payable") ?? null;
|
|
3527
3554
|
const status = best ? "ready" : options.some((o) => o.state === "unknown") ? "unknown" : "blocked";
|
|
3528
3555
|
return {
|
|
@@ -3532,10 +3559,25 @@ async function planAcross(clients, url, init) {
|
|
|
3532
3559
|
payable: best !== null,
|
|
3533
3560
|
best,
|
|
3534
3561
|
options,
|
|
3535
|
-
//
|
|
3536
|
-
|
|
3562
|
+
// Merge EVERY funded chain's blocker into one clear sentence (not just the first) —
|
|
3563
|
+
// see mergeDeclineHint. `null` when a rail is payable.
|
|
3564
|
+
fundingHint: best ? null : mergeDeclineHint(live)
|
|
3537
3565
|
};
|
|
3538
3566
|
}
|
|
3567
|
+
async function fetchAcross(clients, url, init) {
|
|
3568
|
+
if (clients.length === 0) {
|
|
3569
|
+
throw new TypeError("fetchAcross needs at least one PipRailClient.");
|
|
3570
|
+
}
|
|
3571
|
+
const live = await planEachClient(clients, url, init);
|
|
3572
|
+
if (live.length === 0) return clients[0].fetch(url, init);
|
|
3573
|
+
const best = rankAcross(live.map((p) => p.plan)).find((o) => o.state === "payable");
|
|
3574
|
+
if (!best) {
|
|
3575
|
+
const hint = mergeDeclineHint(live.map((p) => p.plan));
|
|
3576
|
+
throw new PaymentDeclinedError(hint || "No funded chain can settle this payment right now.");
|
|
3577
|
+
}
|
|
3578
|
+
const owner = live.find((p) => p.plan.options.includes(best)).client;
|
|
3579
|
+
return owner.fetch(url, { ...init ?? {}, autoRoute: true });
|
|
3580
|
+
}
|
|
3539
3581
|
function railOnNetwork(rail, matches) {
|
|
3540
3582
|
const n = normalizeNetwork(rail.network);
|
|
3541
3583
|
return !n.includes(":") || matches(n);
|
|
@@ -3601,6 +3643,187 @@ async function readInvalidReason(response) {
|
|
|
3601
3643
|
return null;
|
|
3602
3644
|
}
|
|
3603
3645
|
|
|
3646
|
+
// src/payer.ts
|
|
3647
|
+
var MultiChainPayer = class _MultiChainPayer {
|
|
3648
|
+
_clients;
|
|
3649
|
+
/**
|
|
3650
|
+
* Wrap an explicit, ordered set of single-chain clients — use this when a client
|
|
3651
|
+
* needs full control (e.g. a custom EVM chain configured by a viem `Chain`). The
|
|
3652
|
+
* ORDER is your chain preference: across chains the first that can settle wins. Pass
|
|
3653
|
+
* at MOST one client per chain — two clients on the SAME network would double-count in
|
|
3654
|
+
* `spent()`/`budget()` and waste a plan round-trip (`fromWallets` can't produce this).
|
|
3655
|
+
* For the common case, prefer {@link MultiChainPayer.fromWallets}.
|
|
3656
|
+
*/
|
|
3657
|
+
constructor(clients) {
|
|
3658
|
+
if (clients.length === 0) {
|
|
3659
|
+
throw new TypeError("MultiChainPayer needs at least one PipRailClient.");
|
|
3660
|
+
}
|
|
3661
|
+
this._clients = [...clients];
|
|
3662
|
+
}
|
|
3663
|
+
/**
|
|
3664
|
+
* Build one client per funded chain from a `{ chain → wallet }` map — the
|
|
3665
|
+
* ergonomic path. The shared `policy`/`schemes`/`onBeforePay`/`onEvent` apply to
|
|
3666
|
+
* every client; `rpcUrls` are matched per chain. Iteration order of `wallets` is
|
|
3667
|
+
* the chain preference.
|
|
3668
|
+
*
|
|
3669
|
+
* ```ts
|
|
3670
|
+
* const payer = MultiChainPayer.fromWallets({
|
|
3671
|
+
* wallets: {
|
|
3672
|
+
* base: { privateKey: process.env.EVM_KEY! },
|
|
3673
|
+
* solana: { secretKey: process.env.SOLANA_SECRET! },
|
|
3674
|
+
* xrpl: { seed: process.env.XRPL_SEED! },
|
|
3675
|
+
* },
|
|
3676
|
+
* policy: { maxAmount: '1.00', maxTotal: '20.00', tokens: ['USDC', 'USDT'] },
|
|
3677
|
+
* })
|
|
3678
|
+
* const res = await payer.get('https://api.example.com/paid') // pays on the first funded chain that can settle
|
|
3679
|
+
* ```
|
|
3680
|
+
*/
|
|
3681
|
+
static fromWallets(opts) {
|
|
3682
|
+
const entries = Object.entries(opts.wallets);
|
|
3683
|
+
if (entries.length === 0) {
|
|
3684
|
+
throw new TypeError("MultiChainPayer.fromWallets needs at least one wallet.");
|
|
3685
|
+
}
|
|
3686
|
+
const clients = entries.map(
|
|
3687
|
+
([chain, wallet]) => new PipRailClient({
|
|
3688
|
+
chain,
|
|
3689
|
+
wallet,
|
|
3690
|
+
...opts.policy ? { policy: opts.policy } : {},
|
|
3691
|
+
...opts.schemes ? { schemes: opts.schemes } : {},
|
|
3692
|
+
...opts.rpcUrls?.[chain] ? { rpcUrl: opts.rpcUrls[chain] } : {},
|
|
3693
|
+
...opts.onBeforePay ? { onBeforePay: opts.onBeforePay } : {},
|
|
3694
|
+
...opts.onEvent ? { onEvent: opts.onEvent } : {},
|
|
3695
|
+
...opts.maxPaymentRetries != null ? { maxPaymentRetries: opts.maxPaymentRetries } : {},
|
|
3696
|
+
...opts.retryTimeoutMs != null ? { retryTimeoutMs: opts.retryTimeoutMs } : {}
|
|
3697
|
+
})
|
|
3698
|
+
);
|
|
3699
|
+
return new _MultiChainPayer(clients);
|
|
3700
|
+
}
|
|
3701
|
+
/** The underlying single-chain clients, in preference order. Reach for one of
|
|
3702
|
+
* these for chain-specific reads (`estimateCost`, `discoverySigner`, per-chain
|
|
3703
|
+
* `budget()`) that don't make sense merged. */
|
|
3704
|
+
get clients() {
|
|
3705
|
+
return this._clients;
|
|
3706
|
+
}
|
|
3707
|
+
/** Plan a 402 across every funded chain — merged + ranked payable-first. `null`
|
|
3708
|
+
* when the URL needs no payment. (Delegates to {@link planAcross}.) */
|
|
3709
|
+
planPayment(url, init) {
|
|
3710
|
+
return planAcross(this._clients, url, init);
|
|
3711
|
+
}
|
|
3712
|
+
/** Can ANY funded chain settle this URL right now? (A free resource is trivially
|
|
3713
|
+
* "affordable".) No funds move. */
|
|
3714
|
+
async canAfford(url, init) {
|
|
3715
|
+
const plan = await this.planPayment(url, init);
|
|
3716
|
+
return plan == null ? true : plan.payable;
|
|
3717
|
+
}
|
|
3718
|
+
/** Price a gated URL across funded chains — the chosen rail's quote (the first
|
|
3719
|
+
* funded chain that can settle), else the first offered rail's. `null` when the URL
|
|
3720
|
+
* needs no payment. When it IS
|
|
3721
|
+
* gated but none of your chains are offered, surfaces the same informative
|
|
3722
|
+
* `NoCompatibleAcceptError` a single client would (it names the chains the 402 is
|
|
3723
|
+
* payable on) rather than a misleading `null`. No funds move. */
|
|
3724
|
+
async quote(url, init) {
|
|
3725
|
+
const plan = await this.planPayment(url, init);
|
|
3726
|
+
if (plan == null) return null;
|
|
3727
|
+
const opt = plan.best ?? plan.options[0];
|
|
3728
|
+
if (opt) return opt.quote;
|
|
3729
|
+
return this._clients[0].quote(url, init);
|
|
3730
|
+
}
|
|
3731
|
+
/** Pay the first funded chain (in your listed order) that can settle this URL.
|
|
3732
|
+
* Delegates to {@link fetchAcross} — full policy / approval / retry / replay path on
|
|
3733
|
+
* the owning client. The owner re-reads balances at pay time, so the rail paid is the
|
|
3734
|
+
* surfaced `best` on a best-effort basis (it can pick another rail on the SAME chain,
|
|
3735
|
+
* or decline, if balances shift between plan and pay). PROBES the URL with `init`
|
|
3736
|
+
* (method + body) per client — prefer GET / idempotent requests. */
|
|
3737
|
+
fetch(url, init) {
|
|
3738
|
+
return fetchAcross(this._clients, url, init);
|
|
3739
|
+
}
|
|
3740
|
+
/** GET that auto-pays across chains. */
|
|
3741
|
+
get(url, init) {
|
|
3742
|
+
return this.fetch(url, { ...init ?? {}, method: "GET" });
|
|
3743
|
+
}
|
|
3744
|
+
/**
|
|
3745
|
+
* POST that auto-pays across chains. `body` is a string/FormData/URLSearchParams/
|
|
3746
|
+
* ArrayBuffer/Blob (sent as-is) or a plain object (serialised as JSON) — mirrors
|
|
3747
|
+
* {@link PipRailClient.post}.
|
|
3748
|
+
*/
|
|
3749
|
+
post(url, body, init) {
|
|
3750
|
+
const headers = new Headers(init?.headers);
|
|
3751
|
+
let payload;
|
|
3752
|
+
if (body === void 0 || body === null) {
|
|
3753
|
+
payload = void 0;
|
|
3754
|
+
} else if (isBodyInit(body)) {
|
|
3755
|
+
payload = body;
|
|
3756
|
+
} else if (typeof body === "object") {
|
|
3757
|
+
payload = JSON.stringify(body);
|
|
3758
|
+
if (!headers.has("content-type")) headers.set("content-type", "application/json");
|
|
3759
|
+
} else {
|
|
3760
|
+
payload = String(body);
|
|
3761
|
+
}
|
|
3762
|
+
return this.fetch(url, { ...init ?? {}, method: "POST", headers, body: payload });
|
|
3763
|
+
}
|
|
3764
|
+
/**
|
|
3765
|
+
* Find payable resources across every funded chain. With the default
|
|
3766
|
+
* `network: 'self'`, each chain's own results are merged + deduped by URL (so
|
|
3767
|
+
* "self" means "any chain I can pay"). A network-scoped query (a CAIP-2 id or
|
|
3768
|
+
* `'any'`) is chain-independent, so one client answers it. Never throws for a
|
|
3769
|
+
* read problem; moves no funds.
|
|
3770
|
+
*/
|
|
3771
|
+
async discover(opts = {}) {
|
|
3772
|
+
if (opts.network && opts.network !== "self") {
|
|
3773
|
+
return this._clients[0].discover(opts);
|
|
3774
|
+
}
|
|
3775
|
+
const perChain = await Promise.all(
|
|
3776
|
+
this._clients.map((c) => c.discover({ ...opts, network: "self" }).catch(() => []))
|
|
3777
|
+
);
|
|
3778
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3779
|
+
const merged = [];
|
|
3780
|
+
for (const r of perChain.flat()) {
|
|
3781
|
+
if (seen.has(r.resource)) continue;
|
|
3782
|
+
seen.add(r.resource);
|
|
3783
|
+
merged.push(r);
|
|
3784
|
+
}
|
|
3785
|
+
return merged;
|
|
3786
|
+
}
|
|
3787
|
+
/** List a resource YOU run on the open indexes. Registration is a merchant action
|
|
3788
|
+
* independent of which chain you pay FROM, so it goes through your first chain's
|
|
3789
|
+
* client; pass `opts.network` to advertise a specific chain. Moves no funds. */
|
|
3790
|
+
register(url, opts = {}) {
|
|
3791
|
+
return this._clients[0].register(url, opts);
|
|
3792
|
+
}
|
|
3793
|
+
/** Aggregate spend across every chain — counts summed; per-(network,asset) rows
|
|
3794
|
+
* and records concatenated (no cross-chain collisions, never a cross-token sum). */
|
|
3795
|
+
spent() {
|
|
3796
|
+
const summaries = this._clients.map((c) => c.spent());
|
|
3797
|
+
return {
|
|
3798
|
+
count: summaries.reduce((n, s) => n + s.count, 0),
|
|
3799
|
+
byAsset: summaries.flatMap((s) => s.byAsset),
|
|
3800
|
+
records: summaries.flatMap((s) => s.records)
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
/** A merged budget view: every chain's per-(network,asset) remaining rows, plus the
|
|
3804
|
+
* MOST-RESTRICTIVE session time envelope across chains (the soonest deadline wins).
|
|
3805
|
+
* Mirrors {@link PipRailClient.budget}'s shape so the agent toolkit reads it
|
|
3806
|
+
* unchanged; per-chain session detail is on each `clients[i].budget()`. */
|
|
3807
|
+
budget() {
|
|
3808
|
+
const budgets = this._clients.map((c) => c.budget());
|
|
3809
|
+
const session = budgets.map((b) => b.session).reduce((soonest, s) => {
|
|
3810
|
+
if (soonest.secondsRemaining == null) return s;
|
|
3811
|
+
if (s.secondsRemaining == null) return soonest;
|
|
3812
|
+
return s.secondsRemaining < soonest.secondsRemaining ? s : soonest;
|
|
3813
|
+
});
|
|
3814
|
+
return { session, byAsset: budgets.flatMap((b) => b.byAsset) };
|
|
3815
|
+
}
|
|
3816
|
+
};
|
|
3817
|
+
function isBodyInit(value) {
|
|
3818
|
+
if (typeof value === "string") return true;
|
|
3819
|
+
if (value instanceof ArrayBuffer) return true;
|
|
3820
|
+
if (ArrayBuffer.isView(value)) return true;
|
|
3821
|
+
if (typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams) return true;
|
|
3822
|
+
if (typeof FormData !== "undefined" && value instanceof FormData) return true;
|
|
3823
|
+
if (typeof Blob !== "undefined" && value instanceof Blob) return true;
|
|
3824
|
+
return false;
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3604
3827
|
// src/selfdescribe.ts
|
|
3605
3828
|
var BRAND = {
|
|
3606
3829
|
name: "PipRail",
|
|
@@ -4003,7 +4226,12 @@ function paymentTools(client) {
|
|
|
4003
4226
|
url: { type: "string", description: "Full URL of the resource to list." },
|
|
4004
4227
|
name: { type: "string", description: "Display name (defaults to the host)." },
|
|
4005
4228
|
description: { type: "string", description: "What the resource offers." },
|
|
4006
|
-
priceUsd: { type: "number", description: "Advertised price in USD (metadata)." }
|
|
4229
|
+
priceUsd: { type: "number", description: "Advertised price in USD (metadata)." },
|
|
4230
|
+
network: {
|
|
4231
|
+
type: "string",
|
|
4232
|
+
description: "Network slug to advertise, e.g. 'base' (defaults to the paying chain). Set it when registering from a multi-chain wallet so the listing names the right chain."
|
|
4233
|
+
},
|
|
4234
|
+
asset: { type: "string", description: "Payment asset symbol, e.g. 'USDC' (metadata)." }
|
|
4007
4235
|
},
|
|
4008
4236
|
required: ["url"],
|
|
4009
4237
|
additionalProperties: false
|
|
@@ -4013,6 +4241,8 @@ function paymentTools(client) {
|
|
|
4013
4241
|
if (typeof args.name === "string") opts.name = args.name;
|
|
4014
4242
|
if (typeof args.description === "string") opts.description = args.description;
|
|
4015
4243
|
if (typeof args.priceUsd === "number") opts.priceUsd = args.priceUsd;
|
|
4244
|
+
if (typeof args.network === "string") opts.network = args.network;
|
|
4245
|
+
if (typeof args.asset === "string") opts.asset = args.asset;
|
|
4016
4246
|
const outcomes = await client.register(String(args.url), opts);
|
|
4017
4247
|
return { outcomes };
|
|
4018
4248
|
}
|
|
@@ -4808,25 +5038,49 @@ function normaliseHeader(value) {
|
|
|
4808
5038
|
|
|
4809
5039
|
// src/facilitators.ts
|
|
4810
5040
|
var KNOWN_FACILITATORS = {
|
|
4811
|
-
//
|
|
4812
|
-
//
|
|
5041
|
+
// Base (eip155:8453). Every entry is keyless and LIVE-settled by us (a real EIP-3009
|
|
5042
|
+
// exact payment, buyer paid zero ETH) — not just a /supported read — on the dated day.
|
|
4813
5043
|
"eip155:8453": [
|
|
4814
5044
|
{
|
|
4815
5045
|
url: "https://facilitator.payai.network",
|
|
4816
5046
|
keyless: true,
|
|
4817
5047
|
schemes: ["exact"],
|
|
4818
5048
|
settles: ["eip3009"],
|
|
4819
|
-
note: "PayAI \u2014 keyless, sponsors gas (Base USDC EIP-3009)"
|
|
5049
|
+
note: "PayAI \u2014 keyless, sponsors gas (Base USDC EIP-3009). Verified 2026-06-14 (/supported + live demo)."
|
|
5050
|
+
},
|
|
5051
|
+
{
|
|
5052
|
+
url: "https://facilitator.xpay.sh",
|
|
5053
|
+
keyless: true,
|
|
5054
|
+
schemes: ["exact"],
|
|
5055
|
+
settles: ["eip3009"],
|
|
5056
|
+
note: "xpay \u2014 keyless, zero-fee, sponsors gas. LIVE-settled on Base 2026-06-15 (tx 0x2273d5\u2026)."
|
|
4820
5057
|
}
|
|
4821
5058
|
],
|
|
4822
|
-
//
|
|
5059
|
+
// Solana (mainnet-beta). Keyless fee-payer sponsors for the SVM exact rail, each LIVE-settled
|
|
5060
|
+
// by us (a real SPL TransferChecked, buyer paid zero SOL) on the dated day — beyond a /supported
|
|
5061
|
+
// read. Daydreams + Questflow are intentionally ABSENT: their /supported is public but /verify
|
|
5062
|
+
// returns 401 (an API key is required), so they are not keyless for settlement.
|
|
4823
5063
|
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": [
|
|
4824
5064
|
{
|
|
4825
5065
|
url: "https://facilitator.payai.network",
|
|
4826
5066
|
keyless: true,
|
|
4827
5067
|
schemes: ["exact"],
|
|
4828
5068
|
settles: ["svm"],
|
|
4829
|
-
note: "PayAI \u2014 keyless fee-payer sponsor (Solana SPL SVM)"
|
|
5069
|
+
note: "PayAI \u2014 keyless fee-payer sponsor (Solana SPL SVM). LIVE-settled 2026-06-14 (tx 4dL8jRKH\u2026)."
|
|
5070
|
+
},
|
|
5071
|
+
{
|
|
5072
|
+
url: "https://pay.openfacilitator.io",
|
|
5073
|
+
keyless: true,
|
|
5074
|
+
schemes: ["exact"],
|
|
5075
|
+
settles: ["svm"],
|
|
5076
|
+
note: "OpenFacilitator \u2014 keyless (no signup), fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx 5BabDtX\u2026)."
|
|
5077
|
+
},
|
|
5078
|
+
{
|
|
5079
|
+
url: "https://facilitator.corbits.dev",
|
|
5080
|
+
keyless: true,
|
|
5081
|
+
schemes: ["exact"],
|
|
5082
|
+
settles: ["svm"],
|
|
5083
|
+
note: "Corbits \u2014 keyless, Solana-first fee-payer sponsor. LIVE-settled on Solana 2026-06-15 (tx BCreYer\u2026)."
|
|
4830
5084
|
}
|
|
4831
5085
|
]
|
|
4832
5086
|
};
|
|
@@ -4960,6 +5214,7 @@ export {
|
|
|
4960
5214
|
KNOWN_FACILITATORS,
|
|
4961
5215
|
MaxRetriesExceededError,
|
|
4962
5216
|
MissingDriverError,
|
|
5217
|
+
MultiChainPayer,
|
|
4963
5218
|
NoCompatibleAcceptError,
|
|
4964
5219
|
NonReplayableBodyError,
|
|
4965
5220
|
PERMIT2_ADDRESS,
|
|
@@ -5006,6 +5261,7 @@ export {
|
|
|
5006
5261
|
evaluatePolicy,
|
|
5007
5262
|
explainDecline,
|
|
5008
5263
|
facilitatorCoverage,
|
|
5264
|
+
fetchAcross,
|
|
5009
5265
|
firstKeylessFacilitator,
|
|
5010
5266
|
formatSpendReport,
|
|
5011
5267
|
getDirectoryInfo,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.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",
|