@arkade-os/sdk 0.4.43 → 0.4.44

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 (48) hide show
  1. package/README.md +65 -0
  2. package/dist/adapters/expo.cjs +4 -4
  3. package/dist/adapters/expo.js +2 -2
  4. package/dist/adapters/indexedDB.cjs +3 -3
  5. package/dist/adapters/indexedDB.js +2 -2
  6. package/dist/{asyncStorageTaskQueue-CjoL-35w.d.ts → asyncStorageTaskQueue-BtSOVZFn.d.ts} +2 -2
  7. package/dist/{asyncStorageTaskQueue-D1FfHfgK.d.cts → asyncStorageTaskQueue-Dap7qUlF.d.cts} +2 -2
  8. package/dist/{chunk-B4R36PRN.js → chunk-FMI2GKYO.js} +1088 -181
  9. package/dist/chunk-FMI2GKYO.js.map +1 -0
  10. package/dist/{chunk-US274KZO.js → chunk-LCQQPOIT.js} +3 -3
  11. package/dist/{chunk-US274KZO.js.map → chunk-LCQQPOIT.js.map} +1 -1
  12. package/dist/{chunk-763XHDAJ.js → chunk-LJ35HPJW.js} +3 -3
  13. package/dist/{chunk-763XHDAJ.js.map → chunk-LJ35HPJW.js.map} +1 -1
  14. package/dist/{chunk-JIWCE2IK.cjs → chunk-RJ6XVCX4.cjs} +7 -7
  15. package/dist/{chunk-JIWCE2IK.cjs.map → chunk-RJ6XVCX4.cjs.map} +1 -1
  16. package/dist/{chunk-3AQNLQPM.cjs → chunk-UBYY2TPK.cjs} +3 -3
  17. package/dist/{chunk-3AQNLQPM.cjs.map → chunk-UBYY2TPK.cjs.map} +1 -1
  18. package/dist/{chunk-VKKLOT2E.js → chunk-V7WIZR2B.js} +3 -3
  19. package/dist/{chunk-VKKLOT2E.js.map → chunk-V7WIZR2B.js.map} +1 -1
  20. package/dist/{chunk-PLJZRIFZ.cjs → chunk-X37EKDIH.cjs} +11 -11
  21. package/dist/{chunk-PLJZRIFZ.cjs.map → chunk-X37EKDIH.cjs.map} +1 -1
  22. package/dist/{chunk-QGNTDGMN.cjs → chunk-XIVCG6EP.cjs} +1163 -253
  23. package/dist/chunk-XIVCG6EP.cjs.map +1 -0
  24. package/dist/index.cjs +138 -126
  25. package/dist/index.d.cts +232 -1
  26. package/dist/index.d.ts +232 -1
  27. package/dist/index.js +2 -2
  28. package/dist/repositories/realm/index.cjs +17 -17
  29. package/dist/repositories/realm/index.js +3 -3
  30. package/dist/repositories/sqlite/index.cjs +16 -16
  31. package/dist/repositories/sqlite/index.js +3 -3
  32. package/dist/{taskRunner-Djlhfgi1.d.ts → taskRunner-Bptw9UMa.d.ts} +1 -1
  33. package/dist/{taskRunner-BSnslNmq.d.cts → taskRunner-CeFxKhSH.d.cts} +1 -1
  34. package/dist/wallet/expo/background.cjs +12 -12
  35. package/dist/wallet/expo/background.d.cts +2 -2
  36. package/dist/wallet/expo/background.d.ts +2 -2
  37. package/dist/wallet/expo/background.js +4 -4
  38. package/dist/wallet/expo/index.cjs +12 -12
  39. package/dist/wallet/expo/index.d.cts +1 -1
  40. package/dist/wallet/expo/index.d.ts +1 -1
  41. package/dist/wallet/expo/index.js +3 -3
  42. package/dist/worker/expo/index.cjs +7 -7
  43. package/dist/worker/expo/index.d.cts +3 -3
  44. package/dist/worker/expo/index.d.ts +3 -3
  45. package/dist/worker/expo/index.js +3 -3
  46. package/package.json +1 -1
  47. package/dist/chunk-B4R36PRN.js.map +0 -1
  48. package/dist/chunk-QGNTDGMN.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, baseFetch, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-763XHDAJ.js';
2
- import { isMainnetDescriptor, descriptorIsOurs, contractHandlers, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, DefaultVtxo, BoardingContractHandler } from './chunk-YNEDJTX2.js';
3
- import { VtxoScript, timelockToSequence, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, ArkAddress, CSVMultisigTapscript, getSequence, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-BE5MUB7T.js';
1
+ import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, baseFetch, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-LJ35HPJW.js';
2
+ import { contractHandlers, isMainnetDescriptor, descriptorIsOurs, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, DefaultVtxo, BoardingContractHandler } from './chunk-YNEDJTX2.js';
3
+ import { VtxoScript, sequenceToTimelock, timelockToSequence, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, ArkAddress, CSVMultisigTapscript, getSequence, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-BE5MUB7T.js';
4
4
  import { sha256, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr, equalBytes as equalBytes$1 } from '@scure/btc-signer/utils.js';
5
5
  import { SigHash, Script, p2tr, RawWitness, Address, OutScript, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$2 } from '@scure/btc-signer';
6
6
  import { hex, base58, base64 } from '@scure/base';
@@ -1215,6 +1215,114 @@ var isExplorerTransaction = (tx) => {
1215
1215
  (vout) => typeof vout.scriptpubkey_address === "string" && typeof vout.value === "number"
1216
1216
  ) && typeof tx.status === "object" && typeof tx.status.confirmed === "boolean";
1217
1217
  };
1218
+ var getVarIntSize = (n) => {
1219
+ if (n < 253) return 1;
1220
+ if (n <= 65535) return 3;
1221
+ if (n <= 4294967295) return 5;
1222
+ return 9;
1223
+ };
1224
+ var TxWeightEstimator = class _TxWeightEstimator {
1225
+ static P2PKH_SCRIPT_SIG_SIZE = 1 + 73 + 1 + 33;
1226
+ static INPUT_SIZE = 32 + 4 + 1 + 4;
1227
+ static BASE_CONTROL_BLOCK_SIZE = 1 + 32;
1228
+ static OUTPUT_SIZE = 8 + 1;
1229
+ static P2WPKH_OUTPUT_SIZE = 1 + 1 + 20;
1230
+ static BASE_TX_SIZE = 8 + 2;
1231
+ // Version + LockTime
1232
+ static WITNESS_HEADER_SIZE = 2;
1233
+ // Flag + Marker
1234
+ static WITNESS_SCALE_FACTOR = 4;
1235
+ static P2TR_OUTPUT_SIZE = 1 + 1 + 32;
1236
+ hasWitness;
1237
+ inputCount;
1238
+ outputCount;
1239
+ inputSize;
1240
+ inputWitnessSize;
1241
+ outputSize;
1242
+ constructor(hasWitness, inputCount, outputCount, inputSize, inputWitnessSize, outputSize) {
1243
+ this.hasWitness = hasWitness;
1244
+ this.inputCount = inputCount;
1245
+ this.outputCount = outputCount;
1246
+ this.inputSize = inputSize;
1247
+ this.inputWitnessSize = inputWitnessSize;
1248
+ this.outputSize = outputSize;
1249
+ }
1250
+ static create() {
1251
+ return new _TxWeightEstimator(false, 0, 0, 0, 0, 0);
1252
+ }
1253
+ addP2AInput() {
1254
+ this.inputCount++;
1255
+ this.inputSize += _TxWeightEstimator.INPUT_SIZE;
1256
+ return this;
1257
+ }
1258
+ addKeySpendInput(isDefault = true) {
1259
+ this.inputCount++;
1260
+ this.inputWitnessSize += 64 + 1 + (isDefault ? 0 : 1);
1261
+ this.inputSize += _TxWeightEstimator.INPUT_SIZE;
1262
+ this.hasWitness = true;
1263
+ return this;
1264
+ }
1265
+ addP2PKHInput() {
1266
+ this.inputCount++;
1267
+ this.inputWitnessSize++;
1268
+ this.inputSize += _TxWeightEstimator.INPUT_SIZE + _TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE;
1269
+ return this;
1270
+ }
1271
+ addTapscriptInput(leafWitnessSize, leafScriptSize, leafControlBlockSize) {
1272
+ const controlBlockWitnessSize = 1 + _TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE + 1 + leafScriptSize + 1 + leafControlBlockSize;
1273
+ this.inputCount++;
1274
+ this.inputWitnessSize += leafWitnessSize + 1 + controlBlockWitnessSize;
1275
+ this.inputSize += _TxWeightEstimator.INPUT_SIZE;
1276
+ this.hasWitness = true;
1277
+ return this;
1278
+ }
1279
+ addP2WPKHOutput() {
1280
+ this.outputCount++;
1281
+ this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2WPKH_OUTPUT_SIZE;
1282
+ return this;
1283
+ }
1284
+ addP2TROutput() {
1285
+ this.outputCount++;
1286
+ this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2TR_OUTPUT_SIZE;
1287
+ return this;
1288
+ }
1289
+ /**
1290
+ * Adds an output given a raw script.
1291
+ * Cost = 8 bytes (amount) + varint(scriptLen) + scriptLen
1292
+ */
1293
+ addOutputScript(script) {
1294
+ this.outputCount++;
1295
+ this.outputSize += 8 + getVarIntSize(script.length) + script.length;
1296
+ return this;
1297
+ }
1298
+ /**
1299
+ * Adds an output by decoding the address to get the exact script size.
1300
+ */
1301
+ addOutputAddress(address, network) {
1302
+ const payment = Address(network).decode(address);
1303
+ const script = OutScript.encode(payment);
1304
+ return this.addOutputScript(script);
1305
+ }
1306
+ vsize() {
1307
+ const inputCount = getVarIntSize(this.inputCount);
1308
+ const outputCount = getVarIntSize(this.outputCount);
1309
+ const txSizeStripped = _TxWeightEstimator.BASE_TX_SIZE + inputCount + this.inputSize + outputCount + this.outputSize;
1310
+ let weight = txSizeStripped * _TxWeightEstimator.WITNESS_SCALE_FACTOR;
1311
+ if (this.hasWitness) {
1312
+ weight += _TxWeightEstimator.WITNESS_HEADER_SIZE + this.inputWitnessSize;
1313
+ }
1314
+ return vsize(weight);
1315
+ }
1316
+ };
1317
+ var vsize = (weight) => {
1318
+ const value = BigInt(Math.ceil(weight / TxWeightEstimator.WITNESS_SCALE_FACTOR));
1319
+ return {
1320
+ value,
1321
+ fee: (feeRate) => feeRate * value
1322
+ };
1323
+ };
1324
+
1325
+ // src/utils/anchor.ts
1218
1326
  var ANCHOR_VALUE = 0n;
1219
1327
  var ANCHOR_PKSCRIPT = new Uint8Array([81, 2, 78, 115]);
1220
1328
  var P2A = {
@@ -1240,6 +1348,37 @@ function findP2AOutput(tx) {
1240
1348
  }
1241
1349
  throw new Error("P2A output not found");
1242
1350
  }
1351
+ var CHILD_DUST_AMOUNT = 546;
1352
+ function buildAnchorChild(params) {
1353
+ const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
1354
+ const child = new Transaction({ version: 3, allowLegacyWitnessUtxo: true });
1355
+ child.addInput(findP2AOutput(parent));
1356
+ const estimator = TxWeightEstimator.create().addP2AInput();
1357
+ for (const _ of fundingCoins) {
1358
+ estimator.addKeySpendInput(true);
1359
+ }
1360
+ estimator.addOutputAddress(changeAddress, network);
1361
+ const childVsize = Number(estimator.vsize().value);
1362
+ const fee = Math.ceil(feeRate * (parent.vsize + childVsize));
1363
+ let total = 0n;
1364
+ for (const coin of fundingCoins) {
1365
+ total += BigInt(coin.value);
1366
+ child.addInput({
1367
+ txid: coin.txid,
1368
+ index: coin.vout,
1369
+ witnessUtxo: { script: params.changeScript, amount: BigInt(coin.value) },
1370
+ tapInternalKey
1371
+ });
1372
+ }
1373
+ const change = total + P2A.amount - BigInt(fee);
1374
+ if (change < BigInt(CHILD_DUST_AMOUNT)) {
1375
+ throw new Error(
1376
+ `insufficient funding for anchor child: need change >= ${CHILD_DUST_AMOUNT}, got ${change}`
1377
+ );
1378
+ }
1379
+ child.addOutputAddress(changeAddress, change, network);
1380
+ return { child, fee };
1381
+ }
1243
1382
 
1244
1383
  // src/forfeit.ts
1245
1384
  function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
@@ -2154,112 +2293,6 @@ function isValidArkAddress(address) {
2154
2293
  return false;
2155
2294
  }
2156
2295
  }
