@piprail/sdk 2.9.0 → 2.10.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.
@@ -126,8 +126,54 @@ interface X402ExactAcceptEntry {
126
126
  symbol?: string;
127
127
  };
128
128
  }
129
- /** A challenge `accepts[]` entry — either PipRail's `onchain-proof` rail or a standard `exact` rail. */
130
- type X402AnyAccept = X402AcceptEntry | X402ExactAcceptEntry;
129
+ /**
130
+ * A standard x402 `upto` rail (EVM / Permit2) — variable-amount / metered billing.
131
+ * The buyer signs a Permit2 `PermitWitnessTransferFrom` authorization for `amount`
132
+ * as a **MAXIMUM**; the merchant serves the resource, meters the **actual** usage, then
133
+ * self-settles `actual ≤ max` through the canonical `x402UptoPermit2Proxy` from its own
134
+ * relayer (which is the bound `witness.facilitator`). EVM-Permit2 ONLY — the upto spec
135
+ * bans EIP-3009 (it fixes the amount at sign time) and has no non-EVM variant. A SEPARATE
136
+ * accept type from {@link X402ExactAcceptEntry}: the only wire delta vs the exact Permit2
137
+ * rail is `scheme: 'upto'` and the `witness.facilitator` field, but keeping them distinct
138
+ * leaves the exact parser/union untouched and lets the gate/client route on `scheme`.
139
+ */
140
+ interface X402UptoAcceptEntry {
141
+ scheme: 'upto';
142
+ network: Caip2;
143
+ /** The authorized MAXIMUM in base units (already scaled by decimals). The merchant
144
+ * settles the ACTUAL (≤ this) after serving. */
145
+ amount: string;
146
+ asset: AssetId;
147
+ payTo: AddressId;
148
+ maxTimeoutSeconds: number;
149
+ extra: {
150
+ /** PipRail's transfer-method tag for the upto rail. This literal `'permit2-upto'` IS what
151
+ * rides on the wire in `extra.assetTransferMethod` — it's a NON-STANDARD extra key (the
152
+ * upto spec defines no `assetTransferMethod`; the discriminant a conformant foreign client
153
+ * keys off is `scheme: 'upto'` + the Permit2 witness shape, and it ignores this unknown key).
154
+ * We carry it so OUR parser stays unambiguous from the exact Permit2 rail. */
155
+ assetTransferMethod: 'permit2-upto';
156
+ /** The address bound into `witness.facilitator`. In self-settle this is the merchant's
157
+ * own relayer; the buyer MUST sign over it; only this address can settle (the proxy
158
+ * reverts `UnauthorizedFacilitator()` otherwise). */
159
+ facilitatorAddress: string;
160
+ /** The Permit2 domain is fixed (`"Permit2"`), but the token's `name`/`version` ride
161
+ * along for the optional EIP-2612 gas-sponsoring extension. Read/re-derived on-chain,
162
+ * never assumed. */
163
+ name?: string;
164
+ version?: string;
165
+ /** Confirmations the gate waits for before granting access — a PipRail convenience. */
166
+ minConfirmations?: number;
167
+ /** Token decimals — a PipRail convenience (standard clients ignore unknown keys). */
168
+ decimals?: number;
169
+ /** Human-readable MAX, e.g. "0.50". */
170
+ amountFormatted?: string;
171
+ symbol?: string;
172
+ };
173
+ }
174
+ /** A challenge `accepts[]` entry — PipRail's `onchain-proof` rail, a standard `exact`
175
+ * rail, or a standard `upto` (metered) rail. */
176
+ type X402AnyAccept = X402AcceptEntry | X402ExactAcceptEntry | X402UptoAcceptEntry;
131
177
  interface X402Challenge {
132
178
  x402Version: 2;
133
179
  /**
@@ -210,6 +256,42 @@ interface Permit2PaymentPayload {
210
256
  signature: string;
211
257
  permit2Authorization: Permit2Authorization;
212
258
  }
259
+ /**
260
+ * The `permit2Authorization` a payer signs for the x402 `upto` (metered) EVM scheme.
261
+ * Identical to {@link Permit2Authorization} EXCEPT the witness carries a `facilitator`
262
+ * field as its **MIDDLE** member (`{ to, facilitator, validAfter }`) — the only delta
263
+ * from the exact Permit2 witness. The EIP-712 witness type is
264
+ * `Witness(address to,address facilitator,uint256 validAfter)`. `permitted.amount` is
265
+ * the signed **MAXIMUM**; the merchant settles the ACTUAL (≤ max). `spender` is the
266
+ * canonical **x402UptoPermit2Proxy**. All numeric fields are DECIMAL strings on the wire.
267
+ */
268
+ interface Permit2UptoAuthorization {
269
+ /** What may be pulled: the ERC-20 token + the signed MAXIMUM base-unit amount. */
270
+ permitted: {
271
+ token: string;
272
+ amount: string;
273
+ };
274
+ /** The payer (token owner). */
275
+ from: string;
276
+ /** The signature's allowed spender — the canonical x402UptoPermit2Proxy. */
277
+ spender: string;
278
+ /** Permit2 unordered nonce (a uint256, decimal string). Single-use via its bitmap. */
279
+ nonce: string;
280
+ /** Unix-seconds signature expiry. */
281
+ deadline: string;
282
+ /** The proxy-enforced witness: funds go ONLY to `to`, only the bound `facilitator` can
283
+ * settle, and not before `validAfter`. `facilitator` is the MIDDLE field. */
284
+ witness: {
285
+ to: string;
286
+ facilitator: string;
287
+ validAfter: string;
288
+ };
289
+ }
290
+ /** The `payload` a client sends for the `upto` rail: a signature + its Permit2 upto authorization. */
291
+ interface Permit2UptoPaymentPayload {
292
+ signature: string;
293
+ permit2Authorization: Permit2UptoAuthorization;
294
+ }
213
295
  /**
214
296
  * The `payload` a client sends for the **SVM (Solana) `exact`** variant: a base64-encoded,
215
297
  * serialized, **partially-signed** versioned Solana transaction (the buyer's `TransferChecked`
@@ -311,8 +393,21 @@ type ParsedExactPayment = (ParsedExactBase & {
311
393
  method: 'near';
312
394
  payload: ExactNearPaymentPayload;
313
395
  });
396
+ /**
397
+ * What {@link parseUptoPaymentHeader} extracts from an inbound `upto` payment — the
398
+ * metered-rail sibling of {@link ParsedExactPayment}. A single PipRail-internal
399
+ * `method: 'permit2-upto'` discriminant (the on-wire `scheme` is `'upto'`). `network`/
400
+ * `asset` are the CLIENT's claim — used only to MATCH an offered rail; the gate re-derives
401
+ * every verified field from its own trusted rail. Kept separate from the exact parse path
402
+ * so an upto payload (scheme `'upto'`, witness carries `facilitator`) never matches the
403
+ * exact parser and vice-versa.
404
+ */
405
+ type ParsedUptoPayment = ParsedExactBase & {
406
+ method: 'permit2-upto';
407
+ payload: Permit2UptoPaymentPayload;
408
+ };
314
409
  interface X402Receipt {
315
- scheme: 'onchain-proof' | 'exact';
410
+ scheme: 'onchain-proof' | 'exact' | 'upto';
316
411
  /**
317
412
  * x402 v2 SettlementResponse: settlement succeeded. Always `true` here — a
318
413
  * failed verification returns a 402, never a receipt.
@@ -332,6 +427,15 @@ interface X402Receipt {
332
427
  payer: AddressId;
333
428
  payTo: AddressId;
334
429
  verifiedAt: string;
430
+ /**
431
+ * NEW (additive, optional). The challenge nonce this settlement was bound to —
432
+ * the value `genNonce()` minted into the 402 and echoed back as the buyer's
433
+ * `payload.nonce` (NOT an exact-rail authorization/delegate nonce). REQUIRED to
434
+ * re-verify Template-A families (Stellar/XRPL/NEAR/Algorand/TON) off-chain via a
435
+ * synthetic accept; informational on digest-bound (Template-B) families. Omitted
436
+ * unless the gate's `receipts` option is on, so a default 200 stays byte-identical.
437
+ */
438
+ nonce?: string;
335
439
  }
336
440
  /**
337
441
  * The settled-payment record handed to a gate's `onPaid` hook — the wire
@@ -364,6 +468,49 @@ interface PaidReceipt extends X402Receipt {
364
468
  */
365
469
  idempotencyKey: string;
366
470
  }
