@arkade-os/sdk 0.5.0-rc.21 → 0.5.0-rc.23

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 +31 -0
  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-x8ok3tJy.d.cts → asyncStorageTaskQueue-DUu3VwBE.d.cts} +2 -2
  7. package/dist/{asyncStorageTaskQueue-aL7K14e4.d.ts → asyncStorageTaskQueue-Dm71_6ID.d.ts} +2 -2
  8. package/dist/{chunk-LNJPVLIC.js → chunk-B4CZLBE6.js} +4 -4
  9. package/dist/{chunk-LNJPVLIC.js.map → chunk-B4CZLBE6.js.map} +1 -1
  10. package/dist/{chunk-EXFU6MTA.js → chunk-ENGV6VZF.js} +511 -89
  11. package/dist/chunk-ENGV6VZF.js.map +1 -0
  12. package/dist/{chunk-R5OFJ23O.cjs → chunk-H7W2KLN2.cjs} +990 -565
  13. package/dist/chunk-H7W2KLN2.cjs.map +1 -0
  14. package/dist/{chunk-VZMLADXQ.cjs → chunk-JETDFDWV.cjs} +10 -10
  15. package/dist/{chunk-VZMLADXQ.cjs.map → chunk-JETDFDWV.cjs.map} +1 -1
  16. package/dist/{chunk-5XBH5SAL.cjs → chunk-KR6FLFIH.cjs} +3 -3
  17. package/dist/{chunk-5XBH5SAL.cjs.map → chunk-KR6FLFIH.cjs.map} +1 -1
  18. package/dist/{chunk-GVF4OCTL.cjs → chunk-QLJXXVRO.cjs} +48 -48
  19. package/dist/{chunk-GVF4OCTL.cjs.map → chunk-QLJXXVRO.cjs.map} +1 -1
  20. package/dist/{chunk-JZAEFOE4.js → chunk-SPJA7XMU.js} +3 -3
  21. package/dist/{chunk-JZAEFOE4.js.map → chunk-SPJA7XMU.js.map} +1 -1
  22. package/dist/{chunk-CXHJGED6.js → chunk-UDQ3QE4C.js} +3 -3
  23. package/dist/{chunk-CXHJGED6.js.map → chunk-UDQ3QE4C.js.map} +1 -1
  24. package/dist/{chunk-S2WWOVFC.js → chunk-W2VYRZLB.js} +4 -4
  25. package/dist/{chunk-S2WWOVFC.js.map → chunk-W2VYRZLB.js.map} +1 -1
  26. package/dist/{chunk-4FDNOLBO.js → chunk-XZEQV5FE.js} +3 -3
  27. package/dist/{chunk-4FDNOLBO.js.map → chunk-XZEQV5FE.js.map} +1 -1
  28. package/dist/{chunk-Q7PC3NHX.cjs → chunk-YFHGGSII.cjs} +18 -18
  29. package/dist/{chunk-Q7PC3NHX.cjs.map → chunk-YFHGGSII.cjs.map} +1 -1
  30. package/dist/{chunk-HIZNPHB2.cjs → chunk-ZDLFQ7ZH.cjs} +15 -15
  31. package/dist/{chunk-HIZNPHB2.cjs.map → chunk-ZDLFQ7ZH.cjs.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-BT5iON1T.d.ts → delegate-DATx5c2o.d.ts} +1 -1
  37. package/dist/{delegate-u6kXTtWY.d.cts → delegate-DRoyCz4n.d.cts} +1 -1
  38. package/dist/{index-CK5QbTmZ.d.ts → index-BKBoBSKX.d.cts} +83 -9
  39. package/dist/{index-CK5QbTmZ.d.cts → index-BKBoBSKX.d.ts} +83 -9
  40. package/dist/{index-D1D4cR-G.d.ts → index-BjDUwnH-.d.ts} +2 -2
  41. package/dist/{index-BCnhItOQ.d.cts → index-CLgF0km0.d.cts} +2 -2
  42. package/dist/index.cjs +321 -309
  43. package/dist/index.d.cts +78 -16
  44. package/dist/index.d.ts +78 -16
  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-BeYR6NpQ.d.ts → taskRunner-B78rNRXB.d.ts} +2 -2
  55. package/dist/{taskRunner-Csey3EYJ.d.cts → taskRunner-CoGRmz1U.d.cts} +2 -2
  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-DzSLMxBZ.d.ts → wallet-CdUjdg15.d.cts} +23 -5
  65. package/dist/{wallet-DG3Qmbmt.d.cts → wallet-yKzfCUfY.d.ts} +23 -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-EXFU6MTA.js.map +0 -1
  72. package/dist/chunk-R5OFJ23O.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } from './chunk-JZAEFOE4.js';
2
- import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-CXHJGED6.js';
3
- import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, sequenceToCanonicalTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, timelockToSequence, assertAllowedSighashTypes, baseFetch, Intent, rateGate, DEFAULT_NETWORK_NAME, formatSighash, normalizeVtxo, assertTimerMs, getSequence, maybeArkError, isArkError, ArkErrorName, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, isEventSourceError, isEventSourceUnavailableError, getAllNormalizedVtxos, isPastExpiry, assertNonNegativeMs, isRetryableProviderError, DEFAULT_PAGE_SIZE, RestArkProvider, DEFAULT_ARKADE_SERVER_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-4FDNOLBO.js';
1
+ import { AssetId, AssetGroup, AssetInput, AssetOutput, Metadata, Packet, BufferReader, BufferWriter, AssetRef, RestIndexerProvider } from './chunk-SPJA7XMU.js';
2
+ import { witnessRefToBytes, validateProgram, toASM, stringifyArtifact, serializeArkadeContractParams, resolveAsm, parseArtifact, getOpcodeValue, getOpcodeName, fromASM, deserializeArkadeContractParams, computeArkadeScriptPublicKey, bytesToASM, asmToBytes, arkadeWitnessHash, arkadeScriptHash, SUPPORTED_PROGRAM_VERSION, OPCODE_VALUES, OPCODE_NAMES, bignum_exports, ArkadeScript, ArkadeProgramScript, ARKADE_OPS, ARKADE_OPCODE_VALUES, ARKADE_OPCODE_NAMES, ARKADE_OPCODES, ARKADE_OP, toXOnly, inputName, contractHandlers, isMainnetDescriptor, descriptorIsOurs, deriveDescriptorLeafPubKey, deriveDescriptorLeafCompressedPubKey, normalizeToDescriptor, extractPubKey, parseHDDescriptor, identityDescriptor, DefaultVtxo, speculativeReceiveMetadata, DelegateVtxo, WALLET_RECEIVE_SOURCE, BoardingContractHandler } from './chunk-UDQ3QE4C.js';
3
+ import { VtxoScript, __export, Transaction, requiresForfeit, CSVMultisigTapscript, networks, getNetwork, DEFAULT_NETWORK, resolveEmulatorPubkey, isVtxoSpent, getNormalizedVtxos, setArkPsbtField, PrevArkTxField, ConditionWitness, craftToSpendTx, ArkAddress, isVirtualCoin, getArkPsbtFields, CosignerPublicKey, ServerResponseMismatchError, OP_RETURN_EMPTY_PKSCRIPT, canSweepOnchain, sequenceToTimelock, sequenceToCanonicalTimelock, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, VtxoTaprootTree, timelockToSequence, assertAllowedSighashTypes, baseFetch, Intent, rateGate, DEFAULT_NETWORK_NAME, formatSighash, normalizeVtxo, assertTimerMs, getSequence, maybeArkError, isArkError, ArkErrorName, toOffchainInputFeeParams, canRecoverOnchain, MultisigTapscript, isEventSourceError, isEventSourceUnavailableError, getAllNormalizedVtxos, isPastExpiry, assertNonNegativeMs, isRetryableProviderError, DEFAULT_PAGE_SIZE, RestArkProvider, DEFAULT_ARKADE_SERVER_URL, networkFromArkadeInfo, ArkError, toBIP371TapTree, resolveTimeHeight, canSpendOffchain, INFO_FETCH_TIMEOUT_MS, PrevoutTxField, fetchVtxoCreatedAtByTxid, EXPIRY_MIN_PLAUSIBLE_MS, ProviderUnavailableError } from './chunk-XZEQV5FE.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';
@@ -3337,6 +3337,53 @@ function selectedCoinsToAssetInputs(selectedCoins) {
3337
3337
  }
