@arkade-os/sdk 0.5.1 → 0.5.2

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 (72) hide show
  1. package/README.md +9 -5
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +2 -2
  4. package/dist/adapters/expo.d.ts +2 -2
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/{asyncStorageTaskQueue-DFt5LgW5.d.cts → asyncStorageTaskQueue-BtEc3Qca.d.cts} +1 -1
  7. package/dist/{asyncStorageTaskQueue-CdWheMqT.d.ts → asyncStorageTaskQueue-DIn7bTqN.d.ts} +1 -1
  8. package/dist/{chunk-QKNSMVBW.cjs → chunk-2OCYL6BJ.cjs} +1142 -843
  9. package/dist/chunk-2OCYL6BJ.cjs.map +1 -0
  10. package/dist/{chunk-FXVEOEYB.js → chunk-2QRUQXLS.js} +4 -4
  11. package/dist/{chunk-FXVEOEYB.js.map → chunk-2QRUQXLS.js.map} +1 -1
  12. package/dist/{chunk-HQNQ3CLQ.cjs → chunk-64R7CRKN.cjs} +18 -18
  13. package/dist/{chunk-HQNQ3CLQ.cjs.map → chunk-64R7CRKN.cjs.map} +1 -1
  14. package/dist/{chunk-NKKJEA3Z.js → chunk-AJWXVQYG.js} +657 -358
  15. package/dist/chunk-AJWXVQYG.js.map +1 -0
  16. package/dist/{chunk-XLHUGP3G.cjs → chunk-GGKR4O5X.cjs} +3 -3
  17. package/dist/{chunk-XLHUGP3G.cjs.map → chunk-GGKR4O5X.cjs.map} +1 -1
  18. package/dist/{chunk-QFB55EOZ.js → chunk-HKG26NUT.js} +3 -3
  19. package/dist/{chunk-QFB55EOZ.js.map → chunk-HKG26NUT.js.map} +1 -1
  20. package/dist/{chunk-3M22PJVB.js → chunk-LWRMSC4M.js} +3 -3
  21. package/dist/{chunk-3M22PJVB.js.map → chunk-LWRMSC4M.js.map} +1 -1
  22. package/dist/{chunk-XQRIY5K5.js → chunk-MOBDJ7U2.js} +4 -4
  23. package/dist/{chunk-XQRIY5K5.js.map → chunk-MOBDJ7U2.js.map} +1 -1
  24. package/dist/{chunk-GW42FS2X.cjs → chunk-OM6FJ76H.cjs} +48 -48
  25. package/dist/{chunk-GW42FS2X.cjs.map → chunk-OM6FJ76H.cjs.map} +1 -1
  26. package/dist/{chunk-JJ6QKTFZ.cjs → chunk-PVFQFQBY.cjs} +10 -10
  27. package/dist/{chunk-JJ6QKTFZ.cjs.map → chunk-PVFQFQBY.cjs.map} +1 -1
  28. package/dist/{chunk-GQUFPTN7.cjs → chunk-TAIWH3HG.cjs} +16 -16
  29. package/dist/{chunk-GQUFPTN7.cjs.map → chunk-TAIWH3HG.cjs.map} +1 -1
  30. package/dist/{chunk-6MIGYYWB.js → chunk-U5XG7SWA.js} +3 -3
  31. package/dist/{chunk-6MIGYYWB.js.map → chunk-U5XG7SWA.js.map} +1 -1
  32. package/dist/contracts/handlers/index.cjs +9 -9
  33. package/dist/contracts/handlers/index.d.cts +3 -3
  34. package/dist/contracts/handlers/index.d.ts +3 -3
  35. package/dist/contracts/handlers/index.js +2 -2
  36. package/dist/{delegate-CFCfrReG.d.cts → delegate-CaL8EN4Q.d.cts} +1 -1
  37. package/dist/{delegate-BSbGQabI.d.ts → delegate-Jd4zs88Q.d.ts} +1 -1
  38. package/dist/{index-Fpf4mQZr.d.cts → index-BwdGzNSn.d.cts} +2 -2
  39. package/dist/{index-CzUVvIxA.d.ts → index-D-xqVzf8.d.ts} +2 -2
  40. package/dist/{index-B3fRWO5i.d.cts → index-DdKxfC29.d.cts} +26 -16
  41. package/dist/{index-B3fRWO5i.d.ts → index-DdKxfC29.d.ts} +26 -16
  42. package/dist/index.cjs +313 -313
  43. package/dist/index.d.cts +93 -26
  44. package/dist/index.d.ts +93 -26
  45. package/dist/index.js +4 -4
  46. package/dist/repositories/realm/index.cjs +35 -35
  47. package/dist/repositories/realm/index.d.cts +2 -2
  48. package/dist/repositories/realm/index.d.ts +2 -2
  49. package/dist/repositories/realm/index.js +5 -5
  50. package/dist/repositories/sqlite/index.cjs +33 -33
  51. package/dist/repositories/sqlite/index.d.cts +2 -2
  52. package/dist/repositories/sqlite/index.d.ts +2 -2
  53. package/dist/repositories/sqlite/index.js +5 -5
  54. package/dist/{taskRunner-Dk6oDAtd.d.cts → taskRunner-67YSEpsz.d.cts} +1 -1
  55. package/dist/{taskRunner-CdfoCMaw.d.ts → taskRunner-ZyGGjtIq.d.ts} +1 -1
  56. package/dist/wallet/expo/background.cjs +14 -14
  57. package/dist/wallet/expo/background.d.cts +3 -3
  58. package/dist/wallet/expo/background.d.ts +3 -3
  59. package/dist/wallet/expo/background.js +6 -6
  60. package/dist/wallet/expo/index.cjs +15 -15
  61. package/dist/wallet/expo/index.d.cts +4 -4
  62. package/dist/wallet/expo/index.d.ts +4 -4
  63. package/dist/wallet/expo/index.js +5 -5
  64. package/dist/{wallet-D9dvXu-K.d.cts → wallet-B8LW7cV1.d.cts} +6 -5
  65. package/dist/{wallet-BQHNgc_v.d.ts → wallet-bFS7VybL.d.ts} +6 -5
  66. package/dist/worker/expo/index.cjs +9 -9
  67. package/dist/worker/expo/index.d.cts +4 -4
  68. package/dist/worker/expo/index.d.ts +4 -4
  69. package/dist/worker/expo/index.js +5 -5
  70. package/package.json +1 -1
  71. package/dist/chunk-NKKJEA3Z.js.map +0 -1
  72. package/dist/chunk-QKNSMVBW.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, RestIndexerProvider, BufferReader, BufferWriter, AssetRef } from './chunk-6MIGYYWB.js';
2
- import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, UnsupportedProgramVersionError, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, ARKADE_TYPE_ENCODINGS, validateParamValue, contractHandlers, speculativeReceiveMetadata, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-3M22PJVB.js';
3
- import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, timelockToSequence, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, RestArkProvider, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, assertNonNegativeMs, isRetryableProviderError, getAllNormalizedVtxos, DEFAULT_PAGE_SIZE, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL, baseFetch, DEFAULT_NETWORK_NAME, sequenceToCanonicalTimelock, assertTimerMs, isEventSourceError, isEventSourceUnavailableError, normalizeVtxo, isPastExpiry, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, isArkError, ArkErrorName, assertAllowedSighashTypes, Intent, rateGate, formatSighash, getSequence, maybeArkError, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, DEFAULT_ARKADE_EMULATOR_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-QFB55EOZ.js';
1
+ import { Packet, AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, RestIndexerProvider, BufferReader, BufferWriter, AssetRef } from './chunk-U5XG7SWA.js';
2
+ import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, UnsupportedProgramVersionError, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, ARKADE_TYPE_ENCODINGS, validateParamValue, contractHandlers, speculativeReceiveMetadata, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-LWRMSC4M.js';
3
+ import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, timelockToSequence, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, getArkPsbtFields, craftToSpendTx, RestArkProvider, ArkAddress, isVirtualCoin, CosignerPublicKey, ServerResponseMismatchError, assertNonNegativeMs, isRetryableProviderError, getAllNormalizedVtxos, DEFAULT_PAGE_SIZE, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, DEFAULT_ARKADE_SERVER_URL, baseFetch, DEFAULT_NETWORK_NAME, sequenceToCanonicalTimelock, assertTimerMs, isEventSourceError, isEventSourceUnavailableError, normalizeVtxo, isPastExpiry, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, isArkError, ArkErrorName, assertAllowedSighashTypes, Intent, rateGate, formatSighash, getSequence, maybeArkError, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, DEFAULT_ARKADE_EMULATOR_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-HKG26NUT.js';
4
4
  import { sha256, equalBytes, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr } from '@scure/btc-signer/utils.js';
5
5
  import { SigHash, Script, OP, OutScript, Address, RawWitness, p2tr, p2wpkh, TaprootControlBlock, DEFAULT_SEQUENCE, Transaction as Transaction$1 } from '@scure/btc-signer';
6
6
  import { hex, base58, base64, bech32m } from '@scure/base';
@@ -1328,10 +1328,15 @@ async function provisionDescriptor(wallet) {
1328
1328
  return allocated ?? await identityDescriptor(wallet.identity);
1329
1329
  }