471
+ /**
472
+ * The OPTIONAL Tier-2 EIP-712 delivery attestation — the official offer-receipt
473
+ * `SignedReceipt`. Populated only when the merchant enables `receipts: { attest }`
474
+ * (a separate phase); absent for Tier-1 chain-grounded receipts. Kept open for
475
+ * forward-compat with the spec's typed-data fields, filled in by the EVM
476
+ * `signReceipt` SPI; verification is `PipRailClient.verifyAttestation`.
477
+ */
478
+ interface SignedReceipt {
479
+ /** The EIP-712 signature over the receipt typed-data. */
480
+ signature: string;
481
+ /** The recovered signer the verifier expects to equal the merchant `payTo`. */
482
+ signer: AddressId;
483
+ [extra: string]: unknown;
484
+ }
485
+ /**
486
+ * The self-contained, portable receipt a buyer KEEPS and **anyone** re-verifies
487
+ * against the chain with only an RPC — no key, no backend, no PipRail account.
488
+ * It bundles the verified {@link X402Receipt} (which carries `nonce` for Template-A
489
+ * re-verification) with the reconstruction metadata a third party needs to rebuild
490
+ * the trusted accept and re-run the driver's `verify()`: what was paid for
491
+ * (`resource`) and the asset `decimals` (Stellar/XRPL/TON need it to re-scale the
492
+ * amount). Rides the wire in `extensions['offer-receipt'].info` on the
493
+ * `PAYMENT-RESPONSE` header; {@link PipRailClient.verifyReceipt} re-verifies it.
494
+ */
495
+ interface PipRailReceipt {
496
+ /** Receipt-format version — distinct from `x402Version`. */
497
+ piprail: '1';
498
+ /** The verified settlement (carries the challenge `nonce` for Template-A re-verify). */
499
+ receipt: X402Receipt;
500
+ /** What was paid for — the challenge's resource URL. */
501
+ resource: {
502
+ url: string;
503
+ };
504
+ /**
505
+ * ADDITIVE. The asset's on-chain decimals — threaded into the synthetic accept's
506
+ * `extra.decimals` so Stellar/XRPL/TON `verify()` can re-scale the wire amount.
507
+ * Receipt-bundle metadata only (the gate already knows it via {@link PaidReceipt});
508
+ * NOT on the minimal wire {@link X402Receipt}.
509
+ */
510
+ decimals?: number;
511
+ /** OPTIONAL Tier-2 attestation — present only when the merchant signed it. */
512
+ attestation?: SignedReceipt;
513
+ }
367
514
  /**
368
515
  * Why a verification failed — a closed, chain-agnostic vocabulary. Every code a
369
516
  * driver returns is in this union; a client/agent branches on it rather than
@@ -378,7 +525,7 @@ interface PaidReceipt extends X402Receipt {
378
525
  * `maxPaymentRetries` (a short backoff absorbs RPC lag); it does not branch on
379
526
  * the code.
380
527
  */
