@arkade-os/sdk 0.4.41 → 0.4.43

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 (69) hide show
  1. package/dist/adapters/expo.cjs +4 -4
  2. package/dist/adapters/expo.d.cts +2 -2
  3. package/dist/adapters/expo.d.ts +2 -2
  4. package/dist/adapters/expo.js +2 -2
  5. package/dist/adapters/indexedDB.cjs +3 -3
  6. package/dist/adapters/indexedDB.js +2 -2
  7. package/dist/{ark-CSqMJczW.d.cts → ark-I8jfe5VE.d.cts} +157 -2
  8. package/dist/{ark-CSqMJczW.d.ts → ark-I8jfe5VE.d.ts} +157 -2
  9. package/dist/{asyncStorageTaskQueue-SZPrhw23.d.ts → asyncStorageTaskQueue-CjoL-35w.d.ts} +1 -1
  10. package/dist/{asyncStorageTaskQueue-79XdGsdW.d.cts → asyncStorageTaskQueue-D1FfHfgK.d.cts} +1 -1
  11. package/dist/{chunk-ALISWEQ5.cjs → chunk-3AQNLQPM.cjs} +39 -4
  12. package/dist/chunk-3AQNLQPM.cjs.map +1 -0
  13. package/dist/{chunk-5XAYUPK4.js → chunk-763XHDAJ.js} +39 -5
  14. package/dist/chunk-763XHDAJ.js.map +1 -0
  15. package/dist/{chunk-D5MQYYYF.js → chunk-B4R36PRN.js} +1106 -357
  16. package/dist/chunk-B4R36PRN.js.map +1 -0
  17. package/dist/{chunk-KNASU3QI.cjs → chunk-JIWCE2IK.cjs} +7 -7
  18. package/dist/{chunk-KNASU3QI.cjs.map → chunk-JIWCE2IK.cjs.map} +1 -1
  19. package/dist/{chunk-WBF3FNS3.cjs → chunk-PLJZRIFZ.cjs} +11 -11
  20. package/dist/{chunk-WBF3FNS3.cjs.map → chunk-PLJZRIFZ.cjs.map} +1 -1
  21. package/dist/{chunk-3MPXMLP4.cjs → chunk-QGNTDGMN.cjs} +1190 -430
  22. package/dist/chunk-QGNTDGMN.cjs.map +1 -0
  23. package/dist/{chunk-MYI333YH.js → chunk-US274KZO.js} +3 -3
  24. package/dist/{chunk-MYI333YH.js.map → chunk-US274KZO.js.map} +1 -1
  25. package/dist/{chunk-DDG4RE5F.js → chunk-VKKLOT2E.js} +3 -3
  26. package/dist/{chunk-DDG4RE5F.js.map → chunk-VKKLOT2E.js.map} +1 -1
  27. package/dist/contracts/handlers/index.d.cts +3 -3
  28. package/dist/contracts/handlers/index.d.ts +3 -3
  29. package/dist/{delegate-Bqwe-kbj.d.cts → delegate-BRqbh2fW.d.cts} +1 -1
  30. package/dist/{delegate-BTn9BK8E.d.ts → delegate-CgjVjYOP.d.ts} +1 -1
  31. package/dist/{index-aYiHTMkX.d.cts → index-DHuXlDEg.d.cts} +2 -2
  32. package/dist/{index-kITujXlS.d.ts → index-DvWNB_rl.d.ts} +2 -2
  33. package/dist/index.cjs +150 -118
  34. package/dist/index.d.cts +113 -9
  35. package/dist/index.d.ts +113 -9
  36. package/dist/index.js +2 -2
  37. package/dist/repositories/realm/index.cjs +268 -12
  38. package/dist/repositories/realm/index.cjs.map +1 -1
  39. package/dist/repositories/realm/index.d.cts +101 -3
  40. package/dist/repositories/realm/index.d.ts +101 -3
  41. package/dist/repositories/realm/index.js +254 -4
  42. package/dist/repositories/realm/index.js.map +1 -1
  43. package/dist/repositories/sqlite/index.cjs +366 -40
  44. package/dist/repositories/sqlite/index.cjs.map +1 -1
  45. package/dist/repositories/sqlite/index.d.cts +52 -6
  46. package/dist/repositories/sqlite/index.d.ts +52 -6
  47. package/dist/repositories/sqlite/index.js +353 -32
  48. package/dist/repositories/sqlite/index.js.map +1 -1
  49. package/dist/{taskRunner-DRHElPMG.d.cts → taskRunner-BSnslNmq.d.cts} +1 -1
  50. package/dist/{taskRunner-BuBAZQwB.d.ts → taskRunner-Djlhfgi1.d.ts} +1 -1
  51. package/dist/wallet/expo/background.cjs +12 -12
  52. package/dist/wallet/expo/background.d.cts +3 -3
  53. package/dist/wallet/expo/background.d.ts +3 -3
  54. package/dist/wallet/expo/background.js +4 -4
  55. package/dist/wallet/expo/index.cjs +12 -12
  56. package/dist/wallet/expo/index.d.cts +4 -4
  57. package/dist/wallet/expo/index.d.ts +4 -4
  58. package/dist/wallet/expo/index.js +3 -3
  59. package/dist/{wallet-CTEQpKG9.d.ts → wallet-BsqRU8KM.d.cts} +29 -5
  60. package/dist/{wallet-BZgRfnAE.d.cts → wallet-D9z7wssl.d.ts} +29 -5
  61. package/dist/worker/expo/index.cjs +7 -7
  62. package/dist/worker/expo/index.d.cts +4 -4
  63. package/dist/worker/expo/index.d.ts +4 -4
  64. package/dist/worker/expo/index.js +3 -3
  65. package/package.json +2 -2
  66. package/dist/chunk-3MPXMLP4.cjs.map +0 -1
  67. package/dist/chunk-5XAYUPK4.js.map +0 -1
  68. package/dist/chunk-ALISWEQ5.cjs.map +0 -1
  69. package/dist/chunk-D5MQYYYF.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkALISWEQ5_cjs = require('./chunk-ALISWEQ5.cjs');
3
+ var chunk3AQNLQPM_cjs = require('./chunk-3AQNLQPM.cjs');
4
4
  var chunk32YKLQPS_cjs = require('./chunk-32YKLQPS.cjs');
5
5
  var chunkHXDZ2QTW_cjs = require('./chunk-HXDZ2QTW.cjs');
6
6
  var utils_js = require('@scure/btc-signer/utils.js');
