@piprail/sdk 1.0.0 → 1.1.1

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.
@@ -0,0 +1,173 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14;// src/errors.ts
2
+ var PipRailError = class extends Error {
3
+ constructor(message, options) {
4
+ super(message, options);
5
+ this.name = this.constructor.name;
6
+ }
7
+ };
8
+ var InsufficientFundsError = (_class = class extends PipRailError {constructor(...args) { super(...args); _class.prototype.__init.call(this); }
9
+ __init() {this.code = "INSUFFICIENT_FUNDS"}
10
+ }, _class);
11
+ var RecipientNotReadyError = (_class2 = class extends PipRailError {constructor(...args2) { super(...args2); _class2.prototype.__init2.call(this); }
12
+ __init2() {this.code = "RECIPIENT_NOT_READY"}
13
+ }, _class2);
14
+ function toInsufficientFundsError(err) {
15
+ const message = err instanceof Error ? err.message : String(err);
16
+ if (/insufficient (funds|balance|lamports|fee)|not enough|exceeds (the )?balance|underfunded|low[_ ]?reserve|debit the account/i.test(
17
+ message
18
+ )) {
19
+ return new InsufficientFundsError(
20
+ err instanceof Error ? err.message : "Insufficient funds for the payment.",
21
+ { cause: err }
22
+ );
23
+ }
24
+ return null;
25
+ }
26
+ var WrongChainError = (_class3 = class extends PipRailError {constructor(...args3) { super(...args3); _class3.prototype.__init3.call(this); }
27
+ __init3() {this.code = "WRONG_CHAIN"}
28
+ }, _class3);
29
+ var PaymentTimeoutError = (_class4 = class extends PipRailError {
30
+ __init4() {this.code = "PAYMENT_TIMEOUT"}
31
+ /** The already-broadcast proof ref — recover with it, don't re-pay. */
32
+
33
+ constructor(message, options) {
34
+ super(message, options);_class4.prototype.__init4.call(this);;
35
+ this.ref = _optionalChain([options, 'optionalAccess', _ => _.ref]);
36
+ }
37
+ }, _class4);
38
+ var MaxRetriesExceededError = (_class5 = class extends PipRailError {
39
+ __init5() {this.code = "MAX_RETRIES_EXCEEDED"}
40
+ /** The already-broadcast proof ref — recover with it, don't re-pay. */
41
+
42
+ constructor(message, options) {
43
+ super(message, options);_class5.prototype.__init5.call(this);;
44
+ this.ref = _optionalChain([options, 'optionalAccess', _2 => _2.ref]);
45
+ }
46
+ }, _class5);
47
+ var PaymentDeclinedError = (_class6 = class extends PipRailError {constructor(...args4) { super(...args4); _class6.prototype.__init6.call(this); }
48
+ __init6() {this.code = "PAYMENT_DECLINED"}
49
+ }, _class6);
50
+ var ConfirmationTimeoutError = (_class7 = class extends PipRailError {constructor(...args5) { super(...args5); _class7.prototype.__init7.call(this); }
51
+ __init7() {this.code = "CONFIRMATION_TIMEOUT"}
52
+ }, _class7);
53
+ var InvalidEnvelopeError = (_class8 = class extends PipRailError {constructor(...args6) { super(...args6); _class8.prototype.__init8.call(this); }
54
+ __init8() {this.code = "INVALID_ENVELOPE"}
55
+ }, _class8);
56
+ var NoCompatibleAcceptError = (_class9 = class extends PipRailError {constructor(...args7) { super(...args7); _class9.prototype.__init9.call(this); }
57
+ __init9() {this.code = "NO_COMPATIBLE_ACCEPT"}
58
+ }, _class9);
59
+ var NonReplayableBodyError = (_class10 = class extends PipRailError {constructor(...args8) { super(...args8); _class10.prototype.__init10.call(this); }
60
+ __init10() {this.code = "NON_REPLAYABLE_BODY"}
61
+ }, _class10);
62
+ var WrongFamilyError = (_class11 = class extends PipRailError {constructor(...args9) { super(...args9); _class11.prototype.__init11.call(this); }
63
+ __init11() {this.code = "WRONG_FAMILY"}
64
+ }, _class11);
65
+ var UnknownTokenError = (_class12 = class extends PipRailError {constructor(...args10) { super(...args10); _class12.prototype.__init12.call(this); }
66
+ __init12() {this.code = "UNKNOWN_TOKEN"}
67
+ }, _class12);
68
+ var MissingDriverError = (_class13 = class extends PipRailError {constructor(...args11) { super(...args11); _class13.prototype.__init13.call(this); }
69
+ __init13() {this.code = "MISSING_DRIVER"}
70
+ }, _class13);
71
+ var UnsupportedNetworkError = (_class14 = class extends PipRailError {constructor(...args12) { super(...args12); _class14.prototype.__init14.call(this); }
72
+ __init14() {this.code = "UNSUPPORTED_NETWORK"}
73
+ }, _class14);
74
+
75
+ // src/drivers/shared.ts
76
+ var FAMILY_LABEL = {
77
+ evm: "EVM",
78
+ solana: "Solana",
79
+ ton: "TON",
80
+ stellar: "Stellar",
81
+ xrpl: "XRPL",
82
+ tron: "Tron",
83
+ sui: "Sui",
84
+ near: "NEAR"
85
+ };
86
+ var FAMILY_TOKEN = {
87
+ evm: { key: "address", shape: "{ address }", hint: "{ address, decimals }" },
88
+ solana: { key: "mint", shape: "{ mint }", hint: "{ mint, decimals }" },
89
+ ton: { key: "master", shape: "{ master }", hint: "{ master, decimals }" },
90
+ stellar: { key: "code", shape: "{ issuer, code }", hint: "{ issuer, code, decimals }" },
91
+ xrpl: { key: "currencyHex", shape: "{ issuer, currencyHex }", hint: "{ issuer, currencyHex, decimals }" },
92
+ tron: { key: "address", shape: "{ address }", hint: "{ address, decimals }" },
93
+ sui: { key: "coinType", shape: "{ coinType }", hint: "{ coinType, decimals }" },
94
+ near: { key: "contractId", shape: "{ contractId }", hint: "{ contractId, decimals }" }
95
+ };
96
+ function rejectForeignToken(token, family, network) {
97
+ const own = FAMILY_TOKEN[family];
98
+ for (const fam of Object.keys(FAMILY_TOKEN)) {
99
+ if (fam === family) continue;
100
+ if (FAMILY_TOKEN[fam].key === own.key) continue;
101
+ if (FAMILY_TOKEN[fam].key in token) {
102
+ throw new WrongFamilyError(
103
+ `chain ${network} is ${FAMILY_LABEL[family]}; a ${FAMILY_LABEL[fam]} ${FAMILY_TOKEN[fam].shape} token can't be used \u2014 pass ${own.hint}.`
104
+ );
105
+ }
106
+ }
107
+ }
108
+
109
+ // src/util/units.ts
110
+ function parseUnits(value, decimals) {
111
+ if (!/^\d+(\.\d+)?$/.test(value)) {
112
+ throw new Error(`parseUnits: "${value}" is not a non-negative decimal amount.`);
113
+ }
114
+ const [whole, frac = ""] = value.split(".");
115
+ if (frac.length > decimals) {
116
+ throw new Error(
117
+ `parseUnits: "${value}" has more than ${decimals} decimal places.`
118
+ );
119
+ }
120
+ const fracPadded = frac.padEnd(decimals, "0");
121
+ return BigInt(whole + fracPadded);
122
+ }
123
+ function floorUnits(value, decimals) {
124
+ if (!/^\d+(\.\d+)?$/.test(value)) {
125
+ throw new Error(`floorUnits: "${value}" is not a non-negative decimal amount.`);
126
+ }
127
+ const [whole, frac = ""] = value.split(".");
128
+ const fracTrunc = frac.slice(0, decimals).padEnd(decimals, "0");
129
+ return BigInt(whole + fracTrunc);
130
+ }
131
+ function formatUnits(value, decimals) {
132
+ const negative = value < 0n;
133
+ const digits = (negative ? -value : value).toString().padStart(decimals + 1, "0");
134
+ const whole = digits.slice(0, digits.length - decimals);
135
+ const frac = digits.slice(digits.length - decimals).replace(/0+$/, "");
136
+ return `${negative ? "-" : ""}${whole}${frac ? `.${frac}` : ""}`;
137
+ }
138
+
139
+ // src/util/cost.ts
140
+ function nativeCost(opts) {
141
+ return {
142
+ feeSymbol: opts.symbol,
143
+ feeDecimals: opts.decimals,
144
+ fee: opts.fee.toString(),
145
+ feeFormatted: formatUnits(opts.fee, opts.decimals),
146
+ basis: opts.basis,
147
+ ...opts.detail ? { detail: opts.detail } : {}
148
+ };
149
+ }
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+ exports.PipRailError = PipRailError; exports.InsufficientFundsError = InsufficientFundsError; exports.RecipientNotReadyError = RecipientNotReadyError; exports.toInsufficientFundsError = toInsufficientFundsError; exports.WrongChainError = WrongChainError; exports.PaymentTimeoutError = PaymentTimeoutError; exports.MaxRetriesExceededError = MaxRetriesExceededError; exports.PaymentDeclinedError = PaymentDeclinedError; exports.ConfirmationTimeoutError = ConfirmationTimeoutError; exports.InvalidEnvelopeError = InvalidEnvelopeError; exports.NoCompatibleAcceptError = NoCompatibleAcceptError; exports.NonReplayableBodyError = NonReplayableBodyError; exports.WrongFamilyError = WrongFamilyError; exports.UnknownTokenError = UnknownTokenError; exports.MissingDriverError = MissingDriverError; exports.UnsupportedNetworkError = UnsupportedNetworkError; exports.rejectForeignToken = rejectForeignToken; exports.parseUnits = parseUnits; exports.floorUnits = floorUnits; exports.formatUnits = formatUnits; exports.nativeCost = nativeCost;
package/dist/index.cjs CHANGED
@@ -19,7 +19,8 @@
19
19
 
