@bsv/wallet-toolbox-client 2.8.0 → 2.10.0

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.
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { AuthFetch, BEEF_V1, BEEF_V2, Beef, BeefParty, BigNumber, BlockHeadersService, CachedKeyDeriver, Certificate, Curve, Hash, LocalKVStore, LockingScript, LookupResolver, MasterCertificate, MerklePath, P2PKH, PrivateKey, ProtoWallet, PublicKey, PushDrop, RPuzzle, Random, SHIPBroadcaster, Script, ScriptEvaluationError, Signature, Spend, SymmetricKey, Telemetry, Transaction, TransactionSignature, Utils, Validation, Validation as Validation$1, VerifiableCertificate, createNonce, defaultHttpClient, verifyNonce } from "@bsv/sdk";
2
+ import { AuthFetch, BEEF_V1, BEEF_V2, Beef, BeefParty, BeefTx, BigNumber, BlockHeadersService, CachedKeyDeriver, Certificate, Curve, Hash, LocalKVStore, LockingScript, LookupResolver, MasterCertificate, MerklePath, P2PKH, PrivateKey, ProtoWallet, PublicKey, PushDrop, RPuzzle, Random, SHIPBroadcaster, Script, ScriptEvaluationError, Signature, Spend, SymmetricKey, Telemetry, Transaction, TransactionSignature, Utils, Validation, Validation as Validation$1, VerifiableCertificate, createNonce, defaultHttpClient, verifyNonce } from "@bsv/sdk";
3
3
  import { deleteDB, openDB } from "idb";
4
4
  import { AESGCM, AESGCMDecrypt } from "@bsv/sdk/primitives/AESGCM";
5
5
  import argon2Api from "hash-wasm/dist/argon2.umd.min.js";
@@ -4046,7 +4046,7 @@ var EntitySyncState = class EntitySyncState extends EntityBase {
4046
4046
  log += formatSyncSection("OUTPUTS", c.outputs, (r) => `${r.outputId} ${r.txid}.${r.vout} ${r.transactionId} ${r.spendable ? "spendable" : ""} sats:${r.satoshis}`);
4047
4047
  return log;
4048
4048
  }