381
- type VerifyErrorCode = 'tx_not_found' | 'insufficient_confirmations' | 'tx_reverted' | 'no_meta' | 'wrong_recipient' | 'amount_too_low' | 'transfer_not_found' | 'payment_expired' | 'tx_already_used' | 'signature_invalid';
528
+ type VerifyErrorCode = 'tx_not_found' | 'insufficient_confirmations' | 'tx_reverted' | 'no_meta' | 'wrong_recipient' | 'amount_too_low' | 'transfer_not_found' | 'payment_expired' | 'tx_already_used' | 'signature_invalid' | 'upto_settle_exceeds_max';
382
529
  /** The shape every driver's `verify()` returns. Shared by drivers + protocol. */
383
530
  type VerifyResult = {
384
531
  ok: true;
@@ -393,8 +540,50 @@ declare const HEADER_SIGNATURE = "payment-signature";
393
540
  declare const HEADER_RESPONSE = "payment-response";
394
541
  declare const HEADER_SIGNATURE_V1 = "x-payment";
395
542
  declare const HEADER_RESPONSE_V1 = "x-payment-response";
543
+ /**
544
+ * Decode a base64-JSON wire value into a plain object (or `null` on garbage) — the
545
+ * inverse of {@link buildSignatureHeader}/{@link buildExactSignatureHeader}. Exported
546
+ * so a transport that carries the SAME payload as RAW JSON (A2A) can round-trip a
547
+ * base64 fixture into the object the `…Object` parser cores / `gate.verifyObject` consume.
548
+ */
549
+ declare function decodeBase64Json(value: string): unknown;
396
550
  declare function buildChallengeHeader(challenge: X402Challenge): string;
397
- declare function buildReceiptHeader(receipt: X402Receipt): string;
551
+ /**
552
+ * Build the PAYMENT-RESPONSE header from a settled {@link X402Receipt}. When `extensions`
553
+ * is supplied (the gate's `receipts` option is on), it rides as an `extensions` sibling on
554
+ * the SettlementResponse — a standard x402 reader ignores it, {@link parseReceiptExtension}
555
+ * reconstructs the {@link PipRailReceipt}. Omit it (the default) and the header is
556
+ * byte-identical to before this feature.
557
+ */
558
+ declare function buildReceiptHeader(receipt: X402Receipt, extensions?: Record<string, unknown>): string;
559
+ /** The x402 extension key for verifiable delivery receipts (the `offer-receipt` extension). */
560
+ declare const EXT_OFFER_RECEIPT = "offer-receipt";
561
+ /**
562
+ * Assemble the `extensions['offer-receipt']` block for a settled response — PURE
563
+ * JSON, viem-free. SPEC-FAITHFUL placement:
564
+ * - `info.receipt` holds the official `offer-receipt` **SignedReceipt** (the canonical
565
+ * `{ format, payload, signature }` a STOCK `@x402/extensions` reader
566
+ * (`extractReceiptFromResponse` → `info.receipt`) consumes, PLUS an additive `signer` —
567
+ * the recovered signer address, a convenience a stock reader ignores and a verifier
568
+ * re-derives from the signature anyway, so it's never trusted on the wire) — present
569
+ * ONLY when a Tier-2 attestation was signed. When there is no attestation (Tier-1,
570
+ * chain-grounded) there is no signed artifact, so `info.receipt` is absent — a stock
571
+ * reader correctly sees "no signed receipt" (because there isn't one).
572
+ * - `info.settlement` holds PipRail's chain-grounded {@link X402Receipt} (the
573
+ * settlement record {@link parseReceiptExtension} re-reads for `verifyReceipt`) — a
574
+ * PipRail-namespaced sibling a stock reader ignores.
575
+ * The optional `schema` JSON-Schema sibling is owner-gated and not emitted by default.
576
+ * The gate merges the returned record into the SettlementResponse's `extensions` on the
577
+ * `PAYMENT-RESPONSE` header.
578
+ */
579
+ declare function buildReceiptExtension(bundle: {
580
+ receipt: X402Receipt;
581
+ resource: {
582
+ url: string;
583
+ };
584
+ decimals?: number;
585
+ attestation?: SignedReceipt;
586
+ }): Record<string, unknown>;
398
587
  declare function buildSignatureHeader(signature: X402PaymentSignature): string;
399
588
  /**
400
589
  * Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `exact` payment:
@@ -410,6 +599,19 @@ declare function buildExactSignatureHeader(input: {
410
599
  accepted: X402ExactAcceptEntry;
411
600
  payload: ExactPaymentPayloadAny;
412
601
  }): string;
602
+ /**
603
+ * Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `upto` (metered)
604
+ * payment: base64 of `{ x402Version: 2, accepted, payload }`. `accepted` is the chosen
605
+ * upto rail echoed back VERBATIM from the challenge's `accepts[]`; `payload` is the
606
+ * Permit2-upto `{ signature, permit2Authorization }` the buyer's EVM driver produced
607
+ * (the witness carries `facilitator`). Chain-agnostic (pure JSON/base64). Round-trips
608
+ * through {@link parseUptoPaymentHeader}. (The `exact` counterpart is
609
+ * {@link buildExactSignatureHeader}.)
610
+ */
611
+ declare function buildUptoSignatureHeader(input: {
612
+ accepted: X402UptoAcceptEntry;
613
+ payload: Permit2UptoPaymentPayload;
614
+ }): string;
413
615
  /**
414
616
  * Parse the PAYMENT-REQUIRED challenge from a 402 response. Prefers the
415
617
  * `payment-required` header, falls back to the JSON body.
@@ -420,6 +622,17 @@ declare function parseChallenge(response: Response): Promise<X402Challenge | nul
420
622
  * server may set. Returns a fully-formed {@link X402Receipt} only (a bare foreign
421
623
  * exact SettleResponse without a `payer` is read by {@link parseSettleResponse}). */
422
624
  declare function parseReceipt(response: Response): X402Receipt | null;
625
+ /**
626
+ * Read a {@link PipRailReceipt} back from a settled response's `PAYMENT-RESPONSE`
627
+ * header (v2, or the v1 `X-PAYMENT-RESPONSE` fallback). Reads PipRail's chain-grounded
628
+ * settlement record from `extensions['offer-receipt'].info.settlement`, and the optional
629
+ * Tier-2 {@link SignedReceipt} from the spec slot `info.receipt`. Liberal/Postel: TOLERATES
630
+ * + IGNORES a `schema` sibling (or any unknown sibling), and — for robustness — also accepts
631
+ * the settlement record at `info.receipt` if it's there instead (an X402Receipt, distinguished
632
+ * from a SignedReceipt by {@link isValidReceipt}). Returns `null` when no header, no extension
633
+ * block, or no valid settlement record. Pure — no chain read.
634
+ */
635
+ declare function parseReceiptExtension(response: Response): PipRailReceipt | null;
423
636
  /**
424
637
  * A standard x402 SettleResponse as the BUYER reads it off a settled (non-402)
425
638
  * response. The `success` flag is authoritative: `false` is an EXPLICIT facilitator/
@@ -432,6 +645,13 @@ interface SettleOutcome {
432
645
  network?: string;
433
646
  payer?: string;
434
647
  errorReason?: string;
648
+ /**
649
+ * The ACTUAL settled amount in atomic units, when the SettleResponse carries it
650
+ * (the x402 `upto` scheme makes this field REQUIRED — may be `"0"`). The upto buyer
651
+ * reads it to record the metered ACTUAL spend in its ledger rather than the signed MAX.
652
+ * Absent for `onchain-proof`/`exact` settle responses (they fix the amount up front).
653
+ */
654
+ amount?: string;
435
655
  }
