@arkade-os/sdk 0.4.53 → 0.4.55

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.
Files changed (81) hide show
  1. package/dist/adapters/expo.cjs +5 -5
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +3 -3
  5. package/dist/adapters/indexedDB.cjs +5 -5
  6. package/dist/adapters/indexedDB.js +4 -4
  7. package/dist/{ark-B69ugeJw.d.cts → ark-Do9Lqfsp.d.cts} +36 -2
  8. package/dist/{ark-B69ugeJw.d.ts → ark-Do9Lqfsp.d.ts} +36 -2
  9. package/dist/{asyncStorageTaskQueue-B0SUQMXw.d.cts → asyncStorageTaskQueue-C3DYxvAT.d.cts} +1 -1
  10. package/dist/{asyncStorageTaskQueue-DWqxuIAs.d.ts → asyncStorageTaskQueue-DOnBOEDn.d.ts} +1 -1
  11. package/dist/{chunk-CZTQLA55.cjs → chunk-C6UYPHTQ.cjs} +9 -9
  12. package/dist/{chunk-CZTQLA55.cjs.map → chunk-C6UYPHTQ.cjs.map} +1 -1
  13. package/dist/{chunk-4GB73TRR.cjs → chunk-CSS74VCN.cjs} +17 -17
  14. package/dist/{chunk-4GB73TRR.cjs.map → chunk-CSS74VCN.cjs.map} +1 -1
  15. package/dist/{chunk-LHYNNDY6.js → chunk-ENWR2F2P.js} +8 -1327
  16. package/dist/chunk-ENWR2F2P.js.map +1 -0
  17. package/dist/{chunk-RNMLFY2V.cjs → chunk-G7DOBFQN.cjs} +19 -1367
  18. package/dist/chunk-G7DOBFQN.cjs.map +1 -0
  19. package/dist/chunk-JCJ5WFS3.js +2326 -0
  20. package/dist/chunk-JCJ5WFS3.js.map +1 -0
  21. package/dist/{chunk-B4WZOJAI.js → chunk-LAONNMM5.js} +4 -4
  22. package/dist/{chunk-B4WZOJAI.js.map → chunk-LAONNMM5.js.map} +1 -1
  23. package/dist/chunk-OWCPXRGP.cjs +2415 -0
  24. package/dist/chunk-OWCPXRGP.cjs.map +1 -0
  25. package/dist/{chunk-UZLQUWYP.js → chunk-QMPNPZ2T.js} +23 -4
  26. package/dist/chunk-QMPNPZ2T.js.map +1 -0
  27. package/dist/{chunk-3MMUKLCI.js → chunk-QO3IKBYL.js} +827 -130
  28. package/dist/chunk-QO3IKBYL.js.map +1 -0
  29. package/dist/{chunk-3XWDMLOI.js → chunk-SG4X7SEC.js} +4 -4
  30. package/dist/{chunk-3XWDMLOI.js.map → chunk-SG4X7SEC.js.map} +1 -1
  31. package/dist/{chunk-IEMPH7J6.cjs → chunk-V2TOHHPW.cjs} +60 -40
  32. package/dist/chunk-V2TOHHPW.cjs.map +1 -0
  33. package/dist/{chunk-3YC3LQ2E.cjs → chunk-ZPL34T2Q.cjs} +1191 -471
  34. package/dist/chunk-ZPL34T2Q.cjs.map +1 -0
  35. package/dist/contracts/handlers/index.cjs +8 -8
  36. package/dist/contracts/handlers/index.d.cts +3 -3
  37. package/dist/contracts/handlers/index.d.ts +3 -3
  38. package/dist/contracts/handlers/index.js +2 -2
  39. package/dist/{delegate-C_Y2YrXC.d.cts → delegate-C0iIBxen.d.cts} +1 -1
  40. package/dist/{delegate-BU-Cpyjw.d.ts → delegate-DmhFrtdq.d.ts} +1 -1
  41. package/dist/{index-BWF-C9eh.d.ts → index-BNt4wcSh.d.ts} +2 -2
  42. package/dist/{index-tzAInyiX.d.cts → index-BnLM1XxA.d.cts} +2 -2
  43. package/dist/index.cjs +348 -240
  44. package/dist/index.d.cts +424 -14
  45. package/dist/index.d.ts +424 -14
  46. package/dist/index.js +4 -4
  47. package/dist/repositories/realm/index.cjs +19 -19
  48. package/dist/repositories/realm/index.d.cts +2 -2
  49. package/dist/repositories/realm/index.d.ts +2 -2
  50. package/dist/repositories/realm/index.js +5 -5
  51. package/dist/repositories/sqlite/index.cjs +18 -18
  52. package/dist/repositories/sqlite/index.d.cts +2 -2
  53. package/dist/repositories/sqlite/index.d.ts +2 -2
  54. package/dist/repositories/sqlite/index.js +5 -5
  55. package/dist/{taskRunner-nzJFH8qb.d.ts → taskRunner-Bgs-0I3x.d.ts} +1 -1
  56. package/dist/{taskRunner-B7svzMhT.d.cts → taskRunner-RwUvgQ5M.d.cts} +1 -1
  57. package/dist/wallet/expo/background.cjs +14 -14
  58. package/dist/wallet/expo/background.d.cts +3 -3
  59. package/dist/wallet/expo/background.d.ts +3 -3
  60. package/dist/wallet/expo/background.js +6 -6
  61. package/dist/wallet/expo/index.cjs +14 -14
  62. package/dist/wallet/expo/index.d.cts +5 -5
  63. package/dist/wallet/expo/index.d.ts +5 -5
  64. package/dist/wallet/expo/index.js +5 -5
  65. package/dist/{wallet-B6Xiferv.d.cts → wallet-5Aou-V5n.d.ts} +83 -6
  66. package/dist/{wallet-CuHAI-eW.d.ts → wallet-Ck7BH8zR.d.cts} +83 -6
  67. package/dist/worker/expo/index.cjs +9 -9
  68. package/dist/worker/expo/index.d.cts +4 -4
  69. package/dist/worker/expo/index.d.ts +4 -4
  70. package/dist/worker/expo/index.js +5 -5
  71. package/package.json +1 -1
  72. package/dist/chunk-3MMUKLCI.js.map +0 -1
  73. package/dist/chunk-3YC3LQ2E.cjs.map +0 -1
  74. package/dist/chunk-E7HB3GKK.cjs +0 -1030
  75. package/dist/chunk-E7HB3GKK.cjs.map +0 -1
  76. package/dist/chunk-EFNLTS6Q.js +0 -976
  77. package/dist/chunk-EFNLTS6Q.js.map +0 -1
  78. package/dist/chunk-IEMPH7J6.cjs.map +0 -1
  79. package/dist/chunk-LHYNNDY6.js.map +0 -1
  80. package/dist/chunk-RNMLFY2V.cjs.map +0 -1
  81. package/dist/chunk-UZLQUWYP.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkRNMLFY2V_cjs = require('./chunk-RNMLFY2V.cjs');
4
- var chunkIEMPH7J6_cjs = require('./chunk-IEMPH7J6.cjs');
5
- var chunkE7HB3GKK_cjs = require('./chunk-E7HB3GKK.cjs');
3
+ var chunkG7DOBFQN_cjs = require('./chunk-G7DOBFQN.cjs');
4
+ var chunkV2TOHHPW_cjs = require('./chunk-V2TOHHPW.cjs');
5
+ var chunkOWCPXRGP_cjs = require('./chunk-OWCPXRGP.cjs');
6
6
  var chunk5BLDMQED_cjs = require('./chunk-5BLDMQED.cjs');
7
7
  var utils_js = require('@scure/btc-signer/utils.js');
8
8
  var btcSigner = require('@scure/btc-signer');
@@ -47,8 +47,8 @@ function aggregateNonces(pubNonces) {
47
47
  return musig2__namespace.nonceAggregate(pubNonces);
48
48
  }