@@ -181,7 +181,7 @@ var TreeSignerSession = class _TreeSignerSession {
181
181
  noncesByPubkey.set(base.hex.encode(myPublicKey.subarray(1)), myNonce);
182
182
  const tx = this.graph.find(txid);
183
183
  if (!tx) throw new Error(`missing tx for txid ${txid}`);
184
- const cosigners = chunkALISWEQ5_cjs.getArkPsbtFields(tx.root, 0, chunkALISWEQ5_cjs.CosignerPublicKey).map(
184
+ const cosigners = chunk3AQNLQPM_cjs.getArkPsbtFields(tx.root, 0, chunk3AQNLQPM_cjs.CosignerPublicKey).map(
185
185
  (c) => base.hex.encode(c.key.subarray(1))
186
186
  // xonly pubkey
187
187
  );
@@ -233,7 +233,7 @@ var TreeSignerSession = class _TreeSignerSession {
233
233
  if (!aggNonce) throw new Error("missing aggregate nonce");
234
234
  const prevoutAmounts = [];
235
235
  const prevoutScripts = [];
236
- const cosigners = chunkALISWEQ5_cjs.getArkPsbtFields(g.root, 0, chunkALISWEQ5_cjs.CosignerPublicKey).map((c) => c.key);
236
+ const cosigners = chunk3AQNLQPM_cjs.getArkPsbtFields(g.root, 0, chunk3AQNLQPM_cjs.CosignerPublicKey).map((c) => c.key);
237
237
  const { finalKey } = aggregateKeys(cosigners, true, {
238
238
  taprootTweak: this.scriptRoot
239
239
  });
@@ -980,14 +980,14 @@ var RestDelegateProvider = class {
980
980
  */
981
981
  async delegate(intent, forfeitTxs, options) {
982
982
  const url = `${this.url}/v1/delegate`;
983
- const response = await chunkALISWEQ5_cjs.baseFetch(url, {
983
+ const response = await chunk3AQNLQPM_cjs.baseFetch(url, {
984
984
  method: "POST",
985
985
  headers: {
986
986
  "Content-Type": "application/json"
987
987
  },
988
988
  body: JSON.stringify({
989
989
  intent: {
990
- message: chunkALISWEQ5_cjs.Intent.encodeMessage(intent.message),
990
+ message: chunk3AQNLQPM_cjs.Intent.encodeMessage(intent.message),
991
991
  proof: intent.proof
992
992
  },
993
993
  forfeit_txs: forfeitTxs,
@@ -1007,7 +1007,7 @@ var RestDelegateProvider = class {
1007
1007
  */
1008
1008
  async getDelegateInfo() {
1009
1009
  const url = `${this.url}/v1/delegator/info`;
1010
- const response = await chunkALISWEQ5_cjs.baseFetch(url);
1010
+ const response = await chunk3AQNLQPM_cjs.baseFetch(url);
1011
1011
  if (!response.ok) {
1012
1012
  const errorText2 = await response.text();
1013
1013
  throw new Error(`Failed to get delegate info: ${errorText2}`);
@@ -1042,14 +1042,14 @@ var EsploraProvider = class {
1042
1042
  pollingInterval;
1043
1043
  forcePolling;
1044
1044
  async getCoins(address) {
1045
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1045
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
1046
1046
  if (!response.ok) {
1047
1047
  throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
1048
1048
  }
1049
1049
  return response.json();
1050
1050
  }
1051
1051
  async getFeeRate() {
1052
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1052
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
1053
1053
  if (response.status === 404) {
1054
1054
  return void 0;
1055
1055
  }
@@ -1070,7 +1070,7 @@ var EsploraProvider = class {
1070
1070
  }
1071
1071
  }
1072
1072
  async getTxOutspends(txid) {
1073
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1073
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
1074
1074
  if (!response.ok) {
1075
1075
  const error = await response.text();
1076
1076
  throw new Error(`Failed to get transaction outspends: ${error}`);
@@ -1078,7 +1078,7 @@ var EsploraProvider = class {
1078
1078
  return response.json();
1079
1079
  }
1080
1080
  async getTransactions(address) {
1081
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1081
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
1082
1082
  if (!response.ok) {
1083
1083
  const error = await response.text();
1084
1084
  throw new Error(`Failed to get transactions: ${error}`);
@@ -1086,7 +1086,7 @@ var EsploraProvider = class {
1086
1086
  return response.json();
1087
1087
  }
1088
1088
  async getTxStatus(txid) {
1089
- const txresponse = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1089
+ const txresponse = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
1090
1090
  if (!txresponse.ok) {
1091
1091
  throw new Error(txresponse.statusText);
1092
1092
  }
@@ -1094,7 +1094,7 @@ var EsploraProvider = class {
1094
1094
  if (!tx.status.confirmed) {
1095
1095
  return { confirmed: false };
1096
1096
  }
1097
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1097
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
1098
1098
  if (!response.ok) {
1099
1099
  throw new Error(`Failed to get transaction status: ${response.statusText}`);
1100
1100
  }
@@ -1178,7 +1178,7 @@ var EsploraProvider = class {
1178
1178
  return stopFunc;
1179
1179
  }
1180
1180
  async getChainTip() {
1181
- const tipBlocks = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/blocks`);
1181
+ const tipBlocks = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/blocks`);
1182
1182
  if (!tipBlocks.ok) {
1183
1183
  throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
1184
1184
  }
@@ -1197,7 +1197,7 @@ var EsploraProvider = class {
1197
1197
  };
1198
1198
  }
1199
1199
  async broadcastPackage(parent, child) {
1200
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1200
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
1201
1201
  method: "POST",
1202
1202
  headers: {
1203
1203
  "Content-Type": "application/json"
@@ -1211,7 +1211,7 @@ var EsploraProvider = class {
1211
1211
  return response.json();
1212
1212
  }
1213
1213
  async broadcastTx(tx) {
1214
- const response = await chunkALISWEQ5_cjs.baseFetch(`${this.baseUrl}/tx`, {
1214
+ const response = await chunk3AQNLQPM_cjs.baseFetch(`${this.baseUrl}/tx`, {
1215
1215
  method: "POST",
1216
1216
  headers: {
1217
1217
  "Content-Type": "text/plain"
@@ -1282,7 +1282,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
1282
1282
  );
1283
1283
  }
1284
1284
  function buildForfeitTxWithOutput(inputs, output, txLocktime) {
1285
- const tx = new chunkALISWEQ5_cjs.Transaction({
1285
+ const tx = new chunk3AQNLQPM_cjs.Transaction({
1286
1286
  version: 3,
1287
1287
  lockTime: txLocktime
1288
1288
  });
@@ -1358,7 +1358,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
1358
1358
  if (previousScriptKey.length !== 32) {
1359
1359
  throw new Error(`parent output ${childIndex} has invalid script`);
1360
1360
  }
1361
- const cosigners = chunkALISWEQ5_cjs.getArkPsbtFields(child.root, 0, chunkALISWEQ5_cjs.CosignerPublicKey);
1361
+ const cosigners = chunk3AQNLQPM_cjs.getArkPsbtFields(child.root, 0, chunk3AQNLQPM_cjs.CosignerPublicKey);
1362
1362
  if (cosigners.length === 0) {
1363
1363
  throw ErrMissingCosignersPublicKeys;
1364
1364
  }
@@ -1458,7 +1458,7 @@ var Extension = class _Extension {
1458
1458
  `expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
1459
1459
  );
1460
1460
  }
1461
- const reader = new chunkALISWEQ5_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
1461
+ const reader = new chunk3AQNLQPM_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
1462
1462
  const packets = [];
1463
1463
  while (reader.remaining() > 0) {
1464
1464
  const packetType = reader.readByte();
@@ -1532,7 +1532,7 @@ var Extension = class _Extension {
1532
1532
  */
1533
1533
  getAssetPacket() {
1534
1534
  for (const p of this.packets) {
1535
- if (p instanceof chunkALISWEQ5_cjs.Packet) {
1535
+ if (p instanceof chunk3AQNLQPM_cjs.Packet) {
1536
1536
  return p;
1537
1537
  }
1538
1538
  }
@@ -1540,8 +1540,8 @@ var Extension = class _Extension {
1540
1540
  }
1541
1541
  };
1542
1542
  function parsePacket(packetType, data) {
1543
- if (packetType === chunkALISWEQ5_cjs.Packet.PACKET_TYPE) {
1544
- return chunkALISWEQ5_cjs.Packet.fromBytes(data);
1543
+ if (packetType === chunk3AQNLQPM_cjs.Packet.PACKET_TYPE) {
1544
+ return chunk3AQNLQPM_cjs.Packet.fromBytes(data);
1545
1545
  }
1546
1546
  return new UnknownPacket(packetType, data);
1547
1547
  }
@@ -1848,7 +1848,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
1848
1848
  const existing = inputsByAssetId.get(asset.assetId);
1849
1849
  inputsByAssetId.set(asset.assetId, [
1850
1850
  ...existing ?? [],
1851
- chunkALISWEQ5_cjs.AssetInput.create(inputIndex, asset.amount)
1851
+ chunk3AQNLQPM_cjs.AssetInput.create(inputIndex, asset.amount)
1852
1852
  ]);
1853
1853
  }
1854
1854
  }
@@ -1860,7 +1860,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
1860
1860
  const existing = outputsByAssetId.get(asset.assetId);
1861
1861
  outputsByAssetId.set(asset.assetId, [
1862
1862
  ...existing ?? [],
1863
- chunkALISWEQ5_cjs.AssetOutput.create(outputIndex, asset.amount)
1863
+ chunk3AQNLQPM_cjs.AssetOutput.create(outputIndex, asset.amount)
1864
1864
  ]);
1865
1865
  }
1866
1866
  }
@@ -1871,7 +1871,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
1871
1871
  const existing = outputsByAssetId.get(asset.assetId);
1872
1872
  outputsByAssetId.set(asset.assetId, [
1873
1873
  ...existing ?? [],
1874
- chunkALISWEQ5_cjs.AssetOutput.create(outputIndex, asset.amount)
1874
+ chunk3AQNLQPM_cjs.AssetOutput.create(outputIndex, asset.amount)
1875
1875
  ]);
1876
1876
  }
1877
1877
  }
@@ -1880,11 +1880,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
1880
1880
  for (const assetIdStr of allAssetIds) {
1881
1881
  const inputs = inputsByAssetId.get(assetIdStr);
1882
1882
  const outputs = outputsByAssetId.get(assetIdStr);
1883
- const assetId = chunkALISWEQ5_cjs.AssetId.fromString(assetIdStr);
1884
- const group = chunkALISWEQ5_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
1883
+ const assetId = chunk3AQNLQPM_cjs.AssetId.fromString(assetIdStr);
1884
+ const group = chunk3AQNLQPM_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
1885
1885
  groups.push(group);
1886
1886
  }
1887
- return chunkALISWEQ5_cjs.Packet.create(groups);
1887
+ return chunk3AQNLQPM_cjs.Packet.create(groups);
1888
1888
  }
1889
1889
  function selectCoinsWithAsset(coins, assetId, requiredAmount) {
1890
1890
  const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
@@ -2001,7 +2001,7 @@ function buildVirtualTx(inputs, outputs) {
2001
2001
  }
2002
2002
  }
2003
2003
  }
2004
- const tx = new chunkALISWEQ5_cjs.Transaction({
2004
+ const tx = new chunk3AQNLQPM_cjs.Transaction({
2005
2005
  version: 3,
2006
2006
  lockTime: Number(lockTime)
2007
2007
  });
@@ -2016,7 +2016,7 @@ function buildVirtualTx(inputs, outputs) {
2016
2016
  },
2017
2017
  tapLeafScript: [input.tapLeafScript]
2018
2018
  });
2019
- chunkALISWEQ5_cjs.setArkPsbtField(tx, i, chunkALISWEQ5_cjs.VtxoTaprootTree, input.tapTree);
2019
+ chunk3AQNLQPM_cjs.setArkPsbtField(tx, i, chunk3AQNLQPM_cjs.VtxoTaprootTree, input.tapTree);
2020
2020
  }
2021
2021
  for (const output of outputs) {
2022
2022
  tx.addOutput(output);
@@ -2666,7 +2666,7 @@ function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount) {
2666
2666
  );
2667
2667
  }
2668
2668
  function isMigrationCapable(wallet) {
2669
- return "arkProvider" in wallet && "arkServerPublicKey" in wallet && "onchainProvider" in wallet && typeof wallet.rotateServerSigner === "function" && typeof wallet.sendSelectedVtxosToSelf === "function" && typeof wallet.getBoardingUtxosForSigners === "function";
2669
+ return "arkProvider" in wallet && "arkServerPublicKey" in wallet && "onchainProvider" in wallet && typeof wallet.rotateServerSigner === "function" && typeof wallet.refreshDeprecatedSigners === "function" && typeof wallet.sendSelectedVtxosToSelf === "function" && typeof wallet.getBoardingUtxosForSigners === "function";
2670
2670
  }
2671
2671
  function classifiedToRef(c) {
2672
2672
  return {
@@ -3124,7 +3124,7 @@ var VtxoManager = class _VtxoManager {
3124
3124
  `Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
3125
3125
  );
3126
3126
  }
3127
- const tx = new chunkALISWEQ5_cjs.Transaction();
3127
+ const tx = new chunk3AQNLQPM_cjs.Transaction();
3128
3128
  for (const utxo of expiredUtxos) {
3129
3129
  const utxoScript = chunkHXDZ2QTW_cjs.VtxoScript.decode(utxo.tapTree);
3130
3130
  const utxoExitLeaf = utxoScript.leaves.find(
@@ -3190,6 +3190,7 @@ var VtxoManager = class _VtxoManager {
3190
3190
  async migrateCore(options) {
3191
3191
  const wallet = this.requireMigrationCapableWallet();
3192
3192
  const info = await wallet.arkProvider.getInfo();
3193
+ wallet.refreshDeprecatedSigners(info);
3193
3194
  const signerSet = signerSetFromInfo(info);
3194
3195
  const nowSeconds = Math.floor(Date.now() / 1e3);
3195
3196
  const walletSignerHex = base.hex.encode(wallet.arkServerPublicKey);
@@ -3762,7 +3763,7 @@ var VtxoManager = class _VtxoManager {
3762
3763
  * or doesn't carry the metadata.
3763
3764
  */
3764
3765
  extractSpentOutpoint(error) {
3765
- const ark = chunkALISWEQ5_cjs.maybeArkError(error);
3766
+ const ark = chunk3AQNLQPM_cjs.maybeArkError(error);
3766
3767
  if (!ark || ark.name !== "VTXO_ALREADY_SPENT") return void 0;
3767
3768
  const raw = ark.metadata?.vtxo_outpoint;
3768
3769
  if (typeof raw !== "string") return void 0;
@@ -4158,6 +4159,123 @@ function readUInt32BE(array, offset) {
4158
4159
  function noteTapscript(preimageHash) {
4159
4160
  return btcSigner.Script.encode(["SHA256", preimageHash, "EQUAL"]);
4160
4161
  }
4162
+
4163
+ // src/repositories/intentRepository.ts
4164
+ var ALL_INTENT_STATES = [
4165
+ "waiting_to_submit",
4166
+ "waiting_for_batch",
4167
+ "batch_in_progress",
4168
+ "batch_failed",
4169
+ "batch_succeeded",
4170
+ "cancelled"
4171
+ ];
4172
+ var INTENT_TERMINAL_STATES = /* @__PURE__ */ new Set([
4173
+ "batch_failed",
4174
+ "batch_succeeded",
4175
+ "cancelled"
4176
+ ]);
4177
+ function isTerminalIntentState(s) {
4178
+ return INTENT_TERMINAL_STATES.has(s);
4179
+ }
4180
+ function assertIntentIdUnique(intent, existing) {
4181
+ if (intent.intentId === void 0) return;
4182
+ for (const e of existing) {
4183
+ if (e.intentTxId !== intent.intentTxId && e.intentId === intent.intentId) {
4184
+ throw new Error(
4185
+ `intentId "${intent.intentId}" is already used by intent ${e.intentTxId}`
4186
+ );
4187
+ }
4188
+ }
4189
+ }
4190
+ function intentMatchesFilter(i, f) {
4191
+ if (f.intentTxIds && !f.intentTxIds.includes(i.intentTxId)) return false;
4192
+ if (f.intentIds && (!i.intentId || !f.intentIds.includes(i.intentId))) return false;
4193
+ if (f.states && !f.states.includes(i.state)) return false;
4194
+ if (f.containingInputs) {
4195
+ const keys = new Set(i.intentVtxos.map((o) => `${o.txid}:${o.vout}`));
4196
+ if (!f.containingInputs.some((o) => keys.has(`${o.txid}:${o.vout}`))) return false;
4197
+ }
4198
+ if (f.validAt !== void 0) {
4199
+ if (i.validFrom !== void 0 && f.validAt < i.validFrom) return false;
4200
+ if (i.validUntil !== void 0 && f.validAt > i.validUntil) return false;
4201
+ }
4202
+ if (f.searchText) {
4203
+ const hay = [i.intentId, i.batchId, i.commitmentTransactionId].filter(Boolean).join(" ");
4204
+ if (!hay.includes(f.searchText)) return false;
4205
+ }
4206
+ return true;
4207
+ }
4208
+ function intentPageBounds(filter, total) {
4209
+ const skip = Math.max(0, filter?.skip ?? 0);
4210
+ const take = filter?.take === void 0 ? total : Math.max(0, filter.take);
4211
+ return { skip, end: skip + take };
4212
+ }
4213
+
4214
+ // src/wallet/intentStateReducer.ts
4215
+ function reduceIntentState(current, event) {
4216
+ if (isTerminalIntentState(current)) return current;
4217
+ switch (event.type) {
4218
+ case "batch_started" /* BatchStarted */:
4219
+ return "batch_in_progress";
4220
+ case "batch_finalized" /* BatchFinalized */:
4221
+ return "batch_succeeded";
4222
+ case "batch_failed" /* BatchFailed */:
4223
+ return "batch_failed";
4224
+ default:
4225
+ return current;
4226
+ }
4227
+ }
4228
+ function applySettlementEventToIntent(intent, event) {
4229
+ const next = reduceIntentState(intent.state, event);
4230
+ if (next === intent.state) return void 0;
4231
+ const updated = { ...intent, state: next };
4232
+ if ("id" in event && typeof event.id === "string") {
4233
+ updated.batchId = event.id;
4234
+ }
4235
+ if (event.type === "batch_finalized" /* BatchFinalized */) {
4236
+ updated.commitmentTransactionId = event.commitmentTxid;
4237
+ }
4238
+ if (event.type === "batch_failed" /* BatchFailed */) {
4239
+ updated.cancellationReason = event.reason;
4240
+ }
4241
+ return updated;
4242
+ }
4243
+
4244
+ // src/wallet/intentPersistenceHandler.ts
4245
+ async function persistTransition(deps, event) {
4246
+ const repo = deps.intentRepository;
4247
+ if (!repo) return;
4248
+ try {
4249
+ const cur = (await repo.getIntents({ intentTxIds: [deps.intentTxId] }))[0];
4250
+ if (!cur) return;
4251
+ const next = applySettlementEventToIntent(cur, event);
4252
+ if (next) await repo.saveIntent(next);
4253
+ } catch (e) {
4254
+ console.error(`Failed to apply settlement event to intent ${deps.intentTxId}`, e);
4255
+ }
4256
+ }
4257
+ function wrapHandlerWithIntentPersistence(base, deps) {
4258
+ return {
4259
+ ...base,
4260
+ onBatchStarted: async (event) => {
4261
+ const result = await base.onBatchStarted(event);
4262
+ if (!result.skip) await persistTransition(deps, event);
4263
+ return result;
4264
+ },
4265
+ onBatchFinalized: async (event) => {
4266
+ if (base.onBatchFinalized) await base.onBatchFinalized(event);
4267
+ await persistTransition(deps, event);
4268
+ },
4269
+ onBatchFailed: async (event) => {
4270
+ await persistTransition(deps, event);
4271
+ if (base.onBatchFailed) {
4272
+ await base.onBatchFailed(event);
4273
+ return;
4274
+ }
4275
+ throw new Error(event.reason);
4276
+ }
4277
+ };
4278
+ }
4161
4279
  var TxTree = class {
4162
4280
  constructor(root, children = /* @__PURE__ */ new Map()) {
4163
4281
  this.root = root;
@@ -4673,7 +4791,7 @@ var AssetManager = class extends ReadonlyAssetManager {
4673
4791
  const virtualCoins = await this.wallet.getVtxos({
4674
4792
  withRecoverable: false
4675
4793
  });
4676
- const controlAssetRef = params.controlAssetId ? chunkALISWEQ5_cjs.AssetRef.fromId(chunkALISWEQ5_cjs.AssetId.fromString(params.controlAssetId)) : null;
4794
+ const controlAssetRef = params.controlAssetId ? chunk3AQNLQPM_cjs.AssetRef.fromId(chunk3AQNLQPM_cjs.AssetId.fromString(params.controlAssetId)) : null;
4677
4795
  const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
4678
4796
  let totalBtcSelected = 0n;
4679
4797
  const assetChanges = /* @__PURE__ */ new Map();
@@ -4686,8 +4804,8 @@ var AssetManager = class extends ReadonlyAssetManager {
4686
4804
  }
4687
4805
  }
4688
4806
  const groups = [];
4689
- const issuedAssetOutput = chunkALISWEQ5_cjs.AssetOutput.create(0, params.amount);
4690
- const issuedAssetGroup = chunkALISWEQ5_cjs.AssetGroup.create(
4807
+ const issuedAssetOutput = chunk3AQNLQPM_cjs.AssetOutput.create(0, params.amount);
4808
+ const issuedAssetGroup = chunk3AQNLQPM_cjs.AssetGroup.create(
4691
4809
  null,
4692
4810
  controlAssetRef,
4693
4811
  [],
@@ -4702,15 +4820,15 @@ var AssetManager = class extends ReadonlyAssetManager {
4702
4820
  for (const [inputIndex, assets] of assetInputs) {
4703
4821
  for (const asset of assets) {
4704
4822
  if (asset.assetId !== assetId) continue;
4705
- changeInputs.push(chunkALISWEQ5_cjs.AssetInput.create(inputIndex, asset.amount));
4823
+ changeInputs.push(chunk3AQNLQPM_cjs.AssetInput.create(inputIndex, asset.amount));
4706
4824
  }
4707
4825
  }
4708
4826
  groups.push(
4709
- chunkALISWEQ5_cjs.AssetGroup.create(
4710
- chunkALISWEQ5_cjs.AssetId.fromString(assetId),
4827
+ chunk3AQNLQPM_cjs.AssetGroup.create(
4828
+ chunk3AQNLQPM_cjs.AssetId.fromString(assetId),
4711
4829
  null,
4712
4830
  changeInputs,
4713
- [chunkALISWEQ5_cjs.AssetOutput.create(0, amount)],
4831
+ [chunk3AQNLQPM_cjs.AssetOutput.create(0, amount)],
4714
4832
  []
4715
4833
  )
4716
4834
  );
@@ -4723,7 +4841,7 @@ var AssetManager = class extends ReadonlyAssetManager {
4723
4841
  script: outputAddress.pkScript,
4724
4842
  amount: BigInt(totalBtcSelected)
4725
4843
  },
4726
- Extension.create([chunkALISWEQ5_cjs.Packet.create(groups)]).txOut()
4844
+ Extension.create([chunk3AQNLQPM_cjs.Packet.create(groups)]).txOut()
4727
4845
  ];
4728
4846
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
4729
4847
  coinSelection.inputs,
@@ -4731,7 +4849,7 @@ var AssetManager = class extends ReadonlyAssetManager {
4731
4849
  );
4732
4850
  return {
4733
4851
  arkTxId: arkTxid,
4734
- assetId: chunkALISWEQ5_cjs.AssetId.create(arkTxid, 0).toString()
4852
+ assetId: chunk3AQNLQPM_cjs.AssetId.create(arkTxid, 0).toString()
4735
4853
  };
4736
4854
  }
4737
4855
  /**
@@ -4803,16 +4921,16 @@ var AssetManager = class extends ReadonlyAssetManager {
4803
4921
  for (const [inputIndex, assets] of assetInputs) {
4804
4922
  for (const asset of assets) {
4805
4923
  if (asset.assetId !== params.assetId) continue;
4806
- reissueInputs.push(chunkALISWEQ5_cjs.AssetInput.create(inputIndex, asset.amount));
4924
+ reissueInputs.push(chunk3AQNLQPM_cjs.AssetInput.create(inputIndex, asset.amount));
4807
4925
  }
4808
4926
  }
4809
4927
  const totalAssetAmount = assetToReissueAmount + params.amount;
4810
- const reissueAssetIdObj = chunkALISWEQ5_cjs.AssetId.fromString(params.assetId);
4811
- const reissueAssetGroup = chunkALISWEQ5_cjs.AssetGroup.create(
4928
+ const reissueAssetIdObj = chunk3AQNLQPM_cjs.AssetId.fromString(params.assetId);
4929
+ const reissueAssetGroup = chunk3AQNLQPM_cjs.AssetGroup.create(
4812
4930
  reissueAssetIdObj,
4813
4931
  null,
4814
4932
  reissueInputs,
4815
- [chunkALISWEQ5_cjs.AssetOutput.create(0, totalAssetAmount)],
4933
+ [chunk3AQNLQPM_cjs.AssetOutput.create(0, totalAssetAmount)],
4816
4934
  []
4817
4935
  );
4818
4936
  const groups = [reissueAssetGroup];
@@ -4821,15 +4939,15 @@ var AssetManager = class extends ReadonlyAssetManager {
4821
4939
  for (const [inputIndex, assets] of assetInputs) {
4822
4940
  for (const asset of assets) {
4823
4941
  if (asset.assetId !== assetId) continue;
4824
- changeInputs.push(chunkALISWEQ5_cjs.AssetInput.create(inputIndex, asset.amount));
4942
+ changeInputs.push(chunk3AQNLQPM_cjs.AssetInput.create(inputIndex, asset.amount));
4825
4943
  }
4826
4944
  }
4827
4945
  groups.push(
4828
- chunkALISWEQ5_cjs.AssetGroup.create(
4829
- chunkALISWEQ5_cjs.AssetId.fromString(assetId),
4946
+ chunk3AQNLQPM_cjs.AssetGroup.create(
4947
+ chunk3AQNLQPM_cjs.AssetId.fromString(assetId),
4830
4948
  null,
4831
4949
  changeInputs,
4832
- [chunkALISWEQ5_cjs.AssetOutput.create(0, amount)],
4950
+ [chunk3AQNLQPM_cjs.AssetOutput.create(0, amount)],
4833
4951
  []
4834
4952
  )
4835
4953
  );
@@ -4841,7 +4959,7 @@ var AssetManager = class extends ReadonlyAssetManager {
4841
4959
  script: outputAddress.pkScript,
4842
4960
  amount: BigInt(totalBtcSelected)
4843
4961
  },
4844
- Extension.create([chunkALISWEQ5_cjs.Packet.create(groups)]).txOut()
4962
+ Extension.create([chunk3AQNLQPM_cjs.Packet.create(groups)]).txOut()
4845
4963
  ];
4846
4964
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
4847
4965
  return arkTxid;
@@ -4908,15 +5026,15 @@ var AssetManager = class extends ReadonlyAssetManager {
4908
5026
  for (const [inputIndex, assets] of assetInputs) {
4909
5027
  for (const asset of assets) {
4910
5028
  if (asset.assetId !== assetId) continue;
4911
- changeInputs.push(chunkALISWEQ5_cjs.AssetInput.create(inputIndex, asset.amount));
5029
+ changeInputs.push(chunk3AQNLQPM_cjs.AssetInput.create(inputIndex, asset.amount));
4912
5030
  }
4913
5031
  }
4914
5032
  groups.push(
4915
- chunkALISWEQ5_cjs.AssetGroup.create(
4916
- chunkALISWEQ5_cjs.AssetId.fromString(assetId),
5033
+ chunk3AQNLQPM_cjs.AssetGroup.create(
5034
+ chunk3AQNLQPM_cjs.AssetId.fromString(assetId),
4917
5035
  null,
4918
5036
  changeInputs,
4919
- amount > 0n ? [chunkALISWEQ5_cjs.AssetOutput.create(0, amount)] : [],
5037
+ amount > 0n ? [chunk3AQNLQPM_cjs.AssetOutput.create(0, amount)] : [],
4920
5038
  []
4921
5039
  )
4922
5040
  );
@@ -4928,7 +5046,7 @@ var AssetManager = class extends ReadonlyAssetManager {
4928
5046
  script: outputAddress.pkScript,
4929
5047
  amount: BigInt(totalBtcSelected)
4930
5048
  },
4931
- Extension.create([chunkALISWEQ5_cjs.Packet.create(groups)]).txOut()
5049
+ Extension.create([chunk3AQNLQPM_cjs.Packet.create(groups)]).txOut()
4932
5050
  ];
4933
5051
  const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
4934
5052
  return arkTxid;
@@ -4953,7 +5071,7 @@ function castMetadata(metadata) {
4953
5071
  } else {
4954
5072
  throw new Error("Invalid metadata value type");
4955
5073
  }
4956
- md.push(chunkALISWEQ5_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
5074
+ md.push(chunk3AQNLQPM_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
4957
5075
  }
4958
5076
  return md;
4959
5077
  }
@@ -5238,7 +5356,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
5238
5356
  expire_at: 0,
5239
5357
  cosigners_public_keys: cosignerPubKeys
5240
5358
  };
5241
- const proof = chunkALISWEQ5_cjs.Intent.create(message, coins, outputs);
5359
+ const proof = chunk3AQNLQPM_cjs.Intent.create(message, coins, outputs);
5242
5360
  const signedProof = await identity.sign(proof);
5243
5361
  return {
5244
5362
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -5267,214 +5385,216 @@ function isAnnotated(v) {
5267
5385
  return v.tapTree !== void 0 && v.forfeitTapLeafScript !== void 0 && v.intentTapLeafScript !== void 0;
5268
5386
  }
5269
5387
 
5270
- // src/contracts/vtxoOwnership.ts
5271
- function vtxoOutpoint(vtxo) {
5272
- return `${vtxo.txid}:${vtxo.vout}`;
5273
- }
5274
- function isVtxoForScript(vtxo, script) {
5275
- return !!vtxo.script && vtxo.script === script;
5276
- }
5277
- function filterVtxosForScript(vtxos, script) {
5278
- return vtxos.filter((v) => isVtxoForScript(v, script));
5279
- }
5280
- function warnAndFilterVtxosForScript(vtxos, script, context) {
5281
- const matches = [];
5282
- const rejected = [];
5283
- for (const v of vtxos) {
5284
- if (isVtxoForScript(v, script)) {
5285
- matches.push(v);
5286
- } else {
5287
- rejected.push(`${vtxoOutpoint(v)}(script=${v.script ?? ""})`);
5288
- }
5289
- }
5290
- if (rejected.length > 0) {
5291
- console.warn(
5292
- `${context}: dropped ${rejected.length} wrong-script VTXO(s) for script ${script}: ${rejected.join(", ")}`
5293
- );
5294
- }
5295
- return matches;
5296
- }
5297
- function validateVtxosForScript(vtxos, script, context) {
5298
- const mismatches = vtxos.filter((v) => !isVtxoForScript(v, script));
5299
- if (mismatches.length === 0) return;
5300
- const detail = mismatches.map((v) => `${vtxoOutpoint(v)}(script=${v.script ?? ""})`).join(", ");
5301
- throw new Error(
5302
- `${context}: refusing to persist ${mismatches.length} VTXO(s) whose script does not match ${script}: ${detail}`
5303
- );
5304
- }
5305
- async function getVtxosForContract(repo, contract) {
5306
- return repo.getVtxosForScript ? repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
5307
- }
5308
- async function saveVtxosForContract(repo, contract, vtxos) {
5309
- if (repo.saveVtxosForScript) {
5310
- return repo.saveVtxosForScript(
5311
- { script: contract.script, address: contract.address },
5312
- vtxos
5313
- );
5314
- }
5315
- validateVtxosForScript(vtxos, contract.script, "saveVtxosForContract");
5316
- return repo.saveVtxos(contract.address, vtxos);
5388
+ // src/repositories/virtualTxRepository.ts
5389
+ var ChainedTxType = /* @__PURE__ */ ((ChainedTxType2) => {
5390
+ ChainedTxType2[ChainedTxType2["Unspecified"] = 0] = "Unspecified";
5391
+ ChainedTxType2[ChainedTxType2["Commitment"] = 1] = "Commitment";
5392
+ ChainedTxType2[ChainedTxType2["Ark"] = 2] = "Ark";
5393
+ ChainedTxType2[ChainedTxType2["Tree"] = 3] = "Tree";
5394
+ ChainedTxType2[ChainedTxType2["Checkpoint"] = 4] = "Checkpoint";
5395
+ return ChainedTxType2;
5396
+ })(ChainedTxType || {});
5397
+ function mergeChainedTxType(incoming, prev) {
5398
+ if (incoming !== 0 /* Unspecified */) return incoming;
5399
+ return prev ?? 0 /* Unspecified */;
5317
5400
  }
5318
5401
 
5319
- // src/repositories/inMemory/walletRepository.ts
5320
- var InMemoryWalletRepository = class {
5402
+ // src/repositories/inMemory/intentRepository.ts
5403
+ var InMemoryIntentRepository = class {
5321
5404
  version = 1;
5322
- vtxosByAddress = /* @__PURE__ */ new Map();
5323
- utxosByAddress = /* @__PURE__ */ new Map();
5324
- txsByAddress = /* @__PURE__ */ new Map();
5325
- walletState = null;
5326
- async getVtxos(address) {
5327
- return this.vtxosByAddress.get(address) ?? [];
5328
- }
5329
- async saveVtxos(address, vtxos) {
5330
- const existing = this.vtxosByAddress.get(address) ?? [];
5331
- const next = mergeByKey(existing, vtxos, (item) => `${item.txid}:${item.vout}`);
5332
- this.vtxosByAddress.set(address, next);
5405
+ byId = /* @__PURE__ */ new Map();
5406
+ async clear() {
5407
+ this.byId.clear();
5408
+ }
5409
+ async saveIntent(intent) {
5410
+ assertIntentIdUnique(intent, this.byId.values());
5411
+ this.byId.set(intent.intentTxId, {
5412
+ ...intent,
5413
+ intentVtxos: [...intent.intentVtxos],
5414
+ partialForfeits: [...intent.partialForfeits],
5415
+ updatedAt: Date.now()
5416
+ });
5333
5417
  }
5334
- async deleteVtxos(address) {
5335
- this.vtxosByAddress.delete(address);
5418
+ async getIntents(filter) {
5419
+ let out = [...this.byId.values()];
5420
+ if (filter) out = out.filter((i) => intentMatchesFilter(i, filter));
5421
+ out.sort((a, b) => a.createdAt - b.createdAt || a.intentTxId.localeCompare(b.intentTxId));
5422
+ const { skip, end } = intentPageBounds(filter, out.length);
5423
+ return out.slice(skip, end).map(clone);
5336
5424
  }
5337
- async getVtxosForScript(script) {
5338
- const allMatches = [];
5339
- for (const bucket of this.vtxosByAddress.values()) {
5340
- for (const vtxo of bucket) {
5341
- if (isVtxoForScript(vtxo, script)) {
5342
- allMatches.push(vtxo);
5343
- }
5344
- }
5345
- }
5346
- return mergeByKey([], allMatches, (item) => `${item.txid}:${item.vout}`);
5425
+ async getLockedVtxoOutpoints() {
5426
+ const out = [];
5427
+ for (const i of this.byId.values())
5428
+ if (!isTerminalIntentState(i.state)) for (const o of i.intentVtxos) out.push({ ...o });
5429
+ return out;
5347
5430
  }
5348
- async saveVtxosForScript(key, vtxos) {
5349
- if (!key.address) {
5350
- throw new Error("InMemoryWalletRepository requires an address");
5351
- }
5352
- for (const vtxo of vtxos) {
5353
- if (!isVtxoForScript(vtxo, key.script)) {
5354
- throw new Error(
5355
- `VTXO ${vtxo.txid}:${vtxo.vout} script mismatch: expected ${key.script}, got ${vtxo.script}`
5356
- );
5357
- }
5358
- }
5359
- return this.saveVtxos(key.address, vtxos);
5431
+ async [Symbol.asyncDispose]() {
5360
5432
  }
5361
- async deleteVtxosForScript(script) {
5362
- for (const [address, bucket] of this.vtxosByAddress.entries()) {
5363
- const next = bucket.filter((v) => !isVtxoForScript(v, script));
5364
- if (next.length === 0) {
5365
- this.vtxosByAddress.delete(address);
5366
- } else {
5367
- this.vtxosByAddress.set(address, next);
5433
+ };
5434
+ var clone = (i) => ({
5435
+ ...i,
5436
+ intentVtxos: i.intentVtxos.map((o) => ({ ...o })),
5437
+ partialForfeits: [...i.partialForfeits]
5438
+ });
5439
+
5440
+ // src/repositories/inMemory/virtualTxRepository.ts
5441
+ var opKey = (o) => `${o.txid}:${o.vout}`;
5442
+ var InMemoryVirtualTxRepository = class {
5443
+ version = 1;
5444
+ txs = /* @__PURE__ */ new Map();
5445
+ branches = /* @__PURE__ */ new Map();
5446
+ async clear() {
5447
+ this.txs.clear();
5448
+ this.branches.clear();
5449
+ }
5450
+ async upsertVirtualTxs(txs) {
5451
+ for (const t of txs) {
5452
+ const prev = this.txs.get(t.txid);
5453
+ if (!prev) {
5454
+ this.txs.set(t.txid, { ...t });
5455
+ continue;
5368
5456
  }
5457
+ this.txs.set(t.txid, {
5458
+ txid: t.txid,
5459
+ psbt: t.psbt ?? prev.psbt,
5460
+ expiresAt: t.expiresAt ?? prev.expiresAt,
5461
+ type: mergeChainedTxType(t.type, prev.type)
5462
+ });
5369
5463
  }
5370
5464
  }
5371
- async getUtxos(address) {
5372
- return this.utxosByAddress.get(address) ?? [];
5373
- }
5374
- async saveUtxos(address, utxos) {
5375
- const existing = this.utxosByAddress.get(address) ?? [];
5376
- const next = mergeByKey(existing, utxos, (item) => `${item.txid}:${item.vout}`);
5377
- this.utxosByAddress.set(address, next);
5378
- }
5379
- async deleteUtxos(address) {
5380
- this.utxosByAddress.delete(address);
5381
- }
5382
- async getTransactionHistory(address) {
5383
- return this.txsByAddress.get(address) ?? [];
5384
- }
5385
- async saveTransactions(address, txs) {
5386
- const existing = this.txsByAddress.get(address) ?? [];
5387
- const next = mergeByKey(existing, txs, serializeTxKey);
5388
- this.txsByAddress.set(address, next);
5465
+ async getVirtualTx(txid) {
5466
+ const t = this.txs.get(txid);
5467
+ return t ? { ...t } : null;
5389
5468
  }
5390
- async deleteTransactions(address) {
5391
- this.txsByAddress.delete(address);
5469
+ async setBranch(vtxo, branch) {
5470
+ this.branches.set(
5471
+ opKey(vtxo),
5472
+ [...branch].sort((a, b) => a.position - b.position)
5473
+ );
5392
5474
  }
5393
- async getWalletState() {
5394
- return this.walletState;
5475
+ async getBranch(vtxo) {
5476
+ const b = this.branches.get(opKey(vtxo)) ?? [];
5477
+ return b.map((x) => this.txs.get(x.virtualTxid)).filter((t) => !!t).map((t) => ({ ...t }));
5395
5478
  }
5396
- async saveWalletState(state) {
5397
- this.walletState = state;
5479
+ async hasBranch(vtxo) {
5480
+ return (this.branches.get(opKey(vtxo)) ?? []).length > 0;
5398
5481
  }
5399
- async clear() {
5400
- this.vtxosByAddress.clear();
5401
- this.utxosByAddress.clear();
5402
- this.txsByAddress.clear();
5403
- this.walletState = null;
5482
+ async pruneForSpentVtxo(vtxo) {
5483
+ const removed = this.branches.get(opKey(vtxo)) ?? [];
5484
+ this.branches.delete(opKey(vtxo));
5485
+ const stillReferenced = /* @__PURE__ */ new Set();
5486
+ for (const b of this.branches.values())
5487
+ for (const e of b) stillReferenced.add(e.virtualTxid);
5488
+ for (const e of removed)
5489
+ if (!stillReferenced.has(e.virtualTxid)) this.txs.delete(e.virtualTxid);
5404
5490
  }
5405
5491
  async [Symbol.asyncDispose]() {
5406
- return;
5407
5492
  }
5408
5493
  };
5409
- function serializeTxKey(tx) {
5410
- const key = tx.key;
5411
- return `${key.boardingTxid}:${key.commitmentTxid}:${key.arkTxid}`;
5412
- }
5413
- function mergeByKey(existing, incoming, toKey) {
5414
- const next = /* @__PURE__ */ new Map();
5415
- existing.forEach((item) => {
5416
- next.set(toKey(item), item);
5417
- });
5418
- incoming.forEach((item) => {
5419
- next.set(toKey(item), item);
5420
- });
5421
- return Array.from(next.values());
5422
- }
5423
5494
 
5424
- // src/repositories/inMemory/contractRepository.ts
5425
- var InMemoryContractRepository = class {
5426
- version = 1;
5427
- contractData = /* @__PURE__ */ new Map();
5428
- collections = /* @__PURE__ */ new Map();
5429
- contractsByScript = /* @__PURE__ */ new Map();
5430
- async clear() {
5431
- this.contractData.clear();
5432
- this.collections.clear();
5433
- this.contractsByScript.clear();
5434
- }
5435
- // Contract entity management methods
5436
- async getContracts(filter) {
5437
- const contracts = this.contractsByScript.values();
5438
- if (!filter) {
5439
- return [...contracts];
5495
+ // src/repositories/indexedDB/idbUtils.ts
5496
+ var promisifyRequest = (request) => new Promise((resolve, reject) => {
5497
+ request.onsuccess = () => resolve(request.result);
5498
+ request.onerror = () => reject(request.error);
5499
+ });
5500
+ var awaitTransaction = (transaction) => new Promise((resolve, reject) => {
5501
+ transaction.oncomplete = () => resolve();
5502
+ transaction.onerror = () => reject(transaction.error);
5503
+ transaction.onabort = () => reject(transaction.error ?? new Error("transaction aborted"));
5504
+ });
5505
+
5506
+ // src/repositories/indexedDB/manager.ts
5507
+ function getGlobalObject() {
5508
+ if (typeof globalThis !== "undefined") {
5509
+ if (typeof globalThis.self === "object" && globalThis.self !== null) {
5510
+ return { globalObject: globalThis.self };
5440
5511
  }
5441
- const matches = (value, criterion) => {
5442
- if (criterion === void 0) {
5443
- return true;
5444
- }
5445
- return Array.isArray(criterion) ? criterion.includes(value) : value === criterion;
5446
- };
5447
- const results = [];
5448
- for (const contract of contracts) {
5449
- if (matches(contract.script, filter.script) && matches(contract.state, filter.state) && matches(contract.type, filter.type)) {
5450
- results.push(contract);
5451
- }
5512
+ if (typeof globalThis.window === "object" && globalThis.window !== null) {
5513
+ return { globalObject: globalThis.window };
5452
5514
  }
5453
- return results;
5454
- }
5455
- async saveContract(contract) {
5456
- this.contractsByScript.set(contract.script, contract);
5515
+ return { globalObject: globalThis };
5457
5516
  }
5458
- async deleteContract(script) {
5459
- this.contractsByScript.delete(script);
5517
+ throw new Error("Global object not found");
5518
+ }
5519
+ var dbCache = /* @__PURE__ */ new Map();
5520
+ var refCounts = /* @__PURE__ */ new Map();
5521
+ async function openDatabase(dbName, dbVersion, initDatabase2) {
5522
+ const { globalObject } = getGlobalObject();
5523
+ if (!globalObject.indexedDB) {
5524
+ throw new Error("IndexedDB is not available in this environment");
5460
5525
  }
5461
- async [Symbol.asyncDispose]() {
5462
- return;
5526
+ const cached = dbCache.get(dbName);
5527
+ if (cached) {
5528
+ if (cached.version !== dbVersion) {
5529
+ throw new Error(
5530
+ `Database "${dbName}" already opened with version ${cached.version}; requested ${dbVersion}`
5531
+ );
5532
+ }
5533
+ refCounts.set(dbName, (refCounts.get(dbName) ?? 0) + 1);
5534
+ return cached.promise;
5463
5535
  }
5464
- };
5465
- function scriptFromArkAddress(address) {
5466
- return base.hex.encode(chunkHXDZ2QTW_cjs.ArkAddress.decode(address).pkScript);
5467
- }
5468
-
5469
- // src/repositories/indexedDB/schema.ts
5470
- var STORE_VTXOS = "vtxos";
5471
- var STORE_UTXOS = "utxos";
5472
- var STORE_TRANSACTIONS = "transactions";
5473
- var STORE_WALLET_STATE = "walletState";
5474
- var STORE_CONTRACTS = "contracts";
5475
- var LEGACY_STORE_CONTRACT_COLLECTIONS = "contractsCollections";
5476
- var DB_VERSION = 3;
5477
- function initDatabase(db, oldVersion, transaction) {
5536
+ const dbPromise = new Promise((resolve, reject) => {
5537
+ const request = globalObject.indexedDB.open(dbName, dbVersion);
5538
+ request.onerror = () => {
5539
+ dbCache.delete(dbName);
5540
+ refCounts.delete(dbName);
5541
+ reject(request.error);
5542
+ };
5543
+ request.onsuccess = () => {
5544
+ const db = request.result;
5545
+ db.onversionchange = () => {
5546
+ db.close();
5547
+ dbCache.delete(dbName);
5548
+ refCounts.delete(dbName);
5549
+ };
5550
+ resolve(db);
5551
+ };
5552
+ request.onupgradeneeded = (event) => {
5553
+ const db = request.result;
5554
+ initDatabase2(db, event.oldVersion, request.transaction);
5555
+ };
5556
+ request.onblocked = () => {
5557
+ console.warn("Database upgrade blocked - close other tabs/connections");
5558
+ };
5559
+ });
5560
+ dbCache.set(dbName, { version: dbVersion, promise: dbPromise });
5561
+ refCounts.set(dbName, 1);
5562
+ return dbPromise;
5563
+ }
5564
+ async function closeDatabase(dbName) {
5565
+ const cachedEntry = dbCache.get(dbName);
5566
+ if (!cachedEntry) return false;
5567
+ const count = (refCounts.get(dbName) ?? 1) - 1;
5568
+ if (count > 0) {
5569
+ refCounts.set(dbName, count);
5570
+ return false;
5571
+ }
5572
+ refCounts.delete(dbName);
5573
+ dbCache.delete(dbName);
5574
+ try {
5575
+ const db = await cachedEntry.promise;
5576
+ db.close();
5577
+ } catch {
5578
+ }
5579
+ return true;
5580
+ }
5581
+ function scriptFromArkAddress(address) {
5582
+ return base.hex.encode(chunkHXDZ2QTW_cjs.ArkAddress.decode(address).pkScript);
5583
+ }
5584
+
5585
+ // src/repositories/indexedDB/schema.ts
5586
+ var STORE_VTXOS = "vtxos";
5587
+ var STORE_UTXOS = "utxos";
5588
+ var STORE_TRANSACTIONS = "transactions";
5589
+ var STORE_WALLET_STATE = "walletState";
5590
+ var STORE_CONTRACTS = "contracts";
5591
+ var STORE_INTENTS = "intents";
5592
+ var STORE_VIRTUAL_TXS = "virtualTxs";
5593
+ var STORE_VTXO_BRANCHES = "vtxoBranches";
5594
+ var LEGACY_STORE_CONTRACT_COLLECTIONS = "contractsCollections";
5595
+ var DB_VERSION = 3;
5596
+ var INTENT_DB_VERSION = 5;
5597
+ function initDatabase(db, oldVersion, transaction) {
5478
5598
  if (!db.objectStoreNames.contains(STORE_VTXOS)) {
5479
5599
  const vtxosStore = db.createObjectStore(STORE_VTXOS, {
5480
5600
  keyPath: ["address", "txid", "vout"]
@@ -5612,33 +5732,506 @@ function initDatabase(db, oldVersion, transaction) {
5612
5732
  });
5613
5733
  }
5614
5734
  }
5615
- if (!db.objectStoreNames.contains(LEGACY_STORE_CONTRACT_COLLECTIONS)) {
5616
- db.createObjectStore(LEGACY_STORE_CONTRACT_COLLECTIONS, {
5617
- keyPath: "key"
5618
- });
5735
+ if (!db.objectStoreNames.contains(LEGACY_STORE_CONTRACT_COLLECTIONS)) {
5736
+ db.createObjectStore(LEGACY_STORE_CONTRACT_COLLECTIONS, {
5737
+ keyPath: "key"
5738
+ });
5739
+ }
5740
+ if (oldVersion >= 1 && oldVersion < 3 && transaction) {
5741
+ const vtxosStore = transaction.objectStore(STORE_VTXOS);
5742
+ if (!vtxosStore.indexNames.contains("script")) {
5743
+ vtxosStore.createIndex("script", "script", { unique: false });
5744
+ }
5745
+ backfillVtxoScripts(transaction);
5746
+ }
5747
+ }
5748
+ function initDatabaseWithIntents(db, oldVersion, transaction) {
5749
+ initDatabase(db, oldVersion, transaction);
5750
+ if (!db.objectStoreNames.contains(STORE_INTENTS)) {
5751
+ const intentsStore = db.createObjectStore(STORE_INTENTS, {
5752
+ keyPath: "intentTxId"
5753
+ });
5754
+ intentsStore.createIndex("intentId", "intentId", { unique: true });
5755
+ intentsStore.createIndex("state", "state", { unique: false });
5756
+ }
5757
+ if (!db.objectStoreNames.contains(STORE_VIRTUAL_TXS)) {
5758
+ db.createObjectStore(STORE_VIRTUAL_TXS, { keyPath: "txid" });
5759
+ }
5760
+ if (!db.objectStoreNames.contains(STORE_VTXO_BRANCHES)) {
5761
+ const branchesStore = db.createObjectStore(STORE_VTXO_BRANCHES, {
5762
+ keyPath: ["vtxoTxid", "vtxoVout", "position"]
5763
+ });
5764
+ branchesStore.createIndex("vtxo", ["vtxoTxid", "vtxoVout"], { unique: false });
5765
+ branchesStore.createIndex("virtualTxid", "virtualTxid", { unique: false });
5766
+ }
5767
+ if (oldVersion === 4 && transaction) {
5768
+ const intentsStore = transaction.objectStore(STORE_INTENTS);
5769
+ if (intentsStore.indexNames.contains("intentId")) {
5770
+ intentsStore.deleteIndex("intentId");
5771
+ }
5772
+ dedupeIntentIds(intentsStore, () => {
5773
+ intentsStore.createIndex("intentId", "intentId", { unique: true });
5774
+ });
5775
+ }
5776
+ }
5777
+ function dedupeIntentIds(store, onComplete) {
5778
+ const seen = /* @__PURE__ */ new Set();
5779
+ const cursorRequest = store.openCursor();
5780
+ cursorRequest.onsuccess = () => {
5781
+ const cursor = cursorRequest.result;
5782
+ if (!cursor) {
5783
+ onComplete();
5784
+ return;
5785
+ }
5786
+ const id = cursor.value.intentId;
5787
+ if (id != null) {
5788
+ if (seen.has(id)) {
5789
+ cursor.delete();
5790
+ } else {
5791
+ seen.add(id);
5792
+ }
5793
+ }
5794
+ cursor.continue();
5795
+ };
5796
+ }
5797
+ function backfillVtxoScripts(transaction) {
5798
+ const store = transaction.objectStore(STORE_VTXOS);
5799
+ const cursorRequest = store.openCursor();
5800
+ cursorRequest.onsuccess = () => {
5801
+ const cursor = cursorRequest.result;
5802
+ if (!cursor) return;
5803
+ const value = cursor.value;
5804
+ if (!value.script) {
5805
+ value.script = scriptFromArkAddress(value.address);
5806
+ cursor.update(value);
5807
+ }
5808
+ cursor.continue();
5809
+ };
5810
+ }
5811
+
5812
+ // src/worker/browser/utils.ts
5813
+ var DEFAULT_DB_NAME = "arkade-service-worker";
5814
+ var DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS = 1e4;
5815
+ function normalizeOptions2(pathOrOptions) {
5816
+ if (typeof pathOrOptions === "string") {
5817
+ return {
5818
+ path: pathOrOptions,
5819
+ activationTimeoutMs: DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS
5820
+ };
5821
+ }
5822
+ return {
5823
+ path: pathOrOptions.path,
5824
+ activationTimeoutMs: pathOrOptions.activationTimeoutMs ?? DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS
5825
+ };
5826
+ }
5827
+ function waitForServiceWorkerReady(timeoutMs) {
5828
+ return new Promise((resolve, reject) => {
5829
+ const timeoutId = setTimeout(() => {
5830
+ reject(new Error(`Service worker activation timed out after ${timeoutMs}ms`));
5831
+ }, timeoutMs);
5832
+ navigator.serviceWorker.ready.then((registration) => {
5833
+ clearTimeout(timeoutId);
5834
+ resolve(registration);
5835
+ }).catch((error) => {
5836
+ clearTimeout(timeoutId);
5837
+ reject(error);
5838
+ });
5839
+ });
5840
+ }
5841
+ async function setupServiceWorker(pathOrOptions) {
5842
+ if (!("serviceWorker" in navigator)) {
5843
+ throw new Error("Service workers are not supported in this browser");
5844
+ }
5845
+ const { path, activationTimeoutMs } = normalizeOptions2(pathOrOptions);
5846
+ const registration = await navigator.serviceWorker.register(path);
5847
+ await registration.update();
5848
+ const serviceWorker = registration.active || registration.waiting || registration.installing;
5849
+ if (!serviceWorker) {
5850
+ throw new Error("Failed to get service worker instance");
5851
+ }
5852
+ if (serviceWorker.state === "activated") {
5853
+ return serviceWorker;
5854
+ }
5855
+ const readyRegistration = await waitForServiceWorkerReady(activationTimeoutMs);
5856
+ if (!readyRegistration.active) {
5857
+ throw new Error("Service worker registration is ready but has no active worker");
5858
+ }
5859
+ return readyRegistration.active;
5860
+ }
5861
+
5862
+ // src/repositories/indexedDB/virtualTxRepository.ts
5863
+ var IndexedDBVirtualTxRepository = class {
5864
+ constructor(dbName = DEFAULT_DB_NAME) {
5865
+ this.dbName = dbName;
5866
+ }
5867
+ version = 1;
5868
+ db = null;
5869
+ async getDB() {
5870
+ if (!this.db)
5871
+ this.db = await openDatabase(this.dbName, INTENT_DB_VERSION, initDatabaseWithIntents);
5872
+ return this.db;
5873
+ }
5874
+ async clear() {
5875
+ const db = await this.getDB();
5876
+ const transaction = db.transaction([STORE_VIRTUAL_TXS, STORE_VTXO_BRANCHES], "readwrite");
5877
+ transaction.objectStore(STORE_VIRTUAL_TXS).clear();
5878
+ transaction.objectStore(STORE_VTXO_BRANCHES).clear();
5879
+ await awaitTransaction(transaction);
5880
+ }
5881
+ async upsertVirtualTxs(txs) {
5882
+ if (txs.length === 0) return;
5883
+ const db = await this.getDB();
5884
+ const merged = /* @__PURE__ */ new Map();
5885
+ for (const tx of txs) {
5886
+ const acc = merged.get(tx.txid);
5887
+ merged.set(
5888
+ tx.txid,
5889
+ acc ? {
5890
+ txid: tx.txid,
5891
+ psbt: tx.psbt ?? acc.psbt,
5892
+ expiresAt: tx.expiresAt ?? acc.expiresAt,
5893
+ type: mergeChainedTxType(tx.type, acc.type)
5894
+ } : tx
5895
+ );
5896
+ }
5897
+ const transaction = db.transaction([STORE_VIRTUAL_TXS], "readwrite");
5898
+ const store = transaction.objectStore(STORE_VIRTUAL_TXS);
5899
+ for (const tx of merged.values()) {
5900
+ const getReq = store.get(tx.txid);
5901
+ getReq.onsuccess = () => {
5902
+ const prev = getReq.result;
5903
+ store.put({
5904
+ txid: tx.txid,
5905
+ psbt: tx.psbt ?? prev?.psbt ?? null,
5906
+ expiresAt: tx.expiresAt ?? prev?.expiresAt ?? null,
5907
+ type: mergeChainedTxType(tx.type, prev?.type)
5908
+ });
5909
+ };
5910
+ }
5911
+ await awaitTransaction(transaction);
5912
+ }
5913
+ async getVirtualTx(txid) {
5914
+ const db = await this.getDB();
5915
+ const store = db.transaction([STORE_VIRTUAL_TXS], "readonly").objectStore(STORE_VIRTUAL_TXS);
5916
+ const r = await promisifyRequest(store.get(txid));
5917
+ return r ?? null;
5918
+ }
5919
+ async setBranch(vtxo, branch) {
5920
+ const db = await this.getDB();
5921
+ const transaction = db.transaction([STORE_VTXO_BRANCHES], "readwrite");
5922
+ const store = transaction.objectStore(STORE_VTXO_BRANCHES);
5923
+ const getAllReq = store.index("vtxo").getAll(IDBKeyRange.only([vtxo.txid, vtxo.vout]));
5924
+ getAllReq.onsuccess = () => {
5925
+ const existing = getAllReq.result;
5926
+ for (const e of existing) store.delete([e.vtxoTxid, e.vtxoVout, e.position]);
5927
+ for (const b of branch) store.put(b);
5928
+ };
5929
+ await awaitTransaction(transaction);
5930
+ }
5931
+ async getBranch(vtxo) {
5932
+ const db = await this.getDB();
5933
+ const transaction = db.transaction([STORE_VTXO_BRANCHES, STORE_VIRTUAL_TXS], "readonly");
5934
+ const branchStore = transaction.objectStore(STORE_VTXO_BRANCHES);
5935
+ const txStore = transaction.objectStore(STORE_VIRTUAL_TXS);
5936
+ const getAllReq = branchStore.index("vtxo").getAll(IDBKeyRange.only([vtxo.txid, vtxo.vout]));
5937
+ const byTxid = /* @__PURE__ */ new Map();
5938
+ let ordered = [];
5939
+ getAllReq.onsuccess = () => {
5940
+ ordered = getAllReq.result.slice().sort((a, b) => a.position - b.position);
5941
+ for (const b of ordered) {
5942
+ const txReq = txStore.get(b.virtualTxid);
5943
+ txReq.onsuccess = () => {
5944
+ const r = txReq.result;
5945
+ if (r) byTxid.set(b.virtualTxid, r);
5946
+ };
5947
+ }
5948
+ };
5949
+ await awaitTransaction(transaction);
5950
+ const out = [];
5951
+ for (const b of ordered) {
5952
+ const tx = byTxid.get(b.virtualTxid);
5953
+ if (tx) out.push(tx);
5954
+ }
5955
+ return out;
5956
+ }
5957
+ async hasBranch(vtxo) {
5958
+ const db = await this.getDB();
5959
+ const vtxoIndex = db.transaction([STORE_VTXO_BRANCHES], "readonly").objectStore(STORE_VTXO_BRANCHES).index("vtxo");
5960
+ const count = await promisifyRequest(
5961
+ vtxoIndex.count(IDBKeyRange.only([vtxo.txid, vtxo.vout]))
5962
+ );
5963
+ return count > 0;
5964
+ }
5965
+ async pruneForSpentVtxo(vtxo) {
5966
+ const db = await this.getDB();
5967
+ const transaction = db.transaction([STORE_VTXO_BRANCHES, STORE_VIRTUAL_TXS], "readwrite");
5968
+ const branches = transaction.objectStore(STORE_VTXO_BRANCHES);
5969
+ const txStore = transaction.objectStore(STORE_VIRTUAL_TXS);
5970
+ const getAllReq = branches.index("vtxo").getAll(IDBKeyRange.only([vtxo.txid, vtxo.vout]));
5971
+ getAllReq.onsuccess = () => {
5972
+ const removed = getAllReq.result;
5973
+ if (removed.length === 0) return;
5974
+ for (const e of removed) branches.delete([e.vtxoTxid, e.vtxoVout, e.position]);
5975
+ for (const e of removed) {
5976
+ const countReq = branches.index("virtualTxid").count(IDBKeyRange.only(e.virtualTxid));
5977
+ countReq.onsuccess = () => {
5978
+ if (countReq.result === 0) txStore.delete(e.virtualTxid);
5979
+ };
5980
+ }
5981
+ };
5982
+ await awaitTransaction(transaction);
5983
+ }
5984
+ async [Symbol.asyncDispose]() {
5985
+ if (!this.db) return;
5986
+ await closeDatabase(this.dbName);
5987
+ this.db = null;
5988
+ }
5989
+ };
5990
+
5991
+ // src/repositories/indexedDB/intentRepository.ts
5992
+ var IndexedDBIntentRepository = class {
5993
+ constructor(dbName = DEFAULT_DB_NAME) {
5994
+ this.dbName = dbName;
5995
+ }
5996
+ version = 1;
5997
+ db = null;
5998
+ async getDB() {
5999
+ if (!this.db)
6000
+ this.db = await openDatabase(this.dbName, INTENT_DB_VERSION, initDatabaseWithIntents);
6001
+ return this.db;
6002
+ }
6003
+ async clear() {
6004
+ const db = await this.getDB();
6005
+ const transaction = db.transaction([STORE_INTENTS], "readwrite");
6006
+ transaction.objectStore(STORE_INTENTS).clear();
6007
+ await awaitTransaction(transaction);
6008
+ }
6009
+ async saveIntent(intent) {
6010
+ const db = await this.getDB();
6011
+ const transaction = db.transaction([STORE_INTENTS], "readwrite");
6012
+ transaction.objectStore(STORE_INTENTS).put({ ...intent, updatedAt: Date.now() });
6013
+ await awaitTransaction(transaction);
6014
+ }
6015
+ async getIntents(filter) {
6016
+ const db = await this.getDB();
6017
+ const store = db.transaction([STORE_INTENTS], "readonly").objectStore(STORE_INTENTS);
6018
+ const all = await promisifyRequest(store.getAll());
6019
+ all.sort((a, b) => a.createdAt - b.createdAt || a.intentTxId.localeCompare(b.intentTxId));
6020
+ const out = filter ? all.filter((i) => intentMatchesFilter(i, filter)) : all;
6021
+ const { skip, end } = intentPageBounds(filter, out.length);
6022
+ return out.slice(skip, end);
6023
+ }
6024
+ async getLockedVtxoOutpoints() {
6025
+ const db = await this.getDB();
6026
+ const store = db.transaction([STORE_INTENTS], "readonly").objectStore(STORE_INTENTS);
6027
+ const all = await promisifyRequest(store.getAll());
6028
+ const out = [];
6029
+ for (const i of all)
6030
+ if (!isTerminalIntentState(i.state)) for (const o of i.intentVtxos) out.push(o);
6031
+ return out;
6032
+ }
6033
+ async [Symbol.asyncDispose]() {
6034
+ if (!this.db) return;
6035
+ await closeDatabase(this.dbName);
6036
+ this.db = null;
6037
+ }
6038
+ };
6039
+
6040
+ // src/contracts/vtxoOwnership.ts
6041
+ function vtxoOutpoint(vtxo) {
6042
+ return `${vtxo.txid}:${vtxo.vout}`;
6043
+ }
6044
+ function isVtxoForScript(vtxo, script) {
6045
+ return !!vtxo.script && vtxo.script === script;
6046
+ }
6047
+ function filterVtxosForScript(vtxos, script) {
6048
+ return vtxos.filter((v) => isVtxoForScript(v, script));
6049
+ }
6050
+ function warnAndFilterVtxosForScript(vtxos, script, context) {
6051
+ const matches = [];
6052
+ const rejected = [];
6053
+ for (const v of vtxos) {
6054
+ if (isVtxoForScript(v, script)) {
6055
+ matches.push(v);
6056
+ } else {
6057
+ rejected.push(`${vtxoOutpoint(v)}(script=${v.script ?? ""})`);
6058
+ }
6059
+ }
6060
+ if (rejected.length > 0) {
6061
+ console.warn(
6062
+ `${context}: dropped ${rejected.length} wrong-script VTXO(s) for script ${script}: ${rejected.join(", ")}`
6063
+ );
6064
+ }
6065
+ return matches;
6066
+ }
6067
+ function validateVtxosForScript(vtxos, script, context) {
6068
+ const mismatches = vtxos.filter((v) => !isVtxoForScript(v, script));
6069
+ if (mismatches.length === 0) return;
6070
+ const detail = mismatches.map((v) => `${vtxoOutpoint(v)}(script=${v.script ?? ""})`).join(", ");
6071
+ throw new Error(
6072
+ `${context}: refusing to persist ${mismatches.length} VTXO(s) whose script does not match ${script}: ${detail}`
6073
+ );
6074
+ }
6075
+ async function getVtxosForContract(repo, contract) {
6076
+ return repo.getVtxosForScript ? repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
6077
+ }
6078
+ async function saveVtxosForContract(repo, contract, vtxos) {
6079
+ if (repo.saveVtxosForScript) {
6080
+ return repo.saveVtxosForScript(
6081
+ { script: contract.script, address: contract.address },
6082
+ vtxos
6083
+ );
6084
+ }
6085
+ validateVtxosForScript(vtxos, contract.script, "saveVtxosForContract");
6086
+ return repo.saveVtxos(contract.address, vtxos);
6087
+ }
6088
+
6089
+ // src/repositories/inMemory/walletRepository.ts
6090
+ var InMemoryWalletRepository = class {
6091
+ version = 1;
6092
+ vtxosByAddress = /* @__PURE__ */ new Map();
6093
+ utxosByAddress = /* @__PURE__ */ new Map();
6094
+ txsByAddress = /* @__PURE__ */ new Map();
6095
+ walletState = null;
6096
+ async getVtxos(address) {
6097
+ return this.vtxosByAddress.get(address) ?? [];
6098
+ }
6099
+ async saveVtxos(address, vtxos) {
6100
+ const existing = this.vtxosByAddress.get(address) ?? [];
6101
+ const next = mergeByKey(existing, vtxos, (item) => `${item.txid}:${item.vout}`);
6102
+ this.vtxosByAddress.set(address, next);
6103
+ }
6104
+ async deleteVtxos(address) {
6105
+ this.vtxosByAddress.delete(address);
6106
+ }
6107
+ async getVtxosForScript(script) {
6108
+ const allMatches = [];
6109
+ for (const bucket of this.vtxosByAddress.values()) {
6110
+ for (const vtxo of bucket) {
6111
+ if (isVtxoForScript(vtxo, script)) {
6112
+ allMatches.push(vtxo);
6113
+ }
6114
+ }
6115
+ }
6116
+ return mergeByKey([], allMatches, (item) => `${item.txid}:${item.vout}`);
6117
+ }
6118
+ async saveVtxosForScript(key, vtxos) {
6119
+ if (!key.address) {
6120
+ throw new Error("InMemoryWalletRepository requires an address");
6121
+ }
6122
+ for (const vtxo of vtxos) {
6123
+ if (!isVtxoForScript(vtxo, key.script)) {
6124
+ throw new Error(
6125
+ `VTXO ${vtxo.txid}:${vtxo.vout} script mismatch: expected ${key.script}, got ${vtxo.script}`
6126
+ );
6127
+ }
6128
+ }
6129
+ return this.saveVtxos(key.address, vtxos);
6130
+ }
6131
+ async deleteVtxosForScript(script) {
6132
+ for (const [address, bucket] of this.vtxosByAddress.entries()) {
6133
+ const next = bucket.filter((v) => !isVtxoForScript(v, script));
6134
+ if (next.length === 0) {
6135
+ this.vtxosByAddress.delete(address);
6136
+ } else {
6137
+ this.vtxosByAddress.set(address, next);
6138
+ }
6139
+ }
6140
+ }
6141
+ async getUtxos(address) {
6142
+ return this.utxosByAddress.get(address) ?? [];
6143
+ }
6144
+ async saveUtxos(address, utxos) {
6145
+ const existing = this.utxosByAddress.get(address) ?? [];
6146
+ const next = mergeByKey(existing, utxos, (item) => `${item.txid}:${item.vout}`);
6147
+ this.utxosByAddress.set(address, next);
6148
+ }
6149
+ async deleteUtxos(address) {
6150
+ this.utxosByAddress.delete(address);
6151
+ }
6152
+ async getTransactionHistory(address) {
6153
+ return this.txsByAddress.get(address) ?? [];
6154
+ }
6155
+ async saveTransactions(address, txs) {
6156
+ const existing = this.txsByAddress.get(address) ?? [];
6157
+ const next = mergeByKey(existing, txs, serializeTxKey);
6158
+ this.txsByAddress.set(address, next);
6159
+ }
6160
+ async deleteTransactions(address) {
6161
+ this.txsByAddress.delete(address);
6162
+ }
6163
+ async getWalletState() {
6164
+ return this.walletState;
6165
+ }
6166
+ async saveWalletState(state) {
6167
+ this.walletState = state;
6168
+ }
6169
+ async clear() {
6170
+ this.vtxosByAddress.clear();
6171
+ this.utxosByAddress.clear();
6172
+ this.txsByAddress.clear();
6173
+ this.walletState = null;
6174
+ }
6175
+ async [Symbol.asyncDispose]() {
6176
+ return;
6177
+ }
6178
+ };
6179
+ function serializeTxKey(tx) {
6180
+ const key = tx.key;
6181
+ return `${key.boardingTxid}:${key.commitmentTxid}:${key.arkTxid}`;
6182
+ }
6183
+ function mergeByKey(existing, incoming, toKey) {
6184
+ const next = /* @__PURE__ */ new Map();
6185
+ existing.forEach((item) => {
6186
+ next.set(toKey(item), item);
6187
+ });
6188
+ incoming.forEach((item) => {
6189
+ next.set(toKey(item), item);
6190
+ });
6191
+ return Array.from(next.values());
6192
+ }
6193
+
6194
+ // src/repositories/inMemory/contractRepository.ts
6195
+ var InMemoryContractRepository = class {
6196
+ version = 1;
6197
+ contractData = /* @__PURE__ */ new Map();
6198
+ collections = /* @__PURE__ */ new Map();
6199
+ contractsByScript = /* @__PURE__ */ new Map();
6200
+ async clear() {
6201
+ this.contractData.clear();
6202
+ this.collections.clear();
6203
+ this.contractsByScript.clear();
6204
+ }
6205
+ // Contract entity management methods
6206
+ async getContracts(filter) {
6207
+ const contracts = this.contractsByScript.values();
6208
+ if (!filter) {
6209
+ return [...contracts];
6210
+ }
6211
+ const matches = (value, criterion) => {
6212
+ if (criterion === void 0) {
6213
+ return true;
6214
+ }
6215
+ return Array.isArray(criterion) ? criterion.includes(value) : value === criterion;
6216
+ };
6217
+ const results = [];
6218
+ for (const contract of contracts) {
6219
+ if (matches(contract.script, filter.script) && matches(contract.state, filter.state) && matches(contract.type, filter.type)) {
6220
+ results.push(contract);
6221
+ }
6222
+ }
6223
+ return results;
6224
+ }
6225
+ async saveContract(contract) {
6226
+ this.contractsByScript.set(contract.script, contract);
5619
6227
  }
5620
- if (oldVersion >= 1 && oldVersion < 3 && transaction) {
5621
- const vtxosStore = transaction.objectStore(STORE_VTXOS);
5622
- if (!vtxosStore.indexNames.contains("script")) {
5623
- vtxosStore.createIndex("script", "script", { unique: false });
5624
- }
5625
- backfillVtxoScripts(transaction);
6228
+ async deleteContract(script) {
6229
+ this.contractsByScript.delete(script);
5626
6230
  }
5627
- }
5628
- function backfillVtxoScripts(transaction) {
5629
- const store = transaction.objectStore(STORE_VTXOS);
5630
- const cursorRequest = store.openCursor();
5631
- cursorRequest.onsuccess = () => {
5632
- const cursor = cursorRequest.result;
5633
- if (!cursor) return;
5634
- const value = cursor.value;
5635
- if (!value.script) {
5636
- value.script = scriptFromArkAddress(value.address);
5637
- cursor.update(value);
5638
- }
5639
- cursor.continue();
5640
- };
5641
- }
6231
+ async [Symbol.asyncDispose]() {
6232
+ return;
6233
+ }
6234
+ };
5642
6235
  var serializeTapLeaf = ([cb, s]) => ({
5643
6236
  cb: base.hex.encode(btcSigner.TaprootControlBlock.encode(cb)),
5644
6237
  s: base.hex.encode(s)
@@ -5705,132 +6298,6 @@ var deserializeTransaction = (o) => ({
5705
6298
  assets: deserializeAssets(o.assets)
5706
6299
  });
5707
6300
 
5708
- // src/repositories/indexedDB/manager.ts
5709
- function getGlobalObject() {
5710
- if (typeof globalThis !== "undefined") {
5711
- if (typeof globalThis.self === "object" && globalThis.self !== null) {
5712
- return { globalObject: globalThis.self };
5713
- }
5714
- if (typeof globalThis.window === "object" && globalThis.window !== null) {
5715
- return { globalObject: globalThis.window };
5716
- }
5717
- return { globalObject: globalThis };
5718
- }
5719
- throw new Error("Global object not found");
5720
- }
5721
- var dbCache = /* @__PURE__ */ new Map();
5722
- var refCounts = /* @__PURE__ */ new Map();
5723
- async function openDatabase(dbName, dbVersion, initDatabase2) {
5724
- const { globalObject } = getGlobalObject();
5725
- if (!globalObject.indexedDB) {
5726
- throw new Error("IndexedDB is not available in this environment");
5727
- }
5728
- const cached = dbCache.get(dbName);
5729
- if (cached) {
5730
- if (cached.version !== dbVersion) {
5731
- throw new Error(
5732
- `Database "${dbName}" already opened with version ${cached.version}; requested ${dbVersion}`
5733
- );
5734
- }
5735
- refCounts.set(dbName, (refCounts.get(dbName) ?? 0) + 1);
5736
- return cached.promise;
5737
- }
5738
- const dbPromise = new Promise((resolve, reject) => {
5739
- const request = globalObject.indexedDB.open(dbName, dbVersion);
5740
- request.onerror = () => {
5741
- dbCache.delete(dbName);
5742
- refCounts.delete(dbName);
5743
- reject(request.error);
5744
- };
5745
- request.onsuccess = () => {
5746
- const db = request.result;
5747
- db.onversionchange = () => {
5748
- db.close();
5749
- dbCache.delete(dbName);
5750
- refCounts.delete(dbName);
5751
- };
5752
- resolve(db);
5753
- };
5754
- request.onupgradeneeded = (event) => {
5755
- const db = request.result;
5756
- initDatabase2(db, event.oldVersion, request.transaction);
5757
- };
5758
- request.onblocked = () => {
5759
- console.warn("Database upgrade blocked - close other tabs/connections");
5760
- };
5761
- });
5762
- dbCache.set(dbName, { version: dbVersion, promise: dbPromise });
5763
- refCounts.set(dbName, 1);
5764
- return dbPromise;
5765
- }
5766
- async function closeDatabase(dbName) {
5767
- const cachedEntry = dbCache.get(dbName);
5768
- if (!cachedEntry) return false;
5769
- const count = (refCounts.get(dbName) ?? 1) - 1;
5770
- if (count > 0) {
5771
- refCounts.set(dbName, count);
5772
- return false;
5773
- }
5774
- refCounts.delete(dbName);
5775
- dbCache.delete(dbName);
5776
- try {
5777
- const db = await cachedEntry.promise;
5778
- db.close();
5779
- } catch {
5780
- }
5781
- return true;
5782
- }
5783
-
5784
- // src/worker/browser/utils.ts
5785
- var DEFAULT_DB_NAME = "arkade-service-worker";
5786
- var DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS = 1e4;
5787
- function normalizeOptions2(pathOrOptions) {
5788
- if (typeof pathOrOptions === "string") {
5789
- return {
5790
- path: pathOrOptions,
5791
- activationTimeoutMs: DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS
5792
- };
5793
- }
5794
- return {
5795
- path: pathOrOptions.path,
5796
- activationTimeoutMs: pathOrOptions.activationTimeoutMs ?? DEFAULT_SERVICE_WORKER_ACTIVATION_TIMEOUT_MS
5797
- };
5798
- }
5799
- function waitForServiceWorkerReady(timeoutMs) {
5800
- return new Promise((resolve, reject) => {
5801
- const timeoutId = setTimeout(() => {
5802
- reject(new Error(`Service worker activation timed out after ${timeoutMs}ms`));
5803
- }, timeoutMs);
5804
- navigator.serviceWorker.ready.then((registration) => {
5805
- clearTimeout(timeoutId);
5806
- resolve(registration);
5807
- }).catch((error) => {
5808
- clearTimeout(timeoutId);
5809
- reject(error);
5810
- });
5811
- });
5812
- }
5813
- async function setupServiceWorker(pathOrOptions) {
5814
- if (!("serviceWorker" in navigator)) {
5815
- throw new Error("Service workers are not supported in this browser");
5816
- }
5817
- const { path, activationTimeoutMs } = normalizeOptions2(pathOrOptions);
5818
- const registration = await navigator.serviceWorker.register(path);
5819
- await registration.update();
5820
- const serviceWorker = registration.active || registration.waiting || registration.installing;
5821
- if (!serviceWorker) {
5822
- throw new Error("Failed to get service worker instance");
5823
- }
5824
- if (serviceWorker.state === "activated") {
5825
- return serviceWorker;
5826
- }
5827
- const readyRegistration = await waitForServiceWorkerReady(activationTimeoutMs);
5828
- if (!readyRegistration.active) {
5829
- throw new Error("Service worker registration is ready but has no active worker");
5830
- }
5831
- return readyRegistration.active;
5832
- }
5833
-
5834
6301
  // src/repositories/indexedDB/contractRepository.ts
5835
6302
  var IndexedDBContractRepository = class {
5836
6303
  constructor(dbName = DEFAULT_DB_NAME) {
@@ -6987,7 +7454,7 @@ var ContractWatcher = class {
6987
7454
  this.connectionState = "connected";
6988
7455
  this.reconnectAttempts = 0;
6989
7456
  this.listenLoop().catch((e) => {
6990
- if (chunkALISWEQ5_cjs.isEventSourceError(e)) {
7457
+ if (chunk3AQNLQPM_cjs.isEventSourceError(e)) {
6991
7458
  console.debug("ContractWatcher subscription disconnected; reconnecting");
6992
7459
  } else {
6993
7460
  console.error(e);
@@ -7138,7 +7605,7 @@ var ContractWatcher = class {
7138
7605
  this.subscriptionId
7139
7606
  );
7140
7607
  } catch (error) {
7141
- const isStale = error instanceof Error && /subscription\s+\S+\s+not\s+found/i.test(error.message);
7608
+ const isStale = error instanceof Error && /subscription\b.*\bnot\s+found/i.test(error.message);
7142
7609
  if (this.subscriptionId && isStale) {
7143
7610
  this.subscriptionId = void 0;
7144
7611
  this.subscriptionId = await this.config.indexerProvider.subscribeForScripts(scriptsToWatch);
@@ -7268,6 +7735,89 @@ var ContractWatcher = class {
7268
7735
  }
7269
7736
  };
7270
7737
 
7738
+ // src/wallet/intentReconciliation.ts
7739
+ var NON_TERMINAL_INTENT_STATES = ALL_INTENT_STATES.filter(
7740
+ (s) => !isTerminalIntentState(s)
7741
+ );
7742
+ function isConsumed(vtxo) {
7743
+ return vtxo !== void 0 && (vtxo.isSpent === true || vtxo.settledBy !== void 0);
7744
+ }
7745
+ async function classifyIntent(intent, vtxosByOutpoint, now) {
7746
+ if (isTerminalIntentState(intent.state)) return void 0;
7747
+ const inputs = intent.intentVtxos;
7748
+ const consumed = inputs.map((o) => vtxosByOutpoint.get(outpointKey(o)));
7749
+ if (inputs.length > 0 && consumed.every(isConsumed)) {
7750
+ const commitmentTransactionId = intent.commitmentTransactionId ?? consumed.map((v) => v?.settledBy).find((s) => !!s);
7751
+ return terminal(intent, "batch_succeeded", now, { commitmentTransactionId });
7752
+ }
7753
+ if (intent.state === "waiting_to_submit") {
7754
+ return terminal(intent, "cancelled", now, {
7755
+ cancellationReason: "reconciliation: intent was never submitted before restart"
7756
+ });
7757
+ }
7758
+ if (intent.validUntil !== void 0 && intent.validUntil < now) {
7759
+ return terminal(intent, "cancelled", now, {
7760
+ cancellationReason: "reconciliation: intent expired"
7761
+ });
7762
+ }
7763
+ return void 0;
7764
+ }
7765
+ async function reconcileIntents(deps) {
7766
+ const now = deps.now ?? Date.now;
7767
+ let intents;
7768
+ try {
7769
+ intents = await deps.intentRepository.getIntents({
7770
+ states: [...NON_TERMINAL_INTENT_STATES]
7771
+ });
7772
+ } catch (e) {
7773
+ console.error("reconcileIntents: failed to read non-terminal intents", e);
7774
+ return;
7775
+ }
7776
+ if (intents.length === 0) return;
7777
+ const outpoints = dedupeOutpoints(intents.flatMap((i) => i.intentVtxos));
7778
+ let vtxosByOutpoint = /* @__PURE__ */ new Map();
7779
+ if (outpoints.length > 0) {
7780
+ try {
7781
+ const { vtxos } = await deps.indexerProvider.getVtxos({ outpoints });
7782
+ vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
7783
+ } catch (e) {
7784
+ console.error("reconcileIntents: failed to fetch input VTXO state", e);
7785
+ return;
7786
+ }
7787
+ }
7788
+ const nowMs = now();
7789
+ for (const intent of intents) {
7790
+ try {
7791
+ const next = await classifyIntent(intent, vtxosByOutpoint, nowMs);
7792
+ if (!next) continue;
7793
+ const [fresh] = await deps.intentRepository.getIntents({
7794
+ intentTxIds: [intent.intentTxId]
7795
+ });
7796
+ if (!fresh || fresh.state !== intent.state) continue;
7797
+ await deps.intentRepository.saveIntent(next);
7798
+ } catch (e) {
7799
+ console.error(`reconcileIntents: failed to reconcile intent ${intent.intentTxId}`, e);
7800
+ }
7801
+ }
7802
+ }
7803
+ function terminal(intent, state, now, patch) {
7804
+ return { ...intent, ...patch, state, updatedAt: now };
7805
+ }
7806
+ function outpointKey(o) {
7807
+ return `${o.txid}:${o.vout}`;
7808
+ }
7809
+ function dedupeOutpoints(outpoints) {
7810
+ const seen = /* @__PURE__ */ new Set();
7811
+ const out = [];
7812
+ for (const o of outpoints) {
7813
+ const k = outpointKey(o);
7814
+ if (seen.has(k)) continue;
7815
+ seen.add(k);
7816
+ out.push(o);
7817
+ }
7818
+ return out;
7819
+ }
7820
+
7271
7821
  // src/utils/syncCursors.ts
7272
7822
  var SAFETY_LAG_MS = 3e4;
7273
7823
  var OVERLAP_MS = 24 * 60 * 60 * 1e3;
@@ -7391,6 +7941,26 @@ var ContractManager = class _ContractManager {
7391
7941
  if (watched.length > 0) {
7392
7942
  await this.reconcilePendingFrontier(watched);
7393
7943
  }
7944
+ await this.reconcileStaleIntents();
7945
+ }
7946
+ /**
7947
+ * Crash-recovery for persisted settlement intents: reconcile any
7948
+ * non-terminal intent left behind by a mid-settle crash against
7949
+ * authoritative indexer state (see {@link reconcileIntents}). Runs on the
7950
+ * online sync path only — boot and subscription reconnect — never from a
7951
+ * wallet read API. Best-effort: intent recovery is not a sync invariant, so
7952
+ * a failure is logged and sync continues. No-op without an intent store.
7953
+ */
7954
+ async reconcileStaleIntents() {
7955
+ if (!this.config.intentRepository) return;
7956
+ try {
7957
+ await reconcileIntents({
7958
+ intentRepository: this.config.intentRepository,
7959
+ indexerProvider: this.config.indexerProvider
7960
+ });
7961
+ } catch (e) {
7962
+ console.error("ContractManager: intent reconciliation failed", e);
7963
+ }
7394
7964
  }
7395
7965
  /**
7396
7966
  * Create and register a new contract.
@@ -8761,6 +9331,22 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
8761
9331
  function hasToReadonly(identity) {
8762
9332
  return typeof identity === "object" && identity !== null && "toReadonly" in identity && typeof identity.toReadonly === "function";
8763
9333
  }
9334
+ function excludeLockedOutpoints(vtxos, locked) {
9335
+ if (locked.length === 0) return vtxos;
9336
+ const lockedKeys = new Set(locked.map((o) => `${o.txid}:${o.vout}`));
9337
+ return vtxos.filter((v) => !lockedKeys.has(`${v.txid}:${v.vout}`));
9338
+ }
9339
+ async function spendableVtxosExcludingLocked(vtxos, intentRepository) {
9340
+ if (!intentRepository) return vtxos;
9341
+ let locked;
9342
+ try {
9343
+ locked = await intentRepository.getLockedVtxoOutpoints();
9344
+ } catch (e) {
9345
+ console.error("getLockedVtxoOutpoints failed; reporting unfiltered balance", e);
9346
+ return vtxos;
9347
+ }
9348
+ return excludeLockedOutpoints(vtxos, locked);
9349
+ }
8764
9350
  var ReadonlyWallet = class _ReadonlyWallet {
8765
9351
  constructor(identity, network, onchainProvider, indexerProvider, arkServerPublicKey, offchainTapscript, boardingTapscript, dustAmount, walletRepository, contractRepository, delegateProvider, watcherConfig, walletContractTimelocks) {
8766
9352
  this.identity = identity;
@@ -8791,6 +9377,20 @@ var ReadonlyWallet = class _ReadonlyWallet {
8791
9377
  _contractManager;
8792
9378
  _contractManagerInitializing;
8793
9379
  watcherConfig;
9380
+ /**
9381
+ * Opt-in intent-lifecycle repository. Assigned by the `create()`
9382
+ * factories from `config.storage.intentRepository`; `undefined` ⇒ all
9383
+ * intent-persistence code paths are no-ops (default behaviour unchanged).
9384
+ */
9385
+ intentRepository;
9386
+ /**
9387
+ * **Experimental / inert.** Opt-in virtual-tx / exit-branch repository,
9388
+ * exposed so callers can pass it to {@link Unroll.Session.create} as a
9389
+ * best-effort raw-tx cache. Assigned by `create()` from
9390
+ * `config.storage.virtualTxRepository`. Normal sync never writes it
9391
+ * (ContractManager isn't given it); `undefined` ⇒ no-op.
9392
+ */
9393
+ virtualTxRepository;
8794
9394
  _assetManager;
8795
9395
  walletContractTimelocks;
8796
9396
  // Outpoints ("txid:vout") committed to an in-flight settle/send. Filtered
@@ -8848,9 +9448,12 @@ var ReadonlyWallet = class _ReadonlyWallet {
8848
9448
  _deprecatedSigners = /* @__PURE__ */ new Map();
8849
9449
  /**
8850
9450
  * Refresh the cached deprecated-signer set from a fresh server-info
8851
- * snapshot. Called by the create() factories at construction and by the
8852
- * server-info-change handler mid-session. Lenient: a malformed deprecated
8853
- * entry is skipped, never fatal to wallet creation.
9451
+ * snapshot. Called by the create() factories at construction, by the
9452
+ * server-info-change handler mid-session, and by the deprecated-signer
9453
+ * migration pass (`VtxoManager.migrateDeprecatedSignerVtxos`). This set feeds
9454
+ * {@link pendingRecoveryOutpoints}, which drops EXPIRED (past-cutoff)
9455
+ * deprecated-signer VTXOs from the wallet's own coin selection. Lenient: a
9456
+ * malformed deprecated entry is skipped, never fatal to wallet creation.
8854
9457
  */
8855
9458
  refreshDeprecatedSigners(info) {
8856
9459
  const next = /* @__PURE__ */ new Map();
@@ -8945,7 +9548,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
8945
9548
  */
8946
9549
  static async setupWalletConfig(config, pubKey) {
8947
9550
  const arkadeServerUrl = getArkadeServerUrl(config);
8948
- const arkProvider = config.arkProvider || new chunkALISWEQ5_cjs.RestArkProvider(arkadeServerUrl);
9551
+ const arkProvider = config.arkProvider || new chunk3AQNLQPM_cjs.RestArkProvider(arkadeServerUrl);
8949
9552
  let indexerProvider = config.indexerProvider;
8950
9553
  if (!indexerProvider) {
8951
9554
  let indexerUrl = config.indexerUrl;
@@ -8962,7 +9565,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
8962
9565
  indexerUrl = arkadeServerUrl;
8963
9566
  }
8964
9567
  }
8965
- indexerProvider = new chunkALISWEQ5_cjs.RestIndexerProvider(indexerUrl);
9568
+ indexerProvider = new chunk3AQNLQPM_cjs.RestIndexerProvider(indexerUrl);
8966
9569
  }
8967
9570
  const info = await arkProvider.getInfo();
8968
9571
  const network = chunkHXDZ2QTW_cjs.getNetwork(info.network);
@@ -9066,6 +9669,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
9066
9669
  config.watcherConfig,
9067
9670
  setup.walletContractTimelocks
9068
9671
  );
9672
+ wallet.intentRepository = config.storage?.intentRepository;
9673
+ wallet.virtualTxRepository = config.storage?.virtualTxRepository;
9069
9674
  wallet.refreshDeprecatedSigners(setup.info);
9070
9675
  return wallet;
9071
9676
  }
@@ -9097,6 +9702,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
9097
9702
  this.pendingRecoveryOutpoints()
9098
9703
  ]);
9099
9704
  const isPendingRecovery = (coin) => pendingOutpoints.has(`${coin.txid}:${coin.vout}`);
9705
+ const unlockedVtxos = await spendableVtxosExcludingLocked(vtxos, this.intentRepository);
9100
9706
  let confirmed = 0;
9101
9707
  let unconfirmed = 0;
9102
9708
  for (const utxo of boardingUtxos) {
@@ -9106,14 +9712,15 @@ var ReadonlyWallet = class _ReadonlyWallet {
9106
9712
  unconfirmed += utxo.value;
9107
9713
  }
9108
9714
  }
9109
- let settled = 0;
9110
- let preconfirmed = 0;
9111
9715
  let recoverable = 0;
9112
9716
  let pendingRecovery = 0;
9113
- settled = vtxos.filter((coin) => coin.virtualStatus.state === "settled" && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
9114
- preconfirmed = vtxos.filter(
9717
+ const settled = vtxos.filter((coin) => coin.virtualStatus.state === "settled" && !isPendingRecovery(coin)).reduce((sum, coin) => sum + coin.value, 0);
9718
+ const preconfirmed = vtxos.filter(
9115
9719
  (coin) => coin.virtualStatus.state === "preconfirmed" && !isPendingRecovery(coin)
9116
9720
  ).reduce((sum, coin) => sum + coin.value, 0);
9721
+ const available = unlockedVtxos.filter(
9722
+ (coin) => (coin.virtualStatus.state === "settled" || coin.virtualStatus.state === "preconfirmed") && !isPendingRecovery(coin)
9723
+ ).reduce((sum, coin) => sum + coin.value, 0);
9117
9724
  recoverable = vtxos.filter((coin) => isSpendable(coin) && coin.virtualStatus.state === "swept").reduce((sum, coin) => sum + coin.value, 0);
9118
9725
  pendingRecovery = vtxos.filter(isPendingRecovery).reduce((sum, coin) => sum + coin.value, 0);
9119
9726
  const totalBoarding = confirmed + unconfirmed;
@@ -9140,7 +9747,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
9140
9747
  },
9141
9748
  settled,
9142
9749
  preconfirmed,
9143
- available: settled + preconfirmed,
9750
+ available,
9144
9751
  recoverable,
9145
9752
  pendingRecovery,
9146
9753
  total: totalBoarding + totalOffchain,
@@ -9617,6 +10224,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
9617
10224
  indexerProvider: this.indexerProvider,
9618
10225
  contractRepository: this.contractRepository,
9619
10226
  walletRepository: this.walletRepository,
10227
+ intentRepository: this.intentRepository,
9620
10228
  watcherConfig: this.watcherConfig
9621
10229
  });
9622
10230
  const baselinePubkey = await this.identity.xOnlyPublicKey();
@@ -10310,6 +10918,8 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10310
10918
  wallet.setBoardingTapscriptForRotation(resolvedBoarding);
10311
10919
  }
10312
10920
  }
10921
+ wallet.intentRepository = config.storage?.intentRepository;
10922
+ wallet.virtualTxRepository = config.storage?.virtualTxRepository;
10313
10923
  await wallet.getVtxoManager();
10314
10924
  return wallet;
10315
10925
  }
@@ -10589,12 +11199,26 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10589
11199
  ),
10590
11200
  this.makeDeleteIntentSignature(params.inputs)
10591
11201
  ]);
11202
+ let intentTxId;
11203
+ try {
11204
+ intentTxId = btcSigner.Transaction.fromPSBT(base.base64.decode(intent.proof)).id;
11205
+ } catch {
11206
+ intentTxId = params.inputs.map((i) => `${i.txid}:${i.vout}`).sort().join("|");
11207
+ }
11208
+ await this.persistIntentSnapshot(
11209
+ intentTxId,
11210
+ "waiting_to_submit",
11211
+ intent,
11212
+ deleteIntent,
11213
+ params.inputs
11214
+ );
10592
11215
  const topics = [
10593
11216
  ...signingPublicKeys,
10594
11217
  ...params.inputs.map((input) => `${input.txid}:${input.vout}`)
10595
11218
  ];
10596
11219
  const abortController = new AbortController();
10597
11220
  let stream;
11221
+ let committedTxid;
10598
11222
  this._addPendingSpends(params.inputs);
10599
11223
  try {
10600
11224
  stream = this.arkProvider.getEventStream(abortController.signal, topics);
@@ -10609,16 +11233,43 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10609
11233
  yield* stream;
10610
11234
  })();
10611
11235
  const intentId = await this.safeRegisterIntent(intent, params.inputs);
10612
- const handler = this.createBatchHandler(intentId, params.inputs, recipients, session);
11236
+ await this.persistIntentSnapshot(
11237
+ intentTxId,
11238
+ "waiting_for_batch",
11239
+ intent,
11240
+ deleteIntent,
11241
+ params.inputs,
11242
+ { intentId }
11243
+ );
11244
+ const handler = wrapHandlerWithIntentPersistence(
11245
+ this.createBatchHandler(intentId, params.inputs, recipients, session),
11246
+ { intentRepository: this.intentRepository, intentTxId }
11247
+ );
10613
11248
  const commitmentTxid = await exports.Batch.join(primedStream, handler, {
10614
11249
  abortController,
10615
11250
  skipVtxoTreeSigning: !hasOffchainOutputs,
10616
- eventCallback: eventCallback ? (event) => Promise.resolve(eventCallback(event)) : void 0
11251
+ // async so a synchronous throw becomes a rejection Batch.join
11252
+ // swallows, keeping the observational callback off the stream path.
11253
+ eventCallback: eventCallback && (async (event) => {
11254
+ await eventCallback(event);
11255
+ })
10617
11256
  });
11257
+ committedTxid = commitmentTxid;
10618
11258
  await this.updateDbAfterSettle(params.inputs, commitmentTxid);
10619
11259
  await this.maybeRotateBoardingAfterBoard(params.inputs);
10620
11260
  return commitmentTxid;
10621
11261
  } catch (error) {
11262
+ if (committedTxid !== void 0) {
11263
+ await this.persistIntentSnapshot(
11264
+ intentTxId,
11265
+ "batch_succeeded",
11266
+ intent,
11267
+ deleteIntent,
11268
+ params.inputs,
11269
+ { commitmentTransactionId: committedTxid }
11270
+ );
11271
+ throw error;
11272
+ }
10622
11273
  const inputIds = params.inputs.map((i) => `${i.txid}:${i.vout}`).join(",");
10623
11274
  await this.arkProvider.deleteIntent(deleteIntent).catch((e) => {
10624
11275
  console.warn(
@@ -10626,6 +11277,16 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10626
11277
  e
10627
11278
  );
10628
11279
  });
11280
+ await this.persistIntentSnapshot(
11281
+ intentTxId,
11282
+ "cancelled",
11283
+ intent,
11284
+ deleteIntent,
11285
+ params.inputs,
11286
+ {
11287
+ cancellationReason: error instanceof Error ? error.message : String(error)
11288
+ }
11289
+ );
10629
11290
  throw error;
10630
11291
  } finally {
10631
11292
  this._removePendingSpends(params.inputs);
@@ -10900,6 +11561,42 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10900
11561
  }
10901
11562
  return jobs;
10902
11563
  }
11564
+ /**
11565
+ * Best-effort upsert of the current settlement intent into the optional
11566
+ * {@link intentRepository}. Never throws into the settle path — intent
11567
+ * persistence is observational and must not break money flow. Preserves
11568
+ * fields already written by the event reducer (state-event ordering).
11569
+ */
11570
+ async persistIntentSnapshot(intentTxId, state, intent, deleteIntent, inputs, patch) {
11571
+ const repo = this.intentRepository;
11572
+ if (!repo) return;
11573
+ try {
11574
+ const now = Date.now();
11575
+ const existing = (await repo.getIntents({ intentTxIds: [intentTxId] }))[0];
11576
+ if (existing && isTerminalIntentState(existing.state)) {
11577
+ return;
11578
+ }
11579
+ await repo.saveIntent({
11580
+ ...existing ?? {},
11581
+ intentTxId,
11582
+ registerProof: intent.proof,
11583
+ registerProofMessage: chunk3AQNLQPM_cjs.Intent.encodeMessage(intent.message),
11584
+ deleteProof: deleteIntent.proof,
11585
+ deleteProofMessage: chunk3AQNLQPM_cjs.Intent.encodeMessage(deleteIntent.message),
11586
+ intentVtxos: inputs.map((i) => ({
11587
+ txid: i.txid,
11588
+ vout: i.vout
11589
+ })),
11590
+ partialForfeits: existing?.partialForfeits ?? [],
11591
+ createdAt: existing?.createdAt ?? now,
11592
+ updatedAt: now,
11593
+ state,
11594
+ ...patch
11595
+ });
11596
+ } catch (e) {
11597
+ console.error(`Failed to persist intent ${intentTxId} (state=${state})`, e);
11598
+ }
11599
+ }
10903
11600
  /**
10904
11601
  * @internal Sign an on-chain boarding exit / sweep transaction, routing
10905
11602
  * each input to the correct key by its `witnessUtxo.script`: the identity
@@ -10917,7 +11614,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10917
11614
  try {
10918
11615
  return await this.arkProvider.registerIntent(intent);
10919
11616
  } catch (error) {
10920
- if (error instanceof chunkALISWEQ5_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
11617
+ if (error instanceof chunk3AQNLQPM_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
10921
11618
  const deleteIntent = await this.makeDeleteIntentSignature(inputs);
10922
11619
  await this.arkProvider.deleteIntent(deleteIntent);
10923
11620
  return this.arkProvider.registerIntent(intent);
@@ -10933,7 +11630,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10933
11630
  expire_at: 0,
10934
11631
  cosigners_public_keys: cosignerPubKeys
10935
11632
  };
10936
- const proof = chunkALISWEQ5_cjs.Intent.create(message, coins, outputs);
11633
+ const proof = chunk3AQNLQPM_cjs.Intent.create(message, coins, outputs);
10937
11634
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
10938
11635
  return {
10939
11636
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -10945,7 +11642,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10945
11642
  type: "delete",
10946
11643
  expire_at: 0
10947
11644
  };
10948
- const proof = chunkALISWEQ5_cjs.Intent.create(message, coins, []);
11645
+ const proof = chunk3AQNLQPM_cjs.Intent.create(message, coins, []);
10949
11646
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
10950
11647
  return {
10951
11648
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -10957,7 +11654,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
10957
11654
  type: "get-pending-tx",
10958
11655
  expire_at: 0
10959
11656
  };
10960
- const proof = chunkALISWEQ5_cjs.Intent.create(message, coins, []);
11657
+ const proof = chunk3AQNLQPM_cjs.Intent.create(message, coins, []);
10961
11658
  const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
10962
11659
  return {
10963
11660
  proof: base.base64.encode(signedProof.toPSBT()),
@@ -11915,7 +12612,7 @@ var MessageBus = class {
11915
12612
  this.initialized = true;
11916
12613
  }
11917
12614
  async buildServices(config) {
11918
- const arkProvider = new chunkALISWEQ5_cjs.RestArkProvider(config.arkServer.url);
12615
+ const arkProvider = new chunk3AQNLQPM_cjs.RestArkProvider(config.arkServer.url);
11919
12616
  const storage = {
11920
12617
  walletRepository: this.walletRepository,
11921
12618
  contractRepository: this.contractRepository
@@ -13072,7 +13769,7 @@ var WalletMessageHandler = class {
13072
13769
  // Wallet methods
13073
13770
  async handleInitWallet({ payload }) {
13074
13771
  const { arkServerUrl } = payload;
13075
- this.indexerProvider = new chunkALISWEQ5_cjs.RestIndexerProvider(arkServerUrl);
13772
+ this.indexerProvider = new chunk3AQNLQPM_cjs.RestIndexerProvider(arkServerUrl);
13076
13773
  await this.onWalletInitialized();
13077
13774
  }
13078
13775
  async handleGetBalance() {
@@ -14879,7 +15576,7 @@ var OnchainWallet = class _OnchainWallet {
14879
15576
  if (!inputs) {
14880
15577
  throw new Error("Fee estimation failed");
14881
15578
  }
14882
- let tx = new chunkALISWEQ5_cjs.Transaction();
15579
+ let tx = new chunk3AQNLQPM_cjs.Transaction();
14883
15580
  for (const input of inputs) {
14884
15581
  tx.addInput({
14885
15582
  txid: input.txid,
@@ -14910,7 +15607,7 @@ var OnchainWallet = class _OnchainWallet {
14910
15607
  */
14911
15608
  async bumpP2A(parent) {
14912
15609
  const parentVsize = parent.vsize;
14913
- let child = new chunkALISWEQ5_cjs.Transaction({
15610
+ let child = new chunk3AQNLQPM_cjs.Transaction({
14914
15611
  version: 3,
14915
15612
  allowLegacyWitnessUtxo: true
14916
15613
  });
@@ -15676,7 +16373,7 @@ exports.BIP322 = void 0;
15676
16373
  async function sign2(message, identity, network) {
15677
16374
  const xOnlyPubKey = await identity.xOnlyPublicKey();
15678
16375
  const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
15679
- const toSpend = chunkALISWEQ5_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
16376
+ const toSpend = chunk3AQNLQPM_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
15680
16377
  const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
15681
16378
  const signed = await identity.sign(toSign, [0]);
15682
16379
  signed.finalizeIdx(0);
@@ -15734,7 +16431,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
15734
16431
  if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
15735
16432
  return false;
15736
16433
  }
15737
- const toSpend = chunkALISWEQ5_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
16434
+ const toSpend = chunk3AQNLQPM_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
15738
16435
  const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
15739
16436
  const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
15740
16437
  const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
@@ -15755,7 +16452,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
15755
16452
  }
15756
16453
  const sighashType = sigWithHash[sigWithHash.length - 1];
15757
16454
  const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
15758
- const toSpend = chunkALISWEQ5_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
16455
+ const toSpend = chunk3AQNLQPM_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
15759
16456
  const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
15760
16457
  const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
15761
16458
  const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
@@ -15808,7 +16505,7 @@ function encodeCompactSize(n) {
15808
16505
  return buf;
15809
16506
  }
15810
16507
  function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
15811
- const tx = new chunkALISWEQ5_cjs.Transaction({ version: 0 });
16508
+ const tx = new chunk3AQNLQPM_cjs.Transaction({ version: 0 });
15812
16509
  tx.addInput({
15813
16510
  txid: toSpend.id,
15814
16511
  index: 0,
@@ -15822,12 +16519,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
15822
16519
  });
15823
16520
  tx.addOutput({
15824
16521
  amount: 0n,
15825
- script: chunkALISWEQ5_cjs.OP_RETURN_EMPTY_PKSCRIPT
16522
+ script: chunk3AQNLQPM_cjs.OP_RETURN_EMPTY_PKSCRIPT
15826
16523
  });
15827
16524
  return tx;
15828
16525
  }
15829
16526
  function craftBIP322ToSignSimple(toSpend, pkScript) {
15830
- const tx = new chunkALISWEQ5_cjs.Transaction({ version: 0 });
16527
+ const tx = new chunk3AQNLQPM_cjs.Transaction({ version: 0 });
15831
16528
  tx.addInput({
15832
16529
  txid: toSpend.id,
15833
16530
  index: 0,
@@ -15839,10 +16536,24 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
15839
16536
  });
15840
16537
  tx.addOutput({
15841
16538
  amount: 0n,
15842
- script: chunkALISWEQ5_cjs.OP_RETURN_EMPTY_PKSCRIPT
16539
+ script: chunk3AQNLQPM_cjs.OP_RETURN_EMPTY_PKSCRIPT
15843
16540
  });
15844
16541
  return tx;
15845
16542
  }
16543
+ function chainTxTypeToChainedExit(t) {
16544
+ switch (t) {
16545
+ case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
16546
+ return 1 /* Commitment */;
16547
+ case "INDEXER_CHAINED_TX_TYPE_ARK" /* ARK */:
16548
+ return 2 /* Ark */;
16549
+ case "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */:
16550
+ return 3 /* Tree */;
16551
+ case "INDEXER_CHAINED_TX_TYPE_CHECKPOINT" /* CHECKPOINT */:
16552
+ return 4 /* Checkpoint */;
16553
+ default:
16554
+ return 0 /* Unspecified */;
16555
+ }
16556
+ }
15846
16557
  exports.Unroll = void 0;
15847
16558
  ((Unroll2) => {
15848
16559
  ((StepType2) => {
@@ -15852,16 +16563,54 @@ exports.Unroll = void 0;
15852
16563
  })(Unroll2.StepType || (Unroll2.StepType = {}));
15853
16564
  class Session2 {
15854
16565
  /** Create an unroll session from a virtual output outpoint and its dependency chain. */
15855
- constructor(toUnroll, bumper, explorer, indexer) {
16566
+ constructor(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
15856
16567
  this.toUnroll = toUnroll;
15857
16568
  this.bumper = bumper;
15858
16569
  this.explorer = explorer;
15859
16570
  this.indexer = indexer;
16571
+ this.virtualTxRepository = virtualTxRepository;
15860
16572
  }
15861
16573
  /** Create an unroll session by loading the virtual output chain from the indexer. */
15862
- static async create(toUnroll, bumper, explorer, indexer) {
16574
+ static async create(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
15863
16575
  const { chain } = await indexer.getVtxoChain(toUnroll);
15864
- return new Session2({ ...toUnroll, chain }, bumper, explorer, indexer);
16576
+ return new Session2(
16577
+ { ...toUnroll, chain },
16578
+ bumper,
16579
+ explorer,
16580
+ indexer,
16581
+ virtualTxRepository
16582
+ );
16583
+ }
16584
+ /**
16585
+ * Resolve a chain tx's raw PSBT (base64). Repo first when configured;
16586
+ * indexer on a miss, then best-effort cached so a later exit doesn't
16587
+ * re-fetch. Never throws from the cache
16588
+ * write — exit correctness must not depend on persistence.
16589
+ */
16590
+ async resolveVirtualTxBase64(next) {
16591
+ const repo = this.virtualTxRepository;
16592
+ if (repo) {
16593
+ try {
16594
+ const stored = await repo.getVirtualTx(next.txid);
16595
+ if (stored?.psbt) return stored.psbt;
16596
+ } catch {
16597
+ }
16598
+ }
16599
+ const fetched = await this.indexer.getVirtualTxs([next.txid]);
16600
+ const psbt = fetched.txs[0];
16601
+ if (psbt && repo) {
16602
+ const cached = {
16603
+ txid: next.txid,
16604
+ psbt,
16605
+ expiresAt: null,
16606
+ type: chainTxTypeToChainedExit(next.type)
16607
+ };
16608
+ try {
16609
+ await repo.upsertVirtualTxs([cached]);
16610
+ } catch {
16611
+ }
16612
+ }
16613
+ return psbt;
15865
16614
  }
15866
16615
  /**
15867
16616
  * Get the next step to be executed
@@ -15896,11 +16645,11 @@ exports.Unroll = void 0;
15896
16645
  do: () => Promise.resolve()
15897
16646
  };
15898
16647
  }
15899
- const virtualTxs = await this.indexer.getVirtualTxs([nextTxToBroadcast.txid]);
15900
- if (virtualTxs.txs.length === 0) {
16648
+ const virtualTxBase64 = await this.resolveVirtualTxBase64(nextTxToBroadcast);
16649
+ if (!virtualTxBase64) {
15901
16650
  throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
15902
16651
  }
15903
- const tx = chunkALISWEQ5_cjs.Transaction.fromPSBT(base.base64.decode(virtualTxs.txs[0]));
16652
+ const tx = chunk3AQNLQPM_cjs.Transaction.fromPSBT(base.base64.decode(virtualTxBase64));
15904
16653
  if (nextTxToBroadcast.type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
15905
16654
  const input = tx.getInput(0);
15906
16655
  if (!input) {
@@ -16000,7 +16749,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
16000
16749
  btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
16001
16750
  );
16002
16751
  }
16003
- const tx = new chunkALISWEQ5_cjs.Transaction({ version: 2 });
16752
+ const tx = new chunk3AQNLQPM_cjs.Transaction({ version: 2 });
16004
16753
  for (const input of inputs) {
16005
16754
  tx.addInput(input);
16006
16755
  }
@@ -16123,6 +16872,7 @@ function isArkContract(str) {
16123
16872
  exports.ActivityRegistry = ActivityRegistry;
16124
16873
  exports.ArkNote = ArkNote;
16125
16874
  exports.AssetManager = AssetManager;
16875
+ exports.ChainedTxType = ChainedTxType;
16126
16876
  exports.ContractManager = ContractManager;
16127
16877
  exports.ContractRepositoryImpl = ContractRepositoryImpl;
16128
16878
  exports.ContractWatcher = ContractWatcher;
@@ -16141,9 +16891,14 @@ exports.ElectrumOnchainProvider = ElectrumOnchainProvider;
16141
16891
  exports.EsploraProvider = EsploraProvider;
16142
16892
  exports.Estimator = Estimator;
16143
16893
  exports.HDDescriptorProvider = HDDescriptorProvider;
16894
+ exports.INTENT_TERMINAL_STATES = INTENT_TERMINAL_STATES;
16144
16895
  exports.InMemoryContractRepository = InMemoryContractRepository;
16896
+ exports.InMemoryIntentRepository = InMemoryIntentRepository;
16897
+ exports.InMemoryVirtualTxRepository = InMemoryVirtualTxRepository;
16145
16898
  exports.InMemoryWalletRepository = InMemoryWalletRepository;
16146
16899
  exports.IndexedDBContractRepository = IndexedDBContractRepository;
16900
+ exports.IndexedDBIntentRepository = IndexedDBIntentRepository;
16901
+ exports.IndexedDBVirtualTxRepository = IndexedDBVirtualTxRepository;
16147
16902
  exports.IndexedDBWalletRepository = IndexedDBWalletRepository;
16148
16903
  exports.MESSAGE_BUS_INITIALIZING = MESSAGE_BUS_INITIALIZING;
16149
16904
  exports.MESSAGE_BUS_NOT_INITIALIZED = MESSAGE_BUS_NOT_INITIALIZED;
@@ -16177,6 +16932,7 @@ exports.WalletMessageHandler = WalletMessageHandler;
16177
16932
  exports.WalletNotInitializedError = WalletNotInitializedError;
16178
16933
  exports.WalletRepositoryImpl = WalletRepositoryImpl;
16179
16934
  exports.WsElectrumChainSource = WsElectrumChainSource;
16935
+ exports.assertIntentIdUnique = assertIntentIdUnique;
16180
16936
  exports.boardingResolver = boardingResolver;
16181
16937
  exports.buildForfeitTx = buildForfeitTx;
16182
16938
  exports.buildOffchainTx = buildOffchainTx;
@@ -16196,6 +16952,8 @@ exports.extendVirtualCoinForContract = extendVirtualCoinForContract;
16196
16952
  exports.getMigrationStatus = getMigrationStatus;
16197
16953
  exports.getRandomId = getRandomId;
16198
16954
  exports.hasBoardingTxExpired = hasBoardingTxExpired;
16955
+ exports.intentMatchesFilter = intentMatchesFilter;
16956
+ exports.intentPageBounds = intentPageBounds;
16199
16957
  exports.isArkContract = isArkContract;
16200
16958
  exports.isBatchSignable = isBatchSignable;
16201
16959
  exports.isCooperativelyMigratable = isCooperativelyMigratable;
@@ -16204,9 +16962,11 @@ exports.isExpired = isExpired;
16204
16962
  exports.isRecoverable = isRecoverable;
16205
16963
  exports.isSpendable = isSpendable;
16206
16964
  exports.isSubdust = isSubdust;
16965
+ exports.isTerminalIntentState = isTerminalIntentState;
16207
16966
  exports.isValidArkAddress = isValidArkAddress;
16208
16967
  exports.isVtxoExpiringSoon = isVtxoExpiringSoon;
16209
16968
  exports.isVtxoForScript = isVtxoForScript;
16969
+ exports.mergeChainedTxType = mergeChainedTxType;
16210
16970
  exports.migrateWalletRepository = migrateWalletRepository;
16211
16971
  exports.openDatabase = openDatabase;
16212
16972
  exports.requiresMigration = requiresMigration;
@@ -16224,5 +16984,5 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
16224
16984
  exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
16225
16985
  exports.waitForIncomingFunds = waitForIncomingFunds;
16226
16986
  exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
16227
- //# sourceMappingURL=chunk-3MPXMLP4.cjs.map
16228
- //# sourceMappingURL=chunk-3MPXMLP4.cjs.map
16987
+ //# sourceMappingURL=chunk-QGNTDGMN.cjs.map
16988
+ //# sourceMappingURL=chunk-QGNTDGMN.cjs.map