436
656
  /**
437
657
  * Read a standard x402 SettleResponse for the BUYER, from the v2 `payment-response`
@@ -444,7 +664,17 @@ interface SettleOutcome {
444
664
  * settlement from a phantom one (never record a spend on `success:false`).
445
665
  */
446
666
  declare function parseSettleResponse(response: Response): SettleOutcome | null;
447
- /** Parse a PAYMENT-SIGNATURE header value (server side). */
667
+ /**
668
+ * Parse an already-decoded `onchain-proof` PaymentPayload OBJECT (server side) —
669
+ * the object-accepting CORE of {@link parseSignatureHeader}. Identical logic to the
670
+ * base64 entry-point below, minus the `fromBase64Json` decode: this is what the A2A
671
+ * transport feeds raw JSON metadata into (A2A carries the payload as raw JSON, not
672
+ * base64), via `gate.verifyObject`. {@link parseSignatureHeader} is the thin base64
673
+ * wrapper — byte-identical to before this split on the HTTP path.
674
+ */
675
+ declare function parseSignatureObject(parsed: unknown): X402PaymentSignature | null;
676
+ /** Parse a PAYMENT-SIGNATURE header value (server side). A thin base64 wrapper over
677
+ * {@link parseSignatureObject} — byte-identical to before the object-core split. */
448
678
  declare function parseSignatureHeader(value: string): X402PaymentSignature | null;