4049
- async processSyncChunk(writer, args, chunk) {
4049
+ async processSyncChunk(writer, args, chunk, trx) {
4050
4050
  const mes = [
4051
4051
  new MergeEntity(chunk.provenTxs, EntityProvenTx.mergeFind, this.syncMap.provenTx),
4052
4052
  new MergeEntity(chunk.outputBaskets, EntityOutputBasket.mergeFind, this.syncMap.outputBasket),
@@ -4067,16 +4067,16 @@ var EntitySyncState = class EntitySyncState extends EntityBase {
4067
4067
  let done = true;
4068
4068
  if (chunk.user != null) {
4069
4069
  const ei = chunk.user;
4070
- const { found, eo } = await EntityUser.mergeFind(writer, this.userId, ei);
4070
+ const { found, eo } = await EntityUser.mergeFind(writer, this.userId, ei, trx);
4071
4071
  if (found) {
4072
- if (await eo.mergeExisting(writer, args.since, ei)) {
4072
+ if (await eo.mergeExisting(writer, args.since, ei, void 0, trx)) {
4073
4073
  maxUpdated_at = maxDate(maxUpdated_at, ei.updated_at);
4074
4074
  updates++;
4075
4075
  }
4076
4076
  }
4077
4077
  }
4078
4078
  for (const me of mes) {
4079
- const r = await me.merge(args.since, writer, this.userId, this.syncMap);
4079
+ const r = await me.merge(args.since, writer, this.userId, this.syncMap, trx);
4080
4080
  me.esm.count += me.stateArray?.length || 0;
4081
4081
  updates += r.updates;
4082
4082
  inserts += r.inserts;
@@ -4087,7 +4087,7 @@ var EntitySyncState = class EntitySyncState extends EntityBase {
4087
4087
  this.when = maxUpdated_at;
4088
4088
  for (const me of mes) me.esm.count = 0;
4089
4089
  }
4090
- await this.updateStorage(writer, false);
4090
+ await this.updateStorage(writer, false, trx);
4091
4091
  return {
4092
4092
  done,
4093
4093
  maxUpdated_at,
@@ -8219,28 +8219,70 @@ function verifyActionBatchManifestDigest(manifest) {
8219
8219
  //#endregion
8220
8220
  //#region ../src/utility/beefForTxids.ts
8221
8221
  /**
8222
- * Return the minimal subgraph needed to prove the requested transactions.
8222
+ * Return a minimal BEEF when the source contains data outside the requested
8223
+ * transaction dependency closure. Return undefined when no pruning is needed.
8223
8224
  *
8224
- * Parents are added before children so the resulting BEEF preserves dependency
8225
- * order. Shared ancestors and bumps are merged only once.
8225
+ * This form lets forwarding clients retain the caller's original bytes in the
8226
+ * common no-op case instead of rebuilding and reserializing an equivalent BEEF.
8227
+ */
8228
+ function pruneBeefForTxids(source, txids) {
8229
+ const selection = selectTransactions(source, txids);
8230
+ if (selection.transactions.size === source.txs.length && selection.bumpIndexes.size === source.bumps.length) return;
8231
+ return copySelection(source, selection);
8232
+ }
8233
+ /**
8234
+ * Return an independent minimal BEEF needed to prove the requested transactions.
8235
+ *
8236
+ * Transactions remain in source order and are sorted by Beef when serialized.
8237
+ * The source is indexed and walked once, using an explicit stack so a hostile
8238
+ * dependency depth cannot exhaust the JavaScript call stack.
8226
8239
  */
8227
8240
  function beefForTxids(source, txids) {
8228
- const beef = new Beef();
8241
+ return copySelection(source, selectTransactions(source, txids));
8242
+ }
8243
+ function selectTransactions(source, txids) {
8244
+ const byTxid = /* @__PURE__ */ new Map();
8245
+ for (const tx of source.txs) byTxid.set(tx.txid, tx);
8246
+ const transactions = /* @__PURE__ */ new Set();
8247
+ const bumpIndexes = /* @__PURE__ */ new Set();
8229
8248
  const visited = /* @__PURE__ */ new Set();
8230
- const visit = (txid) => {
8231
- if (visited.has(txid)) return;
8249
+ const stack = [...txids];
8250
+ while (stack.length > 0) {
8251
+ const txid = stack.pop();
8252
+ if (txid == null || visited.has(txid)) continue;
8232
8253
  visited.add(txid);
8233
- const sourceTx = source.findTxid(txid);
8234
- if (sourceTx == null) return;
8235
- if (sourceTx.tx != null) {
8236
- for (const input of sourceTx.tx.inputs) if (input.sourceTXID != null) visit(input.sourceTXID);
8237
- }
8238
- if (sourceTx.bumpIndex != null) beef.mergeBump(source.bumps[sourceTx.bumpIndex]);
8239
- beef.mergeBeefTx(sourceTx);
8254
+ const tx = byTxid.get(txid);
8255
+ if (tx == null) continue;
8256
+ transactions.add(tx);
8257
+ const bumpIndex = tx.bumpIndex;
8258
+ if (bumpIndex != null && Number.isSafeInteger(bumpIndex) && bumpIndex >= 0 && bumpIndex < source.bumps.length) bumpIndexes.add(bumpIndex);
8259
+ for (const inputTxid of tx.inputTxids) if (!visited.has(inputTxid)) stack.push(inputTxid);
8260
+ }
8261
+ return {
8262
+ transactions,
8263
+ bumpIndexes
8240
8264
  };
8241
- for (const txid of txids) visit(txid);
8265
+ }
8266
+ function copySelection(source, selection) {
8267
+ const beef = new Beef(source.version);
8268
+ const bumpIndexMap = /* @__PURE__ */ new Map();
8269
+ for (let index = 0; index < source.bumps.length; index++) {
8270
+ if (!selection.bumpIndexes.has(index)) continue;
8271
+ bumpIndexMap.set(index, beef.bumps.length);
8272
+ beef.bumps.push(cloneMerklePath(source.bumps[index]));
8273
+ }
8274
+ for (const sourceTx of source.txs) {
8275
+ if (!selection.transactions.has(sourceTx)) continue;
8276
+ const bumpIndex = sourceTx.bumpIndex == null ? void 0 : bumpIndexMap.get(sourceTx.bumpIndex);
8277
+ const rawTx = sourceTx.rawTxUint8Array;
8278
+ const copy = rawTx == null ? BeefTx.fromTxid(sourceTx.txid, bumpIndex) : new BeefTx(Uint8Array.from(rawTx), bumpIndex, Array.from(sourceTx.inputTxids));
8279
+ beef.txs.push(copy);
8280
+ }
8242
8281
  return beef;
8243
8282
  }
8283
+ function cloneMerklePath(source) {
8284
+ return new MerklePath(source.blockHeight, source.path.map((level) => level.map((leaf) => ({ ...leaf }))), false, false);
8285
+ }
8244
8286
  //#endregion
8245
8287
  //#region ../src/storage/methods/offsetKey.ts
8246
8288
  function keyOffsetToHashedSecret(pub, keyOffset) {
@@ -10938,7 +10980,7 @@ function validateRequiredOutputs(storage, userId, vargs) {
10938
10980
  * @returns {xinputs} extended validated required inputs.
10939
10981
  */
10940
10982
  async function validateRequiredInputs(storage, userId, vargs) {
10941
- const beef = new Beef();
10983
+ let beef = new Beef();
10942
10984
  if (vargs.inputs.length === 0) return {
10943
10985
  storageBeef: beef,
10944
10986
  beef,
@@ -10964,6 +11006,7 @@ async function validateRequiredInputs(storage, userId, vargs) {
10964
11006
  inputsByTxid[input.outpoint.txid] ||= [];
10965
11007
  inputsByTxid[input.outpoint.txid].push(input);
10966
11008
  }
11009
+ beef = beefForTxids(beef, Object.keys(inputsByTxid));
10967
11010
  const localKnownInputTxids = {};
10968
11011
  for (const [txid, txInputs] of Object.entries(inputsByTxid)) localKnownInputTxids[txid] = txInputs.every((input) => {
10969
11012
  const output = preloadedOutputsByOutpoint[`${input.outpoint.txid}.${input.outpoint.vout}`];
@@ -15225,11 +15268,19 @@ var StorageProvider = class StorageProvider extends StorageReaderWriter {
15225
15268
  return await this.updateOutput(output.outputId, { basketId: void 0 });
15226
15269
  }
15227
15270
  async processSyncChunk(args, chunk) {
15228
- const user = verifyTruthy(await this.findUserByIdentityKey(args.identityKey));
15229
- return await new EntitySyncState(verifyOne(await this.findSyncStates({ partial: {
15230
- storageIdentityKey: args.fromStorageIdentityKey,
15231
- userId: user.userId
15232
- } }))).processSyncChunk(this, args, chunk);
15271
+ return await this.transaction(async (trx) => {
15272
+ const user = verifyTruthy(verifyOneOrNone(await this.findUsers({
15273
+ partial: { identityKey: args.identityKey },
15274
+ trx
15275
+ })));
15276
+ return await new EntitySyncState(verifyOne(await this.findSyncStates({
15277
+ partial: {
15278
+ storageIdentityKey: args.fromStorageIdentityKey,
15279
+ userId: user.userId
15280
+ },
15281
+ trx
15282
+ }))).processSyncChunk(this, args, chunk, trx);
15283
+ });
15233
15284
  }
15234
15285
  /**
15235
15286
  * Handles storage changes when a valid MerklePath and mined block header are found for a ProvenTxReq txid.
@@ -17294,8 +17345,10 @@ var StorageIdb = class extends StorageProvider {
17294
17345
  await tx.done;
17295
17346
  return r;
17296
17347
  } catch (err) {
17297
- tx.abort();
17298
- await tx.done;
17348
+ try {
17349
+ tx.abort();
17350
+ await tx.done;
17351
+ } catch {}
17299
17352
  throw err;
17300
17353
  }
17301
17354
  }
@@ -18262,6 +18315,25 @@ var StorageClientBase = class {
18262
18315
  * @returns `StorageCreateActionResults` supporting additional wallet processing to yield `createAction` results.
18263
18316
  */
18264
18317
  async createAction(auth, args) {
18318
+ if (args.inputBEEF != null) if (args.inputs.length === 0) args = {
18319
+ ...args,
18320
+ inputBEEF: void 0
18321
+ };
18322
+ else {
18323
+ let source;
18324
+ try {
18325
+ source = Beef.fromBinary(args.inputBEEF);
18326
+ } catch {
18327
+ source = void 0;
18328
+ }
18329
+ if (source != null) {
18330
+ const pruned = pruneBeefForTxids(source, args.inputs.map((input) => input.outpoint.txid));
18331
+ if (pruned != null) args = {
18332
+ ...args,
18333
+ inputBEEF: pruned.toBinary()
18334
+ };
18335
+ }
18336
+ }
18265
18337
  return await this.rpcCall("createAction", [auth, args]);
18266
18338
  }
18267
18339
  /**
@@ -19562,6 +19634,24 @@ function isLiveBlockHeader(header) {
19562
19634
  return "chainWork" in header && typeof header.previousHash === "string";
19563
19635
  }
19564
19636
  //#endregion
19637
+ //#region ../src/services/chaintracker/chaintracks/Api/BulkFileDataValidatorApi.ts
19638
+ /**
19639
+ * Identifies deterministic rejection of the supplied immutable bytes.
19640
+ * Operational failures such as worker crashes and queue saturation deliberately
19641
+ * use ordinary errors so callers preserve the cache entry and avoid downloading
19642
+ * a replacement that cannot be validated.
19643
+ *
19644
+ * @public
19645
+ */
19646
+ var BulkFileDataValidationError = class extends Error {
19647
+ data;
19648
+ constructor(message, data) {
19649
+ super(message);
19650
+ this.data = data;
19651
+ this.name = "BulkFileDataValidationError";
19652
+ }
19653
+ };
19654
+ //#endregion
19565
19655
  //#region ../src/services/chaintracker/chaintracks/util/HeightRange.ts
19566
19656
  /**
19567
19657
  * Represents a range of block heights.
@@ -19780,6 +19870,8 @@ var Chaintracks = class {
19780
19870
  lastPresentHeight = -1;
19781
19871
  lastPresentHeightMsecs = 0;
19782
19872
  lastPresentHeightMaxAge = 60 * 1e3;
19873
+ presentHeightRefresh;
19874
+ mainLoopHeartbeatMsecs = 0;
19783
19875
  lock = new SingleWriterMultiReaderLock();
19784
19876
  sourceStatus = /* @__PURE__ */ new Map();
19785
19877
  constructor(options) {
@@ -19817,12 +19909,31 @@ var Chaintracks = class {
19817
19909
  return this.chain;
19818
19910
  }
19819
19911
  /**
19820
- * Caches and returns most recently sourced value if less than one minute old.
19821
- * @returns the current externally available chain height (via bulk ingestors).
19912
+ * Returns the last known valid height immediately and refreshes stale state
19913
+ * once in the background. Cold start waits for the single shared refresh.
19822
19914
  */
19823
19915
  async getPresentHeight() {
19824
19916
  const now = Date.now();
19825
19917
  if (this.lastPresentHeight >= 0 && now - this.lastPresentHeightMsecs < this.lastPresentHeightMaxAge) return this.lastPresentHeight;
19918
+ if (this.lastPresentHeight >= 0) {
19919
+ this.refreshPresentHeight().catch((error) => {
19920
+ this.log(`Background present-height refresh failed: ${WalletError.fromUnknown(error).message}`);
19921
+ });
19922
+ return this.lastPresentHeight;
19923
+ }
19924
+ return await this.refreshPresentHeight();
19925
+ }
19926
+ async refreshPresentHeight() {
19927
+ if (this.presentHeightRefresh != null) return await this.presentHeightRefresh;
19928
+ const refresh = this.loadPresentHeight();
19929
+ this.presentHeightRefresh = refresh;
19930
+ try {
19931
+ return await refresh;
19932
+ } finally {
19933
+ if (this.presentHeightRefresh === refresh) this.presentHeightRefresh = void 0;
19934
+ }
19935
+ }
19936
+ async loadPresentHeight() {
19826
19937
  for (const [index, bulk] of this.bulkIngestors.entries()) {
19827
19938
  const source = this.sourceName("bulk", index, bulk);
19828
19939
  try {
@@ -19830,7 +19941,7 @@ var Chaintracks = class {
19830
19941
  if (presentHeight != null && Number.isInteger(presentHeight) && presentHeight >= 0) {
19831
19942
  this.markSourceSuccess(source, "bulk");
19832
19943
  this.lastPresentHeight = presentHeight;
19833
- this.lastPresentHeightMsecs = now;
19944
+ this.lastPresentHeightMsecs = Date.now();
19834
19945
  return presentHeight;
19835
19946
  }
19836
19947
  } catch (uerr) {
@@ -19845,7 +19956,7 @@ var Chaintracks = class {
19845
19956
  const localHeight = Math.max(ranges.bulk.maxHeight, ranges.live.maxHeight);
19846
19957
  if (localHeight >= 0) {
19847
19958
  this.lastPresentHeight = localHeight;
19848
- this.lastPresentHeightMsecs = now;
19959
+ this.lastPresentHeightMsecs = Date.now();
19849
19960
  return localHeight;
19850
19961
  }
19851
19962
  } catch (error) {
@@ -19856,6 +19967,19 @@ var Chaintracks = class {
19856
19967
  async currentHeight() {
19857
19968
  return await this.getPresentHeight();
19858
19969
  }
19970
+ /** Returns local process state without locks, storage reads, or network I/O. */
19971
+ getAvailabilitySnapshot() {
19972
+ return {
19973
+ available: this.available,
19974
+ startupError: this.startupError?.message,
19975
+ presentHeight: this.lastPresentHeight >= 0 ? this.lastPresentHeight : void 0,
19976
+ presentHeightUpdatedAt: this.lastPresentHeightMsecs > 0 ? new Date(this.lastPresentHeightMsecs).toISOString() : void 0,
19977
+ presentHeightRefreshInFlight: this.presentHeightRefresh != null,
19978
+ mainLoopHeartbeatAt: this.mainLoopHeartbeatMsecs > 0 ? new Date(this.mainLoopHeartbeatMsecs).toISOString() : void 0,
19979
+ sources: Array.from(this.sourceStatus.values()).map((status) => ({ ...status })),
19980
+ bulkData: this.storage.bulkManager.getStats()
19981
+ };
19982
+ }
19859
19983
  async subscribeHeaders(listener) {
19860
19984
  const ID = randomBytesBase64(8);
19861
19985
  this.callbacks.header[ID] = listener;
@@ -19920,6 +20044,7 @@ var Chaintracks = class {
19920
20044
  for (const liveIn of this.liveIngestors) await liveIn.shutdown();
19921
20045
  for (const bulkIn of this.bulkIngestors) await bulkIn.shutdown();
19922
20046
  await Promise.all(this.promises);
20047
+ await this.storage.bulkManager.destroy();
19923
20048
  await this.storage.destroy();
19924
20049
  this.available = false;
19925
20050
  this.stopMainThread = false;
@@ -20201,9 +20326,11 @@ var Chaintracks = class {
20201
20326
  const syncCheckRepeatMsecs = 1800 * 1e3;
20202
20327
  while (!this.stopMainThread) try {
20203
20328
  const now = Date.now();
20329
+ this.mainLoopHeartbeatMsecs = now;
20204
20330
  lastSyncCheck = now;
20205
20331
  lastBulkSync = await this.runBulkSyncIfNeeded(now, lastBulkSync, cdnSyncRepeatMsecs);
20206
20332
  await this.processLiveHeaderQueue(lastSyncCheck, syncCheckRepeatMsecs);
20333
+ this.mainLoopHeartbeatMsecs = Date.now();
20207
20334
  } catch (error_) {
20208
20335
  const e = WalletError.fromUnknown(error_);
20209
20336
  if (this.available) this.log(`Error occurred during chaintracks main thread processing: ${e.stack || e.message}`);
@@ -20215,7 +20342,7 @@ var Chaintracks = class {
20215
20342
  }
20216
20343
  /** Returns (potentially updated) lastBulkSync timestamp. */
20217
20344
  async runBulkSyncIfNeeded(now, lastBulkSync, cdnSyncRepeatMsecs) {
20218
- const presentHeight = await this.getPresentHeight();
20345
+ const presentHeight = await this.refreshPresentHeight();
20219
20346
  const before = await this.storage.getAvailableHeightRanges();
20220
20347
  let skipBulkSync = !before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2;
20221
20348
  if (skipBulkSync && now - lastBulkSync > cdnSyncRepeatMsecs) skipBulkSync = false;
@@ -21364,12 +21491,12 @@ var ChaintracksFetch = class {
21364
21491
  this.maxRetryMsecs = positiveSafeInteger(options.maxRetryMsecs, DEFAULT_MAX_RETRY_MSECS, "maxRetryMsecs");
21365
21492
  this.random = options.random ?? Math.random;
21366
21493
  }
21367
- async download(url, maxResponseBytes) {
21494
+ async download(url, maxResponseBytes, options) {
21368
21495
  const responseLimit = maxResponseBytes == null ? this.maxResponseBytes : Math.min(this.maxResponseBytes, positiveSafeInteger(maxResponseBytes, this.maxResponseBytes, "maxResponseBytes"));
21369
21496
  return await this.requestBytes(url, {
21370
21497
  method: "GET",
21371
21498
  headers: { Accept: "application/octet-stream" }
21372
- }, "download", responseLimit);
21499
+ }, "download", responseLimit, options);
21373
21500
  }
21374
21501
  async fetchJson(url) {
21375
21502
  const bytes = await this.requestBytes(url, {
@@ -21378,8 +21505,9 @@ var ChaintracksFetch = class {
21378
21505
  }, "fetch JSON", this.maxResponseBytes);
21379
21506
  return JSON.parse(new TextDecoder().decode(bytes));
21380
21507
  }
21381
- async requestBytes(url, init, kind, maxResponseBytes) {
21508
+ async requestBytes(url, init, kind, maxResponseBytes, downloadOptions) {
21382
21509
  for (let retry = 0;; retry++) {
21510
+ if (retry > 0) await downloadOptions?.beforeRetry?.(retry + 1);
21383
21511
  const controller = new AbortController();
21384
21512
  const timeout = setTimeout(() => controller.abort(), this.timeoutMsecs);
21385
21513
  try {
@@ -21455,6 +21583,38 @@ var ChaintracksFetch = class {
21455
21583
  }
21456
21584
  };
21457
21585
  //#endregion
21586
+ //#region ../src/services/chaintracker/chaintracks/util/InlineBulkFileDataValidator.ts
21587
+ /**
21588
+ * Portable complete-object validator. Node services should normally inject
21589
+ * `NodeBulkFileDataValidator`; browser and mobile consumers retain this
21590
+ * dependency-free fallback.
21591
+ *
21592
+ * @public
21593
+ */
21594
+ var InlineBulkFileDataValidator = class {
21595
+ async validate(request) {
21596
+ try {
21597
+ const expectedLength = request.count * 80;
21598
+ if (request.data.length !== expectedLength) throw new WERR_INVALID_PARAMETER("file.data", `bulk file ${request.fileName} data length ${request.data.length} does not match expected count ${request.count}`);
21599
+ const fileHash = asString(Hash.sha256(asArray(request.data)), "base64");
21600
+ if (request.fileHash != null && fileHash !== request.fileHash) throw new WERR_INVALID_PARAMETER("fileHash", `a match for retrieved data for ${request.fileName}`);
21601
+ const { lastHeaderHash, lastChainWork } = validateBufferOfHeaders(request.data, request.prevHash, 0, request.count, request.prevChainWork);
21602
+ if (request.lastHash && request.lastHash !== lastHeaderHash) throw new WERR_INVALID_PARAMETER("file.lastHash", `expected ${request.lastHash} but got ${lastHeaderHash}`);
21603
+ if (request.lastChainWork && request.lastChainWork !== lastChainWork) throw new WERR_INVALID_PARAMETER("file.lastChainWork", `expected ${request.lastChainWork} but got ${lastChainWork}`);
21604
+ if (request.firstHeight === 0 && request.chain != null) validateGenesisHeader(request.data, request.chain);
21605
+ return {
21606
+ data: request.data,
21607
+ fileHash,
21608
+ lastHeaderHash,
21609
+ lastChainWork
21610
+ };
21611
+ } catch (error) {
21612
+ if (error instanceof BulkFileDataValidationError) throw error;
21613
+ throw new BulkFileDataValidationError(error instanceof Error ? error.message : String(error), request.data);
21614
+ }
21615
+ }
21616
+ };
21617
+ //#endregion
21458
21618
  //#region ../src/services/chaintracker/chaintracks/util/BulkFileDataManager.ts
21459
21619
  /**
21460
21620
  * Manages bulk file data (typically 8MB chunks of 100,000 headers each).
@@ -21480,6 +21640,7 @@ var BulkFileDataManager = class BulkFileDataManager {
21480
21640
  fileHashToIndex = {};
21481
21641
  lock = new SingleWriterMultiReaderLock();
21482
21642
  inFlightLoads = /* @__PURE__ */ new Map();
21643
+ failedLoads = /* @__PURE__ */ new Map();
21483
21644
  storage;
21484
21645
  stats = {
21485
21646
  memoryHits: 0,
@@ -21489,7 +21650,8 @@ var BulkFileDataManager = class BulkFileDataManager {
21489
21650
  persistentCacheRejects: 0,
21490
21651
  coalescedLoads: 0,
21491
21652
  downloads: 0,
21492
- downloadedBytes: 0
21653
+ downloadedBytes: 0,
21654
+ loadBackoffs: 0
21493
21655
  };
21494
21656
  chain;
21495
21657
  maxPerFile;
@@ -21498,6 +21660,8 @@ var BulkFileDataManager = class BulkFileDataManager {
21498
21660
  fromKnownSourceUrl;
21499
21661
  cache;
21500
21662
  downloadBudget;
21663
+ validator;
21664
+ failedLoadRetryMsecs;
21501
21665
  constructor(options) {
21502
21666
  const resolvedOptions = typeof options === "object" ? options : BulkFileDataManager.createDefaultOptions(options);
21503
21667
  this.chain = resolvedOptions.chain;
@@ -21507,10 +21671,17 @@ var BulkFileDataManager = class BulkFileDataManager {
21507
21671
  this.fetch = resolvedOptions.fetch;
21508
21672
  this.cache = resolvedOptions.cache;
21509
21673
  this.downloadBudget = resolvedOptions.downloadBudget;
21674
+ this.validator = resolvedOptions.validator ?? new InlineBulkFileDataValidator();
21675
+ this.failedLoadRetryMsecs = resolvedOptions.failedLoadRetryMsecs ?? 30 * 1e3;
21676
+ if (!Number.isSafeInteger(this.failedLoadRetryMsecs) || this.failedLoadRetryMsecs < 0) throw new WERR_INVALID_PARAMETER("failedLoadRetryMsecs", "a non-negative safe integer");
21510
21677
  this.deleteBulkFilesNoLock();
21511
21678
  }
21512
21679
  getStats() {
21513
- return { ...this.stats };
21680
+ return {
21681
+ ...this.stats,
21682
+ validation: this.validator.getStats?.(),
21683
+ downloadBudget: this.downloadBudget?.snapshot?.()
21684
+ };
21514
21685
  }
21515
21686
  async deleteBulkFiles() {
21516
21687
  return await this.lock.withWriteLock(async () => this.deleteBulkFilesNoLock());
@@ -21729,9 +21900,29 @@ var BulkFileDataManager = class BulkFileDataManager {
21729
21900
  });
21730
21901
  }
21731
21902
  async getDataFromFile(file, offset, length) {
21732
- const bfd = this.getBfdForHeight(file.firstHeight);
21733
- if (bfd == null || bfd.count < file.count) throw new WERR_INVALID_PARAMETER("file", `a match for ${file.firstHeight}, ${file.count} in the BulkFileDataManager.`);
21734
- return await this.lock.withReadLock(async () => await this.getDataFromFileNoLock(bfd, offset, length));
21903
+ const resolved = await this.lock.withReadLock(async () => {
21904
+ const resolved = this.getBfdForHeight(file.firstHeight);
21905
+ if (resolved == null || resolved.count < file.count) throw new WERR_INVALID_PARAMETER("file", `a match for ${file.firstHeight}, ${file.count} in the BulkFileDataManager.`);
21906
+ return {
21907
+ current: resolved,
21908
+ snapshot: snapshotBfd(resolved)
21909
+ };
21910
+ });
21911
+ return await this.getDataFromSnapshot(resolved.current, resolved.snapshot, offset, length);
21912
+ }
21913
+ async getDataFromSnapshot(original, snapshot, offset, length) {
21914
+ const data = await this.getDataFromFileNoLock(snapshot, offset, length);
21915
+ if (snapshot.data != null) await this.lock.withWriteLock(async () => {
21916
+ if (this.bfds.includes(original) && original.fileHash === snapshot.fileHash && original.firstHeight === snapshot.firstHeight && original.count === snapshot.count) {
21917
+ original.data = snapshot.data;
21918
+ original.validated = true;
21919
+ original.lastHash = snapshot.lastHash;
21920
+ original.lastChainWork = snapshot.lastChainWork;
21921
+ original.mru = Date.now();
21922
+ this.ensureMaxRetained();
21923
+ }
21924
+ });
21925
+ return data;
21735
21926
  }
21736
21927
  async getDataFromFileNoLock(bfd, offset, length) {
21737
21928
  const fileLength = bfd.count * 80;
@@ -21742,15 +21933,19 @@ var BulkFileDataManager = class BulkFileDataManager {
21742
21933
  return (await this.ensureData(bfd)).slice(offset, offset + length);
21743
21934
  }
21744
21935
  async findHeaderForHeightOrUndefined(height) {
21745
- return await this.lock.withReadLock(async () => {
21936
+ const resolved = await this.lock.withReadLock(async () => {
21746
21937
  if (!Number.isInteger(height) || height < 0) throw new WERR_INVALID_PARAMETER("height", `a non-negative integer (${height}).`);
21747
21938
  const file = this.bfds.find((f) => f.firstHeight <= height && f.firstHeight + f.count > height);
21748
21939
  if (file == null) return void 0;
21749
- const offset = (height - file.firstHeight) * 80;
21750
- const data = await this.getDataFromFileNoLock(file, offset, 80);
21751
- if (data == null) return void 0;
21752
- return deserializeBlockHeader(data, height, 0);
21940
+ return {
21941
+ current: file,
21942
+ snapshot: snapshotBfd(file),
21943
+ offset: (height - file.firstHeight) * 80
21944
+ };
21753
21945
  });
21946
+ if (resolved == null) return void 0;
21947
+ const data = await this.getDataFromSnapshot(resolved.current, resolved.snapshot, resolved.offset, 80);
21948
+ return data == null ? void 0 : deserializeBlockHeader(data, height, 0);
21754
21949
  }
21755
21950
  async getFileForHeight(height) {
21756
21951
  return await this.lock.withReadLock(async () => {
@@ -21805,22 +22000,30 @@ var BulkFileDataManager = class BulkFileDataManager {
21805
22000
  return bfd;
21806
22001
  }
21807
22002
  async validateBfdData(bfd, expectedFileHash) {
21808
- await this.ensureData(bfd);
21809
- if (bfd.data?.length !== bfd.count * 80) throw new WERR_INVALID_PARAMETER("file.data", `bulk file ${bfd.fileName} data length ${bfd.data?.length} does not match expected count ${bfd.count}`);
21810
- bfd.fileHash = asString(Hash.sha256(asArray(bfd.data)), "base64");
21811
- if (expectedFileHash && expectedFileHash !== bfd.fileHash) throw new WERR_INVALID_PARAMETER("file.fileHash", `expected ${expectedFileHash} but got ${bfd.fileHash}`);
21812
- this.validateBfdHeaders(bfd);
22003
+ const data = await this.ensureData(bfd);
22004
+ bfd.data = await this.validateRetrievedData(bfd, data, expectedFileHash);
21813
22005
  }
21814
- validateBfdHeaders(bfd) {
22006
+ async validateBfdHeaders(bfd, expectedFileHash = bfd.fileHash) {
21815
22007
  const pbf = bfd.firstHeight > 0 ? this.getBfdForHeight(bfd.firstHeight - 1) : void 0;
21816
22008
  const prevHash = pbf?.lastHash ?? "00".repeat(32);
21817
22009
  const prevChainWork = pbf?.lastChainWork ?? "00".repeat(32);
21818
- const { lastHeaderHash, lastChainWork } = validateBufferOfHeaders(bfd.data, prevHash, 0, void 0, prevChainWork);
21819
- if (bfd.lastHash && bfd.lastHash !== lastHeaderHash) throw new WERR_INVALID_PARAMETER("file.lastHash", `expected ${bfd.lastHash} but got ${lastHeaderHash}`);
21820
- if (bfd.lastChainWork && bfd.lastChainWork !== lastChainWork) throw new WERR_INVALID_PARAMETER("file.lastChainWork", `expected ${bfd.lastChainWork} but got ${lastChainWork}`);
21821
- bfd.lastHash = lastHeaderHash;
21822
- bfd.lastChainWork = lastChainWork;
21823
- if (bfd.firstHeight === 0) validateGenesisHeader(bfd.data, bfd.chain);
22010
+ const result = await this.validator.validate({
22011
+ fileName: bfd.fileName,
22012
+ data: bfd.data,
22013
+ count: bfd.count,
22014
+ fileHash: expectedFileHash,
22015
+ firstHeight: bfd.firstHeight,
22016
+ prevHash,
22017
+ prevChainWork,
22018
+ lastHash: bfd.lastHash,
22019
+ lastChainWork: bfd.lastChainWork,
22020
+ chain: bfd.chain
22021
+ });
22022
+ bfd.data = result.data;
22023
+ bfd.fileHash = result.fileHash;
22024
+ bfd.lastHash = result.lastHeaderHash;
22025
+ bfd.lastChainWork = result.lastChainWork;
22026
+ return result.data;
21824
22027
  }
21825
22028
  async ReValidate() {
21826
22029
  return await this.lock.withReadLock(async () => await this.ReValidateNoLock());
@@ -22011,62 +22214,96 @@ var BulkFileDataManager = class BulkFileDataManager {
22011
22214
  this.ensureMaxRetained();
22012
22215
  return data;
22013
22216
  }
22217
+ const failed = this.failedLoads.get(key);
22218
+ if (failed != null) {
22219
+ if (Date.now() < failed.retryAt) {
22220
+ this.stats.loadBackoffs++;
22221
+ throw failed.error;
22222
+ }
22223
+ this.failedLoads.delete(key);
22224
+ }
22014
22225
  const load = this.loadAndValidateData(bfd);
22015
22226
  this.inFlightLoads.set(key, load);
22016
22227
  try {
22017
22228
  const data = await load;
22018
22229
  bfd.data = data;
22019
22230
  bfd.validated = true;
22231
+ this.failedLoads.delete(key);
22020
22232
  bfd.mru = Date.now();
22021
22233
  this.ensureMaxRetained();
22022
22234
  return data;
22235
+ } catch (error) {
22236
+ const resolved = error instanceof Error ? error : new Error(String(error));
22237
+ this.failedLoads.set(key, {
22238
+ retryAt: Date.now() + this.failedLoadRetryMsecs,
22239
+ error: resolved
22240
+ });
22241
+ throw resolved;
22023
22242
  } finally {
22024
22243
  if (this.inFlightLoads.get(key) === load) this.inFlightLoads.delete(key);
22025
22244
  }
22026
22245
  }
22027
22246
  async loadAndValidateData(bfd) {
22028
- if (this.storage != null && bfd.fileId) {
22029
- const stored = await this.storage.getBulkFileData(bfd.fileId);
22030
- if (stored == null) throw new WERR_INVALID_PARAMETER("fileId", `valid, data not found for fileId ${bfd.fileId}`);
22031
- this.validateRetrievedData(bfd, stored);
22032
- this.stats.storageHits++;
22033
- return stored;
22034
- }
22035
- if (this.cache != null) {
22036
- const cached = await this.cache.get(bfd);
22037
- if (cached != null) try {
22038
- this.validateRetrievedData(bfd, cached);
22039
- this.stats.persistentCacheHits++;
22040
- return cached;
22041
- } catch (error) {
22042
- this.stats.persistentCacheRejects++;
22043
- await this.cache.delete?.(bfd);
22044
- this.log(`Rejected corrupt bulk-header cache entry ${bfd.fileName}: ${String(error)}`);
22045
- }
22046
- else this.stats.persistentCacheMisses++;
22047
- }
22048
- if (this.fetch != null && bfd.sourceUrl) {
22049
- const expectedBytes = bfd.count * 80;
22050
- await this.downloadBudget?.consume(expectedBytes);
22051
- const url = this.fetch.pathJoin(bfd.sourceUrl, bfd.fileName);
22052
- const downloaded = await this.fetch.download(url, expectedBytes);
22053
- if (downloaded == null) throw new WERR_INVALID_PARAMETER("sourceUrl", `data not found for sourceUrl ${url}`);
22054
- this.validateRetrievedData(bfd, downloaded);
22055
- this.stats.downloads++;
22056
- this.stats.downloadedBytes += downloaded.length;
22057
- await this.cache?.set(bfd, downloaded);
22058
- return downloaded;
22059
- }
22247
+ const stored = await this.loadFromStorage(bfd);
22248
+ if (stored != null) return stored;
22249
+ const cached = await this.loadFromCache(bfd);
22250
+ if (cached != null) return cached;
22251
+ const downloaded = await this.loadFromRemote(bfd);
22252
+ if (downloaded != null) return downloaded;
22060
22253
  throw new WERR_INVALID_PARAMETER("data", `defined. Unable to retrieve data for ${bfd.fileName}`);
22061
22254
  }
22062
- validateRetrievedData(bfd, data) {
22063
- if (data.length !== bfd.count * 80) throw new WERR_INVALID_PARAMETER("file.data", `bulk file ${bfd.fileName} data length ${data.length} does not match expected count ${bfd.count}`);
22064
- if (asString(Hash.sha256(asArray(data)), "base64") !== bfd.fileHash) throw new WERR_INVALID_PARAMETER("fileHash", `a match for retrieved data for ${bfd.fileName}`);
22255
+ async loadFromStorage(bfd) {
22256
+ if (this.storage == null || !bfd.fileId) return void 0;
22257
+ const stored = await this.storage.getBulkFileData(bfd.fileId);
22258
+ if (stored == null) throw new WERR_INVALID_PARAMETER("fileId", `valid, data not found for fileId ${bfd.fileId}`);
22259
+ const validated = await this.validateRetrievedData(bfd, stored);
22260
+ this.stats.storageHits++;
22261
+ return validated;
22262
+ }
22263
+ async loadFromCache(bfd) {
22264
+ if (this.cache == null) return void 0;
22265
+ const cached = await this.cache.get(bfd);
22266
+ if (cached == null) {
22267
+ this.stats.persistentCacheMisses++;
22268
+ return;
22269
+ }
22270
+ try {
22271
+ const validated = await this.validateRetrievedData(bfd, cached);
22272
+ this.stats.persistentCacheHits++;
22273
+ await this.cache.promoteValidated?.(bfd, validated);
22274
+ return validated;
22275
+ } catch (error) {
22276
+ if (!(error instanceof BulkFileDataValidationError)) throw error;
22277
+ this.stats.persistentCacheRejects++;
22278
+ let rejectedData = error.data;
22279
+ if (!(rejectedData instanceof Uint8Array) && cached.byteLength > 0) rejectedData = cached;
22280
+ await this.cache.quarantine?.(bfd, String(error), rejectedData);
22281
+ this.log(`Rejected corrupt bulk-header cache entry ${bfd.fileName}: ${String(error)}`);
22282
+ return;
22283
+ }
22284
+ }
22285
+ async loadFromRemote(bfd) {
22286
+ if (this.fetch == null || !bfd.sourceUrl) return void 0;
22287
+ const expectedBytes = bfd.count * 80;
22288
+ await this.downloadBudget?.consume(expectedBytes);
22289
+ const url = this.fetch.pathJoin(bfd.sourceUrl, bfd.fileName);
22290
+ const downloaded = await this.fetch.download(url, expectedBytes, { beforeRetry: async () => await this.downloadBudget?.consume(expectedBytes) });
22291
+ if (downloaded == null) throw new WERR_INVALID_PARAMETER("sourceUrl", `data not found for sourceUrl ${url}`);
22292
+ const validated = await this.validateRetrievedData(bfd, downloaded);
22293
+ this.stats.downloads++;
22294
+ this.stats.downloadedBytes += validated.length;
22295
+ await this.cache?.set(bfd, validated);
22296
+ return validated;
22297
+ }
22298
+ async validateRetrievedData(bfd, data, expectedFileHash = bfd.fileHash) {
22065
22299
  const candidate = {
22066
22300
  ...bfd,
22067
22301
  data
22068
22302
  };
22069
- this.validateBfdHeaders(candidate);
22303
+ const validated = await this.validateBfdHeaders(candidate, expectedFileHash);
22304
+ bfd.lastHash = candidate.lastHash;
22305
+ bfd.lastChainWork = candidate.lastChainWork;
22306
+ return validated;
22070
22307
  }
22071
22308
  ensureMaxRetained() {
22072
22309
  if (this.maxRetained === void 0) return;
@@ -22102,17 +22339,24 @@ var BulkFileDataManager = class BulkFileDataManager {
22102
22339
  i++;
22103
22340
  const data = await reader.read();
22104
22341
  if (data == null || data.length === 0) break;
22105
- const last = validateBufferOfHeaders(data, lastHeaderHash, 0, void 0, lastChainWork);
22106
- await toFs.writeFile(toPath(i), data);
22107
- const fileHash = asString(Hash.sha256(asArray(data)), "base64");
22342
+ const validated = await this.validator.validate({
22343
+ fileName: toFileName(i),
22344
+ data,
22345
+ count: data.length / 80,
22346
+ firstHeight,
22347
+ prevHash: lastHeaderHash,
22348
+ prevChainWork: lastChainWork,
22349
+ chain
22350
+ });
22351
+ await toFs.writeFile(toPath(i), validated.data);
22108
22352
  const file = {
22109
22353
  chain,
22110
- count: data.length / 80,
22111
- fileHash,
22354
+ count: validated.data.length / 80,
22355
+ fileHash: validated.fileHash,
22112
22356
  fileName: toFileName(i),
22113
22357
  firstHeight,
22114
- lastChainWork: last.lastChainWork,
22115
- lastHash: last.lastHeaderHash,
22358
+ lastChainWork: validated.lastChainWork,
22359
+ lastHash: validated.lastHeaderHash,
22116
22360
  prevChainWork: lastChainWork,
22117
22361
  prevHash: lastHeaderHash,
22118
22362
  sourceUrl
@@ -22124,7 +22368,16 @@ var BulkFileDataManager = class BulkFileDataManager {
22124
22368
  }
22125
22369
  await toFs.writeFile(toJsonPath(), asUint8Array(JSON.stringify(toBulkFiles), "utf8"));
22126
22370
  }
22371
+ async destroy() {
22372
+ await this.validator.destroy?.();
22373
+ }
22127
22374
  };
22375
+ function snapshotBfd(file) {
22376
+ return {
22377
+ ...file,
22378
+ data: file.data
22379
+ };
22380
+ }
22128
22381
  function selectBulkHeaderFiles(files, chain, maxPerFile) {
22129
22382
  const r = [];
22130
22383
  let height = 0;
@@ -26993,7 +27246,8 @@ function createDefaultBulkFileDataManager(params) {
26993
27246
  maxRetained: params.maxRetained,
26994
27247
  fromKnownSourceUrl: params.cdnUrl,
26995
27248
  cache: params.sources.bulkFileCache,
26996
- downloadBudget: params.sources.bulkFileDownloadBudget
27249
+ downloadBudget: params.sources.bulkFileDownloadBudget,
27250
+ validator: params.sources.bulkFileDataValidator
26997
27251
  });
26998
27252
  }
26999
27253
  function createDefaultChaintracksStorageOptions(params) {
@@ -27518,6 +27772,7 @@ var FixedWindowBulkFileDownloadBudget = class {
27518
27772
  return {
27519
27773
  maxBytes: this.maxBytes,
27520
27774
  consumedBytes: this.consumedBytes,
27775
+ remainingBytes: this.maxBytes - this.consumedBytes,
27521
27776
  windowStartedAt: this.windowStartedAt,
27522
27777
  windowMsecs: this.windowMsecs
27523
27778
  };
@@ -30749,6 +31004,7 @@ var SetupClient = class SetupClient {
30749
31004
  };
30750
31005
  //#endregion
30751
31006
  //#region ../src/CWIStyleWalletManager.ts
31007
+ const CWI_COMPONENT = "wallet-toolbox.cwi-manager";
30752
31008
  /**
30753
31009
  * Number of rounds used in PBKDF2 for deriving password keys.
30754
31010
  */
@@ -30981,11 +31237,11 @@ var OverlayUMPTokenInteractor = class {
30981
31237
  * @param hash The 32-byte SHA-256 hash of the presentation key.
30982
31238
  * @returns A UMPToken object (including currentOutpoint) if found, otherwise undefined.
30983
31239
  */
30984
- async findByPresentationKeyHash(hash) {
30985
- return await this.findToken({
31240
+ async findByPresentationKeyHash(hash, options) {
31241
+ return this.findToken({
30986
31242
  service: "ls_users",
30987
31243
  query: { presentationHash: Utils.toHex(hash) }
30988
- }, "presentation");
31244
+ }, "presentation", options);
30989
31245
  }
30990
31246
  /**
30991
31247
  * Finds a UMP token on-chain by the given recovery key hash, if it exists.
@@ -30994,13 +31250,13 @@ var OverlayUMPTokenInteractor = class {
30994
31250
  * @param hash The 32-byte SHA-256 hash of the recovery key.
30995
31251
  * @returns A UMPToken object (including currentOutpoint) if found, otherwise undefined.
30996
31252
  */
30997
- async findByRecoveryKeyHash(hash) {
30998
- return await this.findToken({
31253
+ async findByRecoveryKeyHash(hash, options) {
31254
+ return this.findToken({
30999
31255
  service: "ls_users",
31000
31256
  query: { recoveryHash: Utils.toHex(hash) }
31001
- }, "recovery");
31257
+ }, "recovery", options);
31002
31258
  }
31003
- async findToken(question, lookupKind) {
31259
+ async findToken(question, lookupKind, options) {
31004
31260
  const correlationId = this.telemetry.enabled === true ? this.telemetry.createCorrelationId() : void 0;
31005
31261
  const startedAt = Date.now();
31006
31262
  this.telemetry.capture({
@@ -31017,34 +31273,39 @@ var OverlayUMPTokenInteractor = class {
31017
31273
  correlationId
31018
31274
  });
31019
31275
  } catch (error) {
31020
- const diagnostics = this.emptyLookupDiagnostics(correlationId);
31021
- this.captureLookupFailure(lookupKind, "lookup-unavailable", diagnostics, startedAt, error);
31276
+ const diagnostics = this.emptyStats(correlationId);
31277
+ this.lookupFailed(lookupKind, "lookup-unavailable", diagnostics, startedAt, error);
31022
31278
  throw new UMPTokenLookupError("lookup-unavailable", diagnostics, { cause: error });
31023
31279
  }
31024
- const diagnostics = this.toLookupDiagnostics(resolution);
31280
+ const diagnostics = this.diagnosticsFor(resolution);
31025
31281
  const tokens = this.parseLookupAnswers(resolution.answer);
31026
31282
  const expectedHash = question.query[lookupKind === "presentation" ? "presentationHash" : "recoveryHash"].toLowerCase();
31027
31283
  const matchingTokens = tokens.filter((token) => Utils.toHex(lookupKind === "presentation" ? token.presentationHash : token.recoveryHash).toLowerCase() === expectedHash);
31028
31284
  if (matchingTokens.length > 1) {
31029
31285
  const newest = this.resolveNewestToken(matchingTokens, resolution.answer.outputs);
31030
31286
  if (newest != null) {
31031
- this.captureLookupCompleted(lookupKind, "found", diagnostics, startedAt, { supersededTokens: matchingTokens.length - 1 });
31287
+ this.lookupDone(lookupKind, "found", diagnostics, startedAt, { supersededTokens: matchingTokens.length - 1 });
31032
31288
  return newest;
31033
31289
  }
31290
+ const pinned = options?.pinnedOutpoint ? matchingTokens.find((token) => token.currentOutpoint === options.pinnedOutpoint) : void 0;
31291
+ if (pinned != null) {
31292
+ this.lookupDone(lookupKind, "found", diagnostics, startedAt);
31293
+ return pinned;
31294
+ }
31034
31295
  const reason = "token-ambiguous";
31035
- this.captureLookupFailure(lookupKind, reason, diagnostics, startedAt);
31296
+ this.lookupFailed(lookupKind, reason, diagnostics, startedAt);
31036
31297
  throw new UMPTokenLookupError(reason, diagnostics);
31037
31298
  }
31038
31299
  if (matchingTokens.length === 1) {
31039
- this.captureLookupCompleted(lookupKind, "found", diagnostics, startedAt);
31300
+ this.lookupDone(lookupKind, "found", diagnostics, startedAt);
31040
31301
  return matchingTokens[0];
31041
31302
  }
31042
31303
  if (resolution.progress.emptyHosts > 0) {
31043
- this.captureLookupCompleted(lookupKind, "not-found", diagnostics, startedAt);
31304
+ this.lookupDone(lookupKind, "not-found", diagnostics, startedAt);
31044
31305
  return;
31045
31306
  }
31046
31307
  const reason = resolution.answer.outputs.length > 0 ? "token-malformed" : "lookup-incomplete";
31047
- this.captureLookupFailure(lookupKind, reason, diagnostics, startedAt);
31308
+ this.lookupFailed(lookupKind, reason, diagnostics, startedAt);
31048
31309
  throw new UMPTokenLookupError(reason, diagnostics);
31049
31310
  }
31050
31311
  /**
@@ -31075,7 +31336,7 @@ var OverlayUMPTokenInteractor = class {
31075
31336
  spent: /* @__PURE__ */ new Set()
31076
31337
  };
31077
31338
  evidence.txs.push(tx);
31078
- this.collectSpentOutpoints(tx, evidence.spent, /* @__PURE__ */ new Set());
31339
+ this.collectSpends(tx, evidence.spent, /* @__PURE__ */ new Set());
31079
31340
  evidenceByCandidate.set(outpoint, evidence);
31080
31341
  } catch {}
31081
31342
  if (evidenceByCandidate.size !== candidates.size) return void 0;
@@ -31084,7 +31345,7 @@ var OverlayUMPTokenInteractor = class {
31084
31345
  const provenContinuations = survivors.filter((outpoint) => {
31085
31346
  const evidence = evidenceByCandidate.get(outpoint);
31086
31347
  const token = candidates.get(outpoint);
31087
- return evidence != null && token != null && evidence.txs.some((tx) => this.consumesSameIdentityToken(tx, token));
31348
+ return evidence != null && token != null && evidence.txs.some((tx) => this.consumesIdentity(tx, token));
31088
31349
  });
31089
31350
  if (provenContinuations.length !== 1) return void 0;
31090
31351
  return candidates.get(provenContinuations[0]);
@@ -31095,7 +31356,7 @@ var OverlayUMPTokenInteractor = class {
31095
31356
  * hash — on-chain proof that the candidate is an update of a same-identity
31096
31357
  * predecessor rather than an independently minted token.
31097
31358
  */
31098
- consumesSameIdentityToken(tx, token) {
31359
+ consumesIdentity(tx, token) {
31099
31360
  const presentationHash = Utils.toHex(token.presentationHash);
31100
31361
  const recoveryHash = Utils.toHex(token.recoveryHash);
31101
31362
  for (const input of tx.inputs) {
@@ -31121,7 +31382,7 @@ var OverlayUMPTokenInteractor = class {
31121
31382
  * renditions are absent from the lookup answer. Iterative so arbitrarily
31122
31383
  * long update chains cannot exhaust the call stack.
31123
31384
  */
31124
- collectSpentOutpoints(tx, spent, visited) {
31385
+ collectSpends(tx, spent, visited) {
31125
31386
  const pending = [tx];
31126
31387
  while (pending.length > 0) {
31127
31388
  const current = pending.pop();
@@ -31136,7 +31397,7 @@ var OverlayUMPTokenInteractor = class {
31136
31397
  }
31137
31398
  }
31138
31399
  }
31139
- emptyLookupDiagnostics(correlationId) {
31400
+ emptyStats(correlationId) {
31140
31401
  return {
31141
31402
  hostCount: 0,
31142
31403
  completedHosts: 0,
@@ -31149,7 +31410,7 @@ var OverlayUMPTokenInteractor = class {
31149
31410
  ...correlationId !== void 0 ? { correlationId } : {}
31150
31411
  };
31151
31412
  }
31152
- toLookupDiagnostics(resolution) {
31413
+ diagnosticsFor(resolution) {
31153
31414
  const progress = resolution.progress;
31154
31415
  return {
31155
31416
  hostCount: progress.hostCount,
@@ -31163,7 +31424,7 @@ var OverlayUMPTokenInteractor = class {
31163
31424
  ...progress.correlationId !== void 0 ? { correlationId: progress.correlationId } : {}
31164
31425
  };
31165
31426
  }
31166
- lookupDiagnosticAttributes(diagnostics) {
31427
+ lookupAttrs(diagnostics) {
31167
31428
  return {
31168
31429
  hostCount: diagnostics.hostCount,
31169
31430
  completedHosts: diagnostics.completedHosts,
@@ -31175,7 +31436,7 @@ var OverlayUMPTokenInteractor = class {
31175
31436
  outputCount: diagnostics.outputCount
31176
31437
  };
31177
31438
  }
31178
- captureLookupCompleted(lookupKind, result, diagnostics, startedAt, extraAttributes = {}) {
31439
+ lookupDone(lookupKind, result, diagnostics, startedAt, extraAttributes = {}) {
31179
31440
  this.telemetry.capture({
31180
31441
  name: "wallet-toolbox.ump.lookup.completed",
31181
31442
  component: "wallet-toolbox.ump",
@@ -31185,12 +31446,12 @@ var OverlayUMPTokenInteractor = class {
31185
31446
  lookupKind,
31186
31447
  result,
31187
31448
  durationMs: Date.now() - startedAt,
31188
- ...this.lookupDiagnosticAttributes(diagnostics),
31449
+ ...this.lookupAttrs(diagnostics),
31189
31450
  ...extraAttributes
31190
31451
  }
31191
31452
  });
31192
31453
  }
31193
- captureLookupFailure(lookupKind, reason, diagnostics, startedAt, error) {
31454
+ lookupFailed(lookupKind, reason, diagnostics, startedAt, error) {
31194
31455
  this.telemetry.capture({
31195
31456
  name: "wallet-toolbox.ump.lookup.indeterminate",
31196
31457
  component: "wallet-toolbox.ump",
@@ -31200,7 +31461,7 @@ var OverlayUMPTokenInteractor = class {
31200
31461
  lookupKind,
31201
31462
  reason,
31202
31463
  durationMs: Date.now() - startedAt,
31203
- ...this.lookupDiagnosticAttributes(diagnostics)
31464
+ ...this.lookupAttrs(diagnostics)
31204
31465
  },
31205
31466
  error
31206
31467
  });
@@ -31218,27 +31479,27 @@ var OverlayUMPTokenInteractor = class {
31218
31479
  * @returns The outpoint of the newly created UMP token (e.g. "abcd1234...ef.0").
31219
31480
  */
31220
31481
  async buildAndSend(wallet, adminOriginator, token, oldTokenToConsume) {
31221
- const fields = this.buildUMPTokenFields(token);
31482
+ const fields = this.tokenFields(token);
31222
31483
  const tokenOutput = [{
31223
31484
  lockingScript: (await new PushDrop(wallet, adminOriginator).lock(fields, [2, "admin user management token"], "1", "self", true, true)).toHex(),
31224
31485
  satoshis: 1,
31225
31486
  outputDescription: "New UMP token output"
31226
31487
  }];
31227
- const { resolvedOldToken, inputToken } = await this.resolveOldTokenInput(oldTokenToConsume);
31488
+ const { resolvedOldToken, inputToken } = await this.resolveOldInput(oldTokenToConsume);
31228
31489
  const inputs = resolvedOldToken?.currentOutpoint ? [{
31229
31490
  outpoint: resolvedOldToken.currentOutpoint,
31230
31491
  unlockingScriptLength: 73,
31231
31492
  inputDescription: "Consume old UMP token"
31232
31493
  }] : [];
31233
- const createResult = await this.createUMPAction(wallet, adminOriginator, inputs, tokenOutput, inputToken, resolvedOldToken);
31234
- if (!createResult.signableTransaction) return await this.broadcastFinishedUMPAction(createResult);
31494
+ const createResult = await this.createAction(wallet, adminOriginator, inputs, tokenOutput, inputToken, resolvedOldToken);
31495
+ if (!createResult.signableTransaction) return this.broadcastFinal(createResult);
31235
31496
  const reference = createResult.signableTransaction.reference;
31236
31497
  const partialTx = Transaction.fromBEEF(createResult.signableTransaction.tx);
31237
- if (resolvedOldToken?.currentOutpoint) return await this.signAndBroadcastWithOldToken(wallet, adminOriginator, reference, partialTx);
31238
- return await this.signAndBroadcastNewToken(wallet, adminOriginator, reference);
31498
+ if (resolvedOldToken?.currentOutpoint) return this.renewToken(wallet, adminOriginator, reference, partialTx);
31499
+ return this.broadcastNew(wallet, adminOriginator, reference);
31239
31500
  }
31240
31501
  /** Assembles the ordered number[][] fields array from a UMPToken. */
31241
- buildUMPTokenFields(token) {
31502
+ tokenFields(token) {
31242
31503
  const fields = [];
31243
31504
  fields[0] = token.passwordSalt;
31244
31505
  fields[1] = token.passwordPresentationPrimary;
@@ -31265,20 +31526,20 @@ var OverlayUMPTokenInteractor = class {
31265
31526
  return fields;
31266
31527
  }
31267
31528
  /** Looks up the old token on the overlay; returns undefined resolved token if not found. */
31268
- async resolveOldTokenInput(oldTokenToConsume) {
31529
+ async resolveOldInput(oldTokenToConsume) {
31269
31530
  if (!oldTokenToConsume?.currentOutpoint) return {
31270
31531
  resolvedOldToken: void 0,
31271
31532
  inputToken: void 0
31272
31533
  };
31273
31534
  const inputToken = await this.findByOutpoint(oldTokenToConsume.currentOutpoint);
31274
- if (inputToken == null) throw new Error("The previous UMP token could not be resolved; refusing to publish a duplicate token.");
31535
+ if (inputToken == null) throw new Error("Previous UMP token unavailable; update refused.");
31275
31536
  return {
31276
31537
  resolvedOldToken: oldTokenToConsume,
31277
31538
  inputToken
31278
31539
  };
31279
31540
  }
31280
31541
  /** Creates the UMP action without dropping a required old-token input on failure. */
31281
- async createUMPAction(wallet, adminOriginator, inputs, outputs, inputToken, resolvedOldToken) {
31542
+ async createAction(wallet, adminOriginator, inputs, outputs, inputToken, resolvedOldToken) {
31282
31543
  try {
31283
31544
  return await wallet.createAction({
31284
31545
  description: resolvedOldToken == null ? "Create new UMP token" : "Renew UMP token (consume old, create new)",
@@ -31305,43 +31566,43 @@ var OverlayUMPTokenInteractor = class {
31305
31566
  }
31306
31567
  }
31307
31568
  /** Handles a fully-finalized (no signable tx) createAction result — broadcasts and returns outpoint. */
31308
- async broadcastFinishedUMPAction(createResult) {
31569
+ async broadcastFinal(createResult) {
31309
31570
  const finalTxid = createResult.txid || (createResult.tx != null ? Transaction.fromAtomicBEEF(createResult.tx).id("hex") : void 0);
31310
- if (!finalTxid) throw new Error("No signableTransaction and no final TX found.");
31311
- if (createResult.tx == null) throw new Error("No final TX data to broadcast.");
31571
+ if (!finalTxid) throw new Error("UMP transaction was not finalized.");
31572
+ if (createResult.tx == null) throw new Error("UMP transaction data missing.");
31312
31573
  const broadcastTx = Transaction.fromAtomicBEEF(createResult.tx);
31313
31574
  const result = await this.broadcaster.broadcast(broadcastTx);
31314
- this.assertSuccessfulBroadcast(result, "create-finalized");
31575
+ this.assertBroadcast(result, "create-finalized");
31315
31576
  return `${finalTxid}.0`;
31316
31577
  }
31317
31578
  /** Signs the old-token input and broadcasts — used during UMP token renewal. */
31318
- async signAndBroadcastWithOldToken(wallet, adminOriginator, reference, partialTx) {
31579
+ async renewToken(wallet, adminOriginator, reference, partialTx) {
31319
31580
  const unlockingScript = await new PushDrop(wallet, adminOriginator).unlock([2, "admin user management token"], "1", "self").sign(partialTx, 0);
31320
31581
  const signResult = await wallet.signAction({
31321
31582
  reference,
31322
31583
  spends: { 0: { unlockingScript: unlockingScript.toHex() } }
31323
31584
  }, adminOriginator);
31324
31585
  const finalTxid = signResult.txid || (signResult.tx == null ? "" : Transaction.fromAtomicBEEF(signResult.tx).id("hex"));
31325
- if (!finalTxid) throw new Error("Could not finalize transaction for renewed UMP token.");
31326
- if (signResult.tx == null) throw new Error("Final transaction data missing after signing renewed UMP token.");
31586
+ if (!finalTxid) throw new Error("Could not finalize renewed UMP token.");
31587
+ if (signResult.tx == null) throw new Error("Renewed UMP token transaction data missing.");
31327
31588
  const result = await this.broadcaster.broadcast(Transaction.fromAtomicBEEF(signResult.tx));
31328
- this.assertSuccessfulBroadcast(result, "renew");
31589
+ this.assertBroadcast(result, "renew");
31329
31590
  return `${finalTxid}.0`;
31330
31591
  }
31331
31592
  /** Signs without input spending and broadcasts — used when creating a brand-new UMP token. */
31332
- async signAndBroadcastNewToken(wallet, adminOriginator, reference) {
31593
+ async broadcastNew(wallet, adminOriginator, reference) {
31333
31594
  const signResult = await wallet.signAction({
31334
31595
  reference,
31335
31596
  spends: {}
31336
31597
  }, adminOriginator);
31337
31598
  const finalTxid = signResult.txid || (signResult.tx == null ? "" : Transaction.fromAtomicBEEF(signResult.tx).id("hex"));
31338
- if (!finalTxid) throw new Error("Failed to finalize new UMP token transaction.");
31339
- if (signResult.tx == null) throw new Error("Final transaction data missing after signing new UMP token.");
31599
+ if (!finalTxid) throw new Error("Could not finalize new UMP token.");
31600
+ if (signResult.tx == null) throw new Error("New UMP token transaction data missing.");
31340
31601
  const result = await this.broadcaster.broadcast(Transaction.fromAtomicBEEF(signResult.tx));
31341
- this.assertSuccessfulBroadcast(result, "create");
31602
+ this.assertBroadcast(result, "create");
31342
31603
  return `${finalTxid}.0`;
31343
31604
  }
31344
- assertSuccessfulBroadcast(result, operation) {
31605
+ assertBroadcast(result, operation) {
31345
31606
  const succeeded = result.status === "success";
31346
31607
  this.telemetry.capture({
31347
31608
  name: succeeded ? "wallet-toolbox.ump.broadcast.completed" : "wallet-toolbox.ump.broadcast.failed",
@@ -31370,12 +31631,12 @@ var OverlayUMPTokenInteractor = class {
31370
31631
  if (answer.type !== "output-list" || answer.outputs.length === 0) return [];
31371
31632
  const tokens = [];
31372
31633
  for (const output of answer.outputs) {
31373
- const token = this.parseLookupOutput(output);
31634
+ const token = this.parseOutput(output);
31374
31635
  if (token != null) tokens.push(token);
31375
31636
  }
31376
31637
  return tokens;
31377
31638
  }
31378
- parseLookupOutput(output) {
31639
+ parseOutput(output) {
31379
31640
  try {
31380
31641
  const tx = Transaction.fromBEEF(output.beef);
31381
31642
  const txOutput = tx.outputs[output.outputIndex];
@@ -31425,14 +31686,14 @@ var OverlayUMPTokenInteractor = class {
31425
31686
  correlationId
31426
31687
  });
31427
31688
  } catch (error) {
31428
- const diagnostics = this.emptyLookupDiagnostics(correlationId);
31429
- this.captureLookupFailure("outpoint", "lookup-unavailable", diagnostics, startedAt, error);
31689
+ const diagnostics = this.emptyStats(correlationId);
31690
+ this.lookupFailed("outpoint", "lookup-unavailable", diagnostics, startedAt, error);
31430
31691
  throw new UMPTokenLookupError("lookup-unavailable", diagnostics, { cause: error });
31431
31692
  }
31432
31693
  if (resolution.answer.outputs.length === 0) {
31433
31694
  if (resolution.progress.emptyHosts === 0) {
31434
- const diagnostics = this.toLookupDiagnostics(resolution);
31435
- this.captureLookupFailure("outpoint", "lookup-incomplete", diagnostics, startedAt);
31695
+ const diagnostics = this.diagnosticsFor(resolution);
31696
+ this.lookupFailed("outpoint", "lookup-incomplete", diagnostics, startedAt);
31436
31697
  throw new UMPTokenLookupError("lookup-incomplete", diagnostics);
31437
31698
  }
31438
31699
  return;
@@ -31574,20 +31835,20 @@ var CWIStyleWalletManager = class {
31574
31835
  if (this._initSnapshot !== void 0) {
31575
31836
  this.telemetry.capture({
31576
31837
  name: "wallet-toolbox.snapshot.initialization.started",
31577
- component: "wallet-toolbox.cwi-manager",
31838
+ component: CWI_COMPONENT,
31578
31839
  severity: "debug"
31579
31840
  });
31580
31841
  try {
31581
31842
  await this.loadSnapshot(this._initSnapshot);
31582
31843
  this.telemetry.capture({
31583
31844
  name: "wallet-toolbox.snapshot.initialization.completed",
31584
- component: "wallet-toolbox.cwi-manager",
31845
+ component: CWI_COMPONENT,
31585
31846
  severity: "info"
31586
31847
  });
31587
31848
  } catch (error) {
31588
31849
  this.telemetry.capture({
31589
31850
  name: "wallet-toolbox.snapshot.initialization.failed",
31590
- component: "wallet-toolbox.cwi-manager",
31851
+ component: CWI_COMPONENT,
31591
31852
  severity: "error",
31592
31853
  error
31593
31854
  });
@@ -31596,9 +31857,11 @@ var CWIStyleWalletManager = class {
31596
31857
  }
31597
31858
  }
31598
31859
  /**
31599
- * Provides the presentation key.
31860
+ * Provides the presentation key. A WAB operator pin may be supplied by the
31861
+ * authentication manager; normal lookup and lineage resolution always run
31862
+ * before this ambiguity-only fallback.
31600
31863
  */
31601
- async providePresentationKey(key) {
31864
+ async providePresentationKey(key, lookupOptions) {
31602
31865
  if (this.authenticated) throw new Error("User is already authenticated");
31603
31866
  if (this.authenticationMode === "recovery-key-and-password") throw new Error("Presentation key is not needed in this mode");
31604
31867
  if (key.length !== 32 || key.some((byte) => !Number.isInteger(byte) || byte < 0 || byte > 255)) throw new TypeError("Presentation key must contain exactly 32 bytes.");
@@ -31607,17 +31870,17 @@ var CWIStyleWalletManager = class {
31607
31870
  const startedAt = Date.now();
31608
31871
  this.telemetry.capture({
31609
31872
  name: "wallet-toolbox.authentication.account-lookup.started",
31610
- component: "wallet-toolbox.cwi-manager",
31873
+ component: CWI_COMPONENT,
31611
31874
  severity: "debug",
31612
31875
  attributes: { lookupKind: "presentation" }
31613
31876
  });
31614
31877
  let token;
31615
31878
  try {
31616
- token = await this.UMPTokenInteractor.findByPresentationKeyHash(hash);
31879
+ token = await this.UMPTokenInteractor.findByPresentationKeyHash(hash, lookupOptions);
31617
31880
  } catch (error) {
31618
31881
  this.telemetry.capture({
31619
31882
  name: "wallet-toolbox.authentication.account-lookup.failed",
31620
- component: "wallet-toolbox.cwi-manager",
31883
+ component: CWI_COMPONENT,
31621
31884
  severity: "warn",
31622
31885
  attributes: {
31623
31886
  lookupKind: "presentation",
@@ -31637,7 +31900,7 @@ var CWIStyleWalletManager = class {
31637
31900
  }
31638
31901
  this.telemetry.capture({
31639
31902
  name: "wallet-toolbox.authentication.account-lookup.completed",
31640
- component: "wallet-toolbox.cwi-manager",
31903
+ component: CWI_COMPONENT,
31641
31904
  severity: "info",
31642
31905
  attributes: {
31643
31906
  lookupKind: "presentation",
@@ -31653,11 +31916,11 @@ var CWIStyleWalletManager = class {
31653
31916
  if (this.authenticated) throw new Error("User is already authenticated");
31654
31917
  if (this.authenticationMode === "presentation-key-and-recovery-key") throw new Error("Password is not needed in this mode");
31655
31918
  if (this.authenticationFlow === "unknown") throw new Error("Determine account status with a presentation or recovery key before providing a password.");
31656
- if (this.authenticationFlow === "existing-user") await this.handleExistingUserPassword(password);
31657
- else await this.handleNewUserPassword(password);
31919
+ if (this.authenticationFlow === "existing-user") await this.unlockExisting(password);
31920
+ else await this.createNewUser(password);
31658
31921
  }
31659
31922
  /** Handles the password step for an existing user — derives keys, sets up infrastructure. */
31660
- async handleExistingUserPassword(password) {
31923
+ async unlockExisting(password) {
31661
31924
  if (this.currentUMPToken == null) throw new Error("Provide presentation or recovery key first.");
31662
31925
  const derivedPasswordKey = await derivePasswordKey(this.currentUMPToken, Utils.toArray(password, "utf8"));
31663
31926
  let rootPrimaryKey;
@@ -31670,11 +31933,11 @@ var CWIStyleWalletManager = class {
31670
31933
  rootPrimaryKey = new SymmetricKey(this.XOR(this.recoveryKey, derivedPasswordKey)).decrypt(this.currentUMPToken.passwordRecoveryPrimary);
31671
31934
  rootPrivilegedKey = new SymmetricKey(this.XOR(rootPrimaryKey, derivedPasswordKey)).decrypt(this.currentUMPToken.passwordPrimaryPrivileged);
31672
31935
  }
31673
- await this.setupRootInfrastructure(rootPrimaryKey, rootPrivilegedKey);
31936
+ await this.setupRoot(rootPrimaryKey, rootPrivilegedKey);
31674
31937
  await this.switchProfile(this.activeProfileId);
31675
31938
  }
31676
31939
  /** Handles the password step for a new user — generates keys, builds UMP token, publishes on-chain. */
31677
- async handleNewUserPassword(password) {
31940
+ async createNewUser(password) {
31678
31941
  if (this.authenticationMode !== "presentation-key-and-password") throw new Error("New-user flow requires presentation key and password mode.");
31679
31942
  if (this.presentationKey == null) throw new Error("No presentation key provided for new-user flow.");
31680
31943
  const recoveryKey = Random(32);
@@ -31713,14 +31976,14 @@ var CWIStyleWalletManager = class {
31713
31976
  passwordKdf: this.kdfConfig
31714
31977
  };
31715
31978
  this.currentUMPToken = newToken;
31716
- await this.setupRootInfrastructure(rootPrimaryKey);
31979
+ await this.setupRoot(rootPrimaryKey);
31717
31980
  await this.switchProfile(DEFAULT_PROFILE_ID);
31718
31981
  if (this.newWalletFunder != null && this.underlying != null) try {
31719
31982
  await this.newWalletFunder(this.presentationKey, this.underlying, this.adminOriginator);
31720
31983
  } catch (error) {
31721
31984
  this.telemetry.capture({
31722
31985
  name: "wallet-toolbox.authentication.new-wallet-funding.failed",
31723
- component: "wallet-toolbox.cwi-manager",
31986
+ component: CWI_COMPONENT,
31724
31987
  severity: "error",
31725
31988
  error: /* @__PURE__ */ new Error("New wallet funding failed.")
31726
31989
  });
@@ -31751,7 +32014,7 @@ var CWIStyleWalletManager = class {
31751
32014
  const xorKey = this.XOR(this.presentationKey, recoveryKey);
31752
32015
  const rootPrimaryKey = new SymmetricKey(xorKey).decrypt(this.currentUMPToken.presentationRecoveryPrimary);
31753
32016
  const rootPrivilegedKey = new SymmetricKey(xorKey).decrypt(this.currentUMPToken.presentationRecoveryPrivileged);
31754
- await this.setupRootInfrastructure(rootPrimaryKey, rootPrivilegedKey);
32017
+ await this.setupRoot(rootPrimaryKey, rootPrivilegedKey);
31755
32018
  await this.switchProfile(this.activeProfileId);
31756
32019
  }
31757
32020
  }
@@ -31782,7 +32045,7 @@ var CWIStyleWalletManager = class {
31782
32045
  if (snapshot.length > 16777216) throw new Error("Snapshot exceeds the maximum supported size.");
31783
32046
  this.telemetry.capture({
31784
32047
  name: "wallet-toolbox.snapshot.saved",
31785
- component: "wallet-toolbox.cwi-manager",
32048
+ component: CWI_COMPONENT,
31786
32049
  severity: "info",
31787
32050
  attributes: {
31788
32051
  formatVersion: 2,
@@ -31820,12 +32083,12 @@ var CWIStyleWalletManager = class {
31820
32083
  const tokenBytes = payloadReader.read(tokenLen);
31821
32084
  const token = this.deserializeUMPToken(tokenBytes);
31822
32085
  this.currentUMPToken = token;
31823
- await this.setupRootInfrastructure(rootPrimaryKey);
32086
+ await this.setupRoot(rootPrimaryKey);
31824
32087
  await this.switchProfile(activeProfileId);
31825
32088
  this.authenticationFlow = "existing-user";
31826
32089
  this.telemetry.capture({
31827
32090
  name: "wallet-toolbox.snapshot.loaded",
31828
- component: "wallet-toolbox.cwi-manager",
32091
+ component: CWI_COMPONENT,
31829
32092
  severity: "info",
31830
32093
  attributes: {
31831
32094
  formatVersion: version,
@@ -31836,7 +32099,7 @@ var CWIStyleWalletManager = class {
31836
32099
  this.destroy();
31837
32100
  this.telemetry.capture({
31838
32101
  name: "wallet-toolbox.snapshot.load-failed",
31839
- component: "wallet-toolbox.cwi-manager",
32102
+ component: CWI_COMPONENT,
31840
32103
  severity: "error",
31841
32104
  error
31842
32105
  });
@@ -31853,7 +32116,7 @@ var CWIStyleWalletManager = class {
31853
32116
  if (refreshed == null) return false;
31854
32117
  if (refreshed.currentOutpoint && currentToken.currentOutpoint && refreshed.currentOutpoint === currentToken.currentOutpoint) return false;
31855
32118
  this.currentUMPToken = refreshed;
31856
- await this.setupRootInfrastructure(this.rootPrimaryKey);
32119
+ await this.setupRoot(this.rootPrimaryKey);
31857
32120
  this.saveSnapshot();
31858
32121
  return true;
31859
32122
  }
@@ -31912,7 +32175,7 @@ var CWIStyleWalletManager = class {
31912
32175
  createdAt: Math.floor(Date.now() / 1e3)
31913
32176
  };
31914
32177
  this.profiles.push(newProfile);
31915
- await this.updateAuthFactors(this.currentUMPToken.passwordSalt, await this.getFactor("passwordKey"), await this.getFactor("presentationKey"), await this.getFactor("recoveryKey"), this.rootPrimaryKey, await this.getFactor("privilegedKey"), this.profiles);
32178
+ await this.updateFactors(this.currentUMPToken.passwordSalt, await this.getFactor("passwordKey"), await this.getFactor("presentationKey"), await this.getFactor("recoveryKey"), this.rootPrimaryKey, await this.getFactor("privilegedKey"), this.profiles);
31916
32179
  return newProfile.id;
31917
32180
  }
31918
32181
  /**
@@ -31929,7 +32192,7 @@ var CWIStyleWalletManager = class {
31929
32192
  if (profileIndex === -1) throw new Error("Profile not found.");
31930
32193
  this.profiles.splice(profileIndex, 1);
31931
32194
  if (this.activeProfileId.every((x, i) => x === profileId[i])) await this.switchProfile(DEFAULT_PROFILE_ID);
31932
- await this.updateAuthFactors(this.currentUMPToken.passwordSalt, await this.getFactor("passwordKey"), await this.getFactor("presentationKey"), await this.getFactor("recoveryKey"), this.rootPrimaryKey, await this.getFactor("privilegedKey"), this.profiles);
32195
+ await this.updateFactors(this.currentUMPToken.passwordSalt, await this.getFactor("passwordKey"), await this.getFactor("presentationKey"), await this.getFactor("recoveryKey"), this.rootPrimaryKey, await this.getFactor("privilegedKey"), this.profiles);
31933
32196
  }
31934
32197
  /**
31935
32198
  * Switches the active profile. This re-derives keys and rebuilds the underlying wallet.
@@ -31970,14 +32233,14 @@ var CWIStyleWalletManager = class {
31970
32233
  const recoveryKey = await this.getFactor("recoveryKey");
31971
32234
  const presentationKey = await this.getFactor("presentationKey");
31972
32235
  const rootPrivilegedKey = await this.getFactor("privilegedKey");
31973
- await this.updateAuthFactors(passwordSalt, newPasswordKey, presentationKey, recoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
32236
+ await this.updateFactors(passwordSalt, newPasswordKey, presentationKey, recoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
31974
32237
  }
31975
32238
  /**
31976
32239
  * Retrieves the current recovery key. Requires privileged access.
31977
32240
  */
31978
32241
  async getRecoveryKey() {
31979
32242
  if (!this.authenticated || this.currentUMPToken == null || this.rootPrivilegedKeyManager == null) throw new Error("Not authenticated or missing required data.");
31980
- return await this.getFactor("recoveryKey");
32243
+ return this.getFactor("recoveryKey");
31981
32244
  }
31982
32245
  /**
31983
32246
  * Changes the user's recovery key. Prompts user to save the new key.
@@ -31989,7 +32252,7 @@ var CWIStyleWalletManager = class {
31989
32252
  const rootPrivilegedKey = await this.getFactor("privilegedKey");
31990
32253
  const newRecoveryKey = Random(32);
31991
32254
  await this.recoveryKeySaver(newRecoveryKey);
31992
- await this.updateAuthFactors(this.currentUMPToken.passwordSalt, passwordKey, presentationKey, newRecoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
32255
+ await this.updateFactors(this.currentUMPToken.passwordSalt, passwordKey, presentationKey, newRecoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
31993
32256
  }
31994
32257
  /**
31995
32258
  * Changes the user's presentation key.
@@ -32000,7 +32263,7 @@ var CWIStyleWalletManager = class {
32000
32263
  const recoveryKey = await this.getFactor("recoveryKey");
32001
32264
  const passwordKey = await this.getFactor("passwordKey");
32002
32265
  const rootPrivilegedKey = await this.getFactor("privilegedKey");
32003
- await this.updateAuthFactors(this.currentUMPToken.passwordSalt, passwordKey, newPresentationKey, recoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
32266
+ await this.updateFactors(this.currentUMPToken.passwordSalt, passwordKey, newPresentationKey, recoveryKey, this.rootPrimaryKey, rootPrivilegedKey, this.profiles);
32004
32267
  if (this.presentationKey != null) this.presentationKey = newPresentationKey;
32005
32268
  }
32006
32269
  /**
@@ -32046,7 +32309,7 @@ var CWIStyleWalletManager = class {
32046
32309
  } catch (error) {
32047
32310
  this.telemetry.capture({
32048
32311
  name: "wallet-toolbox.authentication.factor-decryption.failed",
32049
- component: "wallet-toolbox.cwi-manager",
32312
+ component: CWI_COMPONENT,
32050
32313
  severity: "error",
32051
32314
  attributes: { factor: factorName },
32052
32315
  error
@@ -32059,7 +32322,7 @@ var CWIStyleWalletManager = class {
32059
32322
  * Recomputes UMP token fields with updated factors and profiles, then publishes the update.
32060
32323
  * This operation requires the *root* privileged key and the *default* profile wallet.
32061
32324
  */
32062
- async updateAuthFactors(passwordSalt, passwordKey, presentationKey, recoveryKey, rootPrimaryKey, rootPrivilegedKey, profiles) {
32325
+ async updateFactors(passwordSalt, passwordKey, presentationKey, recoveryKey, rootPrimaryKey, rootPrivilegedKey, profiles) {
32063
32326
  if (!this.authenticated || this.rootPrimaryKey == null || this.currentUMPToken == null) throw new Error("Wallet is not properly authenticated or missing data for update.");
32064
32327
  const oldTokenToConsume = { ...this.currentUMPToken };
32065
32328
  if (!oldTokenToConsume.currentOutpoint) throw new Error("Cannot update UMP token: Old token has no outpoint.");
@@ -32110,7 +32373,7 @@ var CWIStyleWalletManager = class {
32110
32373
  if (!currentActiveId.every((x) => x === 0)) {
32111
32374
  this.telemetry.capture({
32112
32375
  name: "wallet-toolbox.ump.profile-switch.started",
32113
- component: "wallet-toolbox.cwi-manager",
32376
+ component: CWI_COMPONENT,
32114
32377
  severity: "debug",
32115
32378
  attributes: { reason: "token-update" }
32116
32379
  });
@@ -32126,7 +32389,7 @@ var CWIStyleWalletManager = class {
32126
32389
  await this.switchProfile(currentActiveId);
32127
32390
  this.telemetry.capture({
32128
32391
  name: "wallet-toolbox.ump.profile-switch.completed",
32129
- component: "wallet-toolbox.cwi-manager",
32392
+ component: CWI_COMPONENT,
32130
32393
  severity: "debug",
32131
32394
  attributes: { reason: "token-update" }
32132
32395
  });
@@ -32253,9 +32516,9 @@ var CWIStyleWalletManager = class {
32253
32516
  * @param rootPrimaryKey The user's root primary key (32 bytes).
32254
32517
  * @param ephemeralRootPrivilegedKey Optional root privileged key (e.g., during recovery flows).
32255
32518
  */
32256
- async setupRootInfrastructure(rootPrimaryKey, ephemeralRootPrivilegedKey) {
32519
+ async setupRoot(rootKey, ephemeralRootPrivilegedKey) {
32257
32520
  if (this.currentUMPToken == null) throw new Error("A UMP token must exist before setting up root infrastructure!");
32258
- this.rootPrimaryKey = rootPrimaryKey;
32521
+ this.rootPrimaryKey = rootKey;
32259
32522
  let oneTimePrivilegedKey = ephemeralRootPrivilegedKey == null ? void 0 : new PrivateKey(ephemeralRootPrivilegedKey);
32260
32523
  this.rootPrivilegedKeyManager = new PrivilegedKeyManager(async (reason) => {
32261
32524
  if (oneTimePrivilegedKey != null) {
@@ -32276,7 +32539,7 @@ var CWIStyleWalletManager = class {
32276
32539
  });
32277
32540
  this.profiles = [];
32278
32541
  if (this.currentUMPToken.profilesEncrypted != null && this.currentUMPToken.profilesEncrypted.length > 0) try {
32279
- const decryptedProfileBytes = new SymmetricKey(rootPrimaryKey).decrypt(this.currentUMPToken.profilesEncrypted);
32542
+ const decryptedProfileBytes = new SymmetricKey(rootKey).decrypt(this.currentUMPToken.profilesEncrypted);
32280
32543
  const profilesJson = Utils.toUTF8(decryptedProfileBytes);
32281
32544
  const profiles = JSON.parse(profilesJson);
32282
32545
  if (!Array.isArray(profiles) || profiles.length > 1e3 || !profiles.every(isValidProfile)) throw new Error("Decrypted profile data is invalid or exceeds supported bounds.");
@@ -32285,7 +32548,7 @@ var CWIStyleWalletManager = class {
32285
32548
  this.profiles = [];
32286
32549
  this.telemetry.capture({
32287
32550
  name: "wallet-toolbox.profile.load-failed",
32288
- component: "wallet-toolbox.cwi-manager",
32551
+ component: CWI_COMPONENT,
32289
32552
  severity: "error",
32290
32553
  error
32291
32554
  });
@@ -32294,98 +32557,98 @@ var CWIStyleWalletManager = class {
32294
32557
  }
32295
32558
  this.authenticated = true;
32296
32559
  }
32297
- checkAuthAndUnderlying(originator) {
32560
+ assertReady(originator) {
32298
32561
  if (!this.authenticated) throw new Error("User is not authenticated.");
32299
32562
  if (this.underlying == null) throw new Error("Underlying wallet for the active profile is not initialized.");
32300
32563
  if (originator === this.adminOriginator) throw new Error("External applications are not allowed to use the admin originator.");
32301
32564
  }
32302
32565
  async getPublicKey(args, originator) {
32303
- this.checkAuthAndUnderlying(originator);
32304
- return await this.underlying.getPublicKey(args, originator);
32566
+ this.assertReady(originator);
32567
+ return this.underlying.getPublicKey(args, originator);
32305
32568
  }
32306
32569
  async revealCounterpartyKeyLinkage(args, originator) {
32307
- this.checkAuthAndUnderlying(originator);
32308
- return await this.underlying.revealCounterpartyKeyLinkage(args, originator);
32570
+ this.assertReady(originator);
32571
+ return this.underlying.revealCounterpartyKeyLinkage(args, originator);
32309
32572
  }
32310
32573
  async revealSpecificKeyLinkage(args, originator) {
32311
- this.checkAuthAndUnderlying(originator);
32312
- return await this.underlying.revealSpecificKeyLinkage(args, originator);
32574
+ this.assertReady(originator);
32575
+ return this.underlying.revealSpecificKeyLinkage(args, originator);
32313
32576
  }
32314
32577
  async encrypt(args, originator) {
32315
- this.checkAuthAndUnderlying(originator);
32316
- return await this.underlying.encrypt(args, originator);
32578
+ this.assertReady(originator);
32579
+ return this.underlying.encrypt(args, originator);
32317
32580
  }
32318
32581
  async decrypt(args, originator) {
32319
- this.checkAuthAndUnderlying(originator);
32320
- return await this.underlying.decrypt(args, originator);
32582
+ this.assertReady(originator);
32583
+ return this.underlying.decrypt(args, originator);
32321
32584
  }
32322
32585
  async createHmac(args, originator) {
32323
- this.checkAuthAndUnderlying(originator);
32324
- return await this.underlying.createHmac(args, originator);
32586
+ this.assertReady(originator);
32587
+ return this.underlying.createHmac(args, originator);
32325
32588
  }
32326
32589
  async verifyHmac(args, originator) {
32327
- this.checkAuthAndUnderlying(originator);
32328
- return await this.underlying.verifyHmac(args, originator);
32590
+ this.assertReady(originator);
32591
+ return this.underlying.verifyHmac(args, originator);
32329
32592
  }
32330
32593
  async createSignature(args, originator) {
32331
- this.checkAuthAndUnderlying(originator);
32332
- return await this.underlying.createSignature(args, originator);
32594
+ this.assertReady(originator);
32595
+ return this.underlying.createSignature(args, originator);
32333
32596
  }
32334
32597
  async verifySignature(args, originator) {
32335
- this.checkAuthAndUnderlying(originator);
32336
- return await this.underlying.verifySignature(args, originator);
32598
+ this.assertReady(originator);
32599
+ return this.underlying.verifySignature(args, originator);
32337
32600
  }
32338
32601
  async createAction(args, originator) {
32339
- this.checkAuthAndUnderlying(originator);
32340
- return await this.underlying.createAction(args, originator);
32602
+ this.assertReady(originator);
32603
+ return this.underlying.createAction(args, originator);
32341
32604
  }
32342
32605
  async signAction(args, originator) {
32343
- this.checkAuthAndUnderlying(originator);
32344
- return await this.underlying.signAction(args, originator);
32606
+ this.assertReady(originator);
32607
+ return this.underlying.signAction(args, originator);
32345
32608
  }
32346
32609
  async abortAction(args, originator) {
32347
- this.checkAuthAndUnderlying(originator);
32348
- return await this.underlying.abortAction(args, originator);
32610
+ this.assertReady(originator);
32611
+ return this.underlying.abortAction(args, originator);
32349
32612
  }
32350
32613
  async listActions(args, originator) {
32351
- this.checkAuthAndUnderlying(originator);
32352
- return await this.underlying.listActions(args, originator);
32614
+ this.assertReady(originator);
32615
+ return this.underlying.listActions(args, originator);
32353
32616
  }
32354
32617
  async internalizeAction(args, originator) {
32355
- this.checkAuthAndUnderlying(originator);
32356
- return await this.underlying.internalizeAction(args, originator);
32618
+ this.assertReady(originator);
32619
+ return this.underlying.internalizeAction(args, originator);
32357
32620
  }
32358
32621
  async listOutputs(args, originator) {
32359
- this.checkAuthAndUnderlying(originator);
32360
- return await this.underlying.listOutputs(args, originator);
32622
+ this.assertReady(originator);
32623
+ return this.underlying.listOutputs(args, originator);
32361
32624
  }
32362
32625
  async relinquishOutput(args, originator) {
32363
- this.checkAuthAndUnderlying(originator);
32364
- return await this.underlying.relinquishOutput(args, originator);
32626
+ this.assertReady(originator);
32627
+ return this.underlying.relinquishOutput(args, originator);
32365
32628
  }
32366
32629
  async acquireCertificate(args, originator) {
32367
- this.checkAuthAndUnderlying(originator);
32368
- return await this.underlying.acquireCertificate(args, originator);
32630
+ this.assertReady(originator);
32631
+ return this.underlying.acquireCertificate(args, originator);
32369
32632
  }
32370
32633
  async listCertificates(args, originator) {
32371
- this.checkAuthAndUnderlying(originator);
32372
- return await this.underlying.listCertificates(args, originator);
32634
+ this.assertReady(originator);
32635
+ return this.underlying.listCertificates(args, originator);
32373
32636
  }
32374
32637
  async proveCertificate(args, originator) {
32375
- this.checkAuthAndUnderlying(originator);
32376
- return await this.underlying.proveCertificate(args, originator);
32638
+ this.assertReady(originator);
32639
+ return this.underlying.proveCertificate(args, originator);
32377
32640
  }
32378
32641
  async relinquishCertificate(args, originator) {
32379
- this.checkAuthAndUnderlying(originator);
32380
- return await this.underlying.relinquishCertificate(args, originator);
32642
+ this.assertReady(originator);
32643
+ return this.underlying.relinquishCertificate(args, originator);
32381
32644
  }
32382
32645
  async discoverByIdentityKey(args, originator) {
32383
- this.checkAuthAndUnderlying(originator);
32384
- return await this.underlying.discoverByIdentityKey(args, originator);
32646
+ this.assertReady(originator);
32647
+ return this.underlying.discoverByIdentityKey(args, originator);
32385
32648
  }
32386
32649
  async discoverByAttributes(args, originator) {
32387
- this.checkAuthAndUnderlying(originator);
32388
- return await this.underlying.discoverByAttributes(args, originator);
32650
+ this.assertReady(originator);
32651
+ return this.underlying.discoverByAttributes(args, originator);
32389
32652
  }
32390
32653
  async isAuthenticated(_, originator) {
32391
32654
  if (!this.authenticated) throw new Error("User is not authenticated.");
@@ -32395,23 +32658,23 @@ var CWIStyleWalletManager = class {
32395
32658
  async waitForAuthentication(_, originator) {
32396
32659
  if (originator === this.adminOriginator) throw new Error("External applications are not allowed to use the admin originator.");
32397
32660
  while (!this.authenticated || this.underlying == null) await new Promise((resolve) => setTimeout(resolve, 100));
32398
- return await this.underlying.waitForAuthentication({}, originator);
32661
+ return this.underlying.waitForAuthentication({}, originator);
32399
32662
  }
32400
32663
  async getHeight(_, originator) {
32401
- this.checkAuthAndUnderlying(originator);
32402
- return await this.underlying.getHeight({}, originator);
32664
+ this.assertReady(originator);
32665
+ return this.underlying.getHeight({}, originator);
32403
32666
  }
32404
32667
  async getHeaderForHeight(args, originator) {
32405
- this.checkAuthAndUnderlying(originator);
32406
- return await this.underlying.getHeaderForHeight(args, originator);
32668
+ this.assertReady(originator);
32669
+ return this.underlying.getHeaderForHeight(args, originator);
32407
32670
  }
32408
32671
  async getNetwork(_, originator) {
32409
- this.checkAuthAndUnderlying(originator);
32410
- return await this.underlying.getNetwork({}, originator);
32672
+ this.assertReady(originator);
32673
+ return this.underlying.getNetwork({}, originator);
32411
32674
  }
32412
32675
  async getVersion(_, originator) {
32413
- this.checkAuthAndUnderlying(originator);
32414
- return await this.underlying.getVersion({}, originator);
32676
+ this.assertReady(originator);
32677
+ return this.underlying.getVersion({}, originator);
32415
32678
  }
32416
32679
  };
32417
32680
  //#endregion
@@ -32755,6 +33018,8 @@ const DEFAULT_MAX_RESPONSE_BYTES = 1024 * 1024;
32755
33018
  const MAX_CONFIGURED_TIMEOUT_MS = 12e4;
32756
33019
  const MAX_CONFIGURED_REQUEST_BYTES = 10 * 1024 * 1024;
32757
33020
  const MAX_CONFIGURED_RESPONSE_BYTES = 10 * 1024 * 1024;
33021
+ const WAB_COMPONENT = "wallet-toolbox.wab-transport";
33022
+ const WAB_REQUEST_EVENT = "wallet-toolbox.wab.request.";
32758
33023
  const defaultFetch = typeof globalThis !== "undefined" && typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0;
32759
33024
  /**
32760
33025
  * A privacy-safe WAB transport failure. Response bodies and request payloads
@@ -32793,8 +33058,8 @@ function normalizeServerUrl(serverUrl) {
32793
33058
  } catch {
32794
33059
  throw new WABClientError("WAB_INVALID_CONFIGURATION", "WAB server URL must be an absolute URL.", false);
32795
33060
  }
32796
- if (parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") throw new WABClientError("WAB_INVALID_CONFIGURATION", "WAB server URL must not contain credentials, a query, or a fragment.", false);
32797
- if (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && isLocalHostname(parsed.hostname))) throw new WABClientError("WAB_INVALID_CONFIGURATION", "WAB server URL must use HTTPS. Plain HTTP is allowed only for localhost development.", false);
33061
+ if (parsed.username !== "" || parsed.password !== "" || parsed.search !== "" || parsed.hash !== "") throw new WABClientError("WAB_INVALID_CONFIGURATION", "WAB URL cannot include credentials, query, or fragment.", false);
33062
+ if (parsed.protocol !== "https:" && !(parsed.protocol === "http:" && isLocalHostname(parsed.hostname))) throw new WABClientError("WAB_INVALID_CONFIGURATION", "WAB URL requires HTTPS except on localhost.", false);
32798
33063
  let pathname = parsed.pathname;
32799
33064
  while (pathname.endsWith("/")) pathname = pathname.slice(0, -1);
32800
33065
  return {
@@ -32804,7 +33069,7 @@ function normalizeServerUrl(serverUrl) {
32804
33069
  }
32805
33070
  function normalizePositiveInteger(value, fallback, maximum, name) {
32806
33071
  const resolved = value ?? fallback;
32807
- if (!Number.isInteger(resolved) || resolved <= 0 || resolved > maximum) throw new WABClientError("WAB_INVALID_CONFIGURATION", `${name} must be a positive integer no greater than ${maximum}.`, false);
33072
+ if (!Number.isInteger(resolved) || resolved <= 0 || resolved > maximum) throw new WABClientError("WAB_INVALID_CONFIGURATION", `${name} must be an integer from 1 to ${maximum}.`, false);
32808
33073
  return resolved;
32809
33074
  }
32810
33075
  function assertSafePath(path) {
@@ -32829,20 +33094,20 @@ var WABTransport = class {
32829
33094
  serverUrl;
32830
33095
  serverOrigin;
32831
33096
  telemetry;
32832
- fetchClient;
32833
- timeoutMs;
32834
- maxRequestBytes;
32835
- maxResponseBytes;
33097
+ fetcher;
33098
+ timeout;
33099
+ requestLimit;
33100
+ responseLimit;
32836
33101
  constructor(serverUrl, options = {}) {
32837
33102
  const normalized = normalizeServerUrl(serverUrl);
32838
33103
  this.serverUrl = normalized.baseUrl;
32839
33104
  this.serverOrigin = normalized.origin;
32840
- const fetchClient = options.fetch ?? defaultFetch;
32841
- if (typeof fetchClient !== "function") throw new WABClientError("WAB_INVALID_CONFIGURATION", "WABClient requires a fetch implementation.", false);
32842
- this.fetchClient = fetchClient;
32843
- this.timeoutMs = normalizePositiveInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, MAX_CONFIGURED_TIMEOUT_MS, "timeoutMs");
32844
- this.maxRequestBytes = normalizePositiveInteger(options.maxRequestBytes, DEFAULT_MAX_REQUEST_BYTES, MAX_CONFIGURED_REQUEST_BYTES, "maxRequestBytes");
32845
- this.maxResponseBytes = normalizePositiveInteger(options.maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES, MAX_CONFIGURED_RESPONSE_BYTES, "maxResponseBytes");
33105
+ const fetcher = options.fetch ?? defaultFetch;
33106
+ if (typeof fetcher !== "function") throw new WABClientError("WAB_INVALID_CONFIGURATION", "WABClient requires a fetch implementation.", false);
33107
+ this.fetcher = fetcher;
33108
+ this.timeout = normalizePositiveInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, MAX_CONFIGURED_TIMEOUT_MS, "timeoutMs");
33109
+ this.requestLimit = normalizePositiveInteger(options.maxRequestBytes, DEFAULT_MAX_REQUEST_BYTES, MAX_CONFIGURED_REQUEST_BYTES, "maxRequestBytes");
33110
+ this.responseLimit = normalizePositiveInteger(options.maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES, MAX_CONFIGURED_RESPONSE_BYTES, "maxResponseBytes");
32846
33111
  this.telemetry = new Telemetry(options.telemetry);
32847
33112
  }
32848
33113
  createCorrelationId() {
@@ -32850,38 +33115,9 @@ var WABTransport = class {
32850
33115
  return isSafeCorrelationId(correlationId) ? correlationId : new Telemetry().createCorrelationId();
32851
33116
  }
32852
33117
  async request(path, options) {
32853
- const metadata = this.createRequestMetadata(path, options);
32854
- this.captureRequestStarted(metadata);
32855
- const body = this.encodeRequestBody(options, metadata);
32856
- const timeout = this.startRequestTimeout(metadata.errorContext);
32857
- const response = await this.fetchResponse(metadata, body, timeout);
32858
- const responseContext = this.createResponseContext(response, metadata);
32859
- this.assertSuccessfulResponse(response, responseContext, metadata, timeout);
32860
- const responseText = await this.readResponseText(response, responseContext, metadata, timeout);
32861
- const parsed = this.parseResponseObject(responseText, response, responseContext, metadata);
32862
- this.telemetry.capture({
32863
- name: "wallet-toolbox.wab.request.completed",
32864
- component: "wallet-toolbox.wab-transport",
32865
- severity: "info",
32866
- correlationId: metadata.correlationId,
32867
- attributes: {
32868
- operation: metadata.operation,
32869
- method: metadata.method,
32870
- route: metadata.path,
32871
- serverOrigin: this.serverOrigin,
32872
- status: response.status,
32873
- endpointMarkerPresent: responseContext.endpointMarkerPresent,
32874
- responseCorrelationMatched: responseContext.responseCorrelationMatched,
32875
- responseBytes: new TextEncoder().encode(responseText).byteLength,
32876
- durationMs: Date.now() - metadata.startedAt
32877
- }
32878
- });
32879
- return parsed;
32880
- }
32881
- createRequestMetadata(path, options) {
32882
33118
  assertSafePath(path);
32883
33119
  const correlationId = options.correlationId != null && isSafeCorrelationId(options.correlationId) ? options.correlationId : this.createCorrelationId();
32884
- return {
33120
+ const metadata = {
32885
33121
  method: options.method ?? "POST",
32886
33122
  path,
32887
33123
  operation: options.operation,
@@ -32893,46 +33129,73 @@ var WABTransport = class {
32893
33129
  route: path
32894
33130
  }
32895
33131
  };
32896
- }
32897
- captureRequestStarted(metadata) {
32898
33132
  this.telemetry.capture({
32899
- name: "wallet-toolbox.wab.request.started",
32900
- component: "wallet-toolbox.wab-transport",
33133
+ name: `${WAB_REQUEST_EVENT}started`,
33134
+ component: WAB_COMPONENT,
32901
33135
  severity: "debug",
33136
+ correlationId,
33137
+ attributes: {
33138
+ operation: metadata.operation,
33139
+ method: metadata.method,
33140
+ route: path,
33141
+ serverOrigin: this.serverOrigin
33142
+ }
33143
+ });
33144
+ const body = this.bodyFor(options, metadata);
33145
+ const timeout = this.startTimer(metadata.errorContext);
33146
+ const response = await this.fetch(metadata, body, timeout);
33147
+ const responseContext = {
33148
+ ...metadata.errorContext,
33149
+ endpointMarkerPresent: isWabResponse(response),
33150
+ responseCorrelationMatched: response.headers.get("X-Correlation-ID") === correlationId
33151
+ };
33152
+ this.checkResponse(response, responseContext, metadata, timeout);
33153
+ const responseText = await this.readText(response, responseContext, metadata, timeout);
33154
+ const parsed = this.parse(responseText, response, responseContext, metadata);
33155
+ this.telemetry.capture({
33156
+ name: `${WAB_REQUEST_EVENT}completed`,
33157
+ component: WAB_COMPONENT,
33158
+ severity: "info",
32902
33159
  correlationId: metadata.correlationId,
32903
33160
  attributes: {
32904
33161
  operation: metadata.operation,
32905
33162
  method: metadata.method,
32906
33163
  route: metadata.path,
32907
- serverOrigin: this.serverOrigin
33164
+ serverOrigin: this.serverOrigin,
33165
+ status: response.status,
33166
+ endpointMarkerPresent: responseContext.endpointMarkerPresent,
33167
+ responseCorrelationMatched: responseContext.responseCorrelationMatched,
33168
+ responseBytes: new TextEncoder().encode(responseText).byteLength,
33169
+ durationMs: Date.now() - metadata.startedAt
32908
33170
  }
32909
33171
  });
33172
+ return parsed;
32910
33173
  }
32911
- encodeRequestBody(options, metadata) {
33174
+ bodyFor(options, metadata) {
32912
33175
  let body;
32913
33176
  try {
32914
33177
  body = options.body === void 0 ? void 0 : JSON.stringify(options.body);
32915
33178
  } catch (cause) {
32916
- const error = new WABClientError("WAB_INVALID_REQUEST", "WAB request payload could not be encoded.", false, void 0, {
33179
+ const error = new WABClientError("WAB_INVALID_REQUEST", "WAB request encoding failed.", false, void 0, {
32917
33180
  ...metadata.errorContext,
32918
33181
  cause
32919
33182
  });
32920
- this.captureRequestFailure(metadata, error);
33183
+ this.report(metadata, error);
32921
33184
  throw error;
32922
33185
  }
32923
33186
  if (options.body !== void 0 && body === void 0) {
32924
- const error = new WABClientError("WAB_INVALID_REQUEST", "WAB request payload must be JSON-serializable.", false, void 0, metadata.errorContext);
32925
- this.captureRequestFailure(metadata, error);
33187
+ const error = new WABClientError("WAB_INVALID_REQUEST", "WAB request is not JSON-serializable.", false, void 0, metadata.errorContext);
33188
+ this.report(metadata, error);
32926
33189
  throw error;
32927
33190
  }
32928
- if (body != null && new TextEncoder().encode(body).byteLength > this.maxRequestBytes) {
32929
- const error = new WABClientError("WAB_REQUEST_TOO_LARGE", "WAB request exceeded the configured size limit.", false, void 0, metadata.errorContext);
32930
- this.captureRequestFailure(metadata, error);
33191
+ if (body != null && new TextEncoder().encode(body).byteLength > this.requestLimit) {
33192
+ const error = new WABClientError("WAB_REQUEST_TOO_LARGE", "WAB request exceeds its size limit.", false, void 0, metadata.errorContext);
33193
+ this.report(metadata, error);
32931
33194
  throw error;
32932
33195
  }
32933
33196
  return body;
32934
33197
  }
32935
- startRequestTimeout(errorContext) {
33198
+ startTimer(errorContext) {
32936
33199
  const timeout = {
32937
33200
  controller: new AbortController(),
32938
33201
  timedOut: false
@@ -32942,12 +33205,12 @@ var WABTransport = class {
32942
33205
  timeout.timedOut = true;
32943
33206
  timeout.controller.abort();
32944
33207
  reject(new WABClientError("WAB_TIMEOUT", "WAB request timed out.", true, void 0, errorContext));
32945
- }, this.timeoutMs);
33208
+ }, this.timeout);
32946
33209
  });
32947
33210
  return timeout;
32948
33211
  }
32949
- async fetchResponse(metadata, body, timeout) {
32950
- const requestPromise = Promise.resolve().then(() => this.fetchClient(`${this.serverUrl}${metadata.path}`, {
33212
+ async fetch(metadata, body, timeout) {
33213
+ const requestPromise = Promise.resolve().then(() => this.fetcher(`${this.serverUrl}${metadata.path}`, {
32951
33214
  method: metadata.method,
32952
33215
  headers: {
32953
33216
  Accept: "application/json",
@@ -32971,33 +33234,26 @@ var WABTransport = class {
32971
33234
  ...metadata.errorContext,
32972
33235
  cause
32973
33236
  });
32974
- else error = new WABClientError("WAB_NETWORK_ERROR", "WAB request failed before receiving a response.", true, void 0, {
33237
+ else error = new WABClientError("WAB_NETWORK_ERROR", "WAB request failed before response.", true, void 0, {
32975
33238
  ...metadata.errorContext,
32976
33239
  cause
32977
33240
  });
32978
- this.captureRequestFailure(metadata, error);
33241
+ this.report(metadata, error);
32979
33242
  throw error;
32980
33243
  }
32981
33244
  }
32982
- createResponseContext(response, metadata) {
32983
- return {
32984
- ...metadata.errorContext,
32985
- endpointMarkerPresent: isWabResponse(response),
32986
- responseCorrelationMatched: response.headers.get("X-Correlation-ID") === metadata.correlationId
32987
- };
32988
- }
32989
- assertSuccessfulResponse(response, responseContext, metadata, timeout) {
33245
+ checkResponse(response, responseContext, metadata, timeout) {
32990
33246
  if (response.ok) return;
32991
33247
  if (timeout.timer !== void 0) clearTimeout(timeout.timer);
32992
33248
  const endpointMismatch = response.status === 404 && responseContext.endpointMarkerPresent !== true;
32993
- const error = new WABClientError(endpointMismatch ? "WAB_ENDPOINT_MISMATCH" : "WAB_HTTP_ERROR", endpointMismatch ? "Configured WAB endpoint did not return a compatible WAB response." : `WAB request failed with HTTP status ${response.status}.`, isRetryableStatus(response.status), response.status, responseContext);
32994
- this.captureRequestFailure(metadata, error);
33249
+ const error = new WABClientError(endpointMismatch ? "WAB_ENDPOINT_MISMATCH" : "WAB_HTTP_ERROR", endpointMismatch ? "WAB endpoint is incompatible." : `WAB request failed with HTTP status ${response.status}.`, isRetryableStatus(response.status), response.status, responseContext);
33250
+ this.report(metadata, error);
32995
33251
  response.body?.cancel().catch(() => {});
32996
33252
  throw error;
32997
33253
  }
32998
- async readResponseText(response, responseContext, metadata, timeout) {
33254
+ async readText(response, responseContext, metadata, timeout) {
32999
33255
  try {
33000
- return await Promise.race([this.readBoundedResponse(response, responseContext), timeout.promise]);
33256
+ return await Promise.race([this.read(response, responseContext), timeout.promise]);
33001
33257
  } catch (cause) {
33002
33258
  let error;
33003
33259
  if (cause instanceof WABClientError) error = cause;
@@ -33005,17 +33261,17 @@ var WABTransport = class {
33005
33261
  ...responseContext,
33006
33262
  cause
33007
33263
  });
33008
- else error = new WABClientError("WAB_INVALID_RESPONSE", "WAB response could not be read.", true, response.status, {
33264
+ else error = new WABClientError("WAB_INVALID_RESPONSE", "WAB response read failed.", true, response.status, {
33009
33265
  ...responseContext,
33010
33266
  cause
33011
33267
  });
33012
- this.captureRequestFailure(metadata, error);
33268
+ this.report(metadata, error);
33013
33269
  throw error;
33014
33270
  } finally {
33015
33271
  if (timeout.timer !== void 0) clearTimeout(timeout.timer);
33016
33272
  }
33017
33273
  }
33018
- parseResponseObject(responseText, response, responseContext, metadata) {
33274
+ parse(responseText, response, responseContext, metadata) {
33019
33275
  let parsed;
33020
33276
  try {
33021
33277
  parsed = JSON.parse(responseText);
@@ -33024,37 +33280,32 @@ var WABTransport = class {
33024
33280
  ...responseContext,
33025
33281
  cause
33026
33282
  });
33027
- this.captureRequestFailure(metadata, error);
33283
+ this.report(metadata, error);
33028
33284
  throw error;
33029
33285
  }
33030
33286
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
33031
33287
  const error = new WABClientError("WAB_INVALID_RESPONSE", "WAB response must be a JSON object.", true, response.status, responseContext);
33032
- this.captureRequestFailure(metadata, error);
33288
+ this.report(metadata, error);
33033
33289
  throw error;
33034
33290
  }
33035
33291
  return parsed;
33036
33292
  }
33037
- captureRequestFailure(metadata, error) {
33038
- this.captureFailure(metadata.operation, metadata.method, metadata.path, metadata.correlationId, metadata.startedAt, error);
33039
- }
33040
- async readBoundedResponse(response, responseContext) {
33041
- await this.rejectOversizedDeclaredResponse(response, responseContext);
33042
- const reader = response.body?.getReader();
33043
- if (reader == null) return await this.readBoundedArrayBuffer(response, responseContext);
33044
- return await this.readBoundedStream(reader, response, responseContext);
33045
- }
33046
- async rejectOversizedDeclaredResponse(response, responseContext) {
33293
+ async read(response, responseContext) {
33047
33294
  const contentLength = Number(response.headers.get("content-length"));
33048
- if (!Number.isFinite(contentLength) || contentLength <= this.maxResponseBytes) return;
33049
- await this.cancelResponseBody(response);
33050
- throw this.responseTooLargeError(response, responseContext);
33295
+ if (Number.isFinite(contentLength) && contentLength > this.responseLimit) {
33296
+ await this.stopBody(response);
33297
+ throw this.sizeError(response, responseContext);
33298
+ }
33299
+ const reader = response.body?.getReader();
33300
+ if (reader == null) return this.readBuffer(response, responseContext);
33301
+ return this.readStream(reader, response, responseContext);
33051
33302
  }
33052
- async readBoundedArrayBuffer(response, responseContext) {
33303
+ async readBuffer(response, responseContext) {
33053
33304
  const bytes = new Uint8Array(await response.arrayBuffer());
33054
- if (bytes.byteLength > this.maxResponseBytes) throw this.responseTooLargeError(response, responseContext);
33305
+ if (bytes.byteLength > this.responseLimit) throw this.sizeError(response, responseContext);
33055
33306
  return new TextDecoder().decode(bytes);
33056
33307
  }
33057
- async readBoundedStream(reader, response, responseContext) {
33308
+ async readStream(reader, response, responseContext) {
33058
33309
  const chunks = [];
33059
33310
  let total = 0;
33060
33311
  while (true) {
@@ -33062,15 +33313,12 @@ var WABTransport = class {
33062
33313
  if (done) break;
33063
33314
  if (value == null) continue;
33064
33315
  total += value.byteLength;
33065
- if (total > this.maxResponseBytes) {
33066
- await this.cancelResponseReader(reader);
33067
- throw this.responseTooLargeError(response, responseContext);
33316
+ if (total > this.responseLimit) {
33317
+ await this.stopReader(reader);
33318
+ throw this.sizeError(response, responseContext);
33068
33319
  }
33069
33320
  chunks.push(value);
33070
33321
  }
33071
- return this.decodeChunks(chunks, total);
33072
- }
33073
- decodeChunks(chunks, total) {
33074
33322
  const bytes = new Uint8Array(total);
33075
33323
  let offset = 0;
33076
33324
  for (const chunk of chunks) {
@@ -33079,35 +33327,35 @@ var WABTransport = class {
33079
33327
  }
33080
33328
  return new TextDecoder().decode(bytes);
33081
33329
  }
33082
- responseTooLargeError(response, responseContext) {
33083
- return new WABClientError("WAB_RESPONSE_TOO_LARGE", "WAB response exceeded the configured size limit.", false, response.status, responseContext);
33330
+ sizeError(response, responseContext) {
33331
+ return new WABClientError("WAB_RESPONSE_TOO_LARGE", "WAB response exceeds its size limit.", false, response.status, responseContext);
33084
33332
  }
33085
- async cancelResponseBody(response) {
33333
+ async stopBody(response) {
33086
33334
  try {
33087
33335
  await response.body?.cancel();
33088
33336
  } catch {}
33089
33337
  }
33090
- async cancelResponseReader(reader) {
33338
+ async stopReader(reader) {
33091
33339
  try {
33092
33340
  await reader.cancel();
33093
33341
  } catch {}
33094
33342
  }
33095
- captureFailure(operation, method, path, correlationId, startedAt, error) {
33343
+ report(metadata, error) {
33096
33344
  this.telemetry.capture({
33097
- name: "wallet-toolbox.wab.request.failed",
33098
- component: "wallet-toolbox.wab-transport",
33345
+ name: `${WAB_REQUEST_EVENT}failed`,
33346
+ component: WAB_COMPONENT,
33099
33347
  severity: error.retryable ? "warn" : "error",
33100
- correlationId,
33348
+ correlationId: metadata.correlationId,
33101
33349
  attributes: {
33102
- operation,
33103
- method,
33104
- route: path,
33350
+ operation: metadata.operation,
33351
+ method: metadata.method,
33352
+ route: metadata.path,
33105
33353
  serverOrigin: this.serverOrigin,
33106
33354
  retryable: error.retryable,
33107
33355
  ...error.status !== void 0 ? { status: error.status } : {},
33108
33356
  ...error.endpointMarkerPresent !== void 0 ? { endpointMarkerPresent: error.endpointMarkerPresent } : {},
33109
33357
  ...error.responseCorrelationMatched !== void 0 ? { responseCorrelationMatched: error.responseCorrelationMatched } : {},
33110
- durationMs: Date.now() - startedAt
33358
+ durationMs: Date.now() - metadata.startedAt
33111
33359
  },
33112
33360
  error
33113
33361
  });
@@ -33216,8 +33464,8 @@ var WABClient = class {
33216
33464
  constructor(serverUrl, options = {}) {
33217
33465
  this.transport = new WABTransport(serverUrl, options);
33218
33466
  }
33219
- async getInfo() {
33220
- return await this.transport.request("/info", {
33467
+ getInfo() {
33468
+ return this.transport.request("/info", {
33221
33469
  method: "GET",
33222
33470
  operation: "get-info"
33223
33471
  });
@@ -33227,15 +33475,15 @@ var WABClient = class {
33227
33475
  }
33228
33476
  async startAuthMethod(authMethod, presentationKey, payload, correlationId) {
33229
33477
  assertHexIdentifier(presentationKey, "presentationKey");
33230
- return await authMethod.startAuth(this.transport.serverUrl, presentationKey, payload, this.transport, correlationId);
33478
+ return authMethod.startAuth(this.transport.serverUrl, presentationKey, payload, this.transport, correlationId);
33231
33479
  }
33232
33480
  async completeAuthMethod(authMethod, presentationKey, payload, correlationId) {
33233
33481
  assertHexIdentifier(presentationKey, "presentationKey");
33234
- return await authMethod.completeAuth(this.transport.serverUrl, presentationKey, payload, this.transport, correlationId);
33482
+ return authMethod.completeAuth(this.transport.serverUrl, presentationKey, payload, this.transport, correlationId);
33235
33483
  }
33236
33484
  async listLinkedMethods(presentationKey) {
33237
33485
  assertHexIdentifier(presentationKey, "presentationKey");
33238
- return await this.transport.request("/user/linkedMethods", {
33486
+ return this.transport.request("/user/linkedMethods", {
33239
33487
  operation: "list-linked-methods",
33240
33488
  body: { presentationKey }
33241
33489
  });
@@ -33243,7 +33491,7 @@ var WABClient = class {
33243
33491
  async unlinkMethod(presentationKey, authMethodId) {
33244
33492
  assertHexIdentifier(presentationKey, "presentationKey");
33245
33493
  if (!Number.isSafeInteger(authMethodId) || authMethodId <= 0) throw new TypeError("authMethodId must be a positive safe integer.");
33246
- return await this.transport.request("/user/unlinkMethod", {
33494
+ return this.transport.request("/user/unlinkMethod", {
33247
33495
  operation: "unlink-method",
33248
33496
  body: {
33249
33497
  presentationKey,
@@ -33253,14 +33501,14 @@ var WABClient = class {
33253
33501
  }
33254
33502
  async requestFaucet(presentationKey) {
33255
33503
  assertHexIdentifier(presentationKey, "presentationKey");
33256
- return await this.transport.request("/faucet/request", {
33504
+ return this.transport.request("/faucet/request", {
33257
33505
  operation: "request-faucet",
33258
33506
  body: { presentationKey }
33259
33507
  });
33260
33508
  }
33261
33509
  async deleteUser(presentationKey) {
33262
33510
  assertHexIdentifier(presentationKey, "presentationKey");
33263
- return await this.transport.request("/user/delete", {
33511
+ return this.transport.request("/user/delete", {
33264
33512
  operation: "delete-user",
33265
33513
  body: { presentationKey }
33266
33514
  });
@@ -33269,7 +33517,7 @@ var WABClient = class {
33269
33517
  assertMethodType(methodType);
33270
33518
  assertHexIdentifier(userIdHash, "userIdHash");
33271
33519
  const normalizedPayload = normalizeAuthPayload(methodType, payload);
33272
- return await this.transport.request("/auth/start", {
33520
+ return this.transport.request("/auth/start", {
33273
33521
  operation: "start-share-auth",
33274
33522
  body: {
33275
33523
  methodType,
@@ -33282,7 +33530,7 @@ var WABClient = class {
33282
33530
  assertMethodType(methodType);
33283
33531
  assertHexIdentifier(userIdHash, "userIdHash");
33284
33532
  const normalizedPayload = normalizeAuthPayload(methodType, payload);
33285
- return await this.transport.request("/share/store", {
33533
+ return this.transport.request("/share/store", {
33286
33534
  operation: "store-share",
33287
33535
  body: {
33288
33536
  methodType,
@@ -33296,7 +33544,7 @@ var WABClient = class {
33296
33544
  assertMethodType(methodType);
33297
33545
  assertHexIdentifier(userIdHash, "userIdHash");
33298
33546
  const normalizedPayload = normalizeAuthPayload(methodType, payload);
33299
- return await this.transport.request("/share/retrieve", {
33547
+ return this.transport.request("/share/retrieve", {
33300
33548
  operation: "retrieve-share",
33301
33549
  body: {
33302
33550
  methodType,
@@ -33309,7 +33557,7 @@ var WABClient = class {
33309
33557
  assertMethodType(methodType);
33310
33558
  assertHexIdentifier(userIdHash, "userIdHash");
33311
33559
  const normalizedPayload = normalizeAuthPayload(methodType, payload);
33312
- return await this.transport.request("/share/update", {
33560
+ return this.transport.request("/share/update", {
33313
33561
  operation: "update-share",
33314
33562
  body: {
33315
33563
  methodType,
@@ -33323,7 +33571,7 @@ var WABClient = class {
33323
33571
  assertMethodType(methodType);
33324
33572
  assertHexIdentifier(userIdHash, "userIdHash");
33325
33573
  const normalizedPayload = normalizeAuthPayload(methodType, payload);
33326
- return await this.transport.request("/share/delete", {
33574
+ return this.transport.request("/share/delete", {
33327
33575
  operation: "delete-share-user",
33328
33576
  body: {
33329
33577
  methodType,
@@ -33337,9 +33585,13 @@ var WABClient = class {
33337
33585
  //#region ../src/WalletAuthenticationManager.ts
33338
33586
  const DEFAULT_AUTH_SESSION_TTL_MS = 600 * 1e3;
33339
33587
  const MAX_AUTH_SESSION_TTL_MS = 3600 * 1e3;
33588
+ const AUTH_COMPONENT = "wallet-toolbox.authentication-manager";
33589
+ const AUTH_EVENT = "wallet-toolbox.authentication.";
33590
+ const EXISTING_USER = "existing-user";
33591
+ const NEW_USER = "new-user";
33340
33592
  var WABAccountContinuityError = class extends Error {
33341
33593
  code = "WERR_WAB_ACCOUNT_CONTINUITY";
33342
- constructor(message = "WAB and UMP account state did not agree. Retry or use account recovery.") {
33594
+ constructor(message = "WAB and UMP accounts disagree; retry or recover.") {
33343
33595
  super(message);
33344
33596
  this.name = "WABAccountContinuityError";
33345
33597
  }
@@ -33354,6 +33606,7 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33354
33606
  wabClient;
33355
33607
  authMethod;
33356
33608
  authSession;
33609
+ phoneChangeSession;
33357
33610
  authSessionTtlMs;
33358
33611
  constructor(...[adminOriginator, walletBuilder, interactor, recoveryKeySaver, passwordRetriever, wabClient, authMethod, stateSnapshot, options = {}]) {
33359
33612
  super(adminOriginator, walletBuilder, interactor, recoveryKeySaver, passwordRetriever, async (presentationKey, wallet, adminOriginator) => {
@@ -33376,7 +33629,7 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33376
33629
  description: "Fund wallet",
33377
33630
  options: { acceptDelayedBroadcast: false }
33378
33631
  }, adminOriginator);
33379
- if (faucetRedeemTXCreationResult.signableTransaction == null) throw new Error("Faucet redemption did not return a signableTransaction");
33632
+ if (faucetRedeemTXCreationResult.signableTransaction == null) throw new Error("Faucet redemption was not signable.");
33380
33633
  const faucetRedeemTX = Transaction.fromAtomicBEEF(faucetRedeemTXCreationResult.signableTransaction.tx);
33381
33634
  const faucetRedemptionPuzzle = new RPuzzle();
33382
33635
  const randomRedemptionPrivateKey = PrivateKey.fromRandom();
@@ -33409,7 +33662,7 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33409
33662
  * using the chosen AuthMethodInteractor.
33410
33663
  */
33411
33664
  async startAuth(payload) {
33412
- if (this.authMethod == null) throw new Error("No AuthMethod selected in WalletAuthenticationManager");
33665
+ if (this.authMethod == null) throw new Error("No WAB authentication method selected.");
33413
33666
  const authMethod = this.authMethod;
33414
33667
  if (this.authenticated) throw new Error("User is already authenticated");
33415
33668
  this.cancelAuth();
@@ -33422,8 +33675,8 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33422
33675
  ...correlationId !== void 0 ? { correlationId } : {}
33423
33676
  };
33424
33677
  this.telemetry.capture({
33425
- name: "wallet-toolbox.authentication.wab-start.started",
33426
- component: "wallet-toolbox.authentication-manager",
33678
+ name: `${AUTH_EVENT}wab-start.started`,
33679
+ component: AUTH_COMPONENT,
33427
33680
  severity: "debug",
33428
33681
  correlationId,
33429
33682
  attributes: { methodType: authMethod.methodType }
@@ -33435,8 +33688,8 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33435
33688
  throw new Error(message);
33436
33689
  }
33437
33690
  this.telemetry.capture({
33438
- name: "wallet-toolbox.authentication.wab-start.completed",
33439
- component: "wallet-toolbox.authentication-manager",
33691
+ name: `${AUTH_EVENT}wab-start.completed`,
33692
+ component: AUTH_COMPONENT,
33440
33693
  severity: "info",
33441
33694
  correlationId,
33442
33695
  attributes: { methodType: authMethod.methodType }
@@ -33444,8 +33697,8 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33444
33697
  } catch (error) {
33445
33698
  this.cancelAuth();
33446
33699
  this.telemetry.capture({
33447
- name: "wallet-toolbox.authentication.wab-start.failed",
33448
- component: "wallet-toolbox.authentication-manager",
33700
+ name: `${AUTH_EVENT}wab-start.failed`,
33701
+ component: AUTH_COMPONENT,
33449
33702
  severity: "warn",
33450
33703
  correlationId,
33451
33704
  attributes: { methodType: authMethod.methodType },
@@ -33458,22 +33711,22 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33458
33711
  * Completes the WAB-based flow, retrieving the final presentationKey from WAB if successful.
33459
33712
  */
33460
33713
  async completeAuth(payload) {
33461
- if (this.authMethod == null || this.authSession == null) throw new Error("No AuthMethod selected in WalletAuthenticationManager or startAuth has yet to be called.");
33714
+ if (this.authMethod == null || this.authSession == null) throw new Error("Start WAB authentication first.");
33462
33715
  const authMethod = this.authMethod;
33463
33716
  if (this.authSession.methodType !== authMethod.methodType) {
33464
33717
  this.cancelAuth();
33465
- throw new Error("The selected authentication method changed. Start authentication again.");
33718
+ throw new Error("WAB authentication method changed; restart.");
33466
33719
  }
33467
33720
  if (Date.now() >= this.authSession.expiresAt) {
33468
33721
  this.cancelAuth();
33469
- throw new Error("The WAB authentication session expired. Start authentication again.");
33722
+ throw new Error("WAB authentication expired; restart.");
33470
33723
  }
33471
33724
  const session = this.authSession;
33472
33725
  const result = await this.wabClient.completeAuthMethod(authMethod, session.presentationKey, payload, session.correlationId);
33473
33726
  if (result.success !== true || result.presentationKey == null || result.presentationKey.length === 0) {
33474
33727
  this.telemetry.capture({
33475
- name: "wallet-toolbox.authentication.wab-complete.rejected",
33476
- component: "wallet-toolbox.authentication-manager",
33728
+ name: `${AUTH_EVENT}wab-complete.rejected`,
33729
+ component: AUTH_COMPONENT,
33477
33730
  severity: "warn",
33478
33731
  correlationId: session.correlationId,
33479
33732
  attributes: { methodType: session.methodType }
@@ -33488,11 +33741,11 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33488
33741
  this.cancelAuth();
33489
33742
  const wabAccountStatus = this.inferAccountStatus(result, session.presentationKey);
33490
33743
  try {
33491
- await this.providePresentationKey(Utils.toArray(result.presentationKey, "hex"));
33744
+ await this.provideWABPresentationKey(result, wabAccountStatus);
33492
33745
  } catch (error) {
33493
33746
  this.telemetry.capture({
33494
- name: "wallet-toolbox.authentication.ump-continuity.failed",
33495
- component: "wallet-toolbox.authentication-manager",
33747
+ name: `${AUTH_EVENT}ump-continuity.failed`,
33748
+ component: AUTH_COMPONENT,
33496
33749
  severity: "warn",
33497
33750
  correlationId: session.correlationId,
33498
33751
  attributes: {
@@ -33503,18 +33756,18 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33503
33756
  });
33504
33757
  throw error;
33505
33758
  }
33506
- if (wabAccountStatus === "existing-user" && this.authenticationFlow !== "existing-user") {
33759
+ if (wabAccountStatus === EXISTING_USER && this.authenticationFlow !== EXISTING_USER) {
33507
33760
  super.destroy();
33508
33761
  const error = new WABAccountContinuityError();
33509
33762
  this.telemetry.capture({
33510
- name: "wallet-toolbox.authentication.account-continuity.mismatch",
33511
- component: "wallet-toolbox.authentication-manager",
33763
+ name: `${AUTH_EVENT}account-continuity.mismatch`,
33764
+ component: AUTH_COMPONENT,
33512
33765
  severity: "error",
33513
33766
  correlationId: session.correlationId,
33514
33767
  attributes: {
33515
33768
  methodType: session.methodType,
33516
33769
  wabAccountStatus,
33517
- umpAccountStatus: "new-user"
33770
+ umpAccountStatus: NEW_USER
33518
33771
  },
33519
33772
  error
33520
33773
  });
@@ -33522,8 +33775,8 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33522
33775
  }
33523
33776
  const continuity = wabAccountStatus === this.authenticationFlow ? "matched" : "ump-existing";
33524
33777
  this.telemetry.capture({
33525
- name: "wallet-toolbox.authentication.completed",
33526
- component: "wallet-toolbox.authentication-manager",
33778
+ name: `${AUTH_EVENT}completed`,
33779
+ component: AUTH_COMPONENT,
33527
33780
  severity: continuity === "matched" ? "info" : "warn",
33528
33781
  correlationId: session.correlationId,
33529
33782
  attributes: {
@@ -33537,23 +33790,131 @@ var WalletAuthenticationManager = class extends CWIStyleWalletManager {
33537
33790
  cancelAuth() {
33538
33791
  this.authSession = void 0;
33539
33792
  }
33793
+ readPendingPhoneChange(result) {
33794
+ const presentationKey = result.pendingPresentationKey;
33795
+ const changeId = result.pendingPhoneChangeId;
33796
+ if (presentationKey === void 0 && changeId === void 0) return void 0;
33797
+ if (!/^[0-9a-fA-F]{64}$/.test(presentationKey ?? "") || !Number.isSafeInteger(changeId) || changeId <= 0) throw new WABAccountContinuityError("WAB returned invalid pending phone-change data.");
33798
+ return {
33799
+ presentationKey,
33800
+ changeId
33801
+ };
33802
+ }
33803
+ async provideWABPresentationKey(result, wabAccountStatus) {
33804
+ const umpTokenOutpoint = typeof result.umpTokenOutpoint === "string" ? result.umpTokenOutpoint : void 0;
33805
+ const lookupOptions = umpTokenOutpoint == null ? void 0 : { pinnedOutpoint: umpTokenOutpoint };
33806
+ const pending = this.readPendingPhoneChange(result);
33807
+ let usePending = false;
33808
+ try {
33809
+ await this.providePresentationKey(Utils.toArray(result.presentationKey, "hex"), lookupOptions);
33810
+ } catch (error) {
33811
+ if (pending == null) throw error;
33812
+ usePending = true;
33813
+ }
33814
+ if (pending != null && (usePending || wabAccountStatus === EXISTING_USER && this.authenticationFlow !== EXISTING_USER)) {
33815
+ await this.providePresentationKey(Utils.toArray(pending.presentationKey, "hex"), lookupOptions);
33816
+ if (this.authenticationFlow === EXISTING_USER) await this.finalizePendingPhoneChange(result.presentationKey, pending);
33817
+ }
33818
+ }
33819
+ async finalizePendingPhoneChange(currentPresentationKey, pending) {
33820
+ const finalized = await this.phoneChange("finalize", {
33821
+ changeId: pending.changeId,
33822
+ presentationKey: currentPresentationKey,
33823
+ newPresentationKey: pending.presentationKey
33824
+ });
33825
+ if (finalized.success !== true || finalized.changeId !== pending.changeId) throw new WABAccountContinuityError(finalized.message || "WAB could not finalize the pending phone change.");
33826
+ }
33827
+ /**
33828
+ * Starts OTP verification for a replacement phone number. The same number
33829
+ * is valid and intentionally produces a fresh presentation key/hash.
33830
+ */
33831
+ async startPhoneNumberChange(phoneNumber) {
33832
+ if (!this.authenticated) throw new Error("Not authenticated");
33833
+ const normalizedPhone = phoneNumber.trim();
33834
+ const currentPresentationKey = Utils.toHex(await this.getFactor("presentationKey"));
33835
+ const response = await this.phoneChange("start", {
33836
+ presentationKey: currentPresentationKey,
33837
+ phoneNumber: normalizedPhone
33838
+ });
33839
+ if (response.success !== true) throw new Error(response.message || "Phone change failed");
33840
+ this.phoneChangeSession = {
33841
+ phoneNumber: normalizedPhone,
33842
+ presentationKey: currentPresentationKey
33843
+ };
33844
+ }
33845
+ /**
33846
+ * Completes phone verification and stages the WAB association before
33847
+ * publishing the UMP key rotation. WAB retains both the current and pending
33848
+ * presentation keys until finalization, so either side of an interrupted
33849
+ * transition remains recoverable on the next verified login.
33850
+ */
33851
+ async completePhoneNumberChange(otp) {
33852
+ const session = this.phoneChangeSession;
33853
+ if (session == null) throw new Error("No phone change");
33854
+ if (session.changeToken == null) {
33855
+ const authorization = await this.phoneChange("complete", {
33856
+ presentationKey: session.presentationKey,
33857
+ phoneNumber: session.phoneNumber,
33858
+ otp: otp.trim()
33859
+ });
33860
+ if (authorization.success !== true) throw new Error(authorization.message || "Phone change failed");
33861
+ if (/^[0-9a-fA-F]{64}$/.test(authorization.pendingPresentationKey ?? "") && Number.isSafeInteger(authorization.pendingPhoneChangeId) && authorization.pendingPhoneChangeId > 0) {
33862
+ session.newKey = Utils.toArray(authorization.pendingPresentationKey, "hex");
33863
+ session.changeId = authorization.pendingPhoneChangeId;
33864
+ } else if (typeof authorization.changeToken === "string" && authorization.changeToken.length > 0) session.changeToken = authorization.changeToken;
33865
+ else throw new Error(authorization.message || "Phone change failed");
33866
+ }
33867
+ session.newKey ??= Random(32);
33868
+ if (session.changeId == null) {
33869
+ const committed = await this.phoneChange("commit", {
33870
+ changeToken: session.changeToken,
33871
+ presentationKey: session.presentationKey,
33872
+ newPresentationKey: Utils.toHex(session.newKey)
33873
+ });
33874
+ if (committed.success !== true || !Number.isSafeInteger(committed.changeId) || committed.changeId <= 0) throw new Error(committed.message || "Phone change failed");
33875
+ session.changeId = committed.changeId;
33876
+ }
33877
+ const changeId = session.changeId;
33878
+ if (session.umpUpdated !== true) {
33879
+ await this.changePresentationKey(session.newKey);
33880
+ session.umpUpdated = true;
33881
+ }
33882
+ const finalized = await this.phoneChange("finalize", {
33883
+ changeId,
33884
+ presentationKey: session.presentationKey,
33885
+ newPresentationKey: Utils.toHex(session.newKey)
33886
+ });
33887
+ if (finalized.success !== true || finalized.changeId !== changeId) throw new Error(finalized.message || "Phone change failed");
33888
+ this.phoneChangeSession = void 0;
33889
+ return { changeId };
33890
+ }
33891
+ cancelPhoneNumberChange() {
33892
+ this.phoneChangeSession = void 0;
33893
+ }
33540
33894
  destroy() {
33541
33895
  this.cancelAuth();
33896
+ this.cancelPhoneNumberChange();
33542
33897
  super.destroy();
33543
33898
  }
33899
+ phoneChange(phase, body) {
33900
+ return this.wabClient.transport.request(`/auth/phone-change/${phase}`, {
33901
+ operation: "phone-change",
33902
+ body
33903
+ });
33904
+ }
33544
33905
  inferAccountStatus(result, temporaryPresentationKey) {
33545
33906
  if (result.presentationKey == null) throw new WABAccountContinuityError("WAB did not return a presentation key.");
33546
33907
  const keyMatchesTemporary = this.constantTimeHexEqual(result.presentationKey, temporaryPresentationKey);
33547
33908
  const rawAccountStatus = result.accountStatus;
33548
- if (rawAccountStatus !== void 0 && rawAccountStatus !== "new-user" && rawAccountStatus !== "existing-user") throw new WABAccountContinuityError("WAB returned an invalid account-continuity status.");
33909
+ if (rawAccountStatus !== void 0 && rawAccountStatus !== NEW_USER && rawAccountStatus !== EXISTING_USER) throw new WABAccountContinuityError("WAB returned an invalid account status.");
33549
33910
  const rawExistingUser = result.existingUser;
33550
- if (rawExistingUser !== void 0 && typeof rawExistingUser !== "boolean") throw new WABAccountContinuityError("WAB returned an invalid existing-user status.");
33551
- if (rawAccountStatus !== void 0 && rawExistingUser !== void 0 && rawAccountStatus === "existing-user" !== rawExistingUser) throw new WABAccountContinuityError("WAB returned contradictory account-continuity statuses.");
33911
+ if (rawExistingUser !== void 0 && typeof rawExistingUser !== "boolean") throw new WABAccountContinuityError("WAB returned invalid existing-user data.");
33912
+ if (rawAccountStatus !== void 0 && rawExistingUser !== void 0 && rawAccountStatus === EXISTING_USER !== rawExistingUser) throw new WABAccountContinuityError("WAB returned conflicting account status.");
33552
33913
  let compatibilityStatus;
33553
- if (typeof rawExistingUser === "boolean") compatibilityStatus = rawExistingUser ? "existing-user" : "new-user";
33914
+ if (typeof rawExistingUser === "boolean") compatibilityStatus = rawExistingUser ? EXISTING_USER : NEW_USER;
33554
33915
  const explicitStatus = rawAccountStatus ?? compatibilityStatus;
33555
- if (explicitStatus === "new-user" && !keyMatchesTemporary || explicitStatus === "existing-user" && keyMatchesTemporary) throw new WABAccountContinuityError("WAB returned contradictory account-continuity data.");
33556
- return explicitStatus ?? (keyMatchesTemporary ? "new-user" : "existing-user");
33916
+ if (explicitStatus === NEW_USER && !keyMatchesTemporary || explicitStatus === EXISTING_USER && keyMatchesTemporary) throw new WABAccountContinuityError("WAB returned conflicting account status.");
33917
+ return explicitStatus ?? (keyMatchesTemporary ? NEW_USER : EXISTING_USER);
33557
33918
  }
33558
33919
  constantTimeHexEqual(left, right) {
33559
33920
  if (left.length !== right.length) return false;
@@ -36781,6 +37142,6 @@ var WalletPermissionsManager = class WalletPermissionsManager {
36781
37142
  }
36782
37143
  };
36783
37144
  //#endregion
36784
- export { ARGON2ID_DEFAULT_HASH_LENGTH, ARGON2ID_DEFAULT_ITERATIONS, ARGON2ID_DEFAULT_MEMORY_KIB, ARGON2ID_DEFAULT_PARALLELISM, ARGON2ID_MAX_ITERATIONS, ARGON2ID_MAX_MEMORY_KIB, ARGON2ID_MAX_PARALLELISM, AuthMethodInteractor, BHServiceClient, BRC153_REFERENCE_PREFIX, BulkFileDataManager, BulkFileDataReader, BulkFilesReader, BulkFilesReaderFs, BulkFilesReaderStorage, BulkHeaderFile, BulkHeaderFileFs, BulkHeaderFileStorage, BulkHeaderFiles, BulkIngestorBase, BulkIngestorCDN, BulkIngestorCDNBabbage, BulkIngestorChaintracks, BulkIngestorWhatsOnChainCdn, BulkStorageBase, CWIStyleWalletManager, Chaintracks, ChaintracksChainTracker, ChaintracksFetch, ChaintracksFetchError, ChaintracksServiceClient, ChaintracksStorageBase, ChaintracksStorageIdb, ChaintracksStorageNoDb, DEFAULT_MANAGED_CHANGE_MAX_OUTPUTS_PER_ACTION, DEFAULT_MANAGED_CHANGE_MIGRATION_INPUTS_PER_ACTION, DEFAULT_MANAGED_CHANGE_MINIMUM_SATOSHIS, DEFAULT_MANAGED_CHANGE_PENDING_COMPARISON_INPUTS, DEFAULT_MANAGED_CHANGE_TARGET_UTXOS, DEFAULT_PROFILE_ID, DEFAULT_SETTINGS, DevConsoleInteractor, EntityBase, EntityCertificate, EntityCertificateField, EntityCommission, EntityOutput, EntityOutputBasket, EntityOutputTag, EntityOutputTagMap, EntityProvenTx, EntityProvenTxReq, EntitySyncState, EntityTransaction, EntityTxLabel, EntityTxLabelMap, EntityUser, FixedWindowBulkFileDownloadBudget, GoChaintracksServiceClient, HeightRange, KDF_MAX_HASH_LENGTH, LEGACY_MANAGED_CHANGE_MINIMUM_SATOSHIS, LiveIngestorBase, LiveIngestorChaintracksSSE, LiveIngestorWhatsOnChainPoll, LocalChainTracker, MAX_STATE_SNAPSHOT_BYTES, MergeEntity, Monitor, OverlayUMPTokenInteractor, PBKDF2_MAX_ITERATIONS, PBKDF2_NUM_ROUNDS, PersonaIDInteractor, PrivilegedKeyManager, ScriptTemplateBRC29, Services, SetupClient, SimpleWalletManager, StorageClient, StorageIdb, StorageProvider, StorageSyncReader, TESTNET_DEFAULT_SETTINGS, TwilioPhoneInteractor, UMPTokenLookupError, WABAccountContinuityError, WABClient, WABClientError, WABTransport, Wallet, WalletAuthenticationManager, WalletLogger, WalletPermissionsManager, WalletSettingsManager, WalletSigner, WalletStorageManager, WhatsOnChainServices, applyBrc153ReferenceLabel, arcDefaultUrl, arcGorillaPoolUrl, arcadeDefaultUrl, arraysEqual, asArray, asBsvSdkPrivateKey, asBsvSdkPublickKey, asBsvSdkScript, asBsvSdkTx, asString, asUint8Array, brc29ProtocolID, buildChaintracksOptionsWithIngestors, convertProofToMerklePath, createAndStartDefaultChaintracks, createDefaultBulkFileDataManager, createDefaultChaintracksClient, createDefaultChaintracksStorageOptions, createDefaultIdbChaintracksOptions, createDefaultNoDbChaintracksOptions, createDefaultWalletServicesOptions, createIdbChaintracks, createNoDbChaintracks, createSyncMap, decryptBRC39, defaultManagedChangePolicy, doubleSha256BE, doubleSha256LE, encryptBRC39, exportBRC38, exportBRC38Json, exportBRC39, getIdentityKey, getLabelToSpecOp, getListOutputsSpecOp, importBRC38, importBRC39, isAutoSpendableChangeOutput, isBaseBlockHeader, isBlockHeader, isBrc153ReferenceLabel, isLegacyManagedChangeBasketDefault, isLive, isLiveBlockHeader, isManagedChangeOutput, logCreateActionArgs, logWalletError, logger, makeAtomicBeef, makeBrc114ActionTimeLabel, makeBrc153ReferenceLabel, managedChangeOutputFields, maxDate, optionalArraysEqual, outputColumnsWithoutLockingScript, parseBRC38Json, parseBrc114ActionTimeLabels, parseBrc153ReferenceLabel, parseFileLink, parseTxScriptOffsets, partitionActionLabels, randomBytes, randomBytesBase64, randomBytesHex, resolveDefaultChaintracksArguments, sdk_exports as sdk, selectBulkHeaderFiles, sha256Hash, stampLog, stampLogFormat, startChaintracks, tableAuthSessionToPeerSession, throwDummyReviewActions, toBinaryBaseBlockHeader, toDefaultChaintracksArguments, toLookupNetworkPreset, toWalletNetwork, transactionColumnsWithoutRawTx, upgradeLegacyManagedChangeBasketDefault, blockHeaderUtilities_exports as utils, validateManagedChangePolicy, validateScriptHash, validateSecondsSinceEpoch, validateStorageFeeModel, verifyHexString, verifyId, verifyInteger, verifyNumber, verifyOne, verifyOneOrNone, verifyOptionalHexString, verifyTruthy, wait, wocGetHeadersHeaderToBlockHeader };
37145
+ export { ARGON2ID_DEFAULT_HASH_LENGTH, ARGON2ID_DEFAULT_ITERATIONS, ARGON2ID_DEFAULT_MEMORY_KIB, ARGON2ID_DEFAULT_PARALLELISM, ARGON2ID_MAX_ITERATIONS, ARGON2ID_MAX_MEMORY_KIB, ARGON2ID_MAX_PARALLELISM, AuthMethodInteractor, BHServiceClient, BRC153_REFERENCE_PREFIX, BulkFileDataManager, BulkFileDataReader, BulkFileDataValidationError, BulkFilesReader, BulkFilesReaderFs, BulkFilesReaderStorage, BulkHeaderFile, BulkHeaderFileFs, BulkHeaderFileStorage, BulkHeaderFiles, BulkIngestorBase, BulkIngestorCDN, BulkIngestorCDNBabbage, BulkIngestorChaintracks, BulkIngestorWhatsOnChainCdn, BulkStorageBase, CWIStyleWalletManager, Chaintracks, ChaintracksChainTracker, ChaintracksFetch, ChaintracksFetchError, ChaintracksServiceClient, ChaintracksStorageBase, ChaintracksStorageIdb, ChaintracksStorageNoDb, DEFAULT_MANAGED_CHANGE_MAX_OUTPUTS_PER_ACTION, DEFAULT_MANAGED_CHANGE_MIGRATION_INPUTS_PER_ACTION, DEFAULT_MANAGED_CHANGE_MINIMUM_SATOSHIS, DEFAULT_MANAGED_CHANGE_PENDING_COMPARISON_INPUTS, DEFAULT_MANAGED_CHANGE_TARGET_UTXOS, DEFAULT_PROFILE_ID, DEFAULT_SETTINGS, DevConsoleInteractor, EntityBase, EntityCertificate, EntityCertificateField, EntityCommission, EntityOutput, EntityOutputBasket, EntityOutputTag, EntityOutputTagMap, EntityProvenTx, EntityProvenTxReq, EntitySyncState, EntityTransaction, EntityTxLabel, EntityTxLabelMap, EntityUser, FixedWindowBulkFileDownloadBudget, GoChaintracksServiceClient, HeightRange, InlineBulkFileDataValidator, KDF_MAX_HASH_LENGTH, LEGACY_MANAGED_CHANGE_MINIMUM_SATOSHIS, LiveIngestorBase, LiveIngestorChaintracksSSE, LiveIngestorWhatsOnChainPoll, LocalChainTracker, MAX_STATE_SNAPSHOT_BYTES, MergeEntity, Monitor, OverlayUMPTokenInteractor, PBKDF2_MAX_ITERATIONS, PBKDF2_NUM_ROUNDS, PersonaIDInteractor, PrivilegedKeyManager, ScriptTemplateBRC29, Services, SetupClient, SimpleWalletManager, StorageClient, StorageIdb, StorageProvider, StorageSyncReader, TESTNET_DEFAULT_SETTINGS, TwilioPhoneInteractor, UMPTokenLookupError, WABAccountContinuityError, WABClient, WABClientError, WABTransport, Wallet, WalletAuthenticationManager, WalletLogger, WalletPermissionsManager, WalletSettingsManager, WalletSigner, WalletStorageManager, WhatsOnChainServices, applyBrc153ReferenceLabel, arcDefaultUrl, arcGorillaPoolUrl, arcadeDefaultUrl, arraysEqual, asArray, asBsvSdkPrivateKey, asBsvSdkPublickKey, asBsvSdkScript, asBsvSdkTx, asString, asUint8Array, brc29ProtocolID, buildChaintracksOptionsWithIngestors, convertProofToMerklePath, createAndStartDefaultChaintracks, createDefaultBulkFileDataManager, createDefaultChaintracksClient, createDefaultChaintracksStorageOptions, createDefaultIdbChaintracksOptions, createDefaultNoDbChaintracksOptions, createDefaultWalletServicesOptions, createIdbChaintracks, createNoDbChaintracks, createSyncMap, decryptBRC39, defaultManagedChangePolicy, doubleSha256BE, doubleSha256LE, encryptBRC39, exportBRC38, exportBRC38Json, exportBRC39, getIdentityKey, getLabelToSpecOp, getListOutputsSpecOp, importBRC38, importBRC39, isAutoSpendableChangeOutput, isBaseBlockHeader, isBlockHeader, isBrc153ReferenceLabel, isLegacyManagedChangeBasketDefault, isLive, isLiveBlockHeader, isManagedChangeOutput, logCreateActionArgs, logWalletError, logger, makeAtomicBeef, makeBrc114ActionTimeLabel, makeBrc153ReferenceLabel, managedChangeOutputFields, maxDate, optionalArraysEqual, outputColumnsWithoutLockingScript, parseBRC38Json, parseBrc114ActionTimeLabels, parseBrc153ReferenceLabel, parseFileLink, parseTxScriptOffsets, partitionActionLabels, randomBytes, randomBytesBase64, randomBytesHex, resolveDefaultChaintracksArguments, sdk_exports as sdk, selectBulkHeaderFiles, sha256Hash, stampLog, stampLogFormat, startChaintracks, tableAuthSessionToPeerSession, throwDummyReviewActions, toBinaryBaseBlockHeader, toDefaultChaintracksArguments, toLookupNetworkPreset, toWalletNetwork, transactionColumnsWithoutRawTx, upgradeLegacyManagedChangeBasketDefault, blockHeaderUtilities_exports as utils, validateManagedChangePolicy, validateScriptHash, validateSecondsSinceEpoch, validateStorageFeeModel, verifyHexString, verifyId, verifyInteger, verifyNumber, verifyOne, verifyOneOrNone, verifyOptionalHexString, verifyTruthy, wait, wocGetHeadersHeaderToBlockHeader };
36785
37146
 
36786
37147
  //# sourceMappingURL=index.client.mjs.map