1330
1330
  async function provisionRefundKey(wallet) {
1331
- const descriptor = await identityDescriptor(wallet.identity);
1331
+ const descriptorPromise = identityDescriptor(wallet.identity);
1332
+ const identityPubkeyPromise = wallet.identity.xOnlyPublicKey();
1333
+ void identityPubkeyPromise.catch(() => void 0);
1334
+ const descriptor = await descriptorPromise;
1332
1335
  const signer = await contractSigner(wallet, descriptor);
1333
- const pubkey = await signer.xOnlyPublicKey();
1334
- const identityPubkey = await wallet.identity.xOnlyPublicKey();
1336
+ const [pubkey, identityPubkey] = await Promise.all([
1337
+ signer.xOnlyPublicKey(),
1338
+ identityPubkeyPromise
1339
+ ]);
1335
1340
  if (!equalBytes(pubkey, identityPubkey)) {
1336
1341
  throw new Error(
1337
1342
  "provisionRefundKey: descriptor pubkey does not match wallet identity \u2014 the refund key and the refund address would be on different keys"
@@ -1347,7 +1352,6 @@ async function provisionClaimSecret(wallet, opts = {}) {
1347
1352
  }
1348
1353
  const descriptor = await provisionDescriptor(wallet);
1349
1354
  const signer = await contractSigner(wallet, descriptor);
1350
- const pubkey = await signer.xOnlyPublicKey();
1351
1355
  const claim2 = async () => {
1352
1356
  if (opts.preimage) return { preimage: opts.preimage, mustPersistPreimage: true };
1353
1357
  if (isPerArtifactDescriptor(descriptor)) {
@@ -1370,7 +1374,10 @@ async function provisionClaimSecret(wallet, opts = {}) {
1370
1374
  return { preimage: randomBytes(32), mustPersistPreimage: true };
1371
1375
  }
1372
1376
  };
1373
- const { preimage, preimageSalt, mustPersistPreimage } = await claim2();
1377
+ const [pubkey, { preimage, preimageSalt, mustPersistPreimage }] = await Promise.all([
1378
+ signer.xOnlyPublicKey(),
1379
+ claim2()
1380
+ ]);
1374
1381
  return {
1375
1382
  descriptor,
1376
1383
  pubkey,
@@ -4676,12 +4683,14 @@ var VtxoManager = class _VtxoManager {
4676
4683
  * ```
4677
4684
  */
4678
4685
  async recoverVtxos(eventCallback) {
4679
- const allVtxos = await this.wallet.getVtxos({
4680
- withRecoverable: true,
4681
- withUnrolled: false
4682
- });
4686
+ const [allVtxos, now] = await Promise.all([
4687
+ this.wallet.getVtxos({
4688
+ withRecoverable: true,
4689
+ withUnrolled: false
4690
+ }),
4691
+ fetchTimeHeight(this.wallet)
4692
+ ]);
4683
4693
  const dustAmount = getDustAmount(this.wallet);
4684
- const now = await fetchTimeHeight(this.wallet);
4685
4694
  let { vtxosToRecover } = getRecoverableWithSubdust(allVtxos, dustAmount, now);
4686
4695
  if (vtxosToRecover.length === 0) {
4687
4696
  throw new Error("No recoverable VTXOs found");
@@ -4782,12 +4791,17 @@ var VtxoManager = class _VtxoManager {
4782
4791
  * ```
4783
4792
  */
4784
4793
  async getRecoverableBalance() {
4785
- const allVtxos = await this.wallet.getVtxos({
4786
- withRecoverable: true,
4787
- withUnrolled: false
4788
- });
4794
+ const infoProvider = this.getInfoProvider();
4795
+ const [allVtxos, now, info, arkAddress] = await Promise.all([
4796
+ this.wallet.getVtxos({
4797
+ withRecoverable: true,
4798
+ withUnrolled: false
4799
+ }),
4800
+ fetchTimeHeight(this.wallet),
4801
+ infoProvider?.getInfo(),
4802
+ this.wallet.getAddress()
4803
+ ]);
4789
4804
  const dustAmount = getDustAmount(this.wallet);
4790
- const now = await fetchTimeHeight(this.wallet);
4791
4805
  let { vtxosToRecover, includesSubdust } = getRecoverableWithSubdust(
4792
4806
  allVtxos,
4793
4807
  dustAmount,
@@ -4805,14 +4819,9 @@ var VtxoManager = class _VtxoManager {
4805
4819
  now
4806
4820
  ));
4807
4821
  }
4808
- const info = await this.getInfoProvider()?.getInfo();
4809
4822
  const estimator = new Estimator(info?.fees.intentFee ?? {});
4810
4823
  const { payable, net } = priceSettlementInputs(vtxosToRecover, estimator);
4811
- const priced = deductOffchainOutputFee(
4812
- subtotalOf(payable, net),
4813
- estimator,
4814
- await this.wallet.getAddress()
4815
- );
4824
+ const priced = deductOffchainOutputFee(subtotalOf(payable, net), estimator, arkAddress);
4816
4825
  const recoverable = priced > 0n ? priced : 0n;
4817
4826
  const subdustAmount = subtotalOf(
4818
4827
  payable.filter((v) => BigInt(v.value) < dustAmount),
@@ -4866,8 +4875,11 @@ var VtxoManager = class _VtxoManager {
4866
4875
  const cm = await wallet.getContractManager();
4867
4876
  const recoveryScripts = (await cm.getContracts()).filter(isRecoveryOnlyContract).map((contract) => contract.script);
4868
4877
  if (recoveryScripts.length === 0) return;
4869
- const recoveryContracts = await cm.getContractsWithVtxos({ script: recoveryScripts });
4870
- const info = await this.getInfoProvider()?.getInfo();
4878
+ const infoProvider = this.getInfoProvider();
4879
+ const [recoveryContracts, info] = await Promise.all([
4880
+ cm.getContractsWithVtxos({ script: recoveryScripts }),
4881
+ infoProvider?.getInfo()
4882
+ ]);
4871
4883
  const dustAmount = getDustAmount(wallet);
4872
4884
  for (const { contract, vtxos } of recoveryContracts) {
4873
4885
  try {
@@ -4962,12 +4974,13 @@ var VtxoManager = class _VtxoManager {
4962
4974
  if (this.settlementConfig === false && thresholdMs === void 0) {
4963
4975
  return [];
4964
4976
  }
4965
- const vtxos = await this.wallet.getSpendableVtxos({
4977
+ const threshold = thresholdMs !== void 0 ? thresholdMs : this.configuredThresholdMs();
4978
+ const vtxosPromise = this.wallet.getSpendableVtxos({
4966
4979
  withRecoverable: true,
4967
4980
  genericallySpendableOnly: true
4968
4981
  });
4969
- const threshold = thresholdMs !== void 0 ? thresholdMs : this.configuredThresholdMs();
4970
4982
  const tip = now ?? await fetchTimeHeight(this.wallet);
4983
+ const vtxos = await vtxosPromise;
4971
4984
  await this.warnHeldExpiring(threshold, tip);
4972
4985
  return getExpiringAndRecoverableVtxos(vtxos, threshold, getDustAmount(this.wallet), tip);
4973
4986
  }
@@ -5261,8 +5274,10 @@ var VtxoManager = class _VtxoManager {
5261
5274
  const wallet = this.requireMigrationCapableWallet();
5262
5275
  const info = await wallet.arkProvider.getInfo();
5263
5276
  await wallet.settleServerInfoChanges?.();
5264
- const { reports: vtxoReports } = await this.classifyDeprecatedSignerContracts(info);
5265
- const { reports: boardingReports } = await this.classifyDeprecatedSignerBoarding(info);
5277
+ const [{ reports: vtxoReports }, { reports: boardingReports }] = await Promise.all([
5278
+ this.classifyDeprecatedSignerContracts(info),
5279
+ this.classifyDeprecatedSignerBoarding(info)
5280
+ ]);
5266
5281
  return mergeSignerReports(vtxoReports, boardingReports);
5267
5282
  }
5268
5283
  /**
@@ -5284,8 +5299,10 @@ var VtxoManager = class _VtxoManager {
5284
5299
  return { rotated: rotatedOnRefresh, expired: [], signers: [] };
5285
5300
  }
5286
5301
  if (walletClass.status === "UNKNOWN_SIGNER") {
5287
- const { reports: vtxoReports2 } = await this.classifyDeprecatedSignerContracts(info);
5288
- const { reports: boardingReports2 } = await this.classifyDeprecatedSignerBoarding(info);
5302
+ const [{ reports: vtxoReports2 }, { reports: boardingReports2 }] = await Promise.all([
5303
+ this.classifyDeprecatedSignerContracts(info),
5304
+ this.classifyDeprecatedSignerBoarding(info)
5305
+ ]);
5289
5306
  return {
5290
5307
  // True only if a second rotation landed inside the drain, leaving us on a signer
5291
5308
  // newer than `info` (a drained rotation otherwise classifies CURRENT).
@@ -5296,16 +5313,13 @@ var VtxoManager = class _VtxoManager {
5296
5313
  };
5297
5314
  }
5298
5315
  const rotated = await this.ensureReceiveOnActiveSigner(info) || rotatedOnRefresh;
5299
- const {
5300
- reports: vtxoReports,
5301
- migratable: vtxoMigratable,
5302
- expired: vtxoExpired
5303
- } = await this.classifyDeprecatedSignerContracts(info);
5304
- const {
5305
- reports: boardingReports,
5306
- migratable: boardingMigratable,
5307
- expired: boardingExpired
5308
- } = await this.classifyDeprecatedSignerBoarding(info);
5316
+ const [
5317
+ { reports: vtxoReports, migratable: vtxoMigratable, expired: vtxoExpired },
5318
+ { reports: boardingReports, migratable: boardingMigratable, expired: boardingExpired }
5319
+ ] = await Promise.all([
5320
+ this.classifyDeprecatedSignerContracts(info),
5321
+ this.classifyDeprecatedSignerBoarding(info)
5322
+ ]);
5309
5323
  const reports = mergeSignerReports(vtxoReports, boardingReports);
5310
5324
  const expiredRefs = [
5311
5325
  ...vtxoExpired.map(classifiedToRef),
@@ -6304,11 +6318,6 @@ async function classifyIntent(intent, vtxosByOutpoint, now) {
6304
6318
  cancellationReason: "reconciliation: an input was unilaterally exited"
6305
6319
  });
6306
6320
  }
6307
- if (intent.state === "waiting_to_submit") {
6308
- return terminal(intent, "cancelled", now, {
6309
- cancellationReason: "reconciliation: intent was never submitted before restart"
6310
- });
6311
- }
6312
6321
  if (intent.validUntil !== void 0 && intent.validUntil < now) {
6313
6322
  return terminal(intent, "cancelled", now, {
6314
6323
  cancellationReason: "reconciliation: intent expired"
@@ -6510,9 +6519,16 @@ function chainTxTypeToChainedExit(t) {
6510
6519
  var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
6511
6520
  async function buildExitDag(params) {
6512
6521
  const byTxid = /* @__PURE__ */ new Map();
6513
- for (const vtxo of params.vtxos) {
6514
- const outpoint = `${vtxo.txid}:${vtxo.vout}`;
6515
- const chain = await params.chain.getVtxoChain({ txid: vtxo.txid, vout: vtxo.vout });
6522
+ const chains = await Promise.allSettled(
6523
+ params.vtxos.map(async (vtxo) => ({
6524
+ outpoint: `${vtxo.txid}:${vtxo.vout}`,
6525
+ // The resolver returns the full chain (all pages merged, local-first).
6526
+ chain: await params.chain.getVtxoChain({ txid: vtxo.txid, vout: vtxo.vout })
6527
+ }))
6528
+ );
6529
+ for (const result of chains) {
6530
+ if (result.status === "rejected") throw result.reason;
6531
+ const { outpoint, chain } = result.value;
6516
6532
  for (const chainTx of chain) {
6517
6533
  const existing = byTxid.get(chainTx.txid);
6518
6534
  if (existing) {
@@ -6545,25 +6561,26 @@ async function buildExitDag(params) {
6545
6561
  if (order.length !== pending.size) {
6546
6562
  throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
6547
6563
  }
6548
- const nodes = [];
6549
- for (const tx of order) {
6550
- let confirmed = false;
6551
- try {
6552
- const status = await params.onchain.getTxStatus(tx.txid);
6553
- confirmed = status.confirmed;
6554
- } catch {
6555
- confirmed = false;
6556
- }
6564
+ const confirmed = await Promise.all(
6565
+ order.map(async (tx) => {
6566
+ try {
6567
+ const status = await params.onchain.getTxStatus(tx.txid);
6568
+ return status.confirmed;
6569
+ } catch {
6570
+ return false;
6571
+ }
6572
+ })
6573
+ );
6574
+ return order.map((tx, i) => {
6557
6575
  const expires = Number(tx.expiresAt);
6558
- nodes.push({
6576
+ return {
6559
6577
  txid: tx.txid,
6560
6578
  type: tx.type,
6561
6579
  expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
6562
6580
  forVtxos: [...tx.forVtxos].sort(),
6563
- confirmed
6564
- });
6565
- }
6566
- return nodes;
6581
+ confirmed: confirmed[i]
6582
+ };
6583
+ });
6567
6584
  }
6568
6585
  function topoSortByDeps(items, idOf, depsOf) {
6569
6586
  const produced = new Set(items.map(idOf));
@@ -6732,11 +6749,12 @@ var RepositoryExitDataSource = class {
6732
6749
  return chain;
6733
6750
  }
6734
6751
  async getVirtualTxs(txids) {
6752
+ const stored = await Promise.all(txids.map((txid) => this.repo.getVirtualTx(txid)));
6735
6753
  const out = /* @__PURE__ */ new Map();
6736
- for (const txid of txids) {
6737
- const stored = await this.repo.getVirtualTx(txid);
6738
- if (stored?.psbt) out.set(txid, stored.psbt);
6739
- }
6754
+ txids.forEach((txid, i) => {
6755
+ const row = stored[i];
6756
+ if (row?.psbt) out.set(txid, row.psbt);
6757
+ });
6740
6758
  return out;
6741
6759
  }
6742
6760
  };
@@ -7854,8 +7872,10 @@ var DelegateManagerImpl = class {
7854
7872
  return { delegated: [], failed: [] };
7855
7873
  }
7856
7874
  const destinationScript = ArkAddress.decode(destination).pkScript;
7857
- const arkInfo = await this.arkInfoProvider.getInfo();
7858
- const delegateInfo = await this.delegateProvider.getDelegateInfo();
7875
+ const [arkInfo, delegateInfo] = await Promise.all([
7876
+ this.arkInfoProvider.getInfo(),
7877
+ this.delegateProvider.getDelegateInfo()
7878
+ ]);
7859
7879
  const eligible = vtxos.map(normalizeVtxo).filter(
7860
7880
  (v) => isAnnotated(v) && findDelegateTapLeaf(v, delegateInfo.pubkey) !== void 0
7861
7881
  );
@@ -10646,8 +10666,10 @@ var ContractManager = class _ContractManager {
10646
10666
  return contract !== void 0 && contractHandlers.get(contract.type)?.assertSpendableNow !== void 0;
10647
10667
  });
10648
10668
  if (asking.length === 0) return refused;
10649
- const tip = await this.currentChainTip();
10650
- const walletDescriptorValue = await walletDescriptor?.();
10669
+ const [tip, walletDescriptorValue] = await Promise.all([
10670
+ this.currentChainTip(),
10671
+ walletDescriptor?.()
10672
+ ]);
10651
10673
  for (const vtxo of asking) {
10652
10674
  const contract = byScript.get(vtxo.script);
10653
10675
  const handler = contractHandlers.get(contract.type);
@@ -12548,7 +12570,10 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
12548
12570
  * watched; it just stops being advertised). The untagged index-0 baseline is never retired.
12549
12571
  */
12550
12572
  async rotate(wallet) {
12551
- const descriptor = await this.provider.getNextSigningDescriptor();
12573
+ const descriptorPromise = this.provider.getNextSigningDescriptor();
12574
+ const managerPromise = wallet.getContractManager();
12575
+ void managerPromise.catch(() => void 0);
12576
+ const descriptor = await descriptorPromise;
12552
12577
  const { tapscript: newTapscript, params } = buildReceiveContract(
12553
12578
  wallet.offchainTapscript,
12554
12579
  descriptor,
@@ -12556,7 +12581,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
12556
12581
  true
12557
12582
  );
12558
12583
  const newScript = params.script;
12559
- const manager = await wallet.getContractManager();
12584
+ const manager = await managerPromise;
12560
12585
  await manager.createContract(params);
12561
12586
  wallet.setOffchainTapscriptForRotation(newTapscript);
12562
12587
  const previousTagged = this.currentTaggedScript;
@@ -12666,11 +12691,11 @@ function computeOffchainBalance(vtxos, caps) {
12666
12691
  let settled = 0;
12667
12692
  let preconfirmed = 0;
12668
12693
  let available = 0;
12669
- let gated = 0;
12694
+ let contractLocked = 0;
12670
12695
  let pendingSettlement = 0;
12671
12696
  let reserved = 0;
12672
12697
  let recoverable = 0;
12673
- let pendingRecovery = 0;
12698
+ let deprecatedSignerLocked = 0;
12674
12699
  let unrolled = 0;
12675
12700
  const owned = /* @__PURE__ */ new Map();
12676
12701
  const spendable = /* @__PURE__ */ new Map();
@@ -12687,7 +12712,7 @@ function computeOffchainBalance(vtxos, caps) {
12687
12712
  continue;
12688
12713
  }
12689
12714
  if (isPendingRecovery(vtxo)) {
12690
- pendingRecovery += vtxo.value;
12715
+ deprecatedSignerLocked += vtxo.value;
12691
12716
  continue;
12692
12717
  }
12693
12718
  if (canRecoverOnchain(vtxo, now)) {
@@ -12701,7 +12726,7 @@ function computeOffchainBalance(vtxos, caps) {
12701
12726
  settled += vtxo.value;
12702
12727
  }
12703
12728
  if (!isGenericallySpendable(vtxo)) {
12704
- gated += vtxo.value;
12729
+ contractLocked += vtxo.value;
12705
12730
  } else if (!isUnlocked(vtxo)) {
12706
12731
  pendingSettlement += vtxo.value;
12707
12732
  } else if (isReserved?.(vtxo)) {
@@ -12719,13 +12744,13 @@ function computeOffchainBalance(vtxos, caps) {
12719
12744
  settled,
12720
12745
  preconfirmed,
12721
12746
  available,
12722
- gated,
12747
+ contractLocked,
12723
12748
  pendingSettlement,
12724
12749
  reserved,
12725
12750
  recoverable,
12726
- pendingRecovery,
12751
+ deprecatedSignerLocked,
12727
12752
  unrolled,
12728
- total: settled + preconfirmed + recoverable + pendingRecovery + unrolled,
12753
+ total: settled + preconfirmed + recoverable + deprecatedSignerLocked + unrolled,
12729
12754
  assets: toAssets(owned),
12730
12755
  availableAssets: toAssets(spendable)
12731
12756
  };
@@ -12750,15 +12775,19 @@ function toWalletBalance(boardingUtxos, offchain) {
12750
12775
  settled: offchain.settled,
12751
12776
  preconfirmed: offchain.preconfirmed,
12752
12777
  available: offchain.available,
12753
- gated: offchain.gated,
12778
+ contractLocked: offchain.contractLocked,
12754
12779
  pendingSettlement: offchain.pendingSettlement,
12755
12780
  reserved: offchain.reserved,
12756
12781
  recoverable: offchain.recoverable,
12757
- pendingRecovery: offchain.pendingRecovery,
12782
+ deprecatedSignerLocked: offchain.deprecatedSignerLocked,
12758
12783
  unrolled: offchain.unrolled,
12759
12784
  total: totalBoarding + offchain.total,
12760
12785
  assets: offchain.assets,
12761
- availableAssets: offchain.availableAssets
12786
+ availableAssets: offchain.availableAssets,
12787
+ // Deprecated aliases, so code written against older releases still reads a value.
12788
+ gated: offchain.contractLocked,
12789
+ intentLocked: offchain.pendingSettlement,
12790
+ pendingRecovery: offchain.deprecatedSignerLocked
12762
12791
  };
12763
12792
  }
12764
12793
 
@@ -13806,22 +13835,42 @@ var ReadonlyWallet = class _ReadonlyWallet {
13806
13835
  const utxos = [];
13807
13836
  const commitmentsToIgnore = /* @__PURE__ */ new Set();
13808
13837
  const tapscripts = await this.getBoardingTapscripts(this.watchedBoardingSigners());
13809
- const outspendCache = /* @__PURE__ */ new Map();
13810
- const outspendOf = async (txid, index) => {
13811
- if (this.onchainProvider.getTxOutspend) {
13812
- return this.onchainProvider.getTxOutspend(txid, index);
13813
- }
13814
- let statuses = outspendCache.get(txid);
13815
- if (!statuses) {
13816
- statuses = await this.onchainProvider.getTxOutspends(txid);
13817
- outspendCache.set(txid, statuses);
13818
- }
13819
- return statuses[index];
13838
+ const getOne = this.onchainProvider.getTxOutspend?.bind(this.onchainProvider);
13839
+ const listInflight = /* @__PURE__ */ new Map();
13840
+ const oneInflight = /* @__PURE__ */ new Map();
13841
+ const outspendOf = (txid, index) => {
13842
+ if (getOne) {
13843
+ const key = `${txid}:${index}`;
13844
+ let pending2 = oneInflight.get(key);
13845
+ if (!pending2) {
13846
+ pending2 = getOne(txid, index);
13847
+ oneInflight.set(key, pending2);
13848
+ }
13849
+ return pending2;
13850
+ }
13851
+ let pending = listInflight.get(txid);
13852
+ if (!pending) {
13853
+ pending = this.onchainProvider.getTxOutspends(txid);
13854
+ listInflight.set(txid, pending);
13855
+ }
13856
+ return pending.then((statuses) => statuses[index]);
13820
13857
  };
13821
- for (const tapscript of tapscripts) {
13822
- const boardingAddress = tapscript.onchainAddress(this.network);
13823
- const scriptHex = hex.encode(tapscript.pkScript);
13824
- const txs = await this.onchainProvider.getTransactions(boardingAddress);
13858
+ const historyResults = await Promise.allSettled(
13859
+ tapscripts.map(async (tapscript) => {
13860
+ const boardingAddress = tapscript.onchainAddress(this.network);
13861
+ return {
13862
+ boardingAddress,
13863
+ scriptHex: hex.encode(tapscript.pkScript),
13864
+ txs: await this.onchainProvider.getTransactions(boardingAddress)
13865
+ };
13866
+ })
13867
+ );
13868
+ const histories = historyResults.map((result) => {
13869
+ if (result.status === "rejected") throw result.reason;
13870
+ return result.value;
13871
+ });
13872
+ const outputs = [];
13873
+ for (const { boardingAddress, scriptHex, txs } of histories) {
13825
13874
  const commitmentByOutpoint = /* @__PURE__ */ new Map();
13826
13875
  for (const tx of txs) {
13827
13876
  for (const input of tx.vin ?? []) {
@@ -13831,37 +13880,51 @@ var ReadonlyWallet = class _ReadonlyWallet {
13831
13880
  for (const tx of txs) {
13832
13881
  for (let i = 0; i < tx.vout.length; i++) {
13833
13882
  const vout = tx.vout[i];
13834
- if (vout.scriptpubkey_address === boardingAddress) {
13835
- const spentStatus = await outspendOf(tx.txid, i);
13836
- const commitmentTxid = spentStatus?.txid || commitmentByOutpoint.get(`${tx.txid}:${i}`);
13837
- const spent = Boolean(spentStatus?.spent) || commitmentTxid !== void 0;
13838
- if (spent && commitmentTxid) {
13839
- commitmentsToIgnore.add(commitmentTxid);
13840
- }
13841
- const boardingFacts = {
13842
- isSpent: spent,
13843
- isSwept: false,
13844
- isPreconfirmed: false,
13845
- commitmentTxIds: spent && commitmentTxid ? [commitmentTxid] : []
13846
- };
13847
- utxos.push({
13848
- txid: tx.txid,
13849
- vout: i,
13850
- value: Number(vout.value),
13851
- status: {
13852
- confirmed: tx.status.confirmed,
13853
- block_time: tx.status.block_time
13854
- },
13855
- isUnrolled: true,
13856
- ...boardingFacts,
13857
- spentBy: "",
13858
- createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
13859
- script: scriptHex
13860
- });
13861
- }
13883
+ if (vout.scriptpubkey_address !== boardingAddress) continue;
13884
+ outputs.push({
13885
+ txid: tx.txid,
13886
+ vout: i,
13887
+ value: Number(vout.value),
13888
+ confirmed: tx.status.confirmed,
13889
+ blockTime: tx.status.block_time,
13890
+ scriptHex,
13891
+ commitmentFromVin: commitmentByOutpoint.get(`${tx.txid}:${i}`),
13892
+ spentStatus: outspendOf(tx.txid, i)
13893
+ });
13862
13894
  }
13863
13895
  }
13864
13896
  }
13897
+ const spentResults = await Promise.allSettled(outputs.map((output) => output.spentStatus));
13898
+ for (const [i, output] of outputs.entries()) {
13899
+ const spentResult = spentResults[i];
13900
+ if (spentResult.status === "rejected") throw spentResult.reason;
13901
+ const spentStatus = spentResult.value;
13902
+ const commitmentTxid = spentStatus?.txid || output.commitmentFromVin;
13903
+ const spent = Boolean(spentStatus?.spent) || commitmentTxid !== void 0;
13904
+ if (spent && commitmentTxid) {
13905
+ commitmentsToIgnore.add(commitmentTxid);
13906
+ }
13907
+ const boardingFacts = {
13908
+ isSpent: spent,
13909
+ isSwept: false,
13910
+ isPreconfirmed: false,
13911
+ commitmentTxIds: spent && commitmentTxid ? [commitmentTxid] : []
13912
+ };
13913
+ utxos.push({
13914
+ txid: output.txid,
13915
+ vout: output.vout,
13916
+ value: output.value,
13917
+ status: {
13918
+ confirmed: output.confirmed,
13919
+ block_time: output.blockTime
13920
+ },
13921
+ isUnrolled: true,
13922
+ ...boardingFacts,
13923
+ spentBy: "",
13924
+ createdAt: output.confirmed ? new Date(output.blockTime * 1e3) : /* @__PURE__ */ new Date(0),
13925
+ script: output.scriptHex
13926
+ });
13927
+ }
13865
13928
  const unconfirmedTxs = [];
13866
13929
  const confirmedTxs = [];
13867
13930
  for (const utxo of utxos) {
@@ -13953,9 +14016,12 @@ var ReadonlyWallet = class _ReadonlyWallet {
13953
14016
  await this.walletRepository.saveUtxos(
13954
14017
  new Map(groups.map((group, i) => [addresses[i], group.coins]))
13955
14018
  );
14019
+ const cachedByAddress = await Promise.all(
14020
+ addresses.map((address) => collectUtxos(this.walletRepository, address))
14021
+ );
13956
14022
  for (const [i, group] of groups.entries()) {
13957
14023
  const fresh = new Set(group.coins.map((coin) => `${coin.txid}:${coin.vout}`));
13958
- const cached = await collectUtxos(this.walletRepository, addresses[i]);
14024
+ const cached = cachedByAddress[i];
13959
14025
  const kept = cached.filter((coin) => fresh.has(`${coin.txid}:${coin.vout}`));
13960
14026
  if (kept.length === cached.length) continue;
13961
14027
  await this.walletRepository.deleteUtxos(addresses[i]);
@@ -13978,14 +14044,20 @@ var ReadonlyWallet = class _ReadonlyWallet {
13978
14044
  return groups.flatMap((g) => g.coins);
13979
14045
  }
13980
14046
  /**
13981
- * @internal {@link getBoardingUtxos} minus those an in-flight settle is spending, for SDK
13982
- * picks. The getter itself lists them: callers that mirror it (the worker's cache and
13983
- * broadcasts, balances) must not see a settle's inputs vanish, and then stay gone if it fails.
14047
+ * @internal {@link getBoardingUtxos} minus those an in-flight settle is spending or an
14048
+ * unresolved intent locks, for SDK picks. The getter itself lists them: callers that mirror it
14049
+ * (the worker's cache and broadcasts, balances) must not see a settle's inputs vanish, and then
14050
+ * stay gone if it fails.
13984
14051
  */
13985
14052
  async getSelectableBoardingUtxos() {
13986
- return (await this.getBoardingUtxos()).filter(
13987
- (coin) => !this._pendingSpendOutpoints.has(`${coin.txid}:${coin.vout}`)
13988
- );
14053
+ const [utxos, locked] = await Promise.all([
14054
+ this.getBoardingUtxos(),
14055
+ this.lockedOutpoints()
14056
+ ]);
14057
+ return utxos.filter((coin) => {
14058
+ const key = `${coin.txid}:${coin.vout}`;
14059
+ return !this._pendingSpendOutpoints.has(key) && !locked.has(key);
14060
+ });
13989
14061
  }
13990
14062
  async getStoredBoardingUtxos() {
13991
14063
  const currentOnly = /* @__PURE__ */ new Set([
@@ -14010,6 +14082,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
14010
14082
  * @returns A function that stops the subscriptions
14011
14083
  */
14012
14084
  async notifyIncomingFunds(eventCallback) {
14085
+ const cm = this.indexerProvider ? await this.getContractManager() : void 0;
14013
14086
  const arkAddress = await this.getAddress();
14014
14087
  let onchainStopFunc;
14015
14088
  let indexerStopFunc;
@@ -14062,8 +14135,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
14062
14135
  void subscribeOnchain();
14063
14136
  });
14064
14137
  await subscribeOnchain();
14065
- if (this.indexerProvider && arkAddress) {
14066
- const cm = await this.getContractManager();
14138
+ if (cm && arkAddress) {
14067
14139
  let annotationQueue = Promise.resolve();
14068
14140
  indexerStopFunc = cm.onContractEvent((event) => {
14069
14141
  if (!isContractVtxoEvent(event)) {
@@ -14209,21 +14281,25 @@ var ReadonlyWallet = class _ReadonlyWallet {
14209
14281
  extraSources: capture?.sources
14210
14282
  });
14211
14283
  onVtxosPersisted = async (_contract, vtxos) => {
14212
- for (const v of vtxos) {
14213
- if (v.isSpent) continue;
14214
- await captureExitBranch({
14215
- resolver,
14216
- repository: virtualTxRepository,
14217
- vtxo: { txid: v.txid, vout: v.vout },
14218
- value: v.value,
14219
- mode: capture?.mode ?? DEFAULT_EXIT_CAPTURE_MODE,
14220
- minExitWorthSats: capture?.minExitWorthSats ?? DEFAULT_MIN_EXIT_WORTH_SATS
14221
- }).catch(() => {
14222
- });
14223
- }
14284
+ await Promise.all(
14285
+ vtxos.map((v) => {
14286
+ if (v.isSpent) return void 0;
14287
+ return captureExitBranch({
14288
+ resolver,
14289
+ repository: virtualTxRepository,
14290
+ vtxo: { txid: v.txid, vout: v.vout },
14291
+ value: v.value,
14292
+ mode: capture?.mode ?? DEFAULT_EXIT_CAPTURE_MODE,
14293
+ minExitWorthSats: capture?.minExitWorthSats ?? DEFAULT_MIN_EXIT_WORTH_SATS
14294
+ }).catch(() => {
14295
+ });
14296
+ })
14297
+ );
14224
14298
  };
14225
14299
  onVtxosSpent = (vtxos) => pruneExitBranches(virtualTxRepository, vtxos);
14226
14300
  }
14301
+ const baselinePubkeyPromise = this.identity.xOnlyPublicKey();
14302
+ void baselinePubkeyPromise.catch(() => void 0);
14227
14303
  const manager = await ContractManager.create({
14228
14304
  lazyInitialization: this.lazyInitialization,
14229
14305
  indexerProvider: this.indexerProvider,
@@ -14243,7 +14319,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
14243
14319
  return { height, time };
14244
14320
  }
14245
14321
  });
14246
- const baselinePubkey = await this.identity.xOnlyPublicKey();
14322
+ const baselinePubkey = await baselinePubkeyPromise;
14247
14323
  const delegatePubKey = this.offchainTapscript instanceof DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
14248
14324
  const baselineSigners = [
14249
14325
  this.offchainTapscript.options.serverPubKey,
@@ -14846,13 +14922,13 @@ var Wallet2 = class extends ReadonlyWallet {
14846
14922
  async _doRotateServerSigner(xonly, newServerUnrollScript) {
14847
14923
  if (equalBytes(xonly, this.arkServerPublicKey)) return;
14848
14924
  const manager = await this.getContractManager();
14849
- const [currentOffchainRow] = await manager.getContracts({
14850
- script: this.defaultContractScript
14851
- });
14852
14925
  const currentBoardingScript = hex.encode(this._boardingTapscript.pkScript);
14853
- const [currentBoardingRow] = await manager.getContracts({
14854
- script: currentBoardingScript
14855
- });
14926
+ const [offchainRows, boardingRows] = await Promise.all([
14927
+ manager.getContracts({ script: this.defaultContractScript }),
14928
+ manager.getContracts({ script: currentBoardingScript })
14929
+ ]);
14930
+ const [currentOffchainRow] = offchainRows;
14931
+ const [currentBoardingRow] = boardingRows;
14856
14932
  const newOffchain = this.offchainTapscript instanceof DelegateVtxo.Script ? new DelegateVtxo.Script({
14857
14933
  ...this.offchainTapscript.options,
14858
14934
  serverPubKey: xonly
@@ -15035,13 +15111,15 @@ var Wallet2 = class extends ReadonlyWallet {
15035
15111
  return this._restoreInFlight;
15036
15112
  }
15037
15113
  async _runRestore(gapLimit) {
15038
- const manager = await this.getContractManager();
15039
15114
  const provider = this._hdProvider;
15040
15115
  const hd = provider !== void 0;
15041
- const staticDescriptor = hd ? void 0 : await identityDescriptor(this.identity);
15116
+ const [manager, staticDescriptor, arkInfo] = await Promise.all([
15117
+ this.getContractManager(),
15118
+ hd ? void 0 : identityDescriptor(this.identity),
15119
+ this.arkProvider.getInfo()
15120
+ ]);
15042
15121
  const materialize = (index) => hd ? provider.materializeDescriptorAt(index) : staticDescriptor;
15043
15122
  const delegatePubKey = this.offchainTapscript instanceof DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
15044
- const arkInfo = await this.arkProvider.getInfo();
15045
15123
  const currentSignerPubKey = toXOnly(hex.decode(arkInfo.signerPubkey), "ark signer key");
15046
15124
  const deprecatedSignerPubKeys = arkInfo.deprecatedSigners.map(
15047
15125
  (s) => toXOnly(hex.decode(s.pubkey), "deprecated signer key")
@@ -15589,25 +15667,33 @@ var Wallet2 = class extends ReadonlyWallet {
15589
15667
  throw error;
15590
15668
  }
15591
15669
  const inputIds = params.inputs.map((i) => `${i.txid}:${i.vout}`).join(",");
15670
+ let released = !registering;
15592
15671
  if (registering) {
15593
- await this.arkProvider.deleteIntent(deleteIntent).catch((e) => {
15594
- if (isNoMatchingIntentsError(e)) return;
15595
- console.warn(
15596
- `Failed to delete intent after settle failure for inputs [${inputIds}]; intent may linger on server and cause 'duplicated input' on next settle`,
15597
- e
15598
- );
15599
- });
15600
- }
15601
- await this.persistIntentSnapshot(
15602
- intentTxId,
15603
- "cancelled",
15604
- intent,
15605
- deleteIntent,
15606
- params.inputs,
15607
- {
15608
- cancellationReason: error instanceof Error ? error.message : String(error)
15672
+ try {
15673
+ await this.arkProvider.deleteIntent(deleteIntent);
15674
+ released = true;
15675
+ } catch (e) {
15676
+ if (isNoMatchingIntentsError(e)) released = true;
15677
+ else {
15678
+ console.warn(
15679
+ `Failed to delete intent after settle failure for inputs [${inputIds}]; intent may linger on server and cause 'duplicated input' on next settle`,
15680
+ e
15681
+ );
15682
+ }
15609
15683
  }
15610
- );
15684
+ }
15685
+ if (released) {
15686
+ await this.persistIntentSnapshot(
15687
+ intentTxId,
15688
+ "cancelled",
15689
+ intent,
15690
+ deleteIntent,
15691
+ params.inputs,
15692
+ {
15693
+ cancellationReason: error instanceof Error ? error.message : String(error)
15694
+ }
15695
+ );
15696
+ }
15611
15697
  throw error;
15612
15698
  } finally {
15613
15699
  this._removePendingSpends(params.inputs);
@@ -18536,6 +18622,7 @@ var WalletMessageHandler = class {
18536
18622
  indexerProvider;
18537
18623
  walletRepository;
18538
18624
  incomingFundsSubscription;
18625
+ incomingFundsRegistrations = /* @__PURE__ */ new WeakMap();
18539
18626
  contractEventsSubscription;
18540
18627
  onNextTick = [];
18541
18628
  channel;
@@ -18547,6 +18634,11 @@ var WalletMessageHandler = class {
18547
18634
  // stale, folding requests in would truncate an in-flight settle, and
18548
18635
  // sharing with boarding would kill every lazy refresh (see `boardingEpoch`).
18549
18636
  incomingFundsEpoch = 0;
18637
+ /**
18638
+ * Supersedes older initializers without touching `incomingFundsEpoch`, so a
18639
+ * re-init that fails before registering leaves the live subscription delivering.
18640
+ */
18641
+ initEpoch = 0;
18550
18642
  contractEventsEpoch = 0;
18551
18643
  boardingEpoch = 0;
18552
18644
  /** Per-request progress callbacks: ends with the handler, not with a re-init. */
@@ -18571,6 +18663,7 @@ var WalletMessageHandler = class {
18571
18663
  }
18572
18664
  async stop() {
18573
18665
  this.requestEpoch++;
18666
+ this.initEpoch++;
18574
18667
  this.incomingFundsEpoch++;
18575
18668
  this.contractEventsEpoch++;
18576
18669
  this.boardingEpoch++;
@@ -18611,6 +18704,8 @@ var WalletMessageHandler = class {
18611
18704
  }
18612
18705
  epochOf(scope) {
18613
18706
  switch (scope) {
18707
+ case "init":
18708
+ return this.initEpoch;
18614
18709
  case "incomingFunds":
18615
18710
  return this.incomingFundsEpoch;
18616
18711
  case "contractEvents":
@@ -19367,18 +19462,22 @@ var WalletMessageHandler = class {
19367
19462
  }
19368
19463
  async onWalletInitialized() {
19369
19464
  const wallet = this.readonlyWallet;
19465
+ const signingWallet = this.wallet;
19466
+ const lazyBoarding = this.lazyBoardingInit;
19370
19467
  if (!wallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
19371
19468
  return;
19372
19469
  }
19373
- const init = this.newGeneration("incomingFunds");
19470
+ this.initEpoch++;
19471
+ const init = this.newGeneration("init");
19374
19472
  await this.ensureContractEventBroadcasting();
19375
19473
  if (init.stale) return;
19376
- await this.refreshCachedData({ lazyBoarding: this.lazyBoardingInit });
19474
+ await this.refreshCachedData({ lazyBoarding });
19377
19475
  if (init.stale) return;
19378
- if (this.wallet) {
19476
+ if (signingWallet) {
19379
19477
  try {
19380
19478
  const vtxos = await this.getVtxosFromRepo();
19381
- const { pending, finalized } = await this.wallet.finalizePendingTxs(
19479
+ if (init.stale) return;
19480
+ const { pending, finalized } = await signingWallet.finalizePendingTxs(
19382
19481
  vtxos.filter((vtxo) => vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept)
19383
19482
  );
19384
19483
  console.info(
@@ -19389,11 +19488,34 @@ var WalletMessageHandler = class {
19389
19488
  }
19390
19489
  if (init.stale) return;
19391
19490
  }
19392
- if (this.incomingFundsSubscription) this.incomingFundsSubscription();
19393
- this.incomingFundsSubscription = void 0;
19394
19491
  this.incomingFundsEpoch++;
19395
19492
  const emitter = this.newEmitter("incomingFunds");
19493
+ const provider = wallet.onchainProvider ?? this;
19494
+ const previousRegistration = this.incomingFundsRegistrations.get(provider) ?? Promise.resolve();
19495
+ const registration = previousRegistration.then(
19496
+ () => this.registerIncomingFunds(wallet, emitter)
19497
+ );
19498
+ this.incomingFundsRegistrations.set(
19499
+ provider,
19500
+ registration.catch((error) => {
19501
+ console.error("Error subscribing to incoming funds:", error);
19502
+ })
19503
+ );
19504
+ if (!lazyBoarding) await registration;
19505
+ if (signingWallet && !emitter.stale) {
19506
+ try {
19507
+ await signingWallet.getVtxoManager();
19508
+ } catch (error) {
19509
+ console.error("Error starting VtxoManager:", error);
19510
+ }
19511
+ }
19512
+ }
19513
+ async registerIncomingFunds(wallet, emitter) {
19514
+ if (emitter.stale) return;
19515
+ if (this.incomingFundsSubscription) this.incomingFundsSubscription();
19516
+ this.incomingFundsSubscription = void 0;
19396
19517
  const address = await wallet.getAddress();
19518
+ if (emitter.stale) return;
19397
19519
  const unsubscribe = await wallet.notifyIncomingFunds(async (funds) => {
19398
19520
  if (emitter.stale) return;
19399
19521
  if (funds.type === "vtxo") {
@@ -19462,13 +19584,6 @@ var WalletMessageHandler = class {
19462
19584
  });
19463
19585
  if (emitter.stale) return unsubscribe();
19464
19586
  this.incomingFundsSubscription = unsubscribe;
19465
- if (this.wallet) {
19466
- try {
19467
- await this.wallet.getVtxoManager();
19468
- } catch (error) {
19469
- console.error("Error starting VtxoManager:", error);
19470
- }
19471
- }
19472
19587
  }
19473
19588
  /**
19474
19589
  * Refresh boarding inputs and transaction history. The virtual outputs come
@@ -19497,24 +19612,30 @@ var WalletMessageHandler = class {
19497
19612
  payload: { coins }
19498
19613
  })
19499
19614
  );
19500
- await this.refreshHistoryCache(emitter);
19615
+ await this.storeHistoryCache(await this.loadHistoryCache(), emitter);
19501
19616
  })().catch((error) => {
19502
19617
  console.warn("[wallet] background refresh failed", error);
19503
19618
  });
19504
19619
  return;
19505
19620
  }
19621
+ const history = this.loadHistoryCache();
19622
+ void history.catch(() => void 0);
19506
19623
  await this.refreshBoardingCache();
19507
19624
  this.boardingLoaded = true;
19508
- await this.refreshHistoryCache();
19625
+ await this.storeHistoryCache(await history);
19509
19626
  }
19510
- /** @param gen - set by a background caller; each write is skipped once it goes stale. */
19511
- async refreshHistoryCache(gen) {
19627
+ /** History rows plus the address they are stored under. Does not write. */
19628
+ async loadHistoryCache() {
19512
19629
  const wallet = this.readonlyWallet;
19513
- const repository = this.walletRepository;
19514
- if (!wallet || !repository) return;
19630
+ if (!wallet || !this.walletRepository) return void 0;
19515
19631
  const address = await wallet.getAddress();
19516
19632
  const txs = await this.buildTransactionHistoryFromCache();
19517
- if (txs && !gen?.stale) await repository.saveTransactions(address, txs);
19633
+ if (!txs) return void 0;
19634
+ return { address, txs };
19635
+ }
19636
+ async storeHistoryCache(history, gen) {
19637
+ if (!history || gen?.stale || !this.walletRepository) return;
19638
+ await this.walletRepository.saveTransactions(history.address, history.txs);
19518
19639
  }
19519
19640
  /**
19520
19641
  * @param gen - set by a background caller; each write here is skipped once it goes stale.
@@ -19529,11 +19650,17 @@ var WalletMessageHandler = class {
19529
19650
  hex.encode(wallet.boardingTapscript.options.serverPubKey)
19530
19651
  );
19531
19652
  const groups = await wallet.getBoardingUtxosForSigners(/* @__PURE__ */ new Set([currentSigner]));
19532
- for (const { tapscript, coins } of groups) {
19653
+ if (gen?.stale) return;
19654
+ const cachedByAddress = await Promise.all(
19655
+ groups.map(
19656
+ ({ tapscript }) => collectUtxos(repository, tapscript.onchainAddress(wallet.network))
19657
+ )
19658
+ );
19659
+ for (const [i, { tapscript, coins }] of groups.entries()) {
19533
19660
  if (gen?.stale) return;
19534
19661
  const address = tapscript.onchainAddress(wallet.network);
19535
19662
  const freshKeys = new Set(coins.map((coin) => `${coin.txid}:${coin.vout}`));
19536
- const cached = await collectUtxos(repository, address);
19663
+ const cached = cachedByAddress[i];
19537
19664
  const kept = cached.filter((coin) => freshKeys.has(`${coin.txid}:${coin.vout}`));
19538
19665
  if (kept.length === cached.length) continue;
19539
19666
  if (gen?.stale) return;
@@ -19631,6 +19758,7 @@ var WalletMessageHandler = class {
19631
19758
  const wallet = this.wallet ?? this.readonlyWallet;
19632
19759
  if (!wallet) return;
19633
19760
  this.requestEpoch++;
19761
+ this.initEpoch++;
19634
19762
  this.incomingFundsEpoch++;
19635
19763
  this.contractEventsEpoch++;
19636
19764
  this.boardingEpoch++;
@@ -19682,7 +19810,9 @@ var WalletMessageHandler = class {
19682
19810
  * {@link getVtxosFromRepo}).
19683
19811
  */
19684
19812
  async repoSnapshot(options = {}) {
19685
- if (!this.walletRepository || !this.readonlyWallet) return { snapshot: [], vtxos: [] };
19813
+ const repository = this.walletRepository;
19814
+ const wallet = this.readonlyWallet;
19815
+ if (!repository || !wallet) return { snapshot: [], vtxos: [] };
19686
19816
  const seen = /* @__PURE__ */ new Set();
19687
19817
  const allVtxos = [];
19688
19818
  const addVtxos = (vtxos) => {
@@ -19697,19 +19827,18 @@ var WalletMessageHandler = class {
19697
19827
  }
19698
19828
  return fresh;
19699
19829
  };
19700
- const manager = await this.readonlyWallet.getContractManager();
19830
+ const addressPromise = wallet.getAddress();
19831
+ void addressPromise.catch(() => void 0);
19832
+ const manager = await wallet.getContractManager();
19701
19833
  const contracts = await manager.getContracts();
19702
- const snapshot = [];
19703
- for (const contract of contracts) {
19704
- if (!options.includeRecoveryOnly && isRecoveryOnlyContract(contract)) continue;
19705
- snapshot.push({
19706
- contract,
19707
- vtxos: addVtxos(
19708
- await getVtxosForContract(this.walletRepository, contract, options)
19709
- )
19710
- });
19711
- }
19712
- const walletAddress = await this.readonlyWallet.getAddress();
19834
+ const eligible = contracts.filter(
19835
+ (contract) => options.includeRecoveryOnly || !isRecoveryOnlyContract(contract)
19836
+ );
19837
+ const listsPromise = Promise.all(
19838
+ eligible.map((contract) => getVtxosForContract(repository, contract, options))
19839
+ );
19840
+ void listsPromise.catch(() => void 0);
19841
+ const walletAddress = await addressPromise;
19713
19842
  let walletScript;
19714
19843
  try {
19715
19844
  walletScript = scriptFromArkAddress(walletAddress);
@@ -19718,13 +19847,26 @@ var WalletMessageHandler = class {
19718
19847
  `WalletMessageHandler.getVtxosFromRepo: failed to derive script from wallet address ${walletAddress}: ${e instanceof Error ? e.message : String(e)}`
19719
19848
  );
19720
19849
  }
19721
- addVtxos(
19722
- await getVtxosForContract(
19723
- this.walletRepository,
19850
+ const [lists, primaryVtxos] = await Promise.all([
19851
+ listsPromise,
19852
+ // Routed through the same helper as the contract buckets rather than reading the
19853
+ // repository directly, so this bucket normalizes too. Anything left here
19854
+ // is outside every contract row, so it carries no contract to judge it
19855
+ // by — the wallet's own receive address, which is never gated.
19856
+ getVtxosForContract(
19857
+ repository,
19724
19858
  { script: walletScript, address: walletAddress },
19725
19859
  options
19726
19860
  )
19727
- );
19861
+ ]);
19862
+ const snapshot = [];
19863
+ for (const [i, contract] of eligible.entries()) {
19864
+ snapshot.push({
19865
+ contract,
19866
+ vtxos: addVtxos(lists[i])
19867
+ });
19868
+ }
19869
+ addVtxos(primaryVtxos);
19728
19870
  return { snapshot, vtxos: allVtxos };
19729
19871
  }
19730
19872
  /**
@@ -20427,7 +20569,12 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
20427
20569
  };
20428
20570
  try {
20429
20571
  const response = await this.sendMessage(message);
20430
- return response.payload;
20572
+ const balance = response.payload;
20573
+ return {
20574
+ ...balance,
20575
+ contractLocked: balance.contractLocked ?? balance.gated,
20576
+ deprecatedSignerLocked: balance.deprecatedSignerLocked ?? balance.pendingRecovery
20577
+ };
20431
20578
  } catch (error) {
20432
20579
  throw new Error(`Failed to get balance: ${error}`);
20433
20580
  }
@@ -22621,8 +22768,12 @@ async function attachPrevoutTxs(tx, source) {
22621
22768
  }
22622
22769
  if (pending.length === 0) return;
22623
22770
  const resolved = /* @__PURE__ */ new Map();
22624
- for (const txid of new Set(pending.map((p) => p.txid))) {
22625
- resolved.set(txid, await source.getRawTransaction(txid));
22771
+ const txids = [...new Set(pending.map((p) => p.txid))];
22772
+ const fetched = await Promise.allSettled(txids.map((txid) => source.getRawTransaction(txid)));
22773
+ for (let i = 0; i < fetched.length; i++) {
22774
+ const result = fetched[i];
22775
+ if (result.status === "rejected") throw result.reason;
22776
+ resolved.set(txids[i], result.value);
22626
22777
  }
22627
22778
  for (const { index, txid } of pending) {
22628
22779
  setArkPsbtField(tx, index, PrevoutTxField, resolved.get(txid));
@@ -23076,40 +23227,53 @@ var Unroll;
23076
23227
  Unroll2.completeUnroll = completeUnroll;
23077
23228
  })(Unroll || (Unroll = {}));
23078
23229
  async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
23079
- const chainTip = await wallet.onchainProvider.getChainTip();
23080
- let vtxos = await wallet.getVtxos({ withUnrolled: true });
23081
- vtxos = vtxos.filter((vtxo) => vtxoTxIds.includes(vtxo.txid));
23230
+ const [chainTip, storedVtxos, walletDescriptor] = await Promise.all([
23231
+ wallet.onchainProvider.getChainTip(),
23232
+ wallet.getVtxos({ withUnrolled: true }),
23233
+ wallet.identity.xOnlyPublicKey().then((key) => hex.encode(key))
23234
+ ]);
23235
+ const vtxos = storedVtxos.filter((vtxo) => vtxoTxIds.includes(vtxo.txid));
23082
23236
  if (vtxos.length === 0) {
23083
23237
  throw new Error("No vtxos to complete unroll");
23084
23238
  }
23085
23239
  const inputs = [];
23086
23240
  let totalAmount = 0n;
23087
23241
  const txWeightEstimator = TxWeightEstimator.create();
23088
- const walletDescriptor = hex.encode(await wallet.identity.xOnlyPublicKey());
23089
23242
  for (const vtxo of vtxos) {
23090
23243
  if (!canSweepOnchain(vtxo)) {
23091
23244
  throw new Error(
23092
23245
  `Vtxo ${vtxo.txid}:${vtxo.vout} cannot be swept onchain: it is not fully unrolled (use unroll first), or its exit output was already spent`
23093
23246
  );
23094
23247
  }
23095
- const txStatus = await wallet.onchainProvider.getTxStatus(vtxo.txid);
23096
- if (!txStatus.confirmed) {
23097
- throw new Error(`tx ${vtxo.txid} is not confirmed`);
23098
- }
23099
- const resolved = await resolveUnilateralPath({
23100
- vtxo,
23101
- scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
23102
- contractRepository: wallet.contractRepository,
23103
- walletDescriptor,
23104
- currentTime: Date.now()
23105
- });
23106
- const spendingLeaf = resolved.selection.leaf;
23107
- const sequence = resolved.selection.sequence;
23108
- const timelock = sequenceToTimelock(sequence);
23109
- const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
23110
- if (!elapsed) {
23111
- throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
23112
- }
23248
+ }
23249
+ const prepared = await Promise.allSettled(
23250
+ vtxos.map(async (vtxo) => {
23251
+ const [txStatus, resolved] = await Promise.all([
23252
+ wallet.onchainProvider.getTxStatus(vtxo.txid),
23253
+ resolveUnilateralPath({
23254
+ vtxo,
23255
+ scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
23256
+ contractRepository: wallet.contractRepository,
23257
+ walletDescriptor,
23258
+ currentTime: Date.now()
23259
+ })
23260
+ ]);
23261
+ if (!txStatus.confirmed) {
23262
+ throw new Error(`tx ${vtxo.txid} is not confirmed`);
23263
+ }
23264
+ const spendingLeaf = resolved.selection.leaf;
23265
+ const sequence = resolved.selection.sequence;
23266
+ const timelock = sequenceToTimelock(sequence);
23267
+ const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
23268
+ if (!elapsed) {
23269
+ throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
23270
+ }
23271
+ return { vtxo, spendingLeaf, sequence };
23272
+ })
23273
+ );
23274
+ for (const result of prepared) {
23275
+ if (result.status === "rejected") throw result.reason;
23276
+ const { vtxo, spendingLeaf, sequence } = result.value;
23113
23277
  totalAmount += BigInt(vtxo.value);
23114
23278
  inputs.push({
23115
23279
  txid: vtxo.txid,
@@ -23267,15 +23431,18 @@ async function resolveFeeRate(opts) {
23267
23431
  async function selectExitVtxos(opts) {
23268
23432
  if (!opts.vtxos) return opts.wallet.getVtxos();
23269
23433
  const res = await getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
23434
+ const scripts = [
23435
+ ...new Set(res.vtxos.filter((vtxo) => !vtxo.isSpent).map((vtxo) => vtxo.script))
23436
+ ];
23437
+ const contracts = scripts.length === 0 ? [] : await collectContracts(opts.wallet.contractRepository, { script: scripts });
23438
+ const byScript = new Map(contracts.map((contract) => [contract.script, contract]));
23270
23439
  const tapTrees = /* @__PURE__ */ new Map();
23271
23440
  const out = [];
23272
23441
  for (const vtxo of res.vtxos) {
23273
23442
  if (vtxo.isSpent) continue;
23274
23443
  let tapTree = tapTrees.get(vtxo.script);
23275
23444
  if (!tapTree) {
23276
- const [contract] = await collectContracts(opts.wallet.contractRepository, {
23277
- script: vtxo.script
23278
- });
23445
+ const contract = byScript.get(vtxo.script);
23279
23446
  if (!contract) {
23280
23447
  throw new Error(
23281
23448
  `no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
@@ -23294,6 +23461,10 @@ async function selectExitVtxos(opts) {
23294
23461
  }
23295
23462
  async function computeExitLayout(opts, feeRate) {
23296
23463
  const { wallet, onchainWallet } = opts;
23464
+ const coinsPromise = onchainWallet.getCoins();
23465
+ const pubkeyPromise = wallet.identity.xOnlyPublicKey();
23466
+ void coinsPromise.catch(() => void 0);
23467
+ void pubkeyPromise.catch(() => void 0);
23297
23468
  const vtxos = await selectExitVtxos(opts);
23298
23469
  if (vtxos.length === 0) throw new Error("no vtxos to exit");
23299
23470
  const resolver = createExitChainResolver({
@@ -23331,46 +23502,57 @@ async function computeExitLayout(opts, feeRate) {
23331
23502
  (s) => s.parent.id,
23332
23503
  (s) => txInputTxids(s.parent)
23333
23504
  );
23334
- const walletDescriptor = hex.encode(await wallet.identity.xOnlyPublicKey());
23505
+ const walletDescriptor = hex.encode(await pubkeyPromise);
23506
+ const resolvedPaths = await Promise.allSettled(
23507
+ vtxos.map(async (vtxo) => {
23508
+ try {
23509
+ return {
23510
+ vtxo,
23511
+ resolved: await resolveUnilateralPath({
23512
+ vtxo,
23513
+ scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
23514
+ contractRepository: wallet.contractRepository,
23515
+ walletDescriptor,
23516
+ currentTime: Date.now()
23517
+ })
23518
+ };
23519
+ } catch (e) {
23520
+ if (e instanceof ExitPathError) return { vtxo, skipped: e.message };
23521
+ throw e;
23522
+ }
23523
+ })
23524
+ );
23335
23525
  const infos = [];
23336
23526
  const sweeps = [];
23337
- for (const vtxo of vtxos) {
23527
+ for (const result of resolvedPaths) {
23528
+ if (result.status === "rejected") throw result.reason;
23529
+ const { vtxo } = result.value;
23338
23530
  const outpoint = `${vtxo.txid}:${vtxo.vout}`;
23339
- try {
23340
- const resolved = await resolveUnilateralPath({
23341
- vtxo,
23342
- scriptHex: hex.encode(VtxoScript.decode(vtxo.tapTree).pkScript),
23343
- contractRepository: wallet.contractRepository,
23344
- walletDescriptor,
23345
- currentTime: Date.now()
23531
+ if ("skipped" in result.value) {
23532
+ infos.push({ outpoint, value: vtxo.value, skipped: result.value.skipped });
23533
+ continue;
23534
+ }
23535
+ const { resolved } = result.value;
23536
+ const sweepFee = sweepFeeFor(
23537
+ resolved.selection,
23538
+ opts.sweepAddress,
23539
+ wallet.network,
23540
+ feeRate
23541
+ );
23542
+ if (vtxo.value - sweepFee < CHILD_OUTPUT_DUST) {
23543
+ infos.push({
23544
+ outpoint,
23545
+ value: vtxo.value,
23546
+ skipped: `uneconomic: value ${vtxo.value} <= sweep fee + dust`
23346
23547
  });
23347
- const sweepFee = sweepFeeFor(
23348
- resolved.selection,
23349
- opts.sweepAddress,
23350
- wallet.network,
23351
- feeRate
23352
- );
23353
- if (vtxo.value - sweepFee < CHILD_OUTPUT_DUST) {
23354
- infos.push({
23355
- outpoint,
23356
- value: vtxo.value,
23357
- skipped: `uneconomic: value ${vtxo.value} <= sweep fee + dust`
23358
- });
23359
- continue;
23360
- }
23361
- const t = sequenceToTimelock(resolved.selection.sequence);
23362
- const delay = { type: t.type, value: Number(t.value) };
23363
- infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
23364
- sweeps.push({ vtxo, resolved, sweepFee, delay });
23365
- } catch (e) {
23366
- if (e instanceof ExitPathError) {
23367
- infos.push({ outpoint, value: vtxo.value, skipped: e.message });
23368
- continue;
23369
- }
23370
- throw e;
23548
+ continue;
23371
23549
  }
23550
+ const t = sequenceToTimelock(resolved.selection.sequence);
23551
+ const delay = { type: t.type, value: Number(t.value) };
23552
+ infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
23553
+ sweeps.push({ vtxo, resolved, sweepFee, delay });
23372
23554
  }
23373
- const coins = (await onchainWallet.getCoins()).filter((c) => c.status.confirmed);
23555
+ const coins = (await coinsPromise).filter((c) => c.status.confirmed);
23374
23556
  const balance = coins.reduce((sum, c) => sum + c.value, 0);
23375
23557
  const fundingTotal = steps.reduce((sum, s) => sum + s.funding, 0);
23376
23558
  const splitterFeeFor = (inputCount) => {
@@ -24770,6 +24952,13 @@ var Arkade = class _Arkade {
24770
24952
  }
24771
24953
  return new ArkadeContract(this, program, args);
24772
24954
  }
24955
+ /**
24956
+ * Start a spend with no function of its own: each `.from(coins, contract.unlock.<name>(...))`
24957
+ * names the function its coins are spent through.
24958
+ */
24959
+ transaction() {
24960
+ return new ArkadeTransactionBuilder(this);
24961
+ }
24773
24962
  };
24774
24963
  var ArkadeContract = class _ArkadeContract {
24775
24964
  constructor(client, program, args = {}, keys) {
@@ -24831,7 +25020,23 @@ var ArkadeContract = class _ArkadeContract {
24831
25020
  get functions() {
24832
25021
  const out = /* @__PURE__ */ Object.create(null);
24833
25022
  for (const fn of this.compiled) {
24834
- out[fn.name] = (...callArgs) => new ArkadeTransactionBuilder(this, fn, bindInputs(fn, callArgs));
25023
+ out[fn.name] = (...callArgs) => new ArkadeTransactionBuilder(this.client, {
25024
+ contract: this,
25025
+ fn,
25026
+ args: bindInputs(fn, callArgs)
25027
+ });
25028
+ }
25029
+ return out;
25030
+ }
25031
+ /** Spending paths bound to their arguments, for `.from(coins, contract.unlock.<name>(...))`. */
25032
+ get unlock() {
25033
+ const out = /* @__PURE__ */ Object.create(null);
25034
+ for (const fn of this.compiled) {
25035
+ out[fn.name] = (...callArgs) => ({
25036
+ contract: this,
25037
+ fn,
25038
+ args: bindInputs(fn, callArgs)
25039
+ });
24835
25040
  }
24836
25041
  return out;
24837
25042
  }
@@ -24949,27 +25154,62 @@ var ArkadeContract = class _ArkadeContract {
24949
25154
  };
24950
25155
  var ArkadeTransactionBuilder = class {
24951
25156
  /** @internal */
24952
- constructor(contract, fn, args) {
24953
- this.contract = contract;
24954
- this.fn = fn;
24955
- this.args = args;
25157
+ constructor(client, unlocker) {
25158
+ this.client = client;
25159
+ this.unlocker = unlocker;
24956
25160
  }
24957
- contract;
24958
- fn;
24959
- args;
25161
+ client;
25162
+ unlocker;
24960
25163
  outputs = [];
24961
25164
  fundingCoins = [];
24962
25165
  assetSpecs = [];
24963
25166
  extraPackets = [];
24964
- coin;
25167
+ inputs = [];
24965
25168
  changeScript;
24966
- from(coin) {
24967
- this.coin = coin;
25169
+ /**
25170
+ * Spend coins through this builder's function, or through `unlocker`
25171
+ * (`other.unlock.<name>(...args)`, same client), which `ark.transaction()` requires. Calls add
25172
+ * up; contract coins come first, in call order, then `.fund()` inputs.
25173
+ *
25174
+ * Every coin's script sees the same outputs: "output 0 pays X" passes once for all of them.
25175
+ * For one payment per coin, the contract must check `INSPECTNUMINPUTS` or `PUSHCURRENTINPUTINDEX`.
25176
+ */
25177
+ from(coins, unlocker = this.unlocker) {
25178
+ const list = Array.isArray(coins) ? coins : [coins];
25179
+ if (list.length === 0) throw new Error("from(): no coins given");
25180
+ if (!unlocker) {
25181
+ throw new Error("from(): name the function to spend through: contract.unlock.<name>()");
25182
+ }
25183
+ const { contract, fn } = unlocker;
25184
+ if (contract.client !== this.client) {
25185
+ throw new Error(`from(): ${fn.name} belongs to a contract on another Arkade client`);
25186
+ }
25187
+ const script = hex.encode(contract.pkScript);
25188
+ const taken = new Set(this.inputs.map(({ coin: c }) => `${c.txid}:${c.vout}`));
25189
+ const now = Date.now();
25190
+ for (const coin of list) {
25191
+ const outpoint = `${coin.txid}:${coin.vout}`;
25192
+ if (coin.script && coin.script !== script) {
25193
+ throw new Error(
25194
+ `from(): coin ${outpoint} is not locked by the contract of ${fn.name}`
25195
+ );
25196
+ }
25197
+ if (taken.has(outpoint))
25198
+ throw new Error(`from(): coin ${outpoint} is already an input`);
25199
+ const reason = unspendable(coin, now);
25200
+ if (reason) {
25201
+ throw new Error(
25202
+ `from(): coin ${outpoint} ${reason}; recover it into a batch instead`
25203
+ );
25204
+ }
25205
+ taken.add(outpoint);
25206
+ }
25207
+ this.inputs.push(...list.map((coin) => ({ coin, unlocker })));
24968
25208
  return this;
24969
25209
  }
24970
25210
  /**
24971
25211
  * Add extra inputs the caller funds (e.g. a taker's own coins in a swap).
24972
- * These become inputs 1..n and are signed with the client identity.
25212
+ * These come after the contract coins and are signed with the client identity.
24973
25213
  */
24974
25214
  fund(coins) {
24975
25215
  this.fundingCoins.push(...coins);
@@ -25006,23 +25246,39 @@ var ArkadeTransactionBuilder = class {
25006
25246
  }
25007
25247
  /** Assemble the unsigned ark transaction and its checkpoints. */
25008
25248
  async build() {
25009
- if (this.fn.def.tapscript.csv) {
25010
- throw new Error(
25011
- `${this.fn.name}: CSV leaves require an aged onchain output; the offchain builder creates fresh checkpoints \u2014 use the wallet's unilateral exit flow`
25012
- );
25249
+ const { arkTx, checkpoints } = await this.assemble();
25250
+ return { arkTx, checkpoints };
25251
+ }
25252
+ async assemble() {
25253
+ for (const { fn } of this.unlockers()) {
25254
+ if (fn.def.tapscript.csv) {
25255
+ throw new Error(
25256
+ `${fn.name}: CSV leaves require an aged onchain output; the offchain builder creates fresh checkpoints \u2014 use the wallet's unilateral exit flow`
25257
+ );
25258
+ }
25013
25259
  }
25014
25260
  if (this.outputs.length === 0) {
25015
25261
  throw new Error("ArkadeTransactionBuilder: at least one output is required");
25016
25262
  }
25017
25263
  const outputsSum = this.outputs.reduce((s, o) => s + (o.amount ?? 0n), 0n);
25018
- const coin = this.coin ?? await this.selectCoin(outputsSum);
25019
- const def = this.fn.def;
25264
+ let inputs = [...this.inputs];
25265
+ if (inputs.length === 0) {
25266
+ if (!this.unlocker) {
25267
+ throw new Error(
25268
+ "ArkadeTransactionBuilder: add coins with .from(coins, contract.unlock.<name>())"
25269
+ );
25270
+ }
25271
+ inputs = [
25272
+ { coin: await this.selectCoin(this.unlocker, outputsSum), unlocker: this.unlocker }
25273
+ ];
25274
+ }
25275
+ const coinsSum = inputs.reduce((s, { coin }) => s + BigInt(coin.value), 0n);
25020
25276
  const outputs = [...this.outputs];
25021
25277
  const fundingSum = this.fundingCoins.reduce((s, f) => s + BigInt(f.value), 0n);
25022
- const surplus = BigInt(coin.value) + fundingSum - outputsSum;
25278
+ const surplus = coinsSum + fundingSum - outputsSum;
25023
25279
  if (surplus < 0n) {
25024
25280
  throw new Error(
25025
- `ArkadeTransactionBuilder: insufficient inputs \u2014 outputs ${outputsSum} exceed inputs ${BigInt(coin.value) + fundingSum}`
25281
+ `ArkadeTransactionBuilder: insufficient inputs \u2014 outputs ${outputsSum} exceed inputs ${coinsSum + fundingSum}`
25026
25282
  );
25027
25283
  }
25028
25284
  if (surplus > 0n) {
@@ -25035,23 +25291,23 @@ var ArkadeTransactionBuilder = class {
25035
25291
  }
25036
25292
  const { arkTx, checkpoints } = buildOffchainTx(
25037
25293
  [
25038
- {
25294
+ ...inputs.map(({ coin, unlocker }) => ({
25039
25295
  txid: coin.txid,
25040
25296
  vout: coin.vout,
25041
25297
  value: coin.value,
25042
- tapLeafScript: this.fn.tapLeafScript,
25043
- tapTree: this.contract.tapTree
25044
- },
25298
+ tapLeafScript: unlocker.fn.tapLeafScript,
25299
+ tapTree: unlocker.contract.tapTree
25300
+ })),
25045
25301
  ...this.fundingCoins
25046
25302
  ],
25047
25303
  outputs,
25048
- this.contract.client.checkpoint
25304
+ this.client.checkpoint
25049
25305
  );
25050
- if (coin.sourceTx) {
25051
- setArkPsbtField(arkTx, 0, PrevArkTxField, coin.sourceTx);
25052
- }
25053
- if (this.fn.arkadeScript) {
25054
- const indexer = this.contract.client.indexer;
25306
+ inputs.forEach(({ coin }, i) => {
25307
+ if (coin.sourceTx) setArkPsbtField(arkTx, i, PrevArkTxField, coin.sourceTx);
25308
+ });
25309
+ if (inputs.some(({ unlocker }) => unlocker.fn.arkadeScript)) {
25310
+ const indexer = this.client.indexer;
25055
25311
  if (!indexer) {
25056
25312
  throw new PrevTxUnavailableError(
25057
25313
  "covenant spends require an `indexer` on the Arkade client to resolve the previous ark tx of each input"
@@ -25059,56 +25315,76 @@ var ArkadeTransactionBuilder = class {
25059
25315
  }
25060
25316
  await attachPrevArkTxs(
25061
25317
  arkTx,
25062
- [coin.txid, ...this.fundingCoins.map((c) => c.txid)],
25318
+ [...inputs.map(({ coin }) => coin), ...this.fundingCoins].map((c) => c.txid),
25063
25319
  indexer
25064
25320
  );
25065
25321
  }
25066
- const condition = (def.tapscript.witness ?? []).map((w) => this.witnessBytes(w));
25067
- if (condition.length > 0) {
25068
- setArkPsbtField(arkTx, 0, ConditionWitness, condition);
25069
- setArkPsbtField(checkpoints[0], 0, ConditionWitness, condition);
25070
- }
25322
+ inputs.forEach(({ unlocker }, i) => {
25323
+ const condition = (unlocker.fn.def.tapscript.witness ?? []).map(
25324
+ (w) => witnessBytes(unlocker, w)
25325
+ );
25326
+ if (condition.length === 0) return;
25327
+ setArkPsbtField(arkTx, i, ConditionWitness, condition);
25328
+ setArkPsbtField(checkpoints[i], 0, ConditionWitness, condition);
25329
+ });
25071
25330
  const packets = [];
25072
25331
  if (this.assetSpecs.length > 0) {
25073
25332
  packets.push(this.buildAssetPacket());
25074
25333
  }
25075
- const arkadeScript = this.fn.arkadeScript;
25076
- if (arkadeScript) {
25077
- const stack = (def.arkadeScript?.witness ?? []).map((w) => this.witnessBytes(w));
25078
- packets.push(
25079
- EmulatorPacket.create([
25080
- { vin: 0, script: arkadeScript, witness: RawWitness.encode(stack) }
25081
- ])
25082
- );
25334
+ const entries = inputs.flatMap(({ unlocker }, vin) => {
25335
+ const { arkadeScript, def } = unlocker.fn;
25336
+ if (!arkadeScript) return [];
25337
+ const stack = (def.arkadeScript?.witness ?? []).map((w) => witnessBytes(unlocker, w));
25338
+ return [{ vin, script: arkadeScript, witness: RawWitness.encode(stack) }];
25339
+ });
25340
+ if (entries.length > 0) {
25341
+ packets.push(EmulatorPacket.create(entries));
25083
25342
  }
25084
25343
  packets.push(...this.extraPackets);
25085
25344
  if (packets.length > 0) {
25086
25345
  attachExtension(arkTx, packets);
25087
25346
  }
25088
- return { arkTx, checkpoints };
25347
+ return { arkTx, checkpoints, inputs };
25089
25348
  }
25090
25349
  /** Build, submit and return the finalized transaction. */
25091
25350
  async send() {
25092
- if (this.fn.def.tapscript.signers.some(
25093
- (signer) => typeof signer === "object" && "tweak" in signer
25094
- )) {
25095
- throw new Error(
25096
- `${this.fn.name}: covenant-tweaked leaf signing is not supported by Identity; use a signer that supports the covenant tweak with build()`
25097
- );
25351
+ const client = this.client;
25352
+ const userKey = client.userKey;
25353
+ for (const { contract, fn } of this.unlockers()) {
25354
+ if (fn.def.tapscript.signers.some(
25355
+ (signer) => typeof signer === "object" && "tweak" in signer
25356
+ )) {
25357
+ throw new Error(
25358
+ `${fn.name}: covenant-tweaked leaf signing is not supported by Identity; use a signer that supports the covenant tweak with build()`
25359
+ );
25360
+ }
25361
+ const { serverKey } = contract.keys;
25362
+ if (fn.signerKeys.some(
25363
+ (key) => !equalBytes(key, serverKey) && (!userKey || !equalBytes(key, userKey))
25364
+ )) {
25365
+ throw new Error(
25366
+ `${fn.name}: external leaf signatures are required; use build() and sign the PSBT with all required signers`
25367
+ );
25368
+ }
25098
25369
  }
25099
- const { serverKey } = this.contract.keys;
25100
- const userKey = this.contract.client.userKey;
25101
- if (this.fn.signerKeys.some(
25102
- (key) => !equalBytes(key, serverKey) && (!userKey || !equalBytes(key, userKey))
25103
- )) {
25370
+ const { arkTx, checkpoints, inputs } = await this.assemble();
25371
+ const userInputs = this.userInputIndexes(inputs);
25372
+ const serverOnly = inputs.find(
25373
+ ({ unlocker }, i) => !unlocker.fn.arkadeScript && !userInputs.includes(i)
25374
+ );
25375
+ if (serverOnly) {
25104
25376
  throw new Error(
25105
- `${this.fn.name}: external leaf signatures are required; use build() and sign the PSBT with all required signers`
25377
+ `${serverOnly.unlocker.fn.name}: a leaf without a covenant needs the user's signature, and this one has only the server's`
25106
25378
  );
25107
25379
  }
25108
- const { arkTx, checkpoints } = await this.build();
25109
- const client = this.contract.client;
25110
- const userInputs = this.userInputIndexes();
25111
- if (this.fn.arkadeScript) {
25380
+ inputs.forEach(({ coin }, vin) => {
25381
+ if (coin.assets?.length && !this.routesAssetsFrom(vin)) {
25382
+ throw new Error(
25383
+ `coin ${coin.txid}:${coin.vout} carries assets; route them with .withAsset() from input ${vin}`
25384
+ );
25385
+ }
25386
+ });
25387
+ if (inputs.some(({ unlocker }) => unlocker.fn.arkadeScript)) {
25112
25388
  if (!client.emulator) {
25113
25389
  throw new Error("covenant spends require an `emulator` on the Arkade client");
25114
25390
  }
@@ -25133,9 +25409,14 @@ var ArkadeTransactionBuilder = class {
25133
25409
  assertSubmittedArkTxid(res, signedArk, "submitTx");
25134
25410
  const matched = matchServerCheckpoints(res.signedCheckpointTxs, checkpoints, "submitTx");
25135
25411
  const finalCps = await Promise.all(
25136
- matched.map(
25137
- async ({ server }) => base64.encode((await client.identity.sign(server, [0])).toPSBT())
25138
- )
25412
+ matched.map(async ({ server, local }) => {
25413
+ const signed = await client.identity.sign(server, [0]);
25414
+ const [condition] = getArkPsbtFields(local, 0, ConditionWitness);
25415
+ if (condition && getArkPsbtFields(signed, 0, ConditionWitness).length === 0) {
25416
+ setArkPsbtField(signed, 0, ConditionWitness, condition);
25417
+ }
25418
+ return base64.encode(signed.toPSBT());
25419
+ })
25139
25420
  );
25140
25421
  await ark.finalizeTx(res.arkTxid, finalCps);
25141
25422
  return {
@@ -25147,31 +25428,44 @@ var ArkadeTransactionBuilder = class {
25147
25428
  /** Sign the client-owned inputs of the ark tx (no-op when there are none). */
25148
25429
  async signArk(arkTx, userInputs) {
25149
25430
  if (userInputs.length === 0) return arkTx;
25150
- const { identity } = this.contract.client;
25431
+ const { identity } = this.client;
25151
25432
  if (!identity) {
25152
25433
  throw new Error("this spend requires an `identity` to sign its user/funding inputs");
25153
25434
  }
25154
25435
  return identity.sign(arkTx, userInputs);
25155
25436
  }
25156
- /** Indexes of inputs the client owns and must sign (contract input + funded inputs). */
25157
- userInputIndexes() {
25158
- const idxs = [];
25159
- const userKey = this.contract.client.userKey;
25160
- if (userKey && this.fn.signerKeys.some((k) => equalBytes(k, userKey))) {
25161
- idxs.push(0);
25162
- }
25163
- for (let i = 0; i < this.fundingCoins.length; i++) {
25164
- idxs.push(i + 1);
25165
- }
25437
+ /** The functions this spend goes through: the `.from()` ones, else this builder's own. */
25438
+ unlockers() {
25439
+ if (this.inputs.length > 0) return this.inputs.map((i) => i.unlocker);
25440
+ return this.unlocker ? [this.unlocker] : [];
25441
+ }
25442
+ /** Indexes of inputs the client owns and must sign (contract inputs + funded inputs). */
25443
+ userInputIndexes(inputs) {
25444
+ const userKey = this.client.userKey;
25445
+ const idxs = inputs.flatMap(
25446
+ ({ unlocker }, i) => userKey && unlocker.fn.signerKeys.some((k) => equalBytes(k, userKey)) ? [i] : []
25447
+ );
25448
+ for (let i = 0; i < this.fundingCoins.length; i++) idxs.push(inputs.length + i);
25166
25449
  return idxs;
25167
25450
  }
25168
- async selectCoin(amount) {
25169
- const utxos = await this.contract.getUtxos();
25451
+ async selectCoin(unlocker, amount) {
25452
+ const now = Date.now();
25453
+ const routed = this.routesAssetsFrom(0);
25454
+ const utxos = (await unlocker.contract.getUtxos()).filter(
25455
+ (u) => !unspendable(u, now) && (routed || !u.assets?.length)
25456
+ );
25170
25457
  if (utxos.length === 0) throw new Error("no spendable coins for this contract");
25171
25458
  const covering = utxos.filter((u) => BigInt(u.value) >= amount).sort((a, b) => a.value - b.value);
25172
25459
  if (covering.length > 0) return covering[0];
25173
25460
  return [...utxos].sort((a, b) => b.value - a.value)[0];
25174
25461
  }
25462
+ /**
25463
+ * Whether input `vin`'s assets are routed: by a `.withAsset()` input, or a caller's asset packet.
25464
+ * A caller's packet counts for every input, unread; arkd checks what it actually routes.
25465
+ */
25466
+ routesAssetsFrom(vin) {
25467
+ return this.extraPackets.some((p) => p.type() === Packet.PACKET_TYPE) || this.assetSpecs.some((spec) => spec.inputs.some((i) => i.vin === vin));
25468
+ }
25175
25469
  buildAssetPacket() {
25176
25470
  const groups = this.assetSpecs.map((s) => {
25177
25471
  const id = typeof s.assetId === "string" ? AssetId.fromString(s.assetId) : AssetId.fromBytes(s.assetId);
@@ -25185,10 +25479,15 @@ var ArkadeTransactionBuilder = class {
25185
25479
  });
25186
25480
  return Packet.create(groups);
25187
25481
  }
25188
- witnessBytes(ref) {
25189
- return witnessRefToBytes(ref, this.args, this.contract.args);
25190
- }
25191
25482
  };
25483
+ function unspendable(coin, now) {
25484
+ if (coin.isSwept) return "was swept";
25485
+ if (coin.expiresAt && now >= new Date(coin.expiresAt).getTime()) return "has expired";
25486
+ return void 0;
25487
+ }
25488
+ function witnessBytes({ contract, args }, ref) {
25489
+ return witnessRefToBytes(ref, args, contract.args);
25490
+ }
25192
25491
  function bindInputs(fn, callArgs) {
25193
25492
  const inputs = fn.def.inputs ?? [];
25194
25493
  if (callArgs.length !== inputs.length) {
@@ -25688,5 +25987,5 @@ function createDefaultPaymentRouter(wallet) {
25688
25987
  }
25689
25988
 
25690
25989
  export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, Arkade, ArkadeCash, ArkadeCashCreateError, ArkadeCashOperatorMismatchError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_SECONDS, DatabaseUpgradeBlockedError, DelegateManagerImpl, DelegateNotConfiguredError, DescriptorIdentity, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EmulatorPacket, EsploraProvider, Estimator, Extension, ExtensionNotFoundError, ForeignDescriptorError, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, KeyringDescriptorProvider, MAX_PAGE_SIZE, MAX_USED_SIGNING_DESCRIPTORS_LOOK_AHEAD, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SeedIdentity, SendDeadlineExceededError, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, VtxoReservedError, Wallet2 as Wallet, WalletCannotAllocateAddressError, WalletCannotSignError, WalletMessageHandler, WalletNotInitializedError, WsElectrumChainSource, adoptContractDescriptor, arkAssetRail, arkRail, arkTarget, arkade_exports, assertFinalCommitmentMatchesValidated, assertHistoryPageFilter, assertIntentIdUnique, assertNoAssets, assertNoSelection, assertPageRequest, assertRecipientArkadeAddress, assertSendDeadline, assertSendableAmount, assertSubmittedArkTxid, assertValidBatchExpiry, assertValidServerUnrollScript, assetMintResolver, assetsOf, attachPrevArkTxs, attachPrevoutTxs, awaitTransaction, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, buildPreimageMessage, buildSaltedPreimageMessage, captureSendDeadline, checkSaveVtxosForScript, claimWithPreimageIdentity, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, collabExitResolver, collectContracts, collectIntents, collectPages, collectScriptVtxos, collectTransactionHistory, collectUtxos, collectVtxos, combineTapscriptSigs, compareHistoryCursors, contractFilterMatchesNothing, contractFromArkContract, contractFromArkContractWithAddress, contractPreimage, contractSigner, createAssetPacket, createDefaultActivityRegistry, createDefaultPaymentRouter, createExitChainResolver, createManagedConnection, createdAtToIso, decodeArkContract, defaultBatchExpiryPolicy, deleteByIndex, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, exitObserverFor, extendVirtualCoinForContract, extractArkProviderUrl, gateExclusion, gatedContracts, getAllByIndexValues, getRandomId, hasBoardingTxExpired, hasCandidates, intentMatchesFilter, invoiceTarget, isAddressAllocationCapable, isArkContract, isBatchSignable, isBtcAddress, isContractGenericallySpendable, isContractVtxoEvent, isCooperativelyMigratable, isDeterministicSigner, isDiscoverable, isHDAllocationCapable, isHDDeterministicSignCapable, isHDWalletCapable, isLightningInvoice, isLnurl, isMessageBusInitializingError, isMessageBusNotInitializedError, isPerArtifactDescriptor, isSigningIdentity, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, iteratePages, legacyVtxoFacts, logExcludedVtxos, makeHandle, matchServerCheckpoints, mergeChainedTxType, notifyExitObserved, onchainRail, openDatabase, outpointExclusion, outpointReasons, pageResult, promisifyRequest, provisionClaimSecret, provisionRefundKey, registerWalletRestoreHook, resolveAssetAmount, resolveBatchExpiryPolicy, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, submitViaEmulator, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
25691
- //# sourceMappingURL=chunk-NKKJEA3Z.js.map
25692
- //# sourceMappingURL=chunk-NKKJEA3Z.js.map
25990
+ //# sourceMappingURL=chunk-AJWXVQYG.js.map
25991
+ //# sourceMappingURL=chunk-AJWXVQYG.js.map