449
679
  /**
450
680
  * Parse an inbound `exact` payment from a base64 header value (`PAYMENT-SIGNATURE`
@@ -455,6 +685,32 @@ declare function parseSignatureHeader(value: string): X402PaymentSignature | nul
455
685
  * `onchain-proof` proof, or malformed).
456
686
  */
457
687
  declare function parseExactPaymentHeader(value: string): ParsedExactPayment | null;
688
+ /**
689
+ * Parse an already-decoded `exact` PaymentPayload OBJECT — the object-accepting CORE
690
+ * of {@link parseExactPaymentHeader}, identical logic minus the base64 decode. It
691
+ * absorbs the v1/v2 wire skew (the `accepted` wrapper vs flat `scheme`/`network`) and
692
+ * the six exact-method discriminants. The A2A transport feeds raw JSON metadata here
693
+ * (via `gate.verifyObject`); {@link parseExactPaymentHeader} is the thin base64 wrapper,
694
+ * byte-identical to before this split on the HTTP path.
695
+ */
696
+ declare function parseExactObject(parsed: unknown): ParsedExactPayment | null;
697
+ /**
698
+ * Parse an inbound `upto` (metered) payment from a base64 header value
699
+ * (`PAYMENT-SIGNATURE` v2 or `X-PAYMENT` v1). A SEPARATE parser from
700
+ * {@link parseExactPaymentHeader}, gated strictly on `scheme === 'upto'` AND a
701
+ * `witness.facilitator` STRING — so an upto payload never matches the exact parser and an
702
+ * exact Permit2 payload (no `witness.facilitator`) never matches this one. Returns null
703
+ * when the value isn't a recognisable `upto` payment.
704
+ */
705
+ declare function parseUptoPaymentHeader(value: string): ParsedUptoPayment | null;
706
+ /**
707
+ * Parse an already-decoded `upto` (metered) PaymentPayload OBJECT — the object-accepting
708
+ * CORE of {@link parseUptoPaymentHeader}, identical logic minus the base64 decode. Gated
709
+ * strictly on `scheme === 'upto'` + a `witness.facilitator` string. The A2A transport feeds
710
+ * raw JSON metadata here (via `gate.verifyObject`); {@link parseUptoPaymentHeader} is the thin
711
+ * base64 wrapper, byte-identical to before this split on the HTTP path.
712
+ */
713
+ declare function parseUptoObject(parsed: unknown): ParsedUptoPayment | null;
458
714
  /**
459
715
  * Pick the first accepts[] entry on the `onchain-proof` scheme whose network
460
716
  * satisfies `matches` (any chain family). Returns null if none match.
@@ -505,10 +761,21 @@ interface SpendRecord {
505
761
  host: string;
506
762
  network: Caip2;
507
763
  asset: string;
508
- /** Base units paid (already scaled by decimals). */
764
+ /** Base units that count toward the budget. For onchain-proof/exact this is the paid
765
+ * amount. For the metered `upto` rail it is the authorized **MAX** (not the merchant's
766
+ * claimed actual) — the only buyer-provable bound, so a malicious merchant that settles
767
+ * the MAX on-chain but under-reports the actual can never loosen a cumulative cap
768
+ * (`maxTotal` / `maxTotalPerDenom` / `windowTotal`). See {@link settledBase} for the actual. */
509
769
  amountBase: string;
