@arkade-os/sdk 0.4.44 → 0.4.45
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.
- package/README.md +35 -0
- package/dist/adapters/expo.cjs +4 -4
- package/dist/adapters/expo.d.cts +2 -2
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +2 -2
- package/dist/adapters/indexedDB.cjs +3 -3
- package/dist/adapters/indexedDB.js +2 -2
- package/dist/{ark-I8jfe5VE.d.cts → ark-C-PjOngm.d.cts} +89 -1
- package/dist/{ark-I8jfe5VE.d.ts → ark-C-PjOngm.d.ts} +89 -1
- package/dist/{asyncStorageTaskQueue-Dap7qUlF.d.cts → asyncStorageTaskQueue-BmBPvTyh.d.cts} +2 -2
- package/dist/{asyncStorageTaskQueue-BtSOVZFn.d.ts → asyncStorageTaskQueue-CHpI3moJ.d.ts} +2 -2
- package/dist/{chunk-V7WIZR2B.js → chunk-BOA4SHCD.js} +3 -3
- package/dist/{chunk-V7WIZR2B.js.map → chunk-BOA4SHCD.js.map} +1 -1
- package/dist/{chunk-X37EKDIH.cjs → chunk-HZ7VIN7P.cjs} +11 -11
- package/dist/{chunk-X37EKDIH.cjs.map → chunk-HZ7VIN7P.cjs.map} +1 -1
- package/dist/{chunk-RJ6XVCX4.cjs → chunk-OFQGANH2.cjs} +7 -7
- package/dist/{chunk-RJ6XVCX4.cjs.map → chunk-OFQGANH2.cjs.map} +1 -1
- package/dist/{chunk-LCQQPOIT.js → chunk-QZ6HZZZK.js} +3 -3
- package/dist/{chunk-LCQQPOIT.js.map → chunk-QZ6HZZZK.js.map} +1 -1
- package/dist/{chunk-XIVCG6EP.cjs → chunk-SRCWBFSZ.cjs} +1000 -322
- package/dist/chunk-SRCWBFSZ.cjs.map +1 -0
- package/dist/{chunk-FMI2GKYO.js → chunk-TGRJ5WAX.js} +919 -243
- package/dist/chunk-TGRJ5WAX.js.map +1 -0
- package/dist/{chunk-UBYY2TPK.cjs → chunk-UHOHLN3C.cjs} +119 -69
- package/dist/chunk-UHOHLN3C.cjs.map +1 -0
- package/dist/{chunk-LJ35HPJW.js → chunk-YBQV7XBC.js} +119 -70
- package/dist/chunk-YBQV7XBC.js.map +1 -0
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/{delegate-CgjVjYOP.d.ts → delegate-BKNqva1j.d.ts} +1 -1
- package/dist/{delegate-BRqbh2fW.d.cts → delegate-DOEobYwH.d.cts} +1 -1
- package/dist/{index-DHuXlDEg.d.cts → index-BlW4I30l.d.cts} +2 -2
- package/dist/{index-DvWNB_rl.d.ts → index-Cm2fGeox.d.ts} +2 -2
- package/dist/index.cjs +141 -129
- package/dist/index.d.cts +45 -20
- package/dist/index.d.ts +45 -20
- package/dist/index.js +2 -2
- package/dist/repositories/realm/index.cjs +17 -17
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/realm/index.js +3 -3
- package/dist/repositories/sqlite/index.cjs +16 -16
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.js +3 -3
- package/dist/{taskRunner-Bptw9UMa.d.ts → taskRunner-BngWSFMi.d.ts} +2 -2
- package/dist/{taskRunner-CeFxKhSH.d.cts → taskRunner-DOiyRuJa.d.cts} +2 -2
- package/dist/wallet/expo/background.cjs +12 -12
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +4 -4
- package/dist/wallet/expo/index.cjs +21 -12
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +11 -4
- package/dist/wallet/expo/index.d.ts +11 -4
- package/dist/wallet/expo/index.js +12 -3
- package/dist/wallet/expo/index.js.map +1 -1
- package/dist/{wallet-BsqRU8KM.d.cts → wallet-B3awP1Nj.d.ts} +105 -3
- package/dist/{wallet-D9z7wssl.d.ts → wallet-DBjumS42.d.cts} +105 -3
- package/dist/worker/expo/index.cjs +7 -7
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-FMI2GKYO.js.map +0 -1
- package/dist/chunk-LJ35HPJW.js.map +0 -1
- package/dist/chunk-UBYY2TPK.cjs.map +0 -1
- package/dist/chunk-XIVCG6EP.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, baseFetch, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-
|
|
1
|
+
import { craftToSpendTx, Transaction, OP_RETURN_EMPTY_PKSCRIPT, baseFetch, Intent, getArkPsbtFields, CosignerPublicKey, setArkPsbtField, VtxoTaprootTree, maybeArkError, ProviderUnavailableError, FetchError, isFetchTimeoutError, AssetRef, AssetId, AssetOutput, AssetGroup, AssetInput, Packet, Metadata, isEventSourceError, RestArkProvider, RestIndexerProvider, ArkError, BufferReader } from './chunk-YBQV7XBC.js';
|
|
2
2
|
import { contractHandlers, isMainnetDescriptor, descriptorIsOurs, DEFAULT_PAGE_SIZE, DelegateVtxo, WALLET_RECEIVE_SOURCE, deriveDescriptorLeafPubKey, DefaultVtxo, BoardingContractHandler } from './chunk-YNEDJTX2.js';
|
|
3
3
|
import { VtxoScript, sequenceToTimelock, timelockToSequence, DEFAULT_NETWORK, DEFAULT_NETWORK_NAME, decodeTapscript, scriptFromTapLeafScript, CLTVMultisigTapscript, ArkAddress, CSVMultisigTapscript, getSequence, getNetwork, MultisigTapscript, networks as networks$1, DEFAULT_ARKADE_SERVER_URL } from './chunk-BE5MUB7T.js';
|
|
4
4
|
import { sha256, hash160, sha256x2, concatBytes, randomPrivateKeyBytes, pubECDSA, pubSchnorr, equalBytes as equalBytes$1 } from '@scure/btc-signer/utils.js';
|
|
@@ -4287,6 +4287,592 @@ function wrapHandlerWithIntentPersistence(base, deps) {
|
|
|
4287
4287
|
}
|
|
4288
4288
|
};
|
|
4289
4289
|
}
|
|
4290
|
+
|
|
4291
|
+
// src/repositories/virtualTxRepository.ts
|
|
4292
|
+
var ChainedTxType = /* @__PURE__ */ ((ChainedTxType2) => {
|
|
4293
|
+
ChainedTxType2[ChainedTxType2["Unspecified"] = 0] = "Unspecified";
|
|
4294
|
+
ChainedTxType2[ChainedTxType2["Commitment"] = 1] = "Commitment";
|
|
4295
|
+
ChainedTxType2[ChainedTxType2["Ark"] = 2] = "Ark";
|
|
4296
|
+
ChainedTxType2[ChainedTxType2["Tree"] = 3] = "Tree";
|
|
4297
|
+
ChainedTxType2[ChainedTxType2["Checkpoint"] = 4] = "Checkpoint";
|
|
4298
|
+
return ChainedTxType2;
|
|
4299
|
+
})(ChainedTxType || {});
|
|
4300
|
+
function mergeChainedTxType(incoming, prev) {
|
|
4301
|
+
if (incoming !== 0 /* Unspecified */) return incoming;
|
|
4302
|
+
return prev ?? 0 /* Unspecified */;
|
|
4303
|
+
}
|
|
4304
|
+
|
|
4305
|
+
// src/wallet/exit/chain.ts
|
|
4306
|
+
var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
4307
|
+
async function buildExitDag(params) {
|
|
4308
|
+
const byTxid = /* @__PURE__ */ new Map();
|
|
4309
|
+
for (const vtxo of params.vtxos) {
|
|
4310
|
+
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
4311
|
+
const chain = await params.chain.getVtxoChain({ txid: vtxo.txid, vout: vtxo.vout });
|
|
4312
|
+
for (const chainTx of chain) {
|
|
4313
|
+
const existing = byTxid.get(chainTx.txid);
|
|
4314
|
+
if (existing) {
|
|
4315
|
+
existing.forVtxos.add(outpoint);
|
|
4316
|
+
} else {
|
|
4317
|
+
byTxid.set(chainTx.txid, { ...chainTx, forVtxos: /* @__PURE__ */ new Set([outpoint]) });
|
|
4318
|
+
}
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
const pending = new Map(
|
|
4322
|
+
[...byTxid.values()].filter((tx) => !isCommitment(tx.type)).map((tx) => [tx.txid, tx])
|
|
4323
|
+
);
|
|
4324
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
4325
|
+
for (const tx of pending.values()) {
|
|
4326
|
+
const parents = tx.spends.filter((p) => pending.has(p));
|
|
4327
|
+
inDegree.set(tx.txid, parents.length);
|
|
4328
|
+
}
|
|
4329
|
+
const order = [];
|
|
4330
|
+
const queue = [...pending.values()].filter((tx) => inDegree.get(tx.txid) === 0).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
4331
|
+
while (queue.length > 0) {
|
|
4332
|
+
const tx = queue.shift();
|
|
4333
|
+
order.push(tx);
|
|
4334
|
+
const children = [...pending.values()].filter((c) => c.spends.includes(tx.txid)).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
4335
|
+
for (const child of children) {
|
|
4336
|
+
const deg = inDegree.get(child.txid) - 1;
|
|
4337
|
+
inDegree.set(child.txid, deg);
|
|
4338
|
+
if (deg === 0) queue.push(child);
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
if (order.length !== pending.size) {
|
|
4342
|
+
throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
|
|
4343
|
+
}
|
|
4344
|
+
const nodes = [];
|
|
4345
|
+
for (const tx of order) {
|
|
4346
|
+
let confirmed = false;
|
|
4347
|
+
try {
|
|
4348
|
+
const status = await params.onchain.getTxStatus(tx.txid);
|
|
4349
|
+
confirmed = status.confirmed;
|
|
4350
|
+
} catch {
|
|
4351
|
+
confirmed = false;
|
|
4352
|
+
}
|
|
4353
|
+
const expires = Number(tx.expiresAt);
|
|
4354
|
+
nodes.push({
|
|
4355
|
+
txid: tx.txid,
|
|
4356
|
+
type: tx.type,
|
|
4357
|
+
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
|
|
4358
|
+
forVtxos: [...tx.forVtxos].sort(),
|
|
4359
|
+
confirmed
|
|
4360
|
+
});
|
|
4361
|
+
}
|
|
4362
|
+
return nodes;
|
|
4363
|
+
}
|
|
4364
|
+
function topoSortByDeps(items, idOf, depsOf) {
|
|
4365
|
+
const produced = new Set(items.map(idOf));
|
|
4366
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4367
|
+
const ordered = [];
|
|
4368
|
+
let remaining = items;
|
|
4369
|
+
while (remaining.length > 0) {
|
|
4370
|
+
const next = [];
|
|
4371
|
+
let progress = false;
|
|
4372
|
+
for (const item of remaining) {
|
|
4373
|
+
if (depsOf(item).every((d) => !produced.has(d) || emitted.has(d))) {
|
|
4374
|
+
ordered.push(item);
|
|
4375
|
+
emitted.add(idOf(item));
|
|
4376
|
+
progress = true;
|
|
4377
|
+
} else {
|
|
4378
|
+
next.push(item);
|
|
4379
|
+
}
|
|
4380
|
+
}
|
|
4381
|
+
if (!progress) {
|
|
4382
|
+
throw new Error("topological sort: cycle or unsatisfiable dependency");
|
|
4383
|
+
}
|
|
4384
|
+
remaining = next;
|
|
4385
|
+
}
|
|
4386
|
+
return ordered;
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
// src/wallet/exit/capture.ts
|
|
4390
|
+
var DEFAULT_MIN_EXIT_WORTH_SATS = 1e3;
|
|
4391
|
+
var DEFAULT_EXIT_CAPTURE_MODE = "lite";
|
|
4392
|
+
function chainTxTypeToChainedExit(t) {
|
|
4393
|
+
switch (t) {
|
|
4394
|
+
case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
|
|
4395
|
+
return 1 /* Commitment */;
|
|
4396
|
+
case "INDEXER_CHAINED_TX_TYPE_ARK" /* ARK */:
|
|
4397
|
+
return 2 /* Ark */;
|
|
4398
|
+
case "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */:
|
|
4399
|
+
return 3 /* Tree */;
|
|
4400
|
+
case "INDEXER_CHAINED_TX_TYPE_CHECKPOINT" /* CHECKPOINT */:
|
|
4401
|
+
return 4 /* Checkpoint */;
|
|
4402
|
+
default:
|
|
4403
|
+
return 0 /* Unspecified */;
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
function orderAncestryFirst(chain) {
|
|
4407
|
+
const ids = new Set(chain.map((c) => c.txid));
|
|
4408
|
+
return topoSortByDeps(
|
|
4409
|
+
chain,
|
|
4410
|
+
(c) => c.txid,
|
|
4411
|
+
(c) => c.spends.filter((s) => ids.has(s))
|
|
4412
|
+
);
|
|
4413
|
+
}
|
|
4414
|
+
async function captureExitBranch(params) {
|
|
4415
|
+
const { resolver, repository, vtxo, value, mode, minExitWorthSats } = params;
|
|
4416
|
+
if (value < minExitWorthSats) return;
|
|
4417
|
+
if (await repository.hasBranch(vtxo)) return;
|
|
4418
|
+
const ordered = orderAncestryFirst(await resolver.getVtxoChain(vtxo));
|
|
4419
|
+
const psbtByTxid = /* @__PURE__ */ new Map();
|
|
4420
|
+
if (mode === "full") {
|
|
4421
|
+
const nonCommitment = ordered.filter((c) => chainTxTypeToChainedExit(c.type) !== 1 /* Commitment */).map((c) => c.txid);
|
|
4422
|
+
if (nonCommitment.length > 0) {
|
|
4423
|
+
for (const psbt of await resolver.getVirtualTxs(nonCommitment)) {
|
|
4424
|
+
psbtByTxid.set(Transaction.fromPSBT(base64.decode(psbt)).id, psbt);
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
const virtualTxs = ordered.map((c) => {
|
|
4429
|
+
const expires = Number(c.expiresAt);
|
|
4430
|
+
return {
|
|
4431
|
+
txid: c.txid,
|
|
4432
|
+
psbt: psbtByTxid.get(c.txid) ?? null,
|
|
4433
|
+
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : null,
|
|
4434
|
+
type: chainTxTypeToChainedExit(c.type)
|
|
4435
|
+
};
|
|
4436
|
+
});
|
|
4437
|
+
const branch = ordered.map((c, i) => ({
|
|
4438
|
+
vtxoTxid: vtxo.txid,
|
|
4439
|
+
vtxoVout: vtxo.vout,
|
|
4440
|
+
virtualTxid: c.txid,
|
|
4441
|
+
position: i
|
|
4442
|
+
}));
|
|
4443
|
+
await repository.upsertVirtualTxs(virtualTxs);
|
|
4444
|
+
await repository.setBranch(vtxo, branch);
|
|
4445
|
+
}
|
|
4446
|
+
async function pruneExitBranches(repository, outpoints) {
|
|
4447
|
+
for (const outpoint of outpoints) {
|
|
4448
|
+
try {
|
|
4449
|
+
await repository.pruneForSpentVtxo(outpoint);
|
|
4450
|
+
} catch {
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
var IndexerExitDataSource = class {
|
|
4455
|
+
constructor(indexer) {
|
|
4456
|
+
this.indexer = indexer;
|
|
4457
|
+
}
|
|
4458
|
+
name = "indexer";
|
|
4459
|
+
async getVtxoChain(vtxo) {
|
|
4460
|
+
const chain = [];
|
|
4461
|
+
let pageIndex = 0;
|
|
4462
|
+
let hasMore = true;
|
|
4463
|
+
while (hasMore) {
|
|
4464
|
+
const { chain: page, page: meta } = await this.indexer.getVtxoChain(
|
|
4465
|
+
{ txid: vtxo.txid, vout: vtxo.vout },
|
|
4466
|
+
{ pageIndex, pageSize: DEFAULT_PAGE_SIZE }
|
|
4467
|
+
);
|
|
4468
|
+
chain.push(...page);
|
|
4469
|
+
hasMore = meta ? page.length === DEFAULT_PAGE_SIZE : false;
|
|
4470
|
+
pageIndex++;
|
|
4471
|
+
}
|
|
4472
|
+
return chain;
|
|
4473
|
+
}
|
|
4474
|
+
async getVirtualTxs(txids) {
|
|
4475
|
+
const out = /* @__PURE__ */ new Map();
|
|
4476
|
+
let pageIndex = 0;
|
|
4477
|
+
let hasMore = true;
|
|
4478
|
+
while (hasMore) {
|
|
4479
|
+
const { txs, page } = await this.indexer.getVirtualTxs(txids, {
|
|
4480
|
+
pageIndex,
|
|
4481
|
+
pageSize: DEFAULT_PAGE_SIZE
|
|
4482
|
+
});
|
|
4483
|
+
for (const psbt of txs) {
|
|
4484
|
+
out.set(Transaction.fromPSBT(base64.decode(psbt)).id, psbt);
|
|
4485
|
+
}
|
|
4486
|
+
hasMore = page ? txs.length === DEFAULT_PAGE_SIZE : false;
|
|
4487
|
+
pageIndex++;
|
|
4488
|
+
}
|
|
4489
|
+
return out;
|
|
4490
|
+
}
|
|
4491
|
+
};
|
|
4492
|
+
function chainedTxTypeToChainTxType(t) {
|
|
4493
|
+
switch (t) {
|
|
4494
|
+
case 1 /* Commitment */:
|
|
4495
|
+
return "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */;
|
|
4496
|
+
case 2 /* Ark */:
|
|
4497
|
+
return "INDEXER_CHAINED_TX_TYPE_ARK" /* ARK */;
|
|
4498
|
+
case 3 /* Tree */:
|
|
4499
|
+
return "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */;
|
|
4500
|
+
case 4 /* Checkpoint */:
|
|
4501
|
+
return "INDEXER_CHAINED_TX_TYPE_CHECKPOINT" /* CHECKPOINT */;
|
|
4502
|
+
default:
|
|
4503
|
+
return "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
function psbtInputTxids(psbtBase64) {
|
|
4507
|
+
const tx = Transaction.fromPSBT(base64.decode(psbtBase64));
|
|
4508
|
+
const ids = [];
|
|
4509
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
4510
|
+
const txid = tx.getInput(i).txid;
|
|
4511
|
+
if (txid) ids.push(hex.encode(txid));
|
|
4512
|
+
}
|
|
4513
|
+
return ids;
|
|
4514
|
+
}
|
|
4515
|
+
var RepositoryExitDataSource = class {
|
|
4516
|
+
constructor(repo) {
|
|
4517
|
+
this.repo = repo;
|
|
4518
|
+
}
|
|
4519
|
+
name = "repository";
|
|
4520
|
+
async getVtxoChain(vtxo) {
|
|
4521
|
+
const branch = await this.repo.getBranch(vtxo);
|
|
4522
|
+
if (branch.length === 0) return null;
|
|
4523
|
+
const chain = [];
|
|
4524
|
+
for (const v of branch) {
|
|
4525
|
+
const type = chainedTxTypeToChainTxType(v.type);
|
|
4526
|
+
let spends = [];
|
|
4527
|
+
if (v.type !== 1 /* Commitment */) {
|
|
4528
|
+
if (!v.psbt) return null;
|
|
4529
|
+
spends = psbtInputTxids(v.psbt);
|
|
4530
|
+
}
|
|
4531
|
+
chain.push({
|
|
4532
|
+
txid: v.txid,
|
|
4533
|
+
type,
|
|
4534
|
+
expiresAt: v.expiresAt != null ? String(v.expiresAt) : "",
|
|
4535
|
+
spends
|
|
4536
|
+
});
|
|
4537
|
+
}
|
|
4538
|
+
return chain;
|
|
4539
|
+
}
|
|
4540
|
+
async getVirtualTxs(txids) {
|
|
4541
|
+
const out = /* @__PURE__ */ new Map();
|
|
4542
|
+
for (const txid of txids) {
|
|
4543
|
+
const stored = await this.repo.getVirtualTx(txid);
|
|
4544
|
+
if (stored?.psbt) out.set(txid, stored.psbt);
|
|
4545
|
+
}
|
|
4546
|
+
return out;
|
|
4547
|
+
}
|
|
4548
|
+
};
|
|
4549
|
+
|
|
4550
|
+
// src/wallet/exit/resolver.ts
|
|
4551
|
+
var OrderedExitChainResolver = class {
|
|
4552
|
+
constructor(sources, persist) {
|
|
4553
|
+
this.sources = sources;
|
|
4554
|
+
this.persist = persist;
|
|
4555
|
+
}
|
|
4556
|
+
async getVtxoChain(vtxo) {
|
|
4557
|
+
let lastErr;
|
|
4558
|
+
for (const source of this.sources) {
|
|
4559
|
+
try {
|
|
4560
|
+
const chain = await source.getVtxoChain(vtxo);
|
|
4561
|
+
if (chain) return chain;
|
|
4562
|
+
} catch (e) {
|
|
4563
|
+
lastErr = e;
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
if (lastErr) throw lastErr;
|
|
4567
|
+
throw new Error(`no exit-data source resolved the chain for ${vtxo.txid}:${vtxo.vout}`);
|
|
4568
|
+
}
|
|
4569
|
+
async getVirtualTxs(txids) {
|
|
4570
|
+
const found = /* @__PURE__ */ new Map();
|
|
4571
|
+
let remaining = txids;
|
|
4572
|
+
for (const [i, source] of this.sources.entries()) {
|
|
4573
|
+
if (remaining.length === 0) break;
|
|
4574
|
+
let got;
|
|
4575
|
+
try {
|
|
4576
|
+
got = await source.getVirtualTxs(remaining);
|
|
4577
|
+
} catch {
|
|
4578
|
+
continue;
|
|
4579
|
+
}
|
|
4580
|
+
const fresh = [];
|
|
4581
|
+
for (const [txid, psbt] of got) {
|
|
4582
|
+
if (found.has(txid)) continue;
|
|
4583
|
+
found.set(txid, psbt);
|
|
4584
|
+
fresh.push({ txid, psbt, expiresAt: null, type: 0 /* Unspecified */ });
|
|
4585
|
+
}
|
|
4586
|
+
if (i > 0 && this.persist && fresh.length > 0) {
|
|
4587
|
+
try {
|
|
4588
|
+
await this.persist.upsertVirtualTxs(fresh);
|
|
4589
|
+
} catch {
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4592
|
+
remaining = txids.filter((t) => !found.has(t));
|
|
4593
|
+
}
|
|
4594
|
+
return [...found.values()];
|
|
4595
|
+
}
|
|
4596
|
+
};
|
|
4597
|
+
function createExitChainResolver(params) {
|
|
4598
|
+
const sources = [];
|
|
4599
|
+
if (params.repository) sources.push(new RepositoryExitDataSource(params.repository));
|
|
4600
|
+
if (params.extraSources) sources.push(...params.extraSources);
|
|
4601
|
+
sources.push(new IndexerExitDataSource(params.indexer));
|
|
4602
|
+
return new OrderedExitChainResolver(sources, params.repository);
|
|
4603
|
+
}
|
|
4604
|
+
|
|
4605
|
+
// src/providers/availability.ts
|
|
4606
|
+
function isRetryableProviderError(error) {
|
|
4607
|
+
return error instanceof ProviderUnavailableError || error instanceof FetchError || isFetchTimeoutError(error);
|
|
4608
|
+
}
|
|
4609
|
+
|
|
4610
|
+
// src/utils/syncCursors.ts
|
|
4611
|
+
var SAFETY_LAG_MS = 3e4;
|
|
4612
|
+
var OVERLAP_MS = 24 * 60 * 60 * 1e3;
|
|
4613
|
+
var walletStateLocks = /* @__PURE__ */ new WeakMap();
|
|
4614
|
+
async function updateWalletState(repo, updater) {
|
|
4615
|
+
const prev = walletStateLocks.get(repo) ?? Promise.resolve();
|
|
4616
|
+
const op = prev.then(async () => {
|
|
4617
|
+
const state = await repo.getWalletState() ?? {};
|
|
4618
|
+
await repo.saveWalletState(updater(state));
|
|
4619
|
+
});
|
|
4620
|
+
walletStateLocks.set(
|
|
4621
|
+
repo,
|
|
4622
|
+
op.catch(() => {
|
|
4623
|
+
})
|
|
4624
|
+
);
|
|
4625
|
+
return op;
|
|
4626
|
+
}
|
|
4627
|
+
var CURSOR_MIGRATED_KEY = "vtxoCursorMigrated";
|
|
4628
|
+
function hasMigrationMarker(state) {
|
|
4629
|
+
return state?.settings?.[CURSOR_MIGRATED_KEY] === true;
|
|
4630
|
+
}
|
|
4631
|
+
async function getSyncCursor(repo) {
|
|
4632
|
+
const state = await repo.getWalletState();
|
|
4633
|
+
if (!hasMigrationMarker(state)) return 0;
|
|
4634
|
+
return state?.lastSyncTime ?? 0;
|
|
4635
|
+
}
|
|
4636
|
+
async function advanceSyncCursor(repo, lastUpdatedAt) {
|
|
4637
|
+
await updateWalletState(repo, (state) => {
|
|
4638
|
+
const current = hasMigrationMarker(state) ? state.lastSyncTime ?? 0 : 0;
|
|
4639
|
+
return {
|
|
4640
|
+
...state,
|
|
4641
|
+
lastSyncTime: Math.max(current, lastUpdatedAt),
|
|
4642
|
+
settings: {
|
|
4643
|
+
...state.settings ?? {},
|
|
4644
|
+
[CURSOR_MIGRATED_KEY]: true
|
|
4645
|
+
}
|
|
4646
|
+
};
|
|
4647
|
+
});
|
|
4648
|
+
}
|
|
4649
|
+
async function clearSyncCursor(repo) {
|
|
4650
|
+
await updateWalletState(repo, (state) => {
|
|
4651
|
+
const { [CURSOR_MIGRATED_KEY]: _, ...restSettings } = state.settings ?? {};
|
|
4652
|
+
return {
|
|
4653
|
+
...state,
|
|
4654
|
+
lastSyncTime: void 0,
|
|
4655
|
+
settings: restSettings
|
|
4656
|
+
};
|
|
4657
|
+
});
|
|
4658
|
+
}
|
|
4659
|
+
function computeSyncWindow(cursor) {
|
|
4660
|
+
const after = Math.max(0, cursor - OVERLAP_MS);
|
|
4661
|
+
return { after };
|
|
4662
|
+
}
|
|
4663
|
+
function cursorCutoff(requestStartedAt) {
|
|
4664
|
+
return (requestStartedAt ?? Date.now()) - SAFETY_LAG_MS;
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4667
|
+
// src/wallet/arkInfoSnapshot.ts
|
|
4668
|
+
var ARK_INFO_SNAPSHOT_KEY = "arkInfoSnapshot";
|
|
4669
|
+
var MalformedArkInfoSnapshotError = class extends Error {
|
|
4670
|
+
constructor(message, options) {
|
|
4671
|
+
super(message, { cause: options?.cause });
|
|
4672
|
+
this.name = "MalformedArkInfoSnapshotError";
|
|
4673
|
+
}
|
|
4674
|
+
};
|
|
4675
|
+
var CURRENT_VERSION = 1;
|
|
4676
|
+
function serializeArkInfoSnapshot(info, savedAt) {
|
|
4677
|
+
return {
|
|
4678
|
+
version: CURRENT_VERSION,
|
|
4679
|
+
savedAt,
|
|
4680
|
+
source: "arkade.getInfo",
|
|
4681
|
+
arkInfo: {
|
|
4682
|
+
network: info.network,
|
|
4683
|
+
signerPubkey: info.signerPubkey,
|
|
4684
|
+
checkpointTapscript: info.checkpointTapscript,
|
|
4685
|
+
forfeitAddress: info.forfeitAddress,
|
|
4686
|
+
forfeitPubkey: info.forfeitPubkey,
|
|
4687
|
+
unilateralExitDelay: info.unilateralExitDelay.toString(),
|
|
4688
|
+
boardingExitDelay: info.boardingExitDelay.toString(),
|
|
4689
|
+
sessionDuration: info.sessionDuration.toString(),
|
|
4690
|
+
dust: info.dust.toString(),
|
|
4691
|
+
fees: info.fees,
|
|
4692
|
+
digest: info.digest,
|
|
4693
|
+
version: info.version,
|
|
4694
|
+
vtxoMinAmount: info.vtxoMinAmount.toString(),
|
|
4695
|
+
vtxoMaxAmount: info.vtxoMaxAmount.toString(),
|
|
4696
|
+
utxoMinAmount: info.utxoMinAmount.toString(),
|
|
4697
|
+
utxoMaxAmount: info.utxoMaxAmount.toString(),
|
|
4698
|
+
deprecatedSigners: info.deprecatedSigners.map((s) => ({
|
|
4699
|
+
pubkey: s.pubkey,
|
|
4700
|
+
cutoffDate: s.cutoffDate.toString()
|
|
4701
|
+
})),
|
|
4702
|
+
scheduledSession: info.scheduledSession ? {
|
|
4703
|
+
duration: info.scheduledSession.duration.toString(),
|
|
4704
|
+
fees: info.scheduledSession.fees,
|
|
4705
|
+
nextEndTime: info.scheduledSession.nextEndTime.toString(),
|
|
4706
|
+
nextStartTime: info.scheduledSession.nextStartTime.toString(),
|
|
4707
|
+
period: info.scheduledSession.period.toString()
|
|
4708
|
+
} : void 0
|
|
4709
|
+
}
|
|
4710
|
+
};
|
|
4711
|
+
}
|
|
4712
|
+
function hydrateArkInfo(snapshot) {
|
|
4713
|
+
const a = snapshot.arkInfo;
|
|
4714
|
+
return {
|
|
4715
|
+
boardingExitDelay: BigInt(a.boardingExitDelay),
|
|
4716
|
+
checkpointTapscript: a.checkpointTapscript,
|
|
4717
|
+
deprecatedSigners: a.deprecatedSigners.map((s) => ({
|
|
4718
|
+
cutoffDate: BigInt(s.cutoffDate),
|
|
4719
|
+
pubkey: s.pubkey
|
|
4720
|
+
})),
|
|
4721
|
+
digest: a.digest,
|
|
4722
|
+
dust: BigInt(a.dust),
|
|
4723
|
+
fees: a.fees,
|
|
4724
|
+
forfeitAddress: a.forfeitAddress,
|
|
4725
|
+
forfeitPubkey: a.forfeitPubkey,
|
|
4726
|
+
network: a.network,
|
|
4727
|
+
scheduledSession: a.scheduledSession ? {
|
|
4728
|
+
duration: BigInt(a.scheduledSession.duration),
|
|
4729
|
+
fees: a.scheduledSession.fees,
|
|
4730
|
+
nextEndTime: BigInt(a.scheduledSession.nextEndTime),
|
|
4731
|
+
nextStartTime: BigInt(a.scheduledSession.nextStartTime),
|
|
4732
|
+
period: BigInt(a.scheduledSession.period)
|
|
4733
|
+
} : void 0,
|
|
4734
|
+
serviceStatus: {},
|
|
4735
|
+
sessionDuration: BigInt(a.sessionDuration),
|
|
4736
|
+
signerPubkey: a.signerPubkey,
|
|
4737
|
+
unilateralExitDelay: BigInt(a.unilateralExitDelay),
|
|
4738
|
+
utxoMaxAmount: BigInt(a.utxoMaxAmount),
|
|
4739
|
+
utxoMinAmount: BigInt(a.utxoMinAmount),
|
|
4740
|
+
version: a.version,
|
|
4741
|
+
vtxoMaxAmount: BigInt(a.vtxoMaxAmount),
|
|
4742
|
+
vtxoMinAmount: BigInt(a.vtxoMinAmount)
|
|
4743
|
+
};
|
|
4744
|
+
}
|
|
4745
|
+
var DECIMAL_STRING = /^-?\d+$/;
|
|
4746
|
+
function assertString(value, path) {
|
|
4747
|
+
if (typeof value !== "string") {
|
|
4748
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be a string`);
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
function assertDecimalString(value, path) {
|
|
4752
|
+
assertString(value, path);
|
|
4753
|
+
if (!DECIMAL_STRING.test(value)) {
|
|
4754
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be a decimal integer string`);
|
|
4755
|
+
}
|
|
4756
|
+
}
|
|
4757
|
+
function assertFeeInfo(value, path) {
|
|
4758
|
+
if (typeof value !== "object" || value === null) {
|
|
4759
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be an object`);
|
|
4760
|
+
}
|
|
4761
|
+
const fees = value;
|
|
4762
|
+
assertString(fees.txFeeRate, `${path}.txFeeRate`);
|
|
4763
|
+
if (typeof fees.intentFee !== "object" || fees.intentFee === null) {
|
|
4764
|
+
throw new MalformedArkInfoSnapshotError(`${path}.intentFee must be an object`);
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
function parseStoredArkInfoSnapshot(raw) {
|
|
4768
|
+
if (typeof raw !== "object" || raw === null) {
|
|
4769
|
+
throw new MalformedArkInfoSnapshotError("snapshot must be an object");
|
|
4770
|
+
}
|
|
4771
|
+
const snap = raw;
|
|
4772
|
+
if (snap.version !== CURRENT_VERSION) {
|
|
4773
|
+
throw new MalformedArkInfoSnapshotError(
|
|
4774
|
+
`unsupported snapshot version: ${String(snap.version)}`
|
|
4775
|
+
);
|
|
4776
|
+
}
|
|
4777
|
+
if (typeof snap.savedAt !== "number") {
|
|
4778
|
+
throw new MalformedArkInfoSnapshotError("savedAt must be a number");
|
|
4779
|
+
}
|
|
4780
|
+
if (snap.source !== "arkade.getInfo") {
|
|
4781
|
+
throw new MalformedArkInfoSnapshotError(`unexpected source: ${String(snap.source)}`);
|
|
4782
|
+
}
|
|
4783
|
+
if (typeof snap.arkInfo !== "object" || snap.arkInfo === null) {
|
|
4784
|
+
throw new MalformedArkInfoSnapshotError("arkInfo must be an object");
|
|
4785
|
+
}
|
|
4786
|
+
const a = snap.arkInfo;
|
|
4787
|
+
for (const field of [
|
|
4788
|
+
"network",
|
|
4789
|
+
"signerPubkey",
|
|
4790
|
+
"checkpointTapscript",
|
|
4791
|
+
"forfeitAddress",
|
|
4792
|
+
"forfeitPubkey",
|
|
4793
|
+
"digest",
|
|
4794
|
+
"version"
|
|
4795
|
+
]) {
|
|
4796
|
+
assertString(a[field], `arkInfo.${field}`);
|
|
4797
|
+
}
|
|
4798
|
+
for (const field of [
|
|
4799
|
+
"unilateralExitDelay",
|
|
4800
|
+
"boardingExitDelay",
|
|
4801
|
+
"sessionDuration",
|
|
4802
|
+
"dust",
|
|
4803
|
+
"vtxoMinAmount",
|
|
4804
|
+
"vtxoMaxAmount",
|
|
4805
|
+
"utxoMinAmount",
|
|
4806
|
+
"utxoMaxAmount"
|
|
4807
|
+
]) {
|
|
4808
|
+
assertDecimalString(a[field], `arkInfo.${field}`);
|
|
4809
|
+
}
|
|
4810
|
+
assertFeeInfo(a.fees, "arkInfo.fees");
|
|
4811
|
+
if (!Array.isArray(a.deprecatedSigners)) {
|
|
4812
|
+
throw new MalformedArkInfoSnapshotError("arkInfo.deprecatedSigners must be an array");
|
|
4813
|
+
}
|
|
4814
|
+
a.deprecatedSigners.forEach((s, i) => {
|
|
4815
|
+
if (typeof s !== "object" || s === null) {
|
|
4816
|
+
throw new MalformedArkInfoSnapshotError(
|
|
4817
|
+
`arkInfo.deprecatedSigners[${i}] must be an object`
|
|
4818
|
+
);
|
|
4819
|
+
}
|
|
4820
|
+
const signer = s;
|
|
4821
|
+
assertString(signer.pubkey, `arkInfo.deprecatedSigners[${i}].pubkey`);
|
|
4822
|
+
assertDecimalString(signer.cutoffDate, `arkInfo.deprecatedSigners[${i}].cutoffDate`);
|
|
4823
|
+
});
|
|
4824
|
+
if (a.scheduledSession !== void 0) {
|
|
4825
|
+
if (typeof a.scheduledSession !== "object" || a.scheduledSession === null) {
|
|
4826
|
+
throw new MalformedArkInfoSnapshotError("arkInfo.scheduledSession must be an object");
|
|
4827
|
+
}
|
|
4828
|
+
const s = a.scheduledSession;
|
|
4829
|
+
for (const field of ["duration", "nextEndTime", "nextStartTime", "period"]) {
|
|
4830
|
+
assertDecimalString(s[field], `arkInfo.scheduledSession.${field}`);
|
|
4831
|
+
}
|
|
4832
|
+
assertFeeInfo(s.fees, "arkInfo.scheduledSession.fees");
|
|
4833
|
+
}
|
|
4834
|
+
return raw;
|
|
4835
|
+
}
|
|
4836
|
+
async function loadArkInfoSnapshot(repo) {
|
|
4837
|
+
const state = await repo.getWalletState();
|
|
4838
|
+
const raw = state?.settings?.[ARK_INFO_SNAPSHOT_KEY];
|
|
4839
|
+
if (raw === void 0 || raw === null) return null;
|
|
4840
|
+
return parseStoredArkInfoSnapshot(raw);
|
|
4841
|
+
}
|
|
4842
|
+
async function saveArkInfoSnapshot(repo, info, savedAt) {
|
|
4843
|
+
const snapshot = serializeArkInfoSnapshot(info, savedAt);
|
|
4844
|
+
await updateWalletState(repo, (state) => ({
|
|
4845
|
+
...state,
|
|
4846
|
+
settings: {
|
|
4847
|
+
...state.settings ?? {},
|
|
4848
|
+
[ARK_INFO_SNAPSHOT_KEY]: snapshot
|
|
4849
|
+
}
|
|
4850
|
+
}));
|
|
4851
|
+
}
|
|
4852
|
+
async function resolveArkInfo(arkProvider, walletRepository) {
|
|
4853
|
+
let info;
|
|
4854
|
+
try {
|
|
4855
|
+
info = await arkProvider.getInfo();
|
|
4856
|
+
} catch (err) {
|
|
4857
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
4858
|
+
const snapshot = await loadArkInfoSnapshot(walletRepository);
|
|
4859
|
+
if (!snapshot) {
|
|
4860
|
+
throw new ProviderUnavailableError(
|
|
4861
|
+
"Arkade server info is unavailable and no cached snapshot exists",
|
|
4862
|
+
{ cause: err }
|
|
4863
|
+
);
|
|
4864
|
+
}
|
|
4865
|
+
return { info: hydrateArkInfo(snapshot), source: "cache", lastOnlineAt: snapshot.savedAt };
|
|
4866
|
+
}
|
|
4867
|
+
return { info, source: "live" };
|
|
4868
|
+
}
|
|
4869
|
+
async function saveValidatedArkInfoSnapshot(repo, info, savedAt) {
|
|
4870
|
+
try {
|
|
4871
|
+
await saveArkInfoSnapshot(repo, info, savedAt);
|
|
4872
|
+
} catch (err) {
|
|
4873
|
+
console.warn("Failed to persist Ark info snapshot", err);
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4290
4876
|
var TxTree = class {
|
|
4291
4877
|
constructor(root, children = /* @__PURE__ */ new Map()) {
|
|
4292
4878
|
this.root = root;
|
|
@@ -5396,20 +5982,6 @@ function isAnnotated(v) {
|
|
|
5396
5982
|
return v.tapTree !== void 0 && v.forfeitTapLeafScript !== void 0 && v.intentTapLeafScript !== void 0;
|
|
5397
5983
|
}
|
|
5398
5984
|
|
|
5399
|
-
// src/repositories/virtualTxRepository.ts
|
|
5400
|
-
var ChainedTxType = /* @__PURE__ */ ((ChainedTxType2) => {
|
|
5401
|
-
ChainedTxType2[ChainedTxType2["Unspecified"] = 0] = "Unspecified";
|
|
5402
|
-
ChainedTxType2[ChainedTxType2["Commitment"] = 1] = "Commitment";
|
|
5403
|
-
ChainedTxType2[ChainedTxType2["Ark"] = 2] = "Ark";
|
|
5404
|
-
ChainedTxType2[ChainedTxType2["Tree"] = 3] = "Tree";
|
|
5405
|
-
ChainedTxType2[ChainedTxType2["Checkpoint"] = 4] = "Checkpoint";
|
|
5406
|
-
return ChainedTxType2;
|
|
5407
|
-
})(ChainedTxType || {});
|
|
5408
|
-
function mergeChainedTxType(incoming, prev) {
|
|
5409
|
-
if (incoming !== 0 /* Unspecified */) return incoming;
|
|
5410
|
-
return prev ?? 0 /* Unspecified */;
|
|
5411
|
-
}
|
|
5412
|
-
|
|
5413
5985
|
// src/repositories/inMemory/intentRepository.ts
|
|
5414
5986
|
var InMemoryIntentRepository = class {
|
|
5415
5987
|
version = 1;
|
|
@@ -7784,106 +8356,49 @@ async function reconcileIntents(deps) {
|
|
|
7784
8356
|
console.error("reconcileIntents: failed to read non-terminal intents", e);
|
|
7785
8357
|
return;
|
|
7786
8358
|
}
|
|
7787
|
-
if (intents.length === 0) return;
|
|
7788
|
-
const outpoints = dedupeOutpoints(intents.flatMap((i) => i.intentVtxos));
|
|
7789
|
-
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
7790
|
-
if (outpoints.length > 0) {
|
|
7791
|
-
try {
|
|
7792
|
-
const { vtxos } = await deps.indexerProvider.getVtxos({ outpoints });
|
|
7793
|
-
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
7794
|
-
} catch (e) {
|
|
7795
|
-
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
7796
|
-
return;
|
|
7797
|
-
}
|
|
7798
|
-
}
|
|
7799
|
-
const nowMs = now();
|
|
7800
|
-
for (const intent of intents) {
|
|
7801
|
-
try {
|
|
7802
|
-
const next = await classifyIntent(intent, vtxosByOutpoint, nowMs);
|
|
7803
|
-
if (!next) continue;
|
|
7804
|
-
const [fresh] = await deps.intentRepository.getIntents({
|
|
7805
|
-
intentTxIds: [intent.intentTxId]
|
|
7806
|
-
});
|
|
7807
|
-
if (!fresh || fresh.state !== intent.state) continue;
|
|
7808
|
-
await deps.intentRepository.saveIntent(next);
|
|
7809
|
-
} catch (e) {
|
|
7810
|
-
console.error(`reconcileIntents: failed to reconcile intent ${intent.intentTxId}`, e);
|
|
7811
|
-
}
|
|
7812
|
-
}
|
|
7813
|
-
}
|
|
7814
|
-
function terminal(intent, state, now, patch) {
|
|
7815
|
-
return { ...intent, ...patch, state, updatedAt: now };
|
|
7816
|
-
}
|
|
7817
|
-
function outpointKey(o) {
|
|
7818
|
-
return `${o.txid}:${o.vout}`;
|
|
7819
|
-
}
|
|
7820
|
-
function dedupeOutpoints(outpoints) {
|
|
7821
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7822
|
-
const out = [];
|
|
7823
|
-
for (const o of outpoints) {
|
|
7824
|
-
const k = outpointKey(o);
|
|
7825
|
-
if (seen.has(k)) continue;
|
|
7826
|
-
seen.add(k);
|
|
7827
|
-
out.push(o);
|
|
7828
|
-
}
|
|
7829
|
-
return out;
|
|
7830
|
-
}
|
|
7831
|
-
|
|
7832
|
-
// src/utils/syncCursors.ts
|
|
7833
|
-
var SAFETY_LAG_MS = 3e4;
|
|
7834
|
-
var OVERLAP_MS = 24 * 60 * 60 * 1e3;
|
|
7835
|
-
var walletStateLocks = /* @__PURE__ */ new WeakMap();
|
|
7836
|
-
async function updateWalletState(repo, updater) {
|
|
7837
|
-
const prev = walletStateLocks.get(repo) ?? Promise.resolve();
|
|
7838
|
-
const op = prev.then(async () => {
|
|
7839
|
-
const state = await repo.getWalletState() ?? {};
|
|
7840
|
-
await repo.saveWalletState(updater(state));
|
|
7841
|
-
});
|
|
7842
|
-
walletStateLocks.set(
|
|
7843
|
-
repo,
|
|
7844
|
-
op.catch(() => {
|
|
7845
|
-
})
|
|
7846
|
-
);
|
|
7847
|
-
return op;
|
|
7848
|
-
}
|
|
7849
|
-
var CURSOR_MIGRATED_KEY = "vtxoCursorMigrated";
|
|
7850
|
-
function hasMigrationMarker(state) {
|
|
7851
|
-
return state?.settings?.[CURSOR_MIGRATED_KEY] === true;
|
|
7852
|
-
}
|
|
7853
|
-
async function getSyncCursor(repo) {
|
|
7854
|
-
const state = await repo.getWalletState();
|
|
7855
|
-
if (!hasMigrationMarker(state)) return 0;
|
|
7856
|
-
return state?.lastSyncTime ?? 0;
|
|
7857
|
-
}
|
|
7858
|
-
async function advanceSyncCursor(repo, lastUpdatedAt) {
|
|
7859
|
-
await updateWalletState(repo, (state) => {
|
|
7860
|
-
const current = hasMigrationMarker(state) ? state.lastSyncTime ?? 0 : 0;
|
|
7861
|
-
return {
|
|
7862
|
-
...state,
|
|
7863
|
-
lastSyncTime: Math.max(current, lastUpdatedAt),
|
|
7864
|
-
settings: {
|
|
7865
|
-
...state.settings ?? {},
|
|
7866
|
-
[CURSOR_MIGRATED_KEY]: true
|
|
7867
|
-
}
|
|
7868
|
-
};
|
|
7869
|
-
});
|
|
8359
|
+
if (intents.length === 0) return;
|
|
8360
|
+
const outpoints = dedupeOutpoints(intents.flatMap((i) => i.intentVtxos));
|
|
8361
|
+
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
8362
|
+
if (outpoints.length > 0) {
|
|
8363
|
+
try {
|
|
8364
|
+
const { vtxos } = await deps.indexerProvider.getVtxos({ outpoints });
|
|
8365
|
+
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
8366
|
+
} catch (e) {
|
|
8367
|
+
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
8368
|
+
return;
|
|
8369
|
+
}
|
|
8370
|
+
}
|
|
8371
|
+
const nowMs = now();
|
|
8372
|
+
for (const intent of intents) {
|
|
8373
|
+
try {
|
|
8374
|
+
const next = await classifyIntent(intent, vtxosByOutpoint, nowMs);
|
|
8375
|
+
if (!next) continue;
|
|
8376
|
+
const [fresh] = await deps.intentRepository.getIntents({
|
|
8377
|
+
intentTxIds: [intent.intentTxId]
|
|
8378
|
+
});
|
|
8379
|
+
if (!fresh || fresh.state !== intent.state) continue;
|
|
8380
|
+
await deps.intentRepository.saveIntent(next);
|
|
8381
|
+
} catch (e) {
|
|
8382
|
+
console.error(`reconcileIntents: failed to reconcile intent ${intent.intentTxId}`, e);
|
|
8383
|
+
}
|
|
8384
|
+
}
|
|
7870
8385
|
}
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
const { [CURSOR_MIGRATED_KEY]: _, ...restSettings } = state.settings ?? {};
|
|
7874
|
-
return {
|
|
7875
|
-
...state,
|
|
7876
|
-
lastSyncTime: void 0,
|
|
7877
|
-
settings: restSettings
|
|
7878
|
-
};
|
|
7879
|
-
});
|
|
8386
|
+
function terminal(intent, state, now, patch) {
|
|
8387
|
+
return { ...intent, ...patch, state, updatedAt: now };
|
|
7880
8388
|
}
|
|
7881
|
-
function
|
|
7882
|
-
|
|
7883
|
-
return { after };
|
|
8389
|
+
function outpointKey(o) {
|
|
8390
|
+
return `${o.txid}:${o.vout}`;
|
|
7884
8391
|
}
|
|
7885
|
-
function
|
|
7886
|
-
|
|
8392
|
+
function dedupeOutpoints(outpoints) {
|
|
8393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8394
|
+
const out = [];
|
|
8395
|
+
for (const o of outpoints) {
|
|
8396
|
+
const k = outpointKey(o);
|
|
8397
|
+
if (seen.has(k)) continue;
|
|
8398
|
+
seen.add(k);
|
|
8399
|
+
out.push(o);
|
|
8400
|
+
}
|
|
8401
|
+
return out;
|
|
7887
8402
|
}
|
|
7888
8403
|
|
|
7889
8404
|
// src/contracts/contractManager.ts
|
|
@@ -7898,6 +8413,10 @@ var ContractManager = class _ContractManager {
|
|
|
7898
8413
|
initialized = false;
|
|
7899
8414
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
7900
8415
|
stopWatcherFn;
|
|
8416
|
+
/** `undefined` while online; the failure reason once a sync degrades. */
|
|
8417
|
+
syncDegradedReason;
|
|
8418
|
+
/** Epoch-ms of the last successful provider sync, if any. */
|
|
8419
|
+
lastSyncedAt;
|
|
7901
8420
|
constructor(config) {
|
|
7902
8421
|
this.config = config;
|
|
7903
8422
|
this.watcher = new ContractWatcher({
|
|
@@ -7920,6 +8439,26 @@ var ContractManager = class _ContractManager {
|
|
|
7920
8439
|
await cm.initialize();
|
|
7921
8440
|
return cm;
|
|
7922
8441
|
}
|
|
8442
|
+
/**
|
|
8443
|
+
* Latest provider-sync health. See {@link ContractSyncState}. Degradation is
|
|
8444
|
+
* recorded by {@link initialize}, {@link getContractsWithVtxos}, and
|
|
8445
|
+
* {@link createContract}; it flips back to `online` on the next successful
|
|
8446
|
+
* sync. Purely a freshness signal — not a source of truth for wallet data.
|
|
8447
|
+
*/
|
|
8448
|
+
getSyncState() {
|
|
8449
|
+
return this.syncDegradedReason === void 0 ? { mode: "online", lastSyncedAt: this.lastSyncedAt } : {
|
|
8450
|
+
mode: "degraded",
|
|
8451
|
+
reason: this.syncDegradedReason,
|
|
8452
|
+
lastSyncedAt: this.lastSyncedAt
|
|
8453
|
+
};
|
|
8454
|
+
}
|
|
8455
|
+
markSyncOnline() {
|
|
8456
|
+
this.syncDegradedReason = void 0;
|
|
8457
|
+
this.lastSyncedAt = Date.now();
|
|
8458
|
+
}
|
|
8459
|
+
markSyncDegraded(err) {
|
|
8460
|
+
this.syncDegradedReason = err instanceof Error ? err.message : String(err);
|
|
8461
|
+
}
|
|
7923
8462
|
async initialize() {
|
|
7924
8463
|
if (this.initialized) {
|
|
7925
8464
|
return;
|
|
@@ -7928,7 +8467,13 @@ var ContractManager = class _ContractManager {
|
|
|
7928
8467
|
for (const contract of contracts) {
|
|
7929
8468
|
await this.watcher.addContract(contract);
|
|
7930
8469
|
}
|
|
7931
|
-
|
|
8470
|
+
try {
|
|
8471
|
+
await this.reconcileWatched();
|
|
8472
|
+
this.markSyncOnline();
|
|
8473
|
+
} catch (err) {
|
|
8474
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8475
|
+
this.markSyncDegraded(err);
|
|
8476
|
+
}
|
|
7932
8477
|
this.initialized = true;
|
|
7933
8478
|
this.stopWatcherFn = await this.watcher.startWatching((event) => {
|
|
7934
8479
|
this.handleContractEvent(event).catch((error) => {
|
|
@@ -7982,7 +8527,13 @@ var ContractManager = class _ContractManager {
|
|
|
7982
8527
|
async createContract(params) {
|
|
7983
8528
|
const { contract, persisted } = await this.upsertContract(params);
|
|
7984
8529
|
if (persisted) {
|
|
7985
|
-
|
|
8530
|
+
try {
|
|
8531
|
+
await this.fetchContractVxosFromIndexer([contract]);
|
|
8532
|
+
this.markSyncOnline();
|
|
8533
|
+
} catch (err) {
|
|
8534
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8535
|
+
this.markSyncDegraded(err);
|
|
8536
|
+
}
|
|
7986
8537
|
await this.watcher.addContract(contract);
|
|
7987
8538
|
}
|
|
7988
8539
|
return contract;
|
|
@@ -8181,7 +8732,13 @@ var ContractManager = class _ContractManager {
|
|
|
8181
8732
|
}
|
|
8182
8733
|
async getContractsWithVtxos(filter, pageSize) {
|
|
8183
8734
|
const contracts = await this.getContracts(filter);
|
|
8184
|
-
|
|
8735
|
+
try {
|
|
8736
|
+
await this.syncContracts({ contracts, pageSize });
|
|
8737
|
+
this.markSyncOnline();
|
|
8738
|
+
} catch (err) {
|
|
8739
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8740
|
+
this.markSyncDegraded(err);
|
|
8741
|
+
}
|
|
8185
8742
|
const vtxos = await this.getVtxosForContracts(contracts);
|
|
8186
8743
|
return contracts.map((contract) => ({
|
|
8187
8744
|
contract,
|
|
@@ -8419,15 +8976,33 @@ var ContractManager = class _ContractManager {
|
|
|
8419
8976
|
* Handle events from the watcher.
|
|
8420
8977
|
*/
|
|
8421
8978
|
async handleContractEvent(event) {
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8979
|
+
try {
|
|
8980
|
+
switch (event.type) {
|
|
8981
|
+
// Delta-sync only the changed virtual outputs for this contract.
|
|
8982
|
+
case "vtxo_received":
|
|
8983
|
+
await this.syncContracts({ contracts: [event.contract] });
|
|
8984
|
+
this.markSyncOnline();
|
|
8985
|
+
break;
|
|
8986
|
+
case "vtxo_spent":
|
|
8987
|
+
await this.syncContracts({ contracts: [event.contract] });
|
|
8988
|
+
this.markSyncOnline();
|
|
8989
|
+
if (this.config.onVtxosSpent) {
|
|
8990
|
+
try {
|
|
8991
|
+
await this.config.onVtxosSpent(
|
|
8992
|
+
event.vtxos.map((v) => ({ txid: v.txid, vout: v.vout }))
|
|
8993
|
+
);
|
|
8994
|
+
} catch {
|
|
8995
|
+
}
|
|
8996
|
+
}
|
|
8997
|
+
break;
|
|
8998
|
+
case "connection_reset":
|
|
8999
|
+
await this.reconcileWatched();
|
|
9000
|
+
this.markSyncOnline();
|
|
9001
|
+
break;
|
|
9002
|
+
}
|
|
9003
|
+
} catch (err) {
|
|
9004
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
9005
|
+
this.markSyncDegraded(err);
|
|
8431
9006
|
}
|
|
8432
9007
|
this.emitEvent(event);
|
|
8433
9008
|
}
|
|
@@ -8509,6 +9084,12 @@ var ContractManager = class _ContractManager {
|
|
|
8509
9084
|
contract,
|
|
8510
9085
|
filtered
|
|
8511
9086
|
);
|
|
9087
|
+
if (this.config.onVtxosPersisted) {
|
|
9088
|
+
try {
|
|
9089
|
+
await this.config.onVtxosPersisted(contract, filtered);
|
|
9090
|
+
} catch {
|
|
9091
|
+
}
|
|
9092
|
+
}
|
|
8512
9093
|
}
|
|
8513
9094
|
}
|
|
8514
9095
|
async fetchContractVxosFromIndexer(contracts, pageSize, syncWindow) {
|
|
@@ -8529,6 +9110,15 @@ var ContractManager = class _ContractManager {
|
|
|
8529
9110
|
contract,
|
|
8530
9111
|
filtered
|
|
8531
9112
|
);
|
|
9113
|
+
if (this.config.onVtxosPersisted) {
|
|
9114
|
+
try {
|
|
9115
|
+
await this.config.onVtxosPersisted(
|
|
9116
|
+
contract,
|
|
9117
|
+
filtered
|
|
9118
|
+
);
|
|
9119
|
+
} catch {
|
|
9120
|
+
}
|
|
9121
|
+
}
|
|
8532
9122
|
}
|
|
8533
9123
|
}
|
|
8534
9124
|
return result;
|
|
@@ -9402,6 +9992,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9402
9992
|
* (ContractManager isn't given it); `undefined` ⇒ no-op.
|
|
9403
9993
|
*/
|
|
9404
9994
|
virtualTxRepository;
|
|
9995
|
+
/** Opt-in exit-data capture settings; see {@link StorageConfig.exitDataCapture}. */
|
|
9996
|
+
exitDataCapture;
|
|
9405
9997
|
_assetManager;
|
|
9406
9998
|
walletContractTimelocks;
|
|
9407
9999
|
// Outpoints ("txid:vout") committed to an in-flight settle/send. Filtered
|
|
@@ -9444,6 +10036,72 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9444
10036
|
* construction-time snapshot for their lifetime.
|
|
9445
10037
|
*/
|
|
9446
10038
|
_arkServerPublicKey;
|
|
10039
|
+
/**
|
|
10040
|
+
* Whether this wallet was constructed from live operator server-info
|
|
10041
|
+
* (`"live"`) or from a cached snapshot because the operator was unreachable
|
|
10042
|
+
* (`"cache"`). Freshness signal for {@link getProviderConnectionState}.
|
|
10043
|
+
*/
|
|
10044
|
+
_serverInfoSource = "live";
|
|
10045
|
+
/**
|
|
10046
|
+
* Epoch-ms of the last known live operator contact: construction time on the
|
|
10047
|
+
* `live` boot path, the cached snapshot's `savedAt` on the `cache` path.
|
|
10048
|
+
*/
|
|
10049
|
+
_serverInfoLastOnlineAt;
|
|
10050
|
+
/** @see {@link _serverInfoSource} */
|
|
10051
|
+
get serverInfoSource() {
|
|
10052
|
+
return this._serverInfoSource;
|
|
10053
|
+
}
|
|
10054
|
+
/**
|
|
10055
|
+
* Composed provider-connection freshness: the boot server-info source
|
|
10056
|
+
* (Arkade) combined with the contract-manager's indexer-sync health, if the
|
|
10057
|
+
* manager has been initialized. Reads no live provider state — it never
|
|
10058
|
+
* forces a `ContractManager` to construct — so it is safe for readonly
|
|
10059
|
+
* callers that only use address/balance APIs.
|
|
10060
|
+
*
|
|
10061
|
+
* - Boot fell back to a cached snapshot → degraded on `arkade` (`cache`).
|
|
10062
|
+
* - Otherwise, if the contract manager has degraded to repository data →
|
|
10063
|
+
* degraded on `indexer` (`repository`).
|
|
10064
|
+
* - Otherwise online.
|
|
10065
|
+
*
|
|
10066
|
+
* This only describes sync freshness; wallet balances/VTXOs are always read
|
|
10067
|
+
* from the repository regardless of this state.
|
|
10068
|
+
*/
|
|
10069
|
+
getProviderConnectionState() {
|
|
10070
|
+
if (this._serverInfoSource === "cache") {
|
|
10071
|
+
return {
|
|
10072
|
+
mode: "degraded",
|
|
10073
|
+
source: "cache",
|
|
10074
|
+
provider: "arkade",
|
|
10075
|
+
reason: "constructed from cached server-info; operator was unreachable at boot",
|
|
10076
|
+
lastOnlineAt: this._serverInfoLastOnlineAt
|
|
10077
|
+
};
|
|
10078
|
+
}
|
|
10079
|
+
const sync = this._contractManager?.getSyncState();
|
|
10080
|
+
if (sync?.mode === "degraded") {
|
|
10081
|
+
return {
|
|
10082
|
+
mode: "degraded",
|
|
10083
|
+
source: "repository",
|
|
10084
|
+
provider: "indexer",
|
|
10085
|
+
reason: sync.reason,
|
|
10086
|
+
lastOnlineAt: sync.lastSyncedAt ?? this._serverInfoLastOnlineAt
|
|
10087
|
+
};
|
|
10088
|
+
}
|
|
10089
|
+
return {
|
|
10090
|
+
mode: "online",
|
|
10091
|
+
source: "live",
|
|
10092
|
+
lastOnlineAt: sync?.lastSyncedAt ?? this._serverInfoLastOnlineAt ?? 0
|
|
10093
|
+
};
|
|
10094
|
+
}
|
|
10095
|
+
/**
|
|
10096
|
+
* The contract-manager's current provider-sync health **without forcing it
|
|
10097
|
+
* to initialize** — reads the already-constructed manager, or reports
|
|
10098
|
+
* `online` when none exists yet. Unlike {@link getContractManager}, this
|
|
10099
|
+
* never triggers a remote sync, so it is safe on a pure diagnostics path
|
|
10100
|
+
* (e.g. the service-worker sync-state message).
|
|
10101
|
+
*/
|
|
10102
|
+
getContractSyncState() {
|
|
10103
|
+
return this._contractManager?.getSyncState() ?? { mode: "online" };
|
|
10104
|
+
}
|
|
9447
10105
|
/**
|
|
9448
10106
|
* x-only hex of the operator's deprecated signer keys (from
|
|
9449
10107
|
* `ArkInfo.deprecatedSigners`), cached for the OFFLINE read/watch paths.
|
|
@@ -9578,7 +10236,13 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9578
10236
|
}
|
|
9579
10237
|
indexerProvider = new RestIndexerProvider(indexerUrl);
|
|
9580
10238
|
}
|
|
9581
|
-
const
|
|
10239
|
+
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
10240
|
+
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
10241
|
+
const {
|
|
10242
|
+
info,
|
|
10243
|
+
source: serverInfoSource,
|
|
10244
|
+
lastOnlineAt: serverInfoLastOnlineAt
|
|
10245
|
+
} = await resolveArkInfo(arkProvider, walletRepository);
|
|
9582
10246
|
const network = getNetwork(info.network);
|
|
9583
10247
|
if ("descriptor" in config.identity) {
|
|
9584
10248
|
const descriptor = config.identity.descriptor;
|
|
@@ -9632,8 +10296,6 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9632
10296
|
serverPubKey: hex.encode(serverPubKey),
|
|
9633
10297
|
csvTimelock: timelockToSequence(boardingTimelock).toString()
|
|
9634
10298
|
});
|
|
9635
|
-
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
9636
|
-
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
9637
10299
|
return {
|
|
9638
10300
|
arkProvider,
|
|
9639
10301
|
indexerProvider,
|
|
@@ -9647,6 +10309,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9647
10309
|
walletRepository,
|
|
9648
10310
|
contractRepository,
|
|
9649
10311
|
info,
|
|
10312
|
+
serverInfoSource,
|
|
10313
|
+
serverInfoLastOnlineAt,
|
|
9650
10314
|
delegateProvider: config.delegateProvider || config.delegatorProvider,
|
|
9651
10315
|
/** @deprecated alias for `delegateProvider` */
|
|
9652
10316
|
delegatorProvider: config.delegateProvider || config.delegatorProvider,
|
|
@@ -9682,6 +10346,15 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9682
10346
|
);
|
|
9683
10347
|
wallet.intentRepository = config.storage?.intentRepository;
|
|
9684
10348
|
wallet.virtualTxRepository = config.storage?.virtualTxRepository;
|
|
10349
|
+
wallet.exitDataCapture = config.storage?.exitDataCapture;
|
|
10350
|
+
wallet._serverInfoSource = setup.serverInfoSource;
|
|
10351
|
+
if (setup.serverInfoSource === "live") {
|
|
10352
|
+
const now = Date.now();
|
|
10353
|
+
await saveValidatedArkInfoSnapshot(setup.walletRepository, setup.info, now);
|
|
10354
|
+
wallet._serverInfoLastOnlineAt = now;
|
|
10355
|
+
} else {
|
|
10356
|
+
wallet._serverInfoLastOnlineAt = setup.serverInfoLastOnlineAt;
|
|
10357
|
+
}
|
|
9685
10358
|
wallet.refreshDeprecatedSigners(setup.info);
|
|
9686
10359
|
return wallet;
|
|
9687
10360
|
}
|
|
@@ -9812,7 +10485,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9812
10485
|
const response = await contractManager.getContractsWithVtxos();
|
|
9813
10486
|
const allVtxos = response.flatMap((_) => _.vtxos);
|
|
9814
10487
|
const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
|
|
9815
|
-
const getTxCreatedAt = (txid) => this.indexerProvider.getVtxos({ outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime())
|
|
10488
|
+
const getTxCreatedAt = (txid) => this.indexerProvider.getVtxos({ outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime()).catch((err) => {
|
|
10489
|
+
if (isRetryableProviderError(err)) return void 0;
|
|
10490
|
+
throw err;
|
|
10491
|
+
});
|
|
9816
10492
|
return buildTransactionHistory(allVtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
|
|
9817
10493
|
}
|
|
9818
10494
|
/**
|
|
@@ -10231,11 +10907,39 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10231
10907
|
}
|
|
10232
10908
|
}
|
|
10233
10909
|
async initializeContractManager() {
|
|
10910
|
+
const virtualTxRepository = this.virtualTxRepository;
|
|
10911
|
+
let onVtxosPersisted;
|
|
10912
|
+
let onVtxosSpent;
|
|
10913
|
+
if (virtualTxRepository) {
|
|
10914
|
+
const capture = this.exitDataCapture;
|
|
10915
|
+
const resolver = createExitChainResolver({
|
|
10916
|
+
indexer: this.indexerProvider,
|
|
10917
|
+
repository: virtualTxRepository,
|
|
10918
|
+
extraSources: capture?.sources
|
|
10919
|
+
});
|
|
10920
|
+
onVtxosPersisted = async (_contract, vtxos) => {
|
|
10921
|
+
for (const v of vtxos) {
|
|
10922
|
+
if (v.virtualStatus.state === "spent") continue;
|
|
10923
|
+
await captureExitBranch({
|
|
10924
|
+
resolver,
|
|
10925
|
+
repository: virtualTxRepository,
|
|
10926
|
+
vtxo: { txid: v.txid, vout: v.vout },
|
|
10927
|
+
value: v.value,
|
|
10928
|
+
mode: capture?.mode ?? DEFAULT_EXIT_CAPTURE_MODE,
|
|
10929
|
+
minExitWorthSats: capture?.minExitWorthSats ?? DEFAULT_MIN_EXIT_WORTH_SATS
|
|
10930
|
+
}).catch(() => {
|
|
10931
|
+
});
|
|
10932
|
+
}
|
|
10933
|
+
};
|
|
10934
|
+
onVtxosSpent = (vtxos) => pruneExitBranches(virtualTxRepository, vtxos);
|
|
10935
|
+
}
|
|
10234
10936
|
const manager = await ContractManager.create({
|
|
10235
10937
|
indexerProvider: this.indexerProvider,
|
|
10236
10938
|
contractRepository: this.contractRepository,
|
|
10237
10939
|
walletRepository: this.walletRepository,
|
|
10238
10940
|
intentRepository: this.intentRepository,
|
|
10941
|
+
onVtxosPersisted,
|
|
10942
|
+
onVtxosSpent,
|
|
10239
10943
|
watcherConfig: this.watcherConfig
|
|
10240
10944
|
});
|
|
10241
10945
|
const baselinePubkey = await this.identity.xOnlyPublicKey();
|
|
@@ -10910,6 +11614,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
10910
11614
|
boot?.rotator,
|
|
10911
11615
|
boot?.provider
|
|
10912
11616
|
);
|
|
11617
|
+
wallet._serverInfoSource = setup.serverInfoSource;
|
|
11618
|
+
if (setup.serverInfoSource === "live") {
|
|
11619
|
+
const now = Date.now();
|
|
11620
|
+
await saveValidatedArkInfoSnapshot(setup.walletRepository, setup.info, now);
|
|
11621
|
+
wallet._serverInfoLastOnlineAt = now;
|
|
11622
|
+
} else {
|
|
11623
|
+
wallet._serverInfoLastOnlineAt = setup.serverInfoLastOnlineAt;
|
|
11624
|
+
}
|
|
10913
11625
|
wallet.refreshDeprecatedSigners(setup.info);
|
|
10914
11626
|
{
|
|
10915
11627
|
const ap = setup.arkProvider;
|
|
@@ -10931,6 +11643,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
10931
11643
|
}
|
|
10932
11644
|
wallet.intentRepository = config.storage?.intentRepository;
|
|
10933
11645
|
wallet.virtualTxRepository = config.storage?.virtualTxRepository;
|
|
11646
|
+
wallet.exitDataCapture = config.storage?.exitDataCapture;
|
|
10934
11647
|
await wallet.getVtxoManager();
|
|
10935
11648
|
return wallet;
|
|
10936
11649
|
}
|
|
@@ -13448,10 +14161,18 @@ var WalletMessageHandler = class {
|
|
|
13448
14161
|
type: "WALLET_STATUS",
|
|
13449
14162
|
payload: {
|
|
13450
14163
|
walletInitialized: true,
|
|
13451
|
-
xOnlyPublicKey: pubKey
|
|
14164
|
+
xOnlyPublicKey: pubKey,
|
|
14165
|
+
providerConnectionState: this.readonlyWallet.getProviderConnectionState()
|
|
13452
14166
|
}
|
|
13453
14167
|
});
|
|
13454
14168
|
}
|
|
14169
|
+
case "GET_CONTRACT_SYNC_STATE": {
|
|
14170
|
+
return this.tagged({
|
|
14171
|
+
id,
|
|
14172
|
+
type: "CONTRACT_SYNC_STATE",
|
|
14173
|
+
payload: { syncState: this.readonlyWallet.getContractSyncState() }
|
|
14174
|
+
});
|
|
14175
|
+
}
|
|
13455
14176
|
case "CLEAR": {
|
|
13456
14177
|
await this.clear();
|
|
13457
14178
|
return this.tagged({
|
|
@@ -14214,6 +14935,7 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
|
|
|
14214
14935
|
GET_BALANCE: 1e4,
|
|
14215
14936
|
GET_BOARDING_ADDRESS: 1e4,
|
|
14216
14937
|
GET_STATUS: 1e4,
|
|
14938
|
+
GET_CONTRACT_SYNC_STATE: 1e4,
|
|
14217
14939
|
GET_DELEGATE_INFO: 1e4,
|
|
14218
14940
|
IS_CONTRACT_MANAGER_WATCHING: 1e4,
|
|
14219
14941
|
// Medium reads — may involve indexer queries
|
|
@@ -14822,6 +15544,19 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14822
15544
|
throw new Error(`Failed to get status: ${error}`);
|
|
14823
15545
|
}
|
|
14824
15546
|
}
|
|
15547
|
+
/**
|
|
15548
|
+
* Wallet-level provider-connection freshness, delegated to the worker via
|
|
15549
|
+
* `GET_STATUS`. Async by necessity (the worker boundary is asynchronous); no
|
|
15550
|
+
* synchronous variant is offered because it would have the same transport
|
|
15551
|
+
* mismatch as the contract-manager proxy's cached `getSyncState()`.
|
|
15552
|
+
*/
|
|
15553
|
+
async getProviderConnectionState() {
|
|
15554
|
+
const { providerConnectionState } = await this.getStatus();
|
|
15555
|
+
if (!providerConnectionState) {
|
|
15556
|
+
throw new Error("Worker did not report provider connection state");
|
|
15557
|
+
}
|
|
15558
|
+
return providerConnectionState;
|
|
15559
|
+
}
|
|
14825
15560
|
async getActivityHistory() {
|
|
14826
15561
|
return buildActivities(await this.getTransactionHistory(), this.activity.all());
|
|
14827
15562
|
}
|
|
@@ -14876,6 +15611,32 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14876
15611
|
return wallet.sendMessage(message);
|
|
14877
15612
|
};
|
|
14878
15613
|
const messageTag = this.messageTag;
|
|
15614
|
+
const fetchSyncState = async () => {
|
|
15615
|
+
const message = {
|
|
15616
|
+
type: "GET_CONTRACT_SYNC_STATE",
|
|
15617
|
+
id: getRandomId(),
|
|
15618
|
+
tag: messageTag
|
|
15619
|
+
};
|
|
15620
|
+
const response = await sendContractMessage(message);
|
|
15621
|
+
return response.payload.syncState;
|
|
15622
|
+
};
|
|
15623
|
+
const UNKNOWN_STATE = {
|
|
15624
|
+
mode: "degraded",
|
|
15625
|
+
reason: "contract sync state unavailable from the worker"
|
|
15626
|
+
};
|
|
15627
|
+
let syncState = UNKNOWN_STATE;
|
|
15628
|
+
let everProbed = false;
|
|
15629
|
+
const refreshSyncState = async () => {
|
|
15630
|
+
try {
|
|
15631
|
+
syncState = await fetchSyncState();
|
|
15632
|
+
everProbed = true;
|
|
15633
|
+
} catch {
|
|
15634
|
+
if (!everProbed) {
|
|
15635
|
+
syncState = UNKNOWN_STATE;
|
|
15636
|
+
}
|
|
15637
|
+
}
|
|
15638
|
+
};
|
|
15639
|
+
await refreshSyncState();
|
|
14879
15640
|
const manager = {
|
|
14880
15641
|
async createContract(params) {
|
|
14881
15642
|
const message = {
|
|
@@ -14886,6 +15647,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14886
15647
|
};
|
|
14887
15648
|
try {
|
|
14888
15649
|
const response = await sendContractMessage(message);
|
|
15650
|
+
await refreshSyncState();
|
|
14889
15651
|
return response.payload.contract;
|
|
14890
15652
|
} catch (e) {
|
|
14891
15653
|
throw new Error("Failed to create contract");
|
|
@@ -14914,11 +15676,15 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14914
15676
|
};
|
|
14915
15677
|
try {
|
|
14916
15678
|
const response = await sendContractMessage(message);
|
|
15679
|
+
await refreshSyncState();
|
|
14917
15680
|
return response.payload.contracts;
|
|
14918
15681
|
} catch (e) {
|
|
14919
15682
|
throw new Error("Failed to get contracts with vtxos");
|
|
14920
15683
|
}
|
|
14921
15684
|
},
|
|
15685
|
+
getSyncState() {
|
|
15686
|
+
return syncState;
|
|
15687
|
+
},
|
|
14922
15688
|
async annotateVtxos(vtxos) {
|
|
14923
15689
|
if (vtxos.length === 0) return [];
|
|
14924
15690
|
const message = {
|
|
@@ -15027,7 +15793,11 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
15027
15793
|
tag: messageTag,
|
|
15028
15794
|
payload: opts
|
|
15029
15795
|
};
|
|
15030
|
-
|
|
15796
|
+
try {
|
|
15797
|
+
await sendContractMessage(message);
|
|
15798
|
+
} finally {
|
|
15799
|
+
await refreshSyncState();
|
|
15800
|
+
}
|
|
15031
15801
|
},
|
|
15032
15802
|
async refreshOutpoints(outpoints) {
|
|
15033
15803
|
const message = {
|
|
@@ -15036,7 +15806,11 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
15036
15806
|
tag: messageTag,
|
|
15037
15807
|
payload: { outpoints }
|
|
15038
15808
|
};
|
|
15039
|
-
|
|
15809
|
+
try {
|
|
15810
|
+
await sendContractMessage(message);
|
|
15811
|
+
} finally {
|
|
15812
|
+
await refreshSyncState();
|
|
15813
|
+
}
|
|
15040
15814
|
},
|
|
15041
15815
|
scanContracts() {
|
|
15042
15816
|
return Promise.reject(
|
|
@@ -16651,7 +17425,7 @@ async function resolveUnilateralPath(params) {
|
|
|
16651
17425
|
}
|
|
16652
17426
|
|
|
16653
17427
|
// src/wallet/unroll.ts
|
|
16654
|
-
function
|
|
17428
|
+
function chainTxTypeToChainedExit2(t) {
|
|
16655
17429
|
switch (t) {
|
|
16656
17430
|
case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
|
|
16657
17431
|
return 1 /* Commitment */;
|
|
@@ -16714,7 +17488,7 @@ var Unroll;
|
|
|
16714
17488
|
txid: next.txid,
|
|
16715
17489
|
psbt,
|
|
16716
17490
|
expiresAt: null,
|
|
16717
|
-
type:
|
|
17491
|
+
type: chainTxTypeToChainedExit2(next.type)
|
|
16718
17492
|
};
|
|
16719
17493
|
try {
|
|
16720
17494
|
await repo.upsertVirtualTxs([cached]);
|
|
@@ -16892,99 +17666,6 @@ function doWait(onchainProvider, txid) {
|
|
|
16892
17666
|
});
|
|
16893
17667
|
};
|
|
16894
17668
|
}
|
|
16895
|
-
|
|
16896
|
-
// src/wallet/exit/chain.ts
|
|
16897
|
-
var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
16898
|
-
async function buildExitDag(params) {
|
|
16899
|
-
const byTxid = /* @__PURE__ */ new Map();
|
|
16900
|
-
for (const vtxo of params.vtxos) {
|
|
16901
|
-
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
16902
|
-
let pageIndex = 0;
|
|
16903
|
-
let hasMore = true;
|
|
16904
|
-
while (hasMore) {
|
|
16905
|
-
const { chain, page } = await params.indexer.getVtxoChain(
|
|
16906
|
-
{ txid: vtxo.txid, vout: vtxo.vout },
|
|
16907
|
-
{ pageIndex, pageSize: DEFAULT_PAGE_SIZE }
|
|
16908
|
-
);
|
|
16909
|
-
for (const chainTx of chain) {
|
|
16910
|
-
const existing = byTxid.get(chainTx.txid);
|
|
16911
|
-
if (existing) {
|
|
16912
|
-
existing.forVtxos.add(outpoint);
|
|
16913
|
-
} else {
|
|
16914
|
-
byTxid.set(chainTx.txid, { ...chainTx, forVtxos: /* @__PURE__ */ new Set([outpoint]) });
|
|
16915
|
-
}
|
|
16916
|
-
}
|
|
16917
|
-
hasMore = page ? chain.length === DEFAULT_PAGE_SIZE : false;
|
|
16918
|
-
pageIndex++;
|
|
16919
|
-
}
|
|
16920
|
-
}
|
|
16921
|
-
const pending = new Map(
|
|
16922
|
-
[...byTxid.values()].filter((tx) => !isCommitment(tx.type)).map((tx) => [tx.txid, tx])
|
|
16923
|
-
);
|
|
16924
|
-
const inDegree = /* @__PURE__ */ new Map();
|
|
16925
|
-
for (const tx of pending.values()) {
|
|
16926
|
-
const parents = tx.spends.filter((p) => pending.has(p));
|
|
16927
|
-
inDegree.set(tx.txid, parents.length);
|
|
16928
|
-
}
|
|
16929
|
-
const order = [];
|
|
16930
|
-
const queue = [...pending.values()].filter((tx) => inDegree.get(tx.txid) === 0).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
16931
|
-
while (queue.length > 0) {
|
|
16932
|
-
const tx = queue.shift();
|
|
16933
|
-
order.push(tx);
|
|
16934
|
-
const children = [...pending.values()].filter((c) => c.spends.includes(tx.txid)).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
16935
|
-
for (const child of children) {
|
|
16936
|
-
const deg = inDegree.get(child.txid) - 1;
|
|
16937
|
-
inDegree.set(child.txid, deg);
|
|
16938
|
-
if (deg === 0) queue.push(child);
|
|
16939
|
-
}
|
|
16940
|
-
}
|
|
16941
|
-
if (order.length !== pending.size) {
|
|
16942
|
-
throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
|
|
16943
|
-
}
|
|
16944
|
-
const nodes = [];
|
|
16945
|
-
for (const tx of order) {
|
|
16946
|
-
let confirmed = false;
|
|
16947
|
-
try {
|
|
16948
|
-
const status = await params.onchain.getTxStatus(tx.txid);
|
|
16949
|
-
confirmed = status.confirmed;
|
|
16950
|
-
} catch {
|
|
16951
|
-
confirmed = false;
|
|
16952
|
-
}
|
|
16953
|
-
const expires = Number(tx.expiresAt);
|
|
16954
|
-
nodes.push({
|
|
16955
|
-
txid: tx.txid,
|
|
16956
|
-
type: tx.type,
|
|
16957
|
-
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
|
|
16958
|
-
forVtxos: [...tx.forVtxos].sort(),
|
|
16959
|
-
confirmed
|
|
16960
|
-
});
|
|
16961
|
-
}
|
|
16962
|
-
return nodes;
|
|
16963
|
-
}
|
|
16964
|
-
function topoSortByDeps(items, idOf, depsOf) {
|
|
16965
|
-
const produced = new Set(items.map(idOf));
|
|
16966
|
-
const emitted = /* @__PURE__ */ new Set();
|
|
16967
|
-
const ordered = [];
|
|
16968
|
-
let remaining = items;
|
|
16969
|
-
while (remaining.length > 0) {
|
|
16970
|
-
const next = [];
|
|
16971
|
-
let progress = false;
|
|
16972
|
-
for (const item of remaining) {
|
|
16973
|
-
if (depsOf(item).every((d) => !produced.has(d) || emitted.has(d))) {
|
|
16974
|
-
ordered.push(item);
|
|
16975
|
-
emitted.add(idOf(item));
|
|
16976
|
-
progress = true;
|
|
16977
|
-
} else {
|
|
16978
|
-
next.push(item);
|
|
16979
|
-
}
|
|
16980
|
-
}
|
|
16981
|
-
if (!progress) {
|
|
16982
|
-
throw new Error("topological sort: cycle or unsatisfiable dependency");
|
|
16983
|
-
}
|
|
16984
|
-
remaining = next;
|
|
16985
|
-
}
|
|
16986
|
-
return ordered;
|
|
16987
|
-
}
|
|
16988
17669
|
function extraWitnessSize(path) {
|
|
16989
17670
|
return (path.extraWitness ?? []).reduce((sum, item) => sum + 1 + item.length, 0);
|
|
16990
17671
|
}
|
|
@@ -17091,27 +17772,22 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
17091
17772
|
const { wallet, onchainWallet } = opts;
|
|
17092
17773
|
const vtxos = await selectExitVtxos(opts);
|
|
17093
17774
|
if (vtxos.length === 0) throw new Error("no vtxos to exit");
|
|
17775
|
+
const resolver = createExitChainResolver({
|
|
17776
|
+
indexer: wallet.indexerProvider,
|
|
17777
|
+
repository: wallet.virtualTxRepository,
|
|
17778
|
+
extraSources: wallet.exitDataCapture?.sources
|
|
17779
|
+
});
|
|
17094
17780
|
const dag = await buildExitDag({
|
|
17095
17781
|
vtxos,
|
|
17096
|
-
|
|
17782
|
+
chain: resolver,
|
|
17097
17783
|
onchain: wallet.onchainProvider
|
|
17098
17784
|
});
|
|
17099
17785
|
const pendingNodes = dag.filter((n) => !n.confirmed);
|
|
17100
17786
|
const psbts = /* @__PURE__ */ new Map();
|
|
17101
17787
|
if (pendingNodes.length > 0) {
|
|
17102
|
-
const
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
while (hasMore) {
|
|
17106
|
-
const { txs, page } = await wallet.indexerProvider.getVirtualTxs(txids, {
|
|
17107
|
-
pageIndex,
|
|
17108
|
-
pageSize: DEFAULT_PAGE_SIZE
|
|
17109
|
-
});
|
|
17110
|
-
for (const psbt of txs) {
|
|
17111
|
-
psbts.set(Transaction.fromPSBT(base64.decode(psbt)).id, psbt);
|
|
17112
|
-
}
|
|
17113
|
-
hasMore = page ? txs.length === DEFAULT_PAGE_SIZE : false;
|
|
17114
|
-
pageIndex++;
|
|
17788
|
+
const txs = await resolver.getVirtualTxs(pendingNodes.map((n) => n.txid));
|
|
17789
|
+
for (const psbt of txs) {
|
|
17790
|
+
psbts.set(Transaction.fromPSBT(base64.decode(psbt)).id, psbt);
|
|
17115
17791
|
}
|
|
17116
17792
|
}
|
|
17117
17793
|
const childVsize = Number(
|
|
@@ -17754,6 +18430,6 @@ function isArkContract(str) {
|
|
|
17754
18430
|
return str.startsWith(ARKCONTRACT_PREFIX + "=");
|
|
17755
18431
|
}
|
|
17756
18432
|
|
|
17757
|
-
export { ActivityRegistry, ArkNote, AssetManager, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EsploraProvider, Estimator, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createDefaultActivityRegistry, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
17758
|
-
//# sourceMappingURL=chunk-
|
|
17759
|
-
//# sourceMappingURL=chunk-
|
|
18433
|
+
export { ActivityRegistry, ArkNote, AssetManager, BIP322, Batch, ChainedTxType, ContractManager, ContractRepositoryImpl, ContractWatcher, DB_VERSION, DEFAULT_MESSAGE_TIMEOUTS, DelegateManagerImpl, DelegateNotConfiguredError, DelegatorManagerImpl, DelegatorNotConfiguredError, DescriptorSigningProviderMissingError, DustChangeError, ELECTRUM_TCP_HOST, ELECTRUM_WS_URL, ESPLORA_URL, ElectrumOnchainProvider, EsploraProvider, Estimator, HDDescriptorProvider, INTENT_TERMINAL_STATES, InMemoryContractRepository, InMemoryIntentRepository, InMemoryVirtualTxRepository, InMemoryWalletRepository, IndexedDBContractRepository, IndexedDBIntentRepository, IndexedDBVirtualTxRepository, IndexedDBWalletRepository, MESSAGE_BUS_INITIALIZING, MESSAGE_BUS_NOT_INITIALIZED, MIGRATION_KEY, MessageBus, MessageBusInitializingError, MessageBusNotInitializedError, MissingSigningDescriptorError, MnemonicIdentity, OnchainWallet, P2A, Ramps, ReadonlyAssetManager, ReadonlyDescriptorIdentity, ReadonlySingleKey, ReadonlyWallet, ReadonlyWalletError, RestDelegateProvider, RestDelegatorProvider, SeedIdentity, ServiceWorkerReadonlyWallet, ServiceWorkerTimeoutError, ServiceWorkerWallet, SingleKey, TxTree, TxType, TxWeightEstimator, UnilateralExit, Unroll, VtxoManager, Wallet2 as Wallet, WalletMessageHandler, WalletNotInitializedError, WalletRepositoryImpl, WsElectrumChainSource, assertIntentIdUnique, boardingResolver, buildForfeitTx, buildOffchainTx, classifyAgainstSignerSet, classifyContractSigner, closeDatabase, combineTapscriptSigs, contractFromArkContract, contractFromArkContractWithAddress, createDefaultActivityRegistry, createExitChainResolver, decodeArkContract, deserializeAssets, deserializeExitPackage, deserializeUtxo, deserializeVtxo, encodeArkContract, extendVirtualCoinForContract, getMigrationStatus, getRandomId, hasBoardingTxExpired, intentMatchesFilter, intentPageBounds, isArkContract, isBatchSignable, isCooperativelyMigratable, isDiscoverable, isExpired, isRecoverable, isRetryableProviderError, isSpendable, isSubdust, isTerminalIntentState, isValidArkAddress, isVtxoExpiringSoon, isVtxoForScript, mergeChainedTxType, migrateWalletRepository, openDatabase, requiresMigration, rollbackMigration, saveVtxosForContract, scriptFromArkAddress, serializeAssets, serializeExitPackage, serializeUtxo, serializeVtxo, setupServiceWorker, signerSetFromInfo, toXOnlySignerHex, validateConnectorsTxGraph, validateVtxoTxGraph, verifyTapscriptSignatures, waitForIncomingFunds, warnAndFilterVtxosForScript };
|
|
18434
|
+
//# sourceMappingURL=chunk-TGRJ5WAX.js.map
|
|
18435
|
+
//# sourceMappingURL=chunk-TGRJ5WAX.js.map
|