2157
- var getVarIntSize = (n) => {
2158
- if (n < 253) return 1;
2159
- if (n <= 65535) return 3;
2160
- if (n <= 4294967295) return 5;
2161
- return 9;
2162
- };
2163
- var TxWeightEstimator = class _TxWeightEstimator {
2164
- static P2PKH_SCRIPT_SIG_SIZE = 1 + 73 + 1 + 33;
2165
- static INPUT_SIZE = 32 + 4 + 1 + 4;
2166
- static BASE_CONTROL_BLOCK_SIZE = 1 + 32;
2167
- static OUTPUT_SIZE = 8 + 1;
2168
- static P2WPKH_OUTPUT_SIZE = 1 + 1 + 20;
2169
- static BASE_TX_SIZE = 8 + 2;
2170
- // Version + LockTime
2171
- static WITNESS_HEADER_SIZE = 2;
2172
- // Flag + Marker
2173
- static WITNESS_SCALE_FACTOR = 4;
2174
- static P2TR_OUTPUT_SIZE = 1 + 1 + 32;
2175
- hasWitness;
2176
- inputCount;
2177
- outputCount;
2178
- inputSize;
2179
- inputWitnessSize;
2180
- outputSize;
2181
- constructor(hasWitness, inputCount, outputCount, inputSize, inputWitnessSize, outputSize) {
2182
- this.hasWitness = hasWitness;
2183
- this.inputCount = inputCount;
2184
- this.outputCount = outputCount;
2185
- this.inputSize = inputSize;
2186
- this.inputWitnessSize = inputWitnessSize;
2187
- this.outputSize = outputSize;
2188
- }
2189
- static create() {
2190
- return new _TxWeightEstimator(false, 0, 0, 0, 0, 0);
2191
- }
2192
- addP2AInput() {
2193
- this.inputCount++;
2194
- this.inputSize += _TxWeightEstimator.INPUT_SIZE;
2195
- return this;
2196
- }
2197
- addKeySpendInput(isDefault = true) {
2198
- this.inputCount++;
2199
- this.inputWitnessSize += 64 + 1 + (isDefault ? 0 : 1);
2200
- this.inputSize += _TxWeightEstimator.INPUT_SIZE;
2201
- this.hasWitness = true;
2202
- return this;
2203
- }
2204
- addP2PKHInput() {
2205
- this.inputCount++;
2206
- this.inputWitnessSize++;
2207
- this.inputSize += _TxWeightEstimator.INPUT_SIZE + _TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE;
2208
- return this;
2209
- }
2210
- addTapscriptInput(leafWitnessSize, leafScriptSize, leafControlBlockSize) {
2211
- const controlBlockWitnessSize = 1 + _TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE + 1 + leafScriptSize + 1 + leafControlBlockSize;
2212
- this.inputCount++;
2213
- this.inputWitnessSize += leafWitnessSize + 1 + controlBlockWitnessSize;
2214
- this.inputSize += _TxWeightEstimator.INPUT_SIZE;
2215
- this.hasWitness = true;
2216
- return this;
2217
- }
2218
- addP2WPKHOutput() {
2219
- this.outputCount++;
2220
- this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2WPKH_OUTPUT_SIZE;
2221
- return this;
2222
- }
2223
- addP2TROutput() {
2224
- this.outputCount++;
2225
- this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2TR_OUTPUT_SIZE;
2226
- return this;
2227
- }
2228
- /**
2229
- * Adds an output given a raw script.
2230
- * Cost = 8 bytes (amount) + varint(scriptLen) + scriptLen
2231
- */
2232
- addOutputScript(script) {
2233
- this.outputCount++;
2234
- this.outputSize += 8 + getVarIntSize(script.length) + script.length;
2235
- return this;
2236
- }
2237
- /**
2238
- * Adds an output by decoding the address to get the exact script size.
2239
- */
2240
- addOutputAddress(address, network) {
2241
- const payment = Address(network).decode(address);
2242
- const script = OutScript.encode(payment);
2243
- return this.addOutputScript(script);
2244
- }
2245
- vsize() {
2246
- const inputCount = getVarIntSize(this.inputCount);
2247
- const outputCount = getVarIntSize(this.outputCount);
2248
- const txSizeStripped = _TxWeightEstimator.BASE_TX_SIZE + inputCount + this.inputSize + outputCount + this.outputSize;
2249
- let weight = txSizeStripped * _TxWeightEstimator.WITNESS_SCALE_FACTOR;
2250
- if (this.hasWitness) {
2251
- weight += _TxWeightEstimator.WITNESS_HEADER_SIZE + this.inputWitnessSize;
2252
- }
2253
- return vsize(weight);
2254
- }
2255
- };
2256
- var vsize = (weight) => {
2257
- const value = BigInt(Math.ceil(weight / TxWeightEstimator.WITNESS_SCALE_FACTOR));
2258
- return {
2259
- value,
2260
- fee: (feeRate) => feeRate * value
2261
- };
2262
- };
2263
2296
  var AmountVariableName = "amount";
