@piprail/sdk 2.1.1 → 2.2.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 +25 -0
- package/dist/index.cjs +29 -10
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +25 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ 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
|
+
## [2.2.0] — 2026-06-16 — broader x402 ecosystem interoperability
|
|
8
|
+
|
|
9
|
+
Both changes are additive and backward-compatible — defaults and the zero-config 402 stay
|
|
10
|
+
byte-identical; only previously-skipped cases become newly handled.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **The `exact` buyer matches a rail's network whether it's a CAIP-2 id _or_ a chain slug.** The pay
|
|
15
|
+
path now normalizes the offered network (`eip155:8453`, `base`, `bsc`, `56`, …) before matching it to
|
|
16
|
+
the bound chain — the same normalization discovery already used — so a PipRail client interoperates
|
|
17
|
+
with any x402 server or facilitator regardless of how it labels the network. Strictly additive: a
|
|
18
|
+
CAIP-2 label behaves exactly as before; only a chain slug that resolves to the **bound** chain becomes
|
|
19
|
+
newly payable (a different-chain or unrecognized label is never selected, and the trusted EIP-712
|
|
20
|
+
domain still fixes the chain id at signing). Fixes `exact` rails that some facilitators label by slug
|
|
21
|
+
being silently unpayable.
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`facilitatorCoverage()` / `parseFacilitatorSupported()` surface two optional per-kind fields** —
|
|
26
|
+
`x402Version` and `assetTransferMethod` (`'eip3009' | 'permit2'`) — when a facilitator's `GET
|
|
27
|
+
/supported` advertises them, so coverage can tell a v1 rail from a v2 rail and an EIP-3009 kind from a
|
|
28
|
+
Permit2 one. Omitted entirely when absent (no `undefined` keys), so a facilitator reporting neither
|
|
29
|
+
parses exactly as before.
|
|
30
|
+
|
|
7
31
|
## [2.1.1] — 2026-06-15 — discoverability polish (post-2.1.0 audit)
|
|
8
32
|
|
|
9
33
|
A consistency patch from a deep docs↔source audit of the 2.1.0 discoverability surface. No
|
|
@@ -1196,6 +1220,7 @@ straight into your wallet. The API is small and self-contained.
|
|
|
1196
1220
|
to your wallet; PipRail never holds funds.
|
|
1197
1221
|
- `viem ^2.21` is a peer dependency. Node 20+ or a modern browser.
|
|
1198
1222
|
|
|
1223
|
+
[2.2.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
1199
1224
|
[2.1.1]: https://www.npmjs.com/package/@piprail/sdk
|
|
1200
1225
|
[2.1.0]: https://www.npmjs.com/package/@piprail/sdk
|
|
1201
1226
|
[2.0.2]: https://www.npmjs.com/package/@piprail/sdk
|
package/dist/index.cjs
CHANGED
|
@@ -3220,7 +3220,7 @@ var PipRailClient = (_class2 = class {
|
|
|
3220
3220
|
const candidates = this.gatherCandidates(net, challenge, schemes);
|
|
3221
3221
|
if (candidates.length === 0) {
|
|
3222
3222
|
const exactOnNet = challenge.accepts.some(
|
|
3223
|
-
(a) => a.scheme === "exact" &&
|
|
3223
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network)
|
|
3224
3224
|
);
|
|
3225
3225
|
if (schemes.includes("exact") && exactOnNet && typeof net.payExact !== "function") {
|
|
3226
3226
|
throw new (0, _chunkJG6KRAW6cjs.UnsupportedSchemeError)(
|
|
@@ -3229,7 +3229,7 @@ var PipRailClient = (_class2 = class {
|
|
|
3229
3229
|
}
|
|
3230
3230
|
if (!schemes.includes("exact") && exactOnNet && typeof net.payExact === "function") {
|
|
3231
3231
|
const payable = challenge.accepts.some(
|
|
3232
|
-
(a) => a.scheme === "exact" &&
|
|
3232
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && net.describeAsset(a.asset) != null
|
|
3233
3233
|
);
|
|
3234
3234
|
if (payable) {
|
|
3235
3235
|
throw new (0, _chunkJG6KRAW6cjs.NoCompatibleAcceptError)(
|
|
@@ -3249,6 +3249,17 @@ var PipRailClient = (_class2 = class {
|
|
|
3249
3249
|
const chosen = _nullishCoalesce(priced.find((p) => p.quote.withinPolicy), () => ( priced[0]));
|
|
3250
3250
|
return { net, wallet, accept: chosen.accept, challenge, quote: chosen.quote };
|
|
3251
3251
|
}
|
|
3252
|
+
/** Match a foreign-supplied network string against the bound driver, tolerating a
|
|
3253
|
+
* SLUG ('bsc', 'base', '56') the SAME way discovery's `railOnNetwork` already does —
|
|
3254
|
+
* normalize to CAIP-2 first, since a foreign/AEON/community 402 may label the network
|
|
3255
|
+
* with a slug (AEON serves v1 duplicate kinds '56'/'bsc'). ADDITIVE: a value that's
|
|
3256
|
+
* already CAIP-2 passes through `normalizeNetwork` UNCHANGED, so every existing
|
|
3257
|
+
* exact-CAIP-2 match is byte-identical; only slugs resolving to the bound chain become
|
|
3258
|
+
* newly matchable (an unknown slug stays unresolved → still unmatched; a different
|
|
3259
|
+
* chain's slug resolves elsewhere → still unmatched). */
|
|
3260
|
+
supportsNetwork(net, network) {
|
|
3261
|
+
return net.supports(normalizeNetwork(network));
|
|
3262
|
+
}
|
|
3252
3263
|
/** The candidate accepts this client could pay, on the bound network. Always the
|
|
3253
3264
|
* backendless `onchain-proof` rails; PLUS standard `exact` rails when `schemes`
|
|
3254
3265
|
* enables them AND the driver can settle them (EVM `payExact` + a recognised
|
|
@@ -3259,14 +3270,14 @@ var PipRailClient = (_class2 = class {
|
|
|
3259
3270
|
if (schemes.includes("onchain-proof")) {
|
|
3260
3271
|
out.push(
|
|
3261
3272
|
...challenge.accepts.filter(
|
|
3262
|
-
(a) => a.scheme === "onchain-proof" &&
|
|
3273
|
+
(a) => a.scheme === "onchain-proof" && this.supportsNetwork(net, a.network)
|
|
3263
3274
|
)
|
|
3264
3275
|
);
|
|
3265
3276
|
}
|
|
3266
3277
|
if (schemes.includes("exact")) {
|
|
3267
3278
|
out.push(
|
|
3268
3279
|
...challenge.accepts.filter(
|
|
3269
|
-
(a) => a.scheme === "exact" &&
|
|
3280
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && typeof net.payExact === "function" && net.describeAsset(a.asset) != null && // a foreign rail's maxTimeoutSeconds must be a usable positive integer, or
|
|
3270
3281
|
// signing it would build a NaN/garbage validBefore — drop it silently
|
|
3271
3282
|
// (symmetric with an unrecognised token) rather than leak a raw SyntaxError.
|
|
3272
3283
|
Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
|
|
@@ -3508,7 +3519,7 @@ var PipRailClient = (_class2 = class {
|
|
|
3508
3519
|
);
|
|
3509
3520
|
}
|
|
3510
3521
|
async payAndConfirm(net, wallet, accept) {
|
|
3511
|
-
if (!
|
|
3522
|
+
if (!this.supportsNetwork(net, accept.network)) {
|
|
3512
3523
|
throw new (0, _chunkJG6KRAW6cjs.WrongChainError)(
|
|
3513
3524
|
`Challenge expects ${accept.network} but client is on ${net.network}.`
|
|
3514
3525
|
);
|
|
@@ -4761,7 +4772,15 @@ function parseFacilitatorSupported(body) {
|
|
|
4761
4772
|
const o = k;
|
|
4762
4773
|
if (typeof o.scheme !== "string" || typeof o.network !== "string") continue;
|
|
4763
4774
|
const fp = _optionalChain([o, 'access', _77 => _77.extra, 'optionalAccess', _78 => _78.feePayer]);
|
|
4764
|
-
|
|
4775
|
+
const ver = o.x402Version;
|
|
4776
|
+
const method = _optionalChain([o, 'access', _79 => _79.extra, 'optionalAccess', _80 => _80.assetTransferMethod]);
|
|
4777
|
+
out.push({
|
|
4778
|
+
scheme: o.scheme,
|
|
4779
|
+
network: o.network,
|
|
4780
|
+
...typeof fp === "string" ? { feePayer: fp } : {},
|
|
4781
|
+
...typeof ver === "number" ? { x402Version: ver } : {},
|
|
4782
|
+
...typeof method === "string" ? { assetTransferMethod: method } : {}
|
|
4783
|
+
});
|
|
4765
4784
|
}
|
|
4766
4785
|
return out;
|
|
4767
4786
|
}
|
|
@@ -5067,7 +5086,7 @@ function createPaymentGate(options) {
|
|
|
5067
5086
|
instruction: describeChallenge({ x402Version: 2, resource: { url: resourceUrl }, accepts }),
|
|
5068
5087
|
...endpointInfo ? { endpoint: endpointInfo } : {}
|
|
5069
5088
|
});
|
|
5070
|
-
const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
5089
|
+
const rejectionExt = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _81 => _81.extensions]), () => ( {}));
|
|
5071
5090
|
const rejectionPiprail = _nullishCoalesce(rejectionExt.piprail, () => ( {}));
|
|
5072
5091
|
const bodyPiprail = { ..._nullishCoalesce(selfDescribe, () => ( {})), ...rejectionPiprail };
|
|
5073
5092
|
const bodyExtensions = {
|
|
@@ -5087,7 +5106,7 @@ function createPaymentGate(options) {
|
|
|
5087
5106
|
...options.mimeType ? { mimeType: options.mimeType } : {}
|
|
5088
5107
|
},
|
|
5089
5108
|
accepts,
|
|
5090
|
-
..._optionalChain([opts, 'optionalAccess',
|
|
5109
|
+
..._optionalChain([opts, 'optionalAccess', _82 => _82.error]) ? { error: opts.error } : {},
|
|
5091
5110
|
...Object.keys(bodyExtensions).length > 0 ? { extensions: bodyExtensions } : {}
|
|
5092
5111
|
};
|
|
5093
5112
|
const headerChallenge = {
|
|
@@ -5409,7 +5428,7 @@ function isRetryableStatus(status) {
|
|
|
5409
5428
|
}
|
|
5410
5429
|
var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
5411
5430
|
async function signBody(secret, body) {
|
|
5412
|
-
const subtle = _optionalChain([globalThis, 'access',
|
|
5431
|
+
const subtle = _optionalChain([globalThis, 'access', _83 => _83.crypto, 'optionalAccess', _84 => _84.subtle]);
|
|
5413
5432
|
if (!subtle) return null;
|
|
5414
5433
|
try {
|
|
5415
5434
|
const enc = new TextEncoder();
|
|
@@ -5479,7 +5498,7 @@ async function deliverReceipt(receipt, options) {
|
|
|
5479
5498
|
const retryable = status === void 0 ? true : isRetryableStatus(status);
|
|
5480
5499
|
const willRetry = !ok && retryable && attempt < maxAttempts;
|
|
5481
5500
|
try {
|
|
5482
|
-
_optionalChain([onAttempt, 'optionalCall',
|
|
5501
|
+
_optionalChain([onAttempt, 'optionalCall', _85 => _85({ attempt, ok, ...status !== void 0 ? { status } : {}, ...error ? { error } : {}, willRetry })]);
|
|
5483
5502
|
} catch (e40) {
|
|
5484
5503
|
}
|
|
5485
5504
|
if (ok) return { delivered: true, attempts: attempt, status };
|
package/dist/index.d.cts
CHANGED
|
@@ -5562,6 +5562,15 @@ declare class PipRailClient {
|
|
|
5562
5562
|
* `quote()` (read-only) and `fetch()` (which then authorises + pays).
|
|
5563
5563
|
*/
|
|
5564
5564
|
private resolveChallenge;
|
|
5565
|
+
/** Match a foreign-supplied network string against the bound driver, tolerating a
|
|
5566
|
+
* SLUG ('bsc', 'base', '56') the SAME way discovery's `railOnNetwork` already does —
|
|
5567
|
+
* normalize to CAIP-2 first, since a foreign/AEON/community 402 may label the network
|
|
5568
|
+
* with a slug (AEON serves v1 duplicate kinds '56'/'bsc'). ADDITIVE: a value that's
|
|
5569
|
+
* already CAIP-2 passes through `normalizeNetwork` UNCHANGED, so every existing
|
|
5570
|
+
* exact-CAIP-2 match is byte-identical; only slugs resolving to the bound chain become
|
|
5571
|
+
* newly matchable (an unknown slug stays unresolved → still unmatched; a different
|
|
5572
|
+
* chain's slug resolves elsewhere → still unmatched). */
|
|
5573
|
+
private supportsNetwork;
|
|
5565
5574
|
/** The candidate accepts this client could pay, on the bound network. Always the
|
|
5566
5575
|
* backendless `onchain-proof` rails; PLUS standard `exact` rails when `schemes`
|
|
5567
5576
|
* enables them AND the driver can settle them (EVM `payExact` + a recognised
|
|
@@ -6611,6 +6620,14 @@ interface FacilitatorSupportedKind {
|
|
|
6611
6620
|
network: string;
|
|
6612
6621
|
/** The fee-payer pubkey when the kind carries one (SVM rails). */
|
|
6613
6622
|
feePayer?: string;
|
|
6623
|
+
/** The kind's x402 envelope version when the facilitator reports it per-kind — e.g.
|
|
6624
|
+
* AEON's `/supported` serves `{ x402Version, scheme, network }`, letting a reader tell
|
|
6625
|
+
* a v1 from a v2 BNB rail. Optional — absent when the facilitator doesn't advertise it. */
|
|
6626
|
+
x402Version?: number;
|
|
6627
|
+
/** The EVM exact transfer method (`eip3009` / `permit2`) when the facilitator advertises
|
|
6628
|
+
* it in the kind's `extra` — so coverage can tell whether a BNB exact kind is gasless
|
|
6629
|
+
* EIP-3009 or Permit2. Optional — most facilitators (AEON included) omit it. */
|
|
6630
|
+
assetTransferMethod?: string;
|
|
6614
6631
|
}
|
|
6615
6632
|
/**
|
|
6616
6633
|
* Parse a facilitator `/supported` body into its advertised (scheme, network) kinds.
|
package/dist/index.d.ts
CHANGED
|
@@ -5562,6 +5562,15 @@ declare class PipRailClient {
|
|
|
5562
5562
|
* `quote()` (read-only) and `fetch()` (which then authorises + pays).
|
|
5563
5563
|
*/
|
|
5564
5564
|
private resolveChallenge;
|
|
5565
|
+
/** Match a foreign-supplied network string against the bound driver, tolerating a
|
|
5566
|
+
* SLUG ('bsc', 'base', '56') the SAME way discovery's `railOnNetwork` already does —
|
|
5567
|
+
* normalize to CAIP-2 first, since a foreign/AEON/community 402 may label the network
|
|
5568
|
+
* with a slug (AEON serves v1 duplicate kinds '56'/'bsc'). ADDITIVE: a value that's
|
|
5569
|
+
* already CAIP-2 passes through `normalizeNetwork` UNCHANGED, so every existing
|
|
5570
|
+
* exact-CAIP-2 match is byte-identical; only slugs resolving to the bound chain become
|
|
5571
|
+
* newly matchable (an unknown slug stays unresolved → still unmatched; a different
|
|
5572
|
+
* chain's slug resolves elsewhere → still unmatched). */
|
|
5573
|
+
private supportsNetwork;
|
|
5565
5574
|
/** The candidate accepts this client could pay, on the bound network. Always the
|
|
5566
5575
|
* backendless `onchain-proof` rails; PLUS standard `exact` rails when `schemes`
|
|
5567
5576
|
* enables them AND the driver can settle them (EVM `payExact` + a recognised
|
|
@@ -6611,6 +6620,14 @@ interface FacilitatorSupportedKind {
|
|
|
6611
6620
|
network: string;
|
|
6612
6621
|
/** The fee-payer pubkey when the kind carries one (SVM rails). */
|
|
6613
6622
|
feePayer?: string;
|
|
6623
|
+
/** The kind's x402 envelope version when the facilitator reports it per-kind — e.g.
|
|
6624
|
+
* AEON's `/supported` serves `{ x402Version, scheme, network }`, letting a reader tell
|
|
6625
|
+
* a v1 from a v2 BNB rail. Optional — absent when the facilitator doesn't advertise it. */
|
|
6626
|
+
x402Version?: number;
|
|
6627
|
+
/** The EVM exact transfer method (`eip3009` / `permit2`) when the facilitator advertises
|
|
6628
|
+
* it in the kind's `extra` — so coverage can tell whether a BNB exact kind is gasless
|
|
6629
|
+
* EIP-3009 or Permit2. Optional — most facilitators (AEON included) omit it. */
|
|
6630
|
+
assetTransferMethod?: string;
|
|
6614
6631
|
}
|
|
6615
6632
|
/**
|
|
6616
6633
|
* Parse a facilitator `/supported` body into its advertised (scheme, network) kinds.
|
package/dist/index.js
CHANGED
|
@@ -3220,7 +3220,7 @@ var PipRailClient = class {
|
|
|
3220
3220
|
const candidates = this.gatherCandidates(net, challenge, schemes);
|
|
3221
3221
|
if (candidates.length === 0) {
|
|
3222
3222
|
const exactOnNet = challenge.accepts.some(
|
|
3223
|
-
(a) => a.scheme === "exact" &&
|
|
3223
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network)
|
|
3224
3224
|
);
|
|
3225
3225
|
if (schemes.includes("exact") && exactOnNet && typeof net.payExact !== "function") {
|
|
3226
3226
|
throw new UnsupportedSchemeError(
|
|
@@ -3229,7 +3229,7 @@ var PipRailClient = class {
|
|
|
3229
3229
|
}
|
|
3230
3230
|
if (!schemes.includes("exact") && exactOnNet && typeof net.payExact === "function") {
|
|
3231
3231
|
const payable = challenge.accepts.some(
|
|
3232
|
-
(a) => a.scheme === "exact" &&
|
|
3232
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && net.describeAsset(a.asset) != null
|
|
3233
3233
|
);
|
|
3234
3234
|
if (payable) {
|
|
3235
3235
|
throw new NoCompatibleAcceptError(
|
|
@@ -3249,6 +3249,17 @@ var PipRailClient = class {
|
|
|
3249
3249
|
const chosen = priced.find((p) => p.quote.withinPolicy) ?? priced[0];
|
|
3250
3250
|
return { net, wallet, accept: chosen.accept, challenge, quote: chosen.quote };
|
|
3251
3251
|
}
|
|
3252
|
+
/** Match a foreign-supplied network string against the bound driver, tolerating a
|
|
3253
|
+
* SLUG ('bsc', 'base', '56') the SAME way discovery's `railOnNetwork` already does —
|
|
3254
|
+
* normalize to CAIP-2 first, since a foreign/AEON/community 402 may label the network
|
|
3255
|
+
* with a slug (AEON serves v1 duplicate kinds '56'/'bsc'). ADDITIVE: a value that's
|
|
3256
|
+
* already CAIP-2 passes through `normalizeNetwork` UNCHANGED, so every existing
|
|
3257
|
+
* exact-CAIP-2 match is byte-identical; only slugs resolving to the bound chain become
|
|
3258
|
+
* newly matchable (an unknown slug stays unresolved → still unmatched; a different
|
|
3259
|
+
* chain's slug resolves elsewhere → still unmatched). */
|
|
3260
|
+
supportsNetwork(net, network) {
|
|
3261
|
+
return net.supports(normalizeNetwork(network));
|
|
3262
|
+
}
|
|
3252
3263
|
/** The candidate accepts this client could pay, on the bound network. Always the
|
|
3253
3264
|
* backendless `onchain-proof` rails; PLUS standard `exact` rails when `schemes`
|
|
3254
3265
|
* enables them AND the driver can settle them (EVM `payExact` + a recognised
|
|
@@ -3259,14 +3270,14 @@ var PipRailClient = class {
|
|
|
3259
3270
|
if (schemes.includes("onchain-proof")) {
|
|
3260
3271
|
out.push(
|
|
3261
3272
|
...challenge.accepts.filter(
|
|
3262
|
-
(a) => a.scheme === "onchain-proof" &&
|
|
3273
|
+
(a) => a.scheme === "onchain-proof" && this.supportsNetwork(net, a.network)
|
|
3263
3274
|
)
|
|
3264
3275
|
);
|
|
3265
3276
|
}
|
|
3266
3277
|
if (schemes.includes("exact")) {
|
|
3267
3278
|
out.push(
|
|
3268
3279
|
...challenge.accepts.filter(
|
|
3269
|
-
(a) => a.scheme === "exact" &&
|
|
3280
|
+
(a) => a.scheme === "exact" && this.supportsNetwork(net, a.network) && typeof net.payExact === "function" && net.describeAsset(a.asset) != null && // a foreign rail's maxTimeoutSeconds must be a usable positive integer, or
|
|
3270
3281
|
// signing it would build a NaN/garbage validBefore — drop it silently
|
|
3271
3282
|
// (symmetric with an unrecognised token) rather than leak a raw SyntaxError.
|
|
3272
3283
|
Number.isInteger(a.maxTimeoutSeconds) && a.maxTimeoutSeconds > 0
|
|
@@ -3508,7 +3519,7 @@ var PipRailClient = class {
|
|
|
3508
3519
|
);
|
|
3509
3520
|
}
|
|
3510
3521
|
async payAndConfirm(net, wallet, accept) {
|
|
3511
|
-
if (!
|
|
3522
|
+
if (!this.supportsNetwork(net, accept.network)) {
|
|
3512
3523
|
throw new WrongChainError(
|
|
3513
3524
|
`Challenge expects ${accept.network} but client is on ${net.network}.`
|
|
3514
3525
|
);
|
|
@@ -4761,7 +4772,15 @@ function parseFacilitatorSupported(body) {
|
|
|
4761
4772
|
const o = k;
|
|
4762
4773
|
if (typeof o.scheme !== "string" || typeof o.network !== "string") continue;
|
|
4763
4774
|
const fp = o.extra?.feePayer;
|
|
4764
|
-
|
|
4775
|
+
const ver = o.x402Version;
|
|
4776
|
+
const method = o.extra?.assetTransferMethod;
|
|
4777
|
+
out.push({
|
|
4778
|
+
scheme: o.scheme,
|
|
4779
|
+
network: o.network,
|
|
4780
|
+
...typeof fp === "string" ? { feePayer: fp } : {},
|
|
4781
|
+
...typeof ver === "number" ? { x402Version: ver } : {},
|
|
4782
|
+
...typeof method === "string" ? { assetTransferMethod: method } : {}
|
|
4783
|
+
});
|
|
4765
4784
|
}
|
|
4766
4785
|
return out;
|
|
4767
4786
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.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",
|