49
49
  function aggregateKeys(publicKeys, sort, options = {}) {
50
- {
51
- publicKeys = musig2__namespace.sortKeys(publicKeys);
50
+ if (sort) {
51
+ publicKeys = musig2__namespace.sortKeys([...publicKeys]);
52
52
  }
53
53
  const { aggPublicKey: preTweakedKey } = musig2__namespace.keyAggregate(publicKeys);
54
54
  if (!options.taprootTweak) {
@@ -110,24 +110,27 @@ var PartialSig = class _PartialSig {
110
110
  return new _PartialSig(bytes, R);
111
111
  }
112
112
  };
113
- function sign(secNonce, privateKey, combinedNonce, publicKeys, message, options) {
113
+ function createSession(combinedNonce, publicKeys, message, options) {
114
+ const keys = musig2__namespace.sortKeys([...publicKeys]) ;
114
115
  let tweakBytes;
115
116
  if (options?.taprootTweak !== void 0) {
116
- const { preTweakedKey } = aggregateKeys(
117
- musig2__namespace.sortKeys(publicKeys) );
117
+ const { preTweakedKey } = aggregateKeys(keys, false);
118
118
  tweakBytes = secp256k1_js.schnorr.utils.taggedHash(
119
119
  "TapTweak",
120
120
  preTweakedKey.subarray(1),
121
121
  options.taprootTweak
122
122
  );
123
123
  }
124
- const session = new musig2__namespace.Session(
124
+ return new musig2__namespace.Session(
125
125
  combinedNonce,
126
- musig2__namespace.sortKeys(publicKeys) ,
126
+ keys,
127
127
  message,
128
128
  tweakBytes ? [tweakBytes] : void 0,
129
129
  tweakBytes ? [true] : void 0
130
130
  );
131
+ }
132
+ function sign(secNonce, privateKey, combinedNonce, publicKeys, message, options) {
133
+ const session = createSession(combinedNonce, publicKeys, message, options);
131
134
  const partialSig = session.sign(secNonce, privateKey);
132
135
  return PartialSig.decode(partialSig);
133
136
  }
@@ -185,7 +188,7 @@ var TreeSignerSession = class _TreeSignerSession {
185
188
  noncesByPubkey.set(base.hex.encode(myPublicKey.subarray(1)), myNonce);
186
189
  const tx = this.graph.find(txid);
187
190
  if (!tx) throw new Error(`missing tx for txid ${txid}`);
188
- const cosigners = chunkRNMLFY2V_cjs.getArkPsbtFields(tx.root, 0, chunkRNMLFY2V_cjs.CosignerPublicKey).map(
191
+ const cosigners = chunkOWCPXRGP_cjs.getArkPsbtFields(tx.root, 0, chunkOWCPXRGP_cjs.CosignerPublicKey).map(
189
192
  (c) => base.hex.encode(c.key.subarray(1))
190
193
  // xonly pubkey
191
194
  );
@@ -237,7 +240,7 @@ var TreeSignerSession = class _TreeSignerSession {
237
240
  if (!aggNonce) throw new Error("missing aggregate nonce");
238
241
  const prevoutAmounts = [];
239
242
  const prevoutScripts = [];
240
- const cosigners = chunkRNMLFY2V_cjs.getArkPsbtFields(g.root, 0, chunkRNMLFY2V_cjs.CosignerPublicKey).map((c) => c.key);
243
+ const cosigners = chunkOWCPXRGP_cjs.getArkPsbtFields(g.root, 0, chunkOWCPXRGP_cjs.CosignerPublicKey).map((c) => c.key);
241
244
  const { finalKey } = aggregateKeys(cosigners, true, {
242
245
  taprootTweak: this.scriptRoot
243
246
  });
@@ -416,7 +419,7 @@ var SeedIdentity = class _SeedIdentity {
416
419
  let network;
417
420
  if ("descriptor" in opts && typeof opts.descriptor === "string") {
418
421
  descriptor = opts.descriptor;
419
- network = chunkIEMPH7J6_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
422
+ network = chunkV2TOHHPW_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
420
423
  } else {
421
424
  network = opts.isMainnet ?? true ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
422
425
  descriptor = descriptorsScure.scriptExpressions.trBIP32({
@@ -501,7 +504,7 @@ var SeedIdentity = class _SeedIdentity {
501
504
  * `StaticDescriptorProvider` for legacy single-key wallets.
502
505
  */
503
506
  isOurs(descriptor) {
504
- return chunkIEMPH7J6_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
507
+ return chunkV2TOHHPW_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
505
508
  }
506
509
  /**
507
510
  * Signs each request with the key derived from its descriptor.
@@ -536,9 +539,21 @@ var SeedIdentity = class _SeedIdentity {
536
539
  const key = this.derivePrivateKeyForDescriptor(descriptor);
537
540
  return this.signMessageWithKey(key, message, signatureType);
538
541
  }
542
+ /**
543
+ * BIP-340 sign `messageHash` with the key derived from `descriptor`,
544
+ * aux_rand = 0. Backs {@link DescriptorIdentity.signSchnorrDeterministic},
545
+ * which swap preimage derivation reads through.
546
+ */
547
+ async signSchnorrDeterministicWithDescriptor(descriptor, messageHash) {
548
+ if (!this.isOurs(descriptor)) {
549
+ throw new Error(`Descriptor ${descriptor} does not belong to this identity`);
550
+ }
551
+ const key = this.derivePrivateKeyForDescriptor(descriptor);
552
+ return secp256k1.schnorr.signAsync(messageHash, key, new Uint8Array(32));
553
+ }
539
554
  // ── internal helpers ─────────────────────────────────────────────
540
555
  derivePrivateKeyForDescriptor(descriptor) {
541
- const network = chunkIEMPH7J6_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
556
+ const network = chunkV2TOHHPW_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
542
557
  const expansion = descriptorsScure.expand({ descriptor, network });
543
558
  if (expansion.isRanged) {
544
559
  throw new Error(
@@ -624,7 +639,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
624
639
  */
625
640
  descriptor;
626
641
  constructor(descriptor) {
627
- const network = chunkIEMPH7J6_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
642
+ const network = chunkV2TOHHPW_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
628
643
  let expansion;
629
644
  try {
630
645
  expansion = descriptorsScure.expand({ descriptor, network, index: 0 });
@@ -674,7 +689,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
674
689
  * `StaticDescriptorProvider` for legacy single-key wallets.
675
690
  */
676
691
  isOurs(descriptor) {
677
- return chunkIEMPH7J6_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
692
+ return chunkV2TOHHPW_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
678
693
  }
679
694
  };
680
695
  function serializeSeedOwnedSigningIdentity(identity) {
@@ -822,6 +837,59 @@ function assertValidSerializedIdentity(s) {
822
837
  }
823
838
  }
824
839
 
840
+ // src/identity/descriptorIdentity.ts
841
+ function isHDDeterministicSignCapable(value) {
842
+ return typeof value === "object" && value !== null && typeof value.signSchnorrDeterministicWithDescriptor === "function";
843
+ }
844
+ var DescriptorIdentity = class {
845
+ descriptor;
846
+ signer;
847
+ base;
848
+ constructor({ descriptor, signer, base }) {
849
+ this.descriptor = descriptor;
850
+ this.signer = signer;
851
+ this.base = base;
852
+ }
853
+ async xOnlyPublicKey() {
854
+ return chunkV2TOHHPW_cjs.deriveDescriptorLeafPubKey(this.descriptor);
855
+ }
856
+ async compressedPublicKey() {
857
+ return chunkV2TOHHPW_cjs.deriveDescriptorLeafCompressedPubKey(this.descriptor);
858
+ }
859
+ async sign(tx, inputIndexes) {
860
+ const [signed] = await this.signer.signWithDescriptor([
861
+ { descriptor: this.descriptor, tx, inputIndexes }
862
+ ]);
863
+ if (!signed) {
864
+ throw new Error(`Descriptor signer returned no transaction for ${this.descriptor}`);
865
+ }
866
+ return signed;
867
+ }
868
+ async signMessage(message, signatureType = "schnorr") {
869
+ return this.signer.signMessageWithDescriptor(this.descriptor, message, signatureType);
870
+ }
871
+ /**
872
+ * Delegated: `TreeSignerSession.random()` consults no key material, so the
873
+ * session is index-independent.
874
+ */
875
+ signerSession() {
876
+ return this.base.signerSession();
877
+ }
878
+ /**
879
+ * Throws rather than falling back to the baseline key: a preimage derived
880
+ * from the wrong index is unrecoverable, and callers probe this member
881
+ * through a structural guard that cannot tell the two apart.
882
+ */
883
+ async signSchnorrDeterministic(messageHash) {
884
+ if (!isHDDeterministicSignCapable(this.base)) {
885
+ throw new Error(
886
+ `Identity cannot sign deterministically for descriptor ${this.descriptor}`
887
+ );
888
+ }
889
+ return this.base.signSchnorrDeterministicWithDescriptor(this.descriptor, messageHash);
890
+ }
891
+ };
892
+
825
893
  // src/identity/hdCapableIdentity.ts
826
894
  function isHDCapableIdentity(value) {
827
895
  if (typeof value !== "object" || value === null) return false;
@@ -834,6 +902,13 @@ function isBatchSignable(identity) {
834
902
  return "signMultiple" in identity && typeof identity.signMultiple === "function";
835
903
  }
836
904
 
905
+ // src/wallet/hdWalletCapable.ts
906
+ function isHDWalletCapable(value) {
907
+ if (typeof value !== "object" || value === null) return false;
908
+ const v = value;
909
+ return typeof v.getCurrentSigningDescriptor === "function" && typeof v.getUsedSigningDescriptors === "function" && typeof v.signerForDescriptor === "function";
910
+ }
911
+
837
912
  // src/worker/browser/service-worker-manager.ts
838
913
  var registrations = /* @__PURE__ */ new Map();
839
914
  var handshakes = /* @__PURE__ */ new WeakSet();
@@ -986,14 +1061,14 @@ var RestDelegateProvider = class {
986
1061
  */
987
1062
  async delegate(intent, forfeitTxs, options) {
988
1063
  const url = `${this.url}/v1/delegate`;
989
- const response = await chunkRNMLFY2V_cjs.baseFetch(url, {
1064
+ const response = await chunkOWCPXRGP_cjs.baseFetch(url, {
990
1065
  method: "POST",
991
1066
  headers: {
992
1067
  "Content-Type": "application/json"
993
1068
  },
994
1069
  body: JSON.stringify({
995
1070
  intent: {
996
- message: chunkRNMLFY2V_cjs.Intent.encodeMessage(intent.message),
1071
+ message: chunkOWCPXRGP_cjs.Intent.encodeMessage(intent.message),
997
1072
  proof: intent.proof
998
1073
  },
999
1074
  forfeit_txs: forfeitTxs,
@@ -1013,7 +1088,7 @@ var RestDelegateProvider = class {
1013
1088
  */
1014
1089
  async getDelegateInfo() {
1015
1090
  const url = `${this.url}/v1/delegator/info`;
1016
- const response = await chunkRNMLFY2V_cjs.rateGate.runHttp(url, () => chunkRNMLFY2V_cjs.baseFetch(url));
1091
+ const response = await chunkOWCPXRGP_cjs.rateGate.runHttp(url, () => chunkOWCPXRGP_cjs.baseFetch(url));
1017
1092
  if (!response.ok) {
1018
1093
  const errorText2 = await response.text();
1019
1094
  throw new Error(`Failed to get delegate info: ${errorText2}`);
@@ -1040,7 +1115,7 @@ var ESPLORA_URL = {
1040
1115
  regtest: "http://localhost:3000/api"
1041
1116
  };
1042
1117
  var EsploraProvider = class {
1043
- constructor(baseUrl = ESPLORA_URL[chunkE7HB3GKK_cjs.DEFAULT_NETWORK_NAME], opts) {
1118
+ constructor(baseUrl = ESPLORA_URL[chunkOWCPXRGP_cjs.DEFAULT_NETWORK_NAME], opts) {
1044
1119
  this.baseUrl = baseUrl;
1045
1120
  this.pollingInterval = opts?.pollingInterval ?? 15e3;
1046
1121
  this.forcePolling = opts?.forcePolling ?? false;
@@ -1049,14 +1124,14 @@ var EsploraProvider = class {
1049
1124
  pollingInterval;
1050
1125
  forcePolling;
1051
1126
  async getCoins(address) {
1052
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1127
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1053
1128
  if (!response.ok) {
1054
1129
  throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
1055
1130
  }
1056
1131
  return response.json();
1057
1132
  }
1058
1133
  async getFeeRate() {
1059
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1134
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1060
1135
  if (response.status === 404) {
1061
1136
  return void 0;
1062
1137
  }
@@ -1077,7 +1152,7 @@ var EsploraProvider = class {
1077
1152
  }
1078
1153
  }
1079
1154
  async getTxOutspends(txid) {
1080
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1155
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1081
1156
  if (!response.ok) {
1082
1157
  const error = await response.text();
1083
1158
  throw new Error(`Failed to get transaction outspends: ${error}`);
@@ -1085,7 +1160,7 @@ var EsploraProvider = class {
1085
1160
  return response.json();
1086
1161
  }
1087
1162
  async getTransactions(address) {
1088
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1163
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1089
1164
  if (!response.ok) {
1090
1165
  const error = await response.text();
1091
1166
  throw new Error(`Failed to get transactions: ${error}`);
@@ -1093,7 +1168,7 @@ var EsploraProvider = class {
1093
1168
  return response.json();
1094
1169
  }
1095
1170
  async getTxStatus(txid) {
1096
- const txresponse = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1171
+ const txresponse = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1097
1172
  if (!txresponse.ok) {
1098
1173
  throw new Error(txresponse.statusText);
1099
1174
  }
@@ -1101,7 +1176,7 @@ var EsploraProvider = class {
1101
1176
  if (!tx.status.confirmed) {
1102
1177
  return { confirmed: false };
1103
1178
  }
1104
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1179
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1105
1180
  if (!response.ok) {
1106
1181
  throw new Error(`Failed to get transaction status: ${response.statusText}`);
1107
1182
  }
@@ -1185,7 +1260,7 @@ var EsploraProvider = class {
1185
1260
  return stopFunc;
1186
1261
  }
1187
1262
  async getChainTip() {
1188
- const tipBlocks = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/blocks`);
1263
+ const tipBlocks = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/blocks`);
1189
1264
  if (!tipBlocks.ok) {
1190
1265
  throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
1191
1266
  }
@@ -1204,7 +1279,7 @@ var EsploraProvider = class {
1204
1279
  };
1205
1280
  }
1206
1281
  async broadcastPackage(parent, child) {
1207
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1282
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1208
1283
  method: "POST",
1209
1284
  headers: {
1210
1285
  "Content-Type": "application/json"
@@ -1218,7 +1293,7 @@ var EsploraProvider = class {
1218
1293
  return response.json();
1219
1294
  }
1220
1295
  async broadcastTx(tx) {
1221
- const response = await chunkRNMLFY2V_cjs.baseFetch(`${this.baseUrl}/tx`, {
1296
+ const response = await chunkOWCPXRGP_cjs.baseFetch(`${this.baseUrl}/tx`, {
1222
1297
  method: "POST",
1223
1298
  headers: {
1224
1299
  "Content-Type": "text/plain"
@@ -1380,7 +1455,7 @@ function findP2AOutput(tx) {
1380
1455
  var CHILD_DUST_AMOUNT = 546;
1381
1456
  function buildAnchorChild(params) {
1382
1457
  const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
1383
- const child = new chunkRNMLFY2V_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
1458
+ const child = new chunkOWCPXRGP_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
1384
1459
  child.addInput(findP2AOutput(parent));
1385
1460
  const estimator = TxWeightEstimator.create().addP2AInput();
1386
1461
  for (const _ of fundingCoins) {
@@ -1428,7 +1503,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
1428
1503
  );
1429
1504
  }
1430
1505
  function buildForfeitTxWithOutput(inputs, output, txLocktime) {
1431
- const tx = new chunkRNMLFY2V_cjs.Transaction({
1506
+ const tx = new chunkOWCPXRGP_cjs.Transaction({
1432
1507
  version: 3,
1433
1508
  lockTime: txLocktime
1434
1509
  });
@@ -1504,7 +1579,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
1504
1579
  if (previousScriptKey.length !== 32) {
1505
1580
  throw new Error(`parent output ${childIndex} has invalid script`);
1506
1581
  }
1507
- const cosigners = chunkRNMLFY2V_cjs.getArkPsbtFields(child.root, 0, chunkRNMLFY2V_cjs.CosignerPublicKey);
1582
+ const cosigners = chunkOWCPXRGP_cjs.getArkPsbtFields(child.root, 0, chunkOWCPXRGP_cjs.CosignerPublicKey);
1508
1583
  if (cosigners.length === 0) {
1509
1584
  throw ErrMissingCosignersPublicKeys;
1510
1585
  }
@@ -1562,7 +1637,7 @@ var EmulatorPacket = class _EmulatorPacket {
1562
1637
  return new _EmulatorPacket(entries);
1563
1638
  }
1564
1639
  static fromBytes(data) {
1565
- const reader = new chunkRNMLFY2V_cjs.BufferReader(data);
1640
+ const reader = new chunkG7DOBFQN_cjs.BufferReader(data);
1566
1641
  const entryCount = reader.readCompactSize();
1567
1642
  const entries = [];
1568
1643
  for (let i = 0; i < entryCount; i++) {
@@ -1580,7 +1655,7 @@ var EmulatorPacket = class _EmulatorPacket {
1580
1655
  return _EmulatorPacket.PACKET_TYPE;
1581
1656
  }
1582
1657
  serialize() {
1583
- const writer = new chunkRNMLFY2V_cjs.BufferWriter();
1658
+ const writer = new chunkG7DOBFQN_cjs.BufferWriter();
1584
1659
  writer.writeCompactSize(this.entries.length);
1585
1660
  for (const entry of this.entries) {
1586
1661
  writer.writeUint16LE(entry.vin);
@@ -1667,7 +1742,7 @@ var Extension = class _Extension {
1667
1742
  `expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
1668
1743
  );
1669
1744
  }
1670
- const reader = new chunkRNMLFY2V_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
1745
+ const reader = new chunkG7DOBFQN_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
1671
1746
  const packets = [];
1672
1747
  while (reader.remaining() > 0) {
1673
1748
  const packetType = reader.readByte();
@@ -1741,7 +1816,7 @@ var Extension = class _Extension {
1741
1816
  */
1742
1817
  getAssetPacket() {
1743
1818
  for (const p of this.packets) {
1744
- if (p instanceof chunkRNMLFY2V_cjs.Packet) {
1819
+ if (p instanceof chunkG7DOBFQN_cjs.Packet) {
1745
1820
  return p;
1746
1821
  }
1747
1822
  }
@@ -1779,8 +1854,8 @@ var Extension = class _Extension {
1779
1854
  };
1780
1855
  function parsePacket(packetType, data) {
1781
1856
  switch (packetType) {
1782
- case chunkRNMLFY2V_cjs.Packet.PACKET_TYPE:
1783
- return chunkRNMLFY2V_cjs.Packet.fromBytes(data);
1857
+ case chunkG7DOBFQN_cjs.Packet.PACKET_TYPE:
1858
+ return chunkG7DOBFQN_cjs.Packet.fromBytes(data);
1784
1859
  case EmulatorPacket.PACKET_TYPE:
1785
1860
  return EmulatorPacket.fromBytes(data);
1786
1861
  default:
@@ -1827,21 +1902,35 @@ function buildOpReturnScript(data) {
1827
1902
  }
1828
1903
  return script;
1829
1904
  }
1830
- var ErrOffchainOutputNotFound = (address) => new Error(`offchain send output not found: ${address}`);
1831
- var ErrInvalidAssetOutputAmount = (got, want, assetId) => new Error(`invalid asset output amount for ${assetId}: got ${got}, want ${want}`);
1832
- var ErrAssetGroupNotFound = (assetId) => new Error(`asset group not found in batch leaf: ${assetId}`);
1833
- var ErrAssetOutputNotFound = (assetId, outputIndex) => new Error(`asset output not found in asset group ${assetId} at index ${outputIndex}`);
1905
+ var ErrOffchainOutputNotFound = (address) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(`offchain send output not found: ${address}`);
1906
+ var ErrInvalidAssetOutputAmount = (got, want, assetId) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
1907
+ `invalid asset output amount for ${assetId}: got ${got}, want ${want}`
1908
+ );
1909
+ var ErrAssetGroupNotFound = (assetId) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(`asset group not found in batch leaf: ${assetId}`);
1910
+ var ErrAssetOutputNotFound = (assetId, outputIndex) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
1911
+ `asset output not found in asset group ${assetId} at index ${outputIndex}`
1912
+ );
1913
+ var ErrOnchainOutputNotFound = (address) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(`onchain output not found: ${address}`);
1914
+ var ErrUnvalidatedOffchainOutput = (address) => new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
1915
+ `offchain output ${address} cannot be validated: virtual output tree signing did not run`
1916
+ );
1834
1917
  var ErrInvalidOnchainOutputAmount = (address) => new Error(`invalid onchain output amount: ${address}`);
1835
1918
  var ErrInvalidOnchainOutputAssets = (address) => new Error(`onchain output ${address} cannot have assets`);
1836
- var ErrOnchainOutputNotFound = (address) => new Error(`onchain output not found: ${address}`);
1837
1919
  var ErrInvalidOffchainOutputAmount = (address) => new Error(`invalid offchain output ${address}, missing amount`);
1920
+ function assertFinalCommitmentMatchesValidated(finalCommitmentTx, validatedCommitmentTxid, context) {
1921
+ if (!validatedCommitmentTxid) return;
1922
+ if (finalCommitmentTx.id === validatedCommitmentTxid) return;
1923
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
1924
+ `${context}: finalization commitment tx ${finalCommitmentTx.id} differs from the validated commitment tx ${validatedCommitmentTxid}`
1925
+ );
1926
+ }
1838
1927
  function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, network) {
1839
1928
  const usedOutputs = /* @__PURE__ */ new Set();
1840
1929
  const usedOnchainOutputs = /* @__PURE__ */ new Set();
1841
1930
  for (const recipient of recipients) {
1842
1931
  let arkAddress;
1843
1932
  try {
1844
- arkAddress = chunkE7HB3GKK_cjs.ArkAddress.decode(recipient.address);
1933
+ arkAddress = chunkOWCPXRGP_cjs.ArkAddress.decode(recipient.address);
1845
1934
  } catch {
1846
1935
  validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
1847
1936
  continue;
@@ -1849,6 +1938,18 @@ function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, netwo
1849
1938
  validateOffchainRecipient(vtxoTreeLeaves, arkAddress, recipient, usedOutputs);
1850
1939
  }
1851
1940
  }
1941
+ function validateBatchRecipientsWithoutTree(commitmentTx, recipients, network) {
1942
+ const usedOnchainOutputs = /* @__PURE__ */ new Set();
1943
+ for (const recipient of recipients) {
1944
+ try {
1945
+ chunkOWCPXRGP_cjs.ArkAddress.decode(recipient.address);
1946
+ } catch {
1947
+ validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
1948
+ continue;
1949
+ }
1950
+ throw ErrUnvalidatedOffchainOutput(recipient.address);
1951
+ }
1952
+ }
1852
1953
  function validateOnchainRecipient(commitmentTx, recipient, network, usedOutputs) {
1853
1954
  const addr = btcSigner.Address(network).decode(recipient.address);
1854
1955
  const expectedPkScript = btcSigner.OutScript.encode(addr);
@@ -1941,8 +2042,6 @@ function validateAssetGroupOutput(packet, outputIndex, assetId, expectedAmount)
1941
2042
  throw ErrInvalidAssetOutputAmount(assetOutput.amount, expectedAmount, assetId);
1942
2043
  }
1943
2044
  }
1944
-
1945
- // src/wallet/activity.ts
1946
2045
  async function buildActivities(txs, resolvers) {
1947
2046
  const preparedResolvers = (await Promise.all(
1948
2047
  resolvers.map(async (r) => {
@@ -2052,9 +2151,49 @@ function boardingResolver() {
2052
2151
  }
2053
2152
  };
2054
2153
  }
2154
+ function collabExitResolver() {
2155
+ return {
2156
+ id: "collab-exit",
2157
+ resolve(tx) {
2158
+ if (tx.tag !== "exit" || !tx.key.commitmentTxid) return void 0;
2159
+ return [
2160
+ {
2161
+ groupId: `exit:${tx.key.commitmentTxid}`,
2162
+ label: "Collaborative exit",
2163
+ kind: "exit"
2164
+ }
2165
+ ];
2166
+ }
2167
+ };
2168
+ }
2169
+ function assetMintResolver() {
2170
+ return {
2171
+ id: "asset-mint",
2172
+ resolve(tx) {
2173
+ if (!tx.assets?.length || !tx.key.arkTxid) return void 0;
2174
+ const minted = tx.assets.filter((a) => {
2175
+ try {
2176
+ return base.hex.encode(chunkG7DOBFQN_cjs.AssetId.fromString(a.assetId).txid) === tx.key.arkTxid;
2177
+ } catch {
2178
+ return false;
2179
+ }
2180
+ });
2181
+ if (minted.length === 0) return void 0;
2182
+ const received = tx.type === "RECEIVED" /* TxReceived */;
2183
+ return minted.map((a) => ({
2184
+ groupId: `mint:${a.assetId}`,
2185
+ label: received ? "Asset receive" : "Asset mint",
2186
+ kind: received ? "asset-receive" : "asset-mint",
2187
+ metadata: { assetId: a.assetId, amount: a.amount.toString() }
2188
+ }));
2189
+ }
2190
+ };
2191
+ }
2055
2192
  function createDefaultActivityRegistry() {
2056
2193
  const registry = new ActivityRegistry();
2057
2194
  registry.use(boardingResolver());
2195
+ registry.use(collabExitResolver());
2196
+ registry.use(assetMintResolver());
2058
2197
  return registry;
2059
2198
  }
2060
2199
 
@@ -2077,7 +2216,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2077
2216
  const existing = inputsByAssetId.get(asset.assetId);
2078
2217
  inputsByAssetId.set(asset.assetId, [
2079
2218
  ...existing ?? [],
2080
- chunkRNMLFY2V_cjs.AssetInput.create(inputIndex, asset.amount)
2219
+ chunkG7DOBFQN_cjs.AssetInput.create(inputIndex, asset.amount)
2081
2220
  ]);
2082
2221
  }
2083
2222
  }
@@ -2089,7 +2228,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2089
2228
  const existing = outputsByAssetId.get(asset.assetId);
2090
2229
  outputsByAssetId.set(asset.assetId, [
2091
2230
  ...existing ?? [],
2092
- chunkRNMLFY2V_cjs.AssetOutput.create(outputIndex, asset.amount)
2231
+ chunkG7DOBFQN_cjs.AssetOutput.create(outputIndex, asset.amount)
2093
2232
  ]);
2094
2233
  }
2095
2234
  }
@@ -2100,7 +2239,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2100
2239
  const existing = outputsByAssetId.get(asset.assetId);
2101
2240
  outputsByAssetId.set(asset.assetId, [
2102
2241
  ...existing ?? [],
2103
- chunkRNMLFY2V_cjs.AssetOutput.create(outputIndex, asset.amount)
2242
+ chunkG7DOBFQN_cjs.AssetOutput.create(outputIndex, asset.amount)
2104
2243
  ]);
2105
2244
  }
2106
2245
  }
@@ -2109,11 +2248,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2109
2248
  for (const assetIdStr of allAssetIds) {
2110
2249
  const inputs = inputsByAssetId.get(assetIdStr);
2111
2250
  const outputs = outputsByAssetId.get(assetIdStr);
2112
- const assetId = chunkRNMLFY2V_cjs.AssetId.fromString(assetIdStr);
2113
- const group = chunkRNMLFY2V_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
2251
+ const assetId = chunkG7DOBFQN_cjs.AssetId.fromString(assetIdStr);
2252
+ const group = chunkG7DOBFQN_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
2114
2253
  groups.push(group);
2115
2254
  }
2116
- return chunkRNMLFY2V_cjs.Packet.create(groups);
2255
+ return chunkG7DOBFQN_cjs.Packet.create(groups);
2117
2256
  }
2118
2257
  function selectCoinsWithAsset(coins, assetId, requiredAmount) {
2119
2258
  const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
@@ -2218,8 +2357,8 @@ function buildOffchainTx(inputs, outputs, serverUnrollScript) {
2218
2357
  function buildVirtualTx(inputs, outputs) {
2219
2358
  let lockTime = 0n;
2220
2359
  for (const input of inputs) {
2221
- const tapscript = chunkE7HB3GKK_cjs.decodeTapscript(chunkE7HB3GKK_cjs.scriptFromTapLeafScript(input.tapLeafScript));
2222
- if (chunkE7HB3GKK_cjs.CLTVMultisigTapscript.is(tapscript)) {
2360
+ const tapscript = chunkOWCPXRGP_cjs.decodeTapscript(chunkOWCPXRGP_cjs.scriptFromTapLeafScript(input.tapLeafScript));
2361
+ if (chunkOWCPXRGP_cjs.CLTVMultisigTapscript.is(tapscript)) {
2223
2362
  if (lockTime !== 0n) {
2224
2363
  if (isSeconds(lockTime) !== isSeconds(tapscript.params.absoluteTimelock)) {
2225
2364
  throw new Error("cannot mix seconds and blocks locktime");
@@ -2230,7 +2369,7 @@ function buildVirtualTx(inputs, outputs) {
2230
2369
  }
2231
2370
  }
2232
2371
  }
2233
- const tx = new chunkRNMLFY2V_cjs.Transaction({
2372
+ const tx = new chunkOWCPXRGP_cjs.Transaction({
2234
2373
  version: 3,
2235
2374
  lockTime: Number(lockTime)
2236
2375
  });
@@ -2240,12 +2379,12 @@ function buildVirtualTx(inputs, outputs) {
2240
2379
  index: input.vout,
2241
2380
  sequence: lockTime ? btcSigner.DEFAULT_SEQUENCE - 1 : void 0,
2242
2381
  witnessUtxo: {
2243
- script: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript,
2382
+ script: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript,
2244
2383
  amount: BigInt(input.value)
2245
2384
  },
2246
2385
  tapLeafScript: [input.tapLeafScript]
2247
2386
  });
2248
- chunkRNMLFY2V_cjs.setArkPsbtField(tx, i, chunkRNMLFY2V_cjs.VtxoTaprootTree, input.tapTree);
2387
+ chunkOWCPXRGP_cjs.setArkPsbtField(tx, i, chunkOWCPXRGP_cjs.VtxoTaprootTree, input.tapTree);
2249
2388
  }
2250
2389
  for (const output of outputs) {
2251
2390
  tx.addOutput(output);
@@ -2254,8 +2393,8 @@ function buildVirtualTx(inputs, outputs) {
2254
2393
  return tx;
2255
2394
  }
2256
2395
  function buildCheckpointTx(vtxo, serverUnrollScript) {
2257
- const collaborativeClosure = chunkE7HB3GKK_cjs.decodeTapscript(chunkE7HB3GKK_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
2258
- const checkpointVtxoScript = new chunkE7HB3GKK_cjs.VtxoScript([
2396
+ const collaborativeClosure = chunkOWCPXRGP_cjs.decodeTapscript(chunkOWCPXRGP_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
2397
+ const checkpointVtxoScript = new chunkOWCPXRGP_cjs.VtxoScript([
2259
2398
  serverUnrollScript.script,
2260
2399
  collaborativeClosure.script
2261
2400
  ]);
@@ -2301,7 +2440,7 @@ function hasBoardingTxExpired(coin, boardingTimelock, chainTipHeight) {
2301
2440
  function formatSighash(type) {
2302
2441
  return `0x${type.toString(16).padStart(2, "0")}`;
2303
2442
  }
2304
- function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubkeys = [], allowedSighashTypes = [btcSigner.SigHash.DEFAULT]) {
2443
+ function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubkeys = [], allowedSighashTypes = [btcSigner.SigHash.DEFAULT], expectedLeafHash) {
2305
2444
  const input = tx.getInput(inputIndex);
2306
2445
  const prevoutScripts = [];
2307
2446
  const prevoutAmounts = [];
@@ -2316,12 +2455,21 @@ function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubke
2316
2455
  if (!input.tapScriptSig || input.tapScriptSig.length === 0) {
2317
2456
  throw new Error(`Input ${inputIndex} is missing tapScriptSig`);
2318
2457
  }
2458
+ const expectedLeafHashHex = expectedLeafHash ? base.hex.encode(expectedLeafHash) : void 0;
2319
2459
  for (const [tapScriptSigData, signature] of input.tapScriptSig) {
2320
2460
  const pubKey = tapScriptSigData.pubKey;
2321
2461
  const pubKeyHex = base.hex.encode(pubKey);
2322
2462
  if (excludePubkeys.includes(pubKeyHex)) {
2323
2463
  continue;
2324
2464
  }
2465
+ if (expectedLeafHashHex !== void 0) {
2466
+ const signedLeafHex = base.hex.encode(tapScriptSigData.leafHash);
2467
+ if (signedLeafHex !== expectedLeafHashHex) {
2468
+ throw new Error(
2469
+ `Input ${inputIndex}: signature from ${pubKeyHex} commits to leaf ${signedLeafHex}, expected ${expectedLeafHashHex}`
2470
+ );
2471
+ }
2472
+ }
2325
2473
  const sighashType = signature.length === 65 ? signature[64] : btcSigner.SigHash.DEFAULT;
2326
2474
  const sig = signature.subarray(0, 64);
2327
2475
  if (!allowedSighashTypes.includes(sighashType)) {
@@ -2399,12 +2547,76 @@ function combineTapscriptSigs(signedTx, originalTx) {
2399
2547
  }
2400
2548
  function isValidArkAddress(address) {
2401
2549
  try {
2402
- chunkE7HB3GKK_cjs.ArkAddress.decode(address);
2550
+ chunkOWCPXRGP_cjs.ArkAddress.decode(address);
2403
2551
  return true;
2404
2552
  } catch (e) {
2405
2553
  return false;
2406
2554
  }
2407
2555
  }
2556
+ function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, context) {
2557
+ if (serverCheckpointTxs.length !== expectedCheckpoints.length) {
2558
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2559
+ `${context} returned ${serverCheckpointTxs.length} checkpoints, expected ${expectedCheckpoints.length}`
2560
+ );
2561
+ }
2562
+ const byTxid = new Map(expectedCheckpoints.map((c) => [c.id, c]));
2563
+ return serverCheckpointTxs.map((encoded, index) => {
2564
+ const server = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(encoded));
2565
+ const local = byTxid.get(server.id);
2566
+ if (!local) {
2567
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2568
+ `${context} checkpoint ${index} txid ${server.id} does not match any submitted checkpoint`
2569
+ );
2570
+ }
2571
+ byTxid.delete(server.id);
2572
+ return { server, local };
2573
+ });
2574
+ }
2575
+ function assertSubmittedArkTxid(response, signedArkTx, context) {
2576
+ if (response.arkTxid !== signedArkTx.id) {
2577
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2578
+ `${context} returned ark txid ${response.arkTxid}, expected ${signedArkTx.id}`
2579
+ );
2580
+ }
2581
+ if (response.finalArkTx === void 0) return;
2582
+ const finalTxid = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx)).id;
2583
+ if (finalTxid !== signedArkTx.id) {
2584
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2585
+ `${context} returned final ark tx ${finalTxid}, expected ${signedArkTx.id}`
2586
+ );
2587
+ }
2588
+ }
2589
+ function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, context) {
2590
+ const byOutpoint = new Map(inputs.map((input) => [`${input.txid}:${input.vout}`, input]));
2591
+ for (const [index, checkpoint] of checkpoints.entries()) {
2592
+ if (checkpoint.inputsLength !== 1) {
2593
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2594
+ `${context}: checkpoint ${index} spends ${checkpoint.inputsLength} inputs, expected 1`
2595
+ );
2596
+ }
2597
+ const spent = checkpoint.getInput(0);
2598
+ if (!spent.txid || spent.index === void 0) {
2599
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2600
+ `${context}: checkpoint ${index} has no input outpoint`
2601
+ );
2602
+ }
2603
+ const outpoint = `${base.hex.encode(spent.txid)}:${spent.index}`;
2604
+ const input = byOutpoint.get(outpoint);
2605
+ if (!input) {
2606
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2607
+ `${context}: checkpoint ${index} spends ${outpoint}, which is not one of the requested virtual outputs`
2608
+ );
2609
+ }
2610
+ const rebuilt = unrollCandidates.some(
2611
+ (unroll) => buildCheckpointTx(input, unroll).tx.id === checkpoint.id
2612
+ );
2613
+ if (!rebuilt) {
2614
+ throw new chunkOWCPXRGP_cjs.ServerResponseMismatchError(
2615
+ `${context}: checkpoint ${index} txid ${checkpoint.id} differs from the checkpoint built locally for ${outpoint}`
2616
+ );
2617
+ }
2618
+ }
2619
+ }
2408
2620
  async function submitOffchainTx(provider, offchainTx, signer, hooks) {
2409
2621
  const { arkTx: signedArkTx, userSignedCheckpoints } = await signer.signArkTx(
2410
2622
  offchainTx.arkTx,
@@ -2416,27 +2628,26 @@ async function submitOffchainTx(provider, offchainTx, signer, hooks) {
2416
2628
  );
2417
2629
  }
2418
2630
  await hooks?.beforeSubmit?.();
2419
- const { arkTxid, signedCheckpointTxs } = await provider.submitTx(
2631
+ const response = await provider.submitTx(
2420
2632
  base.base64.encode(signedArkTx.toPSBT()),
2421
2633
  offchainTx.checkpoints.map((c) => base.base64.encode(c.toPSBT()))
2422
2634
  );
2423
- if (signedCheckpointTxs.length !== offchainTx.checkpoints.length) {
2424
- throw new Error(
2425
- `submitTx returned ${signedCheckpointTxs.length} checkpoints, expected ${offchainTx.checkpoints.length}`
2426
- );
2427
- }
2635
+ assertSubmittedArkTxid(response, signedArkTx, "submitTx");
2636
+ const { arkTxid, signedCheckpointTxs } = response;
2637
+ const matched = matchServerCheckpoints(signedCheckpointTxs, offchainTx.checkpoints, "submitTx");
2428
2638
  let finalCheckpoints;
2429
2639
  if (userSignedCheckpoints) {
2430
- finalCheckpoints = signedCheckpointTxs.map((c, i) => {
2431
- const serverSigned = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(c));
2432
- combineTapscriptSigs(userSignedCheckpoints[i], serverSigned);
2433
- return base.base64.encode(serverSigned.toPSBT());
2640
+ const userByTxid = new Map(
2641
+ userSignedCheckpoints.map((c, i) => [offchainTx.checkpoints[i].id, c])
2642
+ );
2643
+ finalCheckpoints = matched.map(({ server, local }) => {
2644
+ combineTapscriptSigs(userByTxid.get(local.id), server);
2645
+ return base.base64.encode(server.toPSBT());
2434
2646
  });
2435
2647
  } else {
2436
2648
  finalCheckpoints = await Promise.all(
2437
- signedCheckpointTxs.map(async (c) => {
2438
- const tx = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(c));
2439
- const signed = await signer.signCheckpoint(tx);
2649
+ matched.map(async ({ server }) => {
2650
+ const signed = await signer.signCheckpoint(server);
2440
2651
  return base.base64.encode(signed.toPSBT());
2441
2652
  })
2442
2653
  );
@@ -2634,7 +2845,7 @@ function extendCoinWithTapscript(boardingTapscript, utxo) {
2634
2845
  };
2635
2846
  }
2636
2847
  function deriveContractTapscripts(contract) {
2637
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
2848
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
2638
2849
  if (!handler) {
2639
2850
  throw new Error(`No handler for contract type '${contract.type}'`);
2640
2851
  }
@@ -2703,12 +2914,20 @@ function getRandomId() {
2703
2914
  const randomValue = crypto.getRandomValues(new Uint8Array(16));
2704
2915
  return base.hex.encode(randomValue);
2705
2916
  }
2917
+ function isValidArkAddress2(address) {
2918
+ try {
2919
+ chunkOWCPXRGP_cjs.ArkAddress.decode(address);
2920
+ return true;
2921
+ } catch (e) {
2922
+ return false;
2923
+ }
2924
+ }
2706
2925
  function validateRecipients(recipients, dustAmount) {
2707
2926
  const validatedRecipients = [];
2708
2927
  for (const recipient of recipients) {
2709
2928
  let address;
2710
2929
  try {
2711
- address = chunkE7HB3GKK_cjs.ArkAddress.decode(recipient.address);
2930
+ address = chunkOWCPXRGP_cjs.ArkAddress.decode(recipient.address);
2712
2931
  } catch (e) {
2713
2932
  throw new Error(`Invalid Arkade address: ${recipient.address}`);
2714
2933
  }
@@ -2736,7 +2955,7 @@ function selectPendingRecoveryOutpoints(contractsWithVtxos, signerSet, nowSecond
2736
2955
  continue;
2737
2956
  }
2738
2957
  for (const v of vtxos) {
2739
- if (!chunkE7HB3GKK_cjs.hasTerminalSpend(v) && !v.isSwept) out.add(`${v.txid}:${v.vout}`);
2958
+ if (!chunkOWCPXRGP_cjs.hasTerminalSpend(v) && !v.isSwept) out.add(`${v.txid}:${v.vout}`);
2740
2959
  }
2741
2960
  }
2742
2961
  return out;
@@ -2769,10 +2988,10 @@ function byValueDescending(vtxos) {
2769
2988
  return [...vtxos].sort((a, b) => b.value - a.value);
2770
2989
  }
2771
2990
  async function fetchTimeHeight(wallet) {
2772
- return chunkE7HB3GKK_cjs.resolveTimeHeight(wallet.onchainProvider);
2991
+ return chunkOWCPXRGP_cjs.resolveTimeHeight(wallet.onchainProvider);
2773
2992
  }
2774
2993
  function canMigrateBySend(vtxo, now) {
2775
- if (!chunkE7HB3GKK_cjs.canSpendOffchain(vtxo, now)) return false;
2994
+ if (!chunkOWCPXRGP_cjs.canSpendOffchain(vtxo, now)) return false;
2776
2995
  return vtxo.expiresAt !== void 0 || vtxo.expiresAtHeight !== void 0;
2777
2996
  }
2778
2997
  function byExpiryAscending(vtxos, now) {
@@ -2780,7 +2999,7 @@ function byExpiryAscending(vtxos, now) {
2780
2999
  if (vtxo.isSwept) return -Infinity;
2781
3000
  if (vtxo.expiresAt !== void 0) return vtxo.expiresAt.getTime();
2782
3001
  if (vtxo.expiresAtHeight !== void 0) {
2783
- return chunkE7HB3GKK_cjs.isPastExpiry(vtxo, now) ? -Infinity : Infinity;
3002
+ return chunkOWCPXRGP_cjs.isPastExpiry(vtxo, now) ? -Infinity : Infinity;
2784
3003
  }
2785
3004
  return Infinity;
2786
3005
  };
@@ -2817,10 +3036,10 @@ var DEFAULT_SETTLEMENT_CONFIG = {
2817
3036
  };
2818
3037
  function getRecoverableVtxos(vtxos, dustAmount, now) {
2819
3038
  return vtxos.filter((vtxo) => {
2820
- if (chunkE7HB3GKK_cjs.canRecoverOnchain(vtxo, now)) {
3039
+ if (chunkOWCPXRGP_cjs.canRecoverOnchain(vtxo, now)) {
2821
3040
  return true;
2822
3041
  }
2823
- if (chunkE7HB3GKK_cjs.canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
3042
+ if (chunkOWCPXRGP_cjs.canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
2824
3043
  return true;
2825
3044
  }
2826
3045
  return false;
@@ -2851,7 +3070,7 @@ function getRecoverableWithSubdust(vtxos, dustAmount, now) {
2851
3070
  }
2852
3071
  function isVtxoExpiringSoon(vtxo, thresholdMs) {
2853
3072
  const realThresholdMs = thresholdMs <= 100 ? DEFAULT_THRESHOLD_MS : thresholdMs;
2854
- const expiresAt = chunkE7HB3GKK_cjs.normalizeVtxo(vtxo).expiresAt;
3073
+ const expiresAt = chunkOWCPXRGP_cjs.normalizeVtxo(vtxo).expiresAt;
2855
3074
  if (expiresAt === void 0) return false;
2856
3075
  const now = Date.now();
2857
3076
  const batchExpiry = expiresAt.getTime();
@@ -2860,7 +3079,7 @@ function isVtxoExpiringSoon(vtxo, thresholdMs) {
2860
3079
  }
2861
3080
  function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount, now) {
2862
3081
  return vtxos.filter(
2863
- (vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) || chunkE7HB3GKK_cjs.canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount)
3082
+ (vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) || chunkOWCPXRGP_cjs.canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount)
2864
3083
  );
2865
3084
  }
2866
3085
  function isMigrationCapable(wallet) {
@@ -3342,11 +3561,11 @@ var VtxoManager = class _VtxoManager {
3342
3561
  `Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
3343
3562
  );
3344
3563
  }
3345
- const tx = new chunkRNMLFY2V_cjs.Transaction();
3564
+ const tx = new chunkOWCPXRGP_cjs.Transaction();
3346
3565
  for (const utxo of expiredUtxos) {
3347
- const utxoScript = chunkE7HB3GKK_cjs.VtxoScript.decode(utxo.tapTree);
3566
+ const utxoScript = chunkOWCPXRGP_cjs.VtxoScript.decode(utxo.tapTree);
3348
3567
  const utxoExitLeaf = utxoScript.leaves.find(
3349
- (leaf) => chunkE7HB3GKK_cjs.CSVMultisigTapscript.isScriptValid(chunkE7HB3GKK_cjs.scriptFromTapLeafScript(leaf)) === true
3568
+ (leaf) => chunkOWCPXRGP_cjs.CSVMultisigTapscript.isScriptValid(chunkOWCPXRGP_cjs.scriptFromTapLeafScript(leaf)) === true
3350
3569
  );
3351
3570
  if (!utxoExitLeaf) {
3352
3571
  throw new Error(
@@ -3361,7 +3580,7 @@ var VtxoManager = class _VtxoManager {
3361
3580
  amount: BigInt(utxo.value)
3362
3581
  },
3363
3582
  tapLeafScript: [utxoExitLeaf],
3364
- sequence: chunkE7HB3GKK_cjs.getSequence(utxoExitLeaf)
3583
+ sequence: chunkOWCPXRGP_cjs.getSequence(utxoExitLeaf)
3365
3584
  });
3366
3585
  }
3367
3586
  tx.addOutputAddress(boardingAddress, outputAmount, this.getNetwork());
@@ -3595,8 +3814,8 @@ var VtxoManager = class _VtxoManager {
3595
3814
  if (!serverPubKey) continue;
3596
3815
  const cls = classifyAgainstSignerSet(serverPubKey, signerSet, nowSeconds);
3597
3816
  if (cls.status === "CURRENT") continue;
3598
- const recoverable = vtxos.filter((v) => v.isSwept && !chunkE7HB3GKK_cjs.hasTerminalSpend(v));
3599
- const spendable = vtxos.filter((v) => !chunkE7HB3GKK_cjs.hasTerminalSpend(v) && !v.isSwept);
3817
+ const recoverable = vtxos.filter((v) => v.isSwept && !chunkOWCPXRGP_cjs.hasTerminalSpend(v));
3818
+ const spendable = vtxos.filter((v) => !chunkOWCPXRGP_cjs.hasTerminalSpend(v) && !v.isSwept);
3600
3819
  const value = spendable.reduce((sum, v) => sum + v.value, 0);
3601
3820
  let recoverableCount = 0;
3602
3821
  let recoverableValue = 0;
@@ -3609,7 +3828,7 @@ var VtxoManager = class _VtxoManager {
3609
3828
  awaitingSweepCount = spendable.length;
3610
3829
  awaitingSweepValue = value;
3611
3830
  for (const v of spendable) {
3612
- const exp = chunkE7HB3GKK_cjs.toBatchExpiry(v);
3831
+ const exp = chunkOWCPXRGP_cjs.toBatchExpiry(v);
3613
3832
  if (exp !== void 0 && (nextSweepEta === void 0 || exp < nextSweepEta)) {
3614
3833
  nextSweepEta = exp;
3615
3834
  }
@@ -3870,7 +4089,7 @@ var VtxoManager = class _VtxoManager {
3870
4089
  /** Decodes the boarding tapscript exit path to extract the CSV timelock. */
3871
4090
  getBoardingTimelock() {
3872
4091
  const wallet = this.getSweepWallet();
3873
- const exitScript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(
4092
+ const exitScript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(
3874
4093
  base.hex.decode(wallet.boardingTapscript.exitScript)
3875
4094
  );
3876
4095
  return exitScript.params.timelock;
@@ -4001,8 +4220,8 @@ var VtxoManager = class _VtxoManager {
4001
4220
  * or doesn't carry the metadata.
4002
4221
  */
4003
4222
  extractSpentOutpoint(error) {
4004
- const ark = chunkRNMLFY2V_cjs.maybeArkError(error);
4005
- if (!chunkRNMLFY2V_cjs.isArkError(ark, chunkRNMLFY2V_cjs.ArkErrorName.VTXO_ALREADY_SPENT)) return void 0;
4223
+ const ark = chunkOWCPXRGP_cjs.maybeArkError(error);
4224
+ if (!chunkOWCPXRGP_cjs.isArkError(ark, chunkOWCPXRGP_cjs.ArkErrorName.VTXO_ALREADY_SPENT)) return void 0;
4006
4225
  const raw = ark.metadata?.vtxo_outpoint;
4007
4226
  if (typeof raw !== "string") return void 0;
4008
4227
  const [txid, voutStr] = raw.split(":");
@@ -4192,7 +4411,7 @@ var VtxoManager = class _VtxoManager {
4192
4411
  if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
4193
4412
  break;
4194
4413
  }
4195
- const inputFee = estimator.evalOffchainInput(chunkE7HB3GKK_cjs.toOffchainInputFeeParams(v));
4414
+ const inputFee = estimator.evalOffchainInput(chunkOWCPXRGP_cjs.toOffchainInputFeeParams(v));
4196
4415
  if (inputFee.satoshis >= v.value) {
4197
4416
  continue;
4198
4417
  }
@@ -4212,7 +4431,7 @@ var VtxoManager = class _VtxoManager {
4212
4431
  const arkAddress = await this.wallet.getAddress();
4213
4432
  const outputFee = estimator.evalOffchainOutput({
4214
4433
  amount: totalAmount,
4215
- script: base.hex.encode(chunkE7HB3GKK_cjs.ArkAddress.decode(arkAddress).pkScript)
4434
+ script: base.hex.encode(chunkOWCPXRGP_cjs.ArkAddress.decode(arkAddress).pkScript)
4216
4435
  });
4217
4436
  totalAmount -= BigInt(outputFee.satoshis);
4218
4437
  if (totalAmount < dustAmount) return;
@@ -4292,7 +4511,7 @@ var ArkNote = class _ArkNote {
4292
4511
  this.value = value;
4293
4512
  this.HRP = HRP;
4294
4513
  const preimageHash = utils_js.sha256(this.preimage);
4295
- this.vtxoScript = new chunkE7HB3GKK_cjs.VtxoScript([noteTapscript(preimageHash)]);
4514
+ this.vtxoScript = new chunkOWCPXRGP_cjs.VtxoScript([noteTapscript(preimageHash)]);
4296
4515
  const leaf = this.vtxoScript.leaves[0];
4297
4516
  this.txid = base.hex.encode(new Uint8Array(preimageHash).reverse());
4298
4517
  this.tapTree = this.vtxoScript.encode();
@@ -4459,7 +4678,7 @@ var ArkadeCash = class _ArkadeCash {
4459
4678
  const privateKey = data.slice(1, 33);
4460
4679
  const serverPubKey = data.slice(33, 65);
4461
4680
  const sequence = new DataView(data.buffer, data.byteOffset + 65, 4).getUint32(0, false);
4462
- const csvTimelock = chunkE7HB3GKK_cjs.sequenceToTimelock(sequence);
4681
+ const csvTimelock = chunkOWCPXRGP_cjs.sequenceToTimelock(sequence);
4463
4682
  return new _ArkadeCash(privateKey, serverPubKey, csvTimelock, decoded.prefix);
4464
4683
  }
4465
4684
  toString() {
@@ -4467,7 +4686,7 @@ var ArkadeCash = class _ArkadeCash {
4467
4686
  data[0] = _ArkadeCash.Version;
4468
4687
  data.set(this._privateKey, 1);
4469
4688
  data.set(this._serverPubKey, 33);
4470
- const sequence = chunkE7HB3GKK_cjs.timelockToSequence(this.csvTimelock);
4689
+ const sequence = chunkOWCPXRGP_cjs.timelockToSequence(this.csvTimelock);
4471
4690
  new DataView(data.buffer, data.byteOffset + 65, 4).setUint32(0, sequence, false);
4472
4691
  const words = base.bech32m.toWords(data);
4473
4692
  return base.bech32m.encode(this.hrp, words, 1023);
@@ -4476,7 +4695,7 @@ var ArkadeCash = class _ArkadeCash {
4476
4695
  return SingleKey.fromPrivateKey(this._privateKey);
4477
4696
  }
4478
4697
  get vtxoScript() {
4479
- return new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
4698
+ return new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
4480
4699
  pubKey: this._publicKey,
4481
4700
  serverPubKey: this._serverPubKey,
4482
4701
  csvTimelock: this.csvTimelock
@@ -4737,7 +4956,7 @@ async function captureExitBranch(params) {
4737
4956
  const nonCommitment = ordered.filter((c) => chainTxTypeToChainedExit(c.type) !== 1 /* Commitment */).map((c) => c.txid);
4738
4957
  if (nonCommitment.length > 0) {
4739
4958
  for (const psbt of await resolver.getVirtualTxs(nonCommitment)) {
4740
- psbtByTxid.set(chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
4959
+ psbtByTxid.set(chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
4741
4960
  }
4742
4961
  }
4743
4962
  }
@@ -4780,10 +4999,10 @@ var IndexerExitDataSource = class {
4780
4999
  while (hasMore) {
4781
5000
  const { chain: page, page: meta } = await this.indexer.getVtxoChain(
4782
5001
  { txid: vtxo.txid, vout: vtxo.vout },
4783
- { pageIndex, pageSize: chunkE7HB3GKK_cjs.DEFAULT_PAGE_SIZE }
5002
+ { pageIndex, pageSize: chunkOWCPXRGP_cjs.DEFAULT_PAGE_SIZE }
4784
5003
  );
4785
5004
  chain.push(...page);
4786
- hasMore = meta ? page.length === chunkE7HB3GKK_cjs.DEFAULT_PAGE_SIZE : false;
5005
+ hasMore = meta ? page.length === chunkOWCPXRGP_cjs.DEFAULT_PAGE_SIZE : false;
4787
5006
  pageIndex++;
4788
5007
  }
4789
5008
  return chain;
@@ -4795,12 +5014,12 @@ var IndexerExitDataSource = class {
4795
5014
  while (hasMore) {
4796
5015
  const { txs, page } = await this.indexer.getVirtualTxs(txids, {
4797
5016
  pageIndex,
4798
- pageSize: chunkE7HB3GKK_cjs.DEFAULT_PAGE_SIZE
5017
+ pageSize: chunkOWCPXRGP_cjs.DEFAULT_PAGE_SIZE
4799
5018
  });
4800
5019
  for (const psbt of txs) {
4801
- out.set(chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
5020
+ out.set(chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
4802
5021
  }
4803
- hasMore = page ? txs.length === chunkE7HB3GKK_cjs.DEFAULT_PAGE_SIZE : false;
5022
+ hasMore = page ? txs.length === chunkOWCPXRGP_cjs.DEFAULT_PAGE_SIZE : false;
4804
5023
  pageIndex++;
4805
5024
  }
4806
5025
  return out;
@@ -4821,7 +5040,7 @@ function chainedTxTypeToChainTxType(t) {
4821
5040
  }
4822
5041
  }
4823
5042
  function psbtInputTxids(psbtBase64) {
4824
- const tx = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
5043
+ const tx = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
4825
5044
  const ids = [];
4826
5045
  for (let i = 0; i < tx.inputsLength; i++) {
4827
5046
  const txid = tx.getInput(i).txid;
@@ -4922,11 +5141,6 @@ function createExitChainResolver(params) {
4922
5141
  return new OrderedExitChainResolver(sources, params.repository);
4923
5142
  }
4924
5143
 
4925
- // src/providers/availability.ts
4926
- function isRetryableProviderError(error) {
4927
- return error instanceof chunkRNMLFY2V_cjs.ProviderUnavailableError || error instanceof chunkRNMLFY2V_cjs.FetchError || chunkRNMLFY2V_cjs.isFetchTimeoutError(error);
4928
- }
4929
-
4930
5144
  // src/utils/syncCursors.ts
4931
5145
  var SAFETY_LAG_MS = 3e4;
4932
5146
  var OVERLAP_MS = 24 * 60 * 60 * 1e3;
@@ -5174,10 +5388,10 @@ async function resolveArkInfo(arkProvider, walletRepository) {
5174
5388
  try {
5175
5389
  info = await arkProvider.getInfo();
5176
5390
  } catch (err) {
5177
- if (!isRetryableProviderError(err)) throw err;
5391
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
5178
5392
  const snapshot = await loadArkInfoSnapshot(walletRepository);
5179
5393
  if (!snapshot) {
5180
- throw new chunkRNMLFY2V_cjs.ProviderUnavailableError(
5394
+ throw new chunkOWCPXRGP_cjs.ProviderUnavailableError(
5181
5395
  "Arkade server info is unavailable and no cached snapshot exists",
5182
5396
  { cause: err }
5183
5397
  );
@@ -5549,8 +5763,20 @@ function subtractAssets(spent, change) {
5549
5763
  if (map.size === 0) return void 0;
5550
5764
  return Array.from(map, ([assetId, amount]) => ({ assetId, amount }));
5551
5765
  }
5552
- async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, getTxCreatedAt) {
5553
- const fromOldestVtxo = vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
5766
+ function collectArkTxidsNeedingCreatedAt(vtxos) {
5767
+ const ownTxids = new Set(vtxos.map((v) => v.txid));
5768
+ const txids = /* @__PURE__ */ new Set();
5769
+ for (const vtxo of vtxos) {
5770
+ if (vtxo.isSpent && vtxo.arkTxId && !ownTxids.has(vtxo.arkTxId)) {
5771
+ txids.add(vtxo.arkTxId);
5772
+ }
5773
+ }
5774
+ return [...txids];
5775
+ }
5776
+ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, resolveTxCreatedAt) {
5777
+ const fromOldestVtxo = vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
5778
+ const txidsNeedingCreatedAt = resolveTxCreatedAt ? collectArkTxidsNeedingCreatedAt(fromOldestVtxo) : [];
5779
+ const resolvedCreatedAt = resolveTxCreatedAt && txidsNeedingCreatedAt.length > 0 ? await resolveTxCreatedAt(txidsNeedingCreatedAt) : /* @__PURE__ */ new Map();
5554
5780
  const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
5555
5781
  const sent = [];
5556
5782
  let received = [];
@@ -5610,7 +5836,7 @@ async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnor
5610
5836
  txTime = changes[0].createdAt.getTime();
5611
5837
  } else {
5612
5838
  txAmount = spentAmount;
5613
- txTime = getTxCreatedAt ? await getTxCreatedAt(vtxo.arkTxId) ?? vtxo.createdAt.getTime() + 1 : vtxo.createdAt.getTime() + 1;
5839
+ txTime = resolvedCreatedAt.get(vtxo.arkTxId) ?? vtxo.createdAt.getTime() + 1;
5614
5840
  }
5615
5841
  const assets = subtractAssets(allSpent, changes);
5616
5842
  if (txAmount !== 0 || assets) {
@@ -5712,7 +5938,7 @@ var AssetManager = class extends ReadonlyAssetManager {
5712
5938
  const virtualCoins = await this.wallet.getVtxos({
5713
5939
  withRecoverable: false
5714
5940
  });
5715
- const controlAssetRef = params.controlAssetId ? chunkRNMLFY2V_cjs.AssetRef.fromId(chunkRNMLFY2V_cjs.AssetId.fromString(params.controlAssetId)) : null;
5941
+ const controlAssetRef = params.controlAssetId ? chunkG7DOBFQN_cjs.AssetRef.fromId(chunkG7DOBFQN_cjs.AssetId.fromString(params.controlAssetId)) : null;
5716
5942
  const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
5717
5943
  let totalBtcSelected = 0n;
5718
5944
  const assetChanges = /* @__PURE__ */ new Map();
@@ -5725,8 +5951,8 @@ var AssetManager = class extends ReadonlyAssetManager {
5725
5951
  }
5726
5952
  }
5727
5953
  const groups = [];
5728
- const issuedAssetOutput = chunkRNMLFY2V_cjs.AssetOutput.create(0, params.amount);
5729
- const issuedAssetGroup = chunkRNMLFY2V_cjs.AssetGroup.create(
5954
+ const issuedAssetOutput = chunkG7DOBFQN_cjs.AssetOutput.create(0, params.amount);
5955
+ const issuedAssetGroup = chunkG7DOBFQN_cjs.AssetGroup.create(
5730
5956
  null,
5731
5957
  controlAssetRef,
5732
5958
  [],
@@ -5741,28 +5967,28 @@ var AssetManager = class extends ReadonlyAssetManager {
5741
5967
  for (const [inputIndex, assets] of assetInputs) {
5742
5968
  for (const asset of assets) {
5743
5969
  if (asset.assetId !== assetId) continue;
5744
- changeInputs.push(chunkRNMLFY2V_cjs.AssetInput.create(inputIndex, asset.amount));
5970
+ changeInputs.push(chunkG7DOBFQN_cjs.AssetInput.create(inputIndex, asset.amount));
5745
5971
  }
5746
5972
  }
5747
5973
  groups.push(
5748
- chunkRNMLFY2V_cjs.AssetGroup.create(
5749
- chunkRNMLFY2V_cjs.AssetId.fromString(assetId),
5974
+ chunkG7DOBFQN_cjs.AssetGroup.create(
5975
+ chunkG7DOBFQN_cjs.AssetId.fromString(assetId),
5750
5976
  null,
5751
5977
  changeInputs,
5752
- [chunkRNMLFY2V_cjs.AssetOutput.create(0, amount)],
5978
+ [chunkG7DOBFQN_cjs.AssetOutput.create(0, amount)],
5753
5979
  []
5754
5980
  )
5755
5981
  );
5756
5982
  }
5757
5983
  }
5758
5984
  const address = await this.wallet.getAddress();
5759
- const outputAddress = chunkE7HB3GKK_cjs.ArkAddress.decode(address);
5985
+ const outputAddress = chunkOWCPXRGP_cjs.ArkAddress.decode(address);
5760
5986
  const outputs = [
5761
5987
  {
5762
5988
  script: outputAddress.pkScript,
5763
5989
  amount: BigInt(totalBtcSelected)
5764
5990
  },
5765
- Extension.create([chunkRNMLFY2V_cjs.Packet.create(groups)]).txOut()
5991
+ Extension.create([chunkG7DOBFQN_cjs.Packet.create(groups)]).txOut()
5766
5992
  ];
5767
5993
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
5768
5994
  coinSelection.inputs,
@@ -5770,7 +5996,7 @@ var AssetManager = class extends ReadonlyAssetManager {
5770
5996
  );
5771
5997
  return {
5772
5998
  arkTxId: arkTxid,
5773
- assetId: chunkRNMLFY2V_cjs.AssetId.create(arkTxid, 0).toString()
5999
+ assetId: chunkG7DOBFQN_cjs.AssetId.create(arkTxid, 0).toString()
5774
6000
  };
5775
6001
  }
5776
6002
  /**
@@ -5842,16 +6068,16 @@ var AssetManager = class extends ReadonlyAssetManager {
5842
6068
  for (const [inputIndex, assets] of assetInputs) {
5843
6069
  for (const asset of assets) {
5844
6070
  if (asset.assetId !== params.assetId) continue;
5845
- reissueInputs.push(chunkRNMLFY2V_cjs.AssetInput.create(inputIndex, asset.amount));
6071
+ reissueInputs.push(chunkG7DOBFQN_cjs.AssetInput.create(inputIndex, asset.amount));
5846
6072
  }
5847
6073
  }
5848
6074
  const totalAssetAmount = assetToReissueAmount + params.amount;
5849
- const reissueAssetIdObj = chunkRNMLFY2V_cjs.AssetId.fromString(params.assetId);
5850
- const reissueAssetGroup = chunkRNMLFY2V_cjs.AssetGroup.create(
6075
+ const reissueAssetIdObj = chunkG7DOBFQN_cjs.AssetId.fromString(params.assetId);
6076
+ const reissueAssetGroup = chunkG7DOBFQN_cjs.AssetGroup.create(
5851
6077
  reissueAssetIdObj,
5852
6078
  null,
5853
6079
  reissueInputs,
5854
- [chunkRNMLFY2V_cjs.AssetOutput.create(0, totalAssetAmount)],
6080
+ [chunkG7DOBFQN_cjs.AssetOutput.create(0, totalAssetAmount)],
5855
6081
  []
5856
6082
  );
5857
6083
  const groups = [reissueAssetGroup];
@@ -5860,27 +6086,27 @@ var AssetManager = class extends ReadonlyAssetManager {
5860
6086
  for (const [inputIndex, assets] of assetInputs) {
5861
6087
  for (const asset of assets) {
5862
6088
  if (asset.assetId !== assetId) continue;
5863
- changeInputs.push(chunkRNMLFY2V_cjs.AssetInput.create(inputIndex, asset.amount));
6089
+ changeInputs.push(chunkG7DOBFQN_cjs.AssetInput.create(inputIndex, asset.amount));
5864
6090
  }
5865
6091
  }
5866
6092
  groups.push(
5867
- chunkRNMLFY2V_cjs.AssetGroup.create(
5868
- chunkRNMLFY2V_cjs.AssetId.fromString(assetId),
6093
+ chunkG7DOBFQN_cjs.AssetGroup.create(
6094
+ chunkG7DOBFQN_cjs.AssetId.fromString(assetId),
5869
6095
  null,
5870
6096
  changeInputs,
5871
- [chunkRNMLFY2V_cjs.AssetOutput.create(0, amount)],
6097
+ [chunkG7DOBFQN_cjs.AssetOutput.create(0, amount)],
5872
6098
  []
5873
6099
  )
5874
6100
  );
5875
6101
  }
5876
6102
  const address = await this.wallet.getAddress();
5877
- const outputAddress = chunkE7HB3GKK_cjs.ArkAddress.decode(address);
6103
+ const outputAddress = chunkOWCPXRGP_cjs.ArkAddress.decode(address);
5878
6104
  const outputs = [
5879
6105
  {
5880
6106
  script: outputAddress.pkScript,
5881
6107
  amount: BigInt(totalBtcSelected)
5882
6108
  },
5883
- Extension.create([chunkRNMLFY2V_cjs.Packet.create(groups)]).txOut()
6109
+ Extension.create([chunkG7DOBFQN_cjs.Packet.create(groups)]).txOut()
5884
6110
  ];
5885
6111
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
5886
6112
  return arkTxid;
@@ -5947,27 +6173,27 @@ var AssetManager = class extends ReadonlyAssetManager {
5947
6173
  for (const [inputIndex, assets] of assetInputs) {
5948
6174
  for (const asset of assets) {
5949
6175
  if (asset.assetId !== assetId) continue;
5950
- changeInputs.push(chunkRNMLFY2V_cjs.AssetInput.create(inputIndex, asset.amount));
6176
+ changeInputs.push(chunkG7DOBFQN_cjs.AssetInput.create(inputIndex, asset.amount));
5951
6177
  }
5952
6178
  }
5953
6179
  groups.push(
5954
- chunkRNMLFY2V_cjs.AssetGroup.create(
5955
- chunkRNMLFY2V_cjs.AssetId.fromString(assetId),
6180
+ chunkG7DOBFQN_cjs.AssetGroup.create(
6181
+ chunkG7DOBFQN_cjs.AssetId.fromString(assetId),
5956
6182
  null,
5957
6183
  changeInputs,
5958
- amount > 0n ? [chunkRNMLFY2V_cjs.AssetOutput.create(0, amount)] : [],
6184
+ amount > 0n ? [chunkG7DOBFQN_cjs.AssetOutput.create(0, amount)] : [],
5959
6185
  []
5960
6186
  )
5961
6187
  );
5962
6188
  }
5963
6189
  const address = await this.wallet.getAddress();
5964
- const outputAddress = chunkE7HB3GKK_cjs.ArkAddress.decode(address);
6190
+ const outputAddress = chunkOWCPXRGP_cjs.ArkAddress.decode(address);
5965
6191
  const outputs = [
5966
6192
  {
5967
6193
  script: outputAddress.pkScript,
5968
6194
  amount: BigInt(totalBtcSelected)
5969
6195
  },
5970
- Extension.create([chunkRNMLFY2V_cjs.Packet.create(groups)]).txOut()
6196
+ Extension.create([chunkG7DOBFQN_cjs.Packet.create(groups)]).txOut()
5971
6197
  ];
5972
6198
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
5973
6199
  return arkTxid;
@@ -5992,7 +6218,7 @@ function castMetadata(metadata) {
5992
6218
  } else {
5993
6219
  throw new Error("Invalid metadata value type");
5994
6220
  }
5995
- md.push(chunkRNMLFY2V_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
6221
+ md.push(chunkG7DOBFQN_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
5996
6222
  }
5997
6223
  return md;
5998
6224
  }
@@ -6013,10 +6239,10 @@ var DelegateManagerImpl = class {
6013
6239
  if (vtxos.length === 0) {
6014
6240
  return { delegated: [], failed: [] };
6015
6241
  }
6016
- const destinationScript = chunkE7HB3GKK_cjs.ArkAddress.decode(destination).pkScript;
6242
+ const destinationScript = chunkOWCPXRGP_cjs.ArkAddress.decode(destination).pkScript;
6017
6243
  const arkInfo = await this.arkInfoProvider.getInfo();
6018
6244
  const delegateInfo = await this.delegateProvider.getDelegateInfo();
6019
- const eligible = vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo).filter(
6245
+ const eligible = vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo).filter(
6020
6246
  (v) => isAnnotated(v) && findDelegateTapLeaf(v, delegateInfo.pubkey) !== void 0
6021
6247
  );
6022
6248
  if (eligible.length === 0) {
@@ -6045,11 +6271,11 @@ var DelegateManagerImpl = class {
6045
6271
  const groupByExpiry = /* @__PURE__ */ new Map();
6046
6272
  let recoverableVtxos = [];
6047
6273
  for (const vtxo of eligible) {
6048
- if (chunkE7HB3GKK_cjs.canRecoverOnchain(vtxo, now)) {
6274
+ if (chunkOWCPXRGP_cjs.canRecoverOnchain(vtxo, now)) {
6049
6275
  recoverableVtxos.push(vtxo);
6050
6276
  continue;
6051
6277
  }
6052
- const expiry = chunkE7HB3GKK_cjs.toBatchExpiry(vtxo);
6278
+ const expiry = chunkOWCPXRGP_cjs.toBatchExpiry(vtxo);
6053
6279
  if (!expiry) continue;
6054
6280
  const dayKey = getDayTimestamp(expiry);
6055
6281
  groupByExpiry.set(dayKey, [...groupByExpiry.get(dayKey) ?? [], vtxo]);
@@ -6114,7 +6340,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
6114
6340
  }
6115
6341
  if (!delegateAt) {
6116
6342
  const now = { timestamp: /* @__PURE__ */ new Date() };
6117
- const expiryTimestamp = vtxos.filter((coin) => !chunkE7HB3GKK_cjs.canRecoverOnchain(coin, now) && chunkE7HB3GKK_cjs.toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, chunkE7HB3GKK_cjs.toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
6343
+ const expiryTimestamp = vtxos.filter((coin) => !chunkOWCPXRGP_cjs.canRecoverOnchain(coin, now) && chunkOWCPXRGP_cjs.toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, chunkOWCPXRGP_cjs.toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
6118
6344
  if (!expiryTimestamp || expiryTimestamp === Number.MAX_SAFE_INTEGER) {
6119
6345
  delegateAt = new Date(Date.now() + 1 * 60 * 1e3);
6120
6346
  } else {
@@ -6143,7 +6369,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
6143
6369
  let amount = 0n;
6144
6370
  for (const coin of vtxos) {
6145
6371
  const inputFee = estimator.evalOffchainInput({
6146
- ...chunkE7HB3GKK_cjs.toOffchainInputFeeParams(coin),
6372
+ ...chunkOWCPXRGP_cjs.toOffchainInputFeeParams(coin),
6147
6373
  type: "vtxo"
6148
6374
  });
6149
6375
  if (inputFee.value >= coin.value) {
@@ -6157,7 +6383,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
6157
6383
  const delegateFee = BigInt(Number(fee));
6158
6384
  if (delegateFee > 0n) {
6159
6385
  outputs.push({
6160
- script: chunkE7HB3GKK_cjs.ArkAddress.decode(delegateAddress).pkScript,
6386
+ script: chunkOWCPXRGP_cjs.ArkAddress.decode(delegateAddress).pkScript,
6161
6387
  amount: delegateFee
6162
6388
  });
6163
6389
  }
@@ -6190,10 +6416,10 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
6190
6416
  destinationScript
6191
6417
  );
6192
6418
  const forfeitOutputScript = btcSigner.OutScript.encode(
6193
- btcSigner.Address(chunkE7HB3GKK_cjs.getNetwork(network)).decode(forfeitAddress)
6419
+ btcSigner.Address(chunkOWCPXRGP_cjs.getNetwork(network)).decode(forfeitAddress)
6194
6420
  );
6195
6421
  const forfeits = await Promise.all(
6196
- vtxos.filter((v) => !chunkE7HB3GKK_cjs.canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
6422
+ vtxos.filter((v) => !chunkOWCPXRGP_cjs.canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
6197
6423
  const forfeit = await makeDelegateForfeitTx(
6198
6424
  coin,
6199
6425
  dust,
@@ -6218,7 +6444,7 @@ async function makeDelegateForfeitTx(input, connectorAmount, delegatePubkey, for
6218
6444
  index: input.vout,
6219
6445
  witnessUtxo: {
6220
6446
  amount: BigInt(input.value),
6221
- script: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript
6447
+ script: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript
6222
6448
  },
6223
6449
  sighashType: btcSigner.SigHash.ALL_ANYONECANPAY,
6224
6450
  tapLeafScript: [delegateTapLeaf]
@@ -6276,7 +6502,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
6276
6502
  expire_at: 0,
6277
6503
  cosigners_public_keys: cosignerPubKeys
6278
6504
  };
6279
- const proof = chunkRNMLFY2V_cjs.Intent.create(message, coins, outputs);
6505
+ const proof = chunkOWCPXRGP_cjs.Intent.create(message, coins, outputs);
6280
6506
  const signedProof = await identity.sign(proof);
6281
6507
  return {
6282
6508
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -6294,10 +6520,10 @@ function getDayTimestamp(timestamp) {
6294
6520
  function findDelegateTapLeaf(vtxo, delegatePubkey) {
6295
6521
  if (!vtxo.tapTree) return void 0;
6296
6522
  const pk = delegatePubkey.length === 66 ? delegatePubkey.slice(2) : delegatePubkey;
6297
- const vtxoScript = chunkE7HB3GKK_cjs.VtxoScript.decode(vtxo.tapTree);
6523
+ const vtxoScript = chunkOWCPXRGP_cjs.VtxoScript.decode(vtxo.tapTree);
6298
6524
  return vtxoScript.leaves.find((tapLeaf) => {
6299
- const arkTapscript = chunkE7HB3GKK_cjs.decodeTapscript(chunkE7HB3GKK_cjs.scriptFromTapLeafScript(tapLeaf));
6300
- if (!chunkE7HB3GKK_cjs.MultisigTapscript.is(arkTapscript)) return false;
6525
+ const arkTapscript = chunkOWCPXRGP_cjs.decodeTapscript(chunkOWCPXRGP_cjs.scriptFromTapLeafScript(tapLeaf));
6526
+ if (!chunkOWCPXRGP_cjs.MultisigTapscript.is(arkTapscript)) return false;
6301
6527
  return arkTapscript.params.pubkeys.map(base.hex.encode).includes(pk);
6302
6528
  });
6303
6529
  }
@@ -6485,7 +6711,7 @@ async function closeDatabase(dbName) {
6485
6711
  return true;
6486
6712
  }
6487
6713
  function scriptFromArkAddress(address) {
6488
- return base.hex.encode(chunkE7HB3GKK_cjs.ArkAddress.decode(address).pkScript);
6714
+ return base.hex.encode(chunkOWCPXRGP_cjs.ArkAddress.decode(address).pkScript);
6489
6715
  }
6490
6716
 
6491
6717
  // src/repositories/indexedDB/schema.ts
@@ -6982,7 +7208,7 @@ function validateVtxosForScript(vtxos, script, context) {
6982
7208
  }
6983
7209
  async function getVtxosForContract(repo, contract) {
6984
7210
  const vtxos = repo.getVtxosForScript ? await repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
6985
- return vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo);
7211
+ return vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo);
6986
7212
  }
6987
7213
  async function saveVtxosForContract(repo, contract, vtxos) {
6988
7214
  if (repo.saveVtxosForScript) {
@@ -7186,7 +7412,7 @@ var deserializeTapLeaf = (t) => {
7186
7412
  const s = base.hex.decode(t.s);
7187
7413
  return [cb, s];
7188
7414
  };
7189
- var deserializeVtxo = (o) => chunkE7HB3GKK_cjs.normalizeVtxo({
7415
+ var deserializeVtxo = (o) => chunkOWCPXRGP_cjs.normalizeVtxo({
7190
7416
  ...o,
7191
7417
  createdAt: new Date(o.createdAt),
7192
7418
  tapTree: base.hex.decode(o.tapTree),
@@ -8325,7 +8551,7 @@ var ContractWatcher = class {
8325
8551
  this.connectionState = "connected";
8326
8552
  this.reconnectAttempts = 0;
8327
8553
  this.listenLoop().catch((e) => {
8328
- if (chunkRNMLFY2V_cjs.isEventSourceError(e)) {
8554
+ if (chunkOWCPXRGP_cjs.isEventSourceError(e)) {
8329
8555
  console.debug("ContractWatcher subscription disconnected; reconnecting");
8330
8556
  } else {
8331
8557
  console.error(e);
@@ -8554,14 +8780,14 @@ var ContractWatcher = class {
8554
8780
  const timestamp = Date.now();
8555
8781
  if (update.newVtxos?.length) {
8556
8782
  this.processSubscriptionVtxos(
8557
- update.newVtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo),
8783
+ update.newVtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo),
8558
8784
  "vtxo_received",
8559
8785
  timestamp
8560
8786
  );
8561
8787
  }
8562
8788
  if (update.spentVtxos?.length) {
8563
8789
  this.processSubscriptionVtxos(
8564
- update.spentVtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo),
8790
+ update.spentVtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo),
8565
8791
  "vtxo_spent",
8566
8792
  timestamp
8567
8793
  );
@@ -8694,7 +8920,7 @@ async function reconcileIntents(deps) {
8694
8920
  let vtxosByOutpoint = /* @__PURE__ */ new Map();
8695
8921
  if (outpoints.length > 0) {
8696
8922
  try {
8697
- const { vtxos } = await chunkE7HB3GKK_cjs.getNormalizedVtxos(deps.indexerProvider, { outpoints });
8923
+ const { vtxos } = await chunkOWCPXRGP_cjs.getNormalizedVtxos(deps.indexerProvider, { outpoints });
8698
8924
  vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
8699
8925
  } catch (e) {
8700
8926
  console.error("reconcileIntents: failed to fetch input VTXO state", e);
@@ -8814,7 +9040,7 @@ var ContractManager = class _ContractManager {
8814
9040
  await this.reconcileWatched();
8815
9041
  this.markSyncOnline();
8816
9042
  } catch (err) {
8817
- if (!isRetryableProviderError(err)) throw err;
9043
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
8818
9044
  this.markSyncDegraded(err);
8819
9045
  }
8820
9046
  this.initialized = true;
@@ -8926,7 +9152,7 @@ var ContractManager = class _ContractManager {
8926
9152
  const from = Math.max(0, watermark - lookAhead.size);
8927
9153
  const to = watermark + lookAhead.size;
8928
9154
  const deps = lookAhead.candidateDeps();
8929
- const handlers = chunkIEMPH7J6_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkIEMPH7J6_cjs.contractHandlers.get(t)).filter(hasCandidates);
9155
+ const handlers = chunkV2TOHHPW_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkV2TOHHPW_cjs.contractHandlers.get(t)).filter(hasCandidates);
8930
9156
  const band = /* @__PURE__ */ new Map();
8931
9157
  for (let index = from; index <= to; index++) {
8932
9158
  const descriptor = lookAhead.materialize(index);
@@ -8937,7 +9163,7 @@ var ContractManager = class _ContractManager {
8937
9163
  index,
8938
9164
  params: {
8939
9165
  ...candidate,
8940
- ...chunkIEMPH7J6_cjs.speculativeReceiveMetadata(descriptor)
9166
+ ...chunkV2TOHHPW_cjs.speculativeReceiveMetadata(descriptor)
8941
9167
  }
8942
9168
  });
8943
9169
  }
@@ -8997,7 +9223,7 @@ var ContractManager = class _ContractManager {
8997
9223
  });
8998
9224
  for (const entry of pending) entry.catchUpPending = false;
8999
9225
  } catch (err) {
9000
- if (!isRetryableProviderError(err)) throw err;
9226
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
9001
9227
  this.markSyncDegraded(err);
9002
9228
  }
9003
9229
  }
@@ -9041,7 +9267,7 @@ var ContractManager = class _ContractManager {
9041
9267
  await this.fetchContractVxosFromIndexer([contract]);
9042
9268
  this.markSyncOnline();
9043
9269
  } catch (err) {
9044
- if (!isRetryableProviderError(err)) throw err;
9270
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
9045
9271
  this.markSyncDegraded(err);
9046
9272
  }
9047
9273
  await this.watcher.addContract(contract);
@@ -9078,7 +9304,7 @@ var ContractManager = class _ContractManager {
9078
9304
  return result;
9079
9305
  }
9080
9306
  async upsertContractRow(params) {
9081
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(params.type);
9307
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(params.type);
9082
9308
  if (!handler) {
9083
9309
  throw new Error(`No handler registered for contract type '${params.type}'`);
9084
9310
  }
@@ -9178,7 +9404,7 @@ var ContractManager = class _ContractManager {
9178
9404
  `scanContracts: batchSize must be a positive integer (got ${String(opts.batchSize)})`
9179
9405
  );
9180
9406
  }
9181
- const registered = chunkIEMPH7J6_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkIEMPH7J6_cjs.contractHandlers.get(t)).filter(isDiscoverable);
9407
+ const registered = chunkV2TOHHPW_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkV2TOHHPW_cjs.contractHandlers.get(t)).filter(isDiscoverable);
9182
9408
  const discoverables = [
9183
9409
  ...registered.filter((h) => h.type === "boarding"),
9184
9410
  ...registered.filter((h) => h.type !== "boarding")
@@ -9313,7 +9539,7 @@ var ContractManager = class _ContractManager {
9313
9539
  await this.syncContracts({ contracts, pageSize });
9314
9540
  this.markSyncOnline();
9315
9541
  } catch (err) {
9316
- if (!isRetryableProviderError(err)) throw err;
9542
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
9317
9543
  this.markSyncDegraded(err);
9318
9544
  }
9319
9545
  const vtxos = await this.getVtxosForContracts(contracts);
@@ -9334,7 +9560,7 @@ var ContractManager = class _ContractManager {
9334
9560
  }
9335
9561
  const tapscriptCache = /* @__PURE__ */ new Map();
9336
9562
  return vtxos.map(
9337
- (vtxo) => extendVirtualCoinForContract(chunkE7HB3GKK_cjs.normalizeVtxo(vtxo), byScript, tapscriptCache)
9563
+ (vtxo) => extendVirtualCoinForContract(chunkOWCPXRGP_cjs.normalizeVtxo(vtxo), byScript, tapscriptCache)
9338
9564
  );
9339
9565
  }
9340
9566
  buildContractsDbFilter(filter) {
@@ -9419,7 +9645,7 @@ var ContractManager = class _ContractManager {
9419
9645
  const { contractScript, collaborative = true, walletPubKey, vtxo } = options;
9420
9646
  const [contract] = await this.getContracts({ script: contractScript });
9421
9647
  if (!contract) return [];
9422
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
9648
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
9423
9649
  if (!handler) return [];
9424
9650
  const script = handler.createScript(contract.params);
9425
9651
  const context = {
@@ -9439,7 +9665,7 @@ var ContractManager = class _ContractManager {
9439
9665
  const { contractScript, collaborative = true, walletPubKey } = options;
9440
9666
  const [contract] = await this.getContracts({ script: contractScript });
9441
9667
  if (!contract) return [];
9442
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
9668
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
9443
9669
  if (!handler) return [];
9444
9670
  const script = handler.createScript(contract.params);
9445
9671
  const context = {
@@ -9495,7 +9721,7 @@ var ContractManager = class _ContractManager {
9495
9721
  }
9496
9722
  async refreshOutpoints(outpoints) {
9497
9723
  if (outpoints.length === 0) return;
9498
- const { vtxos } = await chunkE7HB3GKK_cjs.getNormalizedVtxos(this.config.indexerProvider, {
9724
+ const { vtxos } = await chunkOWCPXRGP_cjs.getNormalizedVtxos(this.config.indexerProvider, {
9499
9725
  outpoints
9500
9726
  });
9501
9727
  if (vtxos.length === 0) return;
@@ -9573,7 +9799,7 @@ var ContractManager = class _ContractManager {
9573
9799
  break;
9574
9800
  }
9575
9801
  } catch (err) {
9576
- if (!isRetryableProviderError(err)) throw err;
9802
+ if (!chunkOWCPXRGP_cjs.isRetryableProviderError(err)) throw err;
9577
9803
  this.markSyncDegraded(err);
9578
9804
  }
9579
9805
  this.emitEvent(event);
@@ -9622,7 +9848,7 @@ var ContractManager = class _ContractManager {
9622
9848
  */
9623
9849
  async reconcilePendingFrontier(contracts) {
9624
9850
  const scriptToContract = new Map(contracts.map((c) => [c.script, c]));
9625
- const vtxos = await chunkE7HB3GKK_cjs.getAllNormalizedVtxos(
9851
+ const vtxos = await chunkOWCPXRGP_cjs.getAllNormalizedVtxos(
9626
9852
  this.config.indexerProvider,
9627
9853
  contracts.map((c) => c.script),
9628
9854
  { pendingOnly: true }
@@ -9703,7 +9929,7 @@ var ContractManager = class _ContractManager {
9703
9929
  }
9704
9930
  return result;
9705
9931
  }
9706
- async fetchContractVtxosBulk(contracts, pageSize = chunkE7HB3GKK_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
9932
+ async fetchContractVtxosBulk(contracts, pageSize = chunkOWCPXRGP_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
9707
9933
  if (contracts.length === 0) {
9708
9934
  return { vtxosByScript: /* @__PURE__ */ new Map(), promoted: /* @__PURE__ */ new Map() };
9709
9935
  }
@@ -9719,7 +9945,7 @@ var ContractManager = class _ContractManager {
9719
9945
  before: syncWindow.before
9720
9946
  }
9721
9947
  } : {};
9722
- const vtxos = await chunkE7HB3GKK_cjs.getAllNormalizedVtxos(
9948
+ const vtxos = await chunkOWCPXRGP_cjs.getAllNormalizedVtxos(
9723
9949
  this.config.indexerProvider,
9724
9950
  contracts.map((c) => c.script),
9725
9951
  { ...windowOpts, pageSize }
@@ -9886,7 +10112,7 @@ var HDDescriptorProvider = class _HDDescriptorProvider {
9886
10112
  */
9887
10113
  materializeDescriptorAt(index) {
9888
10114
  const descriptor = this.identity.descriptor;
9889
- const network = chunkIEMPH7J6_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
10115
+ const network = chunkV2TOHHPW_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
9890
10116
  const expansion = descriptorsScure.expand({ descriptor, network, index });
9891
10117
  const keyInfo = expansion.expansionMap?.["@0"];
9892
10118
  if (!keyInfo?.keyExpression) {
@@ -10030,7 +10256,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
10030
10256
  const provider = await resolveDescriptorProvider(config, setup.walletRepository);
10031
10257
  if (!provider) return void 0;
10032
10258
  const allowSilentFallback = (config.walletMode ?? "auto") === "auto";
10033
- const expectedContractType = setup.offchainTapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? "delegate" : "default";
10259
+ const expectedContractType = setup.offchainTapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? "delegate" : "default";
10034
10260
  const factoryOpts = {
10035
10261
  walletRepository: setup.walletRepository,
10036
10262
  contractRepository: setup.contractRepository,
@@ -10229,7 +10455,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
10229
10455
  };
10230
10456
  function deriveLeafPubkey(descriptor) {
10231
10457
  try {
10232
- return chunkIEMPH7J6_cjs.deriveDescriptorLeafPubKey(descriptor);
10458
+ return chunkV2TOHHPW_cjs.deriveDescriptorLeafPubKey(descriptor);
10233
10459
  } catch (e) {
10234
10460
  throw new NonRangeableDescriptorError(
10235
10461
  "Cannot derive leaf pubkey: descriptor is not a materialized, parsable tr(...) shape.",
@@ -10241,7 +10467,7 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
10241
10467
  const pubKey = deriveLeafPubkey(descriptor);
10242
10468
  const tapscript = rebuildTapscript(current, pubKey);
10243
10469
  const serverPubKey = tapscript.options.serverPubKey;
10244
- const csvTimelock = chunkE7HB3GKK_cjs.timelockToSequence(tapscript.options.csvTimelock).toString();
10470
+ const csvTimelock = chunkOWCPXRGP_cjs.timelockToSequence(tapscript.options.csvTimelock).toString();
10245
10471
  const base$1 = {
10246
10472
  script: base.hex.encode(tapscript.pkScript),
10247
10473
  address: tapscript.address(hrp, serverPubKey).encode(),
@@ -10252,11 +10478,11 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
10252
10478
  // index-0 key. Without it, spends produce unsigned PSBTs that the
10253
10479
  // server rejects with `INVALID_PSBT_INPUT (5): missing tapscript spend sig`.
10254
10480
  metadata: {
10255
- ...{ source: chunkIEMPH7J6_cjs.WALLET_RECEIVE_SOURCE },
10481
+ ...{ source: chunkV2TOHHPW_cjs.WALLET_RECEIVE_SOURCE },
10256
10482
  signingDescriptor: descriptor
10257
10483
  }
10258
10484
  };
10259
- const params = tapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? {
10485
+ const params = tapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? {
10260
10486
  ...base$1,
10261
10487
  type: "delegate",
10262
10488
  params: {
@@ -10277,10 +10503,10 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
10277
10503
  return { tapscript, params };
10278
10504
  }
10279
10505
  function rebuildTapscript(current, pubKey) {
10280
- if (current instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script) {
10281
- return new chunkIEMPH7J6_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
10506
+ if (current instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script) {
10507
+ return new chunkV2TOHHPW_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
10282
10508
  }
10283
- return new chunkIEMPH7J6_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
10509
+ return new chunkV2TOHHPW_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
10284
10510
  }
10285
10511
  async function pickActiveReceive(contractRepository, serverPubKey, expectedType) {
10286
10512
  const candidates = await contractRepository.getContracts({
@@ -10289,7 +10515,7 @@ async function pickActiveReceive(contractRepository, serverPubKey, expectedType)
10289
10515
  });
10290
10516
  const serverPubKeyHex = base.hex.encode(serverPubKey);
10291
10517
  const matching = candidates.filter(
10292
- (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkIEMPH7J6_cjs.WALLET_RECEIVE_SOURCE
10518
+ (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkV2TOHHPW_cjs.WALLET_RECEIVE_SOURCE
10293
10519
  ).sort((a, b) => {
10294
10520
  if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
10295
10521
  return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
@@ -10465,12 +10691,12 @@ var InputSignerRouter = class {
10465
10691
  };
10466
10692
 
10467
10693
  // src/wallet/wallet.ts
10468
- var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunkE7HB3GKK_cjs.DEFAULT_ARKADE_SERVER_URL;
10694
+ var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunkOWCPXRGP_cjs.DEFAULT_ARKADE_SERVER_URL;
10469
10695
  function intentProofJobs(coins) {
10470
10696
  if (coins.length === 0) return [];
10471
10697
  const coinJobs = coins.map((coin, i) => ({
10472
10698
  index: i + 1,
10473
- lookupScript: chunkE7HB3GKK_cjs.VtxoScript.decode(coin.tapTree).pkScript
10699
+ lookupScript: chunkOWCPXRGP_cjs.VtxoScript.decode(coin.tapTree).pkScript
10474
10700
  }));
10475
10701
  return [{ index: 0, lookupScript: coinJobs[0].lookupScript }, ...coinJobs];
10476
10702
  }
@@ -10495,7 +10721,7 @@ function dedupeTimelocks(timelocks) {
10495
10721
  const seen = /* @__PURE__ */ new Set();
10496
10722
  const deduped = [];
10497
10723
  for (const timelock of timelocks) {
10498
- const sequence = chunkE7HB3GKK_cjs.timelockToSequence(timelock).toString();
10724
+ const sequence = chunkOWCPXRGP_cjs.timelockToSequence(timelock).toString();
10499
10725
  if (seen.has(sequence)) continue;
10500
10726
  seen.add(sequence);
10501
10727
  deduped.push(timelock);
@@ -10512,7 +10738,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
10512
10738
  state: "active"
10513
10739
  });
10514
10740
  const newest = candidates.filter(
10515
- (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkIEMPH7J6_cjs.WALLET_RECEIVE_SOURCE
10741
+ (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkV2TOHHPW_cjs.WALLET_RECEIVE_SOURCE
10516
10742
  ).sort((a, b) => {
10517
10743
  if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
10518
10744
  return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
@@ -10520,7 +10746,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
10520
10746
  if (!newest?.params.pubKey) return baseline;
10521
10747
  try {
10522
10748
  const pubKey = base.hex.decode(newest.params.pubKey);
10523
- return new chunkIEMPH7J6_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
10749
+ return new chunkV2TOHHPW_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
10524
10750
  } catch (e) {
10525
10751
  console.warn("Skipping malformed boarding contract at boot", newest.script, e);
10526
10752
  return baseline;
@@ -10840,7 +11066,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
10840
11066
  */
10841
11067
  static async setupWalletConfig(config, pubKey) {
10842
11068
  const arkadeServerUrl = getArkadeServerUrl(config);
10843
- const arkProvider = config.arkProvider || new chunkRNMLFY2V_cjs.RestArkProvider(arkadeServerUrl);
11069
+ const arkProvider = config.arkProvider || new chunkOWCPXRGP_cjs.RestArkProvider(arkadeServerUrl);
10844
11070
  let indexerProvider = config.indexerProvider;
10845
11071
  if (!indexerProvider) {
10846
11072
  let indexerUrl = config.indexerUrl;
@@ -10857,7 +11083,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
10857
11083
  indexerUrl = arkadeServerUrl;
10858
11084
  }
10859
11085
  }
10860
- indexerProvider = new chunkRNMLFY2V_cjs.RestIndexerProvider(indexerUrl);
11086
+ indexerProvider = new chunkG7DOBFQN_cjs.RestIndexerProvider(indexerUrl);
10861
11087
  }
10862
11088
  const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
10863
11089
  const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
@@ -10866,7 +11092,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
10866
11092
  source: serverInfoSource,
10867
11093
  lastOnlineAt: serverInfoLastOnlineAt
10868
11094
  } = await resolveArkInfo(arkProvider, walletRepository);
10869
- const network = chunkE7HB3GKK_cjs.getNetwork(info.network);
11095
+ const network = chunkOWCPXRGP_cjs.getNetwork(info.network);
10870
11096
  if ("descriptor" in config.identity) {
10871
11097
  const descriptor = config.identity.descriptor;
10872
11098
  const identityIsMainnet = !descriptor.includes("tpub");
@@ -10913,11 +11139,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
10913
11139
  serverPubKey,
10914
11140
  csvTimelock: exitTimelock
10915
11141
  };
10916
- const offchainTapscript = !delegatePubKey ? new chunkIEMPH7J6_cjs.DefaultVtxo.Script(offchainOptions) : new chunkIEMPH7J6_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
10917
- const boardingTapscript = chunkIEMPH7J6_cjs.BoardingContractHandler.createScript({
11142
+ const offchainTapscript = !delegatePubKey ? new chunkV2TOHHPW_cjs.DefaultVtxo.Script(offchainOptions) : new chunkV2TOHHPW_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
11143
+ const boardingTapscript = chunkV2TOHHPW_cjs.BoardingContractHandler.createScript({
10918
11144
  pubKey: base.hex.encode(pubKey),
10919
11145
  serverPubKey: base.hex.encode(serverPubKey),
10920
- csvTimelock: chunkE7HB3GKK_cjs.timelockToSequence(boardingTimelock).toString()
11146
+ csvTimelock: chunkOWCPXRGP_cjs.timelockToSequence(boardingTimelock).toString()
10921
11147
  });
10922
11148
  return {
10923
11149
  arkProvider,
@@ -11023,19 +11249,19 @@ var ReadonlyWallet = class _ReadonlyWallet {
11023
11249
  let pendingRecovery = 0;
11024
11250
  const now = { timestamp: /* @__PURE__ */ new Date() };
11025
11251
  const settled = vtxos.filter(
11026
- (coin) => chunkE7HB3GKK_cjs.canSpendOffchain(coin, now) && !coin.isPreconfirmed && !isPendingRecovery(coin)
11252
+ (coin) => chunkOWCPXRGP_cjs.canSpendOffchain(coin, now) && !coin.isPreconfirmed && !isPendingRecovery(coin)
11027
11253
  ).reduce((sum, coin) => sum + coin.value, 0);
11028
11254
  const preconfirmed = vtxos.filter(
11029
- (coin) => chunkE7HB3GKK_cjs.canSpendOffchain(coin, now) && coin.isPreconfirmed && !isPendingRecovery(coin)
11255
+ (coin) => chunkOWCPXRGP_cjs.canSpendOffchain(coin, now) && coin.isPreconfirmed && !isPendingRecovery(coin)
11030
11256
  ).reduce((sum, coin) => sum + coin.value, 0);
11031
- const available = unlockedVtxos.filter((coin) => chunkE7HB3GKK_cjs.canSpendOffchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
11032
- recoverable = vtxos.filter((coin) => chunkE7HB3GKK_cjs.canRecoverOnchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
11257
+ const available = unlockedVtxos.filter((coin) => chunkOWCPXRGP_cjs.canSpendOffchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
11258
+ recoverable = vtxos.filter((coin) => chunkOWCPXRGP_cjs.canRecoverOnchain(coin, now) && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
11033
11259
  pendingRecovery = vtxos.filter(isPendingRecovery).reduce((sum, coin) => sum + coin.value, 0);
11034
11260
  const totalBoarding = confirmed + unconfirmed;
11035
11261
  const totalOffchain = settled + preconfirmed + recoverable + pendingRecovery;
11036
11262
  const assetBalances = /* @__PURE__ */ new Map();
11037
11263
  for (const vtxo of vtxos) {
11038
- if (chunkE7HB3GKK_cjs.hasTerminalSpend(vtxo)) continue;
11264
+ if (chunkOWCPXRGP_cjs.hasTerminalSpend(vtxo)) continue;
11039
11265
  if (vtxo.assets) {
11040
11266
  for (const a of vtxo.assets) {
11041
11267
  const current = assetBalances.get(a.assetId) ?? 0n;
@@ -11076,8 +11302,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
11076
11302
  if (this._pendingSpendOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
11077
11303
  return false;
11078
11304
  }
11079
- if (!chunkE7HB3GKK_cjs.hasTerminalSpend(vtxo)) {
11080
- if (!f.withRecoverable && chunkE7HB3GKK_cjs.canRecoverOnchain(vtxo, now)) {
11305
+ if (!chunkOWCPXRGP_cjs.hasTerminalSpend(vtxo)) {
11306
+ if (!f.withRecoverable && chunkOWCPXRGP_cjs.canRecoverOnchain(vtxo, now)) {
11081
11307
  return false;
11082
11308
  }
11083
11309
  return true;
@@ -11110,11 +11336,13 @@ var ReadonlyWallet = class _ReadonlyWallet {
11110
11336
  const response = await contractManager.getContractsWithVtxos();
11111
11337
  const allVtxos = response.flatMap((_) => _.vtxos);
11112
11338
  const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
11113
- const getTxCreatedAt = (txid) => chunkE7HB3GKK_cjs.getNormalizedVtxos(this.indexerProvider, { outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime()).catch((err) => {
11114
- if (isRetryableProviderError(err)) return void 0;
11115
- throw err;
11116
- });
11117
- return buildTransactionHistory(allVtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
11339
+ const resolveTxCreatedAt = (txids) => chunkOWCPXRGP_cjs.fetchVtxoCreatedAtByTxid(this.indexerProvider, txids);
11340
+ return buildTransactionHistory(
11341
+ allVtxos,
11342
+ boardingTxs,
11343
+ commitmentsToIgnore,
11344
+ resolveTxCreatedAt
11345
+ );
11118
11346
  }
11119
11347
  /**
11120
11348
  * Wallet history grouped by registered activity resolvers. With no resolver match,
@@ -11202,7 +11430,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11202
11430
  },
11203
11431
  isUnrolled: true,
11204
11432
  ...boardingFacts,
11205
- virtualStatus: chunkE7HB3GKK_cjs.toVirtualStatus(boardingFacts),
11433
+ virtualStatus: chunkOWCPXRGP_cjs.toVirtualStatus(boardingFacts),
11206
11434
  spentBy: "",
11207
11435
  createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
11208
11436
  script: scriptHex
@@ -11258,9 +11486,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
11258
11486
  async getBoardingTapscripts(allowedSigners) {
11259
11487
  const byScript = /* @__PURE__ */ new Map();
11260
11488
  const add = (s) => byScript.set(base.hex.encode(s.pkScript), s);
11261
- const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunkIEMPH7J6_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
11489
+ const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunkV2TOHHPW_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
11262
11490
  add(
11263
- new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
11491
+ new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
11264
11492
  pubKey: await this.identity.xOnlyPublicKey(),
11265
11493
  serverPubKey: this.boardingTapscript.options.serverPubKey,
11266
11494
  csvTimelock: boardingCsv
@@ -11275,7 +11503,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11275
11503
  for (const c of boardingContracts) {
11276
11504
  if (!allowed.has(toXOnlySignerHex(c.params.serverPubKey))) continue;
11277
11505
  try {
11278
- add(chunkIEMPH7J6_cjs.BoardingContractHandler.createScript(c.params));
11506
+ add(chunkV2TOHHPW_cjs.BoardingContractHandler.createScript(c.params));
11279
11507
  } catch (e) {
11280
11508
  console.warn("Skipping malformed boarding contract", c.script, e);
11281
11509
  }
@@ -11313,7 +11541,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11313
11541
  // Per-row CSV delay decoded from THIS tapscript's exit leaf —
11314
11542
  // not the wallet's current boarding timelock, which a signer
11315
11543
  // rotation may have changed.
11316
- csvTimelock: chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(base.hex.decode(tapscript.exitScript)).params.timelock,
11544
+ csvTimelock: chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(base.hex.decode(tapscript.exitScript)).params.timelock,
11317
11545
  coins: utxos
11318
11546
  });
11319
11547
  }
@@ -11446,7 +11674,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11446
11674
  /** Fetch Arkade transaction ids that are still pending final settlement. */
11447
11675
  async fetchPendingTxs() {
11448
11676
  const scripts = await this.getWalletScripts();
11449
- const vtxos = await chunkE7HB3GKK_cjs.getAllNormalizedVtxos(this.indexerProvider, scripts);
11677
+ const vtxos = await chunkOWCPXRGP_cjs.getAllNormalizedVtxos(this.indexerProvider, scripts);
11450
11678
  return vtxos.filter(
11451
11679
  (vtxo) => (vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept) && vtxo.arkTxId !== void 0
11452
11680
  ).map((_) => _.arkTxId);
@@ -11477,7 +11705,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11477
11705
  });
11478
11706
  for (const contract of contracts) {
11479
11707
  if (map.has(contract.script)) continue;
11480
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
11708
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
11481
11709
  if (handler) {
11482
11710
  const script = handler.createScript(contract.params);
11483
11711
  map.set(contract.script, script);
@@ -11580,7 +11808,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11580
11808
  lookAhead: this.lookAheadConfig()
11581
11809
  });
11582
11810
  const baselinePubkey = await this.identity.xOnlyPublicKey();
11583
- const delegatePubKey = this.offchainTapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
11811
+ const delegatePubKey = this.offchainTapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
11584
11812
  const baselineSigners = [
11585
11813
  this.offchainTapscript.options.serverPubKey,
11586
11814
  ...[...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h))
@@ -11588,8 +11816,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
11588
11816
  const seenBaselineScripts = /* @__PURE__ */ new Set();
11589
11817
  for (const serverPubKey of baselineSigners) {
11590
11818
  for (const csvTimelock of this.walletContractTimelocks) {
11591
- const csvTimelockStr = chunkE7HB3GKK_cjs.timelockToSequence(csvTimelock).toString();
11592
- const defaultScript = new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
11819
+ const csvTimelockStr = chunkOWCPXRGP_cjs.timelockToSequence(csvTimelock).toString();
11820
+ const defaultScript = new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
11593
11821
  pubKey: baselinePubkey,
11594
11822
  serverPubKey,
11595
11823
  csvTimelock
@@ -11610,7 +11838,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11610
11838
  });
11611
11839
  }
11612
11840
  if (delegatePubKey) {
11613
- const delegateScript = new chunkIEMPH7J6_cjs.DelegateVtxo.Script({
11841
+ const delegateScript = new chunkV2TOHHPW_cjs.DelegateVtxo.Script({
11614
11842
  pubKey: baselinePubkey,
11615
11843
  serverPubKey,
11616
11844
  delegatePubKey,
@@ -11634,9 +11862,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
11634
11862
  }
11635
11863
  }
11636
11864
  }
11637
- const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunkIEMPH7J6_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
11865
+ const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunkV2TOHHPW_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
11638
11866
  for (const serverPubKey of baselineSigners) {
11639
- const baselineBoarding = new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
11867
+ const baselineBoarding = new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
11640
11868
  pubKey: baselinePubkey,
11641
11869
  serverPubKey,
11642
11870
  csvTimelock: boardingCsvTimelock
@@ -11649,7 +11877,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
11649
11877
  params: {
11650
11878
  pubKey: base.hex.encode(baselineBoarding.options.pubKey),
11651
11879
  serverPubKey: base.hex.encode(serverPubKey),
11652
- csvTimelock: chunkE7HB3GKK_cjs.timelockToSequence(boardingCsvTimelock).toString()
11880
+ csvTimelock: chunkOWCPXRGP_cjs.timelockToSequence(boardingCsvTimelock).toString()
11653
11881
  },
11654
11882
  script: boardingScriptHex,
11655
11883
  address: baselineBoarding.address(this.network.hrp, serverPubKey).encode(),
@@ -11823,7 +12051,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
11823
12051
  serverPubKey: this.offchainTapscript.options.serverPubKey,
11824
12052
  deprecatedSignerPubKeys: [...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h)),
11825
12053
  csvTimelocks: this.walletContractTimelocks,
11826
- delegatePubKey: this.offchainTapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0
12054
+ delegatePubKey: this.offchainTapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0
11827
12055
  };
11828
12056
  }
11829
12057
  _signerRouter;
@@ -11915,25 +12143,25 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
11915
12143
  return this.getBoardingAddress();
11916
12144
  }
11917
12145
  const descriptor = await provider.getNextSigningDescriptor();
11918
- const pubKey = chunkIEMPH7J6_cjs.deriveDescriptorLeafPubKey(descriptor);
11919
- const newBoarding = new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
12146
+ const pubKey = chunkV2TOHHPW_cjs.deriveDescriptorLeafPubKey(descriptor);
12147
+ const newBoarding = new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
11920
12148
  ...this._boardingTapscript.options,
11921
12149
  pubKey
11922
12150
  });
11923
- const csvTimelock = newBoarding.options.csvTimelock ?? chunkIEMPH7J6_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
12151
+ const csvTimelock = newBoarding.options.csvTimelock ?? chunkV2TOHHPW_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
11924
12152
  const manager = await this.getContractManager();
11925
12153
  await manager.createContract({
11926
12154
  type: "boarding",
11927
12155
  params: {
11928
12156
  pubKey: base.hex.encode(pubKey),
11929
12157
  serverPubKey: base.hex.encode(newBoarding.options.serverPubKey),
11930
- csvTimelock: chunkE7HB3GKK_cjs.timelockToSequence(csvTimelock).toString()
12158
+ csvTimelock: chunkOWCPXRGP_cjs.timelockToSequence(csvTimelock).toString()
11931
12159
  },
11932
12160
  script: base.hex.encode(newBoarding.pkScript),
11933
12161
  address: newBoarding.address(this.network.hrp, this.arkServerPublicKey).encode(),
11934
12162
  state: "active",
11935
12163
  metadata: {
11936
- source: chunkIEMPH7J6_cjs.WALLET_RECEIVE_SOURCE,
12164
+ source: chunkV2TOHHPW_cjs.WALLET_RECEIVE_SOURCE,
11937
12165
  signingDescriptor: descriptor
11938
12166
  }
11939
12167
  });
@@ -11945,6 +12173,51 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
11945
12173
  }
11946
12174
  return newBoarding.onchainAddress(this.network);
11947
12175
  }
12176
+ /**
12177
+ * @see HDWalletCapable.getCurrentSigningDescriptor
12178
+ */
12179
+ async getCurrentSigningDescriptor() {
12180
+ const provider = this._descriptorProvider;
12181
+ if (!(provider instanceof HDDescriptorProvider)) return void 0;
12182
+ return provider.getCurrentSigningDescriptor();
12183
+ }
12184
+ /**
12185
+ * @see HDWalletCapable.getUsedSigningDescriptors
12186
+ *
12187
+ * Union of the watermark band and the descriptors persisted on contracts:
12188
+ * the band alone would miss rows a restore scan wrote, and the contracts
12189
+ * alone would miss indices allocated for something the wallet never
12190
+ * persisted (a swap, an externally issued invoice).
12191
+ */
12192
+ async getUsedSigningDescriptors() {
12193
+ const provider = this._descriptorProvider;
12194
+ const descriptors = /* @__PURE__ */ new Set();
12195
+ if (provider instanceof HDDescriptorProvider) {
12196
+ const lastIndexUsed = await provider.getLastIndexUsed();
12197
+ for (let i = 0; i <= (lastIndexUsed ?? -1); i++) {
12198
+ descriptors.add(provider.materializeDescriptorAt(i));
12199
+ }
12200
+ }
12201
+ for (const contract of await this.contractRepository.getContracts()) {
12202
+ const descriptor = contract.metadata?.signingDescriptor;
12203
+ if (typeof descriptor === "string" && descriptor.length > 0) {
12204
+ descriptors.add(descriptor);
12205
+ }
12206
+ }
12207
+ return [...descriptors].sort(
12208
+ (a, b) => signingDescriptorIndex(a) - signingDescriptorIndex(b)
12209
+ );
12210
+ }
12211
+ /**
12212
+ * @see HDWalletCapable.signerForDescriptor
12213
+ */
12214
+ async signerForDescriptor(descriptor) {
12215
+ const provider = this._descriptorProvider;
12216
+ if (!(provider instanceof HDDescriptorProvider) || !provider.isOurs(descriptor)) {
12217
+ return this.identity;
12218
+ }
12219
+ return new DescriptorIdentity({ descriptor, signer: provider, base: this.identity });
12220
+ }
11948
12221
  /**
11949
12222
  * Mid-session server-signer rotation (plan §4). When arkd rotates its
11950
12223
  * active signer mid-session — the case the long-lived service worker and
@@ -11977,7 +12250,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
11977
12250
  const xonly = toXOnlyPubKey(newServerPubKey);
11978
12251
  let newServerUnrollScript;
11979
12252
  try {
11980
- newServerUnrollScript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(base.hex.decode(checkpointTapscript));
12253
+ newServerUnrollScript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(base.hex.decode(checkpointTapscript));
11981
12254
  } catch (e) {
11982
12255
  throw new Error("Invalid checkpointTapscript from server");
11983
12256
  }
@@ -12005,21 +12278,21 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12005
12278
  const [currentBoardingRow] = await manager.getContracts({
12006
12279
  script: currentBoardingScript
12007
12280
  });
12008
- const newOffchain = this.offchainTapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? new chunkIEMPH7J6_cjs.DelegateVtxo.Script({
12281
+ const newOffchain = this.offchainTapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? new chunkV2TOHHPW_cjs.DelegateVtxo.Script({
12009
12282
  ...this.offchainTapscript.options,
12010
12283
  serverPubKey: xonly
12011
- }) : new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
12284
+ }) : new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
12012
12285
  ...this.offchainTapscript.options,
12013
12286
  serverPubKey: xonly
12014
12287
  });
12015
- const newBoarding = new chunkIEMPH7J6_cjs.DefaultVtxo.Script({
12288
+ const newBoarding = new chunkV2TOHHPW_cjs.DefaultVtxo.Script({
12016
12289
  ...this._boardingTapscript.options,
12017
12290
  serverPubKey: xonly
12018
12291
  });
12019
- const offchainCsv = chunkE7HB3GKK_cjs.timelockToSequence(newOffchain.options.csvTimelock).toString();
12292
+ const offchainCsv = chunkOWCPXRGP_cjs.timelockToSequence(newOffchain.options.csvTimelock).toString();
12020
12293
  const newOffchainScript = base.hex.encode(newOffchain.pkScript);
12021
12294
  const newOffchainAddress = newOffchain.address(this.network.hrp, xonly).encode();
12022
- if (newOffchain instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script) {
12295
+ if (newOffchain instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script) {
12023
12296
  await manager.createContract({
12024
12297
  type: "delegate",
12025
12298
  params: {
@@ -12047,13 +12320,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12047
12320
  metadata: currentOffchainRow?.metadata
12048
12321
  });
12049
12322
  }
12050
- const boardingCsv = newBoarding.options.csvTimelock ?? chunkIEMPH7J6_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
12323
+ const boardingCsv = newBoarding.options.csvTimelock ?? chunkV2TOHHPW_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
12051
12324
  await manager.createContract({
12052
12325
  type: "boarding",
12053
12326
  params: {
12054
12327
  pubKey: base.hex.encode(newBoarding.options.pubKey),
12055
12328
  serverPubKey: base.hex.encode(xonly),
12056
- csvTimelock: chunkE7HB3GKK_cjs.timelockToSequence(boardingCsv).toString()
12329
+ csvTimelock: chunkOWCPXRGP_cjs.timelockToSequence(boardingCsv).toString()
12057
12330
  },
12058
12331
  script: base.hex.encode(newBoarding.pkScript),
12059
12332
  address: newBoarding.address(this.network.hrp, xonly).encode(),
@@ -12086,14 +12359,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12086
12359
  _restoreInFlight;
12087
12360
  _addPendingSpends(inputs) {
12088
12361
  for (const input of inputs) {
12089
- if (chunkE7HB3GKK_cjs.isVirtualCoin(input)) {
12362
+ if (chunkOWCPXRGP_cjs.isVirtualCoin(input)) {
12090
12363
  this._pendingSpendOutpoints.add(`${input.txid}:${input.vout}`);
12091
12364
  }
12092
12365
  }
12093
12366
  }
12094
12367
  _removePendingSpends(inputs) {
12095
12368
  for (const input of inputs) {
12096
- if (chunkE7HB3GKK_cjs.isVirtualCoin(input)) {
12369
+ if (chunkOWCPXRGP_cjs.isVirtualCoin(input)) {
12097
12370
  this._pendingSpendOutpoints.delete(`${input.txid}:${input.vout}`);
12098
12371
  }
12099
12372
  }
@@ -12153,7 +12426,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12153
12426
  const hd = provider instanceof HDDescriptorProvider;
12154
12427
  const staticDescriptor = hd ? void 0 : `tr(${base.hex.encode(await this.identity.xOnlyPublicKey())})`;
12155
12428
  const materialize = (index) => hd ? provider.materializeDescriptorAt(index) : staticDescriptor;
12156
- const delegatePubKey = this.offchainTapscript instanceof chunkIEMPH7J6_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
12429
+ const delegatePubKey = this.offchainTapscript instanceof chunkV2TOHHPW_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
12157
12430
  const arkInfo = await this.arkProvider.getInfo();
12158
12431
  const currentSignerPubKey = toXOnlyPubKey(base.hex.decode(arkInfo.signerPubkey));
12159
12432
  const deprecatedSignerPubKeys = arkInfo.deprecatedSigners.map(
@@ -12172,7 +12445,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12172
12445
  csvTimelocks: this.walletContractTimelocks,
12173
12446
  // Boarding-exit CSV so the boarding handler can build its
12174
12447
  // candidate script (distinct from the unilateral-exit matrix).
12175
- boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunkIEMPH7J6_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
12448
+ boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunkV2TOHHPW_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
12176
12449
  delegatePubKey
12177
12450
  };
12178
12451
  const result = await manager.scanContracts({
@@ -12289,7 +12562,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12289
12562
  let serverUnrollScript;
12290
12563
  try {
12291
12564
  const raw = base.hex.decode(setup.info.checkpointTapscript);
12292
- serverUnrollScript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(raw);
12565
+ serverUnrollScript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(raw);
12293
12566
  } catch (e) {
12294
12567
  throw new Error("Invalid checkpointTapscript from server");
12295
12568
  }
@@ -12427,7 +12700,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12427
12700
  inputs: params.selectedVtxos,
12428
12701
  changeAmount: BigInt(changeAmount)
12429
12702
  };
12430
- const outputAddress = chunkE7HB3GKK_cjs.ArkAddress.decode(params.address);
12703
+ const outputAddress = chunkOWCPXRGP_cjs.ArkAddress.decode(params.address);
12431
12704
  const outputScript = BigInt(params.amount) < this.dustAmount ? outputAddress.subdustPkScript : outputAddress.pkScript;
12432
12705
  const outputs = [
12433
12706
  {
@@ -12480,13 +12753,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12480
12753
  }
12481
12754
  }
12482
12755
  const offchainAddress = await this.getAddress();
12483
- const offchainPkScript = chunkE7HB3GKK_cjs.ArkAddress.decode(offchainAddress).pkScript;
12756
+ const offchainPkScript = chunkOWCPXRGP_cjs.ArkAddress.decode(offchainAddress).pkScript;
12484
12757
  const offchainOutputScript = base.hex.encode(offchainPkScript);
12485
12758
  if (!params) {
12486
12759
  const { fees, vtxoMaxAmount } = await this.arkProvider.getInfo();
12487
12760
  const estimator = new Estimator(fees.intentFee);
12488
12761
  let amount = 0;
12489
- const exitScript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(
12762
+ const exitScript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(
12490
12763
  base.hex.decode(this.boardingTapscript.exitScript)
12491
12764
  );
12492
12765
  const boardingTimelock = exitScript.params.timelock;
@@ -12515,7 +12788,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12515
12788
  if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
12516
12789
  break;
12517
12790
  }
12518
- const inputFee = estimator.evalOffchainInput(chunkE7HB3GKK_cjs.toOffchainInputFeeParams(vtxo));
12791
+ const inputFee = estimator.evalOffchainInput(chunkOWCPXRGP_cjs.toOffchainInputFeeParams(vtxo));
12519
12792
  if (inputFee.satoshis >= vtxo.value) {
12520
12793
  continue;
12521
12794
  }
@@ -12560,7 +12833,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12560
12833
  for (const [index, output] of params.outputs.entries()) {
12561
12834
  let script;
12562
12835
  try {
12563
- const addr = chunkE7HB3GKK_cjs.ArkAddress.decode(output.address);
12836
+ const addr = chunkOWCPXRGP_cjs.ArkAddress.decode(output.address);
12564
12837
  script = addr.pkScript;
12565
12838
  hasOffchainOutputs = true;
12566
12839
  } catch {
@@ -12746,7 +13019,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12746
13019
  async maybeRotateBoardingAfterBoard(inputs) {
12747
13020
  if (!this._descriptorProvider) return;
12748
13021
  const consumedBoarding = inputs.some(
12749
- (input) => typeof input !== "string" && !chunkE7HB3GKK_cjs.isVirtualCoin(input)
13022
+ (input) => typeof input !== "string" && !chunkOWCPXRGP_cjs.isVirtualCoin(input)
12750
13023
  );
12751
13024
  if (!consumedBoarding) return;
12752
13025
  try {
@@ -12755,14 +13028,22 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12755
13028
  console.warn("Failed to rotate boarding address after board", e);
12756
13029
  }
12757
13030
  }
12758
- async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, connectorsGraph) {
13031
+ async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, expectedRecipients, connectorsGraph, validatedCommitmentTxid) {
12759
13032
  const signedForfeits = [];
12760
13033
  let settlementPsbt = btcSigner.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
13034
+ assertFinalCommitmentMatchesValidated(
13035
+ settlementPsbt,
13036
+ validatedCommitmentTxid,
13037
+ "settlement finalization"
13038
+ );
13039
+ if (!validatedCommitmentTxid && expectedRecipients.length > 0) {
13040
+ validateBatchRecipientsWithoutTree(settlementPsbt, expectedRecipients, this.network);
13041
+ }
12761
13042
  let hasBoardingUtxos = false;
12762
13043
  let connectorIndex = 0;
12763
13044
  const connectorsLeaves = connectorsGraph?.leaves() || [];
12764
13045
  for (const input of inputs) {
12765
- if (!chunkE7HB3GKK_cjs.isVirtualCoin(input)) {
13046
+ if (!chunkOWCPXRGP_cjs.isVirtualCoin(input)) {
12766
13047
  for (let i = 0; i < settlementPsbt.inputsLength; i++) {
12767
13048
  const settlementInput = settlementPsbt.getInput(i);
12768
13049
  if (!settlementInput.txid || settlementInput.index === void 0) {
@@ -12793,7 +13074,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12793
13074
  }
12794
13075
  continue;
12795
13076
  }
12796
- if (chunkE7HB3GKK_cjs.canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
13077
+ if (chunkOWCPXRGP_cjs.canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
12797
13078
  continue;
12798
13079
  }
12799
13080
  if (connectorsLeaves.length === 0) {
@@ -12821,7 +13102,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12821
13102
  index: input.vout,
12822
13103
  witnessUtxo: {
12823
13104
  amount: BigInt(input.value),
12824
- script: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript
13105
+ script: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript
12825
13106
  },
12826
13107
  sighashType: btcSigner.SigHash.DEFAULT,
12827
13108
  tapLeafScript: [input.forfeitTapLeafScript]
@@ -12840,7 +13121,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12840
13121
  forfeitTx = await this._signerRouter.sign(forfeitTx, [
12841
13122
  {
12842
13123
  index: 0,
12843
- lookupScript: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript
13124
+ lookupScript: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript
12844
13125
  }
12845
13126
  ]);
12846
13127
  signedForfeits.push(base.base64.encode(forfeitTx.toPSBT()));
@@ -12880,6 +13161,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12880
13161
  */
12881
13162
  createBatchHandler(intentId, inputs, expectedRecipients, session) {
12882
13163
  let sweepTapTreeRoot;
13164
+ let validatedCommitmentTxid;
12883
13165
  return {
12884
13166
  onBatchStarted: async (event) => {
12885
13167
  const utf8IntentId = new TextEncoder().encode(intentId);
@@ -12898,7 +13180,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12898
13180
  if (skip) {
12899
13181
  return { skip };
12900
13182
  }
12901
- const sweepTapscript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.encode({
13183
+ const sweepTapscript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.encode({
12902
13184
  timelock: {
12903
13185
  value: event.batchExpiry,
12904
13186
  type: event.batchExpiry >= 512n ? "seconds" : "blocks"
@@ -12937,6 +13219,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12937
13219
  if (!sharedOutput?.amount) {
12938
13220
  throw new Error("Shared output not found");
12939
13221
  }
13222
+ validatedCommitmentTxid = commitmentTx.id;
12940
13223
  await session.init(vtxoTree, sweepTapTreeRoot, sharedOutput.amount);
12941
13224
  const pubkey = base.hex.encode(await session.getPublicKey());
12942
13225
  const nonces = await session.getNonces();
@@ -12965,7 +13248,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
12965
13248
  event,
12966
13249
  inputs,
12967
13250
  this.forfeitOutputScript,
12968
- connectorTree
13251
+ expectedRecipients,
13252
+ connectorTree,
13253
+ validatedCommitmentTxid
12969
13254
  );
12970
13255
  }
12971
13256
  };
@@ -13004,9 +13289,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13004
13289
  ...existing ?? {},
13005
13290
  intentTxId,
13006
13291
  registerProof: intent.proof,
13007
- registerProofMessage: chunkRNMLFY2V_cjs.Intent.encodeMessage(intent.message),
13292
+ registerProofMessage: chunkOWCPXRGP_cjs.Intent.encodeMessage(intent.message),
13008
13293
  deleteProof: deleteIntent.proof,
13009
- deleteProofMessage: chunkRNMLFY2V_cjs.Intent.encodeMessage(deleteIntent.message),
13294
+ deleteProofMessage: chunkOWCPXRGP_cjs.Intent.encodeMessage(deleteIntent.message),
13010
13295
  intentVtxos: inputs.map((i) => ({
13011
13296
  txid: i.txid,
13012
13297
  vout: i.vout
@@ -13038,7 +13323,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13038
13323
  try {
13039
13324
  return await this.arkProvider.registerIntent(intent);
13040
13325
  } catch (error) {
13041
- if (error instanceof chunkRNMLFY2V_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
13326
+ if (error instanceof chunkOWCPXRGP_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
13042
13327
  const deleteIntent = await this.makeDeleteIntentSignature(inputs);
13043
13328
  await this.arkProvider.deleteIntent(deleteIntent);
13044
13329
  return this.arkProvider.registerIntent(intent);
@@ -13054,7 +13339,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13054
13339
  expire_at: 0,
13055
13340
  cosigners_public_keys: cosignerPubKeys
13056
13341
  };
13057
- const proof = chunkRNMLFY2V_cjs.Intent.create(message, coins, outputs);
13342
+ const proof = chunkOWCPXRGP_cjs.Intent.create(message, coins, outputs);
13058
13343
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
13059
13344
  return {
13060
13345
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -13066,7 +13351,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13066
13351
  type: "delete",
13067
13352
  expire_at: 0
13068
13353
  };
13069
- const proof = chunkRNMLFY2V_cjs.Intent.create(message, coins, []);
13354
+ const proof = chunkOWCPXRGP_cjs.Intent.create(message, coins, []);
13070
13355
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
13071
13356
  return {
13072
13357
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -13078,7 +13363,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13078
13363
  type: "get-pending-tx",
13079
13364
  expire_at: 0
13080
13365
  };
13081
- const proof = chunkRNMLFY2V_cjs.Intent.create(message, coins, []);
13366
+ const proof = chunkOWCPXRGP_cjs.Intent.create(message, coins, []);
13082
13367
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
13083
13368
  return {
13084
13369
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -13099,7 +13384,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13099
13384
  if (!vtxos || vtxos.length === 0) {
13100
13385
  const scriptMap = await this.getScriptMap();
13101
13386
  const allExtended = [];
13102
- const fetchedVtxos = await chunkE7HB3GKK_cjs.getAllNormalizedVtxos(this.indexerProvider, [
13387
+ const fetchedVtxos = await chunkOWCPXRGP_cjs.getAllNormalizedVtxos(this.indexerProvider, [
13103
13388
  ...scriptMap.keys()
13104
13389
  ]);
13105
13390
  for (const vtxo of fetchedVtxos) {
@@ -13124,6 +13409,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13124
13409
  for (let i = 0; i < vtxos.length; i += MAX_INPUTS_PER_INTENT) {
13125
13410
  batches.push(vtxos.slice(i, i + MAX_INPUTS_PER_INTENT));
13126
13411
  }
13412
+ const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
13413
+ const checkpointInputs = vtxos.map((vtxo) => ({
13414
+ ...vtxo,
13415
+ tapLeafScript: vtxo.forfeitTapLeafScript
13416
+ }));
13127
13417
  const seen = /* @__PURE__ */ new Set();
13128
13418
  const results = await Promise.all(
13129
13419
  batches.map(async (batch) => {
@@ -13139,6 +13429,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13139
13429
  const checkpointTxs = pendingTx.signedCheckpointTxs.map(
13140
13430
  (c) => btcSigner.Transaction.fromPSBT(base.base64.decode(c))
13141
13431
  );
13432
+ assertCheckpointsMatchInputs(
13433
+ checkpointTxs,
13434
+ checkpointInputs,
13435
+ unrollCandidates,
13436
+ `pending tx ${pendingTx.arkTxid}`
13437
+ );
13142
13438
  const checkpointJobs = checkpointTxs.map(
13143
13439
  (tx) => this.inputSigningJobsFromWitnessUtxos(tx)
13144
13440
  );
@@ -13194,6 +13490,32 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13194
13490
  }
13195
13491
  return { finalized, pending };
13196
13492
  }
13493
+ /**
13494
+ * The server unroll scripts a pending checkpoint may legitimately have been
13495
+ * built under: this wallet's configured one, the server's current one, and
13496
+ * one per deprecated signer (same closure, deprecated key). A tx submitted
13497
+ * before a signer rotation was built under the old key, so rebuilding
13498
+ * against the current key alone would leave it pending forever.
13499
+ */
13500
+ checkpointUnrollCandidates(info) {
13501
+ const current = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
13502
+ const candidates = [this._serverUnrollScript, current];
13503
+ for (const deprecated of signerSetFromInfo(info).deprecated.keys()) {
13504
+ candidates.push(
13505
+ chunkOWCPXRGP_cjs.CSVMultisigTapscript.encode({
13506
+ ...current.params,
13507
+ pubkeys: [base.hex.decode(deprecated)]
13508
+ })
13509
+ );
13510
+ }
13511
+ const seen = /* @__PURE__ */ new Set();
13512
+ return candidates.filter((candidate) => {
13513
+ const script = base.hex.encode(candidate.script);
13514
+ if (seen.has(script)) return false;
13515
+ seen.add(script);
13516
+ return true;
13517
+ });
13518
+ }
13197
13519
  async hasPendingTxFlag() {
13198
13520
  const state = await this.walletRepository.getWalletState();
13199
13521
  return state?.settings?.hasPendingTx === true;
@@ -13271,7 +13593,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13271
13593
  if (vtxos.length === 0) {
13272
13594
  throw new Error("No VTXOs found for this arkadeCash");
13273
13595
  }
13274
- const myPkScript = chunkE7HB3GKK_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
13596
+ const myPkScript = chunkOWCPXRGP_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
13275
13597
  let { spendable, unclaimed } = this.classifyCashVtxos(vtxos);
13276
13598
  let swept = 0;
13277
13599
  const drainable = vtxos.filter((vtxo) => !isSubdust(vtxo, this.dustAmount));
@@ -13298,7 +13620,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13298
13620
  }
13299
13621
  if (spendable.length > 0) {
13300
13622
  const info = await this.arkProvider.getInfo();
13301
- const serverUnrollScript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(
13623
+ const serverUnrollScript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(
13302
13624
  base.hex.decode(info.checkpointTapscript)
13303
13625
  );
13304
13626
  for (const vtxo of spendable) {
@@ -13344,7 +13666,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13344
13666
  const spendable = [];
13345
13667
  const unclaimed = [];
13346
13668
  for (const vtxo of vtxos) {
13347
- if (chunkE7HB3GKK_cjs.hasTerminalSpend(vtxo)) {
13669
+ if (chunkOWCPXRGP_cjs.hasTerminalSpend(vtxo)) {
13348
13670
  unclaimed.push(cashReport(vtxo, "already-spent"));
13349
13671
  } else if (isSubdust(vtxo, this.dustAmount)) {
13350
13672
  unclaimed.push(cashReport(vtxo, "subdust"));
@@ -13364,7 +13686,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13364
13686
  const all = [];
13365
13687
  const seen = /* @__PURE__ */ new Set();
13366
13688
  for (let pageIndex = 0; ; pageIndex++) {
13367
- const { vtxos, page } = await chunkE7HB3GKK_cjs.getNormalizedVtxos(this.indexerProvider, {
13689
+ const { vtxos, page } = await chunkOWCPXRGP_cjs.getNormalizedVtxos(this.indexerProvider, {
13368
13690
  scripts,
13369
13691
  pageIndex,
13370
13692
  pageSize
@@ -13411,7 +13733,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13411
13733
  for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_INTENT) {
13412
13734
  const batch = inputs.slice(i, i + MAX_INPUTS_PER_INTENT);
13413
13735
  const message = { type: "get-pending-tx", expire_at: 0 };
13414
- const proof = chunkRNMLFY2V_cjs.Intent.create(message, batch, []);
13736
+ const proof = chunkOWCPXRGP_cjs.Intent.create(message, batch, []);
13415
13737
  const signedProof = await identity.sign(
13416
13738
  proof,
13417
13739
  Array.from({ length: batch.length + 1 }, (_, j) => j)
@@ -13426,12 +13748,23 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13426
13748
  pendingTxs.push(pendingTx);
13427
13749
  }
13428
13750
  }
13751
+ if (pendingTxs.length === 0) return result;
13429
13752
  const myPkScriptHex = base.hex.encode(myPkScript);
13753
+ const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
13430
13754
  for (const pendingTx of pendingTxs) {
13431
13755
  try {
13432
13756
  const checkpointTxs = pendingTx.signedCheckpointTxs.map(
13433
13757
  (checkpoint) => btcSigner.Transaction.fromPSBT(base.base64.decode(checkpoint))
13434
13758
  );
13759
+ assertCheckpointsMatchInputs(
13760
+ checkpointTxs,
13761
+ inputs.map((input) => ({
13762
+ ...input,
13763
+ tapLeafScript: input.forfeitTapLeafScript
13764
+ })),
13765
+ unrollCandidates,
13766
+ `pending arkadeCash tx ${pendingTx.arkTxid}`
13767
+ );
13435
13768
  const finalCheckpoints = await Promise.all(
13436
13769
  checkpointTxs.map(
13437
13770
  async (checkpoint) => base.base64.encode((await identity.sign(checkpoint)).toPSBT())
@@ -13706,10 +14039,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13706
14039
  const serverPubKey = this.arkServerPublicKey;
13707
14040
  const serverUnrollScript = this.serverUnrollScript;
13708
14041
  const arkAddress = offchainTapscript.address(this.network.hrp, serverPubKey);
13709
- const normalizedInputs = inputs.map(chunkE7HB3GKK_cjs.normalizeVtxo);
13710
- const at = now ?? await chunkE7HB3GKK_cjs.resolveTimeHeight(this.onchainProvider);
14042
+ const normalizedInputs = inputs.map(chunkOWCPXRGP_cjs.normalizeVtxo);
14043
+ const at = now ?? await chunkOWCPXRGP_cjs.resolveTimeHeight(this.onchainProvider);
13711
14044
  for (const input of normalizedInputs) {
13712
- if (!chunkE7HB3GKK_cjs.canSpendOffchain(input, at)) {
14045
+ if (!chunkOWCPXRGP_cjs.canSpendOffchain(input, at)) {
13713
14046
  throw new Error(
13714
14047
  `sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} is not cooperatively spendable`
13715
14048
  );
@@ -13774,7 +14107,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13774
14107
  );
13775
14108
  const arkTxJobs = inputs.map((input, index) => ({
13776
14109
  index,
13777
- lookupScript: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript
14110
+ lookupScript: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript
13778
14111
  }));
13779
14112
  const identity = this.identity;
13780
14113
  const signer = {
@@ -13841,32 +14174,33 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13841
14174
  `updateDbAfterOffchainTx: inputs length (${inputs.length}) differs from signedCheckpointTxs length (${signedCheckpointTxs.length})`
13842
14175
  );
13843
14176
  }
13844
- const safeLength = Math.min(inputs.length, signedCheckpointTxs.length);
14177
+ const checkpointIdByOutpoint = /* @__PURE__ */ new Map();
14178
+ for (const encoded of signedCheckpointTxs) {
14179
+ const checkpoint = btcSigner.Transaction.fromPSBT(base.base64.decode(encoded));
14180
+ for (let i = 0; i < checkpoint.inputsLength; i++) {
14181
+ const input = checkpoint.getInput(i);
14182
+ if (!input.txid) continue;
14183
+ checkpointIdByOutpoint.set(
14184
+ `${base.hex.encode(input.txid)}:${input.index}`,
14185
+ checkpoint.id
14186
+ );
14187
+ }
14188
+ }
13845
14189
  const cm = await this.getContractManager();
13846
14190
  const annotatedInputs = await cm.annotateVtxos(inputs);
13847
- for (const [inputIndex, vtxo] of annotatedInputs.entries()) {
14191
+ for (const vtxo of annotatedInputs) {
13848
14192
  const spentFacts = { ...vtxo, isSpent: true };
13849
- if (inputIndex < safeLength && signedCheckpointTxs[inputIndex]) {
13850
- const checkpoint = btcSigner.Transaction.fromPSBT(
13851
- base.base64.decode(signedCheckpointTxs[inputIndex])
13852
- );
13853
- spentVtxos.push({
13854
- ...spentFacts,
13855
- virtualStatus: chunkE7HB3GKK_cjs.toVirtualStatus(spentFacts),
13856
- spentBy: checkpoint.id,
13857
- arkTxId: arkTxid
13858
- });
13859
- } else {
13860
- spentVtxos.push({
13861
- ...spentFacts,
13862
- virtualStatus: chunkE7HB3GKK_cjs.toVirtualStatus(spentFacts),
13863
- arkTxId: arkTxid
13864
- });
13865
- }
14193
+ const spentBy = checkpointIdByOutpoint.get(`${vtxo.txid}:${vtxo.vout}`);
14194
+ spentVtxos.push({
14195
+ ...spentFacts,
14196
+ virtualStatus: chunkOWCPXRGP_cjs.toVirtualStatus(spentFacts),
14197
+ ...spentBy ? { spentBy } : {},
14198
+ arkTxId: arkTxid
14199
+ });
13866
14200
  for (const id of vtxo.commitmentTxIds) {
13867
14201
  commitmentTxIds.add(id);
13868
14202
  }
13869
- const vtxoExpiry = chunkE7HB3GKK_cjs.toBatchExpiry(vtxo);
14203
+ const vtxoExpiry = chunkOWCPXRGP_cjs.toBatchExpiry(vtxo);
13870
14204
  if (vtxoExpiry) {
13871
14205
  batchExpiry = Math.min(batchExpiry, vtxoExpiry);
13872
14206
  }
@@ -13879,7 +14213,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13879
14213
  isSwept: false,
13880
14214
  isPreconfirmed: true,
13881
14215
  commitmentTxIds: Array.from(commitmentTxIds),
13882
- ...chunkE7HB3GKK_cjs.parseLegacyExpiry(batchExpiry)
14216
+ ...chunkOWCPXRGP_cjs.parseLegacyExpiry(batchExpiry)
13883
14217
  };
13884
14218
  changeVtxo = {
13885
14219
  txid: arkTxid,
@@ -13891,7 +14225,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13891
14225
  tapTree: offchainTapscript.encode(),
13892
14226
  value: Number(changeAmount),
13893
14227
  ...changeFacts,
13894
- virtualStatus: chunkE7HB3GKK_cjs.toVirtualStatus(changeFacts),
14228
+ virtualStatus: chunkOWCPXRGP_cjs.toVirtualStatus(changeFacts),
13895
14229
  spentBy: "",
13896
14230
  status: {
13897
14231
  confirmed: false
@@ -13960,12 +14294,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13960
14294
  const spentVtxos = [];
13961
14295
  const inputArkTxIds = /* @__PURE__ */ new Set();
13962
14296
  const boardingRemovalsByAddress = /* @__PURE__ */ new Map();
13963
- const vtxoInputs = inputs.filter(chunkE7HB3GKK_cjs.isVirtualCoin);
14297
+ const vtxoInputs = inputs.filter(chunkOWCPXRGP_cjs.isVirtualCoin);
13964
14298
  const cm = await this.getContractManager();
13965
14299
  const annotatedVtxos = await cm.annotateVtxos(vtxoInputs);
13966
14300
  const annotatedByKey = new Map(annotatedVtxos.map((v) => [`${v.txid}:${v.vout}`, v]));
13967
14301
  for (const input of inputs) {
13968
- if (chunkE7HB3GKK_cjs.isVirtualCoin(input)) {
14302
+ if (chunkOWCPXRGP_cjs.isVirtualCoin(input)) {
13969
14303
  const outpoint = `${input.txid}:${input.vout}`;
13970
14304
  const vtxo = annotatedByKey.get(outpoint);
13971
14305
  if (!vtxo) {
@@ -13977,13 +14311,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13977
14311
  const settledFacts = { ...vtxo, isSpent: true };
13978
14312
  spentVtxos.push({
13979
14313
  ...settledFacts,
13980
- virtualStatus: chunkE7HB3GKK_cjs.toVirtualStatus(settledFacts),
14314
+ virtualStatus: chunkOWCPXRGP_cjs.toVirtualStatus(settledFacts),
13981
14315
  settledBy: commitmentTxid
13982
14316
  });
13983
14317
  } else {
13984
14318
  let sourceAddress;
13985
14319
  try {
13986
- sourceAddress = chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
14320
+ sourceAddress = chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
13987
14321
  this.network
13988
14322
  );
13989
14323
  } catch {
@@ -14041,9 +14375,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14041
14375
  }
14042
14376
  };
14043
14377
  function selectVirtualCoins(coins, targetAmount) {
14044
- const sortedCoins = coins.map(chunkE7HB3GKK_cjs.normalizeVtxo).sort((a, b) => {
14045
- const expiryA = chunkE7HB3GKK_cjs.toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
14046
- const expiryB = chunkE7HB3GKK_cjs.toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
14378
+ const sortedCoins = coins.map(chunkOWCPXRGP_cjs.normalizeVtxo).sort((a, b) => {
14379
+ const expiryA = chunkOWCPXRGP_cjs.toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
14380
+ const expiryB = chunkOWCPXRGP_cjs.toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
14047
14381
  if (expiryA !== expiryB) {
14048
14382
  return expiryA - expiryB;
14049
14383
  }
@@ -14300,7 +14634,7 @@ var MessageBus = class {
14300
14634
  this.initialized = true;
14301
14635
  }
14302
14636
  async buildServices(config) {
14303
- const arkProvider = new chunkRNMLFY2V_cjs.RestArkProvider(config.arkServer.url);
14637
+ const arkProvider = new chunkOWCPXRGP_cjs.RestArkProvider(config.arkServer.url);
14304
14638
  const storage = {
14305
14639
  walletRepository: this.walletRepository,
14306
14640
  contractRepository: this.contractRepository
@@ -14629,6 +14963,25 @@ var DustChangeError = class extends Error {
14629
14963
  this.dustAmount = dustAmount;
14630
14964
  }
14631
14965
  };
14966
+ var offboardNetworkNames = [
14967
+ "bitcoin",
14968
+ "regtest",
14969
+ "testnet",
14970
+ "signet",
14971
+ "mutinynet"
14972
+ ];
14973
+ function offboardDestinationScript(destinationAddress) {
14974
+ for (const networkName of offboardNetworkNames) {
14975
+ try {
14976
+ const network = chunkOWCPXRGP_cjs.networks[networkName];
14977
+ const addr = btcSigner.Address(network).decode(destinationAddress);
14978
+ return btcSigner.OutScript.encode(addr);
14979
+ } catch {
14980
+ continue;
14981
+ }
14982
+ }
14983
+ throw new Error(`Failed to decode destination address: ${destinationAddress}`);
14984
+ }
14632
14985
  var Ramps = class {
14633
14986
  /**
14634
14987
  * Create convenience wrappers for onboarding and offboarding flows.
@@ -14684,7 +15037,7 @@ var Ramps = class {
14684
15037
  }
14685
15038
  amount = amount ?? totalAmount;
14686
15039
  const offchainAddress = await this.wallet.getAddress();
14687
- const offchainAddr = chunkE7HB3GKK_cjs.ArkAddress.decode(offchainAddress);
15040
+ const offchainAddr = chunkOWCPXRGP_cjs.ArkAddress.decode(offchainAddress);
14688
15041
  const offchainScript = base.hex.encode(offchainAddr.pkScript);
14689
15042
  const outputFee = estimator.evalOffchainOutput({
14690
15043
  amount,
@@ -14744,7 +15097,7 @@ var Ramps = class {
14744
15097
  const filteredVtxos = [];
14745
15098
  let totalAmount = 0n;
14746
15099
  for (const vtxo of vtxos) {
14747
- const inputFee = estimator.evalOffchainInput(chunkE7HB3GKK_cjs.toOffchainInputFeeParams(vtxo));
15100
+ const inputFee = estimator.evalOffchainInput(chunkOWCPXRGP_cjs.toOffchainInputFeeParams(vtxo));
14748
15101
  if (inputFee.satoshis >= vtxo.value) {
14749
15102
  continue;
14750
15103
  }
@@ -14766,27 +15119,7 @@ var Ramps = class {
14766
15119
  throw new DustChangeError(change, dustAmount);
14767
15120
  }
14768
15121
  amount = amount ?? totalAmount;
14769
- const networkNames = [
14770
- "bitcoin",
14771
- "regtest",
14772
- "testnet",
14773
- "signet",
14774
- "mutinynet"
14775
- ];
14776
- let destinationScript;
14777
- for (const networkName of networkNames) {
14778
- try {
14779
- const network = chunkE7HB3GKK_cjs.networks[networkName];
14780
- const addr = btcSigner.Address(network).decode(destinationAddress);
14781
- destinationScript = btcSigner.OutScript.encode(addr);
14782
- break;
14783
- } catch {
14784
- continue;
14785
- }
14786
- }
14787
- if (!destinationScript) {
14788
- throw new Error(`Failed to decode destination address: ${destinationAddress}`);
14789
- }
15122
+ const destinationScript = offboardDestinationScript(destinationAddress);
14790
15123
  const outputFee = estimator.evalOnchainOutput({
14791
15124
  amount,
14792
15125
  script: base.hex.encode(destinationScript)
@@ -15461,7 +15794,7 @@ var WalletMessageHandler = class {
15461
15794
  // Wallet methods
15462
15795
  async handleInitWallet({ payload }) {
15463
15796
  const { arkServerUrl } = payload;
15464
- this.indexerProvider = new chunkRNMLFY2V_cjs.RestIndexerProvider(arkServerUrl);
15797
+ this.indexerProvider = new chunkG7DOBFQN_cjs.RestIndexerProvider(arkServerUrl);
15465
15798
  await this.onWalletInitialized();
15466
15799
  }
15467
15800
  async handleGetBalance() {
@@ -15485,12 +15818,12 @@ var WalletMessageHandler = class {
15485
15818
  let recoverable = 0;
15486
15819
  let pendingRecovery = 0;
15487
15820
  for (const vtxo of allVtxos) {
15488
- if (chunkE7HB3GKK_cjs.hasTerminalSpend(vtxo)) continue;
15821
+ if (chunkOWCPXRGP_cjs.hasTerminalSpend(vtxo)) continue;
15489
15822
  if (pendingOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
15490
15823
  pendingRecovery += vtxo.value;
15491
- } else if (chunkE7HB3GKK_cjs.canRecoverOnchain(vtxo, now)) {
15824
+ } else if (chunkOWCPXRGP_cjs.canRecoverOnchain(vtxo, now)) {
15492
15825
  recoverable += vtxo.value;
15493
- } else if (chunkE7HB3GKK_cjs.canSpendOffchain(vtxo, now)) {
15826
+ } else if (chunkOWCPXRGP_cjs.canSpendOffchain(vtxo, now)) {
15494
15827
  if (vtxo.isPreconfirmed) {
15495
15828
  preconfirmed += vtxo.value;
15496
15829
  } else {
@@ -15502,7 +15835,7 @@ var WalletMessageHandler = class {
15502
15835
  const totalOffchain = settled + preconfirmed + recoverable + pendingRecovery;
15503
15836
  const assetBalances = /* @__PURE__ */ new Map();
15504
15837
  for (const vtxo of allVtxos) {
15505
- if (chunkE7HB3GKK_cjs.hasTerminalSpend(vtxo)) continue;
15838
+ if (chunkOWCPXRGP_cjs.hasTerminalSpend(vtxo)) continue;
15506
15839
  if (vtxo.assets) {
15507
15840
  for (const a of vtxo.assets) {
15508
15841
  const current = assetBalances.get(a.assetId) ?? 0n;
@@ -15538,7 +15871,7 @@ var WalletMessageHandler = class {
15538
15871
  */
15539
15872
  async getSpendableVtxos() {
15540
15873
  const vtxos = await this.getVtxosFromRepo();
15541
- return vtxos.filter((v) => !chunkE7HB3GKK_cjs.hasTerminalSpend(v));
15874
+ return vtxos.filter((v) => !chunkOWCPXRGP_cjs.hasTerminalSpend(v));
15542
15875
  }
15543
15876
  async onWalletInitialized() {
15544
15877
  if (!this.readonlyWallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
@@ -15750,10 +16083,10 @@ var WalletMessageHandler = class {
15750
16083
  if (dustAmount != null && isSubdust(v, dustAmount)) {
15751
16084
  return false;
15752
16085
  }
15753
- if (chunkE7HB3GKK_cjs.isRecoverable(v)) {
16086
+ if (chunkOWCPXRGP_cjs.isRecoverable(v)) {
15754
16087
  return false;
15755
16088
  }
15756
- if (chunkE7HB3GKK_cjs.isExpired(v)) {
16089
+ if (chunkOWCPXRGP_cjs.isExpired(v)) {
15757
16090
  return false;
15758
16091
  }
15759
16092
  return true;
@@ -15818,47 +16151,15 @@ var WalletMessageHandler = class {
15818
16151
  return allVtxos;
15819
16152
  }
15820
16153
  /**
15821
- * Build transaction history from cached virtual outputs without hitting the indexer.
15822
- * Falls back to indexer only for uncached transaction timestamps.
16154
+ * Build transaction history from cached virtual outputs, hitting the indexer only for
16155
+ * uncached timestamps. Best-effort, like the plain Wallet path.
15823
16156
  */
15824
16157
  async buildTransactionHistoryFromCache(vtxos) {
15825
16158
  if (!this.readonlyWallet) return null;
15826
16159
  const { boardingTxs, commitmentsToIgnore } = await this.readonlyWallet.getBoardingTxs();
15827
- const vtxoCreatedAt = /* @__PURE__ */ new Map();
15828
- for (const vtxo of vtxos) {
15829
- const existing = vtxoCreatedAt.get(vtxo.txid);
15830
- const ts = vtxo.createdAt.getTime();
15831
- if (existing === void 0 || ts < existing) {
15832
- vtxoCreatedAt.set(vtxo.txid, ts);
15833
- }
15834
- }
15835
- if (this.indexerProvider) {
15836
- const uncachedTxids = /* @__PURE__ */ new Set();
15837
- for (const vtxo of vtxos) {
15838
- if (vtxo.isSpent && vtxo.arkTxId && !vtxoCreatedAt.has(vtxo.arkTxId) && !vtxos.some((v) => v.txid === vtxo.arkTxId)) {
15839
- uncachedTxids.add(vtxo.arkTxId);
15840
- }
15841
- }
15842
- if (uncachedTxids.size > 0) {
15843
- const outpoints = [...uncachedTxids].map((txid) => ({
15844
- txid,
15845
- vout: 0
15846
- }));
15847
- const BATCH_SIZE = 100;
15848
- for (let i = 0; i < outpoints.length; i += BATCH_SIZE) {
15849
- const res = await chunkE7HB3GKK_cjs.getNormalizedVtxos(this.indexerProvider, {
15850
- outpoints: outpoints.slice(i, i + BATCH_SIZE)
15851
- });
15852
- for (const v of res.vtxos) {
15853
- vtxoCreatedAt.set(v.txid, v.createdAt.getTime());
15854
- }
15855
- }
15856
- }
15857
- }
15858
- const getTxCreatedAt = async (txid) => {
15859
- return vtxoCreatedAt.get(txid);
15860
- };
15861
- return buildTransactionHistory(vtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
16160
+ const indexerProvider = this.indexerProvider;
16161
+ const resolveTxCreatedAt = indexerProvider ? (txids) => chunkOWCPXRGP_cjs.fetchVtxoCreatedAtByTxid(indexerProvider, txids) : void 0;
16162
+ return buildTransactionHistory(vtxos, boardingTxs, commitmentsToIgnore, resolveTxCreatedAt);
15862
16163
  }
15863
16164
  async ensureContractEventBroadcasting() {
15864
16165
  if (!this.readonlyWallet) return;
@@ -16542,7 +16843,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
16542
16843
  };
16543
16844
  try {
16544
16845
  const response = await this.sendMessage(message);
16545
- return response.payload.vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo);
16846
+ return response.payload.vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo);
16546
16847
  } catch (error) {
16547
16848
  throw new Error(`Failed to get vtxos: ${error}`);
16548
16849
  }
@@ -16655,7 +16956,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
16655
16956
  };
16656
16957
  try {
16657
16958
  const response = await sendContractMessage(message);
16658
- return response.payload.vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo);
16959
+ return response.payload.vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo);
16659
16960
  } catch (e) {
16660
16961
  throw new Error("Failed to annotate vtxos");
16661
16962
  }
@@ -17109,7 +17410,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
17109
17410
  };
17110
17411
  try {
17111
17412
  const response = await wallet.sendMessage(message);
17112
- return response.payload.vtxos.map(chunkE7HB3GKK_cjs.normalizeVtxo);
17413
+ return response.payload.vtxos.map(chunkOWCPXRGP_cjs.normalizeVtxo);
17113
17414
  } catch (e) {
17114
17415
  throw new Error(`Failed to get expiring vtxos: ${e}`);
17115
17416
  }
@@ -17221,12 +17522,12 @@ var OnchainWallet = class _OnchainWallet {
17221
17522
  * @returns Configured onchain wallet
17222
17523
  * @throws Error if the configured identity cannot produce a valid x-only public key
17223
17524
  */
17224
- static async create(identity, networkName = chunkE7HB3GKK_cjs.DEFAULT_NETWORK_NAME, provider) {
17525
+ static async create(identity, networkName = chunkOWCPXRGP_cjs.DEFAULT_NETWORK_NAME, provider) {
17225
17526
  const pubkey = await identity.xOnlyPublicKey();
17226
17527
  if (!pubkey) {
17227
17528
  throw new Error("Invalid configured public key");
17228
17529
  }
17229
- const network = chunkE7HB3GKK_cjs.getNetwork(networkName);
17530
+ const network = chunkOWCPXRGP_cjs.getNetwork(networkName);
17230
17531
  const onchainProvider = provider || new EsploraProvider(ESPLORA_URL[networkName]);
17231
17532
  const onchainP2TR = btcSigner.p2tr(pubkey, void 0, network);
17232
17533
  return new _OnchainWallet(identity, network, onchainP2TR, onchainProvider);
@@ -17332,7 +17633,7 @@ var OnchainWallet = class _OnchainWallet {
17332
17633
  if (!inputs) {
17333
17634
  throw new Error("Fee estimation failed");
17334
17635
  }
17335
- let tx = new chunkRNMLFY2V_cjs.Transaction();
17636
+ let tx = new chunkOWCPXRGP_cjs.Transaction();
17336
17637
  for (const input of inputs) {
17337
17638
  tx.addInput({
17338
17639
  txid: input.txid,
@@ -17390,7 +17691,7 @@ var OnchainWallet = class _OnchainWallet {
17390
17691
  * @throws If the parent has no anchor, or funding cannot be selected/signed
17391
17692
  */
17392
17693
  async bumpAnchor(parentHex, feeRate) {
17393
- const parent = chunkRNMLFY2V_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
17694
+ const parent = chunkOWCPXRGP_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
17394
17695
  const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
17395
17696
  const child = await this.buildBumpPackage(parent, feeRate, coins);
17396
17697
  return [parent.hex, child.hex];
@@ -18155,7 +18456,7 @@ exports.BIP322 = void 0;
18155
18456
  async function sign2(message, identity, network) {
18156
18457
  const xOnlyPubKey = await identity.xOnlyPublicKey();
18157
18458
  const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
18158
- const toSpend = chunkRNMLFY2V_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
18459
+ const toSpend = chunkOWCPXRGP_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
18159
18460
  const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
18160
18461
  const signed = await identity.sign(toSign, [0]);
18161
18462
  signed.finalizeIdx(0);
@@ -18213,7 +18514,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
18213
18514
  if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
18214
18515
  return false;
18215
18516
  }
18216
- const toSpend = chunkRNMLFY2V_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
18517
+ const toSpend = chunkOWCPXRGP_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
18217
18518
  const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
18218
18519
  const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
18219
18520
  const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
@@ -18234,7 +18535,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
18234
18535
  }
18235
18536
  const sighashType = sigWithHash[sigWithHash.length - 1];
18236
18537
  const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
18237
- const toSpend = chunkRNMLFY2V_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
18538
+ const toSpend = chunkOWCPXRGP_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
18238
18539
  const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
18239
18540
  const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
18240
18541
  const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
@@ -18287,7 +18588,7 @@ function encodeCompactSize(n) {
18287
18588
  return buf;
18288
18589
  }
18289
18590
  function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
18290
- const tx = new chunkRNMLFY2V_cjs.Transaction({ version: 0 });
18591
+ const tx = new chunkOWCPXRGP_cjs.Transaction({ version: 0 });
18291
18592
  tx.addInput({
18292
18593
  txid: toSpend.id,
18293
18594
  index: 0,
@@ -18301,12 +18602,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
18301
18602
  });
18302
18603
  tx.addOutput({
18303
18604
  amount: 0n,
18304
- script: chunkRNMLFY2V_cjs.OP_RETURN_EMPTY_PKSCRIPT
18605
+ script: chunkOWCPXRGP_cjs.OP_RETURN_EMPTY_PKSCRIPT
18305
18606
  });
18306
18607
  return tx;
18307
18608
  }
18308
18609
  function craftBIP322ToSignSimple(toSpend, pkScript) {
18309
- const tx = new chunkRNMLFY2V_cjs.Transaction({ version: 0 });
18610
+ const tx = new chunkOWCPXRGP_cjs.Transaction({ version: 0 });
18310
18611
  tx.addInput({
18311
18612
  txid: toSpend.id,
18312
18613
  index: 0,
@@ -18318,7 +18619,7 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
18318
18619
  });
18319
18620
  tx.addOutput({
18320
18621
  amount: 0n,
18321
- script: chunkRNMLFY2V_cjs.OP_RETURN_EMPTY_PKSCRIPT
18622
+ script: chunkOWCPXRGP_cjs.OP_RETURN_EMPTY_PKSCRIPT
18322
18623
  });
18323
18624
  return tx;
18324
18625
  }
@@ -18449,7 +18750,7 @@ var RestEmulatorProvider = class {
18449
18750
  }
18450
18751
  };
18451
18752
  function finalizeVirtualTx(type, psbtBase64) {
18452
- const tx = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
18753
+ const tx = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
18453
18754
  if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
18454
18755
  const input = tx.getInput(0);
18455
18756
  if (!input) {
@@ -18476,14 +18777,14 @@ var ExitPathError = class extends Error {
18476
18777
  reason;
18477
18778
  };
18478
18779
  function delayWeight(sequence) {
18479
- const t = chunkE7HB3GKK_cjs.sequenceToTimelock(sequence);
18780
+ const t = chunkOWCPXRGP_cjs.sequenceToTimelock(sequence);
18480
18781
  return t.type === "blocks" ? Number(t.value) : Number(t.value) / 600;
18481
18782
  }
18482
18783
  async function resolveUnilateralPath(params) {
18483
18784
  const { vtxo, scriptHex, contractRepository } = params;
18484
18785
  const contract = contractRepository ? (await contractRepository.getContracts({ script: scriptHex }))[0] : void 0;
18485
18786
  if (contract) {
18486
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
18787
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
18487
18788
  if (!handler) {
18488
18789
  throw new ExitPathError(
18489
18790
  "no-handler",
@@ -18506,12 +18807,12 @@ async function resolveUnilateralPath(params) {
18506
18807
  paths.sort((a, b) => delayWeight(a.sequence) - delayWeight(b.sequence));
18507
18808
  return { selection: paths[0], label: `${contract.type}:unilateral` };
18508
18809
  }
18509
- const decoded = chunkE7HB3GKK_cjs.VtxoScript.decode(vtxo.tapTree);
18810
+ const decoded = chunkOWCPXRGP_cjs.VtxoScript.decode(vtxo.tapTree);
18510
18811
  let best;
18511
18812
  for (const exit of decoded.exitPaths()) {
18512
18813
  const leaf = decoded.findLeaf(base.hex.encode(exit.script));
18513
18814
  if (!leaf) continue;
18514
- const sequence = chunkE7HB3GKK_cjs.timelockToSequence(exit.params.timelock);
18815
+ const sequence = chunkOWCPXRGP_cjs.timelockToSequence(exit.params.timelock);
18515
18816
  const weight = delayWeight(sequence);
18516
18817
  if (!best || weight < best.weight) {
18517
18818
  best = { selection: { leaf, sequence }, weight };
@@ -18697,14 +18998,14 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
18697
18998
  }
18698
18999
  const resolved = await resolveUnilateralPath({
18699
19000
  vtxo,
18700
- scriptHex: base.hex.encode(chunkE7HB3GKK_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
19001
+ scriptHex: base.hex.encode(chunkOWCPXRGP_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
18701
19002
  contractRepository: wallet.contractRepository,
18702
19003
  walletPubKeyHex: base.hex.encode(await wallet.identity.xOnlyPublicKey()),
18703
19004
  currentTime: Date.now()
18704
19005
  });
18705
19006
  const spendingLeaf = resolved.selection.leaf;
18706
19007
  const sequence = resolved.selection.sequence;
18707
- const timelock = chunkE7HB3GKK_cjs.sequenceToTimelock(sequence);
19008
+ const timelock = chunkOWCPXRGP_cjs.sequenceToTimelock(sequence);
18708
19009
  const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
18709
19010
  if (!elapsed) {
18710
19011
  throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
@@ -18717,7 +19018,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
18717
19018
  sequence,
18718
19019
  witnessUtxo: {
18719
19020
  amount: BigInt(vtxo.value),
18720
- script: chunkE7HB3GKK_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
19021
+ script: chunkOWCPXRGP_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
18721
19022
  },
18722
19023
  sighashType: btcSigner.SigHash.DEFAULT
18723
19024
  });
@@ -18727,7 +19028,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
18727
19028
  btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
18728
19029
  );
18729
19030
  }
18730
- const tx = new chunkRNMLFY2V_cjs.Transaction({ version: 2 });
19031
+ const tx = new chunkOWCPXRGP_cjs.Transaction({ version: 2 });
18731
19032
  for (const input of inputs) {
18732
19033
  tx.addInput(input);
18733
19034
  }
@@ -18794,7 +19095,7 @@ async function buildSignedSweep(params) {
18794
19095
  `uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
18795
19096
  );
18796
19097
  }
18797
- const tx = new chunkRNMLFY2V_cjs.Transaction({ version: 2 });
19098
+ const tx = new chunkOWCPXRGP_cjs.Transaction({ version: 2 });
18798
19099
  tx.addInput({
18799
19100
  txid: vtxo.txid,
18800
19101
  index: vtxo.vout,
@@ -18819,7 +19120,7 @@ async function buildSignedSweep(params) {
18819
19120
  finalScriptWitness: [
18820
19121
  tapScriptSig[0][1],
18821
19122
  ...path.extraWitness,
18822
- chunkE7HB3GKK_cjs.scriptFromTapLeafScript(path.leaf),
19123
+ chunkOWCPXRGP_cjs.scriptFromTapLeafScript(path.leaf),
18823
19124
  btcSigner.TaprootControlBlock.encode(controlBlock)
18824
19125
  ]
18825
19126
  });
@@ -18849,7 +19150,7 @@ async function resolveFeeRate(opts) {
18849
19150
  }
18850
19151
  async function selectExitVtxos(opts) {
18851
19152
  if (!opts.vtxos) return opts.wallet.getVtxos();
18852
- const res = await chunkE7HB3GKK_cjs.getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
19153
+ const res = await chunkOWCPXRGP_cjs.getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
18853
19154
  const tapTrees = /* @__PURE__ */ new Map();
18854
19155
  const out = [];
18855
19156
  for (const vtxo of res.vtxos) {
@@ -18864,7 +19165,7 @@ async function selectExitVtxos(opts) {
18864
19165
  `no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
18865
19166
  );
18866
19167
  }
18867
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(contract.type);
19168
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(contract.type);
18868
19169
  if (!handler) {
18869
19170
  throw new Error(`no contract handler registered for type '${contract.type}'`);
18870
19171
  }
@@ -18894,7 +19195,7 @@ async function computeExitLayout(opts, feeRate) {
18894
19195
  if (pendingNodes.length > 0) {
18895
19196
  const txs = await resolver.getVirtualTxs(pendingNodes.map((n) => n.txid));
18896
19197
  for (const psbt of txs) {
18897
- psbts.set(chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
19198
+ psbts.set(chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
18898
19199
  }
18899
19200
  }
18900
19201
  const childVsize = Number(
@@ -18930,7 +19231,7 @@ async function computeExitLayout(opts, feeRate) {
18930
19231
  try {
18931
19232
  const resolved = await resolveUnilateralPath({
18932
19233
  vtxo,
18933
- scriptHex: base.hex.encode(chunkE7HB3GKK_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
19234
+ scriptHex: base.hex.encode(chunkOWCPXRGP_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
18934
19235
  contractRepository: wallet.contractRepository,
18935
19236
  walletPubKeyHex,
18936
19237
  currentTime: Date.now()
@@ -18949,7 +19250,7 @@ async function computeExitLayout(opts, feeRate) {
18949
19250
  });
18950
19251
  continue;
18951
19252
  }
18952
- const t = chunkE7HB3GKK_cjs.sequenceToTimelock(resolved.selection.sequence);
19253
+ const t = chunkOWCPXRGP_cjs.sequenceToTimelock(resolved.selection.sequence);
18953
19254
  const delay = { type: t.type, value: Number(t.value) };
18954
19255
  infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
18955
19256
  sweeps.push({ vtxo, resolved, sweepFee, delay });
@@ -19035,19 +19336,48 @@ async function estimate(opts) {
19035
19336
  }
19036
19337
 
19037
19338
  // src/wallet/exit/executor.ts
19339
+ function abortErrorFor(signal) {
19340
+ if (signal.reason !== void 0) return signal.reason;
19341
+ const e = new Error("The operation was aborted");
19342
+ e.name = "AbortError";
19343
+ return e;
19344
+ }
19345
+ function throwIfAborted(signal) {
19346
+ if (signal?.aborted) throw abortErrorFor(signal);
19347
+ }
19038
19348
  var Executor = class {
19039
19349
  constructor(pkg, provider, opts) {
19040
19350
  this.pkg = pkg;
19041
19351
  this.provider = provider;
19042
19352
  this.pollIntervalMs = opts?.pollIntervalMs ?? 5e3;
19043
19353
  this.feeWallet = opts?.feeWallet;
19354
+ this.signal = opts?.signal;
19044
19355
  }
19045
19356
  pkg;
19046
19357
  provider;
19047
19358
  pollIntervalMs;
19048
19359
  feeWallet;
19360
+ signal;
19361
+ /**
19362
+ * Poll delay. Nearly all wall-clock time is spent here, so it must be the
19363
+ * thing that reacts to abort — checking only between polls would leave
19364
+ * cancellation up to a full interval late and the timer still pending.
19365
+ */
19049
19366
  sleep() {
19050
- return new Promise((r) => setTimeout(r, this.pollIntervalMs));
19367
+ const signal = this.signal;
19368
+ if (!signal) return new Promise((r) => setTimeout(r, this.pollIntervalMs));
19369
+ return new Promise((resolve, reject) => {
19370
+ if (signal.aborted) return reject(abortErrorFor(signal));
19371
+ const onAbort = () => {
19372
+ clearTimeout(timer);
19373
+ reject(abortErrorFor(signal));
19374
+ };
19375
+ const timer = setTimeout(() => {
19376
+ signal.removeEventListener("abort", onAbort);
19377
+ resolve();
19378
+ }, this.pollIntervalMs);
19379
+ signal.addEventListener("abort", onAbort, { once: true });
19380
+ });
19051
19381
  }
19052
19382
  async status(txid) {
19053
19383
  try {
@@ -19060,10 +19390,12 @@ var Executor = class {
19060
19390
  for (; ; ) {
19061
19391
  const s = await this.status(txid);
19062
19392
  if (s?.confirmed) return s;
19393
+ throwIfAborted(this.signal);
19063
19394
  await this.sleep();
19064
19395
  }
19065
19396
  }
19066
19397
  async *[Symbol.asyncIterator]() {
19398
+ throwIfAborted(this.signal);
19067
19399
  const dead = /* @__PURE__ */ new Set();
19068
19400
  if (this.pkg.validUntil && Date.now() / 1e3 > this.pkg.validUntil) {
19069
19401
  yield {
@@ -19175,6 +19507,7 @@ var Executor = class {
19175
19507
  while (done.size < pending.length) {
19176
19508
  for (const { index, step } of pending) {
19177
19509
  if (done.has(index)) continue;
19510
+ throwIfAborted(this.signal);
19178
19511
  const swept = await this.status(step.txid);
19179
19512
  if (swept?.confirmed) {
19180
19513
  done.add(index);
@@ -19256,7 +19589,7 @@ async function prepare(opts) {
19256
19589
  txid: sweep.vtxo.txid,
19257
19590
  vout: sweep.vtxo.vout,
19258
19591
  value: sweep.vtxo.value,
19259
- pkScript: chunkE7HB3GKK_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
19592
+ pkScript: chunkOWCPXRGP_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
19260
19593
  },
19261
19594
  path: sweep.resolved.selection,
19262
19595
  outputAddress: opts.sweepAddress,
@@ -19341,7 +19674,7 @@ async function prepare(opts) {
19341
19674
  if (newFee <= splitterFee) break;
19342
19675
  splitterFee = newFee;
19343
19676
  }
19344
- const splitter = new chunkRNMLFY2V_cjs.Transaction({ version: 2 });
19677
+ const splitter = new chunkOWCPXRGP_cjs.Transaction({ version: 2 });
19345
19678
  for (const coin of selected.inputs) {
19346
19679
  splitter.addInput({
19347
19680
  txid: coin.txid,
@@ -19484,44 +19817,45 @@ var UnilateralExit = {
19484
19817
  // src/arkade/index.ts
19485
19818
  var arkade_exports = {};
19486
19819
  chunk5BLDMQED_cjs.__export(arkade_exports, {
19487
- ARKADE_OP: () => chunkIEMPH7J6_cjs.ARKADE_OP,
19488
- ARKADE_OPCODES: () => chunkIEMPH7J6_cjs.ARKADE_OPCODES,
19489
- ARKADE_OPCODE_NAMES: () => chunkIEMPH7J6_cjs.ARKADE_OPCODE_NAMES,
19490
- ARKADE_OPCODE_VALUES: () => chunkIEMPH7J6_cjs.ARKADE_OPCODE_VALUES,
19491
- ARKADE_OPS: () => chunkIEMPH7J6_cjs.ARKADE_OPS,
19820
+ ARKADE_OP: () => chunkV2TOHHPW_cjs.ARKADE_OP,
19821
+ ARKADE_OPCODES: () => chunkV2TOHHPW_cjs.ARKADE_OPCODES,
19822
+ ARKADE_OPCODE_NAMES: () => chunkV2TOHHPW_cjs.ARKADE_OPCODE_NAMES,
19823
+ ARKADE_OPCODE_VALUES: () => chunkV2TOHHPW_cjs.ARKADE_OPCODE_VALUES,
19824
+ ARKADE_OPS: () => chunkV2TOHHPW_cjs.ARKADE_OPS,
19492
19825
  Arkade: () => Arkade,
19493
19826
  ArkadeContract: () => ArkadeContract,
19494
- ArkadeProgramScript: () => chunkIEMPH7J6_cjs.ArkadeProgramScript,
19495
- ArkadeScript: () => chunkIEMPH7J6_cjs.ArkadeScript,
19827
+ ArkadeProgramScript: () => chunkV2TOHHPW_cjs.ArkadeProgramScript,
19828
+ ArkadeScript: () => chunkV2TOHHPW_cjs.ArkadeScript,
19496
19829
  ArkadeTransactionBuilder: () => ArkadeTransactionBuilder,
19497
- BigNum: () => chunkIEMPH7J6_cjs.bignum_exports,
19830
+ BigNum: () => chunkV2TOHHPW_cjs.bignum_exports,
19498
19831
  OP: () => btcSigner.OP,
19499
- OPCODE_NAMES: () => chunkIEMPH7J6_cjs.OPCODE_NAMES,
19500
- OPCODE_VALUES: () => chunkIEMPH7J6_cjs.OPCODE_VALUES,
19501
- SUPPORTED_PROGRAM_VERSION: () => chunkIEMPH7J6_cjs.SUPPORTED_PROGRAM_VERSION,
19832
+ OPCODE_NAMES: () => chunkV2TOHHPW_cjs.OPCODE_NAMES,
19833
+ OPCODE_VALUES: () => chunkV2TOHHPW_cjs.OPCODE_VALUES,
19834
+ SUPPORTED_PROGRAM_VERSION: () => chunkV2TOHHPW_cjs.SUPPORTED_PROGRAM_VERSION,
19502
19835
  Script: () => btcSigner.Script,
19503
- arkadeScriptHash: () => chunkIEMPH7J6_cjs.arkadeScriptHash,
19504
- arkadeWitnessHash: () => chunkIEMPH7J6_cjs.arkadeWitnessHash,
19505
- asmToBytes: () => chunkIEMPH7J6_cjs.asmToBytes,
19506
- bytesToASM: () => chunkIEMPH7J6_cjs.bytesToASM,
19507
- computeArkadeScriptPublicKey: () => chunkIEMPH7J6_cjs.computeArkadeScriptPublicKey,
19836
+ arkadeScriptHash: () => chunkV2TOHHPW_cjs.arkadeScriptHash,
19837
+ arkadeWitnessHash: () => chunkV2TOHHPW_cjs.arkadeWitnessHash,
19838
+ asmToBytes: () => chunkV2TOHHPW_cjs.asmToBytes,
19839
+ bytesToASM: () => chunkV2TOHHPW_cjs.bytesToASM,
19840
+ computeArkadeScriptPublicKey: () => chunkV2TOHHPW_cjs.computeArkadeScriptPublicKey,
19508
19841
  createArkadeBatchHandler: () => createArkadeBatchHandler,
19509
- deserializeArkadeContractParams: () => chunkIEMPH7J6_cjs.deserializeArkadeContractParams,
19510
- fromASM: () => chunkIEMPH7J6_cjs.fromASM,
19511
- getOpcodeName: () => chunkIEMPH7J6_cjs.getOpcodeName,
19512
- getOpcodeValue: () => chunkIEMPH7J6_cjs.getOpcodeValue,
19513
- parseArtifact: () => chunkIEMPH7J6_cjs.parseArtifact,
19514
- resolveAsm: () => chunkIEMPH7J6_cjs.resolveAsm,
19515
- serializeArkadeContractParams: () => chunkIEMPH7J6_cjs.serializeArkadeContractParams,
19516
- stringifyArtifact: () => chunkIEMPH7J6_cjs.stringifyArtifact,
19517
- toASM: () => chunkIEMPH7J6_cjs.toASM,
19518
- validateProgram: () => chunkIEMPH7J6_cjs.validateProgram,
19519
- witnessRefToBytes: () => chunkIEMPH7J6_cjs.witnessRefToBytes
19842
+ deserializeArkadeContractParams: () => chunkV2TOHHPW_cjs.deserializeArkadeContractParams,
19843
+ fromASM: () => chunkV2TOHHPW_cjs.fromASM,
19844
+ getOpcodeName: () => chunkV2TOHHPW_cjs.getOpcodeName,
19845
+ getOpcodeValue: () => chunkV2TOHHPW_cjs.getOpcodeValue,
19846
+ parseArtifact: () => chunkV2TOHHPW_cjs.parseArtifact,
19847
+ resolveAsm: () => chunkV2TOHHPW_cjs.resolveAsm,
19848
+ serializeArkadeContractParams: () => chunkV2TOHHPW_cjs.serializeArkadeContractParams,
19849
+ stringifyArtifact: () => chunkV2TOHHPW_cjs.stringifyArtifact,
19850
+ toASM: () => chunkV2TOHHPW_cjs.toASM,
19851
+ validateProgram: () => chunkV2TOHHPW_cjs.validateProgram,
19852
+ witnessRefToBytes: () => chunkV2TOHHPW_cjs.witnessRefToBytes
19520
19853
  });
19521
- var isVtxoCoin = (input) => chunkE7HB3GKK_cjs.isVirtualCoin(input);
19854
+ var isVtxoCoin = (input) => chunkOWCPXRGP_cjs.isVirtualCoin(input);
19522
19855
  function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message, session, arkProvider, emulator, network, recipients) {
19523
19856
  let batchId;
19524
19857
  let sweepTapTreeRoot;
19858
+ let validatedCommitmentTxid;
19525
19859
  return {
19526
19860
  onBatchStarted: async (event) => {
19527
19861
  const utf8IntentId = new TextEncoder().encode(intentId);
@@ -19530,7 +19864,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19530
19864
  if (!event.intentIdHashes.includes(intentIdHashStr)) return { skip: true };
19531
19865
  await arkProvider.confirmRegistration(intentId);
19532
19866
  batchId = event.id;
19533
- const sweepTapscript = chunkE7HB3GKK_cjs.CSVMultisigTapscript.encode({
19867
+ const sweepTapscript = chunkOWCPXRGP_cjs.CSVMultisigTapscript.encode({
19534
19868
  timelock: {
19535
19869
  value: event.batchExpiry,
19536
19870
  // BIP-65: values >= 512 are interpreted as seconds, below as blocks
@@ -19548,7 +19882,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19548
19882
  if (!xOnlyPubkeys.includes(base.hex.encode(xonlySignerPubKey))) {
19549
19883
  return { skip: true };
19550
19884
  }
19551
- const commitmentTx = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(event.unsignedCommitmentTx));
19885
+ const commitmentTx = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(event.unsignedCommitmentTx));
19552
19886
  validateVtxoTxGraph(vtxoTree, commitmentTx, sweepTapTreeRoot);
19553
19887
  if (recipients && recipients.length > 0) {
19554
19888
  validateBatchRecipients(commitmentTx, vtxoTree.leaves(), recipients, network);
@@ -19557,6 +19891,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19557
19891
  if (!sharedOutput?.amount) {
19558
19892
  throw new Error("Shared output not found");
19559
19893
  }
19894
+ validatedCommitmentTxid = commitmentTx.id;
19560
19895
  await session.init(vtxoTree, sweepTapTreeRoot, sharedOutput.amount);
19561
19896
  const pubkey = base.hex.encode(await session.getPublicKey());
19562
19897
  const nonces = await session.getNonces();
@@ -19579,7 +19914,15 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19579
19914
  if (connectorTree) {
19580
19915
  validateConnectorsTxGraph(event.commitmentTx, connectorTree);
19581
19916
  }
19582
- let commitmentPsbt = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
19917
+ let commitmentPsbt = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
19918
+ assertFinalCommitmentMatchesValidated(
19919
+ commitmentPsbt,
19920
+ validatedCommitmentTxid,
19921
+ "arkade batch finalization"
19922
+ );
19923
+ if (!validatedCommitmentTxid && recipients && recipients.length > 0) {
19924
+ validateBatchRecipientsWithoutTree(commitmentPsbt, recipients, network);
19925
+ }
19583
19926
  const signedForfeits = [];
19584
19927
  let connectorIndex = 0;
19585
19928
  const connectorLeaves = connectorTree?.leaves() || [];
@@ -19606,7 +19949,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19606
19949
  boardingIndices.push(boardingIdx);
19607
19950
  continue;
19608
19951
  }
19609
- if (chunkE7HB3GKK_cjs.isRecoverable(input) || isSubdust(input, info.dust)) {
19952
+ if (chunkOWCPXRGP_cjs.isRecoverable(input) || isSubdust(input, info.dust)) {
19610
19953
  continue;
19611
19954
  }
19612
19955
  if (connectorIndex >= connectorLeaves.length) {
@@ -19627,7 +19970,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
19627
19970
  index: input.vout,
19628
19971
  witnessUtxo: {
19629
19972
  amount: BigInt(input.value),
19630
- script: chunkE7HB3GKK_cjs.VtxoScript.decode(input.tapTree).pkScript
19973
+ script: chunkOWCPXRGP_cjs.VtxoScript.decode(input.tapTree).pkScript
19631
19974
  },
19632
19975
  sighashType: btcSigner.SigHash.DEFAULT,
19633
19976
  tapLeafScript: [input.forfeitTapLeafScript]
@@ -19710,7 +20053,7 @@ var Arkade = class _Arkade {
19710
20053
  static async connect(opts) {
19711
20054
  const info = await opts.arkade.getInfo();
19712
20055
  const serverKey = base.hex.decode(info.signerPubkey).slice(1);
19713
- const checkpoint = chunkE7HB3GKK_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
20056
+ const checkpoint = chunkOWCPXRGP_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
19714
20057
  let emulatorKey;
19715
20058
  if (opts.emulator) {
19716
20059
  const eInfo = await opts.emulator.getInfo();
@@ -19724,7 +20067,7 @@ var Arkade = class _Arkade {
19724
20067
  return new _Arkade({
19725
20068
  arkProvider: opts.arkade,
19726
20069
  emulator: opts.emulator,
19727
- network: opts.network ?? chunkE7HB3GKK_cjs.DEFAULT_NETWORK,
20070
+ network: opts.network ?? chunkOWCPXRGP_cjs.DEFAULT_NETWORK,
19728
20071
  serverKey,
19729
20072
  emulatorKey,
19730
20073
  checkpoint,
@@ -19745,7 +20088,7 @@ var Arkade = class _Arkade {
19745
20088
  * key respectively; explicit args always win.
19746
20089
  */
19747
20090
  contract(program, args = {}) {
19748
- const declared = (program.params ?? []).map(chunkIEMPH7J6_cjs.inputName);
20091
+ const declared = (program.params ?? []).map(chunkV2TOHHPW_cjs.inputName);
19749
20092
  if (declared.includes("server") && args.server === void 0) {
19750
20093
  args = { ...args, server: this.serverKey };
19751
20094
  }
@@ -19765,7 +20108,7 @@ var ArkadeContract = class _ArkadeContract {
19765
20108
  userKey: client.userKey,
19766
20109
  emulatorKey: client.emulatorKey
19767
20110
  };
19768
- this.vtxoScript = new chunkIEMPH7J6_cjs.ArkadeProgramScript(program, args, this.keys);
20111
+ this.vtxoScript = new chunkV2TOHHPW_cjs.ArkadeProgramScript(program, args, this.keys);
19769
20112
  this.tapTree = this.vtxoScript.encode();
19770
20113
  this.compiled = this.vtxoScript.compiled;
19771
20114
  }
@@ -19793,7 +20136,7 @@ var ArkadeContract = class _ArkadeContract {
19793
20136
  `ArkadeContract.fromContract: expected contract type 'arkade', got '${contract.type}'`
19794
20137
  );
19795
20138
  }
19796
- const typed = chunkIEMPH7J6_cjs.deserializeArkadeContractParams(contract.params);
20139
+ const typed = chunkV2TOHHPW_cjs.deserializeArkadeContractParams(contract.params);
19797
20140
  return new _ArkadeContract(client, typed.program, typed.args, {
19798
20141
  serverKey: typed.serverKey,
19799
20142
  userKey: typed.userKey,
@@ -19834,7 +20177,7 @@ var ArkadeContract = class _ArkadeContract {
19834
20177
  toContractParams() {
19835
20178
  return {
19836
20179
  type: "arkade",
19837
- params: chunkIEMPH7J6_cjs.serializeArkadeContractParams({
20180
+ params: chunkV2TOHHPW_cjs.serializeArkadeContractParams({
19838
20181
  program: this.program,
19839
20182
  args: this.args,
19840
20183
  serverKey: this.keys.serverKey,
@@ -19879,13 +20222,13 @@ var ArkadeContract = class _ArkadeContract {
19879
20222
  const [registered] = await manager.getContracts({ script: scriptHex });
19880
20223
  if (registered) {
19881
20224
  const [withVtxos] = await manager.getContractsWithVtxos({ script: scriptHex });
19882
- return (withVtxos?.vtxos ?? []).filter((v) => !chunkE7HB3GKK_cjs.hasTerminalSpend(v));
20225
+ return (withVtxos?.vtxos ?? []).filter((v) => !chunkOWCPXRGP_cjs.hasTerminalSpend(v));
19883
20226
  }
19884
20227
  }
19885
20228
  if (!this.client.indexer) {
19886
20229
  throw new Error("ArkadeContract.getUtxos: an indexer is required");
19887
20230
  }
19888
- const { vtxos } = await chunkE7HB3GKK_cjs.getNormalizedVtxos(this.client.indexer, {
20231
+ const { vtxos } = await chunkOWCPXRGP_cjs.getNormalizedVtxos(this.client.indexer, {
19889
20232
  scripts: [scriptHex],
19890
20233
  spendableOnly: true
19891
20234
  });
@@ -19987,12 +20330,12 @@ var ArkadeTransactionBuilder = class {
19987
20330
  this.contract.client.checkpoint
19988
20331
  );
19989
20332
  if (coin.sourceTx) {
19990
- chunkRNMLFY2V_cjs.setArkPsbtField(arkTx, 0, chunkRNMLFY2V_cjs.PrevArkTxField, coin.sourceTx);
20333
+ chunkOWCPXRGP_cjs.setArkPsbtField(arkTx, 0, chunkOWCPXRGP_cjs.PrevArkTxField, coin.sourceTx);
19991
20334
  }
19992
20335
  const condition = (def.tapscript.witness ?? []).map((w) => this.witnessBytes(w));
19993
20336
  if (condition.length > 0) {
19994
- chunkRNMLFY2V_cjs.setArkPsbtField(arkTx, 0, chunkRNMLFY2V_cjs.ConditionWitness, condition);
19995
- chunkRNMLFY2V_cjs.setArkPsbtField(checkpoints[0], 0, chunkRNMLFY2V_cjs.ConditionWitness, condition);
20337
+ chunkOWCPXRGP_cjs.setArkPsbtField(arkTx, 0, chunkOWCPXRGP_cjs.ConditionWitness, condition);
20338
+ chunkOWCPXRGP_cjs.setArkPsbtField(checkpoints[0], 0, chunkOWCPXRGP_cjs.ConditionWitness, condition);
19996
20339
  }
19997
20340
  const packets = [];
19998
20341
  if (this.assetSpecs.length > 0) {
@@ -20031,7 +20374,7 @@ var ArkadeTransactionBuilder = class {
20031
20374
  base.base64.encode(signedArk2.toPSBT()),
20032
20375
  signedCps.map((c) => base.base64.encode(c.toPSBT()))
20033
20376
  );
20034
- const txid = chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(res2.signedArkTx)).id;
20377
+ const txid = chunkOWCPXRGP_cjs.Transaction.fromPSBT(base.base64.decode(res2.signedArkTx)).id;
20035
20378
  return {
20036
20379
  txid,
20037
20380
  signedArkTx: res2.signedArkTx,
@@ -20046,11 +20389,11 @@ var ArkadeTransactionBuilder = class {
20046
20389
  base.base64.encode(signedArk.toPSBT()),
20047
20390
  checkpoints.map((c) => base.base64.encode(c.toPSBT()))
20048
20391
  );
20392
+ assertSubmittedArkTxid(res, signedArk, "submitTx");
20393
+ const matched = matchServerCheckpoints(res.signedCheckpointTxs, checkpoints, "submitTx");
20049
20394
  const finalCps = await Promise.all(
20050
- res.signedCheckpointTxs.map(
20051
- async (b) => base.base64.encode(
20052
- (await client.identity.sign(chunkRNMLFY2V_cjs.Transaction.fromPSBT(base.base64.decode(b)), [0])).toPSBT()
20053
- )
20395
+ matched.map(
20396
+ async ({ server }) => base.base64.encode((await client.identity.sign(server, [0])).toPSBT())
20054
20397
  )
20055
20398
  );
20056
20399
  await client.arkProvider.finalizeTx(res.arkTxid, finalCps);
@@ -20090,23 +20433,23 @@ var ArkadeTransactionBuilder = class {
20090
20433
  }
20091
20434
  buildAssetPacket() {
20092
20435
  const groups = this.assetSpecs.map((s) => {
20093
- const id = typeof s.assetId === "string" ? chunkRNMLFY2V_cjs.AssetId.fromString(s.assetId) : chunkRNMLFY2V_cjs.AssetId.fromBytes(s.assetId);
20094
- return chunkRNMLFY2V_cjs.AssetGroup.create(
20436
+ const id = typeof s.assetId === "string" ? chunkG7DOBFQN_cjs.AssetId.fromString(s.assetId) : chunkG7DOBFQN_cjs.AssetId.fromBytes(s.assetId);
20437
+ return chunkG7DOBFQN_cjs.AssetGroup.create(
20095
20438
  id,
20096
20439
  null,
20097
- s.inputs.map((i) => chunkRNMLFY2V_cjs.AssetInput.create(i.vin, i.amount)),
20098
- s.outputs.map((o) => chunkRNMLFY2V_cjs.AssetOutput.create(o.vout, o.amount)),
20099
- (s.metadata ?? []).map((m) => chunkRNMLFY2V_cjs.Metadata.create(m.key, m.value))
20440
+ s.inputs.map((i) => chunkG7DOBFQN_cjs.AssetInput.create(i.vin, i.amount)),
20441
+ s.outputs.map((o) => chunkG7DOBFQN_cjs.AssetOutput.create(o.vout, o.amount)),
20442
+ (s.metadata ?? []).map((m) => chunkG7DOBFQN_cjs.Metadata.create(m.key, m.value))
20100
20443
  );
20101
20444
  });
20102
- return chunkRNMLFY2V_cjs.Packet.create(groups);
20445
+ return chunkG7DOBFQN_cjs.Packet.create(groups);
20103
20446
  }
20104
20447
  witnessBytes(ref) {
20105
- return chunkIEMPH7J6_cjs.witnessRefToBytes(ref, this.args, this.contract.args);
20448
+ return chunkV2TOHHPW_cjs.witnessRefToBytes(ref, this.args, this.contract.args);
20106
20449
  }
20107
20450
  };
20108
20451
  function bindInputs(fn, callArgs) {
20109
- const names = (fn.def.inputs ?? []).map(chunkIEMPH7J6_cjs.inputName);
20452
+ const names = (fn.def.inputs ?? []).map(chunkV2TOHHPW_cjs.inputName);
20110
20453
  if (callArgs.length !== names.length) {
20111
20454
  throw new Error(`${fn.name}: expected ${names.length} argument(s), got ${callArgs.length}`);
20112
20455
  }
@@ -20134,6 +20477,360 @@ function attachExtension(tx, newPackets) {
20134
20477
  }
20135
20478
  tx.addOutput({ script: newOut.script, amount: newOut.amount });
20136
20479
  }
20480
+
20481
+ // src/utils/bip21.ts
20482
+ var BIP21Error = /* @__PURE__ */ ((BIP21Error2) => {
20483
+ BIP21Error2["INVALID_URI"] = "Invalid BIP21 URI";
20484
+ BIP21Error2["INVALID_ADDRESS"] = "Invalid address";
20485
+ return BIP21Error2;
20486
+ })(BIP21Error || {});
20487
+ var BIP21 = class _BIP21 {
20488
+ /**
20489
+ * Create a BIP21 URI from the provided parameters.
20490
+ *
20491
+ * @param params - BIP21 parameters to encode
20492
+ * @returns Encoded BIP21 URI
20493
+ */
20494
+ static create(params) {
20495
+ const { address, ...options } = params;
20496
+ const queryParams = {};
20497
+ for (const [key, value] of Object.entries(options)) {
20498
+ if (value === void 0) continue;
20499
+ if (key === "amount") {
20500
+ const amount = value;
20501
+ if (!isFinite(amount) || !Number.isSafeInteger(Math.trunc(amount))) {
20502
+ console.warn("Invalid amount");
20503
+ continue;
20504
+ }
20505
+ if (amount < 0) {
20506
+ continue;
20507
+ }
20508
+ queryParams[key] = value;
20509
+ } else if (key === "ark") {
20510
+ if (typeof value === "string" && (value.startsWith("ark") || value.startsWith("tark"))) {
20511
+ queryParams[key] = value;
20512
+ } else {
20513
+ console.warn("Invalid ARK address format");
20514
+ }
20515
+ } else if (key === "sp") {
20516
+ if (typeof value === "string" && value.startsWith("sp")) {
20517
+ queryParams[key] = value;
20518
+ } else {
20519
+ console.warn("Invalid Silent Payment address format");
20520
+ }
20521
+ } else if (typeof value === "string" || typeof value === "number") {
20522
+ queryParams[key] = value;
20523
+ }
20524
+ }
20525
+ const query = Object.keys(queryParams).length > 0 ? "?" + new URLSearchParams(
20526
+ Object.fromEntries(
20527
+ Object.entries(queryParams).map(([k, v]) => [k, String(v)])
20528
+ )
20529
+ ).toString() : "";
20530
+ return `bitcoin:${address ? address.toLowerCase() : ""}${query}`;
20531
+ }
20532
+ /**
20533
+ * Integer-sats amount encoded in a BIP21 URI (`amount=` is BTC), or
20534
+ * `undefined` when absent or the URI is unparseable. Shared by the payment
20535
+ * rails, which accept either a bare address or a BIP21 URI.
20536
+ *
20537
+ * @param uri - BIP21 URI (or bare address) to read the amount from
20538
+ * @returns The amount in satoshis, or `undefined`
20539
+ */
20540
+ static amountSats(uri) {
20541
+ try {
20542
+ const btc = _BIP21.parse(uri).params.amount;
20543
+ return typeof btc === "number" ? Math.round(btc * 1e8) : void 0;
20544
+ } catch {
20545
+ return void 0;
20546
+ }
20547
+ }
20548
+ /**
20549
+ * Parse a BIP21 URI and return its decoded parameters.
20550
+ *
20551
+ * @param uri - BIP21 URI to parse
20552
+ * @returns Parsed BIP21 URI data
20553
+ * @throws Error if the URI does not start with the `bitcoin:` scheme
20554
+ */
20555
+ static parse(uri) {
20556
+ if (!uri.toLowerCase().startsWith("bitcoin:")) {
20557
+ throw new Error("Invalid BIP21 URI" /* INVALID_URI */);
20558
+ }
20559
+ const withoutPrefix = uri.slice(uri.toLowerCase().indexOf("bitcoin:") + 8);
20560
+ const [address, query] = withoutPrefix.split("?");
20561
+ const params = {};
20562
+ if (address) {
20563
+ params.address = address.toLowerCase();
20564
+ }
20565
+ if (query) {
20566
+ const queryParams = new URLSearchParams(query);
20567
+ for (const [key, value] of queryParams.entries()) {
20568
+ if (!value) continue;
20569
+ if (key === "amount") {
20570
+ if (!/^(?:\d+\.?\d*|\.\d+)$/.test(value)) {
20571
+ continue;
20572
+ }
20573
+ const amount = Number(value);
20574
+ if (!isFinite(amount) || !Number.isSafeInteger(Math.trunc(amount))) {
20575
+ continue;
20576
+ }
20577
+ params[key] = amount;
20578
+ } else if (key === "ark") {
20579
+ if (value.startsWith("ark") || value.startsWith("tark")) {
20580
+ params[key] = value;
20581
+ } else {
20582
+ console.warn("Invalid ARK address format");
20583
+ }
20584
+ } else if (key === "sp") {
20585
+ if (value.startsWith("sp")) {
20586
+ params[key] = value;
20587
+ } else {
20588
+ console.warn("Invalid Silent Payment address format");
20589
+ }
20590
+ } else {
20591
+ params[key] = value;
20592
+ }
20593
+ }
20594
+ }
20595
+ return {
20596
+ originalString: uri,
20597
+ params
20598
+ };
20599
+ }
20600
+ };
20601
+
20602
+ // src/payment/predicates.ts
20603
+ var isLightningInvoice = (raw) => /^ln(bcrt|bc|tbs|tb|sb)[0-9a-z]+$/i.test(raw.replace(/^lightning:/i, ""));
20604
+ var isLnurl = (raw) => /^lnurl/i.test(raw) || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(raw);
20605
+ var BECH32_BTC = /^(bc1|tb1|bcrt1)[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,90}$/;
20606
+ var isBech32Btc = (raw) => (raw === raw.toLowerCase() || raw === raw.toUpperCase()) && BECH32_BTC.test(raw.toLowerCase());
20607
+ var isBtcAddress = (raw) => isBech32Btc(raw) || /^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,39}$/.test(raw);
20608
+
20609
+ // src/payment/targets.ts
20610
+ var fromBip21 = (raw, key, accept) => {
20611
+ try {
20612
+ const v = BIP21.parse(raw).params[key];
20613
+ return typeof v === "string" && accept(v) ? v : void 0;
20614
+ } catch {
20615
+ return void 0;
20616
+ }
20617
+ };
20618
+ var arkTarget = (raw) => isValidArkAddress2(raw) ? raw : fromBip21(raw, "ark", isValidArkAddress2);
20619
+ var btcTarget = (raw) => isBtcAddress(raw) ? raw : fromBip21(raw, "address", isBtcAddress);
20620
+ var invoiceTarget = (raw) => {
20621
+ const invoice = isLightningInvoice(raw) ? raw : fromBip21(raw, "lightning", isLightningInvoice);
20622
+ return invoice?.replace(/^lightning:/i, "");
20623
+ };
20624
+
20625
+ // src/payment/amount.ts
20626
+ function assertSendableAmount(railId, amt) {
20627
+ if (!Number.isInteger(amt) || amt <= 0) {
20628
+ throw new Error(`${railId}: invalid amount ${amt} sats (expected a positive integer)`);
20629
+ }
20630
+ }
20631
+ function resolveSendAmount(railId, raw, amount) {
20632
+ const amt = amount ?? BIP21.amountSats(raw);
20633
+ if (amt === void 0) {
20634
+ throw new Error(
20635
+ `${railId}: an amount is required (none provided or encoded in the request)`
20636
+ );
20637
+ }
20638
+ assertSendableAmount(railId, amt);
20639
+ return amt;
20640
+ }
20641
+ function tryResolveSendAmount(raw, amount) {
20642
+ const amt = amount ?? BIP21.amountSats(raw);
20643
+ return amt !== void 0 && Number.isInteger(amt) && amt > 0 ? amt : void 0;
20644
+ }
20645
+
20646
+ // src/payment/handle.ts
20647
+ function makeHandle(id, run) {
20648
+ let status = "pending";
20649
+ let last = { status };
20650
+ const subs = /* @__PURE__ */ new Set();
20651
+ const notify = (f, u) => {
20652
+ try {
20653
+ f(u);
20654
+ } catch {
20655
+ }
20656
+ };
20657
+ const isTerminal = (s) => s === "settled" || s === "failed";
20658
+ const emit = (u) => {
20659
+ status = u.status;
20660
+ last = u;
20661
+ for (const f of subs) notify(f, u);
20662
+ if (isTerminal(u.status)) subs.clear();
20663
+ };
20664
+ const done = run(emit);
20665
+ done.catch((error) => {
20666
+ if (status !== "settled") emit({ status: "failed", error });
20667
+ });
20668
+ return {
20669
+ id,
20670
+ get status() {
20671
+ return status;
20672
+ },
20673
+ subscribe(fn) {
20674
+ notify(fn, last);
20675
+ if (isTerminal(status)) return () => {
20676
+ };
20677
+ subs.add(fn);
20678
+ return () => subs.delete(fn);
20679
+ },
20680
+ settled(opts) {
20681
+ if (!opts?.timeoutMs) return done;
20682
+ let timer;
20683
+ return Promise.race([
20684
+ done,
20685
+ new Promise((_, rej) => {
20686
+ timer = setTimeout(() => rej(new Error("settle timeout")), opts.timeoutMs);
20687
+ })
20688
+ ]).finally(() => clearTimeout(timer));
20689
+ }
20690
+ };
20691
+ }
20692
+
20693
+ // src/payment/router.ts
20694
+ var AmbiguousRouteError = class extends Error {
20695
+ constructor(railIds) {
20696
+ super(`ambiguous route: ${railIds.join(", ")}`);
20697
+ this.railIds = railIds;
20698
+ this.name = "AmbiguousRouteError";
20699
+ }
20700
+ railIds;
20701
+ };
20702
+ var PaymentRouter = class {
20703
+ constructor(ctx) {
20704
+ this.ctx = ctx;
20705
+ }
20706
+ ctx;
20707
+ rails = /* @__PURE__ */ new Map();
20708
+ /** Register a rail (or overwrite one with the same id). */
20709
+ use(rail) {
20710
+ this.rails.set(rail.id, rail);
20711
+ return this;
20712
+ }
20713
+ /** Remove a rail by id. */
20714
+ remove(id) {
20715
+ this.rails.delete(id);
20716
+ return this;
20717
+ }
20718
+ /** Rails matching `req`, filtered by `disabled`/`available()`, ranked by
20719
+ * `priority` (unlisted rails keep insertion order, after listed ones). */
20720
+ async options(req, prefs) {
20721
+ const merged = { ...this.ctx.prefs, ...prefs };
20722
+ const ctx = { ...this.ctx, prefs: merged };
20723
+ const matched = [...this.rails.values()].filter(
20724
+ (rail) => !merged.disabled?.includes(rail.id) && rail.match(req, ctx)
20725
+ );
20726
+ const available = (await Promise.all(
20727
+ matched.map(async (rail) => {
20728
+ try {
20729
+ return await rail.available?.(req, ctx) ?? true ? rail : null;
20730
+ } catch (e) {
20731
+ console.warn(`payment rail "${rail.id}": available() threw`, e);
20732
+ return null;
20733
+ }
20734
+ })
20735
+ )).filter((rail) => rail !== null);
20736
+ const rank = (id) => {
20737
+ const i = merged.priority?.indexOf(id) ?? -1;
20738
+ return i < 0 ? Number.MAX_SAFE_INTEGER : i;
20739
+ };
20740
+ available.sort((a, b) => rank(a.id) - rank(b.id));
20741
+ return available.map((rail) => ({
20742
+ railId: rail.id,
20743
+ quote: () => rail.quote(req, ctx)
20744
+ }));
20745
+ }
20746
+ /** Top-ranked option's quote. Throws when nothing routes, or
20747
+ * {@link AmbiguousRouteError} when `tieBreak` is `"require-choice"` and
20748
+ * more than one option survives. */
20749
+ async route(req, prefs) {
20750
+ const options = await this.options(req, prefs);
20751
+ if (options.length === 0) {
20752
+ throw new Error(`no rail for: ${req.raw}`);
20753
+ }
20754
+ const tieBreak = { ...this.ctx.prefs, ...prefs }.tieBreak ?? "first";
20755
+ if (tieBreak === "require-choice" && options.length > 1) {
20756
+ throw new AmbiguousRouteError(options.map((o) => o.railId));
20757
+ }
20758
+ return options[0].quote();
20759
+ }
20760
+ };
20761
+
20762
+ // src/payment/rails/ark.ts
20763
+ function arkRail() {
20764
+ return {
20765
+ id: "ark",
20766
+ match: (req) => arkTarget(req.raw) !== void 0,
20767
+ quote: async (req, ctx) => {
20768
+ const address = arkTarget(req.raw);
20769
+ const amt = resolveSendAmount("ark", req.raw, req.amount);
20770
+ return {
20771
+ railId: "ark",
20772
+ amount: amt,
20773
+ fee: 0,
20774
+ total: amt,
20775
+ send: async () => makeHandle("ark", async (emit) => {
20776
+ const txid = await ctx.wallet.send({ address, amount: amt });
20777
+ const result = { railId: "ark", txid };
20778
+ emit({ status: "settled", result });
20779
+ return result;
20780
+ })
20781
+ };
20782
+ }
20783
+ };
20784
+ }
20785
+ var GROSS_UP_MAX_ROUNDS = 8;
20786
+ function grossUpOffboard(net, feeInfo, script) {
20787
+ const estimator = new Estimator(feeInfo?.intentFee ?? {});
20788
+ const feeAt = (amount) => estimator.evalOnchainOutput({ amount: BigInt(amount), script }).satoshis;
20789
+ let gross = net;
20790
+ for (let i = 0; i < GROSS_UP_MAX_ROUNDS; i++) {
20791
+ const next = net + feeAt(gross);
20792
+ if (next === gross) break;
20793
+ gross = next;
20794
+ }
20795
+ return { gross, fee: gross - net };
20796
+ }
20797
+ function onchainRail() {
20798
+ return {
20799
+ id: "onchain",
20800
+ match: (req) => btcTarget(req.raw) !== void 0,
20801
+ quote: async (req, ctx) => {
20802
+ const address = btcTarget(req.raw);
20803
+ const amt = resolveSendAmount("onchain", req.raw, req.amount);
20804
+ const { fees } = await ctx.wallet.arkProvider.getInfo();
20805
+ const script = base.hex.encode(offboardDestinationScript(address));
20806
+ const { gross, fee } = grossUpOffboard(amt, fees, script);
20807
+ return {
20808
+ railId: "onchain",
20809
+ amount: amt,
20810
+ fee,
20811
+ total: gross,
20812
+ send: async () => makeHandle("onchain", async (emit) => {
20813
+ const txid = await new Ramps(ctx.wallet).offboard(
20814
+ address,
20815
+ fees,
20816
+ BigInt(gross)
20817
+ );
20818
+ const result = { railId: "onchain", txid };
20819
+ emit({ status: "settled", result });
20820
+ return result;
20821
+ })
20822
+ };
20823
+ }
20824
+ };
20825
+ }
20826
+
20827
+ // src/payment/index.ts
20828
+ function createDefaultPaymentRouter(wallet) {
20829
+ return new PaymentRouter({
20830
+ wallet,
20831
+ prefs: { priority: ["ark", "lightning", "onchain"] }
20832
+ }).use(arkRail()).use(onchainRail());
20833
+ }
20137
20834
  var ARKCONTRACT_PREFIX = "arkcontract";
20138
20835
  function encodeArkContract(contract) {
20139
20836
  const params = new URLSearchParams();
@@ -20159,7 +20856,7 @@ function decodeArkContract(encoded) {
20159
20856
  }
20160
20857
  function contractFromArkContract(encoded, options = {}) {
20161
20858
  const parsed = decodeArkContract(encoded);
20162
- const handler = chunkIEMPH7J6_cjs.contractHandlers.get(parsed.type);
20859
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.get(parsed.type);
20163
20860
  if (!handler) {
20164
20861
  throw new Error(`No handler registered for contract type '${parsed.type}'`);
20165
20862
  }
@@ -20173,9 +20870,9 @@ function contractFromArkContract(encoded, options = {}) {
20173
20870
  metadata: options.metadata
20174
20871
  };
20175
20872
  }
20176
- function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunkE7HB3GKK_cjs.DEFAULT_NETWORK.hrp, options = {}) {
20873
+ function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunkOWCPXRGP_cjs.DEFAULT_NETWORK.hrp, options = {}) {
20177
20874
  const parsed = decodeArkContract(encoded);
20178
- const handler = chunkIEMPH7J6_cjs.contractHandlers.getOrThrow(parsed.type);
20875
+ const handler = chunkV2TOHHPW_cjs.contractHandlers.getOrThrow(parsed.type);
20179
20876
  const params = parsed.data;
20180
20877
  const vtxoScript = handler.createScript(params);
20181
20878
  return {
@@ -20195,10 +20892,13 @@ function isArkContract(str) {
20195
20892
 
20196
20893
  exports.ARKADE_MAGIC = ARKADE_MAGIC;
20197
20894
  exports.ActivityRegistry = ActivityRegistry;
20895
+ exports.AmbiguousRouteError = AmbiguousRouteError;
20198
20896
  exports.ArkNote = ArkNote;
20199
20897
  exports.ArkadeCash = ArkadeCash;
20200
20898
  exports.ArkadeCashCreateError = ArkadeCashCreateError;
20201
20899
  exports.AssetManager = AssetManager;
20900
+ exports.BIP21 = BIP21;
20901
+ exports.BIP21Error = BIP21Error;
20202
20902
  exports.ChainedTxType = ChainedTxType;
20203
20903
  exports.ContractManager = ContractManager;
20204
20904
  exports.ContractRepositoryImpl = ContractRepositoryImpl;
@@ -20209,6 +20909,7 @@ exports.DelegateManagerImpl = DelegateManagerImpl;
20209
20909
  exports.DelegateNotConfiguredError = DelegateNotConfiguredError;
20210
20910
  exports.DelegatorManagerImpl = DelegatorManagerImpl;
20211
20911
  exports.DelegatorNotConfiguredError = DelegatorNotConfiguredError;
20912
+ exports.DescriptorIdentity = DescriptorIdentity;
20212
20913
  exports.DescriptorSigningProviderMissingError = DescriptorSigningProviderMissingError;
20213
20914
  exports.DustChangeError = DustChangeError;
20214
20915
  exports.ELECTRUM_TCP_HOST = ELECTRUM_TCP_HOST;
@@ -20240,6 +20941,7 @@ exports.MissingSigningDescriptorError = MissingSigningDescriptorError;
20240
20941
  exports.MnemonicIdentity = MnemonicIdentity;
20241
20942
  exports.OnchainWallet = OnchainWallet;
20242
20943
  exports.P2A = P2A;
20944
+ exports.PaymentRouter = PaymentRouter;
20243
20945
  exports.Ramps = Ramps;
20244
20946
  exports.ReadonlyAssetManager = ReadonlyAssetManager;
20245
20947
  exports.ReadonlyDescriptorIdentity = ReadonlyDescriptorIdentity;
@@ -20265,19 +20967,27 @@ exports.WalletMessageHandler = WalletMessageHandler;
20265
20967
  exports.WalletNotInitializedError = WalletNotInitializedError;
20266
20968
  exports.WalletRepositoryImpl = WalletRepositoryImpl;
20267
20969
  exports.WsElectrumChainSource = WsElectrumChainSource;
20970
+ exports.arkRail = arkRail;
20971
+ exports.arkTarget = arkTarget;
20268
20972
  exports.arkade_exports = arkade_exports;
20269
20973
  exports.assertIntentIdUnique = assertIntentIdUnique;
20974
+ exports.assertSendableAmount = assertSendableAmount;
20975
+ exports.assertSubmittedArkTxid = assertSubmittedArkTxid;
20976
+ exports.assetMintResolver = assetMintResolver;
20270
20977
  exports.boardingResolver = boardingResolver;
20978
+ exports.btcTarget = btcTarget;
20271
20979
  exports.buildForfeitTx = buildForfeitTx;
20272
20980
  exports.buildOffchainTx = buildOffchainTx;
20273
20981
  exports.classifyAgainstSignerSet = classifyAgainstSignerSet;
20274
20982
  exports.classifyContractSigner = classifyContractSigner;
20275
20983
  exports.closeDatabase = closeDatabase;
20984
+ exports.collabExitResolver = collabExitResolver;
20276
20985
  exports.combineTapscriptSigs = combineTapscriptSigs;
20277
20986
  exports.contractFromArkContract = contractFromArkContract;
20278
20987
  exports.contractFromArkContractWithAddress = contractFromArkContractWithAddress;
20279
20988
  exports.createAssetPacket = createAssetPacket;
20280
20989
  exports.createDefaultActivityRegistry = createDefaultActivityRegistry;
20990
+ exports.createDefaultPaymentRouter = createDefaultPaymentRouter;
20281
20991
  exports.createExitChainResolver = createExitChainResolver;
20282
20992
  exports.decodeArkContract = decodeArkContract;
20283
20993
  exports.deserializeAssets = deserializeAssets;
@@ -20292,22 +21002,31 @@ exports.hasBoardingTxExpired = hasBoardingTxExpired;
20292
21002
  exports.hasCandidates = hasCandidates;
20293
21003
  exports.intentMatchesFilter = intentMatchesFilter;
20294
21004
  exports.intentPageBounds = intentPageBounds;
21005
+ exports.invoiceTarget = invoiceTarget;
20295
21006
  exports.isArkContract = isArkContract;
20296
21007
  exports.isBatchSignable = isBatchSignable;
21008
+ exports.isBtcAddress = isBtcAddress;
20297
21009
  exports.isCooperativelyMigratable = isCooperativelyMigratable;
20298
21010
  exports.isDiscoverable = isDiscoverable;
21011
+ exports.isHDDeterministicSignCapable = isHDDeterministicSignCapable;
21012
+ exports.isHDWalletCapable = isHDWalletCapable;
21013
+ exports.isLightningInvoice = isLightningInvoice;
21014
+ exports.isLnurl = isLnurl;
20299
21015
  exports.isMessageBusInitializingError = isMessageBusInitializingError;
20300
21016
  exports.isMessageBusNotInitializedError = isMessageBusNotInitializedError;
20301
- exports.isRetryableProviderError = isRetryableProviderError;
20302
21017
  exports.isSubdust = isSubdust;
20303
21018
  exports.isTerminalIntentState = isTerminalIntentState;
20304
21019
  exports.isValidArkAddress = isValidArkAddress;
20305
21020
  exports.isVtxoExpiringSoon = isVtxoExpiringSoon;
20306
21021
  exports.isVtxoForScript = isVtxoForScript;
21022
+ exports.makeHandle = makeHandle;
21023
+ exports.matchServerCheckpoints = matchServerCheckpoints;
20307
21024
  exports.mergeChainedTxType = mergeChainedTxType;
20308
21025
  exports.migrateWalletRepository = migrateWalletRepository;
21026
+ exports.onchainRail = onchainRail;
20309
21027
  exports.openDatabase = openDatabase;
20310
21028
  exports.requiresMigration = requiresMigration;
21029
+ exports.resolveSendAmount = resolveSendAmount;
20311
21030
  exports.rollbackMigration = rollbackMigration;
20312
21031
  exports.saveVtxosForContract = saveVtxosForContract;
20313
21032
  exports.scriptFromArkAddress = scriptFromArkAddress;
@@ -20320,10 +21039,11 @@ exports.serializeVtxo = serializeVtxo;
20320
21039
  exports.setupServiceWorker = setupServiceWorker;
20321
21040
  exports.signerSetFromInfo = signerSetFromInfo;
20322
21041
  exports.toXOnlySignerHex = toXOnlySignerHex;
21042
+ exports.tryResolveSendAmount = tryResolveSendAmount;
20323
21043
  exports.validateConnectorsTxGraph = validateConnectorsTxGraph;
20324
21044
  exports.validateVtxoTxGraph = validateVtxoTxGraph;
20325
21045
  exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
20326
21046
  exports.waitForIncomingFunds = waitForIncomingFunds;
20327
21047
  exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
20328
- //# sourceMappingURL=chunk-3YC3LQ2E.cjs.map
20329
- //# sourceMappingURL=chunk-3YC3LQ2E.cjs.map
21048
+ //# sourceMappingURL=chunk-ZPL34T2Q.cjs.map
21049
+ //# sourceMappingURL=chunk-ZPL34T2Q.cjs.map