20
20
 
21
21
 
22
- var _chunkWQWNPAYQcjs = require('./chunk-WQWNPAYQ.cjs');
22
+
23
+ var _chunkNK64H3RMcjs = require('./chunk-NK64H3RM.cjs');
23
24
 
24
25
  // src/drivers/registry.ts
25
26
  var byFamily = /* @__PURE__ */ new Map();
@@ -46,13 +47,13 @@ function resolveNetwork(opts) {
46
47
  const family = familyForChain(opts.chain);
47
48
  const driver = byFamily.get(family);
48
49
  if (!driver) {
49
- throw new (0, _chunkWQWNPAYQcjs.UnsupportedNetworkError)(
50
+ throw new (0, _chunkNK64H3RMcjs.UnsupportedNetworkError)(
50
51
  `No driver registered for the "${family}" family \u2014 it may not be mounted yet (use the async resolveNetwork()).`
51
52
  );
52
53
  }
53
54
  const net = driver.resolve(opts);
54
55
  if (!net) {
55
- throw new (0, _chunkWQWNPAYQcjs.UnsupportedNetworkError)(
56
+ throw new (0, _chunkNK64H3RMcjs.UnsupportedNetworkError)(
56
57
  `The ${family} driver didn't recognise this chain input.`
57
58
  );
58
59
  }
@@ -272,12 +273,12 @@ function createWalletAdapter(config, resolved) {
272
273
  }
273
274
  const wc = config.walletClient;
274
275
  if (!wc.account) {
275
- throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
276
+ throw new (0, _chunkNK64H3RMcjs.WrongFamilyError)(
276
277
  "chain is EVM; the provided walletClient has no attached account. Use `createWalletClient({ account, chain, transport })`, or pass { privateKey }."
277
278
  );
278
279
  }
279
280
  if (wc.chain && wc.chain.id !== resolved.chainId) {
280
- throw new (0, _chunkWQWNPAYQcjs.WrongChainError)(
281
+ throw new (0, _chunkNK64H3RMcjs.WrongChainError)(
281
282
  `PipRailClient: walletClient is on chain ${wc.chain.id} but the SDK was configured with chain ${resolved.chainId}. They must match.`
282
283
  );
283
284
  }
@@ -580,15 +581,15 @@ function makeEvmNetwork(resolved) {
580
581
  const info = resolved.tokens[token.toUpperCase()];
581
582
  if (!info) {
582
583
  const known = Object.keys(resolved.tokens).join(", ") || "(none built in)";
583
- throw new (0, _chunkWQWNPAYQcjs.UnknownTokenError)(
584
+ throw new (0, _chunkNK64H3RMcjs.UnknownTokenError)(
584
585
  `token "${token}" isn't built in for ${resolved.chain.name} (known: ${known}). Pass { address, decimals } instead, or use 'native'.`
585
586
  );
586
587
  }
587
588
  return { asset: info.address, decimals: info.decimals, symbol: info.symbol };
588
589
  }
589
- _chunkWQWNPAYQcjs.rejectForeignToken.call(void 0, token, "evm", network);
590
+ _chunkNK64H3RMcjs.rejectForeignToken.call(void 0, token, "evm", network);
590
591
  if (!("address" in token)) {
591
- throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
592
+ throw new (0, _chunkNK64H3RMcjs.WrongFamilyError)(
592
593
  `chain ${network} is EVM; a custom token must be { address, decimals }.`
593
594
  );
594
595
  }
@@ -620,14 +621,14 @@ function makeEvmNetwork(resolved) {
620
621
  },
621
622
  assertValidPayTo(payTo) {
622
623
  if (!_viem.isAddress.call(void 0, payTo)) {
623
- throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
624
+ throw new (0, _chunkNK64H3RMcjs.WrongFamilyError)(
624
625
  `chain ${network} is EVM, but payTo "${payTo}" is not a valid 0x address.`
625
626
  );
626
627
  }
627
628
  },
628
629
  bindWallet(wallet) {
629
630
  if (typeof wallet !== "object" || wallet === null || !("privateKey" in wallet) && !("walletClient" in wallet)) {
630
- throw new (0, _chunkWQWNPAYQcjs.WrongFamilyError)(
631
+ throw new (0, _chunkNK64H3RMcjs.WrongFamilyError)(
631
632
  `chain ${network} is EVM; wallet must be { privateKey } or { walletClient }.`
632
633
  );
633
634
  }
@@ -644,12 +645,12 @@ function makeEvmNetwork(resolved) {
644
645
  });
645
646
  } catch (err) {
646
647
  if (isViemInsufficientFunds(err)) {
647
- throw new (0, _chunkWQWNPAYQcjs.InsufficientFundsError)(
648
+ throw new (0, _chunkNK64H3RMcjs.InsufficientFundsError)(
648
649
  err instanceof Error ? err.message : "Insufficient funds for payment.",
649
650
  { cause: err }
650
651
  );
651
652
  }
652
- throw _nullishCoalesce(_chunkWQWNPAYQcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
653
+ throw _nullishCoalesce(_chunkNK64H3RMcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
653
654
  }
654
655
  },
655
656
  async confirm(ref, minConfirmations) {
@@ -660,7 +661,7 @@ function makeEvmNetwork(resolved) {
660
661
  });
661
662
  return { height: receipt.blockNumber.toString() };
662
663
  } catch (err) {
663
- throw new (0, _chunkWQWNPAYQcjs.ConfirmationTimeoutError)(
664
+ throw new (0, _chunkNK64H3RMcjs.ConfirmationTimeoutError)(
664
665
  `EVM tx ${ref} did not reach ${minConfirmations} confirmation(s) in time.`,
665
666
  { cause: err }
666
667
  );
@@ -671,7 +672,7 @@ function makeEvmNetwork(resolved) {
671
672
  const gasLimit = accept.asset === "native" ? 21000n : 65000n;
672
673
  try {
673
674
  const gasPrice = await publicClient.getGasPrice();
674
- return _chunkWQWNPAYQcjs.nativeCost.call(void 0, {
675
+ return _chunkNK64H3RMcjs.nativeCost.call(void 0, {
675
676
  symbol,
676
677
  decimals,
677
678
  fee: gasPrice * gasLimit,
@@ -680,7 +681,7 @@ function makeEvmNetwork(resolved) {
680
681
  });
681
682
  } catch (e10) {
682
683
  const gasPrice = 5000000000n;
683
- return _chunkWQWNPAYQcjs.nativeCost.call(void 0, {
684
+ return _chunkNK64H3RMcjs.nativeCost.call(void 0, {
684
685
  symbol,
685
686
  decimals,
686
687
  fee: gasPrice * gasLimit,
@@ -712,9 +713,9 @@ var loaders = {
712
713
  solana: async () => {
713
714
  let mod;
714
715
  try {
715
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-F7H4YDW5.cjs")));
716
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./solana-CRLWAM7C.cjs")));
716
717
  } catch (cause) {
717
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
718
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
718
719
  `Solana selected, but its packages aren't installed. Run: npm install @solana/web3.js @solana/spl-token bs58`,
719
720
  { cause }
720
721
  );
@@ -724,9 +725,9 @@ var loaders = {
724
725
  ton: async () => {
725
726
  let mod;
726
727
  try {
727
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-E5RLUPD2.cjs")));
728
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./ton-OVSQZ4OM.cjs")));
728
729
  } catch (cause) {
729
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
730
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
730
731
  `TON selected, but its packages aren't installed. Run: npm install @ton/ton @ton/core @ton/crypto`,
731
732
  { cause }
732
733
  );
@@ -736,9 +737,9 @@ var loaders = {
736
737
  stellar: async () => {
737
738
  let mod;
738
739
  try {
739
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-BPPQTLNI.cjs")));
740
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./stellar-LIGJKRRK.cjs")));
740
741
  } catch (cause) {
741
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
742
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
742
743
  `Stellar selected, but its package isn't installed. Run: npm install @stellar/stellar-sdk`,
743
744
  { cause }
744
745
  );
@@ -748,9 +749,9 @@ var loaders = {
748
749
  xrpl: async () => {
749
750
  let mod;
750
751
  try {
751
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-6NRFT5CA.cjs")));
752
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./xrpl-QECPQCFS.cjs")));
752
753
  } catch (cause) {
753
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
754
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
754
755
  `XRPL selected, but its package isn't installed. Run: npm install xrpl`,
755
756
  { cause }
756
757
  );
@@ -760,9 +761,9 @@ var loaders = {
760
761
  tron: async () => {
761
762
  let mod;
762
763
  try {
763
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-3UDH7KGF.cjs")));
764
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./tron-V3A6L3X3.cjs")));
764
765
  } catch (cause) {
765
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
766
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
766
767
  `Tron selected, but its package isn't installed. Run: npm install tronweb`,
767
768
  { cause }
768
769
  );
@@ -772,9 +773,9 @@ var loaders = {
772
773
  sui: async () => {
773
774
  let mod;
774
775
  try {
775
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-XV4YYSGV.cjs")));
776
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./sui-JLVWFDOS.cjs")));
776
777
  } catch (cause) {
777
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
778
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
778
779
  `Sui selected, but its package isn't installed. Run: npm install @mysten/sui`,
779
780
  { cause }
780
781
  );
@@ -784,9 +785,9 @@ var loaders = {
784
785
  near: async () => {
785
786
  let mod;
786
787
  try {
787
- mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-4P5XNMMB.cjs")));
788
+ mod = await Promise.resolve().then(() => _interopRequireWildcard(require("./near-VZ6XGVNJ.cjs")));
788
789
  } catch (cause) {
789
- throw new (0, _chunkWQWNPAYQcjs.MissingDriverError)(
790
+ throw new (0, _chunkNK64H3RMcjs.MissingDriverError)(
790
791
  `NEAR selected, but its package isn't installed. Run: npm install near-api-js`,
791
792
  { cause }
792
793
  );
@@ -858,7 +859,7 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
858
859
  }
859
860
  }
860
861
  if (policy.maxAmount !== void 0) {
861
- const cap = _chunkWQWNPAYQcjs.floorUnits.call(void 0, policy.maxAmount, intent.decimals);
862
+ const cap = _chunkNK64H3RMcjs.floorUnits.call(void 0, policy.maxAmount, intent.decimals);
862
863
  if (intent.amountBase > cap) {
863
864
  return deny(
864
865
  `payment of ${intent.amountBase} base units exceeds policy.maxAmount ` + `(${policy.maxAmount} ${_nullishCoalesce(intent.symbol, () => ( ""))}).`.trimEnd()
@@ -866,7 +867,7 @@ function evaluatePolicy(intent, policy, spentForAssetBase) {
866
867
  }
867
868
  }
868
869
  if (policy.maxTotal !== void 0) {
869
- const cap = _chunkWQWNPAYQcjs.floorUnits.call(void 0, policy.maxTotal, intent.decimals);
870
+ const cap = _chunkNK64H3RMcjs.floorUnits.call(void 0, policy.maxTotal, intent.decimals);
870
871
  if (spentForAssetBase + intent.amountBase > cap) {
871
872
  return deny(
872
873
  `this payment would push spend on ${_nullishCoalesce(intent.symbol, () => ( intent.asset))} past policy.maxTotal (${policy.maxTotal}); already spent ${spentForAssetBase} base units.`
@@ -916,7 +917,7 @@ var SpendLedger = (_class = class {constructor() { _class.prototype.__init.call(
916
917
  symbol: b.symbol,
917
918
  decimals: b.decimals,
918
919
  totalBase: b.total.toString(),
919
- totalFormatted: _chunkWQWNPAYQcjs.formatUnits.call(void 0, b.total, b.decimals),
920
+ totalFormatted: _chunkNK64H3RMcjs.formatUnits.call(void 0, b.total, b.decimals),
920
921
  count: b.count
921
922
  })),
922
923
  records: [...this.records]
@@ -1043,7 +1044,7 @@ var PipRailClient = (_class2 = class {
1043
1044
  async fetch(url, init) {
1044
1045
  const body = _optionalChain([init, 'optionalAccess', _9 => _9.body]);
1045
1046
  if (body !== void 0 && body !== null && !isReplayableBodyInit(body)) {
1046
- throw new (0, _chunkWQWNPAYQcjs.NonReplayableBodyError)(
1047
+ throw new (0, _chunkNK64H3RMcjs.NonReplayableBodyError)(
1047
1048
  "fetch(): init.body is not replayable. Pass a string, FormData, URLSearchParams, ArrayBuffer, or Blob \u2014 not a ReadableStream."
1048
1049
  );
1049
1050
  }
@@ -1055,8 +1056,8 @@ var PipRailClient = (_class2 = class {
1055
1056
  );
1056
1057
  this.safeEmit({ kind: "payment-required", challenge, accept });
1057
1058
  await this.authorize(quote);
1058
- const ref = await this.payAndConfirm(net, wallet, accept);
1059
- const response = await this.retryWithProof(url, init, accept, ref);
1059
+ const { ref, confirmed } = await this.payAndConfirm(net, wallet, accept);
1060
+ const response = await this.retryWithProof(url, init, accept, ref, confirmed);
1060
1061
  this.recordSpend(quote, ref);
1061
1062
  return response;
1062
1063
  }
@@ -1069,7 +1070,7 @@ var PipRailClient = (_class2 = class {
1069
1070
  async resolveChallenge(url, response) {
1070
1071
  const challenge = await parseChallenge(response);
1071
1072
  if (!challenge) {
1072
- throw new (0, _chunkWQWNPAYQcjs.InvalidEnvelopeError)(
1073
+ throw new (0, _chunkNK64H3RMcjs.InvalidEnvelopeError)(
1073
1074
  "402 response did not include a parseable x402 challenge."
1074
1075
  );
1075
1076
  }
@@ -1079,7 +1080,7 @@ var PipRailClient = (_class2 = class {
1079
1080
  );
1080
1081
  if (candidates.length === 0) {
1081
1082
  const networks = challenge.accepts.map((a) => a.network).join(", ");
1082
- throw new (0, _chunkWQWNPAYQcjs.NoCompatibleAcceptError)(
1083
+ throw new (0, _chunkNK64H3RMcjs.NoCompatibleAcceptError)(
1083
1084
  `No accepts[] entry for ${net.network} (challenge offered: ${networks || "none"}).`
1084
1085
  );
1085
1086
  }
@@ -1094,7 +1095,7 @@ var PipRailClient = (_class2 = class {
1094
1095
  * driver's describeAsset) + the policy verdict + a symbol-mismatch flag. */
1095
1096
  buildQuote(net, accept, url, description) {
1096
1097
  if (!/^\d+$/.test(accept.amount)) {
1097
- throw new (0, _chunkWQWNPAYQcjs.InvalidEnvelopeError)(
1098
+ throw new (0, _chunkNK64H3RMcjs.InvalidEnvelopeError)(
1098
1099
  `challenge amount "${accept.amount}" is not a base-unit integer.`
1099
1100
  );
1100
1101
  }
@@ -1102,7 +1103,7 @@ var PipRailClient = (_class2 = class {
1102
1103
  const described = net.describeAsset(accept.asset);
1103
1104
  const decimals = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _10 => _10.decimals]), () => ( accept.extra.decimals));
1104
1105
  const symbol = _nullishCoalesce(_optionalChain([described, 'optionalAccess', _11 => _11.symbol]), () => ( accept.extra.symbol));
1105
- const amountFormatted = _chunkWQWNPAYQcjs.formatUnits.call(void 0, amountBase, decimals);
1106
+ const amountFormatted = _chunkNK64H3RMcjs.formatUnits.call(void 0, amountBase, decimals);
1106
1107
  const intent = {
1107
1108
  host: hostOf(url),
1108
1109
  chain: this.opts.chain,
@@ -1142,7 +1143,7 @@ var PipRailClient = (_class2 = class {
1142
1143
  * throwing PaymentDeclinedError, before any funds move. */
1143
1144
  async authorize(quote) {
1144
1145
  if (!quote.withinPolicy) {
1145
- throw new (0, _chunkWQWNPAYQcjs.PaymentDeclinedError)(
1146
+ throw new (0, _chunkNK64H3RMcjs.PaymentDeclinedError)(
1146
1147
  `Payment refused by policy: ${_nullishCoalesce(quote.policyReason, () => ( "not allowed"))}`
1147
1148
  );
1148
1149
  }
@@ -1152,12 +1153,12 @@ var PipRailClient = (_class2 = class {
1152
1153
  try {
1153
1154
  approved = await hook(quote);
1154
1155
  } catch (err) {
1155
- throw new (0, _chunkWQWNPAYQcjs.PaymentDeclinedError)("onBeforePay threw \u2014 refusing to pay.", {
1156
+ throw new (0, _chunkNK64H3RMcjs.PaymentDeclinedError)("onBeforePay threw \u2014 refusing to pay.", {
1156
1157
  cause: err
1157
1158
  });
1158
1159
  }
1159
1160
  if (!approved) {
1160
- throw new (0, _chunkWQWNPAYQcjs.PaymentDeclinedError)(
1161
+ throw new (0, _chunkNK64H3RMcjs.PaymentDeclinedError)(
1161
1162
  `onBeforePay declined ${quote.amountFormatted} ${_nullishCoalesce(quote.symbol, () => ( ""))}`.trimEnd() + ` on ${quote.network}.`
1162
1163
  );
1163
1164
  }
@@ -1181,21 +1182,30 @@ var PipRailClient = (_class2 = class {
1181
1182
  }
1182
1183
  async payAndConfirm(net, wallet, accept) {
1183
1184
  if (!net.supports(accept.network)) {
1184
- throw new (0, _chunkWQWNPAYQcjs.WrongChainError)(
1185
+ throw new (0, _chunkNK64H3RMcjs.WrongChainError)(
1185
1186
  `Challenge expects ${accept.network} but client is on ${net.network}.`
1186
1187
  );
1187
1188
  }
1188
1189
  const ref = await net.send(wallet, accept);
1189
1190
  this.safeEmit({ kind: "payment-broadcast", ref });
1190
- const { height } = await net.confirm(ref, _nullishCoalesce(accept.extra.minConfirmations, () => ( 1)));
1191
- this.safeEmit({
1192
- kind: "payment-confirmed",
1193
- ref,
1194
- blockNumber: BigInt(height)
1195
- });
1196
- return ref;
1191
+ try {
1192
+ const { height } = await net.confirm(ref, _nullishCoalesce(accept.extra.minConfirmations, () => ( 1)));
1193
+ this.safeEmit({
1194
+ kind: "payment-confirmed",
1195
+ ref,
1196
+ blockNumber: BigInt(height)
1197
+ });
1198
+ return { ref, confirmed: true };
1199
+ } catch (err) {
1200
+ this.safeEmit({
1201
+ kind: "payment-unconfirmed",
1202
+ ref,
1203
+ reason: err instanceof Error ? err.message : String(err)
1204
+ });
1205
+ return { ref, confirmed: false };
1206
+ }
1197
1207
  }
1198
- async retryWithProof(url, originalInit, accept, ref) {
1208
+ async retryWithProof(url, originalInit, accept, ref, confirmed) {
1199
1209
  const signature = {
1200
1210
  x402Version: 2,
1201
1211
  accepted: accept,
@@ -1205,9 +1215,11 @@ var PipRailClient = (_class2 = class {
1205
1215
  headers.set(HEADER_SIGNATURE, buildSignatureHeader(signature));
1206
1216
  let lastResponse = null;
1207
1217
  let lastReason = null;
1208
- for (let attempt = 0; attempt < this.maxRetries; attempt += 1) {
1218
+ const attempts = confirmed ? this.maxRetries : Math.max(this.maxRetries, 6);
1219
+ const backoffCap = confirmed ? 2e3 : 5e3;
1220
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
1209
1221
  if (attempt > 0) {
1210
- await new Promise((r) => setTimeout(r, Math.min(2e3, 400 * 2 ** (attempt - 1))));
1222
+ await new Promise((r) => setTimeout(r, Math.min(backoffCap, 400 * 2 ** (attempt - 1))));
1211
1223
  }
1212
1224
  const timeoutController = new AbortController();
1213
1225
  const timeoutId = setTimeout(
@@ -1223,9 +1235,9 @@ var PipRailClient = (_class2 = class {
1223
1235
  });
1224
1236
  } catch (err) {
1225
1237
  if (timeoutController.signal.aborted) {
1226
- throw new (0, _chunkWQWNPAYQcjs.PaymentTimeoutError)(
1227
- `Server did not respond within ${this.retryTimeoutMs}ms after on-chain payment ${ref} confirmed.`,
1228
- { cause: err }
1238
+ throw new (0, _chunkNK64H3RMcjs.PaymentTimeoutError)(
1239
+ `Server did not respond within ${this.retryTimeoutMs}ms after broadcasting payment ${ref}. Re-verify or re-submit ref=${ref} \u2014 do NOT re-pay.`,
1240
+ { cause: err, ref }
1229
1241
  );
1230
1242
  }
1231
1243
  throw err;
@@ -1240,12 +1252,14 @@ var PipRailClient = (_class2 = class {
1240
1252
  lastReason = await _asyncNullishCoalesce(await readInvalidReason(lastResponse), async () => ( lastReason));
1241
1253
  }
1242
1254
  const why = lastReason ? `${lastReason.error}${lastReason.detail ? ` \u2014 ${lastReason.detail}` : ""}` : "server gave no reason";
1255
+ const unconfirmedNote = confirmed ? "" : " (broadcast but NOT locally confirmed \u2014 it may still have settled on-chain)";
1243
1256
  this.safeEmit({
1244
1257
  kind: "payment-failed",
1245
- reason: `server returned 402 after on-chain payment ${ref} confirmed (${why})`
1258
+ reason: `server returned 402 after broadcasting payment ${ref}${unconfirmedNote} (${why})`
1246
1259
  });
1247
- throw new (0, _chunkWQWNPAYQcjs.MaxRetriesExceededError)(
1248
- `Server still returned 402 after ${this.maxRetries} retry attempt(s) with on-chain proof ref=${ref}. Last server rejection: ${why}.`
1260
+ throw new (0, _chunkNK64H3RMcjs.MaxRetriesExceededError)(
1261
+ `Server still returned 402 after ${attempts} attempt(s) with on-chain proof ref=${ref}${unconfirmedNote}. Last server rejection: ${why}. Re-verify or re-submit ref=${ref} before retrying \u2014 never re-pay (it would double-spend).`,
1262
+ { ref }
1249
1263
  );
1250
1264
  }
1251
1265
  }, _class2);
@@ -1351,7 +1365,7 @@ function paymentTools(client) {
1351
1365
  receipt: parseReceipt(res)
1352
1366
  };
1353
1367
  } catch (err) {
1354
- if (err instanceof _chunkWQWNPAYQcjs.PaymentDeclinedError) {
1368
+ if (err instanceof _chunkNK64H3RMcjs.PaymentDeclinedError) {
1355
1369
  return { declined: true, reason: err.message };
1356
1370
  }
1357
1371
  throw err;
@@ -1400,7 +1414,7 @@ function createPaymentGate(options) {
1400
1414
  }
1401
1415
  net.assertValidPayTo(payTo);
1402
1416
  const { asset, decimals, symbol } = net.resolveToken(a.token);
1403
- const amountBase = _chunkWQWNPAYQcjs.parseUnits.call(void 0, a.amount, decimals);
1417
+ const amountBase = _chunkNK64H3RMcjs.parseUnits.call(void 0, a.amount, decimals);
1404
1418
  return { net, asset, decimals, symbol, amountBase, amountFormatted: a.amount, payTo };
1405
1419
  })
1406
1420
  );
@@ -1678,4 +1692,5 @@ function encodeXPaymentHeader(input) {
1678
1692
 
1679
1693
 
1680
1694
 
1681
- exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkWQWNPAYQcjs.ConfirmationTimeoutError; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.InsufficientFundsError = _chunkWQWNPAYQcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkWQWNPAYQcjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkWQWNPAYQcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkWQWNPAYQcjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkWQWNPAYQcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkWQWNPAYQcjs.NonReplayableBodyError; exports.PaymentDeclinedError = _chunkWQWNPAYQcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkWQWNPAYQcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkWQWNPAYQcjs.PipRailError; exports.UnknownTokenError = _chunkWQWNPAYQcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkWQWNPAYQcjs.UnsupportedNetworkError; exports.WrongChainError = _chunkWQWNPAYQcjs.WrongChainError; exports.WrongFamilyError = _chunkWQWNPAYQcjs.WrongFamilyError; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.createPaymentGate = createPaymentGate; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.parseChallenge = parseChallenge; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.registerDriver = registerDriver; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.toInsufficientFundsError = _chunkWQWNPAYQcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody;
1695
+
1696
+ exports.CHAINS = CHAINS; exports.ConfirmationTimeoutError = _chunkNK64H3RMcjs.ConfirmationTimeoutError; exports.EIP3009_TYPES = EIP3009_TYPES; exports.EXACT_NETWORK_SLUGS = EXACT_NETWORK_SLUGS; exports.InsufficientFundsError = _chunkNK64H3RMcjs.InsufficientFundsError; exports.InvalidEnvelopeError = _chunkNK64H3RMcjs.InvalidEnvelopeError; exports.MaxRetriesExceededError = _chunkNK64H3RMcjs.MaxRetriesExceededError; exports.MissingDriverError = _chunkNK64H3RMcjs.MissingDriverError; exports.NoCompatibleAcceptError = _chunkNK64H3RMcjs.NoCompatibleAcceptError; exports.NonReplayableBodyError = _chunkNK64H3RMcjs.NonReplayableBodyError; exports.PaymentDeclinedError = _chunkNK64H3RMcjs.PaymentDeclinedError; exports.PaymentTimeoutError = _chunkNK64H3RMcjs.PaymentTimeoutError; exports.PipRailClient = PipRailClient; exports.PipRailError = _chunkNK64H3RMcjs.PipRailError; exports.RecipientNotReadyError = _chunkNK64H3RMcjs.RecipientNotReadyError; exports.UnknownTokenError = _chunkNK64H3RMcjs.UnknownTokenError; exports.UnsupportedNetworkError = _chunkNK64H3RMcjs.UnsupportedNetworkError; exports.WrongChainError = _chunkNK64H3RMcjs.WrongChainError; exports.WrongFamilyError = _chunkNK64H3RMcjs.WrongFamilyError; exports.buildChallengeHeader = buildChallengeHeader; exports.buildExactAuthorization = buildExactAuthorization; exports.buildReceiptHeader = buildReceiptHeader; exports.buildSignatureHeader = buildSignatureHeader; exports.chainIdForExactNetwork = chainIdForExactNetwork; exports.createPaymentGate = createPaymentGate; exports.encodeXPaymentHeader = encodeXPaymentHeader; exports.evaluatePolicy = evaluatePolicy; exports.parseChallenge = parseChallenge; exports.parseExactRequirements = parseExactRequirements; exports.parseReceipt = parseReceipt; exports.parseSignatureHeader = parseSignatureHeader; exports.paymentTools = paymentTools; exports.pickAccept = pickAccept; exports.registerDriver = registerDriver; exports.requirePayment = requirePayment; exports.resolveChain = resolveChain; exports.toInsufficientFundsError = _chunkNK64H3RMcjs.toInsufficientFundsError; exports.toInvalidBody = toInvalidBody;