@arkade-os/sdk 0.4.66 → 0.4.67

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 (80) hide show
  1. package/README.md +66 -15
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +2 -2
  4. package/dist/adapters/expo.d.ts +2 -2
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/adapters/indexedDB.cjs +5 -5
  7. package/dist/adapters/indexedDB.js +4 -4
  8. package/dist/{asyncStorageTaskQueue-BZcIN7sA.d.cts → asyncStorageTaskQueue-LTpeXYaD.d.cts} +2 -2
  9. package/dist/{asyncStorageTaskQueue-B6SijMi3.d.ts → asyncStorageTaskQueue-Za-e_zMk.d.ts} +2 -2
  10. package/dist/{chunk-ZIRFXBKL.cjs → chunk-2JV4VQ7C.cjs} +33 -13
  11. package/dist/chunk-2JV4VQ7C.cjs.map +1 -0
  12. package/dist/{chunk-J33ZEM3A.js → chunk-3WIWNE4P.js} +33 -14
  13. package/dist/chunk-3WIWNE4P.js.map +1 -0
  14. package/dist/{chunk-CYOI4PEA.js → chunk-6TAQF6EV.js} +107 -13
  15. package/dist/chunk-6TAQF6EV.js.map +1 -0
  16. package/dist/{chunk-DSC3G6QZ.js → chunk-AEWJU6NZ.js} +1006 -167
  17. package/dist/chunk-AEWJU6NZ.js.map +1 -0
  18. package/dist/{chunk-3S3JZUEN.cjs → chunk-CO3KKSWM.cjs} +17 -17
  19. package/dist/{chunk-3S3JZUEN.cjs.map → chunk-CO3KKSWM.cjs.map} +1 -1
  20. package/dist/{chunk-55ZZ6RBL.js → chunk-EALWOVHK.js} +4 -4
  21. package/dist/{chunk-55ZZ6RBL.js.map → chunk-EALWOVHK.js.map} +1 -1
  22. package/dist/{chunk-5E6IZNRG.cjs → chunk-MJUTO3PY.cjs} +1413 -563
  23. package/dist/chunk-MJUTO3PY.cjs.map +1 -0
  24. package/dist/{chunk-R5POS3RS.js → chunk-MZFUZUTQ.js} +4 -4
  25. package/dist/{chunk-R5POS3RS.js.map → chunk-MZFUZUTQ.js.map} +1 -1
  26. package/dist/{chunk-PXPPZF5K.cjs → chunk-OIZ2V2VD.cjs} +152 -58
  27. package/dist/chunk-OIZ2V2VD.cjs.map +1 -0
  28. package/dist/{chunk-IM6IKNSL.cjs → chunk-R2YAMONM.cjs} +17 -17
  29. package/dist/{chunk-IM6IKNSL.cjs.map → chunk-R2YAMONM.cjs.map} +1 -1
  30. package/dist/{chunk-2JZGPXU4.js → chunk-X3VEMUVV.js} +3 -3
  31. package/dist/{chunk-2JZGPXU4.js.map → chunk-X3VEMUVV.js.map} +1 -1
  32. package/dist/{chunk-LL47QIHD.cjs → chunk-YDRZDZPP.cjs} +10 -10
  33. package/dist/{chunk-LL47QIHD.cjs.map → chunk-YDRZDZPP.cjs.map} +1 -1
  34. package/dist/contracts/handlers/index.cjs +9 -9
  35. package/dist/contracts/handlers/index.d.cts +3 -3
  36. package/dist/contracts/handlers/index.d.ts +3 -3
  37. package/dist/contracts/handlers/index.js +2 -2
  38. package/dist/{delegate-YXupcWWJ.d.cts → delegate-Bz2e2zXY.d.cts} +1 -1
  39. package/dist/{delegate-T-vgxMYZ.d.ts → delegate-cdmzb2f9.d.ts} +1 -1
  40. package/dist/{wallet-CNibc3yJ.d.ts → hdWalletCapable-BSjuUYOO.d.cts} +318 -127
  41. package/dist/{wallet-DJN1QgFt.d.cts → hdWalletCapable-Hi12xjCJ.d.ts} +318 -127
  42. package/dist/{index-e7LYXk1d.d.cts → index-BiACuWaf.d.ts} +109 -13
  43. package/dist/{index-D_FgwLH9.d.ts → index-D2GjZxBr.d.cts} +109 -13
  44. package/dist/{index-uUE_uQPn.d.ts → index-DU5o_hz7.d.cts} +206 -19
  45. package/dist/{index-uUE_uQPn.d.cts → index-DU5o_hz7.d.ts} +206 -19
  46. package/dist/index.cjs +322 -278
  47. package/dist/index.d.cts +291 -41
  48. package/dist/index.d.ts +291 -41
  49. package/dist/index.js +4 -4
  50. package/dist/repositories/realm/index.cjs +19 -19
  51. package/dist/repositories/realm/index.d.cts +2 -2
  52. package/dist/repositories/realm/index.d.ts +2 -2
  53. package/dist/repositories/realm/index.js +5 -5
  54. package/dist/repositories/sqlite/index.cjs +18 -18
  55. package/dist/repositories/sqlite/index.d.cts +2 -2
  56. package/dist/repositories/sqlite/index.d.ts +2 -2
  57. package/dist/repositories/sqlite/index.js +5 -5
  58. package/dist/{taskRunner-BOVcIH1N.d.cts → taskRunner-BZJMLQ6g.d.cts} +2 -2
  59. package/dist/{taskRunner-DNyD1kXG.d.ts → taskRunner-DATaRQus.d.ts} +2 -2
  60. package/dist/wallet/expo/background.cjs +14 -14
  61. package/dist/wallet/expo/background.d.cts +3 -3
  62. package/dist/wallet/expo/background.d.ts +3 -3
  63. package/dist/wallet/expo/background.js +6 -6
  64. package/dist/wallet/expo/index.cjs +18 -14
  65. package/dist/wallet/expo/index.cjs.map +1 -1
  66. package/dist/wallet/expo/index.d.cts +7 -5
  67. package/dist/wallet/expo/index.d.ts +7 -5
  68. package/dist/wallet/expo/index.js +10 -6
  69. package/dist/wallet/expo/index.js.map +1 -1
  70. package/dist/worker/expo/index.cjs +9 -9
  71. package/dist/worker/expo/index.d.cts +4 -4
  72. package/dist/worker/expo/index.d.ts +4 -4
  73. package/dist/worker/expo/index.js +5 -5
  74. package/package.json +3 -3
  75. package/dist/chunk-5E6IZNRG.cjs.map +0 -1
  76. package/dist/chunk-CYOI4PEA.js.map +0 -1
  77. package/dist/chunk-DSC3G6QZ.js.map +0 -1
  78. package/dist/chunk-J33ZEM3A.js.map +0 -1
  79. package/dist/chunk-PXPPZF5K.cjs.map +0 -1
  80. package/dist/chunk-ZIRFXBKL.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunk3S3JZUEN_cjs = require('./chunk-3S3JZUEN.cjs');