2264
2297
  var ExpiryVariableName = "expiry";
2265
2298
  var BirthVariableName = "birth";
@@ -15584,42 +15617,11 @@ var OnchainWallet = class _OnchainWallet {
15584
15617
  * @see send
15585
15618
  */
15586
15619
  async bumpP2A(parent) {
15587
- const parentVsize = parent.vsize;
15588
- let child = new Transaction({
15589
- version: 3,
15590
- allowLegacyWitnessUtxo: true
15591
- });
15592
- child.addInput(findP2AOutput(parent));
15593
- const childVsize = TxWeightEstimator.create().addKeySpendInput(true).addP2AInput().addOutputAddress(this.address, this.network).vsize().value;
15594
- const packageVSize = parentVsize + Number(childVsize);
15595
15620
  let feeRate = await this.provider.getFeeRate();
15596
15621
  if (!feeRate || feeRate < _OnchainWallet.MIN_FEE_RATE) {
15597
15622
  feeRate = _OnchainWallet.MIN_FEE_RATE;
15598
15623
  }
15599
- const fee = Math.ceil(feeRate * packageVSize);
15600
- if (!fee) {
15601
- throw new Error(
15602
- `invalid fee, got ${fee} with vsize ${packageVSize}, feeRate ${feeRate}`
15603
- );
15604
- }
15605
- const coins = await this.getCoins();
15606
- const selected = selectCoins(coins, fee, true);
15607
- for (const input of selected.inputs) {
15608
- child.addInput({
15609
- txid: input.txid,
15610
- index: input.vout,
15611
- witnessUtxo: {
15612
- script: this.onchainP2TR.script,
15613
- amount: BigInt(input.value)
15614
- },
15615
- tapInternalKey: this.onchainP2TR.tapInternalKey
15616
- });
15617
- }
15618
- child.addOutputAddress(this.address, P2A.amount + selected.changeAmount, this.network);
15619
- child = await this.identity.sign(child);
15620
- for (let i = 1; i < child.inputsLength; i++) {
15621
- child.finalizeIdx(i);
15622
- }
15624
+ const child = await this.buildBumpPackage(parent, feeRate, await this.getCoins());
15623
15625
  try {
15624
15626
  await this.provider.broadcastTransaction(parent.hex, child.hex);
15625
15627
  } catch (error) {
@@ -15628,6 +15630,59 @@ var OnchainWallet = class _OnchainWallet {
15628
15630
  return [parent.hex, child.hex];
15629
15631
  }
15630
15632
  }
15633
+ /**
15634
+ * Build and sign a CPFP fee child for a parent tx (given as raw hex)
15635
+ * carrying a P2A anchor, funding it from this wallet's **confirmed**
15636
+ * coins, and return the 1P1C package hexes WITHOUT broadcasting.
15637
+ *
15638
+ * This is the graph-mode fee source ({@link ExitFeeWallet}): the exit
15639
+ * executor calls it to bump each transported virtual tx at execution
15640
+ * time, so funding can be deferred rather than pre-signed.
15641
+ *
15642
+ * @param parentHex - Finalized parent transaction, raw network hex
15643
+ * @param feeRate - sat/vB floor for the package (raised to MIN_FEE_RATE)
15644
+ * @returns Tuple of parent hex (unchanged) and signed child hex
15645
+ * @throws If the parent has no anchor, or funding cannot be selected/signed
15646
+ */
15647
+ async bumpAnchor(parentHex, feeRate) {
15648
+ const parent = Transaction.fromRaw(hex.decode(parentHex));
15649
+ const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
15650
+ const child = await this.buildBumpPackage(parent, feeRate, coins);
15651
+ return [parent.hex, child.hex];
15652
+ }
15653
+ /**
15654
+ * Shared core of {@link bumpP2A} and {@link bumpAnchor}: probe the package
15655
+ * fee with a single-input child, select coins for it, then build and sign
15656
+ * with the actual selection (the fee grows per extra input).
15657
+ */
15658
+ async buildBumpPackage(parent, feeRate, coins) {
15659
+ let rate = feeRate;
15660
+ if (!rate || rate < _OnchainWallet.MIN_FEE_RATE) {
15661
+ rate = _OnchainWallet.MIN_FEE_RATE;
15662
+ }
15663
+ const probeVsize = TxWeightEstimator.create().addKeySpendInput(true).addP2AInput().addOutputAddress(this.address, this.network).vsize().value;
15664
+ const probeFee = Math.ceil(rate * (parent.vsize + Number(probeVsize)));
15665
+ if (!probeFee) {
15666
+ throw new Error(
15667
+ `invalid fee, got ${probeFee} with vsize ${parent.vsize + Number(probeVsize)}, feeRate ${rate}`
15668
+ );
15669
+ }
15670
+ const selected = selectCoins(coins, probeFee, true);
15671
+ const { child } = buildAnchorChild({
15672
+ parent,
15673
+ feeRate: rate,
15674
+ fundingCoins: selected.inputs,
15675
+ changeAddress: this.address,
15676
+ changeScript: this.onchainP2TR.script,
15677
+ tapInternalKey: this.onchainP2TR.tapInternalKey,
15678
+ network: this.network
15679
+ });
15680
+ const signed = await this.identity.sign(child);
15681
+ for (let i = 1; i < signed.inputsLength; i++) {
15682
+ signed.finalizeIdx(i);
15683
+ }
15684
+ return signed;
15685
+ }
15631
15686
  };
15632
15687
  function selectCoins(coins, targetAmount, forceChange = false) {
15633
15688
  if (isNaN(targetAmount)) {
@@ -16518,6 +16573,84 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
16518
16573
  });
16519
16574
  return tx;
16520
16575
  }