510
- /** Human-readable amount, e.g. '0.05'. */
770
+ /** Human-readable {@link amountBase}, e.g. '0.05'. */
511
771
  amountFormatted: string;
772
+ /** METERED `upto` ONLY: the merchant-claimed settled **actual**, clamped to `≤` the
773
+ * authorized MAX (`amountBase`). Informational — surfaced for transparency/reconciliation
774
+ * (and equal to the receipt's amount); it does NOT feed any cap (those tally the MAX).
775
+ * Absent for onchain-proof/exact (where the actual IS the budgeted amount). */
776
+ settledBase?: string;
777
+ /** Human-readable {@link settledBase}. */
778
+ settledFormatted?: string;
512
779
  symbol?: string;
513
780
  /** TRUE token decimals. Carried on the record so a {@link SpendStore} can rebuild
514
781
  * exact totals + the grand total on reload (the client stamps it on every settle). */
@@ -655,4 +922,4 @@ declare class SpendLedger {
655
922
  summary(): SpendSummary;
656
923
  }
657
924
 
658
- export { type AddressId as A, buildSignatureHeader as B, type Caip2 as C, memorySpendStore as D, type ExactAuthorizationWire as E, parseChallenge as F, parseExactPaymentHeader as G, HEADER_REQUIRED as H, parseReceipt as I, parseSettleResponse as J, parseSignatureHeader as K, pickAccept as L, type PaidReceipt as P, type SettleOutcome as S, type VerifyErrorCode as V, type X402AcceptEntry as X, type AssetId as a, type ExactPaymentPayload as b, type ExactPaymentPayloadAny as c, HEADER_RESPONSE as d, HEADER_RESPONSE_V1 as e, HEADER_SIGNATURE as f, HEADER_SIGNATURE_V1 as g, type ParsedExactPayment as h, type Permit2Authorization as i, type Permit2PaymentPayload as j, type SpendAssetTotal as k, type SpendDenomTotal as l, SpendLedger as m, type SpendRecord as n, type SpendStore as o, type SpendSummary as p, type VerifyResult as q, type X402AnyAccept as r, type X402Challenge as s, type X402ExactAcceptEntry as t, type X402PaymentSignature as u, type X402Receipt as v, type X402ResourceObject as w, buildChallengeHeader as x, buildExactSignatureHeader as y, buildReceiptHeader as z };
925
+ export { parseSignatureObject as $, type AddressId as A, type X402PaymentSignature as B, type Caip2 as C, type X402Receipt as D, EXT_OFFER_RECEIPT as E, type X402ResourceObject as F, type X402UptoAcceptEntry as G, HEADER_REQUIRED as H, buildChallengeHeader as I, buildExactSignatureHeader as J, buildReceiptExtension as K, buildReceiptHeader as L, buildSignatureHeader as M, buildUptoSignatureHeader as N, decodeBase64Json as O, type PaidReceipt as P, memorySpendStore as Q, parseChallenge as R, type SettleOutcome as S, parseExactObject as T, parseExactPaymentHeader as U, type VerifyErrorCode as V, parseReceipt as W, type X402AcceptEntry as X, parseReceiptExtension as Y, parseSettleResponse as Z, parseSignatureHeader as _, type AssetId as a, parseUptoObject as a0, parseUptoPaymentHeader as a1, pickAccept as a2, type ExactAuthorizationWire as b, type ExactPaymentPayload as c, type ExactPaymentPayloadAny as d, HEADER_RESPONSE as e, HEADER_RESPONSE_V1 as f, HEADER_SIGNATURE as g, HEADER_SIGNATURE_V1 as h, type ParsedExactPayment as i, type ParsedUptoPayment as j, type Permit2Authorization as k, type Permit2PaymentPayload as l, type Permit2UptoAuthorization as m, type Permit2UptoPaymentPayload as n, type PipRailReceipt as o, type SignedReceipt as p, type SpendAssetTotal as q, type SpendDenomTotal as r, SpendLedger as s, type SpendRecord as t, type SpendStore as u, type SpendSummary as v, type VerifyResult as w, type X402AnyAccept as x, type X402Challenge as y, type X402ExactAcceptEntry as z };
package/dist/node.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as SpendStore } from './ledger-BtzrfO-3.cjs';
2
- export { D as memorySpendStore } from './ledger-BtzrfO-3.cjs';
1
+ import { u as SpendStore } from './ledger-OQos-tmj.cjs';
2
+ export { Q as memorySpendStore } from './ledger-OQos-tmj.cjs';
3
3
 
