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