16576
+ function finalizeVirtualTx(type, psbtBase64) {
16577
+ const tx = Transaction.fromPSBT(base64.decode(psbtBase64));
16578
+ if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
16579
+ const input = tx.getInput(0);
16580
+ if (!input) {
16581
+ throw new Error("Input not found");
16582
+ }
16583
+ const tapKeySig = input.tapKeySig;
16584
+ if (!tapKeySig) {
16585
+ throw new Error("Tap key sig not found");
16586
+ }
16587
+ tx.updateInput(0, {
16588
+ finalScriptWitness: [tapKeySig]
16589
+ });
16590
+ return tx;
16591
+ }
16592
+ tx.finalize();
16593
+ return tx;
16594
+ }
16595
+ var ExitPathError = class extends Error {
16596
+ constructor(reason, message) {
16597
+ super(message);
16598
+ this.reason = reason;
16599
+ this.name = "ExitPathError";
16600
+ }
16601
+ };
16602
+ function delayWeight(sequence) {
16603
+ const t = sequenceToTimelock(sequence);
16604
+ return t.type === "blocks" ? Number(t.value) : Number(t.value) / 600;
16605
+ }
16606
+ async function resolveUnilateralPath(params) {
16607
+ const { vtxo, scriptHex, contractRepository } = params;
16608
+ const contract = contractRepository ? (await contractRepository.getContracts({ script: scriptHex }))[0] : void 0;
16609
+ if (contract) {
16610
+ const handler = contractHandlers.get(contract.type);
16611
+ if (!handler) {
16612
+ throw new ExitPathError(
16613
+ "no-handler",
16614
+ `no contract handler registered for type '${contract.type}'`
16615
+ );
16616
+ }
16617
+ const script = handler.createScript(contract.params);
16618
+ const paths = handler.getAllSpendingPaths(script, contract, {
16619
+ collaborative: false,
16620
+ currentTime: params.currentTime,
16621
+ walletDescriptor: params.walletDescriptor,
16622
+ walletPubKey: params.walletPubKeyHex
16623
+ }).filter((p) => p.sequence !== void 0);
16624
+ if (paths.length === 0) {
16625
+ throw new ExitPathError(
16626
+ "no-unilateral-path",
16627
+ `no unilateral path for vtxo ${vtxo.txid}:${vtxo.vout} (type '${contract.type}')`
16628
+ );
16629
+ }
16630
+ paths.sort((a, b) => delayWeight(a.sequence) - delayWeight(b.sequence));
16631
+ return { selection: paths[0], label: `${contract.type}:unilateral` };
16632
+ }
16633
+ const decoded = VtxoScript.decode(vtxo.tapTree);
16634
+ let best;
16635
+ for (const exit of decoded.exitPaths()) {
16636
+ const leaf = decoded.findLeaf(hex.encode(exit.script));
16637
+ if (!leaf) continue;
16638
+ const sequence = timelockToSequence(exit.params.timelock);
16639
+ const weight = delayWeight(sequence);
16640
+ if (!best || weight < best.weight) {
16641
+ best = { selection: { leaf, sequence }, weight };
16642
+ }
16643
+ }
16644
+ if (!best) {
16645
+ throw new ExitPathError(
16646
+ "no-unilateral-path",
16647
+ `no exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`
16648
+ );
16649
+ }
16650
+ return { selection: best.selection, label: "default:exit" };
16651
+ }
16652
+
16653
+ // src/wallet/unroll.ts
16521
16654
  function chainTxTypeToChainedExit(t) {
16522
16655
  switch (t) {
16523
16656
  case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
@@ -16627,22 +16760,7 @@ var Unroll;
16627
16760
  if (!virtualTxBase64) {
16628
16761
  throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
16629
16762
  }
16630
- const tx = Transaction.fromPSBT(base64.decode(virtualTxBase64));
16631
- if (nextTxToBroadcast.type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
16632
- const input = tx.getInput(0);
16633
- if (!input) {
16634
- throw new Error("Input not found");
16635
- }
16636
- const tapKeySig = input.tapKeySig;
16637
- if (!tapKeySig) {
16638
- throw new Error("Tap key sig not found");
16639
- }
16640
- tx.updateInput(0, {
16641
- finalScriptWitness: [tapKeySig]
16642
- });
16643
- } else {
16644
- tx.finalize();
16645
- }
16763
+ const tx = finalizeVirtualTx(nextTxToBroadcast.type, virtualTxBase64);
16646
16764
  const pkg = await this.bumper.bumpP2A(tx);
16647
16765
  return {
16648
16766
  type: 0 /* UNROLL */,
@@ -16696,20 +16814,21 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
16696
16814
  if (!txStatus.confirmed) {
16697
16815
  throw new Error(`tx ${vtxo.txid} is not confirmed`);
16698
16816
  }
16699
- const exit = availableExitPath(
16700
- { height: txStatus.blockHeight, time: txStatus.blockTime },
16701
- chainTip,
16702
- vtxo
16703
- );
16704
- if (!exit) {
16817
+ const resolved = await resolveUnilateralPath({
16818
+ vtxo,
16819
+ scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
16820
+ contractRepository: wallet.contractRepository,
16821
+ walletPubKeyHex: hex.encode(await wallet.identity.xOnlyPublicKey()),
16822
+ currentTime: Date.now()
16823
+ });
16824
+ const spendingLeaf = resolved.selection.leaf;
16825
+ const sequence = resolved.selection.sequence;
16826
+ const timelock = sequenceToTimelock(sequence);
16827
+ const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
16828
+ if (!elapsed) {
16705
16829
  throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
16706
16830
  }
16707
- const spendingLeaf = VtxoScript.decode(vtxo.tapTree).findLeaf(hex.encode(exit.script));
16708
- if (!spendingLeaf) {
16709
- throw new Error(`spending leaf not found for vtxo ${vtxo.txid}:${vtxo.vout}`);
16710
- }
16711
16831
  totalAmount += BigInt(vtxo.value);
16712
- const sequence = timelockToSequence(exit.params.timelock);
16713
16832
  inputs.push({
16714
16833
  txid: vtxo.txid,
16715
16834
  index: vtxo.vout,
@@ -16773,21 +16892,809 @@ function doWait(onchainProvider, txid) {
16773
16892
  });
16774
16893
  };
16775
16894
  }
16776
- function availableExitPath(confirmedAt, current, vtxo) {
16777
- const exits = VtxoScript.decode(vtxo.tapTree).exitPaths();
16778
- for (const exit of exits) {
16779
- if (exit.params.timelock.type === "blocks") {
16780
- if (current.height >= confirmedAt.height + Number(exit.params.timelock.value)) {
16781
- return exit;
16895
+
16896
+ // src/wallet/exit/chain.ts
16897
+ var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
16898
+ async function buildExitDag(params) {
16899
+ const byTxid = /* @__PURE__ */ new Map();
16900
+ for (const vtxo of params.vtxos) {
16901
+ const outpoint = `${vtxo.txid}:${vtxo.vout}`;
16902
+ let pageIndex = 0;
16903
+ let hasMore = true;
16904
+ while (hasMore) {
16905
+ const { chain, page } = await params.indexer.getVtxoChain(
16906
+ { txid: vtxo.txid, vout: vtxo.vout },
16907
+ { pageIndex, pageSize: DEFAULT_PAGE_SIZE }
16908
+ );
16909
+ for (const chainTx of chain) {
16910
+ const existing = byTxid.get(chainTx.txid);
16911
+ if (existing) {
16912
+ existing.forVtxos.add(outpoint);
16913
+ } else {
16914
+ byTxid.set(chainTx.txid, { ...chainTx, forVtxos: /* @__PURE__ */ new Set([outpoint]) });
16915
+ }
16782
16916
  }
16783
- } else {
16784
- if (current.time >= confirmedAt.time + Number(exit.params.timelock.value)) {
16785
- return exit;
16917
+ hasMore = page ? chain.length === DEFAULT_PAGE_SIZE : false;
16918
+ pageIndex++;
16919
+ }
16920
+ }
16921
+ const pending = new Map(
16922
+ [...byTxid.values()].filter((tx) => !isCommitment(tx.type)).map((tx) => [tx.txid, tx])
16923
+ );
16924
+ const inDegree = /* @__PURE__ */ new Map();
16925
+ for (const tx of pending.values()) {
16926
+ const parents = tx.spends.filter((p) => pending.has(p));
16927
+ inDegree.set(tx.txid, parents.length);
16928
+ }
16929
+ const order = [];
16930
+ const queue = [...pending.values()].filter((tx) => inDegree.get(tx.txid) === 0).sort((a, b) => a.txid.localeCompare(b.txid));
16931
+ while (queue.length > 0) {
16932
+ const tx = queue.shift();
16933
+ order.push(tx);
16934
+ const children = [...pending.values()].filter((c) => c.spends.includes(tx.txid)).sort((a, b) => a.txid.localeCompare(b.txid));
16935
+ for (const child of children) {
16936
+ const deg = inDegree.get(child.txid) - 1;
16937
+ inDegree.set(child.txid, deg);
16938
+ if (deg === 0) queue.push(child);
16939
+ }
16940
+ }
16941
+ if (order.length !== pending.size) {
16942
+ throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
16943
+ }
16944
+ const nodes = [];
16945
+ for (const tx of order) {
16946
+ let confirmed = false;
16947
+ try {
16948
+ const status = await params.onchain.getTxStatus(tx.txid);
16949
+ confirmed = status.confirmed;
16950
+ } catch {
16951
+ confirmed = false;
16952
+ }
16953
+ const expires = Number(tx.expiresAt);
16954
+ nodes.push({
16955
+ txid: tx.txid,
16956
+ type: tx.type,
16957
+ expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
16958
+ forVtxos: [...tx.forVtxos].sort(),
16959
+ confirmed
16960
+ });
16961
+ }
16962
+ return nodes;
16963
+ }
16964
+ function topoSortByDeps(items, idOf, depsOf) {
16965
+ const produced = new Set(items.map(idOf));
16966
+ const emitted = /* @__PURE__ */ new Set();
16967
+ const ordered = [];
16968
+ let remaining = items;
16969
+ while (remaining.length > 0) {
16970
+ const next = [];
16971
+ let progress = false;
16972
+ for (const item of remaining) {
16973
+ if (depsOf(item).every((d) => !produced.has(d) || emitted.has(d))) {
16974
+ ordered.push(item);
16975
+ emitted.add(idOf(item));
16976
+ progress = true;
16977
+ } else {
16978
+ next.push(item);
16786
16979
  }
16787
16980
  }
16981
+ if (!progress) {
16982
+ throw new Error("topological sort: cycle or unsatisfiable dependency");
16983
+ }
16984
+ remaining = next;
16788
16985
  }
16789
- return void 0;
16986
+ return ordered;
16987
+ }
16988
+ function extraWitnessSize(path) {
16989
+ return (path.extraWitness ?? []).reduce((sum, item) => sum + 1 + item.length, 0);
16790
16990
  }
16991
+ function sweepFeeFor(path, outputAddress, network, feeRate) {
16992
+ const [controlBlock, scriptWithVersion] = path.leaf;
16993
+ const estimator = TxWeightEstimator.create().addTapscriptInput(
16994
+ 64 + extraWitnessSize(path),
16995
+ scriptWithVersion.length,
16996
+ TaprootControlBlock.encode(controlBlock).length
16997
+ ).addOutputAddress(outputAddress, network);
16998
+ return Number(estimator.vsize().fee(BigInt(Math.ceil(feeRate))));
16999
+ }
17000
+ async function buildSignedSweep(params) {
17001
+ const { vtxo, path, outputAddress, feeRate, network, identity } = params;
17002
+ const fee = sweepFeeFor(path, outputAddress, network, feeRate);
17003
+ const sendAmount = BigInt(vtxo.value) - BigInt(fee);
17004
+ if (sendAmount < BigInt(DUST_AMOUNT)) {
17005
+ throw new Error(
17006
+ `uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
17007
+ );
17008
+ }
17009
+ const tx = new Transaction({ version: 2 });
17010
+ tx.addInput({
17011
+ txid: vtxo.txid,
17012
+ index: vtxo.vout,
17013
+ tapLeafScript: [path.leaf],
17014
+ sequence: path.sequence,
17015
+ witnessUtxo: { amount: BigInt(vtxo.value), script: vtxo.pkScript },
17016
+ sighashType: SigHash.DEFAULT
17017
+ });
17018
+ tx.addOutputAddress(outputAddress, sendAmount, network);
17019
+ const signed = await identity.sign(tx);
17020
+ if (!path.extraWitness || path.extraWitness.length === 0) {
17021
+ signed.finalize();
17022
+ return { tx: signed, fee };
17023
+ }
17024
+ const input = signed.getInput(0);
17025
+ const tapScriptSig = input.tapScriptSig;
17026
+ if (!tapScriptSig || tapScriptSig.length === 0) {
17027
+ throw new Error("exit path requires additional signers");
17028
+ }
17029
+ const [controlBlock] = path.leaf;
17030
+ signed.updateInput(0, {
17031
+ finalScriptWitness: [
17032
+ tapScriptSig[0][1],
17033
+ ...path.extraWitness,
17034
+ scriptFromTapLeafScript(path.leaf),
17035
+ TaprootControlBlock.encode(controlBlock)
17036
+ ]
17037
+ });
17038
+ return { tx: signed, fee };
17039
+ }
17040
+
17041
+ // src/wallet/exit/estimate.ts
17042
+ var CHILD_OUTPUT_DUST = 546;
17043
+ function stepFundingAmount(stepFee) {
17044
+ return stepFee + CHILD_OUTPUT_DUST;
17045
+ }
17046
+ function resolveMode(opts) {
17047
+ return opts.mode ?? "funded";
17048
+ }
17049
+ function resolveNetworkName(opts) {
17050
+ if (opts.networkName) return opts.networkName;
17051
+ const { bech32 } = opts.wallet.network;
17052
+ if (bech32 === "bc") return "bitcoin";
17053
+ if (bech32 === "bcrt") return "regtest";
17054
+ return "testnet";
17055
+ }
17056
+ async function resolveFeeRate(opts) {
17057
+ if (opts.feeRate) return Math.ceil(opts.feeRate);
17058
+ const feeRate = await opts.wallet.onchainProvider.getFeeRate();
17059
+ if (!feeRate || feeRate < OnchainWallet.MIN_FEE_RATE) return OnchainWallet.MIN_FEE_RATE;
17060
+ return Math.ceil(feeRate);
17061
+ }
17062
+ async function selectExitVtxos(opts) {
17063
+ if (!opts.vtxos) return opts.wallet.getVtxos();
17064
+ const res = await opts.wallet.indexerProvider.getVtxos({ outpoints: opts.vtxos });
17065
+ const tapTrees = /* @__PURE__ */ new Map();
17066
+ const out = [];
17067
+ for (const vtxo of res.vtxos) {
17068
+ if (vtxo.isSpent) continue;
17069
+ let tapTree = tapTrees.get(vtxo.script);
17070
+ if (!tapTree) {
17071
+ const [contract] = await opts.wallet.contractRepository.getContracts({
17072
+ script: vtxo.script
17073
+ });
17074
+ if (!contract) {
17075
+ throw new Error(
17076
+ `no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
17077
+ );
17078
+ }
17079
+ const handler = contractHandlers.get(contract.type);
17080
+ if (!handler) {
17081
+ throw new Error(`no contract handler registered for type '${contract.type}'`);
17082
+ }
17083
+ tapTree = handler.createScript(contract.params).encode();
17084
+ tapTrees.set(vtxo.script, tapTree);
17085
+ }
17086
+ out.push({ txid: vtxo.txid, vout: vtxo.vout, value: vtxo.value, tapTree });
17087
+ }
17088
+ return out;
17089
+ }
17090
+ async function computeExitLayout(opts, feeRate) {
17091
+ const { wallet, onchainWallet } = opts;
17092
+ const vtxos = await selectExitVtxos(opts);
17093
+ if (vtxos.length === 0) throw new Error("no vtxos to exit");
17094
+ const dag = await buildExitDag({
17095
+ vtxos,
17096
+ indexer: wallet.indexerProvider,
17097
+ onchain: wallet.onchainProvider
17098
+ });
17099
+ const pendingNodes = dag.filter((n) => !n.confirmed);
17100
+ const psbts = /* @__PURE__ */ new Map();
17101
+ if (pendingNodes.length > 0) {
17102
+ const txids = pendingNodes.map((n) => n.txid);
17103
+ let pageIndex = 0;
17104
+ let hasMore = true;
17105
+ while (hasMore) {
17106
+ const { txs, page } = await wallet.indexerProvider.getVirtualTxs(txids, {
17107
+ pageIndex,
17108
+ pageSize: DEFAULT_PAGE_SIZE
17109
+ });
17110
+ for (const psbt of txs) {
17111
+ psbts.set(Transaction.fromPSBT(base64.decode(psbt)).id, psbt);
17112
+ }
17113
+ hasMore = page ? txs.length === DEFAULT_PAGE_SIZE : false;
17114
+ pageIndex++;
17115
+ }
17116
+ }
17117
+ const childVsize = Number(
17118
+ TxWeightEstimator.create().addP2AInput().addKeySpendInput(true).addOutputAddress(onchainWallet.address, wallet.network).vsize().value
17119
+ );
17120
+ const rawSteps = pendingNodes.map((node) => {
17121
+ const psbt = psbts.get(node.txid);
17122
+ if (!psbt) {
17123
+ throw new Error(`indexer did not return virtual tx ${node.txid}`);
17124
+ }
17125
+ const parent = finalizeVirtualTx(node.type, psbt);
17126
+ const stepFee = Math.ceil(feeRate * (parent.vsize + childVsize));
17127
+ return { node, parent, stepFee, funding: stepFundingAmount(stepFee) };
17128
+ });
17129
+ const parentInputTxids = (tx) => {
17130
+ const ids = [];
17131
+ for (let i = 0; i < tx.inputsLength; i++) {
17132
+ const txid = tx.getInput(i).txid;
17133
+ if (txid) ids.push(hex.encode(txid));
17134
+ }
17135
+ return ids;
17136
+ };
17137
+ const steps = topoSortByDeps(
17138
+ rawSteps,
17139
+ (s) => s.parent.id,
17140
+ (s) => parentInputTxids(s.parent)
17141
+ );
17142
+ const walletPubKeyHex = hex.encode(await wallet.identity.xOnlyPublicKey());
17143
+ const infos = [];
17144
+ const sweeps = [];
17145
+ for (const vtxo of vtxos) {
17146
+ const outpoint = `${vtxo.txid}:${vtxo.vout}`;
17147
+ try {
17148
+ const resolved = await resolveUnilateralPath({
17149
+ vtxo,
17150
+ scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
17151
+ contractRepository: wallet.contractRepository,
17152
+ walletPubKeyHex,
17153
+ currentTime: Date.now()
17154
+ });
17155
+ const sweepFee = sweepFeeFor(
17156
+ resolved.selection,
17157
+ opts.sweepAddress,
17158
+ wallet.network,
17159
+ feeRate
17160
+ );
17161
+ if (vtxo.value - sweepFee < CHILD_OUTPUT_DUST) {
17162
+ infos.push({
17163
+ outpoint,
17164
+ value: vtxo.value,
17165
+ skipped: `uneconomic: value ${vtxo.value} <= sweep fee + dust`
17166
+ });
17167
+ continue;
17168
+ }
17169
+ const t = sequenceToTimelock(resolved.selection.sequence);
17170
+ const delay = { type: t.type, value: Number(t.value) };
17171
+ infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
17172
+ sweeps.push({ vtxo, resolved, sweepFee, delay });
17173
+ } catch (e) {
17174
+ if (e instanceof ExitPathError) {
17175
+ infos.push({ outpoint, value: vtxo.value, skipped: e.message });
17176
+ continue;
17177
+ }
17178
+ throw e;
17179
+ }
17180
+ }
17181
+ const coins = (await onchainWallet.getCoins()).filter((c) => c.status.confirmed);
17182
+ const balance = coins.reduce((sum, c) => sum + c.value, 0);
17183
+ const fundingTotal = steps.reduce((sum, s) => sum + s.funding, 0);
17184
+ const splitterFeeFor = (inputCount) => {
17185
+ if (steps.length === 0) return 0;
17186
+ const est = TxWeightEstimator.create();
17187
+ for (let i = 0; i < inputCount; i++) est.addKeySpendInput(true);
17188
+ for (let i = 0; i < steps.length + 1; i++) {
17189
+ est.addOutputAddress(onchainWallet.address, wallet.network);
17190
+ }
17191
+ return Number(est.vsize().fee(BigInt(feeRate)));
17192
+ };
17193
+ const graph = resolveMode(opts) === "graph";
17194
+ let splitterFee = 0;
17195
+ if (!graph) {
17196
+ splitterFee = splitterFeeFor(Math.max(1, coins.length));
17197
+ if (steps.length > 0 && balance < fundingTotal + splitterFee) {
17198
+ splitterFee = splitterFeeFor(coins.length + 1);
17199
+ }
17200
+ }
17201
+ const stepFees = steps.reduce((s, x) => s + x.stepFee, 0);
17202
+ const sweepFees = sweeps.reduce((s, x) => s + x.sweepFee, 0);
17203
+ const totals = {
17204
+ // graph: each unroll step is parent + a live-built child (2 txs), no
17205
+ // splitter. funded: + 1 splitter tx and pre-signed children.
17206
+ txCount: (graph ? 0 : steps.length > 0 ? 1 : 0) + steps.length * 2 + sweeps.length,
17207
+ totalFeeSats: splitterFee + stepFees + sweepFees,
17208
+ // graph funding is what the executor sends to its own fee address:
17209
+ // just the CPFP fees (change recycles); funded also locks the
17210
+ // per-child dust into the splitter.
17211
+ fundingRequiredSats: graph ? stepFees : splitterFee + fundingTotal,
17212
+ recoveredSats: sweeps.reduce((s, x) => s + (x.vtxo.value - x.sweepFee), 0)
17213
+ };
17214
+ const expiries = pendingNodes.map((n) => n.expiresAt).filter((x) => x !== void 0);
17215
+ const validUntil = expiries.length > 0 ? Math.min(...expiries) : void 0;
17216
+ return {
17217
+ vtxos,
17218
+ dag,
17219
+ steps,
17220
+ sweeps,
17221
+ infos,
17222
+ totals,
17223
+ splitterFee,
17224
+ validUntil,
17225
+ balance,
17226
+ coins
17227
+ };
17228
+ }
17229
+ async function estimate(opts) {
17230
+ const feeRate = await resolveFeeRate(opts);
17231
+ const layout = await computeExitLayout(opts, feeRate);
17232
+ if (resolveMode(opts) === "graph") {
17233
+ return {
17234
+ feeRate,
17235
+ fundingAddress: "",
17236
+ currentBalanceSats: 0,
17237
+ shortfallSats: layout.totals.fundingRequiredSats,
17238
+ validUntil: layout.validUntil,
17239
+ totals: layout.totals,
17240
+ vtxos: layout.infos
17241
+ };
17242
+ }
17243
+ return {
17244
+ feeRate,
17245
+ fundingAddress: opts.onchainWallet.address,
17246
+ currentBalanceSats: layout.balance,
17247
+ shortfallSats: Math.max(0, layout.totals.fundingRequiredSats - layout.balance),
17248
+ validUntil: layout.validUntil,
17249
+ totals: layout.totals,
17250
+ vtxos: layout.infos
17251
+ };
17252
+ }
17253
+
17254
+ // src/wallet/exit/executor.ts
17255
+ var Executor = class {
17256
+ constructor(pkg, provider, opts) {
17257
+ this.pkg = pkg;
17258
+ this.provider = provider;
17259
+ this.pollIntervalMs = opts?.pollIntervalMs ?? 5e3;
17260
+ this.feeWallet = opts?.feeWallet;
17261
+ }
17262
+ pollIntervalMs;
17263
+ feeWallet;
17264
+ sleep() {
17265
+ return new Promise((r) => setTimeout(r, this.pollIntervalMs));
17266
+ }
17267
+ async status(txid) {
17268
+ try {
17269
+ return await this.provider.getTxStatus(txid);
17270
+ } catch {
17271
+ return void 0;
17272
+ }
17273
+ }
17274
+ async waitConfirmed(txid) {
17275
+ for (; ; ) {
17276
+ const s = await this.status(txid);
17277
+ if (s?.confirmed) return s;
17278
+ await this.sleep();
17279
+ }
17280
+ }
17281
+ async *[Symbol.asyncIterator]() {
17282
+ const dead = /* @__PURE__ */ new Set();
17283
+ if (this.pkg.validUntil && Date.now() / 1e3 > this.pkg.validUntil) {
17284
+ yield {
17285
+ stepIndex: -1,
17286
+ kind: "broadcast",
17287
+ status: "warning",
17288
+ reason: `package validUntil ${this.pkg.validUntil} has passed; the operator may have swept \u2014 attempting anyway`
17289
+ };
17290
+ }
17291
+ const sweeps = [];
17292
+ for (let i = 0; i < this.pkg.steps.length; i++) {
17293
+ const step = this.pkg.steps[i];
17294
+ if (step.kind === "sweep") {
17295
+ sweeps.push({ index: i, step });
17296
+ continue;
17297
+ }
17298
+ const forVtxos = step.kind === "package" || step.kind === "bump" ? step.forVtxos : void 0;
17299
+ if (forVtxos && forVtxos.every((v) => dead.has(v))) {
17300
+ yield {
17301
+ stepIndex: i,
17302
+ kind: step.kind,
17303
+ status: "skipped",
17304
+ forVtxos,
17305
+ reason: "branch failed earlier"
17306
+ };
17307
+ continue;
17308
+ }
17309
+ const anchorTxid = step.kind === "package" || step.kind === "bump" ? step.parentTxid : step.txid;
17310
+ const existing = await this.status(anchorTxid);
17311
+ if (existing?.confirmed) {
17312
+ yield {
17313
+ stepIndex: i,
17314
+ kind: step.kind,
17315
+ status: "skipped",
17316
+ txid: anchorTxid,
17317
+ forVtxos
17318
+ };
17319
+ continue;
17320
+ }
17321
+ if (!existing) {
17322
+ try {
17323
+ if (step.kind === "package") {
17324
+ await this.provider.broadcastTransaction(step.parentHex, step.childHex);
17325
+ } else if (step.kind === "bump") {
17326
+ if (!this.feeWallet) {
17327
+ throw new Error(
17328
+ "graph package requires a fee wallet (opts.feeWallet) to fund CPFP bumps"
17329
+ );
17330
+ }
17331
+ const [parentHex, childHex] = await this.feeWallet.bumpAnchor(
17332
+ step.parentHex,
17333
+ this.pkg.feeRate
17334
+ );
17335
+ await this.provider.broadcastTransaction(parentHex, childHex);
17336
+ } else {
17337
+ await this.provider.broadcastTransaction(step.hex);
17338
+ }
17339
+ yield {
17340
+ stepIndex: i,
17341
+ kind: step.kind,
17342
+ status: "broadcast",
17343
+ txid: anchorTxid,
17344
+ forVtxos
17345
+ };
17346
+ } catch (e) {
17347
+ const reason = e instanceof Error ? e.message : String(e);
17348
+ if (step.kind === "broadcast") {
17349
+ for (const s of this.pkg.steps) {
17350
+ if (s.kind === "package") s.forVtxos.forEach((v) => dead.add(v));
17351
+ }
17352
+ } else if (step.kind === "package" || step.kind === "bump") {
17353
+ step.forVtxos.forEach((v) => dead.add(v));
17354
+ }
17355
+ yield {
17356
+ stepIndex: i,
17357
+ kind: step.kind,
17358
+ status: "failed",
17359
+ txid: anchorTxid,
17360
+ forVtxos,
17361
+ reason
17362
+ };
17363
+ continue;
17364
+ }
17365
+ }
17366
+ await this.waitConfirmed(anchorTxid);
17367
+ yield {
17368
+ stepIndex: i,
17369
+ kind: step.kind,
17370
+ status: "confirmed",
17371
+ txid: anchorTxid,
17372
+ forVtxos
17373
+ };
17374
+ }
17375
+ for (const { index, step } of sweeps) {
17376
+ if (dead.has(step.vtxo)) {
17377
+ yield {
17378
+ stepIndex: index,
17379
+ kind: "sweep",
17380
+ status: "failed",
17381
+ txid: step.txid,
17382
+ forVtxos: [step.vtxo],
17383
+ reason: "branch failed earlier"
17384
+ };
17385
+ }
17386
+ }
17387
+ const pending = sweeps.filter(({ step }) => !dead.has(step.vtxo));
17388
+ const waitingAnnounced = /* @__PURE__ */ new Set();
17389
+ const done = /* @__PURE__ */ new Set();
17390
+ while (done.size < pending.length) {
17391
+ for (const { index, step } of pending) {
17392
+ if (done.has(index)) continue;
17393
+ const swept = await this.status(step.txid);
17394
+ if (swept?.confirmed) {
17395
+ done.add(index);
17396
+ yield {
17397
+ stepIndex: index,
17398
+ kind: "sweep",
17399
+ status: "confirmed",
17400
+ txid: step.txid,
17401
+ forVtxos: [step.vtxo]
17402
+ };
17403
+ continue;
17404
+ }
17405
+ if (swept) continue;
17406
+ const dep = await this.status(step.dependsOnTxid);
17407
+ if (!dep?.confirmed) continue;
17408
+ const tip = await this.provider.getChainTip();
17409
+ const mature = step.delay.type === "blocks" ? tip.height >= (dep.blockHeight ?? 0) + step.delay.value : tip.time >= (dep.blockTime ?? 0) + step.delay.value;
17410
+ if (!mature) {
17411
+ if (!waitingAnnounced.has(index)) {
17412
+ waitingAnnounced.add(index);
17413
+ yield {
17414
+ stepIndex: index,
17415
+ kind: "sweep",
17416
+ status: "waiting_csv",
17417
+ txid: step.txid,
17418
+ forVtxos: [step.vtxo],
17419
+ ...step.delay.type === "blocks" ? { maturesAtHeight: (dep.blockHeight ?? 0) + step.delay.value } : { maturesAtTime: (dep.blockTime ?? 0) + step.delay.value }
17420
+ };
17421
+ }
17422
+ continue;
17423
+ }
17424
+ try {
17425
+ await this.provider.broadcastTransaction(step.hex);
17426
+ yield {
17427
+ stepIndex: index,
17428
+ kind: "sweep",
17429
+ status: "broadcast",
17430
+ txid: step.txid,
17431
+ forVtxos: [step.vtxo]
17432
+ };
17433
+ } catch (e) {
17434
+ const reason = e instanceof Error ? e.message : String(e);
17435
+ if (/non-?bip68|non-?final|premature/i.test(reason)) {
17436
+ continue;
17437
+ }
17438
+ done.add(index);
17439
+ yield {
17440
+ stepIndex: index,
17441
+ kind: "sweep",
17442
+ status: "failed",
17443
+ txid: step.txid,
17444
+ forVtxos: [step.vtxo],
17445
+ reason
17446
+ };
17447
+ }
17448
+ }
17449
+ if (done.size < pending.length) await this.sleep();
17450
+ }
17451
+ }
17452
+ };
17453
+ async function prepare(opts) {
17454
+ const { wallet, onchainWallet } = opts;
17455
+ const feeRate = await resolveFeeRate(opts);
17456
+ const mode = resolveMode(opts);
17457
+ if (mode === "funded") {
17458
+ const walletKey = await wallet.identity.xOnlyPublicKey();
17459
+ if (hex.encode(onchainWallet.onchainP2TR.tapInternalKey) !== hex.encode(walletKey)) {
17460
+ throw new Error("onchainWallet must share the wallet identity");
17461
+ }
17462
+ }
17463
+ const layout = await computeExitLayout(opts, feeRate);
17464
+ const sweepSteps = [];
17465
+ const activeOutpoints = /* @__PURE__ */ new Set();
17466
+ for (const sweep of layout.sweeps) {
17467
+ const outpoint = `${sweep.vtxo.txid}:${sweep.vtxo.vout}`;
17468
+ try {
17469
+ const { tx } = await buildSignedSweep({
17470
+ vtxo: {
17471
+ txid: sweep.vtxo.txid,
17472
+ vout: sweep.vtxo.vout,
17473
+ value: sweep.vtxo.value,
17474
+ pkScript: VtxoScript.decode(sweep.vtxo.tapTree).pkScript
17475
+ },
17476
+ path: sweep.resolved.selection,
17477
+ outputAddress: opts.sweepAddress,
17478
+ feeRate,
17479
+ network: wallet.network,
17480
+ identity: wallet.identity
17481
+ });
17482
+ activeOutpoints.add(outpoint);
17483
+ sweepSteps.push({
17484
+ kind: "sweep",
17485
+ vtxo: outpoint,
17486
+ txid: tx.id,
17487
+ hex: tx.hex,
17488
+ dependsOnTxid: sweep.vtxo.txid,
17489
+ delay: sweep.delay
17490
+ });
17491
+ } catch (e) {
17492
+ const info = layout.infos.find((i) => i.outpoint === outpoint);
17493
+ if (info) {
17494
+ info.skipped = e instanceof Error ? e.message : String(e);
17495
+ delete info.sweepFee;
17496
+ delete info.path;
17497
+ delete info.delay;
17498
+ }
17499
+ }
17500
+ }
17501
+ const steps = layout.steps.filter((s) => s.node.forVtxos.some((v) => activeOutpoints.has(v)));
17502
+ if (steps.length === 0 && sweepSteps.length === 0) {
17503
+ throw new Error("no exitable vtxos (all skipped)");
17504
+ }
17505
+ if (mode === "graph") {
17506
+ const bumpSteps = steps.map((step) => ({
17507
+ kind: "bump",
17508
+ parentTxid: step.parent.id,
17509
+ parentHex: step.parent.hex,
17510
+ forVtxos: step.node.forVtxos.filter((v) => activeOutpoints.has(v))
17511
+ }));
17512
+ const stepFees2 = steps.reduce((s, x) => s + x.stepFee, 0);
17513
+ const activeInfos2 = layout.infos.filter((i) => !i.skipped);
17514
+ const sweepFees2 = activeInfos2.reduce((s, i) => s + (i.sweepFee ?? 0), 0);
17515
+ const recovered2 = activeInfos2.reduce((s, i) => s + (i.value ?? 0) - (i.sweepFee ?? 0), 0);
17516
+ return {
17517
+ version: 1,
17518
+ mode: "graph",
17519
+ network: resolveNetworkName(opts),
17520
+ createdAt: Math.floor(Date.now() / 1e3),
17521
+ validUntil: layout.validUntil,
17522
+ feeRate,
17523
+ sweepAddress: opts.sweepAddress,
17524
+ totals: {
17525
+ txCount: bumpSteps.length * 2 + sweepSteps.length,
17526
+ totalFeeSats: stepFees2 + sweepFees2,
17527
+ fundingRequiredSats: stepFees2,
17528
+ recoveredSats: recovered2
17529
+ },
17530
+ vtxos: layout.infos,
17531
+ steps: [...bumpSteps, ...sweepSteps]
17532
+ };
17533
+ }
17534
+ const packageSteps = [];
17535
+ let broadcastStep;
17536
+ let splitterFee = 0;
17537
+ if (steps.length > 0) {
17538
+ const fundingTotal = steps.reduce((sum, s) => sum + s.funding, 0);
17539
+ let selected = { inputs: [], changeAmount: 0n };
17540
+ for (let i = 0; i < 10; i++) {
17541
+ const target = fundingTotal + splitterFee;
17542
+ try {
17543
+ selected = selectCoins(layout.coins, target);
17544
+ } catch {
17545
+ throw new Error(
17546
+ `insufficient confirmed onchain funds: need ${target} sats, have ${layout.balance} (deposit the shortfall to ${onchainWallet.address})`
17547
+ );
17548
+ }
17549
+ const est = TxWeightEstimator.create();
17550
+ for (const _ of selected.inputs) est.addKeySpendInput(true);
17551
+ for (const _ of steps) est.addOutputAddress(onchainWallet.address, wallet.network);
17552
+ if (selected.changeAmount >= BigInt(DUST_AMOUNT)) {
17553
+ est.addOutputAddress(onchainWallet.address, wallet.network);
17554
+ }
17555
+ const newFee = Number(est.vsize().fee(BigInt(feeRate)));
17556
+ if (newFee <= splitterFee) break;
17557
+ splitterFee = newFee;
17558
+ }
17559
+ const splitter = new Transaction({ version: 2 });
17560
+ for (const coin of selected.inputs) {
17561
+ splitter.addInput({
17562
+ txid: coin.txid,
17563
+ index: coin.vout,
17564
+ witnessUtxo: {
17565
+ script: onchainWallet.onchainP2TR.script,
17566
+ amount: BigInt(coin.value)
17567
+ },
17568
+ tapInternalKey: onchainWallet.onchainP2TR.tapInternalKey
17569
+ });
17570
+ }
17571
+ for (const step of steps) {
17572
+ splitter.addOutputAddress(onchainWallet.address, BigInt(step.funding), wallet.network);
17573
+ }
17574
+ const inputSum = selected.inputs.reduce((s, c) => s + c.value, 0);
17575
+ const change = BigInt(inputSum - fundingTotal - splitterFee);
17576
+ if (change < 0n) {
17577
+ throw new Error(
17578
+ `insufficient confirmed onchain funds for the splitter fee: need ${fundingTotal + splitterFee} sats, have ${inputSum} (deposit the shortfall to ${onchainWallet.address})`
17579
+ );
17580
+ }
17581
+ if (change >= BigInt(DUST_AMOUNT)) {
17582
+ splitter.addOutputAddress(onchainWallet.address, change, wallet.network);
17583
+ } else if (change > 0n) {
17584
+ splitterFee += Number(change);
17585
+ }
17586
+ const signedSplitter = await wallet.identity.sign(splitter);
17587
+ signedSplitter.finalize();
17588
+ for (let k = 0; k < steps.length; k++) {
17589
+ const step = steps[k];
17590
+ const { child } = buildAnchorChild({
17591
+ parent: step.parent,
17592
+ feeRate,
17593
+ fundingCoins: [{ txid: signedSplitter.id, vout: k, value: step.funding }],
17594
+ changeAddress: onchainWallet.address,
17595
+ changeScript: onchainWallet.onchainP2TR.script,
17596
+ tapInternalKey: onchainWallet.onchainP2TR.tapInternalKey,
17597
+ network: wallet.network
17598
+ });
17599
+ const signedChild = await wallet.identity.sign(child);
17600
+ for (let i = 1; i < signedChild.inputsLength; i++) {
17601
+ signedChild.finalizeIdx(i);
17602
+ }
17603
+ packageSteps.push({
17604
+ kind: "package",
17605
+ parentTxid: step.parent.id,
17606
+ parentHex: step.parent.hex,
17607
+ childTxid: signedChild.id,
17608
+ childHex: signedChild.hex,
17609
+ forVtxos: step.node.forVtxos.filter((v) => activeOutpoints.has(v))
17610
+ });
17611
+ }
17612
+ broadcastStep = { kind: "broadcast", txid: signedSplitter.id, hex: signedSplitter.hex };
17613
+ await onchainWallet.provider.broadcastTransaction(signedSplitter.hex);
17614
+ }
17615
+ const stepFees = steps.reduce((s, x) => s + x.stepFee, 0);
17616
+ const activeInfos = layout.infos.filter((i) => !i.skipped);
17617
+ const sweepFees = activeInfos.reduce((s, i) => s + (i.sweepFee ?? 0), 0);
17618
+ const recovered = activeInfos.reduce((s, i) => s + (i.value ?? 0) - (i.sweepFee ?? 0), 0);
17619
+ const fundingRequired = splitterFee + steps.reduce((s, x) => s + x.funding, 0);
17620
+ return {
17621
+ version: 1,
17622
+ mode: "funded",
17623
+ network: resolveNetworkName(opts),
17624
+ createdAt: Math.floor(Date.now() / 1e3),
17625
+ validUntil: layout.validUntil,
17626
+ feeRate,
17627
+ sweepAddress: opts.sweepAddress,
17628
+ totals: {
17629
+ txCount: (broadcastStep ? 1 : 0) + packageSteps.length * 2 + sweepSteps.length,
17630
+ totalFeeSats: splitterFee + stepFees + sweepFees,
17631
+ fundingRequiredSats: fundingRequired,
17632
+ recoveredSats: recovered
17633
+ },
17634
+ vtxos: layout.infos,
17635
+ steps: [...broadcastStep ? [broadcastStep] : [], ...packageSteps, ...sweepSteps]
17636
+ };
17637
+ }
17638
+
17639
+ // src/wallet/exit/types.ts
17640
+ function serializeExitPackage(pkg) {
17641
+ return JSON.stringify(pkg);
17642
+ }
17643
+ function deserializeExitPackage(json) {
17644
+ const data = JSON.parse(json);
17645
+ if (data?.version !== 1) {
17646
+ throw new Error(`unsupported exit package version: ${data?.version}`);
17647
+ }
17648
+ if (typeof data.network !== "string" || typeof data.sweepAddress !== "string") {
17649
+ throw new Error("invalid exit package: missing network or sweepAddress");
17650
+ }
17651
+ if (typeof data.feeRate !== "number" || typeof data.createdAt !== "number") {
17652
+ throw new Error("invalid exit package: missing feeRate or createdAt");
17653
+ }
17654
+ if (!Array.isArray(data.steps) || !Array.isArray(data.vtxos)) {
17655
+ throw new Error("invalid exit package: steps and vtxos must be arrays");
17656
+ }
17657
+ if (!isValidTotals(data.totals)) {
17658
+ throw new Error("invalid exit package: malformed totals");
17659
+ }
17660
+ for (const step of data.steps) {
17661
+ if (!isValidStep(step)) {
17662
+ throw new Error(`invalid step: ${JSON.stringify(step)}`);
17663
+ }
17664
+ }
17665
+ return data;
17666
+ }
17667
+ function isValidDelay(d) {
17668
+ const delay = d;
17669
+ return !!delay && (delay.type === "blocks" || delay.type === "seconds") && typeof delay.value === "number";
17670
+ }
17671
+ function isValidTotals(t) {
17672
+ const totals = t;
17673
+ return !!totals && typeof totals === "object" && typeof totals.txCount === "number" && typeof totals.totalFeeSats === "number" && typeof totals.fundingRequiredSats === "number" && typeof totals.recoveredSats === "number";
17674
+ }
17675
+ function isValidStep(step) {
17676
+ const s = step;
17677
+ if (!s || typeof s !== "object") return false;
17678
+ switch (s.kind) {
17679
+ case "broadcast":
17680
+ return typeof s.txid === "string" && typeof s.hex === "string";
17681
+ case "package":
17682
+ return typeof s.parentTxid === "string" && typeof s.parentHex === "string" && typeof s.childTxid === "string" && typeof s.childHex === "string" && Array.isArray(s.forVtxos);
17683
+ case "bump":
17684
+ return typeof s.parentTxid === "string" && typeof s.parentHex === "string" && Array.isArray(s.forVtxos);
17685
+ case "sweep":
17686
+ return typeof s.vtxo === "string" && typeof s.txid === "string" && typeof s.hex === "string" && typeof s.dependsOnTxid === "string" && isValidDelay(s.delay);
17687
+ default:
17688
+ return false;
17689
+ }
17690
+ }
17691
+
17692
+ // src/wallet/exit/index.ts
17693
+ var UnilateralExit = {
17694
+ estimate,
17695
+ prepare,
17696
+ Executor
17697
+ };
16791
17698
  var ARKCONTRACT_PREFIX = "arkcontract";
16792
17699
  function encodeArkContract(contract) {
16793
17700
  const params = new URLSearchParams();
@@ -16847,6 +17754,6 @@ function isArkContract(str) {
16847
17754
  return str.startsWith(ARKCONTRACT_PREFIX + "=");
16848
17755
  }
16849
17756
 
16850
- export { ActivityRegistry, ArkNote, AssetManager, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EsploraProvider, Estimator, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createDefaultActivityRegistry, decodeArkContract, deserializeAssets, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, serializeAssets, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
16851
- //# sourceMappingURL=chunk-B4R36PRN.js.map
16852
- //# sourceMappingURL=chunk-B4R36PRN.js.map
17757
+ export { ActivityRegistry, ArkNote, AssetManager, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EsploraProvider, Estimator, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createDefaultActivityRegistry, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
17758
+ //# sourceMappingURL=chunk-FMI2GKYO.js.map
17759
+ //# sourceMappingURL=chunk-FMI2GKYO.js.map