3338
3338
  return assetInputs;
3339
3339
  }
3340
+
3341
+ // src/wallet/sendDeadline.ts
3342
+ var SendDeadlineExceededError = class extends Error {
3343
+ constructor(validUntil) {
3344
+ super(`Send deadline ${validUntil} expired before provider submission`);
3345
+ this.name = "SendDeadlineExceededError";
3346
+ }
3347
+ };
3348
+ function captureSendDeadline(value, required = false) {
3349
+ if (value === void 0 && !required) return void 0;
3350
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) {
3351
+ throw new TypeError("validUntil must be a positive safe integer UNIX timestamp in seconds");
3352
+ }
3353
+ return value;
3354
+ }
3355
+ function assertSendDeadline(validUntil) {
3356
+ if (validUntil !== void 0 && Date.now() / 1e3 >= validUntil) {
3357
+ throw new SendDeadlineExceededError(validUntil);
3358
+ }
3359
+ }
3360
+
3361
+ // src/wallet/sendInputExpiry.ts
3362
+ function captureInputExpiryFloor(value, required = false) {
3363
+ if (value === void 0 && !required) return void 0;
3364
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3365
+ throw new TypeError(
3366
+ "inputExpiryFloor must specify a time or height and positive bigint value"
3367
+ );
3368
+ }
3369
+ const { kind, value: floor } = value;
3370
+ if (kind !== "time" && kind !== "height" || typeof floor !== "bigint" || floor <= 0n) {
3371
+ throw new TypeError(
3372
+ "inputExpiryFloor must specify a time or height and positive bigint value"
3373
+ );
3374
+ }
3375
+ return Object.freeze({ kind, value: floor });
3376
+ }
3377
+ function meetsInputExpiryFloor(coin, floor) {
3378
+ if (coin.expiresAt === void 0 === (coin.expiresAtHeight === void 0)) return false;
3379
+ if (floor.kind === "height") {
3380
+ const height = coin.expiresAtHeight;
3381
+ return typeof height === "number" && Number.isSafeInteger(height) && height > 0 && BigInt(height) >= floor.value;
3382
+ }
3383
+ if (!(coin.expiresAt instanceof Date)) return false;
3384
+ const milliseconds = coin.expiresAt.getTime();
3385
+ return Number.isSafeInteger(milliseconds) && milliseconds > 0 && BigInt(milliseconds) >= floor.value * 1000n;
3386
+ }
3340
3387
  function toXOnlySignerHex(pubkeyHex) {
3341
3388
  const bytes = hex.decode(pubkeyHex);
3342
3389
  if (bytes.length === 32 || bytes.length === 33) return hex.encode(toXOnly(bytes, "signer key"));
@@ -9550,11 +9597,18 @@ var ContractManager = class _ContractManager {
9550
9597
  initialized = false;
9551
9598
  eventCallbacks = /* @__PURE__ */ new Set();
9552
9599
  stopWatcherFn;
9600
+ /** Watcher events still being handled. They write VTXO rows, so {@link dispose} waits for them. */
9601
+ inFlightEvents = /* @__PURE__ */ new Set();
9553
9602
  /** `undefined` while online; the failure reason once a sync degrades. */
9554
9603
  syncDegradedReason;
9555
9604
  /** Epoch-ms of the last successful provider sync, if any. */
9556
9605
  lastSyncedAt;
9557
9606
  syncedAtByScript = /* @__PURE__ */ new Map();
9607
+ syncsInFlight = 0;
9608
+ /** The off-critical-path boot sequence, if one is running. @see runBootSequence */
9609
+ bootTask;
9610
+ /** A catch-up sync requested behind a stored read. @see requestCatchUpSync */
9611
+ catchUpSync;
9558
9612
  /** Last chain tip read, with the epoch-ms it was read at. @see currentChainTip */
9559
9613
  chainTipCache;
9560
9614
  /** In-flight chain tip read, so concurrent cache misses share one. */
@@ -9595,12 +9649,18 @@ var ContractManager = class _ContractManager {
9595
9649
  * {@link initialize}, {@link getContractsWithVtxos} and {@link createContract}.
9596
9650
  */
9597
9651
  getSyncState() {
9598
- return this.syncDegradedReason === void 0 ? { mode: "online", lastSyncedAt: this.lastSyncedAt } : {
9652
+ const syncing = this.syncsInFlight > 0;
9653
+ return this.syncDegradedReason === void 0 ? { mode: "online", syncing, lastSyncedAt: this.lastSyncedAt } : {
9599
9654
  mode: "degraded",
9655
+ syncing,
9600
9656
  reason: this.syncDegradedReason,
9601
9657
  lastSyncedAt: this.lastSyncedAt
9602
9658
  };
9603
9659
  }
9660
+ /** @inheritdoc */
9661
+ whenBooted() {
9662
+ return this.bootTask ?? Promise.resolve();
9663
+ }
9604
9664
  /** @see ContractManagerConfig.vtxoSyncMaxAgeMs — for factory-built managers. */
9605
9665
  setVtxoSyncMaxAge(maxAgeMs) {
9606
9666
  assertNonNegativeMs("vtxoSyncMaxAgeMs", maxAgeMs);
@@ -9623,9 +9683,14 @@ var ContractManager = class _ContractManager {
9623
9683
  syncGapReason() {
9624
9684
  const annotations = this.annotationDegradedReason();
9625
9685
  const owedRefill = this.lookAheadRefillOwed ? "the look-ahead band is behind the allocation watermark, so a funded address inside it is not being watched yet" : void 0;
9626
- const reasons = [annotations, owedRefill].filter((r) => r !== void 0);
9686
+ const watcher = this.watcherStartFailure === void 0 ? void 0 : `the contract watcher failed to start, so incoming funds are not being observed \u2014 ${this.watcherStartFailure}`;
9687
+ const reasons = [annotations, owedRefill, watcher].filter(
9688
+ (r) => r !== void 0
9689
+ );
9627
9690
  return reasons.length === 0 ? void 0 : reasons.join("; ");
9628
9691
  }
9692
+ /** Why the lazy boot's watcher start failed; nothing retries it, so no sync may clear it. */
9693
+ watcherStartFailure;
9629
9694
  /** Contracts a sync could not annotate, as `script → reason`. */
9630
9695
  annotationFailures = /* @__PURE__ */ new Map();
9631
9696
  annotationDegradedReason() {
@@ -9670,21 +9735,75 @@ var ContractManager = class _ContractManager {
9670
9735
  for (const contract of contracts) {
9671
9736
  await this.watcher.addContract(contract);
9672
9737
  }
9673
- try {
9674
- await this.scheduleLookAheadDrain();
9675
- } catch (err) {
9676
- if (!isRetryableProviderError(err)) throw err;
9677
- this.lookAheadRefillOwed = true;
9678
- this.markSyncDegraded(err);
9738
+ if (!this.config.lazyInitialization) {
9739
+ try {
9740
+ await this.scheduleLookAheadDrain();
9741
+ } catch (err) {
9742
+ if (!isRetryableProviderError(err)) throw err;
9743
+ this.lookAheadRefillOwed = true;
9744
+ this.markSyncDegraded(err);
9745
+ }
9746
+ await this.trySync(() => this.reconcileWatched());
9747
+ this.initialized = true;
9748
+ this.stopWatcherFn = await this.watcher.startWatching(
9749
+ (event) => this.onWatcherEvent(event)
9750
+ );
9751
+ return;
9679
9752
  }
9680
- await this.trySync(() => this.reconcileWatched());
9681
9753
  this.initialized = true;
9682
- this.stopWatcherFn = await this.watcher.startWatching((event) => {
9683
- this.handleContractEvent(event).catch((error) => {
9684
- console.error("Error handling contract event:", error);
9685
- });
9754
+ const boot = this.runBootSequence();
9755
+ this.bootTask = boot;
9756
+ void boot.catch(() => {
9757
+ }).finally(() => {
9758
+ if (this.bootTask === boot) this.bootTask = void 0;
9686
9759
  });
9687
9760
  }
9761
+ async runBootSequence() {
9762
+ this.syncsInFlight++;
9763
+ this.watcherStartFailure = void 0;
9764
+ try {
9765
+ try {
9766
+ await this.scheduleLookAheadDrain();
9767
+ } catch (err) {
9768
+ this.lookAheadRefillOwed = true;
9769
+ this.reportBackgroundFailure("look-ahead drain", err);
9770
+ }
9771
+ try {
9772
+ await this.reconcileWatched();
9773
+ this.markSyncOnline();
9774
+ } catch (err) {
9775
+ this.reportBackgroundFailure("boot sync", err);
9776
+ }
9777
+ if (this.disposed) return;
9778
+ try {
9779
+ const stopWatching = await this.watcher.startWatching(
9780
+ (event) => this.onWatcherEvent(event)
9781
+ );
9782
+ if (this.disposed) stopWatching();
9783
+ else this.stopWatcherFn = stopWatching;
9784
+ } catch (err) {
9785
+ this.watcherStartFailure = err instanceof Error ? err.message : String(err);
9786
+ this.reportBackgroundFailure("watcher start", err);
9787
+ }
9788
+ } finally {
9789
+ this.syncsInFlight--;
9790
+ }
9791
+ }
9792
+ /** Tracked so {@link dispose} can wait for handlers still writing. */
9793
+ onWatcherEvent(event) {
9794
+ const handled = this.handleContractEvent(event).catch((error) => {
9795
+ console.error("Error handling contract event:", error);
9796
+ });
9797
+ this.inFlightEvents.add(handled);
9798
+ void handled.finally(() => this.inFlightEvents.delete(handled));
9799
+ }
9800
+ /** No throw: construction returned long ago, so the state is the channel. */
9801
+ reportBackgroundFailure(stage, err) {
9802
+ this.markSyncDegraded(err);
9803
+ if (!isRetryableProviderError(err)) {
9804
+ console.error(`[contracts] background ${stage} failed`, err);
9805
+ }
9806
+ }
9688
9807
  /**
9689
9808
  * Delta-sync the watched set (boot and reconnect), then reconcile the pending frontier, which
9690
9809
  * catches not-yet-finalized virtual outputs that can sit outside any delta window.
@@ -10165,6 +10284,32 @@ var ContractManager = class _ContractManager {
10165
10284
  vtxos: vtxosByScript.get(contract.script)?.slice() ?? []
10166
10285
  }));
10167
10286
  }
10287
+ async getStoredContractsWithVtxos(filter) {
10288
+ const contracts = await this.getContracts(filter);
10289
+ if (!this.syncedWithin(contracts, this.config.vtxoSyncMaxAgeMs ?? 0)) {
10290
+ this.requestCatchUpSync(contracts);
10291
+ }
10292
+ const vtxos = await this.getVtxosForContracts(contracts);
10293
+ return contracts.map((contract) => ({
10294
+ contract,
10295
+ vtxos: vtxos.filter((vtxo) => vtxo.contractScript === contract.script)
10296
+ }));
10297
+ }
10298
+ requestCatchUpSync(contracts) {
10299
+ if (this.disposed || this.bootTask || this.catchUpSync || contracts.length === 0) return;
10300
+ const run = (async () => {
10301
+ try {
10302
+ await this.syncContracts({ contracts });
10303
+ this.markSyncOnline();
10304
+ } catch (err) {
10305
+ this.reportBackgroundFailure("catch-up sync", err);
10306
+ }
10307
+ })();
10308
+ this.catchUpSync = run;
10309
+ void run.finally(() => {
10310
+ if (this.catchUpSync === run) this.catchUpSync = void 0;
10311
+ });
10312
+ }
10168
10313
  async annotateVtxos(vtxos, tapscripts) {
10169
10314
  if (vtxos.length === 0) return [];
10170
10315
  const scripts = Array.from(new Set(vtxos.map((v) => v.script)));
@@ -10481,6 +10626,7 @@ var ContractManager = class _ContractManager {
10481
10626
  }
10482
10627
  }
10483
10628
  async handleContractEvent(event) {
10629
+ if (this.disposed) return;
10484
10630
  if (this.lookAheadRefillOwed) this.requestLookAheadDrain();
10485
10631
  try {
10486
10632
  switch (event.type) {
@@ -10534,6 +10680,14 @@ var ContractManager = class _ContractManager {
10534
10680
  }
10535
10681
  /** Sync virtual outputs for the given contracts (default: the watched set). */
10536
10682
  async syncContracts(options) {
10683
+ this.syncsInFlight++;
10684
+ try {
10685
+ return await this.performContractSync(options);
10686
+ } finally {
10687
+ this.syncsInFlight--;
10688
+ }
10689
+ }
10690
+ async performContractSync(options) {
10537
10691
  const cursor = await getSyncCursor(this.config.walletRepository);
10538
10692
  const window2 = options.window ?? computeSyncWindow(cursor, this.config.vtxoSyncOverlapMs);
10539
10693
  const mustUpdateCursor = options.contracts === void 0 && options.window === void 0 && (window2.after ?? 0) <= cursor;
@@ -10702,34 +10856,49 @@ var ContractManager = class _ContractManager {
10702
10856
  }
10703
10857
  return { vtxosByScript: result, promoted };
10704
10858
  }
10705
- /** Stop the watcher, clear callbacks, and mark the manager uninitialized. */
10859
+ /**
10860
+ * Stop the watcher, clear callbacks, and mark the manager uninitialized.
10861
+ *
10862
+ * Teardown is synchronous. The returned promise settles once watcher events already being
10863
+ * handled, any look-ahead drain, and any lazy boot sequence finish; after that nothing more is written to the
10864
+ * repositories.
10865
+ */
10706
10866
  dispose() {
10707
10867
  this.disposed = true;
10708
10868
  const pendingDrain = this.lookAheadDrain;
10869
+ const pendingBoot = this.bootTask;
10709
10870
  this.stopWatcherFn?.();
10710
10871
  this.stopWatcherFn = void 0;
10711
10872
  this.eventCallbacks.clear();
10712
10873
  this.lookAheadEntries.clear();
10713
- if (pendingDrain) {
10714
- void pendingDrain.catch(() => {
10715
- }).then(() => {
10716
- if (this.disposed) this.lookAheadEntries.clear();
10717
- });
10718
- }
10874
+ const drainUnwound = pendingDrain?.catch(() => {
10875
+ }).then(() => {
10876
+ if (this.disposed) this.lookAheadEntries.clear();
10877
+ });
10719
10878
  this.initialized = false;
10879
+ return Promise.all([...this.inFlightEvents, drainUnwound, pendingBoot]).then(
10880
+ () => void 0
10881
+ );
10720
10882
  }
10721
10883
  /**
10722
- * Symbol.dispose implementation for the `using` keyword.
10884
+ * Symbol.dispose implementation for the `using` keyword. Teardown is immediate, but it does
10885
+ * not wait for in-flight work; use `await using` for that.
10886
+ */
10887
+ [Symbol.dispose]() {
10888
+ void this.dispose();
10889
+ }
10890
+ /**
10891
+ * Symbol.asyncDispose implementation for the `await using` keyword; waits like {@link dispose}.
10723
10892
  * @example
10724
10893
  * ```typescript
10725
10894
  * {
10726
- * using manager = await wallet.getContractManager();
10895
+ * await using manager = await wallet.getContractManager();
10727
10896
  * // ... use manager
10728
- * } // automatically disposed
10897
+ * } // disposed, with in-flight events finished
10729
10898
  * ```
10730
10899
  */
10731
- [Symbol.dispose]() {
10732
- this.dispose();
10900
+ async [Symbol.asyncDispose]() {
10901
+ await this.dispose();
10733
10902
  }
10734
10903
  };
10735
10904
 
@@ -12473,6 +12642,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
12473
12642
  walletRepository;
12474
12643
  contractRepository;
12475
12644
  delegateProvider;
12645
+ lazyInitialization = false;
12646
+ boardingLoaded = false;
12476
12647
  _contractManager;
12477
12648
  _contractManagerInitializing;
12478
12649
  watcherConfig;
@@ -12535,9 +12706,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
12535
12706
  * construct, so it is safe for readonly callers.
12536
12707
  */
12537
12708
  getProviderConnectionState() {
12709
+ const syncing = this._contractManager?.getSyncState().syncing ?? false;
12538
12710
  if (this._serverInfoSource === "cache") {
12539
12711
  return {
12540
12712
  mode: "degraded",
12713
+ syncing,
12541
12714
  source: "cache",
12542
12715
  provider: "arkade",
12543
12716
  reason: "constructed from cached server-info; operator was unreachable at boot",
@@ -12548,6 +12721,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12548
12721
  if (sync?.mode === "degraded") {
12549
12722
  return {
12550
12723
  mode: "degraded",
12724
+ syncing,
12551
12725
  source: "repository",
12552
12726
  provider: "indexer",
12553
12727
  reason: sync.reason,
@@ -12556,6 +12730,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12556
12730
  }
12557
12731
  return {
12558
12732
  mode: "online",
12733
+ syncing,
12559
12734
  source: "live",
12560
12735
  lastOnlineAt: sync?.lastSyncedAt ?? this._serverInfoLastOnlineAt ?? 0
12561
12736
  };
@@ -12802,6 +12977,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
12802
12977
  );
12803
12978
  wallet.vtxoSyncOverlapMs = config.vtxoSyncOverlapMs;
12804
12979
  wallet.intentRepository = config.storage?.intentRepository;
12980
+ wallet.lazyInitialization = config.lazyInitialization ?? false;
12805
12981
  wallet.virtualTxRepository = config.storage?.virtualTxRepository;
12806
12982
  wallet.exitDataCapture = config.storage?.exitDataCapture;
12807
12983
  wallet._serverInfoSource = setup.serverInfoSource;
@@ -12842,6 +13018,19 @@ var ReadonlyWallet = class _ReadonlyWallet {
12842
13018
  // The bucketer drops every spent coin and the gate reads contracts only.
12843
13019
  this.contractSnapshot(void 0, { unspentOnly: true })
12844
13020
  ]);
13021
+ return this.balanceFromSnapshot(boardingUtxos, snapshot);
13022
+ }
13023
+ /** Cached balance; inspect connection state and boarding.loaded before displaying zeros. */
13024
+ async getStoredBalance() {
13025
+ const [boardingUtxos, snapshot] = await Promise.all([
13026
+ this.getStoredBoardingUtxos(),
13027
+ this.contractSnapshotStored()
13028
+ ]);
13029
+ const balance = await this.balanceFromSnapshot(boardingUtxos, snapshot);
13030
+ balance.boarding.loaded = this.boardingLoaded;
13031
+ return balance;
13032
+ }
13033
+ async balanceFromSnapshot(boardingUtxos, snapshot) {
12845
13034
  const vtxos = filterSnapshotVtxos(
12846
13035
  snapshot,
12847
13036
  { withRecoverable: true, withUnrolled: true },
@@ -12868,6 +13057,14 @@ var ReadonlyWallet = class _ReadonlyWallet {
12868
13057
  this._pendingSpendOutpoints
12869
13058
  );
12870
13059
  }
13060
+ /** Cached VTXOs; may be empty before the first sync. Never use for coin selection. */
13061
+ async getStoredVtxos(filter) {
13062
+ return filterSnapshotVtxos(
13063
+ await this.contractSnapshotStored(),
13064
+ filter,
13065
+ this._pendingSpendOutpoints
13066
+ );
13067
+ }
12871
13068
  /** @inheritdoc */
12872
13069
  async getSpendableVtxos(filter) {
12873
13070
  const snapshot = await this.contractSnapshot(filter, {
@@ -12972,6 +13169,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
12972
13169
  requireSynced: filter?.requireSynced
12973
13170
  });
12974
13171
  }
13172
+ async contractSnapshotStored() {
13173
+ const contractManager = await this.getContractManager();
13174
+ return contractManager.getStoredContractsWithVtxos ? contractManager.getStoredContractsWithVtxos() : contractManager.getContractsWithVtxos();
13175
+ }
12975
13176
  /**
12976
13177
  * The two exclusion sets the gate is made of, derived from one snapshot so
12977
13178
  * {@link getSpendableVtxos} and the balance answer about the same instant.
@@ -13236,6 +13437,14 @@ var ReadonlyWallet = class _ReadonlyWallet {
13236
13437
  await this.walletRepository.saveUtxos(
13237
13438
  new Map(groups.map((group, i) => [addresses[i], group.coins]))
13238
13439
  );
13440
+ for (const [i, group] of groups.entries()) {
13441
+ const fresh = new Set(group.coins.map((coin) => `${coin.txid}:${coin.vout}`));
13442
+ const cached = await collectUtxos(this.walletRepository, addresses[i]);
13443
+ const kept = cached.filter((coin) => fresh.has(`${coin.txid}:${coin.vout}`));
13444
+ if (kept.length === cached.length) continue;
13445
+ await this.walletRepository.deleteUtxos(addresses[i]);
13446
+ if (kept.length > 0) await this.walletRepository.saveUtxos(addresses[i], kept);
13447
+ }
13239
13448
  return groups;
13240
13449
  }
13241
13450
  /**
@@ -13249,8 +13458,21 @@ var ReadonlyWallet = class _ReadonlyWallet {
13249
13458
  toXOnlySignerHex(hex.encode(this.boardingTapscript.options.serverPubKey))
13250
13459
  ]);
13251
13460
  const groups = await this.getBoardingUtxosForSigners(currentOnly);
13461
+ this.boardingLoaded = true;
13252
13462
  return groups.flatMap((g) => g.coins);
13253
13463
  }
13464
+ async getStoredBoardingUtxos() {
13465
+ const currentOnly = /* @__PURE__ */ new Set([
13466
+ toXOnlySignerHex(hex.encode(this.boardingTapscript.options.serverPubKey))
13467
+ ]);
13468
+ const tapscripts = await this.getBoardingTapscripts(currentOnly);
13469
+ const perAddress = await Promise.all(
13470
+ tapscripts.map(
13471
+ (tapscript) => collectUtxos(this.walletRepository, tapscript.onchainAddress(this.network))
13472
+ )
13473
+ );
13474
+ return perAddress.flat();
13475
+ }
13254
13476
  /**
13255
13477
  * Subscribe to onchain and offchain notifications for newly received funds.
13256
13478
  *
@@ -13477,6 +13699,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13477
13699
  onVtxosSpent = (vtxos) => pruneExitBranches(virtualTxRepository, vtxos);
13478
13700
  }
13479
13701
  const manager = await ContractManager.create({
13702
+ lazyInitialization: this.lazyInitialization,
13480
13703
  indexerProvider: this.indexerProvider,
13481
13704
  contractRepository: this.contractRepository,
13482
13705
  walletRepository: this.walletRepository,
@@ -13576,7 +13799,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
13576
13799
  /** Dispose wallet-owned managers and release background resources. */
13577
13800
  async dispose() {
13578
13801
  const manager = this._contractManager ?? (this._contractManagerInitializing ? await this._contractManagerInitializing.catch(() => void 0) : void 0);
13579
- manager?.dispose();
13802
+ await manager?.dispose();
13580
13803
  this._contractManager = void 0;
13581
13804
  this._contractManagerInitializing = void 0;
13582
13805
  }
@@ -14419,6 +14642,7 @@ var Wallet2 = class extends ReadonlyWallet {
14419
14642
  },
14420
14643
  checkpointExitDelayOverrides
14421
14644
  );
14645
+ wallet.lazyInitialization = config.lazyInitialization ?? false;
14422
14646
  wallet._serverInfoSource = setup.serverInfoSource;
14423
14647
  if (setup.serverInfoSource === "live") {
14424
14648
  const now = Date.now();
@@ -14505,12 +14729,17 @@ var Wallet2 = class extends ReadonlyWallet {
14505
14729
  *
14506
14730
  * @param params - Optional settlement inputs and outputs. When omitted, the wallet settles all eligible funds.
14507
14731
  * @param eventCallback - Optional callback invoked for settlement stream events.
14732
+ * @param hooks - Optional phases for preparation and intent registration.
14508
14733
  * @returns The finalized Arkade transaction id
14509
14734
  */
14510
- async settle(params, eventCallback) {
14511
- return this._withTxLock(() => this._settleImpl(params, eventCallback));
14735
+ async settle(params, eventCallback, hooks) {
14736
+ return this._withTxLock(() => {
14737
+ hooks?.onPhase?.("preparing");
14738
+ const onRegistrationAttempt = hooks?.onPhase ? () => hooks.onPhase?.("registration_attempt") : void 0;
14739
+ return this._settleImpl(params, eventCallback, onRegistrationAttempt);
14740
+ });
14512
14741
  }
14513
- async _settleImpl(params, eventCallback) {
14742
+ async _settleImpl(params, eventCallback, onRegistrationAttempt) {
14514
14743
  if (params?.inputs) {
14515
14744
  for (const input of params.inputs) {
14516
14745
  if (typeof input === "string") {
@@ -14725,6 +14954,7 @@ var Wallet2 = class extends ReadonlyWallet {
14725
14954
  }
14726
14955
  yield* stream;
14727
14956
  })();
14957
+ onRegistrationAttempt?.();
14728
14958
  const intentId = await this.safeRegisterIntent(intent, params.inputs);
14729
14959
  await this.persistIntentSnapshot(
14730
14960
  intentTxId,
@@ -15736,13 +15966,13 @@ var Wallet2 = class extends ReadonlyWallet {
15736
15966
  */
15737
15967
  async send(...args) {
15738
15968
  const params = asSendParams(args);
15739
- return this._withTxLock(() => this._sendImpl(params));
15969
+ const validUntil = captureSendDeadline(params.validUntil);
15970
+ const inputExpiryFloor = captureInputExpiryFloor(params.inputExpiryFloor);
15971
+ assertSendDeadline(validUntil);
15972
+ return this._withTxLock(() => this._sendImpl(params, validUntil, inputExpiryFloor));
15740
15973
  }
15741
- async _sendImpl({
15742
- recipients: args,
15743
- selectedVtxos,
15744
- maxChangeFee
15745
- }) {
15974
+ async _sendImpl({ recipients: args, selectedVtxos, maxChangeFee }, validUntil, inputExpiryFloor) {
15975
+ assertSendDeadline(validUntil);
15746
15976
  if (args.length === 0) {
15747
15977
  throw new Error("At least one receiver is required");
15748
15978
  }
@@ -15753,6 +15983,10 @@ var Wallet2 = class extends ReadonlyWallet {
15753
15983
  throw new Error("send({ maxChangeFee }): expected a non-negative safe integer");
15754
15984
  }
15755
15985
  if (selectedVtxos) {
15986
+ if (inputExpiryFloor) selectedVtxos = selectedVtxos.map(normalizeVtxo);
15987
+ if (inputExpiryFloor && selectedVtxos.some((coin) => !meetsInputExpiryFloor(coin, inputExpiryFloor))) {
15988
+ throw new Error("send({ selectedVtxos }): input expiry floor not met");
15989
+ }
15756
15990
  void this.logUngatedInputs("send({ selectedVtxos })", selectedVtxos);
15757
15991
  }
15758
15992
  const offchainTapscript = this.offchainTapscript;
@@ -15771,6 +16005,11 @@ var Wallet2 = class extends ReadonlyWallet {
15771
16005
  withRecoverable: false,
15772
16006
  genericallySpendableOnly: true
15773
16007
  });
16008
+ if (inputExpiryFloor) {
16009
+ virtualCoins = virtualCoins.filter(
16010
+ (coin) => meetsInputExpiryFloor(coin, inputExpiryFloor)
16011
+ );
16012
+ }
15774
16013
  }
15775
16014
  const assetChanges = /* @__PURE__ */ new Map();
15776
16015
  let selectedCoins = selectedVtxos ? [...selectedVtxos] : [];
@@ -16005,27 +16244,33 @@ var Wallet2 = class extends ReadonlyWallet {
16005
16244
  outputs.push(Extension.create(allExtPackets).txOut());
16006
16245
  }
16007
16246
  const sentAmount = recipients.reduce((sum, r) => sum + r.amount, 0);
16008
- return this._submitOffchainSpend(selectedCoins, outputs, {
16009
- sentAmount,
16010
- changeAmount: BigInt(changeAmount),
16011
- changeVout: changeReceiver ? changeIndex : 0,
16012
- offchainTapscript,
16013
- serverPubKey,
16014
- serverUnrollScript,
16015
- changeAssets: changeReceiver?.assets
16016
- });
16247
+ return this._submitOffchainSpend(
16248
+ selectedCoins,
16249
+ outputs,
16250
+ {
16251
+ sentAmount,
16252
+ changeAmount: BigInt(changeAmount),
16253
+ changeVout: changeReceiver ? changeIndex : 0,
16254
+ offchainTapscript,
16255
+ serverPubKey,
16256
+ serverUnrollScript,
16257
+ changeAssets: changeReceiver?.assets
16258
+ },
16259
+ { validUntil }
16260
+ );
16017
16261
  }
16018
16262
  /**
16019
16263
  * Shared submit/persist tail of `send` and {@link sendSelectedVtxosToSelf}; callers own coin
16020
16264
  * selection, outputs and the synchronous epoch snapshot.
16021
16265
  */
16022
- async _submitOffchainSpend(inputs, outputs, persist) {
16266
+ async _submitOffchainSpend(inputs, outputs, persist, options) {
16023
16267
  this._addPendingSpends(inputs);
16024
16268
  try {
16025
- const { arkTxid, signedCheckpointTxs } = await this.buildAndSubmitOffchainTx(
16269
+ const { arkTxid, signedCheckpointTxs } = await this._buildAndSubmitOffchainTx(
16026
16270
  inputs,
16027
16271
  outputs,
16028
- persist.serverUnrollScript
16272
+ persist.serverUnrollScript,
16273
+ options
16029
16274
  );
16030
16275
  await this.updateDbAfterOffchainTx(
16031
16276
  inputs,
@@ -16118,7 +16363,16 @@ var Wallet2 = class extends ReadonlyWallet {
16118
16363
  *
16119
16364
  * @returns The Arkade transaction id and server-signed checkpoint PSBTs (for bookkeeping)
16120
16365
  */
16121
- async buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript = this.serverUnrollScript) {
16366
+ async buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript = this.serverUnrollScript, options) {
16367
+ const validUntil = captureSendDeadline(options?.validUntil);
16368
+ assertSendDeadline(validUntil);
16369
+ return this._withTxLock(
16370
+ () => this._buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript, { validUntil })
16371
+ );
16372
+ }
16373
+ async _buildAndSubmitOffchainTx(inputs, outputs, serverUnrollScript, options) {
16374
+ const validUntil = captureSendDeadline(options?.validUntil);
16375
+ assertSendDeadline(validUntil);
16122
16376
  void this.logUngatedInputs("buildAndSubmitOffchainTx", inputs);
16123
16377
  await (await this.getContractManager()).assertAnnotatable(inputs);
16124
16378
  const offchainTx = buildOffchainTx(
@@ -16176,7 +16430,25 @@ var Wallet2 = class extends ReadonlyWallet {
16176
16430
  {
16177
16431
  // Mark pending before submitting — if we crash between submit and
16178
16432
  // finalize, the next init recovers via finalizePendingTxs.
16179
- beforeSubmit: () => this.setPendingTxFlag(true),
16433
+ beforeSubmit: async () => {
16434
+ const ownsPendingFlag = validUntil !== void 0 && !await this.hasPendingTxFlag();
16435
+ await this.setPendingTxFlag(true);
16436
+ try {
16437
+ assertSendDeadline(validUntil);
16438
+ } catch (error) {
16439
+ if (ownsPendingFlag) {
16440
+ try {
16441
+ await this.setPendingTxFlag(false);
16442
+ } catch (clearError) {
16443
+ console.error(
16444
+ "Failed to clear pending tx flag after deadline expiry:",
16445
+ clearError
16446
+ );
16447
+ }
16448
+ }
16449
+ throw error;
16450
+ }
16451
+ },
16180
16452
  afterFinalize: async () => {
16181
16453
  try {
16182
16454
  await this.setPendingTxFlag(false);
@@ -16811,6 +17083,7 @@ var MessageBus = class {
16811
17083
  delegateProvider,
16812
17084
  settlementConfig: config.settlementConfig,
16813
17085
  walletMode: config.walletMode,
17086
+ lazyInitialization: config.lazyInitialization,
16814
17087
  watcherConfig: config.watcherConfig,
16815
17088
  lookAheadWindow: config.lookAheadWindow,
16816
17089
  minBatchExpirySeconds: config.minBatchExpirySeconds,
@@ -16820,6 +17093,7 @@ var MessageBus = class {
16820
17093
  }
16821
17094
  const identity = hydrateIdentity(serialized);
16822
17095
  const readonlyWallet = await ReadonlyWallet.create({
17096
+ lazyInitialization: config.lazyInitialization,
16823
17097
  identity,
16824
17098
  arkProvider,
16825
17099
  arkServerPublicKey: config.arkServer.publicKey,
@@ -17406,8 +17680,6 @@ var Ramps = class {
17406
17680
  return { change, changeAddress };
17407
17681
  }
17408
17682
  };
17409
-
17410
- // src/wallet/serviceWorker/wallet-message-handler.ts
17411
17683
  var WalletNotInitializedError = class extends Error {
17412
17684
  constructor() {
17413
17685
  super("Wallet handler not initialized");
@@ -17550,9 +17822,11 @@ var WalletMessageHandler = class {
17550
17822
  // `onWalletInitialized` re-subscribes incoming funds while
17551
17823
  // `ensureContractEventBroadcasting` deliberately keeps its subscription, so
17552
17824
  // a shared bump would leave the live contract-event emitter permanently
17553
- // stale, and folding requests in would truncate an in-flight settle.
17825
+ // stale, folding requests in would truncate an in-flight settle, and
17826
+ // sharing with boarding would kill every lazy refresh (see `boardingEpoch`).
17554
17827
  incomingFundsEpoch = 0;
17555
17828
  contractEventsEpoch = 0;
17829
+ boardingEpoch = 0;
17556
17830
  /** Per-request progress callbacks: ends with the handler, not with a re-init. */
17557
17831
  requestEpoch = 0;
17558
17832
  /**
@@ -17577,6 +17851,7 @@ var WalletMessageHandler = class {
17577
17851
  this.requestEpoch++;
17578
17852
  this.incomingFundsEpoch++;
17579
17853
  this.contractEventsEpoch++;
17854
+ this.boardingEpoch++;
17580
17855
  this.channel = void 0;
17581
17856
  this.onNextTick = [];
17582
17857
  if (this.incomingFundsSubscription) {
@@ -17618,6 +17893,8 @@ var WalletMessageHandler = class {
17618
17893
  return this.incomingFundsEpoch;
17619
17894
  case "contractEvents":
17620
17895
  return this.contractEventsEpoch;
17896
+ case "boarding":
17897
+ return this.boardingEpoch;
17621
17898
  case "request":
17622
17899
  return this.requestEpoch;
17623
17900
  default: {
@@ -17790,7 +18067,10 @@ var WalletMessageHandler = class {
17790
18067
  });
17791
18068
  }
17792
18069
  case "GET_BOARDING_UTXOS": {
17793
- const utxos = await this.getAllBoardingUtxos();
18070
+ if (!this.readonlyWallet) {
18071
+ throw new WalletNotInitializedError();
18072
+ }
18073
+ const utxos = await this.readonlyWallet.getBoardingUtxos();
17794
18074
  return this.tagged({
17795
18075
  id,
17796
18076
  type: "BOARDING_UTXOS",
@@ -18066,6 +18346,43 @@ var WalletMessageHandler = class {
18066
18346
  payload: { txid }
18067
18347
  });
18068
18348
  }
18349
+ case "SEND_WITH_DEADLINE":
18350
+ case "SEND_WITH_INPUT_EXPIRY_FLOOR": {
18351
+ const wallet = this.requireWallet();
18352
+ const {
18353
+ recipients,
18354
+ selectedVtxos,
18355
+ maxChangeFee,
18356
+ validUntil: wireDeadline
18357
+ } = message.payload;
18358
+ const inputExpiryFloor = message.type === "SEND_WITH_INPUT_EXPIRY_FLOOR" ? captureInputExpiryFloor(
18359
+ message.payload.inputExpiryFloor,
18360
+ true
18361
+ ) : void 0;
18362
+ const validUntil = captureSendDeadline(
18363
+ wireDeadline,
18364
+ message.type === "SEND_WITH_DEADLINE"
18365
+ );
18366
+ try {
18367
+ const txid = await wallet.send({
18368
+ recipients,
18369
+ ...selectedVtxos ? { selectedVtxos } : {},
18370
+ ...maxChangeFee !== void 0 ? { maxChangeFee } : {},
18371
+ validUntil,
18372
+ ...inputExpiryFloor ? { inputExpiryFloor } : {}
18373
+ });
18374
+ return this.tagged({ id, type: "SEND_SUCCESS", payload: { txid } });
18375
+ } catch (error) {
18376
+ if (validUntil === void 0 || !(error instanceof SendDeadlineExceededError))
18377
+ throw error;
18378
+ return this.tagged({
18379
+ id,
18380
+ type: "SEND_DEADLINE_EXCEEDED",
18381
+ error,
18382
+ payload: { validUntil }
18383
+ });
18384
+ }
18385
+ }
18069
18386
  case "GET_ASSET_DETAILS": {
18070
18387
  const { assetId } = message.payload;
18071
18388
  const assetDetails = await this.readonlyWallet.assetManager.getAssetDetails(assetId);
@@ -18261,9 +18578,16 @@ var WalletMessageHandler = class {
18261
18578
  // Wallet methods
18262
18579
  async handleInitWallet({ payload }) {
18263
18580
  const { arkServerUrl } = payload;
18581
+ this.lazyBoardingInit = payload.lazyBoarding ?? false;
18582
+ this.boardingEpoch++;
18583
+ this.boardingLoaded = false;
18264
18584
  this.indexerProvider = new RestIndexerProvider(arkServerUrl);
18265
18585
  await this.onWalletInitialized();
18266
18586
  }
18587
+ /** @see RequestInitWallet.payload.lazyBoarding */
18588
+ lazyBoardingInit = false;
18589
+ /** Set once this session has actually fetched the boarding addresses. */
18590
+ boardingLoaded = false;
18267
18591
  /**
18268
18592
  * The worker's own balance. Same bucketing rules as `Wallet.getBalance` —
18269
18593
  * both call {@link computeOffchainBalance} — but deliberately a different
@@ -18274,7 +18598,7 @@ var WalletMessageHandler = class {
18274
18598
  */
18275
18599
  async handleGetBalance() {
18276
18600
  const [boardingUtxos, { snapshot, vtxos: allVtxos }] = await Promise.all([
18277
- this.getAllBoardingUtxos(),
18601
+ this.getBoardingUtxosForBalance(),
18278
18602
  // The bucketer drops every spent coin and the gate reads contracts only.
18279
18603
  this.repoSnapshot({ unspentOnly: true })
18280
18604
  ]);
@@ -18290,11 +18614,14 @@ var WalletMessageHandler = class {
18290
18614
  isUnlocked: (vtxo) => unlocked.has(`${vtxo.txid}:${vtxo.vout}`),
18291
18615
  dustCarrier: getDustAmount(this.readonlyWallet)
18292
18616
  });
18293
- return toWalletBalance(boardingUtxos, offchain);
18617
+ const balance = toWalletBalance(boardingUtxos, offchain);
18618
+ balance.boarding.loaded = this.boardingLoaded;
18619
+ return balance;
18294
18620
  }
18295
- async getAllBoardingUtxos() {
18621
+ async getBoardingUtxosForBalance() {
18296
18622
  if (!this.readonlyWallet) return [];
18297
- return this.readonlyWallet.getBoardingUtxos();
18623
+ if (!this.lazyBoardingInit) return this.readonlyWallet.getBoardingUtxos();
18624
+ return this.readonlyWallet.getStoredBoardingUtxos ? this.readonlyWallet.getStoredBoardingUtxos() : this.readonlyWallet.getBoardingUtxos();
18298
18625
  }
18299
18626
  async onWalletInitialized() {
18300
18627
  const wallet = this.readonlyWallet;
@@ -18304,7 +18631,7 @@ var WalletMessageHandler = class {
18304
18631
  const init = this.newGeneration("incomingFunds");
18305
18632
  await this.ensureContractEventBroadcasting();
18306
18633
  if (init.stale) return;
18307
- await this.refreshCachedData();
18634
+ await this.refreshCachedData({ lazyBoarding: this.lazyBoardingInit });
18308
18635
  if (init.stale) return;
18309
18636
  if (this.wallet) {
18310
18637
  try {
@@ -18402,27 +18729,75 @@ var WalletMessageHandler = class {
18402
18729
  }
18403
18730
  }
18404
18731
  /**
18405
- * Refresh virtual outputs, boarding inputs, and transaction history from cache.
18406
- * Shared by onWalletInitialized (full bootstrap) and reloadWallet
18407
- * (post-refresh), avoiding duplicate subscriptions and VtxoManager restarts.
18732
+ * Refresh boarding inputs and transaction history. The virtual outputs come
18733
+ * from the contract manager, which runs before this. Shared by
18734
+ * onWalletInitialized (full bootstrap) and reloadWallet (post-refresh),
18735
+ * avoiding duplicate subscriptions and VtxoManager restarts.
18736
+ *
18737
+ * Both legs reach the onchain provider, so `lazyBoarding` moves them both
18738
+ * off the caller's path. @see RequestInitWallet.payload.lazyBoarding
18408
18739
  */
18409
- async refreshCachedData() {
18740
+ async refreshCachedData(opts) {
18410
18741
  if (!this.readonlyWallet || !this.walletRepository) {
18411
18742
  return;
18412
18743
  }
18413
- const boardingAddresses = await this.readonlyWallet.getBoardingAddresses();
18414
- const fresh = await this.readonlyWallet.getBoardingUtxos();
18415
- const freshKeys = new Set(fresh.map((u) => `${u.txid}:${u.vout}`));
18416
- for (const addr of boardingAddresses) {
18417
- const cached = await collectUtxos(this.walletRepository, addr);
18418
- const kept = cached.filter((u) => freshKeys.has(`${u.txid}:${u.vout}`));
18419
- if (kept.length === cached.length) continue;
18420
- await this.walletRepository.deleteUtxos(addr);
18421
- if (kept.length > 0) await this.walletRepository.saveUtxos(addr, kept);
18744
+ if (opts?.lazyBoarding) {
18745
+ const emitter = this.newEmitter("boarding");
18746
+ void (async () => {
18747
+ await this.refreshBoardingCache(emitter);
18748
+ if (emitter.stale) return;
18749
+ this.boardingLoaded = true;
18750
+ const coins = await this.readonlyWallet?.getStoredBoardingUtxos?.() ?? [];
18751
+ emitter.emit(
18752
+ this.tagged({
18753
+ type: "UTXO_UPDATE",
18754
+ broadcast: true,
18755
+ payload: { coins }
18756
+ })
18757
+ );
18758
+ await this.refreshHistoryCache(emitter);
18759
+ })().catch((error) => {
18760
+ console.warn("[wallet] background refresh failed", error);
18761
+ });
18762
+ return;
18422
18763
  }
18423
- const address = await this.readonlyWallet.getAddress();
18764
+ await this.refreshBoardingCache();
18765
+ this.boardingLoaded = true;
18766
+ await this.refreshHistoryCache();
18767
+ }
18768
+ /** @param gen - set by a background caller; each write is skipped once it goes stale. */
18769
+ async refreshHistoryCache(gen) {
18770
+ const wallet = this.readonlyWallet;
18771
+ const repository = this.walletRepository;
18772
+ if (!wallet || !repository) return;
18773
+ const address = await wallet.getAddress();
18424
18774
  const txs = await this.buildTransactionHistoryFromCache();
18425
- if (txs) await this.walletRepository.saveTransactions(address, txs);
18775
+ if (txs && !gen?.stale) await repository.saveTransactions(address, txs);
18776
+ }
18777
+ /**
18778
+ * @param gen - set by a background caller; each write here is skipped once it goes stale.
18779
+ * The fetch saves the fetched rows itself, before control returns, so that one write is
18780
+ * outside this check.
18781
+ */
18782
+ async refreshBoardingCache(gen) {
18783
+ const wallet = this.readonlyWallet;
18784
+ const repository = this.walletRepository;
18785
+ if (!wallet || !repository) return;
18786
+ const currentSigner = toXOnlySignerHex(
18787
+ hex.encode(wallet.boardingTapscript.options.serverPubKey)
18788
+ );
18789
+ const groups = await wallet.getBoardingUtxosForSigners(/* @__PURE__ */ new Set([currentSigner]));
18790
+ for (const { tapscript, coins } of groups) {
18791
+ if (gen?.stale) return;
18792
+ const address = tapscript.onchainAddress(wallet.network);
18793
+ const freshKeys = new Set(coins.map((coin) => `${coin.txid}:${coin.vout}`));
18794
+ const cached = await collectUtxos(repository, address);
18795
+ const kept = cached.filter((coin) => freshKeys.has(`${coin.txid}:${coin.vout}`));
18796
+ if (kept.length === cached.length) continue;
18797
+ if (gen?.stale) return;
18798
+ await repository.deleteUtxos(address);
18799
+ if (kept.length > 0) await repository.saveUtxos(address, kept);
18800
+ }
18426
18801
  }
18427
18802
  /**
18428
18803
  * Force a full VTXO refresh from the indexer, then refresh cached data.
@@ -18516,6 +18891,8 @@ var WalletMessageHandler = class {
18516
18891
  this.requestEpoch++;
18517
18892
  this.incomingFundsEpoch++;
18518
18893
  this.contractEventsEpoch++;
18894
+ this.boardingEpoch++;
18895
+ this.boardingLoaded = false;
18519
18896
  this.onNextTick = [];
18520
18897
  if (this.incomingFundsSubscription) {
18521
18898
  this.incomingFundsSubscription();
@@ -18719,6 +19096,8 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
18719
19096
  // are treated as long-running on both sides of the bus: the values below
18720
19097
  // are retained only for type completeness and are never enforced.
18721
19098
  SEND: 5e4,
19099
+ SEND_WITH_DEADLINE: 5e4,
19100
+ SEND_WITH_INPUT_EXPIRY_FLOOR: 5e4,
18722
19101
  SETTLE: 5e4,
18723
19102
  // Broadcast: the server round-trip a spend ends in, so it belongs
18724
19103
  // with the writes rather than the reads above.
@@ -18916,6 +19295,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
18916
19295
  const serializedWallet = await serializeReadonlyIdentity(options.identity);
18917
19296
  return _ServiceWorkerReadonlyWallet.bootstrap(wallet, options, serializedWallet, {
18918
19297
  delegateUrl: options.delegateUrl,
19298
+ lazyInitialization: options.lazyInitialization,
18919
19299
  watcherConfig: options.watcherConfig
18920
19300
  });
18921
19301
  }
@@ -18923,6 +19303,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
18923
19303
  static async bootstrap(wallet, options, serializedWallet, busConfig) {
18924
19304
  const arkServer = options.arkServer ?? { url: DEFAULT_ARKADE_SERVER_URL };
18925
19305
  const initWalletPayload = {
19306
+ lazyBoarding: options.lazyBoarding,
18926
19307
  arkServerUrl: arkServer.url,
18927
19308
  arkServerPublicKey: arkServer.publicKey
18928
19309
  };
@@ -19005,6 +19386,16 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
19005
19386
  if (request.id !== response.id) {
19006
19387
  return;
19007
19388
  }
19389
+ if (response.type === "SEND_DEADLINE_EXCEEDED") {
19390
+ if (event.source !== this.serviceWorker || response.tag !== request.tag) return;
19391
+ cleanup();
19392
+ if ((request.type === "SEND_WITH_DEADLINE" || request.type === "SEND_WITH_INPUT_EXPIRY_FLOOR") && response.error instanceof Error && (response.broadcast === void 0 || response.broadcast === false) && Number.isSafeInteger(response.payload?.validUntil) && response.payload.validUntil > 0 && response.payload.validUntil === request.payload.validUntil) {
19393
+ reject(new SendDeadlineExceededError(request.payload.validUntil));
19394
+ } else {
19395
+ reject(new Error("Invalid timed-send refusal response"));
19396
+ }
19397
+ return;
19398
+ }
19008
19399
  cleanup();
19009
19400
  if (response.error) {
19010
19401
  reject(restoreErrorName(response));
@@ -19747,8 +20138,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
19747
20138
  });
19748
20139
  }
19749
20140
  },
19750
- dispose() {
19751
- return;
20141
+ async dispose() {
19752
20142
  },
19753
20143
  [Symbol.dispose]() {
19754
20144
  return;
@@ -19808,6 +20198,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
19808
20198
  delegateUrl: options.delegateUrl,
19809
20199
  settlementConfig: options.settlementConfig,
19810
20200
  walletMode: options.walletMode,
20201
+ lazyInitialization: options.lazyInitialization,
19811
20202
  watcherConfig: options.watcherConfig,
19812
20203
  lookAheadWindow: options.lookAheadWindow,
19813
20204
  minBatchExpirySeconds: options.minBatchExpirySeconds,
@@ -20045,27 +20436,51 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
20045
20436
  }
20046
20437
  async send(...args) {
20047
20438
  const [first] = args;
20048
- const { recipients, selectedVtxos, maxChangeFee } = args.length === 1 && first && "recipients" in first ? first : {
20439
+ const {
20440
+ recipients,
20441
+ selectedVtxos,
20442
+ maxChangeFee,
20443
+ validUntil: wireDeadline,
20444
+ inputExpiryFloor: wireInputExpiryFloor
20445
+ } = args.length === 1 && first && "recipients" in first ? first : {
20049
20446
  recipients: args,
20050
20447
  selectedVtxos: void 0,
20051
- maxChangeFee: void 0
20448
+ maxChangeFee: void 0,
20449
+ validUntil: void 0,
20450
+ inputExpiryFloor: void 0
20052
20451
  };
20053
- const message = {
20452
+ const validUntil = captureSendDeadline(wireDeadline);
20453
+ const inputExpiryFloor = captureInputExpiryFloor(wireInputExpiryFloor);
20454
+ const options = {
20455
+ ...selectedVtxos ? { selectedVtxos } : {},
20456
+ ...maxChangeFee !== void 0 ? { maxChangeFee } : {}
20457
+ };
20458
+ const message = inputExpiryFloor !== void 0 ? {
20054
20459
  tag: this.messageTag,
20055
- type: "SEND",
20460
+ type: "SEND_WITH_INPUT_EXPIRY_FLOOR",
20056
20461
  id: getRandomId(),
20057
- // Omitted rather than sent as `undefined`, so an older worker sees
20058
- // exactly the payload it saw before.
20059
20462
  payload: {
20060
20463
  recipients,
20061
- ...selectedVtxos ? { selectedVtxos } : {},
20062
- ...maxChangeFee !== void 0 ? { maxChangeFee } : {}
20464
+ ...options,
20465
+ inputExpiryFloor,
20466
+ ...validUntil === void 0 ? {} : { validUntil }
20063
20467
  }
20468
+ } : validUntil === void 0 ? {
20469
+ tag: this.messageTag,
20470
+ type: "SEND",
20471
+ id: getRandomId(),
20472
+ payload: { recipients, ...options }
20473
+ } : {
20474
+ tag: this.messageTag,
20475
+ type: "SEND_WITH_DEADLINE",
20476
+ id: getRandomId(),
20477
+ payload: { recipients, ...options, validUntil }
20064
20478
  };
20065
20479
  try {
20066
20480
  const response = await this.sendMessage(message);
20067
20481
  return response.payload.txid;
20068
20482
  } catch (error) {
20483
+ if (error instanceof SendDeadlineExceededError) throw error;
20069
20484
  throw new Error(`Send failed: ${error}`);
20070
20485
  }
20071
20486
  }
@@ -23615,6 +24030,7 @@ var ArkadeTransactionBuilder = class {
23615
24030
  outputs = [];
23616
24031
  fundingCoins = [];
23617
24032
  assetSpecs = [];
24033
+ extraPackets = [];
23618
24034
  coin;
23619
24035
  changeScript;
23620
24036
  from(coin) {
@@ -23634,6 +24050,11 @@ var ArkadeTransactionBuilder = class {
23634
24050
  this.assetSpecs.push(spec);
23635
24051
  return this;
23636
24052
  }
24053
+ /** Add an extension packet; reusing the asset or emulator packet's type fails at build. */
24054
+ withPacket(packet) {
24055
+ this.extraPackets.push(packet);
24056
+ return this;
24057
+ }
23637
24058
  /** Destination for any surplus (inputs − outputs). Required when the spend is not exact. */
23638
24059
  change(script) {
23639
24060
  this.changeScript = script;
@@ -23725,6 +24146,7 @@ var ArkadeTransactionBuilder = class {
23725
24146
  ])
23726
24147
  );
23727
24148
  }
24149
+ packets.push(...this.extraPackets);
23728
24150
  if (packets.length > 0) {
23729
24151
  attachExtension(arkTx, packets);
23730
24152
  }
@@ -24320,6 +24742,6 @@ function createDefaultPaymentRouter(wallet) {
24320
24742
  }).use(arkRail()).use(arkAssetRail()).use(onchainRail({ feeInfo: walletFeeSource(wallet) }));
24321
24743
  }
24322
24744
 
24323
- export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_SECONDS, DEFAULT_MIN_CHECKPOINT_EXIT_DELAY_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, MUTINYNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SIGNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, Wallet2 as Wallet, WalletCannotAllocateAddressError, WalletCannotSignError, WalletMessageHandler, WalletNotInitializedError, WsElectrumChainSource, adoptContractDescriptor, arkAssetRail, arkRail, arkTarget, arkade_exports, assertFinalCommitmentMatchesValidated, assertHistoryPageFilter, assertIntentIdUnique, assertNoAssets, assertNoSelection, assertPageRequest, assertRecipientArkadeAddress, assertSendableAmount, assertSubmittedArkTxid, assertValidBatchExpiry, assertValidServerUnrollScript, assetMintResolver, assetsOf, attachPrevArkTxs, attachPrevoutTxs, awaitTransaction, boardingResolver, btcTarget, buildForfeitTx, buildOffchainTx, buildPreimageMessage, buildSaltedPreimageMessage, 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, defaultCheckpointExitDelayPolicy, 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, resolveCheckpointExitDelayPolicy, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
24324
- //# sourceMappingURL=chunk-EXFU6MTA.js.map
24325
- //# sourceMappingURL=chunk-EXFU6MTA.js.map
24745
+ export { ARKADE_MAGIC, ARKADE_SALTED_PREIMAGE_TAG, ARKADE_SWAP_PREIMAGE_TAG, ASSET_CARRIER_SATS, AbortError, ActivityRegistry, AmbiguousRouteError, ArkNote, ArkadeCash, ArkadeCashCreateError, AssetManager, BIP21, BIP21Error, BIP322, BLOCKED_UPGRADE_TIMEOUT_MS, Batch, CachingArkProvider, ChainedTxType, ConnectionDisposedError, ContractManager, ContractWatcher, DEFAULT_MESSAGE_TIMEOUTS, DEFAULT_MIN_BATCH_EXPIRY_SECONDS, DEFAULT_MIN_CHECKPOINT_EXIT_DELAY_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, MUTINYNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, OversizedChangeError, P2A, PaymentRouter, PrevTxUnavailableError, REGTEST_MIN_BATCH_EXPIRY_SECONDS, REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestEmulatorProvider, SIGNET_MIN_CHECKPOINT_EXIT_DELAY_SECONDS, SeedIdentity, SendDeadlineExceededError, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, StaticDescriptorProvider, TxTree, TxType, TxWeightEstimator, UnannotatableInputError, UnilateralExit, UnknownPacket, Unroll, VtxoManager, 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, defaultCheckpointExitDelayPolicy, 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, resolveCheckpointExitDelayPolicy, resolveDescriptorSigner, resolvePrevTxs, resolveSendAmount, saveVtxosForContract, scriptFromArkAddress, selectCoinsWithAsset, selectVirtualCoins, selectionOf, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signAndSubmitOffchainTx, signerSetFromInfo, signingDescriptorIndex, strictSigningDescriptorIndex, toXOnlySignerHex, tryResolveSendAmount, utxoEntries, validateBatchRecipients, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, walletFeeSource, warnAndFilterVtxosForScript, withPrevTxs };
24746
+ //# sourceMappingURL=chunk-ENGV6VZF.js.map
24747
+ //# sourceMappingURL=chunk-ENGV6VZF.js.map