4
4
  /**
5
5
  * A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as SpendStore } from './ledger-BtzrfO-3.js';
2
- export { D as memorySpendStore } from './ledger-BtzrfO-3.js';
1
+ import { u as SpendStore } from './ledger-OQos-tmj.js';
2
+ export { Q as memorySpendStore } from './ledger-OQos-tmj.js';
3
3
 
4
4
  /**
5
5
  * A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
@@ -0,0 +1,14 @@
1
+ import {
2
+ RECEIPT_DOMAIN,
3
+ RECEIPT_PRIMARY_TYPE,
4
+ RECEIPT_TYPES,
5
+ signReceiptEvm,
6
+ verifyReceiptAttestationEvm
7
+ } from "./chunk-3SBTJKAG.js";
8
+ export {
9
+ RECEIPT_DOMAIN,
10
+ RECEIPT_PRIMARY_TYPE,
11
+ RECEIPT_TYPES,
12
+ signReceiptEvm,
13
+ verifyReceiptAttestationEvm
14
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+ var _chunkCQQI5IJXcjs = require('./chunk-CQQI5IJX.cjs');
8
+
9
+
10
+
11
+
12
+
13
+
14
+ exports.RECEIPT_DOMAIN = _chunkCQQI5IJXcjs.RECEIPT_DOMAIN; exports.RECEIPT_PRIMARY_TYPE = _chunkCQQI5IJXcjs.RECEIPT_PRIMARY_TYPE; exports.RECEIPT_TYPES = _chunkCQQI5IJXcjs.RECEIPT_TYPES; exports.signReceiptEvm = _chunkCQQI5IJXcjs.signReceiptEvm; exports.verifyReceiptAttestationEvm = _chunkCQQI5IJXcjs.verifyReceiptAttestationEvm;
@@ -336,7 +336,7 @@ function makeStellarNetwork(preset, rpcUrl) {
336
336
  }
337
337
  return {
338
338
  asset: stellarAssetId(t.code, t.issuer),
339
- decimals: t.decimals,
339
+ decimals: STELLAR_DECIMALS,
340
340
  symbol: t.symbol ?? t.code
341
341
  };
342
342
  },
@@ -336,7 +336,7 @@ function makeStellarNetwork(preset, rpcUrl) {
336
336
  }
337
337
  return {
338
338
  asset: stellarAssetId(t.code, t.issuer),
339
- decimals: t.decimals,
339
+ decimals: STELLAR_DECIMALS,
340
340
  symbol: _nullishCoalesce(t.symbol, () => ( t.code))
341
341
  };
342
342
  },
@@ -44,13 +44,23 @@ async function paySui(params) {
44
44
  const [coin] = tx.splitCoins(tx.gas, [amount]);
45
45
  tx.transferObjects([coin], accept.payTo);
46
46
  } else {
47
- const coins = await client.getCoins({ owner: sender, coinType: accept.asset });
48
- if (!coins.data.length) {
47
+ const ids = [];
48
+ let gathered = 0n;
49
+ let cursor;
50
+ do {
51
+ const page = await client.getCoins({ owner: sender, coinType: accept.asset, cursor });
52
+ for (const c of page.data) {
53
+ ids.push(c.coinObjectId);
54
+ gathered += BigInt(c.balance);
55
+ if (gathered >= amount) break;
56
+ }
57
+ cursor = page.hasNextPage ? page.nextCursor : null;
58
+ } while (gathered < amount && cursor);
59
+ if (!ids.length) {
49
60
  throw new InsufficientFundsError(
50
61
  `Sui wallet holds no ${accept.asset} coin objects to pay from.`
51
62
  );
52
63
  }
53
- const ids = coins.data.map((c) => c.coinObjectId);
54
64
  const primary = ids[0];
55
65
  if (ids.length > 1) {
56
66
  tx.mergeCoins(tx.object(primary), ids.slice(1).map((id) => tx.object(id)));
@@ -44,13 +44,23 @@ async function paySui(params) {
44
44
  const [coin] = tx.splitCoins(tx.gas, [amount]);
45
45
  tx.transferObjects([coin], accept.payTo);
46
46
  } else {
47
- const coins = await client.getCoins({ owner: sender, coinType: accept.asset });
48
- if (!coins.data.length) {
47
+ const ids = [];
48
+ let gathered = 0n;
49
+ let cursor;
50
+ do {
51
+ const page = await client.getCoins({ owner: sender, coinType: accept.asset, cursor });
52
+ for (const c of page.data) {
53
+ ids.push(c.coinObjectId);
54
+ gathered += BigInt(c.balance);
55
+ if (gathered >= amount) break;
56
+ }
57
+ cursor = page.hasNextPage ? page.nextCursor : null;
58
+ } while (gathered < amount && cursor);
59
+ if (!ids.length) {
49
60
  throw new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
50
61
  `Sui wallet holds no ${accept.asset} coin objects to pay from.`
51
62
  );
52
63
  }
53
- const ids = coins.data.map((c) => c.coinObjectId);
54
64
  const primary = ids[0];
55
65
  if (ids.length > 1) {
56
66
  tx.mergeCoins(tx.object(primary), ids.slice(1).map((id) => tx.object(id)));
@@ -76,8 +76,14 @@ async function payTron(params) {
76
76
  }
77
77
  async function payTronNative(params) {
78
78
  const { client, from, privateKey, accept } = params;
79
+ const sun = BigInt(accept.amount);
80
+ if (sun > BigInt(Number.MAX_SAFE_INTEGER)) {
81
+ throw new InsufficientFundsError(
82
+ `Tron native amount ${accept.amount} sun exceeds the safe-integer range tronweb.sendTrx accepts \u2014 price this resource in a smaller native amount or a TRC-20 token.`
83
+ );
84
+ }
79
85
  try {
80
- const unsigned = await client.transactionBuilder.sendTrx(accept.payTo, Number(accept.amount), from);
86
+ const unsigned = await client.transactionBuilder.sendTrx(accept.payTo, Number(sun), from);
81
87
  const signed = await client.trx.sign(unsigned, privateKey);
82
88
  const broadcast = await client.trx.sendRawTransaction(signed);
83
89
  if (broadcast.result === true || broadcast.txid || broadcast.transaction?.txID) {
@@ -76,8 +76,14 @@ async function payTron(params) {
76
76
  }
77
77
  async function payTronNative(params) {
78
78
  const { client, from, privateKey, accept } = params;
79
+ const sun = BigInt(accept.amount);
80
+ if (sun > BigInt(Number.MAX_SAFE_INTEGER)) {
81
+ throw new (0, _chunkMWBT7MCEcjs.InsufficientFundsError)(
82
+ `Tron native amount ${accept.amount} sun exceeds the safe-integer range tronweb.sendTrx accepts \u2014 price this resource in a smaller native amount or a TRC-20 token.`
83
+ );
84
+ }
79
85
  try {
80
- const unsigned = await client.transactionBuilder.sendTrx(accept.payTo, Number(accept.amount), from);
86
+ const unsigned = await client.transactionBuilder.sendTrx(accept.payTo, Number(sun), from);
81
87
  const signed = await client.trx.sign(unsigned, privateKey);
82
88
  const broadcast = await client.trx.sendRawTransaction(signed);
83
89
  if (broadcast.result === true || broadcast.txid || _optionalChain([broadcast, 'access', _9 => _9.transaction, 'optionalAccess', _10 => _10.txID])) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piprail/sdk",
3
- "version": "2.9.0",
3
+ "version": "2.10.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",