4
- var chunkPXPPZF5K_cjs = require('./chunk-PXPPZF5K.cjs');
5
- var chunkZIRFXBKL_cjs = require('./chunk-ZIRFXBKL.cjs');
3
+ var chunkCO3KKSWM_cjs = require('./chunk-CO3KKSWM.cjs');
4
+ var chunkOIZ2V2VD_cjs = require('./chunk-OIZ2V2VD.cjs');
5
+ var chunk2JV4VQ7C_cjs = require('./chunk-2JV4VQ7C.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');
@@ -188,7 +188,7 @@ var TreeSignerSession = class _TreeSignerSession {
188
188
  noncesByPubkey.set(base.hex.encode(myPublicKey.subarray(1)), myNonce);
189
189
  const tx = this.graph.find(txid);
190
190
  if (!tx) throw new Error(`missing tx for txid ${txid}`);
191
- const cosigners = chunkZIRFXBKL_cjs.getArkPsbtFields(tx.root, 0, chunkZIRFXBKL_cjs.CosignerPublicKey).map(
191
+ const cosigners = chunk2JV4VQ7C_cjs.getArkPsbtFields(tx.root, 0, chunk2JV4VQ7C_cjs.CosignerPublicKey).map(
192
192
  (c) => base.hex.encode(c.key.subarray(1))
193
193
  // xonly pubkey
194
194
  );
@@ -240,7 +240,7 @@ var TreeSignerSession = class _TreeSignerSession {
240
240
  if (!aggNonce) throw new Error("missing aggregate nonce");
241
241
  const prevoutAmounts = [];
242
242
  const prevoutScripts = [];
243
- const cosigners = chunkZIRFXBKL_cjs.getArkPsbtFields(g.root, 0, chunkZIRFXBKL_cjs.CosignerPublicKey).map((c) => c.key);
243
+ const cosigners = chunk2JV4VQ7C_cjs.getArkPsbtFields(g.root, 0, chunk2JV4VQ7C_cjs.CosignerPublicKey).map((c) => c.key);
244
244
  const { finalKey } = aggregateKeys(cosigners, true, {
245
245
  taprootTweak: this.scriptRoot
246
246
  });
@@ -431,7 +431,7 @@ var SeedIdentity = class _SeedIdentity {
431
431
  let network;
432
432
  if ("descriptor" in opts && typeof opts.descriptor === "string") {
433
433
  descriptor = opts.descriptor;
434
- network = chunkPXPPZF5K_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
434
+ network = chunkOIZ2V2VD_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
435
435
  } else {
436
436
  network = opts.isMainnet ?? true ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
437
437
  descriptor = descriptorsScure.scriptExpressions.trBIP32({
@@ -529,7 +529,7 @@ var SeedIdentity = class _SeedIdentity {
529
529
  * `StaticDescriptorProvider` for legacy single-key wallets.
530
530
  */
531
531
  isOurs(descriptor) {
532
- return chunkPXPPZF5K_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
532
+ return chunkOIZ2V2VD_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
533
533
  }
534
534
  /**
535
535
  * Signs each request with the key derived from its descriptor.
@@ -578,7 +578,7 @@ var SeedIdentity = class _SeedIdentity {
578
578
  }
579
579
  // ── internal helpers ─────────────────────────────────────────────
580
580
  derivePrivateKeyForDescriptor(descriptor) {
581
- const network = chunkPXPPZF5K_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
581
+ const network = chunkOIZ2V2VD_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
582
582
  const expansion = descriptorsScure.expand({ descriptor, network });
583
583
  if (expansion.isRanged) {
584
584
  throw new Error(
@@ -664,7 +664,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
664
664
  */
665
665
  descriptor;
666
666
  constructor(descriptor) {
667
- const network = chunkPXPPZF5K_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
667
+ const network = chunkOIZ2V2VD_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
668
668
  let expansion;
669
669
  try {
670
670
  expansion = descriptorsScure.expand({ descriptor, network, index: 0 });
@@ -714,7 +714,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
714
714
  * `StaticDescriptorProvider` for legacy single-key wallets.
715
715
  */
716
716
  isOurs(descriptor) {
717
- return chunkPXPPZF5K_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
717
+ return chunkOIZ2V2VD_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
718
718
  }
719
719
  };
720
720
  function serializeSeedOwnedSigningIdentity(identity) {
@@ -876,10 +876,10 @@ var DescriptorIdentity = class {
876
876
  this.base = base;
877
877
  }
878
878
  async xOnlyPublicKey() {
879
- return chunkPXPPZF5K_cjs.deriveDescriptorLeafPubKey(this.descriptor);
879
+ return chunkOIZ2V2VD_cjs.deriveDescriptorLeafPubKey(this.descriptor);
880
880
  }
881
881
  async compressedPublicKey() {
882
- return chunkPXPPZF5K_cjs.deriveDescriptorLeafCompressedPubKey(this.descriptor);
882
+ return chunkOIZ2V2VD_cjs.deriveDescriptorLeafCompressedPubKey(this.descriptor);
883
883
  }
884
884
  async sign(tx, inputIndexes) {
885
885
  const [signed] = await this.signer.signWithDescriptor([
@@ -939,14 +939,20 @@ var ForeignDescriptorError = class extends Error {
939
939
  descriptor;
940
940
  name = "ForeignDescriptorError";
941
941
  };
942
+ var WalletCannotAllocateAddressError = class extends Error {
943
+ name = "WalletCannotAllocateAddressError";
944
+ constructor(reason, options) {
945
+ super(`cannot allocate a fresh address: ${reason}`, options);
946
+ }
947
+ };
942
948
  async function resolveDescriptorSigner(descriptor, identity, provider) {
943
949
  const owner = provider?.isOurs(descriptor) ? provider : isHDCapableIdentity(identity) && identity.isOurs(descriptor) ? identity : void 0;
944
- if (owner && chunkPXPPZF5K_cjs.parseHDDescriptor(descriptor)) {
950
+ if (owner && chunkOIZ2V2VD_cjs.parseHDDescriptor(descriptor)) {
945
951
  return new DescriptorIdentity({ descriptor, signer: owner, base: identity });
946
952
  }
947
953
  let key;
948
954
  try {
949
- key = chunkPXPPZF5K_cjs.deriveDescriptorLeafPubKey(descriptor);
955
+ key = chunkOIZ2V2VD_cjs.deriveDescriptorLeafPubKey(descriptor);
950
956
  } catch {
951
957
  throw new ForeignDescriptorError(descriptor);
952
958
  }
@@ -963,6 +969,10 @@ function isHDAllocationCapable(value) {
963
969
  const v = value;
964
970
  return typeof v.getNextSigningDescriptor === "function" && typeof v.advanceSigningDescriptorWatermark === "function";
965
971
  }
972
+ function isAddressAllocationCapable(value) {
973
+ if (typeof value !== "object" || value === null) return false;
974
+ return typeof value.getNewAddresses === "function";
975
+ }
966
976
 
967
977
  // ../../node_modules/@noble/hashes/utils.js
968
978
  function isBytes(a) {
@@ -1317,22 +1327,33 @@ function buildSaltedPreimageMessage(xonly, salt) {
1317
1327
  }
1318
1328
  var PREIMAGE_INDEX = 0;
1319
1329
  function isPerArtifactDescriptor(descriptor) {
1320
- return chunkPXPPZF5K_cjs.parseHDDescriptor(descriptor) !== null;
1330
+ return chunkOIZ2V2VD_cjs.parseHDDescriptor(descriptor) !== null;
1321
1331
  }
1322
1332
  async function provisionDescriptor(wallet) {
1323
1333
  const allocated = isHDAllocationCapable(wallet) ? await wallet.getNextSigningDescriptor() : void 0;
1324
- return allocated ?? await chunkPXPPZF5K_cjs.identityDescriptor(wallet.identity);
1334
+ return allocated ?? await chunkOIZ2V2VD_cjs.identityDescriptor(wallet.identity);
1325
1335
  }
1326
1336
  async function provisionRefundKey(wallet) {
1327
- const descriptor = await provisionDescriptor(wallet);
1337
+ const descriptor = await chunkOIZ2V2VD_cjs.identityDescriptor(wallet.identity);
1328
1338
  const signer = await contractSigner(wallet, descriptor);
1329
- return { descriptor, pubkey: await signer.xOnlyPublicKey() };
1339
+ const pubkey = await signer.xOnlyPublicKey();
1340
+ const identityPubkey = await wallet.identity.xOnlyPublicKey();
1341
+ if (!utils_js.equalBytes(pubkey, identityPubkey)) {
1342
+ throw new Error(
1343
+ "provisionRefundKey: descriptor pubkey does not match wallet identity \u2014 the refund key and the refund address would be on different keys"
1344
+ );
1345
+ }
1346
+ const address = await wallet.getAddress();
1347
+ const { pkScript } = chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
1348
+ return { descriptor, pubkey, pkScript, address };
1330
1349
  }
1331
1350
  async function provisionClaimSecret(wallet, opts = {}) {
1332
1351
  if (opts.preimage && opts.preimage.length !== 32) {
1333
1352
  throw new Error(`preimage must be 32 bytes, got ${opts.preimage.length}`);
1334
1353
  }
1335
- const { descriptor, pubkey } = await provisionRefundKey(wallet);
1354
+ const descriptor = await provisionDescriptor(wallet);
1355
+ const signer = await contractSigner(wallet, descriptor);
1356
+ const pubkey = await signer.xOnlyPublicKey();
1336
1357
  const claim = async () => {
1337
1358
  if (opts.preimage) return { preimage: opts.preimage, mustPersistPreimage: true };
1338
1359
  if (isPerArtifactDescriptor(descriptor)) {
@@ -1369,7 +1390,7 @@ async function contractSigner(wallet, descriptor) {
1369
1390
  const signer = isHDWalletCapable(wallet) ? await wallet.signerForDescriptor(descriptor) : wallet.identity;
1370
1391
  let expected;
1371
1392
  try {
1372
- expected = chunkPXPPZF5K_cjs.deriveDescriptorLeafPubKey(descriptor);
1393
+ expected = chunkOIZ2V2VD_cjs.deriveDescriptorLeafPubKey(descriptor);
1373
1394
  } catch (cause) {
1374
1395
  throw new ForeignDescriptorError(descriptor, { cause });
1375
1396
  }
@@ -1588,14 +1609,14 @@ var RestDelegateProvider = class {
1588
1609
  */
1589
1610
  async delegate(intent, forfeitTxs, options) {
1590
1611
  const url = `${this.url}/v1/delegate`;
1591
- const response = await chunkZIRFXBKL_cjs.baseFetch(url, {
1612
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(url, {
1592
1613
  method: "POST",
1593
1614
  headers: {
1594
1615
  "Content-Type": "application/json"
1595
1616
  },
1596
1617
  body: JSON.stringify({
1597
1618
  intent: {
1598
- message: chunkZIRFXBKL_cjs.Intent.encodeMessage(intent.message),
1619
+ message: chunk2JV4VQ7C_cjs.Intent.encodeMessage(intent.message),
1599
1620
  proof: intent.proof
1600
1621
  },
1601
1622
  forfeit_txs: forfeitTxs,
@@ -1615,7 +1636,7 @@ var RestDelegateProvider = class {
1615
1636
  */
1616
1637
  async getDelegateInfo() {
1617
1638
  const url = `${this.url}/v1/delegator/info`;
1618
- const response = await chunkZIRFXBKL_cjs.rateGate.runHttp(url, () => chunkZIRFXBKL_cjs.baseFetch(url));
1639
+ const response = await chunk2JV4VQ7C_cjs.rateGate.runHttp(url, () => chunk2JV4VQ7C_cjs.baseFetch(url));
1619
1640
  if (!response.ok) {
1620
1641
  const errorText2 = await response.text();
1621
1642
  throw new Error(`Failed to get delegate info: ${errorText2}`);
@@ -1632,8 +1653,6 @@ var RestDelegatorProvider = RestDelegateProvider;
1632
1653
  function isDelegateInfo(data) {
1633
1654
  return !!data && typeof data === "object" && "pubkey" in data && "fee" in data && typeof data.pubkey === "string" && typeof data.fee === "string" && data.pubkey !== "" && data.fee !== "" && (typeof data.delegateAddress === "string" && data.delegateAddress !== "" || typeof data.delegatorAddress === "string" && data.delegatorAddress !== "");
1634
1655
  }
1635
-
1636
- // src/providers/onchain.ts
1637
1656
  var ESPLORA_URL = {
1638
1657
  bitcoin: "https://mempool.arkade.sh/api",
1639
1658
  testnet: "https://mempool.space/testnet/api",
@@ -1642,7 +1661,7 @@ var ESPLORA_URL = {
1642
1661
  regtest: "http://localhost:3000/api"
1643
1662
  };
1644
1663
  var EsploraProvider = class {
1645
- constructor(baseUrl = ESPLORA_URL[chunkZIRFXBKL_cjs.DEFAULT_NETWORK_NAME], opts) {
1664
+ constructor(baseUrl = ESPLORA_URL[chunk2JV4VQ7C_cjs.DEFAULT_NETWORK_NAME], opts) {
1646
1665
  this.baseUrl = baseUrl;
1647
1666
  this.pollingInterval = opts?.pollingInterval ?? 15e3;
1648
1667
  this.forcePolling = opts?.forcePolling ?? false;
@@ -1651,14 +1670,14 @@ var EsploraProvider = class {
1651
1670
  pollingInterval;
1652
1671
  forcePolling;
1653
1672
  async getCoins(address) {
1654
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1673
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1655
1674
  if (!response.ok) {
1656
1675
  throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
1657
1676
  }
1658
1677
  return response.json();
1659
1678
  }
1660
1679
  async getFeeRate() {
1661
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1680
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1662
1681
  if (response.status === 404) {
1663
1682
  return void 0;
1664
1683
  }
@@ -1679,7 +1698,7 @@ var EsploraProvider = class {
1679
1698
  }
1680
1699
  }
1681
1700
  async getTxOutspends(txid) {
1682
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1701
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1683
1702
  if (!response.ok) {
1684
1703
  const error = await response.text();
1685
1704
  throw new Error(`Failed to get transaction outspends: ${error}`);
@@ -1687,15 +1706,23 @@ var EsploraProvider = class {
1687
1706
  return response.json();
1688
1707
  }
1689
1708
  async getTransactions(address) {
1690
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1709
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1691
1710
  if (!response.ok) {
1692
1711
  const error = await response.text();
1693
1712
  throw new Error(`Failed to get transactions: ${error}`);
1694
1713
  }
1695
1714
  return response.json();
1696
1715
  }
1716
+ async getRawTransaction(txid) {
1717
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/hex`);
1718
+ if (!response.ok) {
1719
+ const error = await response.text();
1720
+ throw new Error(`Failed to get raw transaction ${txid}: ${error}`);
1721
+ }
1722
+ return base.hex.decode((await response.text()).trim());
1723
+ }
1697
1724
  async getTxStatus(txid) {
1698
- const txresponse = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1725
+ const txresponse = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1699
1726
  if (!txresponse.ok) {
1700
1727
  throw new Error(txresponse.statusText);
1701
1728
  }
@@ -1703,7 +1730,7 @@ var EsploraProvider = class {
1703
1730
  if (!tx.status.confirmed) {
1704
1731
  return { confirmed: false };
1705
1732
  }
1706
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1733
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1707
1734
  if (!response.ok) {
1708
1735
  throw new Error(`Failed to get transaction status: ${response.statusText}`);
1709
1736
  }
@@ -1787,7 +1814,7 @@ var EsploraProvider = class {
1787
1814
  return stopFunc;
1788
1815
  }
1789
1816
  async getChainTip() {
1790
- const tipBlocks = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/blocks`);
1817
+ const tipBlocks = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/blocks`);
1791
1818
  if (!tipBlocks.ok) {
1792
1819
  throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
1793
1820
  }
@@ -1806,7 +1833,7 @@ var EsploraProvider = class {
1806
1833
  };
1807
1834
  }
1808
1835
  async broadcastPackage(parent, child) {
1809
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1836
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1810
1837
  method: "POST",
1811
1838
  headers: {
1812
1839
  "Content-Type": "application/json"
@@ -1817,10 +1844,12 @@ var EsploraProvider = class {
1817
1844
  const error = await response.text();
1818
1845
  throw new Error(`Failed to broadcast package: ${error}`);
1819
1846
  }
1820
- return response.json();
1847
+ const result = await response.json();
1848
+ assertPackageAccepted(result);
1849
+ return result;
1821
1850
  }
1822
1851
  async broadcastTx(tx) {
1823
- const response = await chunkZIRFXBKL_cjs.baseFetch(`${this.baseUrl}/tx`, {
1852
+ const response = await chunk2JV4VQ7C_cjs.baseFetch(`${this.baseUrl}/tx`, {
1824
1853
  method: "POST",
1825
1854
  headers: {
1826
1855
  "Content-Type": "text/plain"
@@ -1834,6 +1863,24 @@ var EsploraProvider = class {
1834
1863
  return response.text();
1835
1864
  }
1836
1865
  };
1866
+ function assertPackageAccepted(result) {
1867
+ if (!result || typeof result !== "object") return;
1868
+ const r = result;
1869
+ const msg = typeof r.package_msg === "string" ? r.package_msg : void 0;
1870
+ if (msg === void 0 || msg === "success") return;
1871
+ const reasons = [];
1872
+ const results = r["tx-results"];
1873
+ if (results && typeof results === "object") {
1874
+ for (const entry of Object.values(results)) {
1875
+ if (!entry || typeof entry !== "object" || entry.error === void 0) continue;
1876
+ const txid = typeof entry.txid === "string" ? entry.txid : "unknown tx";
1877
+ reasons.push(`${txid}: ${String(entry.error)}`);
1878
+ }
1879
+ }
1880
+ throw new Error(
1881
+ reasons.length > 0 ? `Package rejected (${msg}) \u2014 ${reasons.join("; ")}` : `Package rejected (${msg})`
1882
+ );
1883
+ }
1837
1884
  function isValidBlocksTip(tip) {
1838
1885
  return Array.isArray(tip) && tip.every((t) => {
1839
1886
  return t && typeof t === "object" && typeof t.id === "string" && t.id.length > 0 && typeof t.height === "number" && t.height >= 0 && typeof t.mediantime === "number" && t.mediantime > 0;
@@ -1982,7 +2029,7 @@ function findP2AOutput(tx) {
1982
2029
  var CHILD_DUST_AMOUNT = 546;
1983
2030
  function buildAnchorChild(params) {
1984
2031
  const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
1985
- const child = new chunkZIRFXBKL_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
2032
+ const child = new chunk2JV4VQ7C_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
1986
2033
  child.addInput(findP2AOutput(parent));
1987
2034
  const estimator = TxWeightEstimator.create().addP2AInput();
1988
2035
  for (const _ of fundingCoins) {
@@ -2030,7 +2077,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
2030
2077
  );
2031
2078
  }
2032
2079
  function buildForfeitTxWithOutput(inputs, output, txLocktime) {
2033
- const tx = new chunkZIRFXBKL_cjs.Transaction({
2080
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({
2034
2081
  version: 3,
2035
2082
  lockTime: txLocktime
2036
2083
  });
@@ -2106,7 +2153,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
2106
2153
  if (previousScriptKey.length !== 32) {
2107
2154
  throw new Error(`parent output ${childIndex} has invalid script`);
2108
2155
  }
2109
- const cosigners = chunkZIRFXBKL_cjs.getArkPsbtFields(child.root, 0, chunkZIRFXBKL_cjs.CosignerPublicKey);
2156
+ const cosigners = chunk2JV4VQ7C_cjs.getArkPsbtFields(child.root, 0, chunk2JV4VQ7C_cjs.CosignerPublicKey);
2110
2157
  if (cosigners.length === 0) {
2111
2158
  throw ErrMissingCosignersPublicKeys;
2112
2159
  }
@@ -2164,7 +2211,7 @@ var EmulatorPacket = class _EmulatorPacket {
2164
2211
  return new _EmulatorPacket(entries);
2165
2212
  }
2166
2213
  static fromBytes(data) {
2167
- const reader = new chunk3S3JZUEN_cjs.BufferReader(data);
2214
+ const reader = new chunkCO3KKSWM_cjs.BufferReader(data);
2168
2215
  const entryCount = reader.readCompactSize();
2169
2216
  const entries = [];
2170
2217
  for (let i = 0; i < entryCount; i++) {
@@ -2182,7 +2229,7 @@ var EmulatorPacket = class _EmulatorPacket {
2182
2229
  return _EmulatorPacket.PACKET_TYPE;
2183
2230
  }
2184
2231
  serialize() {
2185
- const writer = new chunk3S3JZUEN_cjs.BufferWriter();
2232
+ const writer = new chunkCO3KKSWM_cjs.BufferWriter();
2186
2233
  writer.writeCompactSize(this.entries.length);
2187
2234
  for (const entry of this.entries) {
2188
2235
  writer.writeUint16LE(entry.vin);
@@ -2269,7 +2316,7 @@ var Extension = class _Extension {
2269
2316
  `expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
2270
2317
  );
2271
2318
  }
2272
- const reader = new chunk3S3JZUEN_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
2319
+ const reader = new chunkCO3KKSWM_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
2273
2320
  const packets = [];
2274
2321
  while (reader.remaining() > 0) {
2275
2322
  const packetType = reader.readByte();
@@ -2343,7 +2390,7 @@ var Extension = class _Extension {
2343
2390
  */
2344
2391
  getAssetPacket() {
2345
2392
  for (const p of this.packets) {
2346
- if (p instanceof chunk3S3JZUEN_cjs.Packet) {
2393
+ if (p instanceof chunkCO3KKSWM_cjs.Packet) {
2347
2394
  return p;
2348
2395
  }
2349
2396
  }
@@ -2381,8 +2428,8 @@ var Extension = class _Extension {
2381
2428
  };
2382
2429
  function parsePacket(packetType, data) {
2383
2430
  switch (packetType) {
2384
- case chunk3S3JZUEN_cjs.Packet.PACKET_TYPE:
2385
- return chunk3S3JZUEN_cjs.Packet.fromBytes(data);
2431
+ case chunkCO3KKSWM_cjs.Packet.PACKET_TYPE:
2432
+ return chunkCO3KKSWM_cjs.Packet.fromBytes(data);
2386
2433
  case EmulatorPacket.PACKET_TYPE:
2387
2434
  return EmulatorPacket.fromBytes(data);
2388
2435
  default:
@@ -2429,16 +2476,16 @@ function buildOpReturnScript(data) {
2429
2476
  }
2430
2477
  return script;
2431
2478
  }
2432
- var ErrOffchainOutputNotFound = (address) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(`offchain send output not found: ${address}`);
2433
- var ErrInvalidAssetOutputAmount = (got, want, assetId) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2479
+ var ErrOffchainOutputNotFound = (address) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(`offchain send output not found: ${address}`);
2480
+ var ErrInvalidAssetOutputAmount = (got, want, assetId) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2434
2481
  `invalid asset output amount for ${assetId}: got ${got}, want ${want}`
2435
2482
  );
2436
- var ErrAssetGroupNotFound = (assetId) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(`asset group not found in batch leaf: ${assetId}`);
2437
- var ErrAssetOutputNotFound = (assetId, outputIndex) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2483
+ var ErrAssetGroupNotFound = (assetId) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(`asset group not found in batch leaf: ${assetId}`);
2484
+ var ErrAssetOutputNotFound = (assetId, outputIndex) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2438
2485
  `asset output not found in asset group ${assetId} at index ${outputIndex}`
2439
2486
  );
2440
- var ErrOnchainOutputNotFound = (address) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(`onchain output not found: ${address}`);
2441
- var ErrUnvalidatedOffchainOutput = (address) => new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2487
+ var ErrOnchainOutputNotFound = (address) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(`onchain output not found: ${address}`);
2488
+ var ErrUnvalidatedOffchainOutput = (address) => new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2442
2489
  `offchain output ${address} cannot be validated: virtual output tree signing did not run`
2443
2490
  );
2444
2491
  var ErrInvalidOnchainOutputAmount = (address) => new Error(`invalid onchain output amount: ${address}`);
@@ -2447,7 +2494,7 @@ var ErrInvalidOffchainOutputAmount = (address) => new Error(`invalid offchain ou
2447
2494
  function assertFinalCommitmentMatchesValidated(finalCommitmentTx, validatedCommitmentTxid, context) {
2448
2495
  if (!validatedCommitmentTxid) return;
2449
2496
  if (finalCommitmentTx.id === validatedCommitmentTxid) return;
2450
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2497
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2451
2498
  `${context}: finalization commitment tx ${finalCommitmentTx.id} differs from the validated commitment tx ${validatedCommitmentTxid}`
2452
2499
  );
2453
2500
  }
@@ -2457,7 +2504,7 @@ function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, netwo
2457
2504
  for (const recipient of recipients) {
2458
2505
  let arkAddress;
2459
2506
  try {
2460
- arkAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(recipient.address);
2507
+ arkAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(recipient.address);
2461
2508
  } catch {
2462
2509
  validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
2463
2510
  continue;
@@ -2469,7 +2516,7 @@ function validateBatchRecipientsWithoutTree(commitmentTx, recipients, network) {
2469
2516
  const usedOnchainOutputs = /* @__PURE__ */ new Set();
2470
2517
  for (const recipient of recipients) {
2471
2518
  try {
2472
- chunkZIRFXBKL_cjs.ArkAddress.decode(recipient.address);
2519
+ chunk2JV4VQ7C_cjs.ArkAddress.decode(recipient.address);
2473
2520
  } catch {
2474
2521
  validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
2475
2522
  continue;
@@ -2702,7 +2749,7 @@ function assetMintResolver() {
2702
2749
  if (!tx.assets?.length || !tx.key.arkTxid) return void 0;
2703
2750
  const minted = tx.assets.filter((a) => {
2704
2751
  try {
2705
- return base.hex.encode(chunk3S3JZUEN_cjs.AssetId.fromString(a.assetId).txid) === tx.key.arkTxid;
2752
+ return base.hex.encode(chunkCO3KKSWM_cjs.AssetId.fromString(a.assetId).txid) === tx.key.arkTxid;
2706
2753
  } catch {
2707
2754
  return false;
2708
2755
  }
@@ -2745,7 +2792,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2745
2792
  const existing = inputsByAssetId.get(asset.assetId);
2746
2793
  inputsByAssetId.set(asset.assetId, [
2747
2794
  ...existing ?? [],
2748
- chunk3S3JZUEN_cjs.AssetInput.create(inputIndex, asset.amount)
2795
+ chunkCO3KKSWM_cjs.AssetInput.create(inputIndex, asset.amount)
2749
2796
  ]);
2750
2797
  }
2751
2798
  }
@@ -2757,7 +2804,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2757
2804
  const existing = outputsByAssetId.get(asset.assetId);
2758
2805
  outputsByAssetId.set(asset.assetId, [
2759
2806
  ...existing ?? [],
2760
- chunk3S3JZUEN_cjs.AssetOutput.create(outputIndex, asset.amount)
2807
+ chunkCO3KKSWM_cjs.AssetOutput.create(outputIndex, asset.amount)
2761
2808
  ]);
2762
2809
  }
2763
2810
  }
@@ -2768,7 +2815,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2768
2815
  const existing = outputsByAssetId.get(asset.assetId);
2769
2816
  outputsByAssetId.set(asset.assetId, [
2770
2817
  ...existing ?? [],
2771
- chunk3S3JZUEN_cjs.AssetOutput.create(outputIndex, asset.amount)
2818
+ chunkCO3KKSWM_cjs.AssetOutput.create(outputIndex, asset.amount)
2772
2819
  ]);
2773
2820
  }
2774
2821
  }
@@ -2777,11 +2824,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
2777
2824
  for (const assetIdStr of allAssetIds) {
2778
2825
  const inputs = inputsByAssetId.get(assetIdStr);
2779
2826
  const outputs = outputsByAssetId.get(assetIdStr);
2780
- const assetId = chunk3S3JZUEN_cjs.AssetId.fromString(assetIdStr);
2781
- const group = chunk3S3JZUEN_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
2827
+ const assetId = chunkCO3KKSWM_cjs.AssetId.fromString(assetIdStr);
2828
+ const group = chunkCO3KKSWM_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
2782
2829
  groups.push(group);
2783
2830
  }
2784
- return chunk3S3JZUEN_cjs.Packet.create(groups);
2831
+ return chunkCO3KKSWM_cjs.Packet.create(groups);
2785
2832
  }
2786
2833
  function selectCoinsWithAsset(coins, assetId, requiredAmount) {
2787
2834
  const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
@@ -2818,7 +2865,7 @@ function selectedCoinsToAssetInputs(selectedCoins) {
2818
2865
  }
2819
2866
  function toXOnlySignerHex(pubkeyHex) {
2820
2867
  const bytes = base.hex.decode(pubkeyHex);
2821
- if (bytes.length === 32 || bytes.length === 33) return base.hex.encode(chunkPXPPZF5K_cjs.toXOnly(bytes, "signer key"));
2868
+ if (bytes.length === 32 || bytes.length === 33) return base.hex.encode(chunkOIZ2V2VD_cjs.toXOnly(bytes, "signer key"));
2822
2869
  throw new Error(`invalid signer pubkey length: expected 32 or 33 bytes, got ${bytes.length}`);
2823
2870
  }
2824
2871
  function signerSetFromInfo(info) {
@@ -2865,13 +2912,13 @@ var toTimelock = (value) => ({
2865
2912
  var toSeconds = (t) => t.type === "seconds" ? t.value : t.value * NOMINAL_BLOCK_SECONDS;
2866
2913
  function assertTimelockInPolicy(timelock, policy, label, overrideOption) {
2867
2914
  if (policy.requireSeconds && timelock.type === "blocks") {
2868
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2915
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2869
2916
  `${label} rejected: block-typed timelocks are not accepted (got ${timelock.value})`
2870
2917
  );
2871
2918
  }
2872
2919
  const seconds = toSeconds(timelock);
2873
2920
  if (seconds < policy.minSeconds) {
2874
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2921
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2875
2922
  `${label} rejected: ${timelock.value} ${timelock.type} is below the ${policy.minSeconds}s floor; pass ${overrideOption}: ${seconds}n to Wallet.create to lower it`
2876
2923
  );
2877
2924
  }
@@ -2892,7 +2939,7 @@ function resolveBatchExpiryPolicy(network, overrides) {
2892
2939
  }
2893
2940
  function assertValidBatchExpiry(batchExpiry, policy) {
2894
2941
  if (policy.advertisedVtxoTreeExpiry !== void 0 && batchExpiry !== policy.advertisedVtxoTreeExpiry) {
2895
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2942
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2896
2943
  `batch expiry rejected: ${batchExpiry} does not match the advertised vtxoTreeExpiry ${policy.advertisedVtxoTreeExpiry}`
2897
2944
  );
2898
2945
  }
@@ -2922,21 +2969,21 @@ function resolveCheckpointExitDelayPolicy(network, overrides) {
2922
2969
  function assertValidServerUnrollScript(checkpointTapscript, policy) {
2923
2970
  let script;
2924
2971
  try {
2925
- script = chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(base.hex.decode(checkpointTapscript));
2972
+ script = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(base.hex.decode(checkpointTapscript));
2926
2973
  } catch (e) {
2927
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2974
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2928
2975
  `checkpoint exit delay rejected: invalid checkpointTapscript from server (${e instanceof Error ? e.message : String(e)})`
2929
2976
  );
2930
2977
  }
2931
2978
  if (policy.advertisedForfeitPubkey !== void 0) {
2932
2979
  const { pubkeys } = script.params;
2933
2980
  if (pubkeys.length !== 1) {
2934
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2981
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2935
2982
  `checkpoint exit delay rejected: checkpointTapscript must commit to exactly one pubkey, got ${pubkeys.length} [${pubkeys.map(base.hex.encode).join(", ")}]`
2936
2983
  );
2937
2984
  }
2938
2985
  if (!utils_js.equalBytes(pubkeys[0], policy.advertisedForfeitPubkey)) {
2939
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
2986
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
2940
2987
  `checkpoint exit delay rejected: checkpointTapscript pubkey ${base.hex.encode(pubkeys[0])} does not match the advertised forfeitPubkey ${base.hex.encode(policy.advertisedForfeitPubkey)}`
2941
2988
  );
2942
2989
  }
@@ -2980,8 +3027,8 @@ function buildOffchainTx(inputs, outputs, serverUnrollScript) {
2980
3027
  function buildVirtualTx(inputs, outputs) {
2981
3028
  let lockTime = 0n;
2982
3029
  for (const input of inputs) {
2983
- const tapscript = chunkZIRFXBKL_cjs.decodeTapscript(chunkZIRFXBKL_cjs.scriptFromTapLeafScript(input.tapLeafScript));
2984
- if (chunkZIRFXBKL_cjs.CLTVMultisigTapscript.is(tapscript)) {
3030
+ const tapscript = chunk2JV4VQ7C_cjs.decodeTapscript(chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(input.tapLeafScript));
3031
+ if (chunk2JV4VQ7C_cjs.CLTVMultisigTapscript.is(tapscript)) {
2985
3032
  if (lockTime !== 0n) {
2986
3033
  if (isSeconds(lockTime) !== isSeconds(tapscript.params.absoluteTimelock)) {
2987
3034
  throw new Error("cannot mix seconds and blocks locktime");
@@ -2992,7 +3039,7 @@ function buildVirtualTx(inputs, outputs) {
2992
3039
  }
2993
3040
  }
2994
3041
  }
2995
- const tx = new chunkZIRFXBKL_cjs.Transaction({
3042
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({
2996
3043
  version: 3,
2997
3044
  lockTime: Number(lockTime)
2998
3045
  });
@@ -3002,12 +3049,12 @@ function buildVirtualTx(inputs, outputs) {
3002
3049
  index: input.vout,
3003
3050
  sequence: lockTime ? btcSigner.DEFAULT_SEQUENCE - 1 : void 0,
3004
3051
  witnessUtxo: {
3005
- script: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript,
3052
+ script: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript,
3006
3053
  amount: BigInt(input.value)
3007
3054
  },
3008
3055
  tapLeafScript: [input.tapLeafScript]
3009
3056
  });
3010
- chunkZIRFXBKL_cjs.setArkPsbtField(tx, i, chunkZIRFXBKL_cjs.VtxoTaprootTree, input.tapTree);
3057
+ chunk2JV4VQ7C_cjs.setArkPsbtField(tx, i, chunk2JV4VQ7C_cjs.VtxoTaprootTree, input.tapTree);
3011
3058
  }
3012
3059
  for (const output of outputs) {
3013
3060
  tx.addOutput(output);
@@ -3016,8 +3063,8 @@ function buildVirtualTx(inputs, outputs) {
3016
3063
  return tx;
3017
3064
  }
3018
3065
  function buildCheckpointTx(vtxo, serverUnrollScript) {
3019
- const collaborativeClosure = chunkZIRFXBKL_cjs.decodeTapscript(chunkZIRFXBKL_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
3020
- const checkpointVtxoScript = new chunkZIRFXBKL_cjs.VtxoScript([
3066
+ const collaborativeClosure = chunk2JV4VQ7C_cjs.decodeTapscript(chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
3067
+ const checkpointVtxoScript = new chunk2JV4VQ7C_cjs.VtxoScript([
3021
3068
  serverUnrollScript.script,
3022
3069
  collaborativeClosure.script
3023
3070
  ]);
@@ -3170,7 +3217,7 @@ function combineTapscriptSigs(signedTx, originalTx) {
3170
3217
  }
3171
3218
  function isValidArkAddress(address) {
3172
3219
  try {
3173
- chunkZIRFXBKL_cjs.ArkAddress.decode(address);
3220
+ chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
3174
3221
  return true;
3175
3222
  } catch (e) {
3176
3223
  return false;
@@ -3178,16 +3225,16 @@ function isValidArkAddress(address) {
3178
3225
  }
3179
3226
  function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, context) {
3180
3227
  if (serverCheckpointTxs.length !== expectedCheckpoints.length) {
3181
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3228
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3182
3229
  `${context} returned ${serverCheckpointTxs.length} checkpoints, expected ${expectedCheckpoints.length}`
3183
3230
  );
3184
3231
  }
3185
3232
  const byTxid = new Map(expectedCheckpoints.map((c) => [c.id, c]));
3186
3233
  return serverCheckpointTxs.map((encoded, index) => {
3187
- const server = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(encoded));
3234
+ const server = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(encoded));
3188
3235
  const local = byTxid.get(server.id);
3189
3236
  if (!local) {
3190
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3237
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3191
3238
  `${context} checkpoint ${index} txid ${server.id} does not match any submitted checkpoint`
3192
3239
  );
3193
3240
  }
@@ -3197,14 +3244,14 @@ function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, contex
3197
3244
  }
3198
3245
  function assertSubmittedArkTxid(response, signedArkTx, context) {
3199
3246
  if (response.arkTxid !== signedArkTx.id) {
3200
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3247
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3201
3248
  `${context} returned ark txid ${response.arkTxid}, expected ${signedArkTx.id}`
3202
3249
  );
3203
3250
  }
3204
3251
  if (response.finalArkTx === void 0) return;
3205
- const finalTxid = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx)).id;
3252
+ const finalTxid = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx)).id;
3206
3253
  if (finalTxid !== signedArkTx.id) {
3207
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3254
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3208
3255
  `${context} returned final ark tx ${finalTxid}, expected ${signedArkTx.id}`
3209
3256
  );
3210
3257
  }
@@ -3223,10 +3270,10 @@ function assertServerSignedLeaf(serverTx, localTx, inputIndex, serverPubkeyHex,
3223
3270
  [serverPubkeyHex],
3224
3271
  void 0,
3225
3272
  void 0,
3226
- payment_js.tapLeafHash(chunkZIRFXBKL_cjs.scriptFromTapLeafScript(leaf))
3273
+ payment_js.tapLeafHash(chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(leaf))
3227
3274
  );
3228
3275
  } catch (error) {
3229
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3276
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3230
3277
  `${context}: input ${inputIndex} is not signed by the server on the leaf being spent (${error instanceof Error ? error.message : String(error)})`
3231
3278
  );
3232
3279
  }
@@ -3235,20 +3282,20 @@ function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, con
3235
3282
  const byOutpoint = new Map(inputs.map((input) => [`${input.txid}:${input.vout}`, input]));
3236
3283
  for (const [index, checkpoint] of checkpoints.entries()) {
3237
3284
  if (checkpoint.inputsLength !== 1) {
3238
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3285
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3239
3286
  `${context}: checkpoint ${index} spends ${checkpoint.inputsLength} inputs, expected 1`
3240
3287
  );
3241
3288
  }
3242
3289
  const spent = checkpoint.getInput(0);
3243
3290
  if (!spent.txid || spent.index === void 0) {
3244
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3291
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3245
3292
  `${context}: checkpoint ${index} has no input outpoint`
3246
3293
  );
3247
3294
  }
3248
3295
  const outpoint = `${base.hex.encode(spent.txid)}:${spent.index}`;
3249
3296
  const input = byOutpoint.get(outpoint);
3250
3297
  if (!input) {
3251
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3298
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3252
3299
  `${context}: checkpoint ${index} spends ${outpoint}, which is not one of the requested virtual outputs`
3253
3300
  );
3254
3301
  }
@@ -3256,7 +3303,7 @@ function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, con
3256
3303
  (unroll) => buildCheckpointTx(input, unroll).tx.id === checkpoint.id
3257
3304
  );
3258
3305
  if (!rebuilt) {
3259
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3306
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3260
3307
  `${context}: checkpoint ${index} txid ${checkpoint.id} differs from the checkpoint built locally for ${outpoint}`
3261
3308
  );
3262
3309
  }
@@ -3283,12 +3330,12 @@ async function submitOffchainTx(provider, offchainTx, signer, hooks, options) {
3283
3330
  const verify = options?.verifyServerSignatures;
3284
3331
  if (verify) {
3285
3332
  if (response.finalArkTx === void 0) {
3286
- throw new chunkZIRFXBKL_cjs.ServerResponseMismatchError(
3333
+ throw new chunk2JV4VQ7C_cjs.ServerResponseMismatchError(
3287
3334
  "submitTx: server returned no final ark tx to verify its signatures against"
3288
3335
  );
3289
3336
  }
3290
- const finalArkTx = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx));
3291
- const serverPubkeyHex = base.hex.encode(chunkPXPPZF5K_cjs.toXOnly(verify.serverPubkey, "server key"));
3337
+ const finalArkTx = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx));
3338
+ const serverPubkeyHex = base.hex.encode(chunkOIZ2V2VD_cjs.toXOnly(verify.serverPubkey, "server key"));
3292
3339
  for (let i = 0; i < offchainTx.arkTx.inputsLength; i++) {
3293
3340
  assertServerSignedLeaf(
3294
3341
  finalArkTx,
@@ -3344,12 +3391,12 @@ function claimWithPreimageIdentity(identity, preimage) {
3344
3391
  return {
3345
3392
  ...identity,
3346
3393
  sign: async (tx, inputIndexes) => {
3347
- const signed = chunkZIRFXBKL_cjs.Transaction.fromPSBT(
3394
+ const signed = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(
3348
3395
  (await identity.sign(tx.clone(), inputIndexes)).toPSBT()
3349
3396
  );
3350
3397
  const indexes = inputIndexes ?? Array.from({ length: signed.inputsLength }, (_, i) => i);
3351
3398
  for (const index of indexes) {
3352
- chunkZIRFXBKL_cjs.setArkPsbtField(signed, index, chunkZIRFXBKL_cjs.ConditionWitness, [preimage]);
3399
+ chunk2JV4VQ7C_cjs.setArkPsbtField(signed, index, chunk2JV4VQ7C_cjs.ConditionWitness, [preimage]);
3353
3400
  }
3354
3401
  return signed;
3355
3402
  }
@@ -3541,7 +3588,7 @@ function extendCoinWithTapscript(boardingTapscript, utxo) {
3541
3588
  };
3542
3589
  }
3543
3590
  function deriveContractTapscripts(contract) {
3544
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
3591
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
3545
3592
  if (!handler) {
3546
3593
  throw new Error(`No handler for contract type '${contract.type}'`);
3547
3594
  }
@@ -3612,7 +3659,7 @@ function getRandomId() {
3612
3659
  }
3613
3660
  function isValidArkAddress2(address) {
3614
3661
  try {
3615
- chunkZIRFXBKL_cjs.ArkAddress.decode(address);
3662
+ chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
3616
3663
  return true;
3617
3664
  } catch (e) {
3618
3665
  return false;
@@ -3640,7 +3687,7 @@ function assertRecipientArkAddress(encoded, address, context) {
3640
3687
  function assertTapTreeDerivesAddress(encoded, tapTree, address) {
3641
3688
  let derived;
3642
3689
  try {
3643
- derived = chunkZIRFXBKL_cjs.VtxoScript.decode(tapTree).pkScript;
3690
+ derived = chunk2JV4VQ7C_cjs.VtxoScript.decode(tapTree).pkScript;
3644
3691
  } catch (e) {
3645
3692
  throw new Error(
3646
3693
  `Invalid tapTree for ${encoded}: ${e instanceof Error ? e.message : String(e)}`
@@ -3657,7 +3704,7 @@ function validateRecipients(recipients, dustAmount, context) {
3657
3704
  for (const recipient of recipients) {
3658
3705
  let address;
3659
3706
  try {
3660
- address = chunkZIRFXBKL_cjs.ArkAddress.decode(recipient.address);
3707
+ address = chunk2JV4VQ7C_cjs.ArkAddress.decode(recipient.address);
3661
3708
  } catch (e) {
3662
3709
  throw new Error(`Invalid Arkade address: ${recipient.address}`);
3663
3710
  }
@@ -3682,7 +3729,7 @@ function validateRecipients(recipients, dustAmount, context) {
3682
3729
 
3683
3730
  // src/contracts/spendability.ts
3684
3731
  function isContractGenericallySpendable(contract) {
3685
- return chunkPXPPZF5K_cjs.contractHandlers.get(contract.type)?.isGenericallySpendable?.(contract) === true;
3732
+ return chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type)?.isGenericallySpendable?.(contract) === true;
3686
3733
  }
3687
3734
  function gatedContracts(contracts) {
3688
3735
  const gated = /* @__PURE__ */ new Map();
@@ -3695,7 +3742,7 @@ function gateExclusion(gated) {
3695
3742
  return (vtxo) => {
3696
3743
  const type = vtxo.script === void 0 ? void 0 : gated.get(vtxo.script);
3697
3744
  if (type === void 0) return void 0;
3698
- if (!chunkPXPPZF5K_cjs.contractHandlers.has(type)) {
3745
+ if (!chunkOIZ2V2VD_cjs.contractHandlers.has(type)) {
3699
3746
  return `at ${vtxo.script} (contract type '${type}') has no handler registered in this build`;
3700
3747
  }
3701
3748
  return `at ${vtxo.script} (contract type '${type}') is not generically spendable`;
@@ -3731,7 +3778,9 @@ function selectPendingRecoveryOutpoints(contractsWithVtxos, signerSet, nowSecond
3731
3778
  continue;
3732
3779
  }
3733
3780
  for (const v of vtxos) {
3734
- if (!chunkZIRFXBKL_cjs.hasTerminalSpend(v) && !v.isSwept) out.add(`${v.txid}:${v.vout}`);
3781
+ if (!chunk2JV4VQ7C_cjs.hasTerminalSpend(v) && !v.isSwept && !v.isUnrolled) {
3782
+ out.add(`${v.txid}:${v.vout}`);
3783
+ }
3735
3784
  }
3736
3785
  }
3737
3786
  return out;
@@ -3764,10 +3813,10 @@ function byValueDescending(vtxos) {
3764
3813
  return [...vtxos].sort((a, b) => b.value - a.value);
3765
3814
  }
3766
3815
  async function fetchTimeHeight(wallet) {
3767
- return chunkZIRFXBKL_cjs.resolveTimeHeight(wallet.onchainProvider);
3816
+ return chunk2JV4VQ7C_cjs.resolveTimeHeight(wallet.onchainProvider);
3768
3817
  }
3769
3818
  function canMigrateBySend(vtxo, now) {
3770
- if (!chunkZIRFXBKL_cjs.canSpendOffchain(vtxo, now)) return false;
3819
+ if (!chunk2JV4VQ7C_cjs.canSpendOffchain(vtxo, now)) return false;
3771
3820
  return vtxo.expiresAt !== void 0 || vtxo.expiresAtHeight !== void 0;
3772
3821
  }
3773
3822
  function byExpiryAscending(vtxos, now) {
@@ -3775,7 +3824,7 @@ function byExpiryAscending(vtxos, now) {
3775
3824
  if (vtxo.isSwept) return -Infinity;
3776
3825
  if (vtxo.expiresAt !== void 0) return vtxo.expiresAt.getTime();
3777
3826
  if (vtxo.expiresAtHeight !== void 0) {
3778
- return chunkZIRFXBKL_cjs.isPastExpiry(vtxo, now) ? -Infinity : Infinity;
3827
+ return chunk2JV4VQ7C_cjs.isPastExpiry(vtxo, now) ? -Infinity : Infinity;
3779
3828
  }
3780
3829
  return Infinity;
3781
3830
  };
@@ -3802,7 +3851,7 @@ function priceSettlementInputs(vtxos, estimator) {
3802
3851
  const payable = [];
3803
3852
  const net = /* @__PURE__ */ new Map();
3804
3853
  for (const vtxo of vtxos) {
3805
- const inputFee = estimator.evalOffchainInput(chunkZIRFXBKL_cjs.toOffchainInputFeeParams(vtxo));
3854
+ const inputFee = estimator.evalOffchainInput(chunk2JV4VQ7C_cjs.toOffchainInputFeeParams(vtxo));
3806
3855
  if (inputFee.satoshis >= vtxo.value) {
3807
3856
  continue;
3808
3857
  }
@@ -3828,7 +3877,7 @@ function deductOffchainOutputFee(subtotal, estimator, arkAddress) {
3828
3877
  }
3829
3878
  const outputFee = estimator.evalOffchainOutput({
3830
3879
  amount: subtotal,
3831
- script: base.hex.encode(chunkZIRFXBKL_cjs.ArkAddress.decode(arkAddress).pkScript)
3880
+ script: base.hex.encode(chunk2JV4VQ7C_cjs.ArkAddress.decode(arkAddress).pkScript)
3832
3881
  });
3833
3882
  return subtotal - BigInt(outputFee.satoshis);
3834
3883
  }
@@ -3846,10 +3895,10 @@ var DEFAULT_SETTLEMENT_CONFIG = {
3846
3895
  };
3847
3896
  function getRecoverableVtxos(vtxos, dustAmount, now) {
3848
3897
  return vtxos.filter((vtxo) => {
3849
- if (chunkZIRFXBKL_cjs.canRecoverOnchain(vtxo, now)) {
3898
+ if (chunk2JV4VQ7C_cjs.canRecoverOnchain(vtxo, now)) {
3850
3899
  return true;
3851
3900
  }
3852
- if (chunkZIRFXBKL_cjs.canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
3901
+ if (chunk2JV4VQ7C_cjs.canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
3853
3902
  return true;
3854
3903
  }
3855
3904
  return false;
@@ -3880,7 +3929,7 @@ function getRecoverableWithSubdust(vtxos, dustAmount, now) {
3880
3929
  }
3881
3930
  function isVtxoExpiringSoon(vtxo, thresholdMs) {
3882
3931
  const realThresholdMs = thresholdMs <= 100 ? DEFAULT_THRESHOLD_MS : thresholdMs;
3883
- const expiresAt = chunkZIRFXBKL_cjs.normalizeVtxo(vtxo).expiresAt;
3932
+ const expiresAt = chunk2JV4VQ7C_cjs.normalizeVtxo(vtxo).expiresAt;
3884
3933
  if (expiresAt === void 0) return false;
3885
3934
  const now = Date.now();
3886
3935
  const batchExpiry = expiresAt.getTime();
@@ -3889,7 +3938,7 @@ function isVtxoExpiringSoon(vtxo, thresholdMs) {
3889
3938
  }
3890
3939
  function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount, now) {
3891
3940
  return vtxos.filter(
3892
- (vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) || chunkZIRFXBKL_cjs.canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount)
3941
+ (vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) || chunk2JV4VQ7C_cjs.canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount)
3893
3942
  );
3894
3943
  }
3895
3944
  function isMigrationCapable(wallet) {
@@ -4488,11 +4537,11 @@ var VtxoManager = class _VtxoManager {
4488
4537
  `Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
4489
4538
  );
4490
4539
  }
4491
- const tx = new chunkZIRFXBKL_cjs.Transaction();
4540
+ const tx = new chunk2JV4VQ7C_cjs.Transaction();
4492
4541
  for (const utxo of expiredUtxos) {
4493
- const utxoScript = chunkZIRFXBKL_cjs.VtxoScript.decode(utxo.tapTree);
4542
+ const utxoScript = chunk2JV4VQ7C_cjs.VtxoScript.decode(utxo.tapTree);
4494
4543
  const utxoExitLeaf = utxoScript.leaves.find(
4495
- (leaf) => chunkZIRFXBKL_cjs.CSVMultisigTapscript.isScriptValid(chunkZIRFXBKL_cjs.scriptFromTapLeafScript(leaf)) === true
4544
+ (leaf) => chunk2JV4VQ7C_cjs.CSVMultisigTapscript.isScriptValid(chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(leaf)) === true
4496
4545
  );
4497
4546
  if (!utxoExitLeaf) {
4498
4547
  throw new Error(
@@ -4507,7 +4556,7 @@ var VtxoManager = class _VtxoManager {
4507
4556
  amount: BigInt(utxo.value)
4508
4557
  },
4509
4558
  tapLeafScript: [utxoExitLeaf],
4510
- sequence: chunkZIRFXBKL_cjs.getSequence(utxoExitLeaf)
4559
+ sequence: chunk2JV4VQ7C_cjs.getSequence(utxoExitLeaf)
4511
4560
  });
4512
4561
  }
4513
4562
  tx.addOutputAddress(boardingAddress, outputAmount, this.getNetwork());
@@ -4540,6 +4589,7 @@ var VtxoManager = class _VtxoManager {
4540
4589
  async getDeprecatedSignerStatus() {
4541
4590
  const wallet = this.requireMigrationCapableWallet();
4542
4591
  const info = await wallet.arkProvider.getInfo();
4592
+ await wallet.settleServerInfoChanges?.();
4543
4593
  const { reports: vtxoReports } = await this.classifyDeprecatedSignerContracts(info);
4544
4594
  const { reports: boardingReports } = await this.classifyDeprecatedSignerBoarding(info);
4545
4595
  return mergeSignerReports(vtxoReports, boardingReports);
@@ -4553,26 +4603,33 @@ var VtxoManager = class _VtxoManager {
4553
4603
  */
4554
4604
  async migrateCore(options) {
4555
4605
  const wallet = this.requireMigrationCapableWallet();
4606
+ const signerBeforeRefresh = base.hex.encode(wallet.arkServerPublicKey);
4556
4607
  const info = await wallet.arkProvider.getInfo();
4608
+ await wallet.settleServerInfoChanges?.();
4609
+ const rotatedOnRefresh = signerBeforeRefresh !== base.hex.encode(wallet.arkServerPublicKey);
4557
4610
  wallet.refreshDeprecatedSigners(info);
4558
4611
  const signerSet = signerSetFromInfo(info);
4559
4612
  const nowSeconds = Math.floor(Date.now() / 1e3);
4560
4613
  const walletSignerHex = base.hex.encode(wallet.arkServerPublicKey);
4561
4614
  const walletClass = classifyAgainstSignerSet(walletSignerHex, signerSet, nowSeconds);
4562
4615
  if (signerSet.deprecated.size === 0 && walletClass.status === "CURRENT") {
4563
- return { rotated: false, expired: [], signers: [] };
4616
+ return { rotated: rotatedOnRefresh, expired: [], signers: [] };
4564
4617
  }
4565
4618
  if (walletClass.status === "UNKNOWN_SIGNER") {
4566
4619
  const { reports: vtxoReports2 } = await this.classifyDeprecatedSignerContracts(info);
4567
4620
  const { reports: boardingReports2 } = await this.classifyDeprecatedSignerBoarding(info);
4568
4621
  return {
4569
- rotated: false,
4622
+ // Normally false here — a drained rotation targets the active
4623
+ // signer, which classifies CURRENT, not UNKNOWN. It is true only
4624
+ // when a second rotation landed inside the drain, leaving us on a
4625
+ // signer newer than `info`: still a rotation this pass applied.
4626
+ rotated: rotatedOnRefresh,
4570
4627
  expired: [],
4571
4628
  signers: mergeSignerReports(vtxoReports2, boardingReports2),
4572
4629
  skipped: "unknown-wallet-signer"
4573
4630
  };
4574
4631
  }
4575
- const rotated = await this.ensureReceiveOnActiveSigner(info);
4632
+ const rotated = await this.ensureReceiveOnActiveSigner(info) || rotatedOnRefresh;
4576
4633
  const {
4577
4634
  reports: vtxoReports,
4578
4635
  migratable: vtxoMigratable,
@@ -4741,8 +4798,9 @@ var VtxoManager = class _VtxoManager {
4741
4798
  if (!serverPubKey) continue;
4742
4799
  const cls = classifyAgainstSignerSet(serverPubKey, signerSet, nowSeconds);
4743
4800
  if (cls.status === "CURRENT") continue;
4744
- const recoverable = vtxos.filter((v) => v.isSwept && !chunkZIRFXBKL_cjs.hasTerminalSpend(v));
4745
- const spendable = vtxos.filter((v) => !chunkZIRFXBKL_cjs.hasTerminalSpend(v) && !v.isSwept);
4801
+ const live = vtxos.filter((v) => !v.isUnrolled);
4802
+ const recoverable = live.filter((v) => v.isSwept && !chunk2JV4VQ7C_cjs.hasTerminalSpend(v));
4803
+ const spendable = live.filter((v) => !chunk2JV4VQ7C_cjs.hasTerminalSpend(v) && !v.isSwept);
4746
4804
  const value = spendable.reduce((sum, v) => sum + v.value, 0);
4747
4805
  let recoverableCount = 0;
4748
4806
  let recoverableValue = 0;
@@ -4755,7 +4813,7 @@ var VtxoManager = class _VtxoManager {
4755
4813
  awaitingSweepCount = spendable.length;
4756
4814
  awaitingSweepValue = value;
4757
4815
  for (const v of spendable) {
4758
- const exp = chunkZIRFXBKL_cjs.toBatchExpiry(v);
4816
+ const exp = chunk2JV4VQ7C_cjs.toBatchExpiry(v);
4759
4817
  if (exp !== void 0 && (nextSweepEta === void 0 || exp < nextSweepEta)) {
4760
4818
  nextSweepEta = exp;
4761
4819
  }
@@ -5016,7 +5074,7 @@ var VtxoManager = class _VtxoManager {
5016
5074
  /** Decodes the boarding tapscript exit path to extract the CSV timelock. */
5017
5075
  getBoardingTimelock() {
5018
5076
  const wallet = this.getSweepWallet();
5019
- const exitScript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(
5077
+ const exitScript = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(
5020
5078
  base.hex.decode(wallet.boardingTapscript.exitScript)
5021
5079
  );
5022
5080
  return exitScript.params.timelock;
@@ -5147,8 +5205,8 @@ var VtxoManager = class _VtxoManager {
5147
5205
  * or doesn't carry the metadata.
5148
5206
  */
5149
5207
  extractSpentOutpoint(error) {
5150
- const ark = chunkZIRFXBKL_cjs.maybeArkError(error);
5151
- if (!chunkZIRFXBKL_cjs.isArkError(ark, chunkZIRFXBKL_cjs.ArkErrorName.VTXO_ALREADY_SPENT)) return void 0;
5208
+ const ark = chunk2JV4VQ7C_cjs.maybeArkError(error);
5209
+ if (!chunk2JV4VQ7C_cjs.isArkError(ark, chunk2JV4VQ7C_cjs.ArkErrorName.VTXO_ALREADY_SPENT)) return void 0;
5152
5210
  const raw = ark.metadata?.vtxo_outpoint;
5153
5211
  if (typeof raw !== "string") return void 0;
5154
5212
  const [txid, voutStr] = raw.split(":");
@@ -5338,7 +5396,7 @@ var VtxoManager = class _VtxoManager {
5338
5396
  if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
5339
5397
  break;
5340
5398
  }
5341
- const inputFee = estimator.evalOffchainInput(chunkZIRFXBKL_cjs.toOffchainInputFeeParams(v));
5399
+ const inputFee = estimator.evalOffchainInput(chunk2JV4VQ7C_cjs.toOffchainInputFeeParams(v));
5342
5400
  if (inputFee.satoshis >= v.value) {
5343
5401
  continue;
5344
5402
  }
@@ -5358,7 +5416,7 @@ var VtxoManager = class _VtxoManager {
5358
5416
  const arkAddress = await this.wallet.getAddress();
5359
5417
  const outputFee = estimator.evalOffchainOutput({
5360
5418
  amount: totalAmount,
5361
- script: base.hex.encode(chunkZIRFXBKL_cjs.ArkAddress.decode(arkAddress).pkScript)
5419
+ script: base.hex.encode(chunk2JV4VQ7C_cjs.ArkAddress.decode(arkAddress).pkScript)
5362
5420
  });
5363
5421
  totalAmount -= BigInt(outputFee.satoshis);
5364
5422
  if (totalAmount < dustAmount) return;
@@ -5438,7 +5496,7 @@ var ArkNote = class _ArkNote {
5438
5496
  this.value = value;
5439
5497
  this.HRP = HRP;
5440
5498
  const preimageHash = utils_js.sha256(this.preimage);
5441
- this.vtxoScript = new chunkZIRFXBKL_cjs.VtxoScript([noteTapscript(preimageHash)]);
5499
+ this.vtxoScript = new chunk2JV4VQ7C_cjs.VtxoScript([noteTapscript(preimageHash)]);
5442
5500
  const leaf = this.vtxoScript.leaves[0];
5443
5501
  this.txid = base.hex.encode(new Uint8Array(preimageHash).reverse());
5444
5502
  this.tapTree = this.vtxoScript.encode();
@@ -5605,7 +5663,7 @@ var ArkadeCash = class _ArkadeCash {
5605
5663
  const privateKey = data.slice(1, 33);
5606
5664
  const serverPubKey = data.slice(33, 65);
5607
5665
  const sequence = new DataView(data.buffer, data.byteOffset + 65, 4).getUint32(0, false);
5608
- const csvTimelock = chunkZIRFXBKL_cjs.sequenceToTimelock(sequence);
5666
+ const csvTimelock = chunk2JV4VQ7C_cjs.sequenceToTimelock(sequence);
5609
5667
  return new _ArkadeCash(privateKey, serverPubKey, csvTimelock, decoded.prefix);
5610
5668
  }
5611
5669
  toString() {
@@ -5613,7 +5671,7 @@ var ArkadeCash = class _ArkadeCash {
5613
5671
  data[0] = _ArkadeCash.Version;
5614
5672
  data.set(this._privateKey, 1);
5615
5673
  data.set(this._serverPubKey, 33);
5616
- const sequence = chunkZIRFXBKL_cjs.timelockToSequence(this.csvTimelock);
5674
+ const sequence = chunk2JV4VQ7C_cjs.timelockToSequence(this.csvTimelock);
5617
5675
  new DataView(data.buffer, data.byteOffset + 65, 4).setUint32(0, sequence, false);
5618
5676
  const words = base.bech32m.toWords(data);
5619
5677
  return base.bech32m.encode(this.hrp, words, 1023);
@@ -5622,7 +5680,7 @@ var ArkadeCash = class _ArkadeCash {
5622
5680
  return SingleKey.fromPrivateKey(this._privateKey);
5623
5681
  }
5624
5682
  get vtxoScript() {
5625
- return new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
5683
+ return new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
5626
5684
  pubKey: this._publicKey,
5627
5685
  serverPubKey: this._serverPubKey,
5628
5686
  csvTimelock: this.csvTimelock
@@ -5883,7 +5941,7 @@ async function captureExitBranch(params) {
5883
5941
  const nonCommitment = ordered.filter((c) => chainTxTypeToChainedExit(c.type) !== 1 /* Commitment */).map((c) => c.txid);
5884
5942
  if (nonCommitment.length > 0) {
5885
5943
  for (const psbt of await resolver.getVirtualTxs(nonCommitment)) {
5886
- psbtByTxid.set(chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
5944
+ psbtByTxid.set(chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
5887
5945
  }
5888
5946
  }
5889
5947
  }
@@ -5926,10 +5984,10 @@ var IndexerExitDataSource = class {
5926
5984
  while (hasMore) {
5927
5985
  const { chain: page, page: meta } = await this.indexer.getVtxoChain(
5928
5986
  { txid: vtxo.txid, vout: vtxo.vout },
5929
- { pageIndex, pageSize: chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE }
5987
+ { pageIndex, pageSize: chunk2JV4VQ7C_cjs.DEFAULT_PAGE_SIZE }
5930
5988
  );
5931
5989
  chain.push(...page);
5932
- hasMore = meta ? page.length === chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE : false;
5990
+ hasMore = meta ? page.length === chunk2JV4VQ7C_cjs.DEFAULT_PAGE_SIZE : false;
5933
5991
  pageIndex++;
5934
5992
  }
5935
5993
  return chain;
@@ -5941,12 +5999,12 @@ var IndexerExitDataSource = class {
5941
5999
  while (hasMore) {
5942
6000
  const { txs, page } = await this.indexer.getVirtualTxs(txids, {
5943
6001
  pageIndex,
5944
- pageSize: chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE
6002
+ pageSize: chunk2JV4VQ7C_cjs.DEFAULT_PAGE_SIZE
5945
6003
  });
5946
6004
  for (const psbt of txs) {
5947
- out.set(chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
6005
+ out.set(chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
5948
6006
  }
5949
- hasMore = page ? txs.length === chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE : false;
6007
+ hasMore = page ? txs.length === chunk2JV4VQ7C_cjs.DEFAULT_PAGE_SIZE : false;
5950
6008
  pageIndex++;
5951
6009
  }
5952
6010
  return out;
@@ -5967,7 +6025,7 @@ function chainedTxTypeToChainTxType(t) {
5967
6025
  }
5968
6026
  }
5969
6027
  function psbtInputTxids(psbtBase64) {
5970
- const tx = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
6028
+ const tx = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
5971
6029
  const ids = [];
5972
6030
  for (let i = 0; i < tx.inputsLength; i++) {
5973
6031
  const txid = tx.getInput(i).txid;
@@ -6326,10 +6384,10 @@ async function resolveArkInfo(arkProvider, walletRepository) {
6326
6384
  try {
6327
6385
  info = await arkProvider.getInfo();
6328
6386
  } catch (err) {
6329
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
6387
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
6330
6388
  const snapshot = await loadArkInfoSnapshot(walletRepository);
6331
6389
  if (!snapshot) {
6332
- throw new chunkZIRFXBKL_cjs.ProviderUnavailableError(
6390
+ throw new chunk2JV4VQ7C_cjs.ProviderUnavailableError(
6333
6391
  "Arkade server info is unavailable and no cached snapshot exists",
6334
6392
  { cause: err }
6335
6393
  );
@@ -6712,7 +6770,7 @@ function collectArkTxidsNeedingCreatedAt(vtxos) {
6712
6770
  return [...txids];
6713
6771
  }
6714
6772
  async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, resolveTxCreatedAt) {
6715
- const fromOldestVtxo = vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
6773
+ const fromOldestVtxo = vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
6716
6774
  const txidsNeedingCreatedAt = resolveTxCreatedAt ? collectArkTxidsNeedingCreatedAt(fromOldestVtxo) : [];
6717
6775
  const resolvedCreatedAt = resolveTxCreatedAt && txidsNeedingCreatedAt.length > 0 ? await resolveTxCreatedAt(txidsNeedingCreatedAt) : /* @__PURE__ */ new Map();
6718
6776
  const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
@@ -6876,7 +6934,7 @@ var AssetManager = class extends ReadonlyAssetManager {
6876
6934
  const virtualCoins = await this.wallet.getSpendableVtxos({
6877
6935
  withRecoverable: false
6878
6936
  });
6879
- const controlAssetRef = params.controlAssetId ? chunk3S3JZUEN_cjs.AssetRef.fromId(chunk3S3JZUEN_cjs.AssetId.fromString(params.controlAssetId)) : null;
6937
+ const controlAssetRef = params.controlAssetId ? chunkCO3KKSWM_cjs.AssetRef.fromId(chunkCO3KKSWM_cjs.AssetId.fromString(params.controlAssetId)) : null;
6880
6938
  const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
6881
6939
  let totalBtcSelected = 0n;
6882
6940
  const assetChanges = /* @__PURE__ */ new Map();
@@ -6889,8 +6947,8 @@ var AssetManager = class extends ReadonlyAssetManager {
6889
6947
  }
6890
6948
  }
6891
6949
  const groups = [];
6892
- const issuedAssetOutput = chunk3S3JZUEN_cjs.AssetOutput.create(0, params.amount);
6893
- const issuedAssetGroup = chunk3S3JZUEN_cjs.AssetGroup.create(
6950
+ const issuedAssetOutput = chunkCO3KKSWM_cjs.AssetOutput.create(0, params.amount);
6951
+ const issuedAssetGroup = chunkCO3KKSWM_cjs.AssetGroup.create(
6894
6952
  null,
6895
6953
  controlAssetRef,
6896
6954
  [],
@@ -6905,28 +6963,28 @@ var AssetManager = class extends ReadonlyAssetManager {
6905
6963
  for (const [inputIndex, assets] of assetInputs) {
6906
6964
  for (const asset of assets) {
6907
6965
  if (asset.assetId !== assetId) continue;
6908
- changeInputs.push(chunk3S3JZUEN_cjs.AssetInput.create(inputIndex, asset.amount));
6966
+ changeInputs.push(chunkCO3KKSWM_cjs.AssetInput.create(inputIndex, asset.amount));
6909
6967
  }
6910
6968
  }
6911
6969
  groups.push(
6912
- chunk3S3JZUEN_cjs.AssetGroup.create(
6913
- chunk3S3JZUEN_cjs.AssetId.fromString(assetId),
6970
+ chunkCO3KKSWM_cjs.AssetGroup.create(
6971
+ chunkCO3KKSWM_cjs.AssetId.fromString(assetId),
6914
6972
  null,
6915
6973
  changeInputs,
6916
- [chunk3S3JZUEN_cjs.AssetOutput.create(0, amount)],
6974
+ [chunkCO3KKSWM_cjs.AssetOutput.create(0, amount)],
6917
6975
  []
6918
6976
  )
6919
6977
  );
6920
6978
  }
6921
6979
  }
6922
6980
  const address = await this.wallet.getAddress();
6923
- const outputAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(address);
6981
+ const outputAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
6924
6982
  const outputs = [
6925
6983
  {
6926
6984
  script: outputAddress.pkScript,
6927
6985
  amount: BigInt(totalBtcSelected)
6928
6986
  },
6929
- Extension.create([chunk3S3JZUEN_cjs.Packet.create(groups)]).txOut()
6987
+ Extension.create([chunkCO3KKSWM_cjs.Packet.create(groups)]).txOut()
6930
6988
  ];
6931
6989
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
6932
6990
  coinSelection.inputs,
@@ -6934,7 +6992,7 @@ var AssetManager = class extends ReadonlyAssetManager {
6934
6992
  );
6935
6993
  return {
6936
6994
  arkTxId: arkTxid,
6937
- assetId: chunk3S3JZUEN_cjs.AssetId.create(arkTxid, 0).toString()
6995
+ assetId: chunkCO3KKSWM_cjs.AssetId.create(arkTxid, 0).toString()
6938
6996
  };
6939
6997
  }
6940
6998
  /**
@@ -7006,16 +7064,16 @@ var AssetManager = class extends ReadonlyAssetManager {
7006
7064
  for (const [inputIndex, assets] of assetInputs) {
7007
7065
  for (const asset of assets) {
7008
7066
  if (asset.assetId !== params.assetId) continue;
7009
- reissueInputs.push(chunk3S3JZUEN_cjs.AssetInput.create(inputIndex, asset.amount));
7067
+ reissueInputs.push(chunkCO3KKSWM_cjs.AssetInput.create(inputIndex, asset.amount));
7010
7068
  }
7011
7069
  }
7012
7070
  const totalAssetAmount = assetToReissueAmount + params.amount;
7013
- const reissueAssetIdObj = chunk3S3JZUEN_cjs.AssetId.fromString(params.assetId);
7014
- const reissueAssetGroup = chunk3S3JZUEN_cjs.AssetGroup.create(
7071
+ const reissueAssetIdObj = chunkCO3KKSWM_cjs.AssetId.fromString(params.assetId);
7072
+ const reissueAssetGroup = chunkCO3KKSWM_cjs.AssetGroup.create(
7015
7073
  reissueAssetIdObj,
7016
7074
  null,
7017
7075
  reissueInputs,
7018
- [chunk3S3JZUEN_cjs.AssetOutput.create(0, totalAssetAmount)],
7076
+ [chunkCO3KKSWM_cjs.AssetOutput.create(0, totalAssetAmount)],
7019
7077
  []
7020
7078
  );
7021
7079
  const groups = [reissueAssetGroup];
@@ -7024,27 +7082,27 @@ var AssetManager = class extends ReadonlyAssetManager {
7024
7082
  for (const [inputIndex, assets] of assetInputs) {
7025
7083
  for (const asset of assets) {
7026
7084
  if (asset.assetId !== assetId) continue;
7027
- changeInputs.push(chunk3S3JZUEN_cjs.AssetInput.create(inputIndex, asset.amount));
7085
+ changeInputs.push(chunkCO3KKSWM_cjs.AssetInput.create(inputIndex, asset.amount));
7028
7086
  }
7029
7087
  }
7030
7088
  groups.push(
7031
- chunk3S3JZUEN_cjs.AssetGroup.create(
7032
- chunk3S3JZUEN_cjs.AssetId.fromString(assetId),
7089
+ chunkCO3KKSWM_cjs.AssetGroup.create(
7090
+ chunkCO3KKSWM_cjs.AssetId.fromString(assetId),
7033
7091
  null,
7034
7092
  changeInputs,
7035
- [chunk3S3JZUEN_cjs.AssetOutput.create(0, amount)],
7093
+ [chunkCO3KKSWM_cjs.AssetOutput.create(0, amount)],
7036
7094
  []
7037
7095
  )
7038
7096
  );
7039
7097
  }
7040
7098
  const address = await this.wallet.getAddress();
7041
- const outputAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(address);
7099
+ const outputAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
7042
7100
  const outputs = [
7043
7101
  {
7044
7102
  script: outputAddress.pkScript,
7045
7103
  amount: BigInt(totalBtcSelected)
7046
7104
  },
7047
- Extension.create([chunk3S3JZUEN_cjs.Packet.create(groups)]).txOut()
7105
+ Extension.create([chunkCO3KKSWM_cjs.Packet.create(groups)]).txOut()
7048
7106
  ];
7049
7107
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
7050
7108
  return arkTxid;
@@ -7111,27 +7169,27 @@ var AssetManager = class extends ReadonlyAssetManager {
7111
7169
  for (const [inputIndex, assets] of assetInputs) {
7112
7170
  for (const asset of assets) {
7113
7171
  if (asset.assetId !== assetId) continue;
7114
- changeInputs.push(chunk3S3JZUEN_cjs.AssetInput.create(inputIndex, asset.amount));
7172
+ changeInputs.push(chunkCO3KKSWM_cjs.AssetInput.create(inputIndex, asset.amount));
7115
7173
  }
7116
7174
  }
7117
7175
  groups.push(
7118
- chunk3S3JZUEN_cjs.AssetGroup.create(
7119
- chunk3S3JZUEN_cjs.AssetId.fromString(assetId),
7176
+ chunkCO3KKSWM_cjs.AssetGroup.create(
7177
+ chunkCO3KKSWM_cjs.AssetId.fromString(assetId),
7120
7178
  null,
7121
7179
  changeInputs,
7122
- amount > 0n ? [chunk3S3JZUEN_cjs.AssetOutput.create(0, amount)] : [],
7180
+ amount > 0n ? [chunkCO3KKSWM_cjs.AssetOutput.create(0, amount)] : [],
7123
7181
  []
7124
7182
  )
7125
7183
  );
7126
7184
  }
7127
7185
  const address = await this.wallet.getAddress();
7128
- const outputAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(address);
7186
+ const outputAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(address);
7129
7187
  const outputs = [
7130
7188
  {
7131
7189
  script: outputAddress.pkScript,
7132
7190
  amount: BigInt(totalBtcSelected)
7133
7191
  },
7134
- Extension.create([chunk3S3JZUEN_cjs.Packet.create(groups)]).txOut()
7192
+ Extension.create([chunkCO3KKSWM_cjs.Packet.create(groups)]).txOut()
7135
7193
  ];
7136
7194
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
7137
7195
  return arkTxid;
@@ -7156,7 +7214,7 @@ function castMetadata(metadata) {
7156
7214
  } else {
7157
7215
  throw new Error("Invalid metadata value type");
7158
7216
  }
7159
- md.push(chunk3S3JZUEN_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
7217
+ md.push(chunkCO3KKSWM_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
7160
7218
  }
7161
7219
  return md;
7162
7220
  }
@@ -7177,10 +7235,10 @@ var DelegateManagerImpl = class {
7177
7235
  if (vtxos.length === 0) {
7178
7236
  return { delegated: [], failed: [] };
7179
7237
  }
7180
- const destinationScript = chunkZIRFXBKL_cjs.ArkAddress.decode(destination).pkScript;
7238
+ const destinationScript = chunk2JV4VQ7C_cjs.ArkAddress.decode(destination).pkScript;
7181
7239
  const arkInfo = await this.arkInfoProvider.getInfo();
7182
7240
  const delegateInfo = await this.delegateProvider.getDelegateInfo();
7183
- const eligible = vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo).filter(
7241
+ const eligible = vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo).filter(
7184
7242
  (v) => isAnnotated(v) && findDelegateTapLeaf(v, delegateInfo.pubkey) !== void 0
7185
7243
  );
7186
7244
  if (eligible.length === 0) {
@@ -7209,11 +7267,11 @@ var DelegateManagerImpl = class {
7209
7267
  const groupByExpiry = /* @__PURE__ */ new Map();
7210
7268
  let recoverableVtxos = [];
7211
7269
  for (const vtxo of eligible) {
7212
- if (chunkZIRFXBKL_cjs.canRecoverOnchain(vtxo, now)) {
7270
+ if (chunk2JV4VQ7C_cjs.canRecoverOnchain(vtxo, now)) {
7213
7271
  recoverableVtxos.push(vtxo);
7214
7272
  continue;
7215
7273
  }
7216
- const expiry = chunkZIRFXBKL_cjs.toBatchExpiry(vtxo);
7274
+ const expiry = chunk2JV4VQ7C_cjs.toBatchExpiry(vtxo);
7217
7275
  if (!expiry) continue;
7218
7276
  const dayKey = getDayTimestamp(expiry);
7219
7277
  groupByExpiry.set(dayKey, [...groupByExpiry.get(dayKey) ?? [], vtxo]);
@@ -7278,7 +7336,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
7278
7336
  }
7279
7337
  if (!delegateAt) {
7280
7338
  const now = { timestamp: /* @__PURE__ */ new Date() };
7281
- const expiryTimestamp = vtxos.filter((coin) => !chunkZIRFXBKL_cjs.canRecoverOnchain(coin, now) && chunkZIRFXBKL_cjs.toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, chunkZIRFXBKL_cjs.toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
7339
+ const expiryTimestamp = vtxos.filter((coin) => !chunk2JV4VQ7C_cjs.canRecoverOnchain(coin, now) && chunk2JV4VQ7C_cjs.toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, chunk2JV4VQ7C_cjs.toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
7282
7340
  if (!expiryTimestamp || expiryTimestamp === Number.MAX_SAFE_INTEGER) {
7283
7341
  delegateAt = new Date(Date.now() + 1 * 60 * 1e3);
7284
7342
  } else {
@@ -7307,7 +7365,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
7307
7365
  let amount = 0n;
7308
7366
  for (const coin of vtxos) {
7309
7367
  const inputFee = estimator.evalOffchainInput({
7310
- ...chunkZIRFXBKL_cjs.toOffchainInputFeeParams(coin),
7368
+ ...chunk2JV4VQ7C_cjs.toOffchainInputFeeParams(coin),
7311
7369
  type: "vtxo"
7312
7370
  });
7313
7371
  if (inputFee.value >= coin.value) {
@@ -7321,7 +7379,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
7321
7379
  const delegateFee = BigInt(Number(fee));
7322
7380
  if (delegateFee > 0n) {
7323
7381
  outputs.push({
7324
- script: chunkZIRFXBKL_cjs.ArkAddress.decode(delegateAddress).pkScript,
7382
+ script: chunk2JV4VQ7C_cjs.ArkAddress.decode(delegateAddress).pkScript,
7325
7383
  amount: delegateFee
7326
7384
  });
7327
7385
  }
@@ -7354,10 +7412,10 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
7354
7412
  destinationScript
7355
7413
  );
7356
7414
  const forfeitOutputScript = btcSigner.OutScript.encode(
7357
- btcSigner.Address(chunkZIRFXBKL_cjs.getNetwork(network)).decode(forfeitAddress)
7415
+ btcSigner.Address(chunk2JV4VQ7C_cjs.getNetwork(network)).decode(forfeitAddress)
7358
7416
  );
7359
7417
  const forfeits = await Promise.all(
7360
- vtxos.filter((v) => !chunkZIRFXBKL_cjs.canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
7418
+ vtxos.filter((v) => !chunk2JV4VQ7C_cjs.canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
7361
7419
  const forfeit = await makeDelegateForfeitTx(
7362
7420
  coin,
7363
7421
  dust,
@@ -7382,7 +7440,7 @@ async function makeDelegateForfeitTx(input, connectorAmount, delegatePubkey, for
7382
7440
  index: input.vout,
7383
7441
  witnessUtxo: {
7384
7442
  amount: BigInt(input.value),
7385
- script: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript
7443
+ script: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript
7386
7444
  },
7387
7445
  sighashType: btcSigner.SigHash.ALL_ANYONECANPAY,
7388
7446
  tapLeafScript: [delegateTapLeaf]
@@ -7440,7 +7498,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
7440
7498
  expire_at: 0,
7441
7499
  cosigners_public_keys: cosignerPubKeys
7442
7500
  };
7443
- const proof = chunkZIRFXBKL_cjs.Intent.create(message, coins, outputs);
7501
+ const proof = chunk2JV4VQ7C_cjs.Intent.create(message, coins, outputs);
7444
7502
  const signedProof = await identity.sign(proof);
7445
7503
  return {
7446
7504
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -7458,10 +7516,10 @@ function getDayTimestamp(timestamp) {
7458
7516
  function findDelegateTapLeaf(vtxo, delegatePubkey) {
7459
7517
  if (!vtxo.tapTree) return void 0;
7460
7518
  const pk = delegatePubkey.length === 66 ? delegatePubkey.slice(2) : delegatePubkey;
7461
- const vtxoScript = chunkZIRFXBKL_cjs.VtxoScript.decode(vtxo.tapTree);
7519
+ const vtxoScript = chunk2JV4VQ7C_cjs.VtxoScript.decode(vtxo.tapTree);
7462
7520
  return vtxoScript.leaves.find((tapLeaf) => {
7463
- const arkTapscript = chunkZIRFXBKL_cjs.decodeTapscript(chunkZIRFXBKL_cjs.scriptFromTapLeafScript(tapLeaf));
7464
- if (!chunkZIRFXBKL_cjs.MultisigTapscript.is(arkTapscript)) return false;
7521
+ const arkTapscript = chunk2JV4VQ7C_cjs.decodeTapscript(chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(tapLeaf));
7522
+ if (!chunk2JV4VQ7C_cjs.MultisigTapscript.is(arkTapscript)) return false;
7465
7523
  return arkTapscript.params.pubkeys.map(base.hex.encode).includes(pk);
7466
7524
  });
7467
7525
  }
@@ -7742,7 +7800,7 @@ function createManagedConnection(dbName, version, initDatabase2) {
7742
7800
  };
7743
7801
  }
7744
7802
  function scriptFromArkAddress(address) {
7745
- return base.hex.encode(chunkZIRFXBKL_cjs.ArkAddress.decode(address).pkScript);
7803
+ return base.hex.encode(chunk2JV4VQ7C_cjs.ArkAddress.decode(address).pkScript);
7746
7804
  }
7747
7805
 
7748
7806
  // src/repositories/indexedDB/schema.ts
@@ -8237,7 +8295,7 @@ function validateVtxosForScript(vtxos, script, context) {
8237
8295
  }
8238
8296
  async function getVtxosForContract(repo, contract) {
8239
8297
  const vtxos = repo.getVtxosForScript ? await repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
8240
- return vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo);
8298
+ return vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
8241
8299
  }
8242
8300
  async function saveVtxosForContract(repo, contract, vtxos) {
8243
8301
  if (repo.saveVtxosForScript) {
@@ -8379,7 +8437,7 @@ function decodeArkContract(encoded) {
8379
8437
  }
8380
8438
  function contractFromArkContract(encoded, options = {}) {
8381
8439
  const parsed = decodeArkContract(encoded);
8382
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(parsed.type);
8440
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(parsed.type);
8383
8441
  if (!handler) {
8384
8442
  throw new Error(`No handler registered for contract type '${parsed.type}'`);
8385
8443
  }
@@ -8393,9 +8451,9 @@ function contractFromArkContract(encoded, options = {}) {
8393
8451
  metadata: options.metadata
8394
8452
  };
8395
8453
  }
8396
- function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunkZIRFXBKL_cjs.DEFAULT_NETWORK.hrp, options = {}) {
8454
+ function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunk2JV4VQ7C_cjs.DEFAULT_NETWORK.hrp, options = {}) {
8397
8455
  const parsed = decodeArkContract(encoded);
8398
- const handler = chunkPXPPZF5K_cjs.contractHandlers.getOrThrow(parsed.type);
8456
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.getOrThrow(parsed.type);
8399
8457
  const params = parsed.data;
8400
8458
  const vtxoScript = handler.createScript(params);
8401
8459
  return {
@@ -8649,9 +8707,9 @@ var ContractWatcher = class {
8649
8707
  this.connectionState = "connected";
8650
8708
  this.reconnectAttempts = 0;
8651
8709
  this.listenLoop().catch((e) => {
8652
- if (chunkZIRFXBKL_cjs.isEventSourceError(e)) {
8710
+ if (chunk2JV4VQ7C_cjs.isEventSourceError(e)) {
8653
8711
  console.debug("ContractWatcher subscription disconnected; reconnecting");
8654
- } else if (!chunkZIRFXBKL_cjs.isEventSourceUnavailableError(e)) {
8712
+ } else if (!chunk2JV4VQ7C_cjs.isEventSourceUnavailableError(e)) {
8655
8713
  console.error(e);
8656
8714
  }
8657
8715
  this.connectionState = "disconnected";
@@ -8663,7 +8721,7 @@ var ContractWatcher = class {
8663
8721
  this.scheduleReconnect();
8664
8722
  });
8665
8723
  } catch (error) {
8666
- if (!chunkZIRFXBKL_cjs.isEventSourceUnavailableError(error)) {
8724
+ if (!chunk2JV4VQ7C_cjs.isEventSourceUnavailableError(error)) {
8667
8725
  console.error("ContractWatcher connection failed:", error);
8668
8726
  }
8669
8727
  this.connectionState = "disconnected";
@@ -8689,7 +8747,7 @@ var ContractWatcher = class {
8689
8747
  * slower; what it loses is push latency.
8690
8748
  */
8691
8749
  reportEventSourceUnavailable(error) {
8692
- if (!chunkZIRFXBKL_cjs.isEventSourceUnavailableError(error)) return false;
8750
+ if (!chunk2JV4VQ7C_cjs.isEventSourceUnavailableError(error)) return false;
8693
8751
  if (!this.eventSourceReported) {
8694
8752
  this.eventSourceReported = true;
8695
8753
  console.warn(
@@ -8905,14 +8963,14 @@ var ContractWatcher = class {
8905
8963
  const timestamp = Date.now();
8906
8964
  if (update.newVtxos?.length) {
8907
8965
  this.processSubscriptionVtxos(
8908
- update.newVtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo),
8966
+ update.newVtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo),
8909
8967
  "vtxo_received",
8910
8968
  timestamp
8911
8969
  );
8912
8970
  }
8913
8971
  if (update.spentVtxos?.length) {
8914
8972
  this.processSubscriptionVtxos(
8915
- update.spentVtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo),
8973
+ update.spentVtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo),
8916
8974
  "vtxo_spent",
8917
8975
  timestamp
8918
8976
  );
@@ -9007,7 +9065,7 @@ var NON_TERMINAL_INTENT_STATES = ALL_INTENT_STATES.filter(
9007
9065
  (s) => !isTerminalIntentState(s)
9008
9066
  );
9009
9067
  function isConsumed(vtxo) {
9010
- return vtxo !== void 0 && (vtxo.isSpent === true || vtxo.settledBy !== void 0);
9068
+ return vtxo !== void 0 && chunk2JV4VQ7C_cjs.hasTerminalSpend(vtxo);
9011
9069
  }
9012
9070
  async function classifyIntent(intent, vtxosByOutpoint, now) {
9013
9071
  if (isTerminalIntentState(intent.state)) return void 0;
@@ -9017,6 +9075,11 @@ async function classifyIntent(intent, vtxosByOutpoint, now) {
9017
9075
  const commitmentTransactionId = intent.commitmentTransactionId ?? consumed.map((v) => v?.settledBy).find((s) => !!s);
9018
9076
  return terminal(intent, "batch_succeeded", now, { commitmentTransactionId });
9019
9077
  }
9078
+ if (consumed.some((vtxo) => vtxo?.isUnrolled)) {
9079
+ return terminal(intent, "cancelled", now, {
9080
+ cancellationReason: "reconciliation: an input was unilaterally exited"
9081
+ });
9082
+ }
9020
9083
  if (intent.state === "waiting_to_submit") {
9021
9084
  return terminal(intent, "cancelled", now, {
9022
9085
  cancellationReason: "reconciliation: intent was never submitted before restart"
@@ -9045,7 +9108,7 @@ async function reconcileIntents(deps) {
9045
9108
  let vtxosByOutpoint = /* @__PURE__ */ new Map();
9046
9109
  if (outpoints.length > 0) {
9047
9110
  try {
9048
- const { vtxos } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(deps.indexerProvider, { outpoints });
9111
+ const { vtxos } = await chunk2JV4VQ7C_cjs.getNormalizedVtxos(deps.indexerProvider, { outpoints });
9049
9112
  vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
9050
9113
  } catch (e) {
9051
9114
  console.error("reconcileIntents: failed to fetch input VTXO state", e);
@@ -9219,7 +9282,7 @@ var ContractManager = class _ContractManager {
9219
9282
  await this.reconcileWatched();
9220
9283
  this.markSyncOnline();
9221
9284
  } catch (err) {
9222
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
9285
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
9223
9286
  this.markSyncDegraded(err);
9224
9287
  }
9225
9288
  this.initialized = true;
@@ -9351,7 +9414,7 @@ var ContractManager = class _ContractManager {
9351
9414
  const from = Math.max(0, watermark - lookAhead.size);
9352
9415
  const to = watermark + lookAhead.size;
9353
9416
  const deps = lookAhead.candidateDeps();
9354
- const handlers = chunkPXPPZF5K_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkPXPPZF5K_cjs.contractHandlers.get(t)).filter(hasCandidates);
9417
+ const handlers = chunkOIZ2V2VD_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkOIZ2V2VD_cjs.contractHandlers.get(t)).filter(hasCandidates);
9355
9418
  const band = /* @__PURE__ */ new Map();
9356
9419
  for (let index = from; index <= to; index++) {
9357
9420
  const descriptor = lookAhead.materialize(index);
@@ -9362,7 +9425,7 @@ var ContractManager = class _ContractManager {
9362
9425
  index,
9363
9426
  params: {
9364
9427
  ...candidate,
9365
- ...chunkPXPPZF5K_cjs.speculativeReceiveMetadata(descriptor)
9428
+ ...chunkOIZ2V2VD_cjs.speculativeReceiveMetadata(descriptor)
9366
9429
  }
9367
9430
  });
9368
9431
  }
@@ -9424,7 +9487,7 @@ var ContractManager = class _ContractManager {
9424
9487
  });
9425
9488
  for (const entry of pending) entry.catchUpPending = false;
9426
9489
  } catch (err) {
9427
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
9490
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
9428
9491
  this.markSyncDegraded(err);
9429
9492
  }
9430
9493
  }
@@ -9474,7 +9537,7 @@ var ContractManager = class _ContractManager {
9474
9537
  await this.fetchContractVxosFromIndexer([contract]);
9475
9538
  this.markSyncOnline();
9476
9539
  } catch (err) {
9477
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
9540
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
9478
9541
  this.markSyncDegraded(err);
9479
9542
  }
9480
9543
  await this.watcher.addContract(contract);
@@ -9511,7 +9574,7 @@ var ContractManager = class _ContractManager {
9511
9574
  return result;
9512
9575
  }
9513
9576
  async upsertContractRow(params) {
9514
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(params.type);
9577
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(params.type);
9515
9578
  if (!handler) {
9516
9579
  throw new Error(`No handler registered for contract type '${params.type}'`);
9517
9580
  }
@@ -9611,7 +9674,7 @@ var ContractManager = class _ContractManager {
9611
9674
  `scanContracts: batchSize must be a positive integer (got ${String(opts.batchSize)})`
9612
9675
  );
9613
9676
  }
9614
- const registered = chunkPXPPZF5K_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkPXPPZF5K_cjs.contractHandlers.get(t)).filter(isDiscoverable);
9677
+ const registered = chunkOIZ2V2VD_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkOIZ2V2VD_cjs.contractHandlers.get(t)).filter(isDiscoverable);
9615
9678
  const discoverables = [
9616
9679
  ...registered.filter((h) => h.type === "boarding"),
9617
9680
  ...registered.filter((h) => h.type !== "boarding")
@@ -9746,7 +9809,7 @@ var ContractManager = class _ContractManager {
9746
9809
  await this.syncContracts({ contracts, pageSize });
9747
9810
  this.markSyncOnline();
9748
9811
  } catch (err) {
9749
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
9812
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
9750
9813
  this.markSyncDegraded(err);
9751
9814
  }
9752
9815
  const vtxos = await this.getVtxosForContracts(contracts);
@@ -9767,7 +9830,7 @@ var ContractManager = class _ContractManager {
9767
9830
  }
9768
9831
  const tapscriptCache = tapscripts ?? /* @__PURE__ */ new Map();
9769
9832
  return vtxos.map(
9770
- (vtxo) => extendVirtualCoinForContract(chunkZIRFXBKL_cjs.normalizeVtxo(vtxo), byScript, tapscriptCache)
9833
+ (vtxo) => extendVirtualCoinForContract(chunk2JV4VQ7C_cjs.normalizeVtxo(vtxo), byScript, tapscriptCache)
9771
9834
  );
9772
9835
  }
9773
9836
  /** @inheritdoc */
@@ -9811,14 +9874,14 @@ var ContractManager = class _ContractManager {
9811
9874
  const byScript = new Map(contracts.map((contract) => [contract.script, contract]));
9812
9875
  const asking = vtxos.filter((vtxo) => {
9813
9876
  const contract = byScript.get(vtxo.script);
9814
- return contract !== void 0 && chunkPXPPZF5K_cjs.contractHandlers.get(contract.type)?.assertSpendableNow !== void 0;
9877
+ return contract !== void 0 && chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type)?.assertSpendableNow !== void 0;
9815
9878
  });
9816
9879
  if (asking.length === 0) return refused;
9817
9880
  const tip = await this.currentChainTip();
9818
9881
  const walletKey = await walletPubKey?.();
9819
9882
  for (const vtxo of asking) {
9820
9883
  const contract = byScript.get(vtxo.script);
9821
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
9884
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
9822
9885
  if (!handler?.assertSpendableNow) continue;
9823
9886
  const context = {
9824
9887
  collaborative: true,
@@ -9833,7 +9896,7 @@ var ContractManager = class _ContractManager {
9833
9896
  // the next handler to answer a CSV question would meet a
9834
9897
  // TypeError instead of a `false`. Carry the coin only when it
9835
9898
  // really is one.
9836
- vtxo: chunkZIRFXBKL_cjs.isVirtualCoin(vtxo) && "status" in vtxo ? vtxo : void 0
9899
+ vtxo: chunk2JV4VQ7C_cjs.isVirtualCoin(vtxo) && "status" in vtxo ? vtxo : void 0
9837
9900
  };
9838
9901
  try {
9839
9902
  await handler.assertSpendableNow(
@@ -9989,7 +10052,7 @@ var ContractManager = class _ContractManager {
9989
10052
  const { contractScript, collaborative = true, walletPubKey, vtxo } = options;
9990
10053
  const [contract] = await this.getContracts({ script: contractScript });
9991
10054
  if (!contract) return [];
9992
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
10055
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
9993
10056
  if (!handler) return [];
9994
10057
  const script = handler.createScript(contract.params);
9995
10058
  const tip = await this.currentChainTip();
@@ -10017,7 +10080,7 @@ var ContractManager = class _ContractManager {
10017
10080
  const { contractScript, collaborative = true, walletPubKey } = options;
10018
10081
  const [contract] = await this.getContracts({ script: contractScript });
10019
10082
  if (!contract) return [];
10020
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
10083
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
10021
10084
  if (!handler) return [];
10022
10085
  const script = handler.createScript(contract.params);
10023
10086
  const context = {
@@ -10073,7 +10136,7 @@ var ContractManager = class _ContractManager {
10073
10136
  }
10074
10137
  async refreshOutpoints(outpoints) {
10075
10138
  if (outpoints.length === 0) return;
10076
- const { vtxos } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(this.config.indexerProvider, {
10139
+ const { vtxos } = await chunk2JV4VQ7C_cjs.getNormalizedVtxos(this.config.indexerProvider, {
10077
10140
  outpoints
10078
10141
  });
10079
10142
  if (vtxos.length === 0) return;
@@ -10152,7 +10215,7 @@ var ContractManager = class _ContractManager {
10152
10215
  break;
10153
10216
  }
10154
10217
  } catch (err) {
10155
- if (!chunkZIRFXBKL_cjs.isRetryableProviderError(err)) throw err;
10218
+ if (!chunk2JV4VQ7C_cjs.isRetryableProviderError(err)) throw err;
10156
10219
  this.markSyncDegraded(err);
10157
10220
  }
10158
10221
  this.emitEvent(event);
@@ -10231,7 +10294,7 @@ var ContractManager = class _ContractManager {
10231
10294
  */
10232
10295
  async reconcilePendingFrontier(contracts) {
10233
10296
  const scriptToContract = new Map(contracts.map((c) => [c.script, c]));
10234
- const vtxos = await chunkZIRFXBKL_cjs.getAllNormalizedVtxos(
10297
+ const vtxos = await chunk2JV4VQ7C_cjs.getAllNormalizedVtxos(
10235
10298
  this.config.indexerProvider,
10236
10299
  contracts.map((c) => c.script),
10237
10300
  { pendingOnly: true }
@@ -10314,7 +10377,7 @@ var ContractManager = class _ContractManager {
10314
10377
  }
10315
10378
  return result;
10316
10379
  }
10317
- async fetchContractVtxosBulk(contracts, pageSize = chunkZIRFXBKL_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
10380
+ async fetchContractVtxosBulk(contracts, pageSize = chunk2JV4VQ7C_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
10318
10381
  if (contracts.length === 0) {
10319
10382
  return { vtxosByScript: /* @__PURE__ */ new Map(), promoted: /* @__PURE__ */ new Map() };
10320
10383
  }
@@ -10330,7 +10393,7 @@ var ContractManager = class _ContractManager {
10330
10393
  before: syncWindow.before
10331
10394
  }
10332
10395
  } : {};
10333
- const vtxos = await chunkZIRFXBKL_cjs.getAllNormalizedVtxos(
10396
+ const vtxos = await chunk2JV4VQ7C_cjs.getAllNormalizedVtxos(
10334
10397
  this.config.indexerProvider,
10335
10398
  contracts.map((c) => c.script),
10336
10399
  { ...windowOpts, pageSize }
@@ -10475,7 +10538,7 @@ var deserializeTapLeaf = (t) => {
10475
10538
  const s = base.hex.decode(t.s);
10476
10539
  return [cb, s];
10477
10540
  };
10478
- var deserializeVtxo = (o) => chunkZIRFXBKL_cjs.normalizeVtxo({
10541
+ var deserializeVtxo = (o) => chunk2JV4VQ7C_cjs.normalizeVtxo({
10479
10542
  ...o,
10480
10543
  createdAt: new Date(o.createdAt),
10481
10544
  tapTree: base.hex.decode(o.tapTree),
@@ -11298,7 +11361,7 @@ var HDDescriptorProvider = class _HDDescriptorProvider {
11298
11361
  */
11299
11362
  materializeDescriptorAt(index) {
11300
11363
  const descriptor = this.identity.descriptor;
11301
- const network = chunkPXPPZF5K_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
11364
+ const network = chunkOIZ2V2VD_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
11302
11365
  const expansion = descriptorsScure.expand({ descriptor, network, index });
11303
11366
  const keyInfo = expansion.expansionMap?.["@0"];
11304
11367
  if (!keyInfo?.keyExpression) {
@@ -11446,7 +11509,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
11446
11509
  const provider = await resolveDescriptorProvider(config, setup.walletRepository);
11447
11510
  if (!provider) return void 0;
11448
11511
  const allowSilentFallback = (config.walletMode ?? "auto") === "auto";
11449
- const expectedContractType = setup.offchainTapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? "delegate" : "default";
11512
+ const expectedContractType = setup.offchainTapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? "delegate" : "default";
11450
11513
  const factoryOpts = {
11451
11514
  walletRepository: setup.walletRepository,
11452
11515
  contractRepository: setup.contractRepository,
@@ -11626,7 +11689,9 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
11626
11689
  const { tapscript: newTapscript, params } = buildReceiveContract(
11627
11690
  wallet.offchainTapscript,
11628
11691
  descriptor,
11629
- wallet.network.hrp);
11692
+ wallet.network.hrp,
11693
+ true
11694
+ );
11630
11695
  const newScript = params.script;
11631
11696
  const manager = await wallet.getContractManager();
11632
11697
  await manager.createContract(params);
@@ -11645,7 +11710,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
11645
11710
  };
11646
11711
  function deriveLeafPubkey(descriptor) {
11647
11712
  try {
11648
- return chunkPXPPZF5K_cjs.deriveDescriptorLeafPubKey(descriptor);
11713
+ return chunkOIZ2V2VD_cjs.deriveDescriptorLeafPubKey(descriptor);
11649
11714
  } catch (e) {
11650
11715
  throw new NonRangeableDescriptorError(
11651
11716
  "Cannot derive leaf pubkey: descriptor is not a materialized, parsable tr(...) shape.",
@@ -11657,7 +11722,7 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
11657
11722
  const pubKey = deriveLeafPubkey(descriptor);
11658
11723
  const tapscript = rebuildTapscript(current, pubKey);
11659
11724
  const serverPubKey = tapscript.options.serverPubKey;
11660
- const csvTimelock = chunkZIRFXBKL_cjs.timelockToSequence(tapscript.options.csvTimelock).toString();
11725
+ const csvTimelock = chunk2JV4VQ7C_cjs.timelockToSequence(tapscript.options.csvTimelock).toString();
11661
11726
  const base$1 = {
11662
11727
  script: base.hex.encode(tapscript.pkScript),
11663
11728
  address: tapscript.address(hrp, serverPubKey).encode(),
@@ -11668,11 +11733,11 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
11668
11733
  // index-0 key. Without it, spends produce unsigned PSBTs that the
11669
11734
  // server rejects with `INVALID_PSBT_INPUT (5): missing tapscript spend sig`.
11670
11735
  metadata: {
11671
- ...{ source: chunkPXPPZF5K_cjs.WALLET_RECEIVE_SOURCE },
11736
+ ...tagSource && { source: chunkOIZ2V2VD_cjs.WALLET_RECEIVE_SOURCE },
11672
11737
  signingDescriptor: descriptor
11673
11738
  }
11674
11739
  };
11675
- const params = tapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? {
11740
+ const params = tapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? {
11676
11741
  ...base$1,
11677
11742
  type: "delegate",
11678
11743
  params: {
@@ -11693,10 +11758,10 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
11693
11758
  return { tapscript, params };
11694
11759
  }
11695
11760
  function rebuildTapscript(current, pubKey) {
11696
- if (current instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script) {
11697
- return new chunkPXPPZF5K_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
11761
+ if (current instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script) {
11762
+ return new chunkOIZ2V2VD_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
11698
11763
  }
11699
- return new chunkPXPPZF5K_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
11764
+ return new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
11700
11765
  }
11701
11766
  async function pickActiveReceive(contractRepository, serverPubKey, expectedType) {
11702
11767
  const candidates = await contractRepository.getContracts({
@@ -11705,7 +11770,7 @@ async function pickActiveReceive(contractRepository, serverPubKey, expectedType)
11705
11770
  });
11706
11771
  const serverPubKeyHex = base.hex.encode(serverPubKey);
11707
11772
  const matching = candidates.filter(
11708
- (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkPXPPZF5K_cjs.WALLET_RECEIVE_SOURCE
11773
+ (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkOIZ2V2VD_cjs.WALLET_RECEIVE_SOURCE
11709
11774
  ).sort((a, b) => {
11710
11775
  if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
11711
11776
  return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
@@ -11752,6 +11817,7 @@ function computeOffchainBalance(vtxos, caps) {
11752
11817
  let intentLocked = 0;
11753
11818
  let recoverable = 0;
11754
11819
  let pendingRecovery = 0;
11820
+ let unrolled = 0;
11755
11821
  const owned = /* @__PURE__ */ new Map();
11756
11822
  const spendable = /* @__PURE__ */ new Map();
11757
11823
  const addAssets = (into, vtxo) => {
@@ -11760,17 +11826,21 @@ function computeOffchainBalance(vtxos, caps) {
11760
11826
  }
11761
11827
  };
11762
11828
  for (const vtxo of vtxos) {
11763
- if (chunkZIRFXBKL_cjs.hasTerminalSpend(vtxo)) continue;
11829
+ if (chunk2JV4VQ7C_cjs.hasTerminalSpend(vtxo)) continue;
11764
11830
  addAssets(owned, vtxo);
11831
+ if (vtxo.isUnrolled) {
11832
+ unrolled += vtxo.value;
11833
+ continue;
11834
+ }
11765
11835
  if (isPendingRecovery(vtxo)) {
11766
11836
  pendingRecovery += vtxo.value;
11767
11837
  continue;
11768
11838
  }
11769
- if (chunkZIRFXBKL_cjs.canRecoverOnchain(vtxo, now)) {
11839
+ if (chunk2JV4VQ7C_cjs.canRecoverOnchain(vtxo, now)) {
11770
11840
  recoverable += vtxo.value;
11771
11841
  continue;
11772
11842
  }
11773
- if (!chunkZIRFXBKL_cjs.canSpendOffchain(vtxo, now)) continue;
11843
+ if (!chunk2JV4VQ7C_cjs.canSpendOffchain(vtxo, now)) continue;
11774
11844
  if (vtxo.isPreconfirmed) {
11775
11845
  preconfirmed += vtxo.value;
11776
11846
  } else {
@@ -11794,7 +11864,8 @@ function computeOffchainBalance(vtxos, caps) {
11794
11864
  intentLocked,
11795
11865
  recoverable,
11796
11866
  pendingRecovery,
11797
- total: settled + preconfirmed + recoverable + pendingRecovery,
11867
+ unrolled,
11868
+ total: settled + preconfirmed + recoverable + pendingRecovery + unrolled,
11798
11869
  assets: toAssets(owned),
11799
11870
  availableAssets: toAssets(spendable)
11800
11871
  };
@@ -11939,12 +12010,12 @@ var InputSignerRouter = class {
11939
12010
  };
11940
12011
 
11941
12012
  // src/wallet/wallet.ts
11942
- var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunkZIRFXBKL_cjs.DEFAULT_ARKADE_SERVER_URL;
12013
+ var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunk2JV4VQ7C_cjs.DEFAULT_ARKADE_SERVER_URL;
11943
12014
  function intentProofJobs(coins) {
11944
12015
  if (coins.length === 0) return [];
11945
12016
  const coinJobs = coins.map((coin, i) => ({
11946
12017
  index: i + 1,
11947
- lookupScript: chunkZIRFXBKL_cjs.VtxoScript.decode(coin.tapTree).pkScript
12018
+ lookupScript: chunk2JV4VQ7C_cjs.VtxoScript.decode(coin.tapTree).pkScript
11948
12019
  }));
11949
12020
  return [{ index: 0, lookupScript: coinJobs[0].lookupScript }, ...coinJobs];
11950
12021
  }
@@ -11976,7 +12047,7 @@ function dedupeTimelocks(timelocks) {
11976
12047
  const seen = /* @__PURE__ */ new Set();
11977
12048
  const deduped = [];
11978
12049
  for (const timelock of timelocks) {
11979
- const sequence = chunkZIRFXBKL_cjs.timelockToSequence(timelock).toString();
12050
+ const sequence = chunk2JV4VQ7C_cjs.timelockToSequence(timelock).toString();
11980
12051
  if (seen.has(sequence)) continue;
11981
12052
  seen.add(sequence);
11982
12053
  deduped.push(timelock);
@@ -11993,7 +12064,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
11993
12064
  state: "active"
11994
12065
  });
11995
12066
  const newest = candidates.filter(
11996
- (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkPXPPZF5K_cjs.WALLET_RECEIVE_SOURCE
12067
+ (c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkOIZ2V2VD_cjs.WALLET_RECEIVE_SOURCE
11997
12068
  ).sort((a, b) => {
11998
12069
  if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
11999
12070
  return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
@@ -12001,7 +12072,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
12001
12072
  if (!newest?.params.pubKey) return baseline;
12002
12073
  try {
12003
12074
  const pubKey = base.hex.decode(newest.params.pubKey);
12004
- return new chunkPXPPZF5K_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
12075
+ return new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
12005
12076
  } catch (e) {
12006
12077
  console.warn("Skipping malformed boarding contract at boot", newest.script, e);
12007
12078
  return baseline;
@@ -12017,13 +12088,16 @@ function filterSnapshotVtxos(snapshot, filter, pendingSpendOutpoints) {
12017
12088
  if (pendingSpendOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
12018
12089
  return false;
12019
12090
  }
12020
- if (!chunkZIRFXBKL_cjs.hasTerminalSpend(vtxo)) {
12021
- if (!f.withRecoverable && chunkZIRFXBKL_cjs.canRecoverOnchain(vtxo, now)) {
12022
- return false;
12023
- }
12024
- return true;
12091
+ if (vtxo.isUnrolled) {
12092
+ return !!f.withUnrolled;
12025
12093
  }
12026
- return !!(f.withUnrolled && vtxo.isUnrolled);
12094
+ if (chunk2JV4VQ7C_cjs.hasTerminalSpend(vtxo)) {
12095
+ return false;
12096
+ }
12097
+ if (!f.withRecoverable && chunk2JV4VQ7C_cjs.canRecoverOnchain(vtxo, now)) {
12098
+ return false;
12099
+ }
12100
+ return true;
12027
12101
  });
12028
12102
  }
12029
12103
  var PENDING_RECOVERY_REASON = "is past its operator signer's rotation cutoff \u2014 the operator will not co-sign it until it recovers";
@@ -12359,7 +12433,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12359
12433
  */
12360
12434
  static async setupWalletConfig(config, pubKey) {
12361
12435
  const arkadeServerUrl = getArkadeServerUrl(config);
12362
- const arkProvider = config.arkProvider || new chunkZIRFXBKL_cjs.RestArkProvider(arkadeServerUrl);
12436
+ const arkProvider = config.arkProvider || new chunk2JV4VQ7C_cjs.RestArkProvider(arkadeServerUrl);
12363
12437
  let indexerProvider = config.indexerProvider;
12364
12438
  if (!indexerProvider) {
12365
12439
  let indexerUrl = config.indexerUrl;
@@ -12376,7 +12450,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12376
12450
  indexerUrl = arkadeServerUrl;
12377
12451
  }
12378
12452
  }
12379
- indexerProvider = new chunk3S3JZUEN_cjs.RestIndexerProvider(indexerUrl);
12453
+ indexerProvider = new chunkCO3KKSWM_cjs.RestIndexerProvider(indexerUrl);
12380
12454
  }
12381
12455
  const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
12382
12456
  const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
@@ -12385,7 +12459,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12385
12459
  source: serverInfoSource,
12386
12460
  lastOnlineAt: serverInfoLastOnlineAt
12387
12461
  } = await resolveArkInfo(arkProvider, walletRepository);
12388
- const network = chunkZIRFXBKL_cjs.getNetwork(info.network);
12462
+ const network = chunk2JV4VQ7C_cjs.getNetwork(info.network);
12389
12463
  if ("descriptor" in config.identity) {
12390
12464
  const descriptor = config.identity.descriptor;
12391
12465
  const identityIsMainnet = !descriptor.includes("tpub");
@@ -12425,18 +12499,18 @@ var ReadonlyWallet = class _ReadonlyWallet {
12425
12499
  value: info.boardingExitDelay,
12426
12500
  type: info.boardingExitDelay < 512n ? "blocks" : "seconds"
12427
12501
  };
12428
- const serverPubKey = chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
12429
- const delegatePubKey = config.delegateProvider ? await config.delegateProvider.getDelegateInfo().then((info2) => chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : config.delegatorProvider ? await config.delegatorProvider.getDelegateInfo().then((info2) => chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : void 0;
12502
+ const serverPubKey = chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
12503
+ const delegatePubKey = config.delegateProvider ? await config.delegateProvider.getDelegateInfo().then((info2) => chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : config.delegatorProvider ? await config.delegatorProvider.getDelegateInfo().then((info2) => chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : void 0;
12430
12504
  const offchainOptions = {
12431
12505
  pubKey,
12432
12506
  serverPubKey,
12433
12507
  csvTimelock: exitTimelock
12434
12508
  };
12435
- const offchainTapscript = !delegatePubKey ? new chunkPXPPZF5K_cjs.DefaultVtxo.Script(offchainOptions) : new chunkPXPPZF5K_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
12436
- const boardingTapscript = chunkPXPPZF5K_cjs.BoardingContractHandler.createScript({
12509
+ const offchainTapscript = !delegatePubKey ? new chunkOIZ2V2VD_cjs.DefaultVtxo.Script(offchainOptions) : new chunkOIZ2V2VD_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
12510
+ const boardingTapscript = chunkOIZ2V2VD_cjs.BoardingContractHandler.createScript({
12437
12511
  pubKey: base.hex.encode(pubKey),
12438
12512
  serverPubKey: base.hex.encode(serverPubKey),
12439
- csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(boardingTimelock).toString()
12513
+ csvTimelock: chunk2JV4VQ7C_cjs.timelockToSequence(boardingTimelock).toString()
12440
12514
  });
12441
12515
  return {
12442
12516
  arkProvider,
@@ -12526,7 +12600,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
12526
12600
  this.getBoardingUtxos(),
12527
12601
  this.contractSnapshot()
12528
12602
  ]);
12529
- const vtxos = filterSnapshotVtxos(snapshot, void 0, this._pendingSpendOutpoints);
12603
+ const vtxos = filterSnapshotVtxos(
12604
+ snapshot,
12605
+ { withRecoverable: true, withUnrolled: true },
12606
+ this._pendingSpendOutpoints
12607
+ );
12530
12608
  let confirmed = 0;
12531
12609
  let unconfirmed = 0;
12532
12610
  for (const utxo of boardingUtxos) {
@@ -12554,6 +12632,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12554
12632
  intentLocked: offchain.intentLocked,
12555
12633
  recoverable: offchain.recoverable,
12556
12634
  pendingRecovery: offchain.pendingRecovery,
12635
+ unrolled: offchain.unrolled,
12557
12636
  total: totalBoarding + offchain.total,
12558
12637
  assets: offchain.assets,
12559
12638
  availableAssets: offchain.availableAssets
@@ -12733,7 +12812,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12733
12812
  const response = await contractManager.getContractsWithVtxos();
12734
12813
  const allVtxos = response.flatMap((_) => _.vtxos);
12735
12814
  const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
12736
- const resolveTxCreatedAt = (txids) => chunkZIRFXBKL_cjs.fetchVtxoCreatedAtByTxid(this.indexerProvider, txids);
12815
+ const resolveTxCreatedAt = (txids) => chunk2JV4VQ7C_cjs.fetchVtxoCreatedAtByTxid(this.indexerProvider, txids);
12737
12816
  return buildTransactionHistory(
12738
12817
  allVtxos,
12739
12818
  boardingTxs,
@@ -12827,7 +12906,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12827
12906
  },
12828
12907
  isUnrolled: true,
12829
12908
  ...boardingFacts,
12830
- virtualStatus: chunkZIRFXBKL_cjs.toVirtualStatus(boardingFacts),
12909
+ virtualStatus: chunk2JV4VQ7C_cjs.toVirtualStatus(boardingFacts),
12831
12910
  spentBy: "",
12832
12911
  createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
12833
12912
  script: scriptHex
@@ -12883,9 +12962,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
12883
12962
  async getBoardingTapscripts(allowedSigners) {
12884
12963
  const byScript = /* @__PURE__ */ new Map();
12885
12964
  const add = (s) => byScript.set(base.hex.encode(s.pkScript), s);
12886
- const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunkPXPPZF5K_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
12965
+ const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunkOIZ2V2VD_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
12887
12966
  add(
12888
- new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
12967
+ new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
12889
12968
  pubKey: await this.identity.xOnlyPublicKey(),
12890
12969
  serverPubKey: this.boardingTapscript.options.serverPubKey,
12891
12970
  csvTimelock: boardingCsv
@@ -12900,7 +12979,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12900
12979
  for (const c of boardingContracts) {
12901
12980
  if (!allowed.has(toXOnlySignerHex(c.params.serverPubKey))) continue;
12902
12981
  try {
12903
- add(chunkPXPPZF5K_cjs.BoardingContractHandler.createScript(c.params));
12982
+ add(chunkOIZ2V2VD_cjs.BoardingContractHandler.createScript(c.params));
12904
12983
  } catch (e) {
12905
12984
  console.warn("Skipping malformed boarding contract", c.script, e);
12906
12985
  }
@@ -12938,7 +13017,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12938
13017
  // Per-row CSV delay decoded from THIS tapscript's exit leaf —
12939
13018
  // not the wallet's current boarding timelock, which a signer
12940
13019
  // rotation may have changed.
12941
- csvTimelock: chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(base.hex.decode(tapscript.exitScript)).params.timelock,
13020
+ csvTimelock: chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(base.hex.decode(tapscript.exitScript)).params.timelock,
12942
13021
  coins: utxos
12943
13022
  });
12944
13023
  }
@@ -13071,7 +13150,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13071
13150
  /** Fetch Arkade transaction ids that are still pending final settlement. */
13072
13151
  async fetchPendingTxs() {
13073
13152
  const scripts = await this.getWalletScripts();
13074
- const vtxos = await chunkZIRFXBKL_cjs.getAllNormalizedVtxos(this.indexerProvider, scripts);
13153
+ const vtxos = await chunk2JV4VQ7C_cjs.getAllNormalizedVtxos(this.indexerProvider, scripts);
13075
13154
  return vtxos.filter(
13076
13155
  (vtxo) => (vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept) && vtxo.arkTxId !== void 0
13077
13156
  ).map((_) => _.arkTxId);
@@ -13102,7 +13181,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13102
13181
  });
13103
13182
  for (const contract of contracts) {
13104
13183
  if (map.has(contract.script)) continue;
13105
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
13184
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
13106
13185
  if (handler) {
13107
13186
  const script = handler.createScript(contract.params);
13108
13187
  map.set(contract.script, script);
@@ -13214,7 +13293,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13214
13293
  }
13215
13294
  });
13216
13295
  const baselinePubkey = await this.identity.xOnlyPublicKey();
13217
- const delegatePubKey = this.offchainTapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
13296
+ const delegatePubKey = this.offchainTapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
13218
13297
  const baselineSigners = [
13219
13298
  this.offchainTapscript.options.serverPubKey,
13220
13299
  ...[...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h))
@@ -13222,8 +13301,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
13222
13301
  const seenBaselineScripts = /* @__PURE__ */ new Set();
13223
13302
  for (const serverPubKey of baselineSigners) {
13224
13303
  for (const csvTimelock of this.walletContractTimelocks) {
13225
- const csvTimelockStr = chunkZIRFXBKL_cjs.timelockToSequence(csvTimelock).toString();
13226
- const defaultScript = new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
13304
+ const csvTimelockStr = chunk2JV4VQ7C_cjs.timelockToSequence(csvTimelock).toString();
13305
+ const defaultScript = new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
13227
13306
  pubKey: baselinePubkey,
13228
13307
  serverPubKey,
13229
13308
  csvTimelock
@@ -13244,7 +13323,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13244
13323
  });
13245
13324
  }
13246
13325
  if (delegatePubKey) {
13247
- const delegateScript = new chunkPXPPZF5K_cjs.DelegateVtxo.Script({
13326
+ const delegateScript = new chunkOIZ2V2VD_cjs.DelegateVtxo.Script({
13248
13327
  pubKey: baselinePubkey,
13249
13328
  serverPubKey,
13250
13329
  delegatePubKey,
@@ -13268,9 +13347,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
13268
13347
  }
13269
13348
  }
13270
13349
  }
13271
- const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunkPXPPZF5K_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
13350
+ const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunkOIZ2V2VD_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
13272
13351
  for (const serverPubKey of baselineSigners) {
13273
- const baselineBoarding = new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
13352
+ const baselineBoarding = new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
13274
13353
  pubKey: baselinePubkey,
13275
13354
  serverPubKey,
13276
13355
  csvTimelock: boardingCsvTimelock
@@ -13283,7 +13362,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13283
13362
  params: {
13284
13363
  pubKey: base.hex.encode(baselineBoarding.options.pubKey),
13285
13364
  serverPubKey: base.hex.encode(serverPubKey),
13286
- csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(boardingCsvTimelock).toString()
13365
+ csvTimelock: chunk2JV4VQ7C_cjs.timelockToSequence(boardingCsvTimelock).toString()
13287
13366
  },
13288
13367
  script: boardingScriptHex,
13289
13368
  address: baselineBoarding.address(this.network.hrp, serverPubKey).encode(),
@@ -13413,6 +13492,27 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13413
13492
  console.warn("server-signer rotation on info change failed", e);
13414
13493
  }
13415
13494
  }
13495
+ /**
13496
+ * Await an `onServerInfoChanged` handler still applying a rotation.
13497
+ *
13498
+ * The provider emits synchronously but {@link handleServerInfoChanged} runs
13499
+ * off the emit, so between the two a caller can observe a half-applied
13500
+ * rotation: {@link rotateServerSigner} persists the active signer's contract
13501
+ * rows *before* committing the tapscripts, so `arkServerPublicKey` still
13502
+ * reads the old key while the new key's rows are already in the repository.
13503
+ * A path that refreshes server info and then reads signer-derived state must
13504
+ * drain the chain first, or it both reads that torn state and races the
13505
+ * handler for the rotation itself.
13506
+ *
13507
+ * Resolves once the chain is idle; a handler that threw already logged, and
13508
+ * its rejection is swallowed here.
13509
+ *
13510
+ * @internal Invoked by {@link dispose} and the {@link VtxoManager} migration
13511
+ * pass; not part of the stable public API.
13512
+ */
13513
+ async settleServerInfoChanges() {
13514
+ await this._serverInfoInFlight?.catch(() => void 0);
13515
+ }
13416
13516
  _receiveRotatorInstalled = false;
13417
13517
  /**
13418
13518
  * Descriptor-aware signer used by {@link _signerRouter} to sign
@@ -13462,7 +13562,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13462
13562
  serverPubKey: this.offchainTapscript.options.serverPubKey,
13463
13563
  deprecatedSignerPubKeys: [...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h)),
13464
13564
  csvTimelocks: this.walletContractTimelocks,
13465
- delegatePubKey: this.offchainTapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0
13565
+ delegatePubKey: this.offchainTapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0
13466
13566
  };
13467
13567
  }
13468
13568
  _signerRouter;
@@ -13547,43 +13647,250 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13547
13647
  * provider and keeps a single index-0 boarding address for its lifetime,
13548
13648
  * so this returns the existing {@link getBoardingAddress} unchanged
13549
13649
  * (no rotation, no index burned).
13650
+ *
13651
+ * **Behaviour change.** A wallet configured with a custom
13652
+ * {@link DescriptorProvider} (`walletMode: <provider>`) now rotates here.
13653
+ * It previously did not: allocation went through the contract manager,
13654
+ * which only wires an `allocate` hook for {@link HDDescriptorProvider}, so
13655
+ * such a wallet read as "declined to allocate" and silently kept its
13656
+ * index-0 boarding address forever. Those wallets now burn an index per
13657
+ * call — including via {@link maybeRotateBoardingAfterBoard}, which fires
13658
+ * on every settle that consumes a boarding UTXO. Funds at retired
13659
+ * addresses stay reachable: each rotation persists its `boarding` contract
13660
+ * before swapping, and {@link getBoardingUtxos} fans out over the full
13661
+ * historical set.
13662
+ *
13663
+ * @deprecated Use {@link getNewAddresses} — it mints any combination of
13664
+ * address types at one shared index, and reports the contract row behind
13665
+ * each. Note the difference in display behaviour: this method *swaps* the
13666
+ * advertised boarding address, where `getNewAddresses` mints side
13667
+ * addresses and leaves {@link getBoardingAddress} alone. To keep this
13668
+ * method's behaviour, keep calling this method.
13550
13669
  */
13551
13670
  async getNewBoardingAddress() {
13552
- const provider = this._descriptorProvider;
13553
- if (!provider) {
13554
- return this.getBoardingAddress();
13671
+ const [minted] = await this.allocateAddresses(["boarding"], false, true);
13672
+ if (!minted?.allocated) return this.getBoardingAddress();
13673
+ if (minted.type === "boarding") this.setBoardingTapscriptForRotation(minted.tapscript);
13674
+ return minted.address;
13675
+ }
13676
+ /**
13677
+ * Allocate a *fresh* address of each requested type, all derived from one
13678
+ * newly allocated HD index.
13679
+ *
13680
+ * This is the explicit allocator the receive path otherwise lacks:
13681
+ * {@link getAddress} and {@link getBoardingAddress} are stable reads of the
13682
+ * wallet's display addresses, and the display receive address only advances
13683
+ * when a payment arrives ({@link WalletReceiveRotator} rotates on
13684
+ * `vtxo_received`). Issuing a second address before the first is paid — one
13685
+ * invoice for Alice, another for Bob — has to go through here.
13686
+ *
13687
+ * Each call:
13688
+ *
13689
+ * - allocates **one** index from the shared HD stream, however many types
13690
+ * were asked for, so a `default` + `boarding` pair are siblings rather
13691
+ * than two burnt indices;
13692
+ * - builds each requested script at that index, preserving every other
13693
+ * option of the wallet's current script for that flavour (including a
13694
+ * delegate wallet's `delegate` shape);
13695
+ * - persists each as an `active` contract carrying its `signingDescriptor`,
13696
+ * so the ContractWatcher monitors it, the balance counts it, and
13697
+ * {@link signerForDescriptor} can recover the key;
13698
+ * - slides the look-ahead band, since the watermark moved past indices an
13699
+ * external issuer may still be handing out.
13700
+ *
13701
+ * The minted rows are deliberately left **untagged**: the boot lookups
13702
+ * adopt the newest {@link WALLET_RECEIVE_SOURCE}-tagged row as the display
13703
+ * address, and a side address issued to one counterparty must not become
13704
+ * the address the wallet advertises to everyone else. {@link getAddress}
13705
+ * and {@link getBoardingAddress} are unchanged by this call.
13706
+ *
13707
+ * A wallet with no HD stream (`walletMode: 'static'` / `'auto'`) has one
13708
+ * address per flavour for its lifetime. Without `forceNew` it returns those
13709
+ * — the real persisted rows, no index burned; with `forceNew` it throws
13710
+ * {@link WalletCannotAllocateAddressError} rather than hand back an address
13711
+ * that is not in fact fresh.
13712
+ *
13713
+ * @example
13714
+ * ```typescript
13715
+ * const [invoice] = await wallet.getNewAddresses({ forceNew: true });
13716
+ * // hand `invoice.address` to Alice, keep the descriptor with the invoice
13717
+ * const signer = await wallet.signerForDescriptor(invoice.signingDescriptor);
13718
+ * ```
13719
+ */
13720
+ async getNewAddresses(opts) {
13721
+ const minted = await this.allocateAddresses(
13722
+ opts?.types ?? ["default"],
13723
+ opts?.forceNew ?? false,
13724
+ false
13725
+ );
13726
+ return minted.map(({ address, signingDescriptor, contract }) => ({
13727
+ address,
13728
+ signingDescriptor,
13729
+ contract
13730
+ }));
13731
+ }
13732
+ /**
13733
+ * Shared allocation core behind {@link getNewAddresses} and the deprecated
13734
+ * {@link getNewBoardingAddress}, so the two cannot drift on what an
13735
+ * allocation costs or what gets persisted.
13736
+ *
13737
+ * @param tagSource - Tag the persisted rows {@link WALLET_RECEIVE_SOURCE},
13738
+ * making the next boot adopt them as the display address. Only the
13739
+ * deprecated boarding allocator passes `true`; `getNewAddresses` mints side
13740
+ * addresses and must not hijack what the wallet advertises.
13741
+ */
13742
+ async allocateAddresses(types, forceNew, tagSource) {
13743
+ if (types.length === 0) {
13744
+ throw new Error("getNewAddresses: `types` must name at least one address type");
13555
13745
  }
13556
13746
  const manager = await this.getContractManager();
13557
- const descriptor = await manager.getNextSigningDescriptor();
13558
- if (!descriptor) return this.getBoardingAddress();
13559
- const pubKey = chunkPXPPZF5K_cjs.deriveDescriptorLeafPubKey(descriptor);
13560
- const newBoarding = new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
13747
+ const provider = this._descriptorProvider;
13748
+ const descriptor = !provider ? void 0 : provider instanceof HDDescriptorProvider ? await manager.getNextSigningDescriptor() : await provider.getNextSigningDescriptor();
13749
+ if (!descriptor) {
13750
+ if (forceNew) {
13751
+ throw new WalletCannotAllocateAddressError(
13752
+ provider ? "the descriptor provider declined to allocate an index" : "this wallet has no HD stream (walletMode 'static' / 'auto')"
13753
+ );
13754
+ }
13755
+ return this.currentAddresses(manager, types);
13756
+ }
13757
+ const allocated = [];
13758
+ try {
13759
+ for (const type of types) {
13760
+ allocated.push(await this.mintAddress(manager, type, descriptor, tagSource, true));
13761
+ }
13762
+ } finally {
13763
+ try {
13764
+ await manager.refillLookAhead();
13765
+ } catch (e) {
13766
+ console.warn("look-ahead refill after address allocation failed", e);
13767
+ }
13768
+ }
13769
+ return allocated;
13770
+ }
13771
+ /**
13772
+ * The wallet's existing display addresses, as persisted contract rows —
13773
+ * the honest answer for a wallet with no index to burn.
13774
+ *
13775
+ * Each type is minted from the descriptor that already owns its display
13776
+ * script ({@link displayDescriptor}), not from the identity key, so the
13777
+ * returned `signingDescriptor` is the one that signs for the returned
13778
+ * `address` even on a wallet that has rotated.
13779
+ */
13780
+ async currentAddresses(manager, types) {
13781
+ const out = [];
13782
+ for (const type of types) {
13783
+ const descriptor = await this.displayDescriptor(manager, type);
13784
+ out.push(await this.mintAddress(manager, type, descriptor, false, false));
13785
+ }
13786
+ return out;
13787
+ }
13788
+ /**
13789
+ * The descriptor that owns the wallet's current display script for `type`,
13790
+ * read off the row the wallet persisted when it adopted that script.
13791
+ *
13792
+ * Deriving it from the identity instead is only correct for a wallet that
13793
+ * never rotates. On one that has — an HD wallet whose provider later
13794
+ * declines to allocate — the display script belongs to an HD child, and
13795
+ * pairing its address with the identity descriptor hands the caller a
13796
+ * {@link NewAddress} whose `signingDescriptor` resolves, via
13797
+ * {@link signerForDescriptor}, to a signer holding the wrong key.
13798
+ *
13799
+ * Falls back to the identity's pathless `tr(pubkey)` when no row carries a
13800
+ * descriptor: the static / `auto` case, where the identity key genuinely
13801
+ * owns the display script and this is what `getNextSigningDescriptor`
13802
+ * answers too. (The index-0 baselines registered at construction carry no
13803
+ * `signingDescriptor` metadata, so those wallets take this path.)
13804
+ */
13805
+ async displayDescriptor(manager, type) {
13806
+ const display = type === "boarding" ? this._boardingTapscript : this.offchainTapscript;
13807
+ const [row] = await manager.getContracts({ script: base.hex.encode(display.pkScript) });
13808
+ const persisted = row?.metadata?.signingDescriptor;
13809
+ if (typeof persisted === "string") return persisted;
13810
+ return chunkOIZ2V2VD_cjs.identityDescriptor(this.identity);
13811
+ }
13812
+ /**
13813
+ * Build, persist and shape one address of `type` owned by `descriptor` —
13814
+ * the single build-and-register path behind both {@link allocateAddresses}
13815
+ * and {@link currentAddresses}, so a freshly allocated address and a
13816
+ * re-registered display address cannot disagree on what gets written.
13817
+ *
13818
+ * The descriptor is the sole source of the script's owner key in both
13819
+ * branches. Deriving one flavour from the descriptor and the other from a
13820
+ * tapscript field is what lets `address` and `signingDescriptor` drift
13821
+ * apart.
13822
+ */
13823
+ async mintAddress(manager, type, descriptor, tagSource, allocated) {
13824
+ if (type === "boarding") {
13825
+ const built2 = this.buildBoardingContract(
13826
+ chunkOIZ2V2VD_cjs.deriveDescriptorLeafPubKey(descriptor),
13827
+ descriptor,
13828
+ tagSource
13829
+ );
13830
+ const contract2 = await manager.createContract(built2.params);
13831
+ return {
13832
+ type,
13833
+ // `built.tapscript` is a `DefaultVtxo.Script` here without a
13834
+ // cast — the branch, not a widened local, does the narrowing.
13835
+ tapscript: built2.tapscript,
13836
+ // A boarding row persists the *ark* encoding of its script, so
13837
+ // `contract.address` is unusable for an onchain sender: the
13838
+ // onchain form has to be re-derived.
13839
+ address: built2.tapscript.onchainAddress(this.network),
13840
+ signingDescriptor: descriptor,
13841
+ contract: contract2,
13842
+ allocated
13843
+ };
13844
+ }
13845
+ const built = buildReceiveContract(
13846
+ this.offchainTapscript,
13847
+ descriptor,
13848
+ this.network.hrp,
13849
+ tagSource
13850
+ );
13851
+ const contract = await manager.createContract(built.params);
13852
+ return {
13853
+ type,
13854
+ tapscript: built.tapscript,
13855
+ // Offchain rows already store the address they advertise, and
13856
+ // reading it back keeps a coalesced row (`createContract` is
13857
+ // first-wins on script) honest about what was actually persisted.
13858
+ address: contract.address,
13859
+ signingDescriptor: descriptor,
13860
+ contract,
13861
+ allocated
13862
+ };
13863
+ }
13864
+ /**
13865
+ * Build the boarding contract owned by `pubKey`, keeping every other option
13866
+ * of the wallet's current boarding tapscript (notably the boarding-exit
13867
+ * CSV, which is index-independent). The offchain analogue lives in
13868
+ * {@link buildReceiveContract}.
13869
+ */
13870
+ buildBoardingContract(pubKey, descriptor, tagSource) {
13871
+ const tapscript = new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
13561
13872
  ...this._boardingTapscript.options,
13562
13873
  pubKey
13563
13874
  });
13564
- const csvTimelock = newBoarding.options.csvTimelock ?? chunkPXPPZF5K_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
13565
- await manager.createContract({
13566
- type: "boarding",
13875
+ const csvTimelock = tapscript.options.csvTimelock ?? chunkOIZ2V2VD_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
13876
+ return {
13877
+ tapscript,
13567
13878
  params: {
13568
- pubKey: base.hex.encode(pubKey),
13569
- serverPubKey: base.hex.encode(newBoarding.options.serverPubKey),
13570
- csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(csvTimelock).toString()
13571
- },
13572
- script: base.hex.encode(newBoarding.pkScript),
13573
- address: newBoarding.address(this.network.hrp, this.arkServerPublicKey).encode(),
13574
- state: "active",
13575
- metadata: {
13576
- source: chunkPXPPZF5K_cjs.WALLET_RECEIVE_SOURCE,
13577
- signingDescriptor: descriptor
13879
+ type: "boarding",
13880
+ params: {
13881
+ pubKey: base.hex.encode(pubKey),
13882
+ serverPubKey: base.hex.encode(tapscript.options.serverPubKey),
13883
+ csvTimelock: chunk2JV4VQ7C_cjs.timelockToSequence(csvTimelock).toString()
13884
+ },
13885
+ script: base.hex.encode(tapscript.pkScript),
13886
+ address: tapscript.address(this.network.hrp, this.arkServerPublicKey).encode(),
13887
+ state: "active",
13888
+ metadata: {
13889
+ ...tagSource && { source: chunkOIZ2V2VD_cjs.WALLET_RECEIVE_SOURCE },
13890
+ signingDescriptor: descriptor
13891
+ }
13578
13892
  }
13579
- });
13580
- this.setBoardingTapscriptForRotation(newBoarding);
13581
- try {
13582
- await manager.refillLookAhead();
13583
- } catch (e) {
13584
- console.warn("look-ahead refill after boarding allocation failed", e);
13585
- }
13586
- return newBoarding.onchainAddress(this.network);
13893
+ };
13587
13894
  }
13588
13895
  /**
13589
13896
  * @see HDWalletCapable.getCurrentSigningDescriptor
@@ -13608,7 +13915,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13608
13915
  if (this._descriptorProvider instanceof HDDescriptorProvider) {
13609
13916
  return (await this.getContractManager()).getNextSigningDescriptor();
13610
13917
  }
13611
- return chunkPXPPZF5K_cjs.identityDescriptor(this.identity);
13918
+ return chunkOIZ2V2VD_cjs.identityDescriptor(this.identity);
13612
13919
  }
13613
13920
  /**
13614
13921
  * @see HDAllocationCapable.advanceSigningDescriptorWatermark
@@ -13704,7 +14011,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13704
14011
  * the stable public API.
13705
14012
  */
13706
14013
  async rotateServerSigner(newServerPubKey, checkpointTapscript) {
13707
- const xonly = chunkPXPPZF5K_cjs.toXOnly(newServerPubKey, "ark signer key");
14014
+ const xonly = chunkOIZ2V2VD_cjs.toXOnly(newServerPubKey, "ark signer key");
13708
14015
  const newServerUnrollScript = assertValidServerUnrollScript(
13709
14016
  checkpointTapscript,
13710
14017
  resolveCheckpointExitDelayPolicy(this.network, this.checkpointExitDelayPolicy)
@@ -13733,21 +14040,21 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13733
14040
  const [currentBoardingRow] = await manager.getContracts({
13734
14041
  script: currentBoardingScript
13735
14042
  });
13736
- const newOffchain = this.offchainTapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? new chunkPXPPZF5K_cjs.DelegateVtxo.Script({
14043
+ const newOffchain = this.offchainTapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? new chunkOIZ2V2VD_cjs.DelegateVtxo.Script({
13737
14044
  ...this.offchainTapscript.options,
13738
14045
  serverPubKey: xonly
13739
- }) : new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
14046
+ }) : new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
13740
14047
  ...this.offchainTapscript.options,
13741
14048
  serverPubKey: xonly
13742
14049
  });
13743
- const newBoarding = new chunkPXPPZF5K_cjs.DefaultVtxo.Script({
14050
+ const newBoarding = new chunkOIZ2V2VD_cjs.DefaultVtxo.Script({
13744
14051
  ...this._boardingTapscript.options,
13745
14052
  serverPubKey: xonly
13746
14053
  });
13747
- const offchainCsv = chunkZIRFXBKL_cjs.timelockToSequence(newOffchain.options.csvTimelock).toString();
14054
+ const offchainCsv = chunk2JV4VQ7C_cjs.timelockToSequence(newOffchain.options.csvTimelock).toString();
13748
14055
  const newOffchainScript = base.hex.encode(newOffchain.pkScript);
13749
14056
  const newOffchainAddress = newOffchain.address(this.network.hrp, xonly).encode();
13750
- if (newOffchain instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script) {
14057
+ if (newOffchain instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script) {
13751
14058
  await manager.createContract({
13752
14059
  type: "delegate",
13753
14060
  params: {
@@ -13775,13 +14082,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13775
14082
  metadata: currentOffchainRow?.metadata
13776
14083
  });
13777
14084
  }
13778
- const boardingCsv = newBoarding.options.csvTimelock ?? chunkPXPPZF5K_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
14085
+ const boardingCsv = newBoarding.options.csvTimelock ?? chunkOIZ2V2VD_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
13779
14086
  await manager.createContract({
13780
14087
  type: "boarding",
13781
14088
  params: {
13782
14089
  pubKey: base.hex.encode(newBoarding.options.pubKey),
13783
14090
  serverPubKey: base.hex.encode(xonly),
13784
- csvTimelock: chunkZIRFXBKL_cjs.timelockToSequence(boardingCsv).toString()
14091
+ csvTimelock: chunk2JV4VQ7C_cjs.timelockToSequence(boardingCsv).toString()
13785
14092
  },
13786
14093
  script: base.hex.encode(newBoarding.pkScript),
13787
14094
  address: newBoarding.address(this.network.hrp, xonly).encode(),
@@ -13814,14 +14121,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13814
14121
  _restoreInFlight;
13815
14122
  _addPendingSpends(inputs) {
13816
14123
  for (const input of inputs) {
13817
- if (chunkZIRFXBKL_cjs.isVirtualCoin(input)) {
14124
+ if (chunk2JV4VQ7C_cjs.isVirtualCoin(input)) {
13818
14125
  this._pendingSpendOutpoints.add(`${input.txid}:${input.vout}`);
13819
14126
  }
13820
14127
  }
13821
14128
  }
13822
14129
  _removePendingSpends(inputs) {
13823
14130
  for (const input of inputs) {
13824
- if (chunkZIRFXBKL_cjs.isVirtualCoin(input)) {
14131
+ if (chunk2JV4VQ7C_cjs.isVirtualCoin(input)) {
13825
14132
  this._pendingSpendOutpoints.delete(`${input.txid}:${input.vout}`);
13826
14133
  }
13827
14134
  }
@@ -13879,13 +14186,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13879
14186
  const manager = await this.getContractManager();
13880
14187
  const provider = this._descriptorProvider;
13881
14188
  const hd = provider instanceof HDDescriptorProvider;
13882
- const staticDescriptor = hd ? void 0 : await chunkPXPPZF5K_cjs.identityDescriptor(this.identity);
14189
+ const staticDescriptor = hd ? void 0 : await chunkOIZ2V2VD_cjs.identityDescriptor(this.identity);
13883
14190
  const materialize = (index) => hd ? provider.materializeDescriptorAt(index) : staticDescriptor;
13884
- const delegatePubKey = this.offchainTapscript instanceof chunkPXPPZF5K_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
14191
+ const delegatePubKey = this.offchainTapscript instanceof chunkOIZ2V2VD_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
13885
14192
  const arkInfo = await this.arkProvider.getInfo();
13886
- const currentSignerPubKey = chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(arkInfo.signerPubkey), "ark signer key");
14193
+ const currentSignerPubKey = chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(arkInfo.signerPubkey), "ark signer key");
13887
14194
  const deprecatedSignerPubKeys = arkInfo.deprecatedSigners.map(
13888
- (s) => chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(s.pubkey), "deprecated signer key")
14195
+ (s) => chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(s.pubkey), "deprecated signer key")
13889
14196
  );
13890
14197
  const deps = {
13891
14198
  indexerProvider: this.indexerProvider,
@@ -13900,7 +14207,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13900
14207
  csvTimelocks: this.walletContractTimelocks,
13901
14208
  // Boarding-exit CSV so the boarding handler can build its
13902
14209
  // candidate script (distinct from the unilateral-exit matrix).
13903
- boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunkPXPPZF5K_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
14210
+ boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunkOIZ2V2VD_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
13904
14211
  delegatePubKey
13905
14212
  };
13906
14213
  const result = await manager.scanContracts({
@@ -13968,7 +14275,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
13968
14275
  await this._restoreInFlight?.catch(() => void 0);
13969
14276
  this._serverInfoUnsub?.();
13970
14277
  this._serverInfoUnsub = void 0;
13971
- await this._serverInfoInFlight?.catch(() => void 0);
14278
+ await this.settleServerInfoChanges();
13972
14279
  let rotatorError;
13973
14280
  try {
13974
14281
  await this._receiveRotator?.dispose();
@@ -14014,7 +14321,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14014
14321
  throw new Error("Invalid configured public key");
14015
14322
  }
14016
14323
  const setup = await ReadonlyWallet.setupWalletConfig(config, pubkey);
14017
- const forfeitPubkey = chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(setup.info.forfeitPubkey), "forfeit key");
14324
+ const forfeitPubkey = chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(setup.info.forfeitPubkey), "forfeit key");
14018
14325
  const forfeitAddress = btcSigner.Address(setup.network).decode(setup.info.forfeitAddress);
14019
14326
  const forfeitOutputScript = btcSigner.OutScript.encode(forfeitAddress);
14020
14327
  const checkpointExitDelayOverrides = {
@@ -14163,7 +14470,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14163
14470
  inputs: params.selectedVtxos,
14164
14471
  changeAmount: BigInt(changeAmount)
14165
14472
  };
14166
- const outputAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(params.address);
14473
+ const outputAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(params.address);
14167
14474
  assertRecipientArkAddress(
14168
14475
  params.address,
14169
14476
  outputAddress,
@@ -14229,13 +14536,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14229
14536
  void this.logUngatedInputs("settle({ inputs })", params.inputs);
14230
14537
  }
14231
14538
  const offchainAddress = await this.getAddress();
14232
- const offchainPkScript = chunkZIRFXBKL_cjs.ArkAddress.decode(offchainAddress).pkScript;
14539
+ const offchainPkScript = chunk2JV4VQ7C_cjs.ArkAddress.decode(offchainAddress).pkScript;
14233
14540
  const offchainOutputScript = base.hex.encode(offchainPkScript);
14234
14541
  if (!params) {
14235
14542
  const { fees, vtxoMaxAmount } = await this.arkProvider.getInfo();
14236
14543
  const estimator = new Estimator(fees.intentFee);
14237
14544
  let amount = 0;
14238
- const exitScript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(
14545
+ const exitScript = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(
14239
14546
  base.hex.decode(this.boardingTapscript.exitScript)
14240
14547
  );
14241
14548
  const boardingTimelock = exitScript.params.timelock;
@@ -14264,7 +14571,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14264
14571
  if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
14265
14572
  break;
14266
14573
  }
14267
- const inputFee = estimator.evalOffchainInput(chunkZIRFXBKL_cjs.toOffchainInputFeeParams(vtxo));
14574
+ const inputFee = estimator.evalOffchainInput(chunk2JV4VQ7C_cjs.toOffchainInputFeeParams(vtxo));
14268
14575
  if (inputFee.satoshis >= vtxo.value) {
14269
14576
  continue;
14270
14577
  }
@@ -14311,7 +14618,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14311
14618
  let script;
14312
14619
  let arkAddress;
14313
14620
  try {
14314
- arkAddress = chunkZIRFXBKL_cjs.ArkAddress.decode(output.address);
14621
+ arkAddress = chunk2JV4VQ7C_cjs.ArkAddress.decode(output.address);
14315
14622
  } catch {
14316
14623
  arkAddress = void 0;
14317
14624
  }
@@ -14401,7 +14708,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14401
14708
  const abortController = new AbortController();
14402
14709
  let stream;
14403
14710
  let committedTxid;
14404
- const settleInputVtxos = params.inputs.filter(chunkZIRFXBKL_cjs.isVirtualCoin);
14711
+ const settleInputVtxos = params.inputs.filter(chunk2JV4VQ7C_cjs.isVirtualCoin);
14405
14712
  const contractManager = await this.getContractManager();
14406
14713
  await contractManager.assertAnnotatable(settleInputVtxos);
14407
14714
  await contractManager.assertSpendableNow?.(
@@ -14500,7 +14807,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14500
14807
  * `typeof` guard skips the arknote strings settle also accepts.
14501
14808
  *
14502
14809
  * No-ops for static / `auto` wallets (no descriptor provider — boarding
14503
- * stays on its fixed index-0 address). Best-effort and non-fatal: the
14810
+ * stays on its fixed index-0 address). Wallets on a custom
14811
+ * {@link DescriptorProvider} DO rotate here now, where they previously
14812
+ * no-opped — see the behaviour-change note on {@link
14813
+ * getNewBoardingAddress}. Best-effort and non-fatal: the
14504
14814
  * settle has already committed and its txid must be returned, so a
14505
14815
  * rotation failure is logged and swallowed rather than thrown. Funds at
14506
14816
  * the retired boarding address remain discoverable — the old `boarding`
@@ -14510,7 +14820,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14510
14820
  async maybeRotateBoardingAfterBoard(inputs) {
14511
14821
  if (!this._descriptorProvider) return;
14512
14822
  const consumedBoarding = inputs.some(
14513
- (input) => typeof input !== "string" && !chunkZIRFXBKL_cjs.isVirtualCoin(input)
14823
+ (input) => typeof input !== "string" && !chunk2JV4VQ7C_cjs.isVirtualCoin(input)
14514
14824
  );
14515
14825
  if (!consumedBoarding) return;
14516
14826
  try {
@@ -14534,7 +14844,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14534
14844
  let connectorIndex = 0;
14535
14845
  const connectorsLeaves = connectorsGraph?.leaves() || [];
14536
14846
  for (const input of inputs) {
14537
- if (!chunkZIRFXBKL_cjs.isVirtualCoin(input)) {
14847
+ if (!chunk2JV4VQ7C_cjs.isVirtualCoin(input)) {
14538
14848
  for (let i = 0; i < settlementPsbt.inputsLength; i++) {
14539
14849
  const settlementInput = settlementPsbt.getInput(i);
14540
14850
  if (!settlementInput.txid || settlementInput.index === void 0) {
@@ -14565,7 +14875,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14565
14875
  }
14566
14876
  continue;
14567
14877
  }
14568
- if (chunkZIRFXBKL_cjs.canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
14878
+ if (chunk2JV4VQ7C_cjs.canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
14569
14879
  continue;
14570
14880
  }
14571
14881
  if (connectorsLeaves.length === 0) {
@@ -14593,7 +14903,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14593
14903
  index: input.vout,
14594
14904
  witnessUtxo: {
14595
14905
  amount: BigInt(input.value),
14596
- script: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript
14906
+ script: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript
14597
14907
  },
14598
14908
  sighashType: btcSigner.SigHash.DEFAULT,
14599
14909
  tapLeafScript: [input.forfeitTapLeafScript]
@@ -14612,7 +14922,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14612
14922
  forfeitTx = await this._signerRouter.sign(forfeitTx, [
14613
14923
  {
14614
14924
  index: 0,
14615
- lookupScript: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript
14925
+ lookupScript: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript
14616
14926
  }
14617
14927
  ]);
14618
14928
  signedForfeits.push(base.base64.encode(forfeitTx.toPSBT()));
@@ -14670,7 +14980,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14670
14980
  resolveBatchExpiryPolicy(this.network, this.batchExpiryPolicy)
14671
14981
  );
14672
14982
  await this.arkProvider.confirmRegistration(intentId);
14673
- const sweepTapscript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
14983
+ const sweepTapscript = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.encode({
14674
14984
  timelock,
14675
14985
  pubkeys: [this.forfeitPubkey]
14676
14986
  }).script;
@@ -14685,10 +14995,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14685
14995
  throw new Error("Sweep tap tree root not set");
14686
14996
  }
14687
14997
  const xOnlyPublicKeys = event.cosignersPublicKeys.map(
14688
- (k) => base.hex.encode(chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
14998
+ (k) => base.hex.encode(chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
14689
14999
  );
14690
15000
  const signerPublicKey = await session.getPublicKey();
14691
- const xonlySignerPublicKey = chunkPXPPZF5K_cjs.toXOnly(signerPublicKey, "signer key");
15001
+ const xonlySignerPublicKey = chunkOIZ2V2VD_cjs.toXOnly(signerPublicKey, "signer key");
14692
15002
  if (!xOnlyPublicKeys.includes(base.hex.encode(xonlySignerPublicKey))) {
14693
15003
  return { skip: true };
14694
15004
  }
@@ -14778,9 +15088,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14778
15088
  ...existing ?? {},
14779
15089
  intentTxId,
14780
15090
  registerProof: intent.proof,
14781
- registerProofMessage: chunkZIRFXBKL_cjs.Intent.encodeMessage(intent.message),
15091
+ registerProofMessage: chunk2JV4VQ7C_cjs.Intent.encodeMessage(intent.message),
14782
15092
  deleteProof: deleteIntent.proof,
14783
- deleteProofMessage: chunkZIRFXBKL_cjs.Intent.encodeMessage(deleteIntent.message),
15093
+ deleteProofMessage: chunk2JV4VQ7C_cjs.Intent.encodeMessage(deleteIntent.message),
14784
15094
  intentVtxos: inputs.map((i) => ({
14785
15095
  txid: i.txid,
14786
15096
  vout: i.vout
@@ -14812,7 +15122,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14812
15122
  try {
14813
15123
  return await this.arkProvider.registerIntent(intent);
14814
15124
  } catch (error) {
14815
- if (error instanceof chunkZIRFXBKL_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
15125
+ if (error instanceof chunk2JV4VQ7C_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
14816
15126
  const deleteIntent = await this.makeDeleteIntentSignature(inputs);
14817
15127
  await this.arkProvider.deleteIntent(deleteIntent);
14818
15128
  return this.arkProvider.registerIntent(intent);
@@ -14828,7 +15138,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14828
15138
  expire_at: 0,
14829
15139
  cosigners_public_keys: cosignerPubKeys
14830
15140
  };
14831
- const proof = chunkZIRFXBKL_cjs.Intent.create(message, coins, outputs);
15141
+ const proof = chunk2JV4VQ7C_cjs.Intent.create(message, coins, outputs);
14832
15142
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
14833
15143
  return {
14834
15144
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -14840,7 +15150,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14840
15150
  type: "delete",
14841
15151
  expire_at: 0
14842
15152
  };
14843
- const proof = chunkZIRFXBKL_cjs.Intent.create(message, coins, []);
15153
+ const proof = chunk2JV4VQ7C_cjs.Intent.create(message, coins, []);
14844
15154
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
14845
15155
  return {
14846
15156
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -14852,7 +15162,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14852
15162
  type: "get-pending-tx",
14853
15163
  expire_at: 0
14854
15164
  };
14855
- const proof = chunkZIRFXBKL_cjs.Intent.create(message, coins, []);
15165
+ const proof = chunk2JV4VQ7C_cjs.Intent.create(message, coins, []);
14856
15166
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
14857
15167
  return {
14858
15168
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -14873,7 +15183,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14873
15183
  if (!vtxos || vtxos.length === 0) {
14874
15184
  const scriptMap = await this.getScriptMap();
14875
15185
  const allExtended = [];
14876
- const fetchedVtxos = await chunkZIRFXBKL_cjs.getAllNormalizedVtxos(this.indexerProvider, [
15186
+ const fetchedVtxos = await chunk2JV4VQ7C_cjs.getAllNormalizedVtxos(this.indexerProvider, [
14877
15187
  ...scriptMap.keys()
14878
15188
  ]);
14879
15189
  for (const vtxo of fetchedVtxos) {
@@ -14987,11 +15297,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
14987
15297
  * against the current key alone would leave it pending forever.
14988
15298
  */
14989
15299
  checkpointUnrollCandidates(info) {
14990
- const current = chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
15300
+ const current = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
14991
15301
  const candidates = [this._serverUnrollScript, current];
14992
15302
  for (const deprecated of signerSetFromInfo(info).deprecated.keys()) {
14993
15303
  candidates.push(
14994
- chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
15304
+ chunk2JV4VQ7C_cjs.CSVMultisigTapscript.encode({
14995
15305
  ...current.params,
14996
15306
  pubkeys: [base.hex.decode(deprecated)]
14997
15307
  })
@@ -15082,7 +15392,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15082
15392
  if (vtxos.length === 0) {
15083
15393
  throw new Error("No VTXOs found for this arkadeCash");
15084
15394
  }
15085
- const myPkScript = chunkZIRFXBKL_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
15395
+ const myPkScript = chunk2JV4VQ7C_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
15086
15396
  let { spendable, unclaimed } = this.classifyCashVtxos(vtxos);
15087
15397
  let swept = 0;
15088
15398
  const drainable = vtxos.filter((vtxo) => !isSubdust(vtxo, this.dustAmount));
@@ -15156,8 +15466,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15156
15466
  const spendable = [];
15157
15467
  const unclaimed = [];
15158
15468
  for (const vtxo of vtxos) {
15159
- if (chunkZIRFXBKL_cjs.hasTerminalSpend(vtxo)) {
15469
+ if (chunk2JV4VQ7C_cjs.hasTerminalSpend(vtxo)) {
15160
15470
  unclaimed.push(cashReport(vtxo, "already-spent"));
15471
+ } else if (vtxo.isUnrolled) {
15472
+ unclaimed.push(cashReport(vtxo, "exited"));
15161
15473
  } else if (isSubdust(vtxo, this.dustAmount)) {
15162
15474
  unclaimed.push(cashReport(vtxo, "subdust"));
15163
15475
  } else if (vtxo.isSwept) {
@@ -15176,7 +15488,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15176
15488
  const all = [];
15177
15489
  const seen = /* @__PURE__ */ new Set();
15178
15490
  for (let pageIndex = 0; ; pageIndex++) {
15179
- const { vtxos, page } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(this.indexerProvider, {
15491
+ const { vtxos, page } = await chunk2JV4VQ7C_cjs.getNormalizedVtxos(this.indexerProvider, {
15180
15492
  scripts,
15181
15493
  pageIndex,
15182
15494
  pageSize
@@ -15223,7 +15535,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15223
15535
  for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_INTENT) {
15224
15536
  const batch = inputs.slice(i, i + MAX_INPUTS_PER_INTENT);
15225
15537
  const message = { type: "get-pending-tx", expire_at: 0 };
15226
- const proof = chunkZIRFXBKL_cjs.Intent.create(message, batch, []);
15538
+ const proof = chunk2JV4VQ7C_cjs.Intent.create(message, batch, []);
15227
15539
  const signedProof = await identity.sign(
15228
15540
  proof,
15229
15541
  Array.from({ length: batch.length + 1 }, (_, j) => j)
@@ -15442,7 +15754,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15442
15754
  script: recipient.script,
15443
15755
  amount: BigInt(recipient.amount),
15444
15756
  // Already checked against the recipient address in `validateRecipients`.
15445
- ...recipient.tapTree ? { tapTree: chunkZIRFXBKL_cjs.TapTreeCoder.decode(recipient.tapTree) } : {}
15757
+ ...recipient.tapTree ? { tapTree: chunk2JV4VQ7C_cjs.TapTreeCoder.decode(recipient.tapTree) } : {}
15446
15758
  }));
15447
15759
  const totalBtcOutput = outputs.reduce((sum, o) => sum + Number(o.amount), 0);
15448
15760
  let changeAmount = totalBtcSelected - totalBtcOutput;
@@ -15586,10 +15898,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15586
15898
  const serverPubKey = this.arkServerPublicKey;
15587
15899
  const serverUnrollScript = this.serverUnrollScript;
15588
15900
  const arkAddress = offchainTapscript.address(this.network.hrp, serverPubKey);
15589
- const normalizedInputs = inputs.map(chunkZIRFXBKL_cjs.normalizeVtxo);
15590
- const at = now ?? await chunkZIRFXBKL_cjs.resolveTimeHeight(this.onchainProvider);
15901
+ const normalizedInputs = inputs.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
15902
+ const at = now ?? await chunk2JV4VQ7C_cjs.resolveTimeHeight(this.onchainProvider);
15591
15903
  for (const input of normalizedInputs) {
15592
- if (!chunkZIRFXBKL_cjs.canSpendOffchain(input, at)) {
15904
+ if (!chunk2JV4VQ7C_cjs.canSpendOffchain(input, at)) {
15593
15905
  throw new Error(
15594
15906
  `sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} is not cooperatively spendable`
15595
15907
  );
@@ -15659,7 +15971,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15659
15971
  );
15660
15972
  const arkTxJobs = inputs.map((input, index) => ({
15661
15973
  index,
15662
- lookupScript: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript
15974
+ lookupScript: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript
15663
15975
  }));
15664
15976
  const identity = this.identity;
15665
15977
  const signer = {
@@ -15745,14 +16057,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15745
16057
  const spentBy = checkpointIdByOutpoint.get(`${vtxo.txid}:${vtxo.vout}`);
15746
16058
  spentVtxos.push({
15747
16059
  ...spentFacts,
15748
- virtualStatus: chunkZIRFXBKL_cjs.toVirtualStatus(spentFacts),
16060
+ virtualStatus: chunk2JV4VQ7C_cjs.toVirtualStatus(spentFacts),
15749
16061
  ...spentBy ? { spentBy } : {},
15750
16062
  arkTxId: arkTxid
15751
16063
  });
15752
16064
  for (const id of vtxo.commitmentTxIds) {
15753
16065
  commitmentTxIds.add(id);
15754
16066
  }
15755
- const vtxoExpiry = chunkZIRFXBKL_cjs.toBatchExpiry(vtxo);
16067
+ const vtxoExpiry = chunk2JV4VQ7C_cjs.toBatchExpiry(vtxo);
15756
16068
  if (vtxoExpiry) {
15757
16069
  batchExpiry = Math.min(batchExpiry, vtxoExpiry);
15758
16070
  }
@@ -15765,7 +16077,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15765
16077
  isSwept: false,
15766
16078
  isPreconfirmed: true,
15767
16079
  commitmentTxIds: Array.from(commitmentTxIds),
15768
- ...chunkZIRFXBKL_cjs.parseLegacyExpiry(batchExpiry)
16080
+ ...chunk2JV4VQ7C_cjs.parseLegacyExpiry(batchExpiry)
15769
16081
  };
15770
16082
  changeVtxo = {
15771
16083
  txid: arkTxid,
@@ -15777,7 +16089,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15777
16089
  tapTree: offchainTapscript.encode(),
15778
16090
  value: Number(changeAmount),
15779
16091
  ...changeFacts,
15780
- virtualStatus: chunkZIRFXBKL_cjs.toVirtualStatus(changeFacts),
16092
+ virtualStatus: chunk2JV4VQ7C_cjs.toVirtualStatus(changeFacts),
15781
16093
  spentBy: "",
15782
16094
  status: {
15783
16095
  confirmed: false
@@ -15846,12 +16158,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15846
16158
  const spentVtxos = [];
15847
16159
  const inputArkTxIds = /* @__PURE__ */ new Set();
15848
16160
  const boardingRemovalsByAddress = /* @__PURE__ */ new Map();
15849
- const vtxoInputs = inputs.filter(chunkZIRFXBKL_cjs.isVirtualCoin);
16161
+ const vtxoInputs = inputs.filter(chunk2JV4VQ7C_cjs.isVirtualCoin);
15850
16162
  const cm = await this.getContractManager();
15851
16163
  const annotatedVtxos = await cm.annotateVtxos(vtxoInputs);
15852
16164
  const annotatedByKey = new Map(annotatedVtxos.map((v) => [`${v.txid}:${v.vout}`, v]));
15853
16165
  for (const input of inputs) {
15854
- if (chunkZIRFXBKL_cjs.isVirtualCoin(input)) {
16166
+ if (chunk2JV4VQ7C_cjs.isVirtualCoin(input)) {
15855
16167
  const outpoint = `${input.txid}:${input.vout}`;
15856
16168
  const vtxo = annotatedByKey.get(outpoint);
15857
16169
  if (!vtxo) {
@@ -15863,13 +16175,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15863
16175
  const settledFacts = { ...vtxo, isSpent: true };
15864
16176
  spentVtxos.push({
15865
16177
  ...settledFacts,
15866
- virtualStatus: chunkZIRFXBKL_cjs.toVirtualStatus(settledFacts),
16178
+ virtualStatus: chunk2JV4VQ7C_cjs.toVirtualStatus(settledFacts),
15867
16179
  settledBy: commitmentTxid
15868
16180
  });
15869
16181
  } else {
15870
16182
  let sourceAddress;
15871
16183
  try {
15872
- sourceAddress = chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
16184
+ sourceAddress = chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
15873
16185
  this.network
15874
16186
  );
15875
16187
  } catch {
@@ -15927,9 +16239,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
15927
16239
  }
15928
16240
  };
15929
16241
  function selectVirtualCoins(coins, targetAmount) {
15930
- const sortedCoins = coins.map(chunkZIRFXBKL_cjs.normalizeVtxo).sort((a, b) => {
15931
- const expiryA = chunkZIRFXBKL_cjs.toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
15932
- const expiryB = chunkZIRFXBKL_cjs.toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
16242
+ const sortedCoins = coins.map(chunk2JV4VQ7C_cjs.normalizeVtxo).sort((a, b) => {
16243
+ const expiryA = chunk2JV4VQ7C_cjs.toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
16244
+ const expiryB = chunk2JV4VQ7C_cjs.toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
15933
16245
  if (expiryA !== expiryB) {
15934
16246
  return expiryA - expiryB;
15935
16247
  }
@@ -16048,6 +16360,11 @@ var MessageBus = class {
16048
16360
  buildServicesFn;
16049
16361
  boundOnMessage = this.onMessage.bind(this);
16050
16362
  intentRepository;
16363
+ /** Pending broadcasts, drained FIFO by a single {@link drain} loop. */
16364
+ broadcastQueue = [];
16365
+ draining = false;
16366
+ /** Bumped wherever the generation owning the queued broadcasts ends. */
16367
+ broadcastEpoch = 0;
16051
16368
  /** Start the message bus and attach service-worker event listeners. */
16052
16369
  async start() {
16053
16370
  if (this.running) return;
@@ -16070,6 +16387,7 @@ var MessageBus = class {
16070
16387
  this.running = false;
16071
16388
  this.tickInProgress = false;
16072
16389
  this.initialized = false;
16390
+ this.invalidateBroadcasts();
16073
16391
  if (this.tickTimeout !== null) {
16074
16392
  self.clearTimeout(this.tickTimeout);
16075
16393
  this.tickTimeout = null;
@@ -16082,6 +16400,78 @@ var MessageBus = class {
16082
16400
  self.removeEventListener("message", this.boundOnMessage);
16083
16401
  await Promise.all(Array.from(this.handlers.values()).map((updater) => updater.stop()));
16084
16402
  }
16403
+ /** Invalidate every broadcast belonging to the outgoing generation. */
16404
+ invalidateBroadcasts() {
16405
+ this.broadcastEpoch++;
16406
+ this.broadcastQueue.length = 0;
16407
+ }
16408
+ broadcastToClients(responses) {
16409
+ this.broadcastQueue.push(...responses);
16410
+ void this.drain();
16411
+ }
16412
+ /**
16413
+ * Single fan-out loop, so pushes and tick responses keep one FIFO order.
16414
+ * A helper posting per response would race: `clients.matchAll()` gives no
16415
+ * cross-call resolution order, and it would de-batch `runTick`.
16416
+ */
16417
+ async drain() {
16418
+ if (this.draining) return;
16419
+ this.draining = true;
16420
+ try {
16421
+ while (this.broadcastQueue.length) {
16422
+ const epoch = this.broadcastEpoch;
16423
+ const batch = this.broadcastQueue.splice(0);
16424
+ if (!this.running) {
16425
+ this.logDroppedBroadcasts(batch, "bus stopped");
16426
+ return;
16427
+ }
16428
+ let clients;
16429
+ try {
16430
+ clients = await self.clients.matchAll({
16431
+ includeUncontrolled: true,
16432
+ type: "window"
16433
+ });
16434
+ } catch (err) {
16435
+ this.logDroppedBroadcasts(batch, "clients.matchAll failed", err);
16436
+ continue;
16437
+ }
16438
+ if (!this.running) {
16439
+ this.logDroppedBroadcasts(batch, "bus stopped during matchAll");
16440
+ return;
16441
+ }
16442
+ if (this.broadcastEpoch !== epoch) {
16443
+ this.logDroppedBroadcasts(batch, "re-init landed during matchAll");
16444
+ continue;
16445
+ }
16446
+ for (const message of batch) {
16447
+ for (const client of clients) {
16448
+ try {
16449
+ client.postMessage(message);
16450
+ } catch (err) {
16451
+ if (this.debug)
16452
+ console.warn(`[${message.tag}] broadcast to client failed`, err);
16453
+ }
16454
+ }
16455
+ }
16456
+ }
16457
+ } catch {
16458
+ } finally {
16459
+ this.draining = false;
16460
+ if (this.running && this.broadcastQueue.length) void this.drain();
16461
+ }
16462
+ }
16463
+ /**
16464
+ * A dropped batch has no periodic recovery to fall back on now that events
16465
+ * no longer ride the tick, so name the loss under {@link Options.debug}.
16466
+ */
16467
+ logDroppedBroadcasts(batch, reason, ...error) {
16468
+ if (!this.debug) return;
16469
+ console.warn(
16470
+ `dropping ${batch.length} broadcast(s): ${reason}`,
16471
+ batch.map((response) => response.tag),
16472
+ ...error
16473
+ );
16474
+ }
16085
16475
  scheduleNextTick() {
16086
16476
  if (!this.running) return;
16087
16477
  if (this.tickTimeout !== null) return;
@@ -16110,16 +16500,7 @@ var MessageBus = class {
16110
16500
  if (this.debug)
16111
16501
  console.log(`[${updater.messageTag}] outgoing tick response:`, response);
16112
16502
  if (response && response.length > 0) {
16113
- self.clients.matchAll({
16114
- includeUncontrolled: true,
16115
- type: "window"
16116
- }).then((clients) => {
16117
- for (const message of response) {
16118
- clients.forEach((client) => {
16119
- client.postMessage(message);
16120
- });
16121
- }
16122
- });
16503
+ this.broadcastToClients(response);
16123
16504
  }
16124
16505
  } catch (err) {
16125
16506
  if (this.debug) console.error(`[${updater.messageTag}] tick failed`, err);
@@ -16158,6 +16539,14 @@ var MessageBus = class {
16158
16539
  self.clearTimeout(this.tickTimeout);
16159
16540
  this.tickTimeout = null;
16160
16541
  }
16542
+ this.invalidateBroadcasts();
16543
+ const epoch = this.broadcastEpoch;
16544
+ const channel = {
16545
+ broadcast: (response) => {
16546
+ if (epoch !== this.broadcastEpoch) return;
16547
+ this.broadcastToClients([response]);
16548
+ }
16549
+ };
16161
16550
  if (this.initialized) {
16162
16551
  this.initialized = false;
16163
16552
  await Promise.all(
@@ -16174,9 +16563,7 @@ var MessageBus = class {
16174
16563
  try {
16175
16564
  for (const updater of this.handlers.values()) {
16176
16565
  if (this.debug) console.log(`Starting updater: ${updater.messageTag}`);
16177
- await updater.start(services, {
16178
- walletRepository: this.walletRepository
16179
- });
16566
+ await updater.start(services, { walletRepository: this.walletRepository }, channel);
16180
16567
  started.push(updater);
16181
16568
  }
16182
16569
  } catch (err) {
@@ -16189,7 +16576,7 @@ var MessageBus = class {
16189
16576
  this.initialized = true;
16190
16577
  }
16191
16578
  async buildServices(config) {
16192
- const arkProvider = new chunkZIRFXBKL_cjs.RestArkProvider(config.arkServer.url);
16579
+ const arkProvider = new chunk2JV4VQ7C_cjs.RestArkProvider(config.arkServer.url);
16193
16580
  const storage = {
16194
16581
  walletRepository: this.walletRepository,
16195
16582
  contractRepository: this.contractRepository,
@@ -16531,7 +16918,7 @@ var offboardNetworkNames = [
16531
16918
  function offboardDestinationScript(destinationAddress) {
16532
16919
  for (const networkName of offboardNetworkNames) {
16533
16920
  try {
16534
- const network = chunkZIRFXBKL_cjs.networks[networkName];
16921
+ const network = chunk2JV4VQ7C_cjs.networks[networkName];
16535
16922
  const addr = btcSigner.Address(network).decode(destinationAddress);
16536
16923
  return btcSigner.OutScript.encode(addr);
16537
16924
  } catch {
@@ -16595,7 +16982,7 @@ var Ramps = class {
16595
16982
  }
16596
16983
  amount = amount ?? totalAmount;
16597
16984
  const offchainAddress = await this.wallet.getAddress();
16598
- const offchainAddr = chunkZIRFXBKL_cjs.ArkAddress.decode(offchainAddress);
16985
+ const offchainAddr = chunk2JV4VQ7C_cjs.ArkAddress.decode(offchainAddress);
16599
16986
  const offchainScript = base.hex.encode(offchainAddr.pkScript);
16600
16987
  const outputFee = estimator.evalOffchainOutput({
16601
16988
  amount,
@@ -16655,7 +17042,7 @@ var Ramps = class {
16655
17042
  const filteredVtxos = [];
16656
17043
  let totalAmount = 0n;
16657
17044
  for (const vtxo of vtxos) {
16658
- const inputFee = estimator.evalOffchainInput(chunkZIRFXBKL_cjs.toOffchainInputFeeParams(vtxo));
17045
+ const inputFee = estimator.evalOffchainInput(chunk2JV4VQ7C_cjs.toOffchainInputFeeParams(vtxo));
16659
17046
  if (inputFee.satoshis >= vtxo.value) {
16660
17047
  continue;
16661
17048
  }
@@ -16846,6 +17233,17 @@ var WalletMessageHandler = class {
16846
17233
  incomingFundsSubscription;
16847
17234
  contractEventsSubscription;
16848
17235
  onNextTick = [];
17236
+ channel;
17237
+ // One counter per subscription field, bumped exactly where that field is
17238
+ // dropped — never where a neighbour's is. They cannot be merged:
17239
+ // `onWalletInitialized` re-subscribes incoming funds while
17240
+ // `ensureContractEventBroadcasting` deliberately keeps its subscription, so
17241
+ // a shared bump would leave the live contract-event emitter permanently
17242
+ // stale, and folding requests in would truncate an in-flight settle.
17243
+ incomingFundsEpoch = 0;
17244
+ contractEventsEpoch = 0;
17245
+ /** Per-request progress callbacks: ends with the handler, not with a re-init. */
17246
+ requestEpoch = 0;
16849
17247
  /**
16850
17248
  * Instantiate a new WalletUpdater.
16851
17249
  * Can override the default `messageTag` allowing more than one updater to run in parallel.
@@ -16856,13 +17254,20 @@ var WalletMessageHandler = class {
16856
17254
  }
16857
17255
  // lifecycle methods
16858
17256
  async start(...params) {
16859
- const [services, repositories] = params;
17257
+ const [services, repositories, channel] = params;
16860
17258
  this.readonlyWallet = services.readonlyWallet;
16861
17259
  this.wallet = services.wallet;
16862
17260
  this.arkProvider = services.arkProvider;
16863
17261
  this.walletRepository = repositories.walletRepository;
17262
+ this.channel = channel;
17263
+ this.onNextTick = [];
16864
17264
  }
16865
17265
  async stop() {
17266
+ this.requestEpoch++;
17267
+ this.incomingFundsEpoch++;
17268
+ this.contractEventsEpoch++;
17269
+ this.channel = void 0;
17270
+ this.onNextTick = [];
16866
17271
  if (this.incomingFundsSubscription) {
16867
17272
  this.incomingFundsSubscription();
16868
17273
  this.incomingFundsSubscription = void 0;
@@ -16885,8 +17290,8 @@ var WalletMessageHandler = class {
16885
17290
  this.indexerProvider = void 0;
16886
17291
  }
16887
17292
  async tick(_now) {
16888
- const results = await Promise.allSettled(this.onNextTick.map((fn) => fn()));
16889
- this.onNextTick = [];
17293
+ const pending = this.onNextTick.splice(0);
17294
+ const results = await Promise.allSettled(pending.map((fn) => fn()));
16890
17295
  return results.map((result) => {
16891
17296
  if (result.status === "fulfilled") {
16892
17297
  return result.value;
@@ -16896,8 +17301,46 @@ var WalletMessageHandler = class {
16896
17301
  }
16897
17302
  }).filter((response) => response !== null);
16898
17303
  }
16899
- scheduleForNextTick(callback) {
16900
- this.onNextTick.push(callback);
17304
+ epochOf(scope) {
17305
+ switch (scope) {
17306
+ case "incomingFunds":
17307
+ return this.incomingFundsEpoch;
17308
+ case "contractEvents":
17309
+ return this.contractEventsEpoch;
17310
+ case "request":
17311
+ return this.requestEpoch;
17312
+ default: {
17313
+ const _exhaustive = scope;
17314
+ throw new Error(`Unknown scope: ${_exhaustive}`);
17315
+ }
17316
+ }
17317
+ }
17318
+ newGeneration(scope) {
17319
+ const born = this.epochOf(scope);
17320
+ const stale = () => born !== this.epochOf(scope);
17321
+ return {
17322
+ get stale() {
17323
+ return stale();
17324
+ }
17325
+ };
17326
+ }
17327
+ /**
17328
+ * A handle rather than a `broadcast(response, epoch)` call, because it can
17329
+ * only be written where the closure it guards is created — an epoch passed
17330
+ * at the call site reads identically whether it guards anything or not.
17331
+ */
17332
+ newEmitter(scope) {
17333
+ const gen = this.newGeneration(scope);
17334
+ return {
17335
+ get stale() {
17336
+ return gen.stale;
17337
+ },
17338
+ emit: (response) => {
17339
+ if (!response || gen.stale) return;
17340
+ if (this.channel) return this.channel.broadcast(response);
17341
+ this.onNextTick.push(() => response);
17342
+ }
17343
+ };
16901
17344
  }
16902
17345
  requireWallet() {
16903
17346
  if (!this.wallet) {
@@ -16926,6 +17369,7 @@ var WalletMessageHandler = class {
16926
17369
  }
16927
17370
  async handleMessage(message) {
16928
17371
  const id = message.id;
17372
+ const emitter = this.newEmitter("request");
16929
17373
  if (message.type === "INIT_WALLET") {
16930
17374
  await this.handleInitWallet(message);
16931
17375
  return this.tagged({
@@ -17194,6 +17638,18 @@ var WalletMessageHandler = class {
17194
17638
  payload: { descriptor }
17195
17639
  });
17196
17640
  }
17641
+ case "GET_NEW_ADDRESSES": {
17642
+ const wallet = this.wallet;
17643
+ if (!wallet) throw new WalletNotInitializedError();
17644
+ const addresses = await wallet.getNewAddresses(
17645
+ message.payload
17646
+ );
17647
+ return this.tagged({
17648
+ id,
17649
+ type: "NEW_ADDRESSES",
17650
+ payload: { addresses }
17651
+ });
17652
+ }
17197
17653
  case "GET_USED_SIGNING_DESCRIPTORS": {
17198
17654
  const wallet = this.wallet;
17199
17655
  const descriptors = isHDWalletCapable(wallet) ? await wallet.getUsedSigningDescriptors(
@@ -17284,8 +17740,8 @@ var WalletMessageHandler = class {
17284
17740
  const wallet = this.requireWallet();
17285
17741
  const vtxoManager = await wallet.getVtxoManager();
17286
17742
  const txid = await vtxoManager.recoverVtxos((e) => {
17287
- this.scheduleForNextTick(
17288
- () => this.tagged({
17743
+ emitter.emit(
17744
+ this.tagged({
17289
17745
  id,
17290
17746
  type: "RECOVER_VTXOS_EVENT",
17291
17747
  payload: e
@@ -17329,8 +17785,8 @@ var WalletMessageHandler = class {
17329
17785
  const wallet = this.requireWallet();
17330
17786
  const vtxoManager = await wallet.getVtxoManager();
17331
17787
  const txid = await vtxoManager.renewVtxos((e) => {
17332
- this.scheduleForNextTick(
17333
- () => this.tagged({
17788
+ emitter.emit(
17789
+ this.tagged({
17334
17790
  id,
17335
17791
  type: "RENEW_VTXOS_EVENT",
17336
17792
  payload: e
@@ -17368,8 +17824,8 @@ var WalletMessageHandler = class {
17368
17824
  const vtxoManager = await wallet.getVtxoManager();
17369
17825
  const report = await vtxoManager.migrateDeprecatedSignerVtxos({
17370
17826
  eventCallback: (e) => {
17371
- this.scheduleForNextTick(
17372
- () => this.tagged({
17827
+ emitter.emit(
17828
+ this.tagged({
17373
17829
  id,
17374
17830
  type: "MIGRATE_DEPRECATED_SIGNER_VTXOS_EVENT",
17375
17831
  payload: e
@@ -17422,7 +17878,7 @@ var WalletMessageHandler = class {
17422
17878
  // Wallet methods
17423
17879
  async handleInitWallet({ payload }) {
17424
17880
  const { arkServerUrl } = payload;
17425
- this.indexerProvider = new chunk3S3JZUEN_cjs.RestIndexerProvider(arkServerUrl);
17881
+ this.indexerProvider = new chunkCO3KKSWM_cjs.RestIndexerProvider(arkServerUrl);
17426
17882
  await this.onWalletInitialized();
17427
17883
  }
17428
17884
  /**
@@ -17472,6 +17928,7 @@ var WalletMessageHandler = class {
17472
17928
  intentLocked: offchain.intentLocked,
17473
17929
  recoverable: offchain.recoverable,
17474
17930
  pendingRecovery: offchain.pendingRecovery,
17931
+ unrolled: offchain.unrolled,
17475
17932
  total: totalBoarding + offchain.total,
17476
17933
  assets: offchain.assets,
17477
17934
  availableAssets: offchain.availableAssets
@@ -17482,11 +17939,15 @@ var WalletMessageHandler = class {
17482
17939
  return this.readonlyWallet.getBoardingUtxos();
17483
17940
  }
17484
17941
  async onWalletInitialized() {
17485
- if (!this.readonlyWallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
17942
+ const wallet = this.readonlyWallet;
17943
+ if (!wallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
17486
17944
  return;
17487
17945
  }
17946
+ const init = this.newGeneration("incomingFunds");
17488
17947
  await this.ensureContractEventBroadcasting();
17948
+ if (init.stale) return;
17489
17949
  await this.refreshCachedData();
17950
+ if (init.stale) return;
17490
17951
  if (this.wallet) {
17491
17952
  try {
17492
17953
  const vtxos = await this.getVtxosFromRepo();
@@ -17499,72 +17960,81 @@ var WalletMessageHandler = class {
17499
17960
  } catch (error) {
17500
17961
  console.error("Error recovering pending transactions:", error);
17501
17962
  }
17963
+ if (init.stale) return;
17502
17964
  }
17503
17965
  if (this.incomingFundsSubscription) this.incomingFundsSubscription();
17504
- const address = await this.readonlyWallet.getAddress();
17505
- this.incomingFundsSubscription = await this.readonlyWallet.notifyIncomingFunds(
17506
- async (funds) => {
17507
- if (funds.type === "vtxo") {
17508
- const { newVtxos, spentVtxos } = funds;
17509
- if (newVtxos.length + spentVtxos.length === 0) return;
17510
- const byScript = /* @__PURE__ */ new Map();
17511
- for (const v of [...newVtxos, ...spentVtxos]) {
17512
- if (!v.script) {
17513
- console.warn(
17514
- `WalletMessageHandler.notifyIncomingFunds: dropping VTXO without script ${v.txid}:${v.vout}`
17515
- );
17516
- continue;
17517
- }
17518
- const arr = byScript.get(v.script) ?? [];
17519
- arr.push(v);
17520
- byScript.set(v.script, arr);
17521
- }
17522
- let walletScript;
17523
- try {
17524
- walletScript = scriptFromArkAddress(address);
17525
- } catch {
17526
- walletScript = void 0;
17527
- }
17528
- const cm = await this.readonlyWallet.getContractManager();
17529
- const contracts = await cm.getContracts();
17530
- const addrByScript = new Map(contracts.map((c) => [c.script, c.address]));
17531
- for (const [script, vtxos] of byScript) {
17532
- const filtered = warnAndFilterVtxosForScript(
17533
- vtxos,
17534
- script,
17535
- "WalletMessageHandler.notifyIncomingFunds"
17966
+ this.incomingFundsSubscription = void 0;
17967
+ this.incomingFundsEpoch++;
17968
+ const emitter = this.newEmitter("incomingFunds");
17969
+ const address = await wallet.getAddress();
17970
+ const unsubscribe = await wallet.notifyIncomingFunds(async (funds) => {
17971
+ if (emitter.stale) return;
17972
+ if (funds.type === "vtxo") {
17973
+ const { newVtxos, spentVtxos } = funds;
17974
+ if (newVtxos.length + spentVtxos.length === 0) return;
17975
+ const byScript = /* @__PURE__ */ new Map();
17976
+ for (const v of [...newVtxos, ...spentVtxos]) {
17977
+ if (!v.script) {
17978
+ console.warn(
17979
+ `WalletMessageHandler.notifyIncomingFunds: dropping VTXO without script ${v.txid}:${v.vout}`
17536
17980
  );
17537
- if (filtered.length === 0) continue;
17538
- const targetAddress = script === walletScript ? address : addrByScript.get(script);
17539
- if (!targetAddress) continue;
17540
- if (this.walletRepository) {
17541
- await saveVtxosForContract(
17542
- this.walletRepository,
17543
- { script, address: targetAddress },
17544
- filtered
17545
- );
17546
- }
17981
+ continue;
17547
17982
  }
17548
- this.scheduleForNextTick(
17549
- () => this.tagged({
17550
- type: "VTXO_UPDATE",
17551
- broadcast: true,
17552
- payload: { newVtxos, spentVtxos }
17553
- })
17554
- );
17983
+ const arr = byScript.get(v.script) ?? [];
17984
+ arr.push(v);
17985
+ byScript.set(v.script, arr);
17555
17986
  }
17556
- if (funds.type === "utxo") {
17557
- const utxos = await this.readonlyWallet.getBoardingUtxos();
17558
- this.scheduleForNextTick(
17559
- () => this.tagged({
17560
- type: "UTXO_UPDATE",
17561
- broadcast: true,
17562
- payload: { coins: utxos }
17563
- })
17987
+ let walletScript;
17988
+ try {
17989
+ walletScript = scriptFromArkAddress(address);
17990
+ } catch {
17991
+ walletScript = void 0;
17992
+ }
17993
+ const cm = await wallet.getContractManager();
17994
+ if (emitter.stale) return;
17995
+ const contracts = await cm.getContracts();
17996
+ if (emitter.stale) return;
17997
+ const addrByScript = new Map(contracts.map((c) => [c.script, c.address]));
17998
+ for (const [script, vtxos] of byScript) {
17999
+ const filtered = warnAndFilterVtxosForScript(
18000
+ vtxos,
18001
+ script,
18002
+ "WalletMessageHandler.notifyIncomingFunds"
17564
18003
  );
18004
+ if (filtered.length === 0) continue;
18005
+ const targetAddress = script === walletScript ? address : addrByScript.get(script);
18006
+ if (!targetAddress) continue;
18007
+ if (this.walletRepository) {
18008
+ if (emitter.stale) return;
18009
+ await saveVtxosForContract(
18010
+ this.walletRepository,
18011
+ { script, address: targetAddress },
18012
+ filtered
18013
+ );
18014
+ }
17565
18015
  }
18016
+ emitter.emit(
18017
+ this.tagged({
18018
+ type: "VTXO_UPDATE",
18019
+ broadcast: true,
18020
+ payload: { newVtxos, spentVtxos }
18021
+ })
18022
+ );
17566
18023
  }
17567
- );
18024
+ if (funds.type === "utxo") {
18025
+ if (emitter.stale) return;
18026
+ const utxos = await wallet.getBoardingUtxos();
18027
+ emitter.emit(
18028
+ this.tagged({
18029
+ type: "UTXO_UPDATE",
18030
+ broadcast: true,
18031
+ payload: { coins: utxos }
18032
+ })
18033
+ );
18034
+ }
18035
+ });
18036
+ if (emitter.stale) return unsubscribe();
18037
+ this.incomingFundsSubscription = unsubscribe;
17568
18038
  if (this.wallet) {
17569
18039
  try {
17570
18040
  await this.wallet.getVtxoManager();
@@ -17609,10 +18079,11 @@ var WalletMessageHandler = class {
17609
18079
  await this.refreshCachedData();
17610
18080
  }
17611
18081
  async handleSettle(message) {
18082
+ const emitter = this.newEmitter("request");
17612
18083
  const wallet = this.requireWallet();
17613
18084
  const txid = await wallet.settle(message.payload.params, (e) => {
17614
- this.scheduleForNextTick(
17615
- () => this.tagged({
18085
+ emitter.emit(
18086
+ this.tagged({
17616
18087
  id: message.id,
17617
18088
  type: "SETTLE_EVENT",
17618
18089
  payload: e
@@ -17689,30 +18160,39 @@ var WalletMessageHandler = class {
17689
18160
  throw new WalletNotInitializedError();
17690
18161
  }
17691
18162
  const allVtxos = await this.getVtxosFromRepo();
17692
- const vtxos = allVtxos.filter((v) => !chunkZIRFXBKL_cjs.hasTerminalSpend(v));
17693
18163
  const dustAmount = this.readonlyWallet.dustAmount;
18164
+ const withUnrolled = message.payload.filter?.withUnrolled ?? false;
17694
18165
  const includeRecoverable = message.payload.filter?.withRecoverable ?? false;
17695
- const filteredVtxos = includeRecoverable ? vtxos : vtxos.filter((v) => {
18166
+ return allVtxos.filter((v) => {
18167
+ if (v.isUnrolled) {
18168
+ return withUnrolled;
18169
+ }
18170
+ if (chunk2JV4VQ7C_cjs.hasTerminalSpend(v)) {
18171
+ return false;
18172
+ }
18173
+ if (includeRecoverable) {
18174
+ return true;
18175
+ }
17696
18176
  if (dustAmount != null && isSubdust(v, dustAmount)) {
17697
18177
  return false;
17698
18178
  }
17699
- if (chunkZIRFXBKL_cjs.isRecoverable(v)) {
18179
+ if (chunk2JV4VQ7C_cjs.isRecoverable(v)) {
17700
18180
  return false;
17701
18181
  }
17702
- if (chunkZIRFXBKL_cjs.isExpired(v)) {
18182
+ if (chunk2JV4VQ7C_cjs.isExpired(v)) {
17703
18183
  return false;
17704
18184
  }
17705
18185
  return true;
17706
18186
  });
17707
- if (!message.payload.filter?.withUnrolled) {
17708
- return filteredVtxos;
17709
- }
17710
- return filteredVtxos.concat(allVtxos.filter((v) => chunkZIRFXBKL_cjs.hasTerminalSpend(v) && v.isUnrolled));
17711
18187
  }
17712
18188
  /** Tear down handler subscriptions, then delegate the full wipe to the wallet. */
17713
18189
  async clear() {
17714
18190
  const wallet = this.wallet ?? this.readonlyWallet;
17715
18191
  if (!wallet) return;
18192
+ this.requestEpoch++;
18193
+ this.incomingFundsEpoch++;
18194
+ this.contractEventsEpoch++;
18195
+ this.onNextTick = [];
17716
18196
  if (this.incomingFundsSubscription) {
17717
18197
  this.incomingFundsSubscription();
17718
18198
  this.incomingFundsSubscription = void 0;
@@ -17797,17 +18277,21 @@ var WalletMessageHandler = class {
17797
18277
  if (!this.readonlyWallet) return null;
17798
18278
  const { boardingTxs, commitmentsToIgnore } = await this.readonlyWallet.getBoardingTxs();
17799
18279
  const indexerProvider = this.indexerProvider;
17800
- const resolveTxCreatedAt = indexerProvider ? (txids) => chunkZIRFXBKL_cjs.fetchVtxoCreatedAtByTxid(indexerProvider, txids) : void 0;
18280
+ const resolveTxCreatedAt = indexerProvider ? (txids) => chunk2JV4VQ7C_cjs.fetchVtxoCreatedAtByTxid(indexerProvider, txids) : void 0;
17801
18281
  return buildTransactionHistory(vtxos, boardingTxs, commitmentsToIgnore, resolveTxCreatedAt);
17802
18282
  }
17803
18283
  async ensureContractEventBroadcasting() {
17804
- if (!this.readonlyWallet) return;
18284
+ const wallet = this.readonlyWallet;
18285
+ if (!wallet) return;
17805
18286
  if (this.contractEventsSubscription) return;
18287
+ const gen = this.newGeneration("contractEvents");
17806
18288
  try {
17807
- const manager = await this.readonlyWallet.getContractManager();
18289
+ const manager = await wallet.getContractManager();
18290
+ if (gen.stale || this.contractEventsSubscription) return;
18291
+ const emitter = this.newEmitter("contractEvents");
17808
18292
  this.contractEventsSubscription = manager.onContractEvent((event) => {
17809
- this.scheduleForNextTick(
17810
- () => this.tagged({
18293
+ emitter.emit(
18294
+ this.tagged({
17811
18295
  type: "CONTRACT_EVENT",
17812
18296
  broadcast: true,
17813
18297
  payload: { event }
@@ -17838,6 +18322,9 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
17838
18322
  // Allocation is a local repository write plus a fire-and-forget band
17839
18323
  // slide — no indexer round trip on the request path.
17840
18324
  GET_NEXT_SIGNING_DESCRIPTOR: 1e4,
18325
+ // Same shape as the bare allocation above, plus one contract write per
18326
+ // requested type — still local, still no indexer round trip.
18327
+ GET_NEW_ADDRESSES: 1e4,
17841
18328
  GET_USED_SIGNING_DESCRIPTORS: 2e4,
17842
18329
  ADVANCE_SIGNING_DESCRIPTOR_WATERMARK: 1e4,
17843
18330
  // Medium reads — may involve indexer queries
@@ -18486,7 +18973,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
18486
18973
  };
18487
18974
  try {
18488
18975
  const response = await this.sendMessage(message);
18489
- return response.payload.vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo);
18976
+ return response.payload.vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
18490
18977
  } catch (error) {
18491
18978
  throw new Error(`Failed to get vtxos: ${error}`);
18492
18979
  }
@@ -18511,7 +18998,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
18511
18998
  };
18512
18999
  try {
18513
19000
  const response = await this.sendMessage(message);
18514
- return response.payload.vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo);
19001
+ return response.payload.vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
18515
19002
  } catch (error) {
18516
19003
  throw new Error(`Failed to get spendable vtxos: ${error}`);
18517
19004
  }
@@ -18642,7 +19129,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
18642
19129
  };
18643
19130
  try {
18644
19131
  const response = await sendContractMessage(message);
18645
- return response.payload.vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo);
19132
+ return response.payload.vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
18646
19133
  } catch (e) {
18647
19134
  throw new Error("Failed to annotate vtxos");
18648
19135
  }
@@ -18983,6 +19470,35 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
18983
19470
  throw new Error(`Failed to allocate next signing descriptor: ${error}`);
18984
19471
  }
18985
19472
  }
19473
+ /**
19474
+ * @see Wallet.getNewAddresses
19475
+ *
19476
+ * Proxied as a single request rather than rebuilt page-side out of
19477
+ * {@link getNextSigningDescriptor}: the worker owns the HD watermark *and*
19478
+ * the contract repository, so splitting the operation would let a page burn
19479
+ * an index and then fail to register the script, leaving an address nothing
19480
+ * watches.
19481
+ *
19482
+ * Note the error shape — `WalletCannotAllocateAddressError` is thrown
19483
+ * worker-side and cannot cross the message boundary as a class, so a
19484
+ * `forceNew` refusal surfaces here as a plain `Error` carrying its message
19485
+ * (and the worker-side error as `cause`). Callers that must branch on the
19486
+ * refusal match the message rather than `instanceof`.
19487
+ */
19488
+ async getNewAddresses(opts) {
19489
+ const message = {
19490
+ id: getRandomId(),
19491
+ tag: this.messageTag,
19492
+ type: "GET_NEW_ADDRESSES",
19493
+ ...opts ? { payload: opts } : {}
19494
+ };
19495
+ try {
19496
+ const response = await this.sendMessage(message);
19497
+ return response.payload.addresses;
19498
+ } catch (error) {
19499
+ throw new Error(`Failed to allocate new addresses: ${error}`, { cause: error });
19500
+ }
19501
+ }
18986
19502
  /** @see HDWalletCapable.getUsedSigningDescriptors */
18987
19503
  async getUsedSigningDescriptors(opts) {
18988
19504
  const message = {
@@ -19214,7 +19730,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
19214
19730
  };
19215
19731
  try {
19216
19732
  const response = await wallet.sendMessage(message);
19217
- return response.payload.vtxos.map(chunkZIRFXBKL_cjs.normalizeVtxo);
19733
+ return response.payload.vtxos.map(chunk2JV4VQ7C_cjs.normalizeVtxo);
19218
19734
  } catch (e) {
19219
19735
  throw new Error(`Failed to get expiring vtxos: ${e}`);
19220
19736
  }
@@ -19326,12 +19842,12 @@ var OnchainWallet = class _OnchainWallet {
19326
19842
  * @returns Configured onchain wallet
19327
19843
  * @throws Error if the configured identity cannot produce a valid x-only public key
19328
19844
  */
19329
- static async create(identity, networkName = chunkZIRFXBKL_cjs.DEFAULT_NETWORK_NAME, provider) {
19845
+ static async create(identity, networkName = chunk2JV4VQ7C_cjs.DEFAULT_NETWORK_NAME, provider) {
19330
19846
  const pubkey = await identity.xOnlyPublicKey();
19331
19847
  if (!pubkey) {
19332
19848
  throw new Error("Invalid configured public key");
19333
19849
  }
19334
- const network = chunkZIRFXBKL_cjs.getNetwork(networkName);
19850
+ const network = chunk2JV4VQ7C_cjs.getNetwork(networkName);
19335
19851
  const onchainProvider = provider || new EsploraProvider(ESPLORA_URL[networkName]);
19336
19852
  const onchainP2TR = btcSigner.p2tr(pubkey, void 0, network);
19337
19853
  return new _OnchainWallet(identity, network, onchainP2TR, onchainProvider);
@@ -19437,7 +19953,7 @@ var OnchainWallet = class _OnchainWallet {
19437
19953
  if (!inputs) {
19438
19954
  throw new Error("Fee estimation failed");
19439
19955
  }
19440
- let tx = new chunkZIRFXBKL_cjs.Transaction();
19956
+ let tx = new chunk2JV4VQ7C_cjs.Transaction();
19441
19957
  for (const input of inputs) {
19442
19958
  tx.addInput({
19443
19959
  txid: input.txid,
@@ -19495,7 +20011,7 @@ var OnchainWallet = class _OnchainWallet {
19495
20011
  * @throws If the parent has no anchor, or funding cannot be selected/signed
19496
20012
  */
19497
20013
  async bumpAnchor(parentHex, feeRate) {
19498
- const parent = chunkZIRFXBKL_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
20014
+ const parent = chunk2JV4VQ7C_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
19499
20015
  const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
19500
20016
  const child = await this.buildBumpPackage(parent, feeRate, coins);
19501
20017
  return [parent.hex, child.hex];
@@ -19949,6 +20465,10 @@ var ElectrumOnchainProvider = class {
19949
20465
  }
19950
20466
  throw new Error("Only 1 or 1P1C package can be broadcast");
19951
20467
  }
20468
+ async getRawTransaction(txid) {
20469
+ const [tx] = await this.chain.fetchTransactions([txid]);
20470
+ return base.hex.decode(tx.hex);
20471
+ }
19952
20472
  async getTxOutspends(txid) {
19953
20473
  const [txResult] = await this.chain.fetchTransactions([txid]);
19954
20474
  const tx = btcSigner.Transaction.fromRaw(base.hex.decode(txResult.hex), {
@@ -20254,13 +20774,190 @@ function childTxidFromHex(txHex) {
20254
20774
  });
20255
20775
  return tx.id;
20256
20776
  }
20777
+
20778
+ // src/providers/cachingArk.ts
20779
+ var DEFAULT_TTL_MS = 6e4;
20780
+ var CachingArkProvider = class {
20781
+ constructor(inner, ttlMs = DEFAULT_TTL_MS) {
20782
+ this.inner = inner;
20783
+ this.ttlMs = ttlMs;
20784
+ this.unsubscribe = inner.onServerInfoChanged?.((info) => {
20785
+ this.cached = info;
20786
+ this.expiresAt = Date.now() + this.ttlMs;
20787
+ this.generation++;
20788
+ }) ?? (() => {
20789
+ });
20790
+ }
20791
+ inner;
20792
+ ttlMs;
20793
+ cached;
20794
+ expiresAt = 0;
20795
+ inflight;
20796
+ /** Bumped on every event-driven cache write; see {@link getInfo}. */
20797
+ generation = 0;
20798
+ unsubscribe;
20799
+ /** Releases the inner provider's server-info subscription. */
20800
+ dispose() {
20801
+ this.unsubscribe();
20802
+ }
20803
+ get serverUrl() {
20804
+ const url = this.inner.serverUrl;
20805
+ return typeof url === "string" ? url : void 0;
20806
+ }
20807
+ async getInfo() {
20808
+ if (this.cached && Date.now() < this.expiresAt) return this.cached;
20809
+ if (!this.inflight) {
20810
+ const generation = this.generation;
20811
+ this.inflight = this.inner.getInfo().then((info) => {
20812
+ if (this.generation !== generation) return this.cached ?? info;
20813
+ this.cached = info;
20814
+ this.expiresAt = Date.now() + this.ttlMs;
20815
+ return info;
20816
+ }).finally(() => {
20817
+ this.inflight = void 0;
20818
+ });
20819
+ }
20820
+ return this.inflight;
20821
+ }
20822
+ submitTx(signedArkTx, checkpointTxs) {
20823
+ return this.inner.submitTx(signedArkTx, checkpointTxs);
20824
+ }
20825
+ finalizeTx(arkTxid, finalCheckpointTxs) {
20826
+ return this.inner.finalizeTx(arkTxid, finalCheckpointTxs);
20827
+ }
20828
+ registerIntent(intent) {
20829
+ return this.inner.registerIntent(intent);
20830
+ }
20831
+ deleteIntent(intent) {
20832
+ return this.inner.deleteIntent(intent);
20833
+ }
20834
+ confirmRegistration(intentId) {
20835
+ return this.inner.confirmRegistration(intentId);
20836
+ }
20837
+ submitTreeNonces(batchId, pubkey, nonces) {
20838
+ return this.inner.submitTreeNonces(batchId, pubkey, nonces);
20839
+ }
20840
+ submitTreeSignatures(batchId, pubkey, signatures) {
20841
+ return this.inner.submitTreeSignatures(batchId, pubkey, signatures);
20842
+ }
20843
+ submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx) {
20844
+ return this.inner.submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx);
20845
+ }
20846
+ getEventStream(signal, topics) {
20847
+ return this.inner.getEventStream(signal, topics);
20848
+ }
20849
+ getTransactionsStream(signal) {
20850
+ return this.inner.getTransactionsStream(signal);
20851
+ }
20852
+ getPendingTxs(intent) {
20853
+ return this.inner.getPendingTxs(intent);
20854
+ }
20855
+ onServerInfoChanged(listener) {
20856
+ return this.inner.onServerInfoChanged?.(listener) ?? (() => {
20857
+ });
20858
+ }
20859
+ };
20860
+ var PrevTxUnavailableError = class extends Error {
20861
+ constructor(message, txids = []) {
20862
+ super(message);
20863
+ this.txids = txids;
20864
+ this.name = "PrevTxUnavailableError";
20865
+ }
20866
+ txids;
20867
+ };
20868
+ async function resolvePrevTxs(txids, source, onchain) {
20869
+ const resolved = /* @__PURE__ */ new Map();
20870
+ const wanted = [...new Set(txids)];
20871
+ if (wanted.length === 0) return resolved;
20872
+ try {
20873
+ const { txs } = await source.getVirtualTxs(wanted);
20874
+ for (const psbt of txs) {
20875
+ const tx = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbt));
20876
+ resolved.set(tx.id, tx.toBytes());
20877
+ }
20878
+ } catch (err) {
20879
+ if (!onchain) throw err;
20880
+ }
20881
+ let missing = wanted.filter((txid) => !resolved.has(txid));
20882
+ if (missing.length > 0 && onchain) {
20883
+ const raw = await Promise.all(
20884
+ missing.map(async (txid) => {
20885
+ try {
20886
+ return await onchain.getRawTransaction(txid);
20887
+ } catch {
20888
+ return void 0;
20889
+ }
20890
+ })
20891
+ );
20892
+ for (const [i, bytes] of raw.entries()) {
20893
+ if (bytes) resolved.set(missing[i], bytes);
20894
+ }
20895
+ missing = missing.filter((txid) => !resolved.has(txid));
20896
+ }
20897
+ if (missing.length > 0) {
20898
+ throw new PrevTxUnavailableError(
20899
+ `cannot resolve the previous transaction of ${missing.join(", ")}` + (onchain ? "" : " (no onchain source configured)"),
20900
+ missing
20901
+ );
20902
+ }
20903
+ return resolved;
20904
+ }
20905
+ async function attachPrevArkTxs(tx, txids, source, onchain) {
20906
+ const pending = [];
20907
+ for (let i = 0; i < tx.inputsLength; i++) {
20908
+ if (chunk2JV4VQ7C_cjs.getArkPsbtFields(tx, i, chunk2JV4VQ7C_cjs.PrevArkTxField).length === 0) pending.push(i);
20909
+ }
20910
+ if (pending.length === 0) return;
20911
+ const resolved = await resolvePrevTxs(
20912
+ pending.map((i) => txidAt(txids, i)),
20913
+ source,
20914
+ onchain
20915
+ );
20916
+ for (const i of pending) {
20917
+ chunk2JV4VQ7C_cjs.setArkPsbtField(tx, i, chunk2JV4VQ7C_cjs.PrevArkTxField, resolved.get(txidAt(txids, i)));
20918
+ }
20919
+ }
20920
+ async function attachPrevoutTxs(tx, source) {
20921
+ const pending = [];
20922
+ for (let i = 0; i < tx.inputsLength; i++) {
20923
+ if (chunk2JV4VQ7C_cjs.getArkPsbtFields(tx, i, chunk2JV4VQ7C_cjs.PrevoutTxField).length > 0) continue;
20924
+ const input = tx.getInput(i);
20925
+ if (!input?.txid) throw new PrevTxUnavailableError(`input ${i} has no outpoint`);
20926
+ pending.push({ index: i, txid: base.hex.encode(input.txid) });
20927
+ }
20928
+ if (pending.length === 0) return;
20929
+ const resolved = /* @__PURE__ */ new Map();
20930
+ for (const txid of new Set(pending.map((p) => p.txid))) {
20931
+ resolved.set(txid, await source.getRawTransaction(txid));
20932
+ }
20933
+ for (const { index, txid } of pending) {
20934
+ chunk2JV4VQ7C_cjs.setArkPsbtField(tx, index, chunk2JV4VQ7C_cjs.PrevoutTxField, resolved.get(txid));
20935
+ }
20936
+ }
20937
+ async function withPrevTxs(coins, source, onchain) {
20938
+ const pending = coins.filter((c) => !c.prevTx);
20939
+ if (pending.length === 0) return coins;
20940
+ const resolved = await resolvePrevTxs(
20941
+ pending.map((c) => c.txid),
20942
+ source,
20943
+ onchain
20944
+ );
20945
+ return coins.map((c) => c.prevTx ? c : { ...c, prevTx: resolved.get(c.txid) });
20946
+ }
20947
+ function txidAt(txids, index) {
20948
+ const txid = txids[index];
20949
+ if (txid === void 0) {
20950
+ throw new PrevTxUnavailableError(`no source txid supplied for input ${index}`);
20951
+ }
20952
+ return txid;
20953
+ }
20257
20954
  var TAG_BIP322 = "BIP0322-signed-message";
20258
20955
  exports.BIP322 = void 0;
20259
20956
  ((BIP3222) => {
20260
20957
  async function sign2(message, identity, network) {
20261
20958
  const xOnlyPubKey = await identity.xOnlyPublicKey();
20262
20959
  const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
20263
- const toSpend = chunkZIRFXBKL_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
20960
+ const toSpend = chunk2JV4VQ7C_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
20264
20961
  const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
20265
20962
  const signed = await identity.sign(toSign, [0]);
20266
20963
  signed.finalizeIdx(0);
@@ -20318,7 +21015,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
20318
21015
  if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
20319
21016
  return false;
20320
21017
  }
20321
- const toSpend = chunkZIRFXBKL_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
21018
+ const toSpend = chunk2JV4VQ7C_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
20322
21019
  const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
20323
21020
  const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
20324
21021
  const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
@@ -20339,7 +21036,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
20339
21036
  }
20340
21037
  const sighashType = sigWithHash[sigWithHash.length - 1];
20341
21038
  const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
20342
- const toSpend = chunkZIRFXBKL_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
21039
+ const toSpend = chunk2JV4VQ7C_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
20343
21040
  const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
20344
21041
  const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
20345
21042
  const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
@@ -20392,7 +21089,7 @@ function encodeCompactSize(n) {
20392
21089
  return buf;
20393
21090
  }
20394
21091
  function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
20395
- const tx = new chunkZIRFXBKL_cjs.Transaction({ version: 0 });
21092
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({ version: 0 });
20396
21093
  tx.addInput({
20397
21094
  txid: toSpend.id,
20398
21095
  index: 0,
@@ -20406,12 +21103,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
20406
21103
  });
20407
21104
  tx.addOutput({
20408
21105
  amount: 0n,
20409
- script: chunkZIRFXBKL_cjs.OP_RETURN_EMPTY_PKSCRIPT
21106
+ script: chunk2JV4VQ7C_cjs.OP_RETURN_EMPTY_PKSCRIPT
20410
21107
  });
20411
21108
  return tx;
20412
21109
  }
20413
21110
  function craftBIP322ToSignSimple(toSpend, pkScript) {
20414
- const tx = new chunkZIRFXBKL_cjs.Transaction({ version: 0 });
21111
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({ version: 0 });
20415
21112
  tx.addInput({
20416
21113
  txid: toSpend.id,
20417
21114
  index: 0,
@@ -20423,7 +21120,7 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
20423
21120
  });
20424
21121
  tx.addOutput({
20425
21122
  amount: 0n,
20426
- script: chunkZIRFXBKL_cjs.OP_RETURN_EMPTY_PKSCRIPT
21123
+ script: chunk2JV4VQ7C_cjs.OP_RETURN_EMPTY_PKSCRIPT
20427
21124
  });
20428
21125
  return tx;
20429
21126
  }
@@ -20554,7 +21251,7 @@ var RestEmulatorProvider = class {
20554
21251
  }
20555
21252
  };
20556
21253
  function finalizeVirtualTx(type, psbtBase64) {
20557
- const tx = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
21254
+ const tx = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
20558
21255
  if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
20559
21256
  const input = tx.getInput(0);
20560
21257
  if (!input) {
@@ -20581,14 +21278,14 @@ var ExitPathError = class extends Error {
20581
21278
  reason;
20582
21279
  };
20583
21280
  function delayWeight(sequence) {
20584
- const t = chunkZIRFXBKL_cjs.sequenceToTimelock(sequence);
21281
+ const t = chunk2JV4VQ7C_cjs.sequenceToTimelock(sequence);
20585
21282
  return t.type === "blocks" ? Number(t.value) : Number(t.value) / 600;
20586
21283
  }
20587
21284
  async function resolveUnilateralPath(params) {
20588
21285
  const { vtxo, scriptHex, contractRepository } = params;
20589
21286
  const contract = contractRepository ? (await contractRepository.getContracts({ script: scriptHex }))[0] : void 0;
20590
21287
  if (contract) {
20591
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
21288
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
20592
21289
  if (!handler) {
20593
21290
  throw new ExitPathError(
20594
21291
  "no-handler",
@@ -20611,12 +21308,12 @@ async function resolveUnilateralPath(params) {
20611
21308
  paths.sort((a, b) => delayWeight(a.sequence) - delayWeight(b.sequence));
20612
21309
  return { selection: paths[0], label: `${contract.type}:unilateral` };
20613
21310
  }
20614
- const decoded = chunkZIRFXBKL_cjs.VtxoScript.decode(vtxo.tapTree);
21311
+ const decoded = chunk2JV4VQ7C_cjs.VtxoScript.decode(vtxo.tapTree);
20615
21312
  let best;
20616
21313
  for (const exit of decoded.exitPaths()) {
20617
21314
  const leaf = decoded.findLeaf(base.hex.encode(exit.script));
20618
21315
  if (!leaf) continue;
20619
- const sequence = chunkZIRFXBKL_cjs.timelockToSequence(exit.params.timelock);
21316
+ const sequence = chunk2JV4VQ7C_cjs.timelockToSequence(exit.params.timelock);
20620
21317
  const weight = delayWeight(sequence);
20621
21318
  if (!best || weight < best.weight) {
20622
21319
  best = { selection: { leaf, sequence }, weight };
@@ -20631,6 +21328,22 @@ async function resolveUnilateralPath(params) {
20631
21328
  return { selection: best.selection, label: "default:exit" };
20632
21329
  }
20633
21330
 
21331
+ // src/wallet/exitObserver.ts
21332
+ function exitObserverFor(manager) {
21333
+ return (outpoint) => manager.refreshOutpoints([outpoint]);
21334
+ }
21335
+ async function notifyExitObserved(onExitObserved, outpoint) {
21336
+ if (!onExitObserved) return;
21337
+ try {
21338
+ await onExitObserved(outpoint);
21339
+ } catch (e) {
21340
+ console.error(
21341
+ `exit observer failed for ${outpoint.txid}:${outpoint.vout} \u2014 the exit is unaffected`,
21342
+ e
21343
+ );
21344
+ }
21345
+ }
21346
+
20634
21347
  // src/wallet/unroll.ts
20635
21348
  function chainTxTypeToChainedExit2(t) {
20636
21349
  switch (t) {
@@ -20655,27 +21368,30 @@ exports.Unroll = void 0;
20655
21368
  })(Unroll2.StepType || (Unroll2.StepType = {}));
20656
21369
  class Session2 {
20657
21370
  /** Create an unroll session from a virtual output outpoint and its dependency chain. */
20658
- constructor(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
21371
+ constructor(toUnroll, bumper, explorer, indexer, virtualTxRepository, onExitObserved) {
20659
21372
  this.toUnroll = toUnroll;
20660
21373
  this.bumper = bumper;
20661
21374
  this.explorer = explorer;
20662
21375
  this.indexer = indexer;
20663
21376
  this.virtualTxRepository = virtualTxRepository;
21377
+ this.onExitObserved = onExitObserved;
20664
21378
  }
20665
21379
  toUnroll;
20666
21380
  bumper;
20667
21381
  explorer;
20668
21382
  indexer;
20669
21383
  virtualTxRepository;
21384
+ onExitObserved;
20670
21385
  /** Create an unroll session by loading the virtual output chain from the indexer. */
20671
- static async create(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
21386
+ static async create(toUnroll, bumper, explorer, indexer, virtualTxRepository, onExitObserved) {
20672
21387
  const { chain } = await indexer.getVtxoChain(toUnroll);
20673
21388
  return new Session2(
20674
21389
  { ...toUnroll, chain },
20675
21390
  bumper,
20676
21391
  explorer,
20677
21392
  indexer,
20678
- virtualTxRepository
21393
+ virtualTxRepository,
21394
+ onExitObserved
20679
21395
  );
20680
21396
  }
20681
21397
  /**
@@ -20711,6 +21427,14 @@ exports.Unroll = void 0;
20711
21427
  }
20712
21428
  /**
20713
21429
  * Get the next step to be executed
21430
+ *
21431
+ * @remarks
21432
+ * `do()` is the step, not a formality: every effect lives there, and at
21433
+ * `StepType.DONE` that includes firing {@link onExitObserved}. A caller
21434
+ * driving `next()` by hand must always await it — the async iterator
21435
+ * below does. Reading `type` and skipping `do()` leaves the exit
21436
+ * unobserved, and on the other step kinds unbroadcast.
21437
+ *
20714
21438
  * @returns The next step to be executed + the function to execute it
20715
21439
  */
20716
21440
  async next() {
@@ -20739,7 +21463,12 @@ exports.Unroll = void 0;
20739
21463
  return {
20740
21464
  type: 2 /* DONE */,
20741
21465
  vtxoTxid: this.toUnroll.txid,
20742
- do: () => Promise.resolve()
21466
+ // The observation rides on `do` rather than the iterator so
21467
+ // a caller driving `next()` by hand fires it too.
21468
+ do: () => notifyExitObserved(this.onExitObserved, {
21469
+ txid: this.toUnroll.txid,
21470
+ vout: this.toUnroll.vout
21471
+ })
20743
21472
  };
20744
21473
  }
20745
21474
  const virtualTxBase64 = await this.resolveVirtualTxBase64(nextTxToBroadcast);
@@ -20773,9 +21502,22 @@ exports.Unroll = void 0;
20773
21502
  }
20774
21503
  }
20775
21504
  Unroll2.Session = Session2;
21505
+ async function sessionFor(wallet, toUnroll, bumper) {
21506
+ const manager = await wallet.getContractManager();
21507
+ return Session2.create(
21508
+ toUnroll,
21509
+ bumper,
21510
+ wallet.onchainProvider,
21511
+ wallet.indexerProvider,
21512
+ wallet.virtualTxRepository,
21513
+ exitObserverFor(manager)
21514
+ );
21515
+ }
21516
+ Unroll2.sessionFor = sessionFor;
20776
21517
  async function completeUnroll(wallet, vtxoTxids, outputAddress) {
20777
21518
  const signedTx = await prepareUnrollTransaction(wallet, vtxoTxids, outputAddress);
20778
21519
  await wallet.onchainProvider.broadcastTransaction(signedTx.hex);
21520
+ await refreshSpentExitOutputs(wallet, signedTx);
20779
21521
  return signedTx.id;
20780
21522
  }
20781
21523
  Unroll2.completeUnroll = completeUnroll;
@@ -20791,9 +21533,9 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
20791
21533
  let totalAmount = 0n;
20792
21534
  const txWeightEstimator = TxWeightEstimator.create();
20793
21535
  for (const vtxo of vtxos) {
20794
- if (!vtxo.isUnrolled) {
21536
+ if (!chunk2JV4VQ7C_cjs.canSweepOnchain(vtxo)) {
20795
21537
  throw new Error(
20796
- `Vtxo ${vtxo.txid}:${vtxo.vout} is not fully unrolled, use unroll first`
21538
+ `Vtxo ${vtxo.txid}:${vtxo.vout} cannot be swept onchain: it is not fully unrolled (use unroll first), or its exit output was already spent`
20797
21539
  );
20798
21540
  }
20799
21541
  const txStatus = await wallet.onchainProvider.getTxStatus(vtxo.txid);
@@ -20802,14 +21544,14 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
20802
21544
  }
20803
21545
  const resolved = await resolveUnilateralPath({
20804
21546
  vtxo,
20805
- scriptHex: base.hex.encode(chunkZIRFXBKL_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
21547
+ scriptHex: base.hex.encode(chunk2JV4VQ7C_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
20806
21548
  contractRepository: wallet.contractRepository,
20807
21549
  walletPubKeyHex: base.hex.encode(await wallet.identity.xOnlyPublicKey()),
20808
21550
  currentTime: Date.now()
20809
21551
  });
20810
21552
  const spendingLeaf = resolved.selection.leaf;
20811
21553
  const sequence = resolved.selection.sequence;
20812
- const timelock = chunkZIRFXBKL_cjs.sequenceToTimelock(sequence);
21554
+ const timelock = chunk2JV4VQ7C_cjs.sequenceToTimelock(sequence);
20813
21555
  const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
20814
21556
  if (!elapsed) {
20815
21557
  throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
@@ -20822,7 +21564,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
20822
21564
  sequence,
20823
21565
  witnessUtxo: {
20824
21566
  amount: BigInt(vtxo.value),
20825
- script: chunkZIRFXBKL_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
21567
+ script: chunk2JV4VQ7C_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
20826
21568
  },
20827
21569
  sighashType: btcSigner.SigHash.DEFAULT
20828
21570
  });
@@ -20832,7 +21574,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
20832
21574
  btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
20833
21575
  );
20834
21576
  }
20835
- const tx = new chunkZIRFXBKL_cjs.Transaction({ version: 2 });
21577
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({ version: 2 });
20836
21578
  for (const input of inputs) {
20837
21579
  tx.addInput(input);
20838
21580
  }
@@ -20854,6 +21596,22 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
20854
21596
  signedTx.finalize();
20855
21597
  return signedTx;
20856
21598
  }
21599
+ async function refreshSpentExitOutputs(wallet, signedTx) {
21600
+ const outpoints = [];
21601
+ for (let i = 0; i < signedTx.inputsLength; i++) {
21602
+ const input = signedTx.getInput(i);
21603
+ if (input.txid && input.index !== void 0) {
21604
+ outpoints.push({ txid: base.hex.encode(input.txid), vout: input.index });
21605
+ }
21606
+ }
21607
+ if (outpoints.length === 0) return;
21608
+ try {
21609
+ const manager = await wallet.getContractManager();
21610
+ await manager.refreshOutpoints(outpoints);
21611
+ } catch (e) {
21612
+ console.error("completeUnroll: failed to refresh the spent exit outputs", e);
21613
+ }
21614
+ }
20857
21615
  function sleep2(ms) {
20858
21616
  return new Promise((resolve) => setTimeout(resolve, ms));
20859
21617
  }
@@ -20899,7 +21657,7 @@ async function buildSignedSweep(params) {
20899
21657
  `uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
20900
21658
  );
20901
21659
  }
20902
- const tx = new chunkZIRFXBKL_cjs.Transaction({ version: 2 });
21660
+ const tx = new chunk2JV4VQ7C_cjs.Transaction({ version: 2 });
20903
21661
  tx.addInput({
20904
21662
  txid: vtxo.txid,
20905
21663
  index: vtxo.vout,
@@ -20924,7 +21682,7 @@ async function buildSignedSweep(params) {
20924
21682
  finalScriptWitness: [
20925
21683
  tapScriptSig[0][1],
20926
21684
  ...path.extraWitness,
20927
- chunkZIRFXBKL_cjs.scriptFromTapLeafScript(path.leaf),
21685
+ chunk2JV4VQ7C_cjs.scriptFromTapLeafScript(path.leaf),
20928
21686
  btcSigner.TaprootControlBlock.encode(controlBlock)
20929
21687
  ]
20930
21688
  });
@@ -20932,7 +21690,7 @@ async function buildSignedSweep(params) {
20932
21690
  }
20933
21691
 
20934
21692
  // src/wallet/exit/estimate.ts
20935
- var CHILD_OUTPUT_DUST = 546;
21693
+ var CHILD_OUTPUT_DUST = CHILD_DUST_AMOUNT;
20936
21694
  function stepFundingAmount(stepFee) {
20937
21695
  return stepFee + CHILD_OUTPUT_DUST;
20938
21696
  }
@@ -20954,7 +21712,7 @@ async function resolveFeeRate(opts) {
20954
21712
  }
20955
21713
  async function selectExitVtxos(opts) {
20956
21714
  if (!opts.vtxos) return opts.wallet.getVtxos();
20957
- const res = await chunkZIRFXBKL_cjs.getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
21715
+ const res = await chunk2JV4VQ7C_cjs.getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
20958
21716
  const tapTrees = /* @__PURE__ */ new Map();
20959
21717
  const out = [];
20960
21718
  for (const vtxo of res.vtxos) {
@@ -20969,7 +21727,7 @@ async function selectExitVtxos(opts) {
20969
21727
  `no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
20970
21728
  );
20971
21729
  }
20972
- const handler = chunkPXPPZF5K_cjs.contractHandlers.get(contract.type);
21730
+ const handler = chunkOIZ2V2VD_cjs.contractHandlers.get(contract.type);
20973
21731
  if (!handler) {
20974
21732
  throw new Error(`no contract handler registered for type '${contract.type}'`);
20975
21733
  }
@@ -20999,7 +21757,7 @@ async function computeExitLayout(opts, feeRate) {
20999
21757
  if (pendingNodes.length > 0) {
21000
21758
  const txs = await resolver.getVirtualTxs(pendingNodes.map((n) => n.txid));
21001
21759
  for (const psbt of txs) {
21002
- psbts.set(chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
21760
+ psbts.set(chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
21003
21761
  }
21004
21762
  }
21005
21763
  const childVsize = Number(
@@ -21035,7 +21793,7 @@ async function computeExitLayout(opts, feeRate) {
21035
21793
  try {
21036
21794
  const resolved = await resolveUnilateralPath({
21037
21795
  vtxo,
21038
- scriptHex: base.hex.encode(chunkZIRFXBKL_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
21796
+ scriptHex: base.hex.encode(chunk2JV4VQ7C_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
21039
21797
  contractRepository: wallet.contractRepository,
21040
21798
  walletPubKeyHex,
21041
21799
  currentTime: Date.now()
@@ -21054,7 +21812,7 @@ async function computeExitLayout(opts, feeRate) {
21054
21812
  });
21055
21813
  continue;
21056
21814
  }
21057
- const t = chunkZIRFXBKL_cjs.sequenceToTimelock(resolved.selection.sequence);
21815
+ const t = chunk2JV4VQ7C_cjs.sequenceToTimelock(resolved.selection.sequence);
21058
21816
  const delay = { type: t.type, value: Number(t.value) };
21059
21817
  infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
21060
21818
  sweeps.push({ vtxo, resolved, sweepFee, delay });
@@ -21093,10 +21851,18 @@ async function computeExitLayout(opts, feeRate) {
21093
21851
  // splitter. funded: + 1 splitter tx and pre-signed children.
21094
21852
  txCount: (graph ? 0 : steps.length > 0 ? 1 : 0) + steps.length * 2 + sweeps.length,
21095
21853
  totalFeeSats: splitterFee + stepFees + sweepFees,
21096
- // graph funding is what the executor sends to its own fee address:
21097
- // just the CPFP fees (change recycles); funded also locks the
21098
- // per-child dust into the splitter.
21099
- fundingRequiredSats: graph ? stepFees : splitterFee + fundingTotal,
21854
+ // graph funding is what the executor sends to its own fee address: the
21855
+ // CPFP fees, plus one dust floor. Change recycles through that single
21856
+ // address, so each bump hands its remainder to the next and only the
21857
+ // *final* change has to clear `CHILD_DUST_AMOUNT` — but it does have to,
21858
+ // and `buildAnchorChild` throws rather than absorbing a short remainder
21859
+ // into the fee. Quoting bare fees quotes an amount that strands the last
21860
+ // bump and every sweep behind it.
21861
+ //
21862
+ // funded reserves the same floor per step instead of once overall (see
21863
+ // `stepFundingAmount`), because it pre-funds each child separately
21864
+ // through the splitter rather than recycling one output.
21865
+ fundingRequiredSats: graph ? steps.length > 0 ? stepFees + CHILD_OUTPUT_DUST : 0 : splitterFee + fundingTotal,
21100
21866
  recoveredSats: sweeps.reduce((s, x) => s + (x.vtxo.value - x.sweepFee), 0)
21101
21867
  };
21102
21868
  const expiries = pendingNodes.map((n) => n.expiresAt).filter((x) => x !== void 0);
@@ -21156,12 +21922,32 @@ var Executor = class {
21156
21922
  this.pollIntervalMs = opts?.pollIntervalMs ?? 5e3;
21157
21923
  this.feeWallet = opts?.feeWallet;
21158
21924
  this.signal = opts?.signal;
21925
+ this.onExitObserved = opts?.onExitObserved;
21159
21926
  }
21160
21927
  pkg;
21161
21928
  provider;
21162
21929
  pollIntervalMs;
21163
21930
  feeWallet;
21164
21931
  signal;
21932
+ onExitObserved;
21933
+ /**
21934
+ * Per-VTXO branch progress, which the executor otherwise does not track:
21935
+ * `dead` / `done` are per-step, and a VTXO is only onchain once EVERY
21936
+ * `package`/`bump` step naming it has confirmed. (`broadcast` — the funding
21937
+ * splitter — carries no `forVtxos` and serves no single VTXO.)
21938
+ */
21939
+ branchSteps() {
21940
+ const byVtxo = /* @__PURE__ */ new Map();
21941
+ this.pkg.steps.forEach((step, i) => {
21942
+ if (step.kind !== "package" && step.kind !== "bump") return;
21943
+ for (const vtxo of step.forVtxos) {
21944
+ let steps = byVtxo.get(vtxo);
21945
+ if (!steps) byVtxo.set(vtxo, steps = /* @__PURE__ */ new Set());
21946
+ steps.add(i);
21947
+ }
21948
+ });
21949
+ return byVtxo;
21950
+ }
21165
21951
  /**
21166
21952
  * Poll delay. Nearly all wall-clock time is spent here, so it must be the
21167
21953
  * thing that reacts to abort — checking only between polls would leave
@@ -21201,6 +21987,19 @@ var Executor = class {
21201
21987
  async *[Symbol.asyncIterator]() {
21202
21988
  throwIfAborted(this.signal);
21203
21989
  const dead = /* @__PURE__ */ new Set();
21990
+ const branchSteps = this.branchSteps();
21991
+ const onchainSteps = /* @__PURE__ */ new Set();
21992
+ const branchObserved = /* @__PURE__ */ new Set();
21993
+ const observeBranch = async (stepIndex, forVtxos) => {
21994
+ onchainSteps.add(stepIndex);
21995
+ for (const vtxo of forVtxos ?? []) {
21996
+ if (branchObserved.has(vtxo)) continue;
21997
+ const steps = branchSteps.get(vtxo);
21998
+ if (!steps || ![...steps].every((i) => onchainSteps.has(i))) continue;
21999
+ branchObserved.add(vtxo);
22000
+ await this.observe(vtxo);
22001
+ }
22002
+ };
21204
22003
  if (this.pkg.validUntil && Date.now() / 1e3 > this.pkg.validUntil) {
21205
22004
  yield {
21206
22005
  stepIndex: -1,
@@ -21230,6 +22029,7 @@ var Executor = class {
21230
22029
  const anchorTxid = step.kind === "package" || step.kind === "bump" ? step.parentTxid : step.txid;
21231
22030
  const existing = await this.status(anchorTxid);
21232
22031
  if (existing?.confirmed) {
22032
+ await observeBranch(i, forVtxos);
21233
22033
  yield {
21234
22034
  stepIndex: i,
21235
22035
  kind: step.kind,
@@ -21285,6 +22085,7 @@ var Executor = class {
21285
22085
  }
21286
22086
  }
21287
22087
  await this.waitConfirmed(anchorTxid);
22088
+ await observeBranch(i, forVtxos);
21288
22089
  yield {
21289
22090
  stepIndex: i,
21290
22091
  kind: step.kind,
@@ -21315,6 +22116,7 @@ var Executor = class {
21315
22116
  const swept = await this.status(step.txid);
21316
22117
  if (swept?.confirmed) {
21317
22118
  done.add(index);
22119
+ await this.observe(step.vtxo);
21318
22120
  yield {
21319
22121
  stepIndex: index,
21320
22122
  kind: "sweep",
@@ -21371,7 +22173,25 @@ var Executor = class {
21371
22173
  if (done.size < pending.length) await this.sleep();
21372
22174
  }
21373
22175
  }
22176
+ /** `"txid:vout"` -> outpoint, then hand it to the hook. A malformed entry is skipped. */
22177
+ async observe(outpoint) {
22178
+ if (!this.onExitObserved) return;
22179
+ const sep = outpoint.lastIndexOf(":");
22180
+ const rest = outpoint.slice(sep + 1);
22181
+ const vout = Number(rest);
22182
+ if (sep <= 0 || rest === "" || !Number.isInteger(vout)) return;
22183
+ await notifyExitObserved(this.onExitObserved, { txid: outpoint.slice(0, sep), vout });
22184
+ }
21374
22185
  };
22186
+
22187
+ // src/wallet/exit/execute.ts
22188
+ async function execute(wallet, pkg, opts) {
22189
+ const manager = await wallet.getContractManager();
22190
+ return new Executor(pkg, opts?.provider ?? wallet.onchainProvider, {
22191
+ ...opts,
22192
+ onExitObserved: opts?.onExitObserved ?? exitObserverFor(manager)
22193
+ });
22194
+ }
21375
22195
  async function prepare(opts) {
21376
22196
  const { wallet, onchainWallet } = opts;
21377
22197
  const feeRate = await resolveFeeRate(opts);
@@ -21393,7 +22213,7 @@ async function prepare(opts) {
21393
22213
  txid: sweep.vtxo.txid,
21394
22214
  vout: sweep.vtxo.vout,
21395
22215
  value: sweep.vtxo.value,
21396
- pkScript: chunkZIRFXBKL_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
22216
+ pkScript: chunk2JV4VQ7C_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
21397
22217
  },
21398
22218
  path: sweep.resolved.selection,
21399
22219
  outputAddress: opts.sweepAddress,
@@ -21446,7 +22266,10 @@ async function prepare(opts) {
21446
22266
  totals: {
21447
22267
  txCount: bumpSteps.length * 2 + sweepSteps.length,
21448
22268
  totalFeeSats: stepFees2 + sweepFees2,
21449
- fundingRequiredSats: stepFees2,
22269
+ // Fees plus the single dust floor the recycling change output
22270
+ // must keep clear; see the note in `estimate.ts`. Must match
22271
+ // the quote `estimate` gives for the same package.
22272
+ fundingRequiredSats: bumpSteps.length > 0 ? stepFees2 + CHILD_OUTPUT_DUST : 0,
21450
22273
  recoveredSats: recovered2
21451
22274
  },
21452
22275
  vtxos: layout.infos,
@@ -21478,7 +22301,7 @@ async function prepare(opts) {
21478
22301
  if (newFee <= splitterFee) break;
21479
22302
  splitterFee = newFee;
21480
22303
  }
21481
- const splitter = new chunkZIRFXBKL_cjs.Transaction({ version: 2 });
22304
+ const splitter = new chunk2JV4VQ7C_cjs.Transaction({ version: 2 });
21482
22305
  for (const coin of selected.inputs) {
21483
22306
  splitter.addInput({
21484
22307
  txid: coin.txid,
@@ -21615,47 +22438,48 @@ function isValidStep(step) {
21615
22438
  var UnilateralExit = {
21616
22439
  estimate,
21617
22440
  prepare,
22441
+ execute,
21618
22442
  Executor
21619
22443
  };
21620
22444
 
21621
22445
  // src/arkade/index.ts
21622
22446
  var arkade_exports = {};
21623
22447
  chunk5BLDMQED_cjs.__export(arkade_exports, {
21624
- ARKADE_OP: () => chunkPXPPZF5K_cjs.ARKADE_OP,
21625
- ARKADE_OPCODES: () => chunkPXPPZF5K_cjs.ARKADE_OPCODES,
21626
- ARKADE_OPCODE_NAMES: () => chunkPXPPZF5K_cjs.ARKADE_OPCODE_NAMES,
21627
- ARKADE_OPCODE_VALUES: () => chunkPXPPZF5K_cjs.ARKADE_OPCODE_VALUES,
21628
- ARKADE_OPS: () => chunkPXPPZF5K_cjs.ARKADE_OPS,
22448
+ ARKADE_OP: () => chunkOIZ2V2VD_cjs.ARKADE_OP,
22449
+ ARKADE_OPCODES: () => chunkOIZ2V2VD_cjs.ARKADE_OPCODES,
22450
+ ARKADE_OPCODE_NAMES: () => chunkOIZ2V2VD_cjs.ARKADE_OPCODE_NAMES,
22451
+ ARKADE_OPCODE_VALUES: () => chunkOIZ2V2VD_cjs.ARKADE_OPCODE_VALUES,
22452
+ ARKADE_OPS: () => chunkOIZ2V2VD_cjs.ARKADE_OPS,
21629
22453
  Arkade: () => Arkade,
21630
22454
  ArkadeContract: () => ArkadeContract,
21631
- ArkadeProgramScript: () => chunkPXPPZF5K_cjs.ArkadeProgramScript,
21632
- ArkadeScript: () => chunkPXPPZF5K_cjs.ArkadeScript,
22455
+ ArkadeProgramScript: () => chunkOIZ2V2VD_cjs.ArkadeProgramScript,
22456
+ ArkadeScript: () => chunkOIZ2V2VD_cjs.ArkadeScript,
21633
22457
  ArkadeTransactionBuilder: () => ArkadeTransactionBuilder,
21634
- BigNum: () => chunkPXPPZF5K_cjs.bignum_exports,
22458
+ BigNum: () => chunkOIZ2V2VD_cjs.bignum_exports,
21635
22459
  OP: () => btcSigner.OP,
21636
- OPCODE_NAMES: () => chunkPXPPZF5K_cjs.OPCODE_NAMES,
21637
- OPCODE_VALUES: () => chunkPXPPZF5K_cjs.OPCODE_VALUES,
21638
- SUPPORTED_PROGRAM_VERSION: () => chunkPXPPZF5K_cjs.SUPPORTED_PROGRAM_VERSION,
22460
+ OPCODE_NAMES: () => chunkOIZ2V2VD_cjs.OPCODE_NAMES,
22461
+ OPCODE_VALUES: () => chunkOIZ2V2VD_cjs.OPCODE_VALUES,
22462
+ SUPPORTED_PROGRAM_VERSION: () => chunkOIZ2V2VD_cjs.SUPPORTED_PROGRAM_VERSION,
21639
22463
  Script: () => btcSigner.Script,
21640
- arkadeScriptHash: () => chunkPXPPZF5K_cjs.arkadeScriptHash,
21641
- arkadeWitnessHash: () => chunkPXPPZF5K_cjs.arkadeWitnessHash,
21642
- asmToBytes: () => chunkPXPPZF5K_cjs.asmToBytes,
21643
- bytesToASM: () => chunkPXPPZF5K_cjs.bytesToASM,
21644
- computeArkadeScriptPublicKey: () => chunkPXPPZF5K_cjs.computeArkadeScriptPublicKey,
22464
+ arkadeScriptHash: () => chunkOIZ2V2VD_cjs.arkadeScriptHash,
22465
+ arkadeWitnessHash: () => chunkOIZ2V2VD_cjs.arkadeWitnessHash,
22466
+ asmToBytes: () => chunkOIZ2V2VD_cjs.asmToBytes,
22467
+ bytesToASM: () => chunkOIZ2V2VD_cjs.bytesToASM,
22468
+ computeArkadeScriptPublicKey: () => chunkOIZ2V2VD_cjs.computeArkadeScriptPublicKey,
21645
22469
  createArkadeBatchHandler: () => createArkadeBatchHandler,
21646
- deserializeArkadeContractParams: () => chunkPXPPZF5K_cjs.deserializeArkadeContractParams,
21647
- fromASM: () => chunkPXPPZF5K_cjs.fromASM,
21648
- getOpcodeName: () => chunkPXPPZF5K_cjs.getOpcodeName,
21649
- getOpcodeValue: () => chunkPXPPZF5K_cjs.getOpcodeValue,
21650
- parseArtifact: () => chunkPXPPZF5K_cjs.parseArtifact,
21651
- resolveAsm: () => chunkPXPPZF5K_cjs.resolveAsm,
21652
- serializeArkadeContractParams: () => chunkPXPPZF5K_cjs.serializeArkadeContractParams,
21653
- stringifyArtifact: () => chunkPXPPZF5K_cjs.stringifyArtifact,
21654
- toASM: () => chunkPXPPZF5K_cjs.toASM,
21655
- validateProgram: () => chunkPXPPZF5K_cjs.validateProgram,
21656
- witnessRefToBytes: () => chunkPXPPZF5K_cjs.witnessRefToBytes
22470
+ deserializeArkadeContractParams: () => chunkOIZ2V2VD_cjs.deserializeArkadeContractParams,
22471
+ fromASM: () => chunkOIZ2V2VD_cjs.fromASM,
22472
+ getOpcodeName: () => chunkOIZ2V2VD_cjs.getOpcodeName,
22473
+ getOpcodeValue: () => chunkOIZ2V2VD_cjs.getOpcodeValue,
22474
+ parseArtifact: () => chunkOIZ2V2VD_cjs.parseArtifact,
22475
+ resolveAsm: () => chunkOIZ2V2VD_cjs.resolveAsm,
22476
+ serializeArkadeContractParams: () => chunkOIZ2V2VD_cjs.serializeArkadeContractParams,
22477
+ stringifyArtifact: () => chunkOIZ2V2VD_cjs.stringifyArtifact,
22478
+ toASM: () => chunkOIZ2V2VD_cjs.toASM,
22479
+ validateProgram: () => chunkOIZ2V2VD_cjs.validateProgram,
22480
+ witnessRefToBytes: () => chunkOIZ2V2VD_cjs.witnessRefToBytes
21657
22481
  });
21658
- var isVtxoCoin = (input) => chunkZIRFXBKL_cjs.isVirtualCoin(input);
22482
+ var isVtxoCoin = (input) => chunk2JV4VQ7C_cjs.isVirtualCoin(input);
21659
22483
  function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message, session, arkProvider, emulator, network, recipients, batchExpiryPolicy) {
21660
22484
  let batchId;
21661
22485
  let sweepTapTreeRoot;
@@ -21676,23 +22500,23 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
21676
22500
  );
21677
22501
  await arkProvider.confirmRegistration(intentId);
21678
22502
  batchId = event.id;
21679
- const sweepTapscript = chunkZIRFXBKL_cjs.CSVMultisigTapscript.encode({
22503
+ const sweepTapscript = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.encode({
21680
22504
  timelock,
21681
- pubkeys: [chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(info.forfeitPubkey), "forfeit key")]
22505
+ pubkeys: [chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(info.forfeitPubkey), "forfeit key")]
21682
22506
  }).script;
21683
22507
  sweepTapTreeRoot = payment_js.tapLeafHash(sweepTapscript);
21684
22508
  return { skip: false };
21685
22509
  },
21686
22510
  onTreeSigningStarted: async (event, vtxoTree) => {
21687
22511
  const signerPubKey = await session.getPublicKey();
21688
- const xonlySignerPubKey = chunkPXPPZF5K_cjs.toXOnly(signerPubKey, "signer key");
22512
+ const xonlySignerPubKey = chunkOIZ2V2VD_cjs.toXOnly(signerPubKey, "signer key");
21689
22513
  const xOnlyPubkeys = event.cosignersPublicKeys.map(
21690
- (k) => base.hex.encode(chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
22514
+ (k) => base.hex.encode(chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
21691
22515
  );
21692
22516
  if (!xOnlyPubkeys.includes(base.hex.encode(xonlySignerPubKey))) {
21693
22517
  return { skip: true };
21694
22518
  }
21695
- const commitmentTx = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(event.unsignedCommitmentTx));
22519
+ const commitmentTx = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(event.unsignedCommitmentTx));
21696
22520
  validateVtxoTxGraph(vtxoTree, commitmentTx, sweepTapTreeRoot);
21697
22521
  if (recipients && recipients.length > 0) {
21698
22522
  validateBatchRecipients(commitmentTx, vtxoTree.leaves(), recipients, network);
@@ -21724,7 +22548,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
21724
22548
  if (connectorTree) {
21725
22549
  validateConnectorsTxGraph(event.commitmentTx, connectorTree);
21726
22550
  }
21727
- let commitmentPsbt = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
22551
+ let commitmentPsbt = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
21728
22552
  assertFinalCommitmentMatchesValidated(
21729
22553
  commitmentPsbt,
21730
22554
  validatedCommitmentTxid,
@@ -21759,7 +22583,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
21759
22583
  boardingIndices.push(boardingIdx);
21760
22584
  continue;
21761
22585
  }
21762
- if (chunkZIRFXBKL_cjs.isRecoverable(input) || isSubdust(input, info.dust)) {
22586
+ if (chunk2JV4VQ7C_cjs.isRecoverable(input) || isSubdust(input, info.dust)) {
21763
22587
  continue;
21764
22588
  }
21765
22589
  if (connectorIndex >= connectorLeaves.length) {
@@ -21780,7 +22604,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
21780
22604
  index: input.vout,
21781
22605
  witnessUtxo: {
21782
22606
  amount: BigInt(input.value),
21783
- script: chunkZIRFXBKL_cjs.VtxoScript.decode(input.tapTree).pkScript
22607
+ script: chunk2JV4VQ7C_cjs.VtxoScript.decode(input.tapTree).pkScript
21784
22608
  },
21785
22609
  sighashType: btcSigner.SigHash.DEFAULT,
21786
22610
  tapLeafScript: [input.forfeitTapLeafScript]
@@ -21871,16 +22695,16 @@ var Arkade = class _Arkade {
21871
22695
  /** Connect and resolve the server key, checkpoint closure and (if present) the co-signer key. */
21872
22696
  static async connect(opts) {
21873
22697
  const info = await opts.arkade.getInfo();
21874
- const serverKey = chunkPXPPZF5K_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
21875
- const checkpoint = chunkZIRFXBKL_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
21876
- const network = opts.network ?? chunkZIRFXBKL_cjs.DEFAULT_NETWORK;
22698
+ const serverKey = chunkOIZ2V2VD_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
22699
+ const checkpoint = chunk2JV4VQ7C_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
22700
+ const network = opts.network ?? chunk2JV4VQ7C_cjs.DEFAULT_NETWORK;
21877
22701
  let emulatorKey;
21878
22702
  if (opts.emulator) {
21879
- emulatorKey = base.hex.decode(chunkZIRFXBKL_cjs.resolveEmulatorPubkey(network, opts.emulatorPubkey));
22703
+ emulatorKey = base.hex.decode(chunk2JV4VQ7C_cjs.resolveEmulatorPubkey(network, opts.emulatorPubkey));
21880
22704
  }
21881
22705
  let userKey;
21882
22706
  if (opts.identity) {
21883
- userKey = chunkPXPPZF5K_cjs.toXOnly(await opts.identity.xOnlyPublicKey(), "identity key");
22707
+ userKey = chunkOIZ2V2VD_cjs.toXOnly(await opts.identity.xOnlyPublicKey(), "identity key");
21884
22708
  }
21885
22709
  return new _Arkade({
21886
22710
  arkProvider: opts.arkade,
@@ -21906,7 +22730,7 @@ var Arkade = class _Arkade {
21906
22730
  * key respectively; explicit args always win.
21907
22731
  */
21908
22732
  contract(program, args = {}) {
21909
- const declared = (program.params ?? []).map(chunkPXPPZF5K_cjs.inputName);
22733
+ const declared = (program.params ?? []).map(chunkOIZ2V2VD_cjs.inputName);
21910
22734
  if (declared.includes("server") && args.server === void 0) {
21911
22735
  args = { ...args, server: this.serverKey };
21912
22736
  }
@@ -21926,7 +22750,7 @@ var ArkadeContract = class _ArkadeContract {
21926
22750
  userKey: client.userKey,
21927
22751
  emulatorKey: client.emulatorKey
21928
22752
  };
21929
- this.vtxoScript = new chunkPXPPZF5K_cjs.ArkadeProgramScript(program, args, this.keys);
22753
+ this.vtxoScript = new chunkOIZ2V2VD_cjs.ArkadeProgramScript(program, args, this.keys);
21930
22754
  this.tapTree = this.vtxoScript.encode();
21931
22755
  this.compiled = this.vtxoScript.compiled;
21932
22756
  }
@@ -21954,7 +22778,7 @@ var ArkadeContract = class _ArkadeContract {
21954
22778
  `ArkadeContract.fromContract: expected contract type 'arkade', got '${contract.type}'`
21955
22779
  );
21956
22780
  }
21957
- const typed = chunkPXPPZF5K_cjs.deserializeArkadeContractParams(contract.params);
22781
+ const typed = chunkOIZ2V2VD_cjs.deserializeArkadeContractParams(contract.params);
21958
22782
  return new _ArkadeContract(client, typed.program, typed.args, {
21959
22783
  serverKey: typed.serverKey,
21960
22784
  userKey: typed.userKey,
@@ -21995,7 +22819,7 @@ var ArkadeContract = class _ArkadeContract {
21995
22819
  toContractParams() {
21996
22820
  return {
21997
22821
  type: "arkade",
21998
- params: chunkPXPPZF5K_cjs.serializeArkadeContractParams({
22822
+ params: chunkOIZ2V2VD_cjs.serializeArkadeContractParams({
21999
22823
  program: this.program,
22000
22824
  args: this.args,
22001
22825
  serverKey: this.keys.serverKey,
@@ -22040,13 +22864,15 @@ var ArkadeContract = class _ArkadeContract {
22040
22864
  const [registered] = await manager.getContracts({ script: scriptHex });
22041
22865
  if (registered) {
22042
22866
  const [withVtxos] = await manager.getContractsWithVtxos({ script: scriptHex });
22043
- return (withVtxos?.vtxos ?? []).filter((v) => !chunkZIRFXBKL_cjs.hasTerminalSpend(v));
22867
+ return (withVtxos?.vtxos ?? []).filter(
22868
+ (v) => !chunk2JV4VQ7C_cjs.hasTerminalSpend(v) && !v.isUnrolled
22869
+ );
22044
22870
  }
22045
22871
  }
22046
22872
  if (!this.client.indexer) {
22047
22873
  throw new Error("ArkadeContract.getUtxos: an indexer is required");
22048
22874
  }
22049
- const { vtxos } = await chunkZIRFXBKL_cjs.getNormalizedVtxos(this.client.indexer, {
22875
+ const { vtxos } = await chunk2JV4VQ7C_cjs.getNormalizedVtxos(this.client.indexer, {
22050
22876
  scripts: [scriptHex],
22051
22877
  spendableOnly: true
22052
22878
  });
@@ -22148,12 +22974,25 @@ var ArkadeTransactionBuilder = class {
22148
22974
  this.contract.client.checkpoint
22149
22975
  );
22150
22976
  if (coin.sourceTx) {
22151
- chunkZIRFXBKL_cjs.setArkPsbtField(arkTx, 0, chunkZIRFXBKL_cjs.PrevArkTxField, coin.sourceTx);
22977
+ chunk2JV4VQ7C_cjs.setArkPsbtField(arkTx, 0, chunk2JV4VQ7C_cjs.PrevArkTxField, coin.sourceTx);
22978
+ }
22979
+ if (this.fn.arkadeScript) {
22980
+ const indexer = this.contract.client.indexer;
22981
+ if (!indexer) {
22982
+ throw new PrevTxUnavailableError(
22983
+ "covenant spends require an `indexer` on the Arkade client to resolve the previous ark tx of each input"
22984
+ );
22985
+ }
22986
+ await attachPrevArkTxs(
22987
+ arkTx,
22988
+ [coin.txid, ...this.fundingCoins.map((c) => c.txid)],
22989
+ indexer
22990
+ );
22152
22991
  }
22153
22992
  const condition = (def.tapscript.witness ?? []).map((w) => this.witnessBytes(w));
22154
22993
  if (condition.length > 0) {
22155
- chunkZIRFXBKL_cjs.setArkPsbtField(arkTx, 0, chunkZIRFXBKL_cjs.ConditionWitness, condition);
22156
- chunkZIRFXBKL_cjs.setArkPsbtField(checkpoints[0], 0, chunkZIRFXBKL_cjs.ConditionWitness, condition);
22994
+ chunk2JV4VQ7C_cjs.setArkPsbtField(arkTx, 0, chunk2JV4VQ7C_cjs.ConditionWitness, condition);
22995
+ chunk2JV4VQ7C_cjs.setArkPsbtField(checkpoints[0], 0, chunk2JV4VQ7C_cjs.ConditionWitness, condition);
22157
22996
  }
22158
22997
  const packets = [];
22159
22998
  if (this.assetSpecs.length > 0) {
@@ -22192,7 +23031,7 @@ var ArkadeTransactionBuilder = class {
22192
23031
  base.base64.encode(signedArk2.toPSBT()),
22193
23032
  signedCps.map((c) => base.base64.encode(c.toPSBT()))
22194
23033
  );
22195
- const txid = chunkZIRFXBKL_cjs.Transaction.fromPSBT(base.base64.decode(res2.signedArkTx)).id;
23034
+ const txid = chunk2JV4VQ7C_cjs.Transaction.fromPSBT(base.base64.decode(res2.signedArkTx)).id;
22196
23035
  return {
22197
23036
  txid,
22198
23037
  signedArkTx: res2.signedArkTx,
@@ -22251,23 +23090,23 @@ var ArkadeTransactionBuilder = class {
22251
23090
  }
22252
23091
  buildAssetPacket() {
22253
23092
  const groups = this.assetSpecs.map((s) => {
22254
- const id = typeof s.assetId === "string" ? chunk3S3JZUEN_cjs.AssetId.fromString(s.assetId) : chunk3S3JZUEN_cjs.AssetId.fromBytes(s.assetId);
22255
- return chunk3S3JZUEN_cjs.AssetGroup.create(
23093
+ const id = typeof s.assetId === "string" ? chunkCO3KKSWM_cjs.AssetId.fromString(s.assetId) : chunkCO3KKSWM_cjs.AssetId.fromBytes(s.assetId);
23094
+ return chunkCO3KKSWM_cjs.AssetGroup.create(
22256
23095
  id,
22257
23096
  null,
22258
- s.inputs.map((i) => chunk3S3JZUEN_cjs.AssetInput.create(i.vin, i.amount)),
22259
- s.outputs.map((o) => chunk3S3JZUEN_cjs.AssetOutput.create(o.vout, o.amount)),
22260
- (s.metadata ?? []).map((m) => chunk3S3JZUEN_cjs.Metadata.create(m.key, m.value))
23097
+ s.inputs.map((i) => chunkCO3KKSWM_cjs.AssetInput.create(i.vin, i.amount)),
23098
+ s.outputs.map((o) => chunkCO3KKSWM_cjs.AssetOutput.create(o.vout, o.amount)),
23099
+ (s.metadata ?? []).map((m) => chunkCO3KKSWM_cjs.Metadata.create(m.key, m.value))
22261
23100
  );
22262
23101
  });
22263
- return chunk3S3JZUEN_cjs.Packet.create(groups);
23102
+ return chunkCO3KKSWM_cjs.Packet.create(groups);
22264
23103
  }
22265
23104
  witnessBytes(ref) {
22266
- return chunkPXPPZF5K_cjs.witnessRefToBytes(ref, this.args, this.contract.args);
23105
+ return chunkOIZ2V2VD_cjs.witnessRefToBytes(ref, this.args, this.contract.args);
22267
23106
  }
22268
23107
  };
22269
23108
  function bindInputs(fn, callArgs) {
22270
- const names = (fn.def.inputs ?? []).map(chunkPXPPZF5K_cjs.inputName);
23109
+ const names = (fn.def.inputs ?? []).map(chunkOIZ2V2VD_cjs.inputName);
22271
23110
  if (callArgs.length !== names.length) {
22272
23111
  throw new Error(`${fn.name}: expected ${names.length} argument(s), got ${callArgs.length}`);
22273
23112
  }
@@ -22667,6 +23506,7 @@ exports.AssetManager = AssetManager;
22667
23506
  exports.BIP21 = BIP21;
22668
23507
  exports.BIP21Error = BIP21Error;
22669
23508
  exports.BLOCKED_UPGRADE_TIMEOUT_MS = BLOCKED_UPGRADE_TIMEOUT_MS;
23509
+ exports.CachingArkProvider = CachingArkProvider;
22670
23510
  exports.ChainedTxType = ChainedTxType;
22671
23511
  exports.ConnectionDisposedError = ConnectionDisposedError;
22672
23512
  exports.ContractManager = ContractManager;
@@ -22717,6 +23557,7 @@ exports.MnemonicIdentity = MnemonicIdentity;
22717
23557
  exports.OnchainWallet = OnchainWallet;
22718
23558
  exports.P2A = P2A;
22719
23559
  exports.PaymentRouter = PaymentRouter;
23560
+ exports.PrevTxUnavailableError = PrevTxUnavailableError;
22720
23561
  exports.REGTEST_MIN_BATCH_EXPIRY_SECONDS = REGTEST_MIN_BATCH_EXPIRY_SECONDS;
22721
23562
  exports.REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS = REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS;
22722
23563
  exports.Ramps = Ramps;
@@ -22742,6 +23583,7 @@ exports.UnilateralExit = UnilateralExit;
22742
23583
  exports.UnknownPacket = UnknownPacket;
22743
23584
  exports.VtxoManager = VtxoManager;
22744
23585
  exports.Wallet = Wallet2;
23586
+ exports.WalletCannotAllocateAddressError = WalletCannotAllocateAddressError;
22745
23587
  exports.WalletCannotSignError = WalletCannotSignError;
22746
23588
  exports.WalletMessageHandler = WalletMessageHandler;
22747
23589
  exports.WalletNotInitializedError = WalletNotInitializedError;
@@ -22758,6 +23600,8 @@ exports.assertSubmittedArkTxid = assertSubmittedArkTxid;
22758
23600
  exports.assertValidBatchExpiry = assertValidBatchExpiry;
22759
23601
  exports.assertValidServerUnrollScript = assertValidServerUnrollScript;
22760
23602
  exports.assetMintResolver = assetMintResolver;
23603
+ exports.attachPrevArkTxs = attachPrevArkTxs;
23604
+ exports.attachPrevoutTxs = attachPrevoutTxs;
22761
23605
  exports.awaitTransaction = awaitTransaction;
22762
23606
  exports.boardingResolver = boardingResolver;
22763
23607
  exports.btcTarget = btcTarget;
@@ -22789,7 +23633,9 @@ exports.deserializeExitPackage = deserializeExitPackage;
22789
23633
  exports.deserializeUtxo = deserializeUtxo;
22790
23634
  exports.deserializeVtxo = deserializeVtxo;
22791
23635
  exports.encodeArkContract = encodeArkContract;
23636
+ exports.exitObserverFor = exitObserverFor;
22792
23637
  exports.extendVirtualCoinForContract = extendVirtualCoinForContract;
23638
+ exports.extractArkProviderUrl = extractArkProviderUrl;
22793
23639
  exports.gateExclusion = gateExclusion;
22794
23640
  exports.gatedContracts = gatedContracts;
22795
23641
  exports.getAllByIndexValues = getAllByIndexValues;
@@ -22800,6 +23646,7 @@ exports.hasCandidates = hasCandidates;
22800
23646
  exports.intentMatchesFilter = intentMatchesFilter;
22801
23647
  exports.intentPageBounds = intentPageBounds;
22802
23648
  exports.invoiceTarget = invoiceTarget;
23649
+ exports.isAddressAllocationCapable = isAddressAllocationCapable;
22803
23650
  exports.isArkContract = isArkContract;
22804
23651
  exports.isBatchSignable = isBatchSignable;
22805
23652
  exports.isBtcAddress = isBtcAddress;
@@ -22827,6 +23674,7 @@ exports.makeHandle = makeHandle;
22827
23674
  exports.matchServerCheckpoints = matchServerCheckpoints;
22828
23675
  exports.mergeChainedTxType = mergeChainedTxType;
22829
23676
  exports.migrateWalletRepository = migrateWalletRepository;
23677
+ exports.notifyExitObserved = notifyExitObserved;
22830
23678
  exports.onchainRail = onchainRail;
22831
23679
  exports.openDatabase = openDatabase;
22832
23680
  exports.outpointExclusion = outpointExclusion;
@@ -22838,6 +23686,7 @@ exports.requiresMigration = requiresMigration;
22838
23686
  exports.resolveBatchExpiryPolicy = resolveBatchExpiryPolicy;
22839
23687
  exports.resolveCheckpointExitDelayPolicy = resolveCheckpointExitDelayPolicy;
22840
23688
  exports.resolveDescriptorSigner = resolveDescriptorSigner;
23689
+ exports.resolvePrevTxs = resolvePrevTxs;
22841
23690
  exports.resolveSendAmount = resolveSendAmount;
22842
23691
  exports.rollbackMigration = rollbackMigration;
22843
23692
  exports.saveVtxosForContract = saveVtxosForContract;
@@ -22861,5 +23710,6 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
22861
23710
  exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
22862
23711
  exports.waitForIncomingFunds = waitForIncomingFunds;
22863
23712
  exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
22864
- //# sourceMappingURL=chunk-5E6IZNRG.cjs.map
22865
- //# sourceMappingURL=chunk-5E6IZNRG.cjs.map
23713
+ exports.withPrevTxs = withPrevTxs;
23714
+ //# sourceMappingURL=chunk-MJUTO3PY.cjs.map
23715
+ //# sourceMappingURL=chunk-MJUTO3PY.cjs.map