@arkade-os/sdk 0.4.66 → 0.4.68
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 +71 -15
- 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/adapters/indexedDB.cjs +5 -5
- package/dist/adapters/indexedDB.js +4 -4
- package/dist/{asyncStorageTaskQueue-BZcIN7sA.d.cts → asyncStorageTaskQueue-B2CcXIHU.d.cts} +1 -1
- package/dist/{asyncStorageTaskQueue-B6SijMi3.d.ts → asyncStorageTaskQueue-DaZlVTbM.d.ts} +1 -1
- package/dist/{chunk-2JZGPXU4.js → chunk-33Q2RFET.js} +3 -3
- package/dist/{chunk-2JZGPXU4.js.map → chunk-33Q2RFET.js.map} +1 -1
- package/dist/{chunk-CYOI4PEA.js → chunk-45FKMOJH.js} +160 -114
- package/dist/chunk-45FKMOJH.js.map +1 -0
- package/dist/{chunk-J33ZEM3A.js → chunk-4CMXV5SF.js} +45 -14
- package/dist/chunk-4CMXV5SF.js.map +1 -0
- package/dist/{chunk-LL47QIHD.cjs → chunk-4KCVS4ZN.cjs} +10 -10
- package/dist/{chunk-LL47QIHD.cjs.map → chunk-4KCVS4ZN.cjs.map} +1 -1
- package/dist/{chunk-PXPPZF5K.cjs → chunk-6YUACVX4.cjs} +205 -159
- package/dist/chunk-6YUACVX4.cjs.map +1 -0
- package/dist/{chunk-ZIRFXBKL.cjs → chunk-EJOFL5WH.cjs} +47 -13
- package/dist/chunk-EJOFL5WH.cjs.map +1 -0
- package/dist/{chunk-R5POS3RS.js → chunk-G4I6PU5H.js} +4 -4
- package/dist/{chunk-R5POS3RS.js.map → chunk-G4I6PU5H.js.map} +1 -1
- package/dist/{chunk-55ZZ6RBL.js → chunk-GQ4NMQGR.js} +4 -4
- package/dist/{chunk-55ZZ6RBL.js.map → chunk-GQ4NMQGR.js.map} +1 -1
- package/dist/{chunk-IM6IKNSL.cjs → chunk-JGMSZIE4.cjs} +17 -17
- package/dist/{chunk-IM6IKNSL.cjs.map → chunk-JGMSZIE4.cjs.map} +1 -1
- package/dist/{chunk-3S3JZUEN.cjs → chunk-PJR63FTK.cjs} +17 -17
- package/dist/{chunk-3S3JZUEN.cjs.map → chunk-PJR63FTK.cjs.map} +1 -1
- package/dist/{chunk-DSC3G6QZ.js → chunk-VBHXBI7F.js} +1060 -185
- package/dist/chunk-VBHXBI7F.js.map +1 -0
- package/dist/{chunk-5E6IZNRG.cjs → chunk-WCJVKFAP.cjs} +1467 -581
- package/dist/chunk-WCJVKFAP.cjs.map +1 -0
- 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-T-vgxMYZ.d.ts → delegate-AomVWxO_.d.ts} +1 -1
- package/dist/{delegate-YXupcWWJ.d.cts → delegate-Bffc5f54.d.cts} +1 -1
- package/dist/{wallet-CNibc3yJ.d.ts → hdWalletCapable-B5nRs3RH.d.cts} +318 -127
- package/dist/{wallet-DJN1QgFt.d.cts → hdWalletCapable-DZdIVa23.d.ts} +318 -127
- package/dist/{index-uUE_uQPn.d.ts → index-C7RZCfoY.d.cts} +222 -19
- package/dist/{index-uUE_uQPn.d.cts → index-C7RZCfoY.d.ts} +222 -19
- package/dist/{index-e7LYXk1d.d.cts → index-jouvy8FD.d.ts} +172 -99
- package/dist/{index-D_FgwLH9.d.ts → index-nfyQM33h.d.cts} +172 -99
- package/dist/index.cjs +326 -278
- package/dist/index.d.cts +295 -41
- package/dist/index.d.ts +295 -41
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +19 -19
- 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 +18 -18
- 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-BOVcIH1N.d.cts → taskRunner-D2vnpPBT.d.cts} +1 -1
- package/dist/{taskRunner-DNyD1kXG.d.ts → taskRunner-DuwK9t8O.d.ts} +1 -1
- 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 +18 -14
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +7 -5
- package/dist/wallet/expo/index.d.ts +7 -5
- package/dist/wallet/expo/index.js +10 -6
- package/dist/wallet/expo/index.js.map +1 -1
- 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 +3 -3
- package/dist/chunk-5E6IZNRG.cjs.map +0 -1
- package/dist/chunk-CYOI4PEA.js.map +0 -1
- package/dist/chunk-DSC3G6QZ.js.map +0 -1
- package/dist/chunk-J33ZEM3A.js.map +0 -1
- package/dist/chunk-PXPPZF5K.cjs.map +0 -1
- package/dist/chunk-ZIRFXBKL.cjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkPJR63FTK_cjs = require('./chunk-PJR63FTK.cjs');
|
|
4
|
+
var chunk6YUACVX4_cjs = require('./chunk-6YUACVX4.cjs');
|
|
5
|
+
var chunkEJOFL5WH_cjs = require('./chunk-EJOFL5WH.cjs');
|
|
6
6
|
var chunk5BLDMQED_cjs = require('./chunk-5BLDMQED.cjs');
|
|
7
7
|
var utils_js = require('@scure/btc-signer/utils.js');
|
|
8
8
|
var btcSigner = require('@scure/btc-signer');
|
|
@@ -188,7 +188,7 @@ var TreeSignerSession = class _TreeSignerSession {
|
|
|
188
188
|
noncesByPubkey.set(base.hex.encode(myPublicKey.subarray(1)), myNonce);
|
|
189
189
|
const tx = this.graph.find(txid);
|
|
190
190
|
if (!tx) throw new Error(`missing tx for txid ${txid}`);
|
|
191
|
-
const cosigners =
|
|
191
|
+
const cosigners = chunkEJOFL5WH_cjs.getArkPsbtFields(tx.root, 0, chunkEJOFL5WH_cjs.CosignerPublicKey).map(
|
|
192
192
|
(c) => base.hex.encode(c.key.subarray(1))
|
|
193
193
|
// xonly pubkey
|
|
194
194
|
);
|
|
@@ -240,7 +240,7 @@ var TreeSignerSession = class _TreeSignerSession {
|
|
|
240
240
|
if (!aggNonce) throw new Error("missing aggregate nonce");
|
|
241
241
|
const prevoutAmounts = [];
|
|
242
242
|
const prevoutScripts = [];
|
|
243
|
-
const cosigners =
|
|
243
|
+
const cosigners = chunkEJOFL5WH_cjs.getArkPsbtFields(g.root, 0, chunkEJOFL5WH_cjs.CosignerPublicKey).map((c) => c.key);
|
|
244
244
|
const { finalKey } = aggregateKeys(cosigners, true, {
|
|
245
245
|
taprootTweak: this.scriptRoot
|
|
246
246
|
});
|
|
@@ -294,7 +294,7 @@ function getPrevOutput(finalKey, graph, sharedOutputAmount, tx) {
|
|
|
294
294
|
script: pkScript
|
|
295
295
|
};
|
|
296
296
|
}
|
|
297
|
-
var
|
|
297
|
+
var ALLOWED_SIGHASH = [btcSigner.SigHash.DEFAULT, btcSigner.SigHash.ALL, btcSigner.SigHash.ALL_ANYONECANPAY];
|
|
298
298
|
var SingleKey = class _SingleKey {
|
|
299
299
|
key;
|
|
300
300
|
constructor(key) {
|
|
@@ -323,8 +323,9 @@ var SingleKey = class _SingleKey {
|
|
|
323
323
|
async sign(tx, inputIndexes) {
|
|
324
324
|
const txCpy = tx.clone();
|
|
325
325
|
if (!inputIndexes) {
|
|
326
|
+
chunkEJOFL5WH_cjs.assertAllowedSighashTypes(txCpy, ALLOWED_SIGHASH);
|
|
326
327
|
try {
|
|
327
|
-
if (!txCpy.sign(this.key,
|
|
328
|
+
if (!txCpy.sign(this.key, ALLOWED_SIGHASH)) {
|
|
328
329
|
throw new Error("Failed to sign transaction");
|
|
329
330
|
}
|
|
330
331
|
} catch (e) {
|
|
@@ -335,7 +336,7 @@ var SingleKey = class _SingleKey {
|
|
|
335
336
|
return txCpy;
|
|
336
337
|
}
|
|
337
338
|
for (const inputIndex of inputIndexes) {
|
|
338
|
-
if (!txCpy.signIdx(this.key, inputIndex,
|
|
339
|
+
if (!txCpy.signIdx(this.key, inputIndex, ALLOWED_SIGHASH)) {
|
|
339
340
|
throw new Error(`Failed to sign input #${inputIndex}`);
|
|
340
341
|
}
|
|
341
342
|
}
|
|
@@ -400,7 +401,7 @@ var ReadonlySingleKey = class _ReadonlySingleKey {
|
|
|
400
401
|
return Promise.resolve(this.publicKey);
|
|
401
402
|
}
|
|
402
403
|
};
|
|
403
|
-
var
|
|
404
|
+
var ALLOWED_SIGHASH2 = [btcSigner.SigHash.DEFAULT, btcSigner.SigHash.ALL, btcSigner.SigHash.ALL_ANYONECANPAY];
|
|
404
405
|
var seedBytes = /* @__PURE__ */ new WeakMap();
|
|
405
406
|
var mnemonicMeta = /* @__PURE__ */ new WeakMap();
|
|
406
407
|
var SeedIdentity = class _SeedIdentity {
|
|
@@ -431,7 +432,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
431
432
|
let network;
|
|
432
433
|
if ("descriptor" in opts && typeof opts.descriptor === "string") {
|
|
433
434
|
descriptor = opts.descriptor;
|
|
434
|
-
network =
|
|
435
|
+
network = chunk6YUACVX4_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
435
436
|
} else {
|
|
436
437
|
network = opts.isMainnet ?? true ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
437
438
|
descriptor = descriptorsScure.scriptExpressions.trBIP32({
|
|
@@ -529,7 +530,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
529
530
|
* `StaticDescriptorProvider` for legacy single-key wallets.
|
|
530
531
|
*/
|
|
531
532
|
isOurs(descriptor) {
|
|
532
|
-
return
|
|
533
|
+
return chunk6YUACVX4_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
|
|
533
534
|
}
|
|
534
535
|
/**
|
|
535
536
|
* Signs each request with the key derived from its descriptor.
|
|
@@ -578,7 +579,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
578
579
|
}
|
|
579
580
|
// ── internal helpers ─────────────────────────────────────────────
|
|
580
581
|
derivePrivateKeyForDescriptor(descriptor) {
|
|
581
|
-
const network =
|
|
582
|
+
const network = chunk6YUACVX4_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
582
583
|
const expansion = descriptorsScure.expand({ descriptor, network });
|
|
583
584
|
if (expansion.isRanged) {
|
|
584
585
|
throw new Error(
|
|
@@ -603,8 +604,9 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
603
604
|
signTxWithKey(tx, key, inputIndexes) {
|
|
604
605
|
const txCpy = tx.clone();
|
|
605
606
|
if (!inputIndexes) {
|
|
607
|
+
chunkEJOFL5WH_cjs.assertAllowedSighashTypes(txCpy, ALLOWED_SIGHASH2);
|
|
606
608
|
try {
|
|
607
|
-
if (!txCpy.sign(key,
|
|
609
|
+
if (!txCpy.sign(key, ALLOWED_SIGHASH2)) {
|
|
608
610
|
throw new Error("Failed to sign transaction");
|
|
609
611
|
}
|
|
610
612
|
} catch (e) {
|
|
@@ -614,7 +616,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
614
616
|
}
|
|
615
617
|
} else {
|
|
616
618
|
for (const idx of inputIndexes) {
|
|
617
|
-
if (!txCpy.signIdx(key, idx,
|
|
619
|
+
if (!txCpy.signIdx(key, idx, ALLOWED_SIGHASH2)) {
|
|
618
620
|
throw new Error(`Failed to sign input #${idx}`);
|
|
619
621
|
}
|
|
620
622
|
}
|
|
@@ -664,7 +666,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
|
|
|
664
666
|
*/
|
|
665
667
|
descriptor;
|
|
666
668
|
constructor(descriptor) {
|
|
667
|
-
const network =
|
|
669
|
+
const network = chunk6YUACVX4_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
668
670
|
let expansion;
|
|
669
671
|
try {
|
|
670
672
|
expansion = descriptorsScure.expand({ descriptor, network, index: 0 });
|
|
@@ -714,7 +716,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
|
|
|
714
716
|
* `StaticDescriptorProvider` for legacy single-key wallets.
|
|
715
717
|
*/
|
|
716
718
|
isOurs(descriptor) {
|
|
717
|
-
return
|
|
719
|
+
return chunk6YUACVX4_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
|
|
718
720
|
}
|
|
719
721
|
};
|
|
720
722
|
function serializeSeedOwnedSigningIdentity(identity) {
|
|
@@ -876,10 +878,10 @@ var DescriptorIdentity = class {
|
|
|
876
878
|
this.base = base;
|
|
877
879
|
}
|
|
878
880
|
async xOnlyPublicKey() {
|
|
879
|
-
return
|
|
881
|
+
return chunk6YUACVX4_cjs.deriveDescriptorLeafPubKey(this.descriptor);
|
|
880
882
|
}
|
|
881
883
|
async compressedPublicKey() {
|
|
882
|
-
return
|
|
884
|
+
return chunk6YUACVX4_cjs.deriveDescriptorLeafCompressedPubKey(this.descriptor);
|
|
883
885
|
}
|
|
884
886
|
async sign(tx, inputIndexes) {
|
|
885
887
|
const [signed] = await this.signer.signWithDescriptor([
|
|
@@ -939,14 +941,20 @@ var ForeignDescriptorError = class extends Error {
|
|
|
939
941
|
descriptor;
|
|
940
942
|
name = "ForeignDescriptorError";
|
|
941
943
|
};
|
|
944
|
+
var WalletCannotAllocateAddressError = class extends Error {
|
|
945
|
+
name = "WalletCannotAllocateAddressError";
|
|
946
|
+
constructor(reason, options) {
|
|
947
|
+
super(`cannot allocate a fresh address: ${reason}`, options);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
942
950
|
async function resolveDescriptorSigner(descriptor, identity, provider) {
|
|
943
951
|
const owner = provider?.isOurs(descriptor) ? provider : isHDCapableIdentity(identity) && identity.isOurs(descriptor) ? identity : void 0;
|
|
944
|
-
if (owner &&
|
|
952
|
+
if (owner && chunk6YUACVX4_cjs.parseHDDescriptor(descriptor)) {
|
|
945
953
|
return new DescriptorIdentity({ descriptor, signer: owner, base: identity });
|
|
946
954
|
}
|
|
947
955
|
let key;
|
|
948
956
|
try {
|
|
949
|
-
key =
|
|
957
|
+
key = chunk6YUACVX4_cjs.deriveDescriptorLeafPubKey(descriptor);
|
|
950
958
|
} catch {
|
|
951
959
|
throw new ForeignDescriptorError(descriptor);
|
|
952
960
|
}
|
|
@@ -963,6 +971,10 @@ function isHDAllocationCapable(value) {
|
|
|
963
971
|
const v = value;
|
|
964
972
|
return typeof v.getNextSigningDescriptor === "function" && typeof v.advanceSigningDescriptorWatermark === "function";
|
|
965
973
|
}
|
|
974
|
+
function isAddressAllocationCapable(value) {
|
|
975
|
+
if (typeof value !== "object" || value === null) return false;
|
|
976
|
+
return typeof value.getNewAddresses === "function";
|
|
977
|
+
}
|
|
966
978
|
|
|
967
979
|
// ../../node_modules/@noble/hashes/utils.js
|
|
968
980
|
function isBytes(a) {
|
|
@@ -1317,22 +1329,33 @@ function buildSaltedPreimageMessage(xonly, salt) {
|
|
|
1317
1329
|
}
|
|
1318
1330
|
var PREIMAGE_INDEX = 0;
|
|
1319
1331
|
function isPerArtifactDescriptor(descriptor) {
|
|
1320
|
-
return
|
|
1332
|
+
return chunk6YUACVX4_cjs.parseHDDescriptor(descriptor) !== null;
|
|
1321
1333
|
}
|
|
1322
1334
|
async function provisionDescriptor(wallet) {
|
|
1323
1335
|
const allocated = isHDAllocationCapable(wallet) ? await wallet.getNextSigningDescriptor() : void 0;
|
|
1324
|
-
return allocated ?? await
|
|
1336
|
+
return allocated ?? await chunk6YUACVX4_cjs.identityDescriptor(wallet.identity);
|
|
1325
1337
|
}
|
|
1326
1338
|
async function provisionRefundKey(wallet) {
|
|
1327
|
-
const descriptor = await
|
|
1339
|
+
const descriptor = await chunk6YUACVX4_cjs.identityDescriptor(wallet.identity);
|
|
1328
1340
|
const signer = await contractSigner(wallet, descriptor);
|
|
1329
|
-
|
|
1341
|
+
const pubkey = await signer.xOnlyPublicKey();
|
|
1342
|
+
const identityPubkey = await wallet.identity.xOnlyPublicKey();
|
|
1343
|
+
if (!utils_js.equalBytes(pubkey, identityPubkey)) {
|
|
1344
|
+
throw new Error(
|
|
1345
|
+
"provisionRefundKey: descriptor pubkey does not match wallet identity \u2014 the refund key and the refund address would be on different keys"
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
const address = await wallet.getAddress();
|
|
1349
|
+
const { pkScript } = chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
1350
|
+
return { descriptor, pubkey, pkScript, address };
|
|
1330
1351
|
}
|
|
1331
1352
|
async function provisionClaimSecret(wallet, opts = {}) {
|
|
1332
1353
|
if (opts.preimage && opts.preimage.length !== 32) {
|
|
1333
1354
|
throw new Error(`preimage must be 32 bytes, got ${opts.preimage.length}`);
|
|
1334
1355
|
}
|
|
1335
|
-
const
|
|
1356
|
+
const descriptor = await provisionDescriptor(wallet);
|
|
1357
|
+
const signer = await contractSigner(wallet, descriptor);
|
|
1358
|
+
const pubkey = await signer.xOnlyPublicKey();
|
|
1336
1359
|
const claim = async () => {
|
|
1337
1360
|
if (opts.preimage) return { preimage: opts.preimage, mustPersistPreimage: true };
|
|
1338
1361
|
if (isPerArtifactDescriptor(descriptor)) {
|
|
@@ -1369,7 +1392,7 @@ async function contractSigner(wallet, descriptor) {
|
|
|
1369
1392
|
const signer = isHDWalletCapable(wallet) ? await wallet.signerForDescriptor(descriptor) : wallet.identity;
|
|
1370
1393
|
let expected;
|
|
1371
1394
|
try {
|
|
1372
|
-
expected =
|
|
1395
|
+
expected = chunk6YUACVX4_cjs.deriveDescriptorLeafPubKey(descriptor);
|
|
1373
1396
|
} catch (cause) {
|
|
1374
1397
|
throw new ForeignDescriptorError(descriptor, { cause });
|
|
1375
1398
|
}
|
|
@@ -1588,14 +1611,14 @@ var RestDelegateProvider = class {
|
|
|
1588
1611
|
*/
|
|
1589
1612
|
async delegate(intent, forfeitTxs, options) {
|
|
1590
1613
|
const url = `${this.url}/v1/delegate`;
|
|
1591
|
-
const response = await
|
|
1614
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(url, {
|
|
1592
1615
|
method: "POST",
|
|
1593
1616
|
headers: {
|
|
1594
1617
|
"Content-Type": "application/json"
|
|
1595
1618
|
},
|
|
1596
1619
|
body: JSON.stringify({
|
|
1597
1620
|
intent: {
|
|
1598
|
-
message:
|
|
1621
|
+
message: chunkEJOFL5WH_cjs.Intent.encodeMessage(intent.message),
|
|
1599
1622
|
proof: intent.proof
|
|
1600
1623
|
},
|
|
1601
1624
|
forfeit_txs: forfeitTxs,
|
|
@@ -1615,7 +1638,7 @@ var RestDelegateProvider = class {
|
|
|
1615
1638
|
*/
|
|
1616
1639
|
async getDelegateInfo() {
|
|
1617
1640
|
const url = `${this.url}/v1/delegator/info`;
|
|
1618
|
-
const response = await
|
|
1641
|
+
const response = await chunkEJOFL5WH_cjs.rateGate.runHttp(url, () => chunkEJOFL5WH_cjs.baseFetch(url));
|
|
1619
1642
|
if (!response.ok) {
|
|
1620
1643
|
const errorText2 = await response.text();
|
|
1621
1644
|
throw new Error(`Failed to get delegate info: ${errorText2}`);
|
|
@@ -1632,8 +1655,6 @@ var RestDelegatorProvider = RestDelegateProvider;
|
|
|
1632
1655
|
function isDelegateInfo(data) {
|
|
1633
1656
|
return !!data && typeof data === "object" && "pubkey" in data && "fee" in data && typeof data.pubkey === "string" && typeof data.fee === "string" && data.pubkey !== "" && data.fee !== "" && (typeof data.delegateAddress === "string" && data.delegateAddress !== "" || typeof data.delegatorAddress === "string" && data.delegatorAddress !== "");
|
|
1634
1657
|
}
|
|
1635
|
-
|
|
1636
|
-
// src/providers/onchain.ts
|
|
1637
1658
|
var ESPLORA_URL = {
|
|
1638
1659
|
bitcoin: "https://mempool.arkade.sh/api",
|
|
1639
1660
|
testnet: "https://mempool.space/testnet/api",
|
|
@@ -1642,7 +1663,7 @@ var ESPLORA_URL = {
|
|
|
1642
1663
|
regtest: "http://localhost:3000/api"
|
|
1643
1664
|
};
|
|
1644
1665
|
var EsploraProvider = class {
|
|
1645
|
-
constructor(baseUrl = ESPLORA_URL[
|
|
1666
|
+
constructor(baseUrl = ESPLORA_URL[chunkEJOFL5WH_cjs.DEFAULT_NETWORK_NAME], opts) {
|
|
1646
1667
|
this.baseUrl = baseUrl;
|
|
1647
1668
|
this.pollingInterval = opts?.pollingInterval ?? 15e3;
|
|
1648
1669
|
this.forcePolling = opts?.forcePolling ?? false;
|
|
@@ -1651,14 +1672,14 @@ var EsploraProvider = class {
|
|
|
1651
1672
|
pollingInterval;
|
|
1652
1673
|
forcePolling;
|
|
1653
1674
|
async getCoins(address) {
|
|
1654
|
-
const response = await
|
|
1675
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
|
|
1655
1676
|
if (!response.ok) {
|
|
1656
1677
|
throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
|
|
1657
1678
|
}
|
|
1658
1679
|
return response.json();
|
|
1659
1680
|
}
|
|
1660
1681
|
async getFeeRate() {
|
|
1661
|
-
const response = await
|
|
1682
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
|
|
1662
1683
|
if (response.status === 404) {
|
|
1663
1684
|
return void 0;
|
|
1664
1685
|
}
|
|
@@ -1679,7 +1700,7 @@ var EsploraProvider = class {
|
|
|
1679
1700
|
}
|
|
1680
1701
|
}
|
|
1681
1702
|
async getTxOutspends(txid) {
|
|
1682
|
-
const response = await
|
|
1703
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
|
|
1683
1704
|
if (!response.ok) {
|
|
1684
1705
|
const error = await response.text();
|
|
1685
1706
|
throw new Error(`Failed to get transaction outspends: ${error}`);
|
|
@@ -1687,15 +1708,23 @@ var EsploraProvider = class {
|
|
|
1687
1708
|
return response.json();
|
|
1688
1709
|
}
|
|
1689
1710
|
async getTransactions(address) {
|
|
1690
|
-
const response = await
|
|
1711
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
|
|
1691
1712
|
if (!response.ok) {
|
|
1692
1713
|
const error = await response.text();
|
|
1693
1714
|
throw new Error(`Failed to get transactions: ${error}`);
|
|
1694
1715
|
}
|
|
1695
1716
|
return response.json();
|
|
1696
1717
|
}
|
|
1718
|
+
async getRawTransaction(txid) {
|
|
1719
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/hex`);
|
|
1720
|
+
if (!response.ok) {
|
|
1721
|
+
const error = await response.text();
|
|
1722
|
+
throw new Error(`Failed to get raw transaction ${txid}: ${error}`);
|
|
1723
|
+
}
|
|
1724
|
+
return base.hex.decode((await response.text()).trim());
|
|
1725
|
+
}
|
|
1697
1726
|
async getTxStatus(txid) {
|
|
1698
|
-
const txresponse = await
|
|
1727
|
+
const txresponse = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
|
|
1699
1728
|
if (!txresponse.ok) {
|
|
1700
1729
|
throw new Error(txresponse.statusText);
|
|
1701
1730
|
}
|
|
@@ -1703,7 +1732,7 @@ var EsploraProvider = class {
|
|
|
1703
1732
|
if (!tx.status.confirmed) {
|
|
1704
1733
|
return { confirmed: false };
|
|
1705
1734
|
}
|
|
1706
|
-
const response = await
|
|
1735
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
|
|
1707
1736
|
if (!response.ok) {
|
|
1708
1737
|
throw new Error(`Failed to get transaction status: ${response.statusText}`);
|
|
1709
1738
|
}
|
|
@@ -1787,7 +1816,7 @@ var EsploraProvider = class {
|
|
|
1787
1816
|
return stopFunc;
|
|
1788
1817
|
}
|
|
1789
1818
|
async getChainTip() {
|
|
1790
|
-
const tipBlocks = await
|
|
1819
|
+
const tipBlocks = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/blocks`);
|
|
1791
1820
|
if (!tipBlocks.ok) {
|
|
1792
1821
|
throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
|
|
1793
1822
|
}
|
|
@@ -1806,7 +1835,7 @@ var EsploraProvider = class {
|
|
|
1806
1835
|
};
|
|
1807
1836
|
}
|
|
1808
1837
|
async broadcastPackage(parent, child) {
|
|
1809
|
-
const response = await
|
|
1838
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
|
|
1810
1839
|
method: "POST",
|
|
1811
1840
|
headers: {
|
|
1812
1841
|
"Content-Type": "application/json"
|
|
@@ -1817,10 +1846,12 @@ var EsploraProvider = class {
|
|
|
1817
1846
|
const error = await response.text();
|
|
1818
1847
|
throw new Error(`Failed to broadcast package: ${error}`);
|
|
1819
1848
|
}
|
|
1820
|
-
|
|
1849
|
+
const result = await response.json();
|
|
1850
|
+
assertPackageAccepted(result);
|
|
1851
|
+
return result;
|
|
1821
1852
|
}
|
|
1822
1853
|
async broadcastTx(tx) {
|
|
1823
|
-
const response = await
|
|
1854
|
+
const response = await chunkEJOFL5WH_cjs.baseFetch(`${this.baseUrl}/tx`, {
|
|
1824
1855
|
method: "POST",
|
|
1825
1856
|
headers: {
|
|
1826
1857
|
"Content-Type": "text/plain"
|
|
@@ -1834,6 +1865,24 @@ var EsploraProvider = class {
|
|
|
1834
1865
|
return response.text();
|
|
1835
1866
|
}
|
|
1836
1867
|
};
|
|
1868
|
+
function assertPackageAccepted(result) {
|
|
1869
|
+
if (!result || typeof result !== "object") return;
|
|
1870
|
+
const r = result;
|
|
1871
|
+
const msg = typeof r.package_msg === "string" ? r.package_msg : void 0;
|
|
1872
|
+
if (msg === void 0 || msg === "success") return;
|
|
1873
|
+
const reasons = [];
|
|
1874
|
+
const results = r["tx-results"];
|
|
1875
|
+
if (results && typeof results === "object") {
|
|
1876
|
+
for (const entry of Object.values(results)) {
|
|
1877
|
+
if (!entry || typeof entry !== "object" || entry.error === void 0) continue;
|
|
1878
|
+
const txid = typeof entry.txid === "string" ? entry.txid : "unknown tx";
|
|
1879
|
+
reasons.push(`${txid}: ${String(entry.error)}`);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
throw new Error(
|
|
1883
|
+
reasons.length > 0 ? `Package rejected (${msg}) \u2014 ${reasons.join("; ")}` : `Package rejected (${msg})`
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1837
1886
|
function isValidBlocksTip(tip) {
|
|
1838
1887
|
return Array.isArray(tip) && tip.every((t) => {
|
|
1839
1888
|
return t && typeof t === "object" && typeof t.id === "string" && t.id.length > 0 && typeof t.height === "number" && t.height >= 0 && typeof t.mediantime === "number" && t.mediantime > 0;
|
|
@@ -1982,7 +2031,7 @@ function findP2AOutput(tx) {
|
|
|
1982
2031
|
var CHILD_DUST_AMOUNT = 546;
|
|
1983
2032
|
function buildAnchorChild(params) {
|
|
1984
2033
|
const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
|
|
1985
|
-
const child = new
|
|
2034
|
+
const child = new chunkEJOFL5WH_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
|
|
1986
2035
|
child.addInput(findP2AOutput(parent));
|
|
1987
2036
|
const estimator = TxWeightEstimator.create().addP2AInput();
|
|
1988
2037
|
for (const _ of fundingCoins) {
|
|
@@ -2030,7 +2079,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
|
|
|
2030
2079
|
);
|
|
2031
2080
|
}
|
|
2032
2081
|
function buildForfeitTxWithOutput(inputs, output, txLocktime) {
|
|
2033
|
-
const tx = new
|
|
2082
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({
|
|
2034
2083
|
version: 3,
|
|
2035
2084
|
lockTime: txLocktime
|
|
2036
2085
|
});
|
|
@@ -2106,7 +2155,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
2106
2155
|
if (previousScriptKey.length !== 32) {
|
|
2107
2156
|
throw new Error(`parent output ${childIndex} has invalid script`);
|
|
2108
2157
|
}
|
|
2109
|
-
const cosigners =
|
|
2158
|
+
const cosigners = chunkEJOFL5WH_cjs.getArkPsbtFields(child.root, 0, chunkEJOFL5WH_cjs.CosignerPublicKey);
|
|
2110
2159
|
if (cosigners.length === 0) {
|
|
2111
2160
|
throw ErrMissingCosignersPublicKeys;
|
|
2112
2161
|
}
|
|
@@ -2164,7 +2213,7 @@ var EmulatorPacket = class _EmulatorPacket {
|
|
|
2164
2213
|
return new _EmulatorPacket(entries);
|
|
2165
2214
|
}
|
|
2166
2215
|
static fromBytes(data) {
|
|
2167
|
-
const reader = new
|
|
2216
|
+
const reader = new chunkPJR63FTK_cjs.BufferReader(data);
|
|
2168
2217
|
const entryCount = reader.readCompactSize();
|
|
2169
2218
|
const entries = [];
|
|
2170
2219
|
for (let i = 0; i < entryCount; i++) {
|
|
@@ -2182,7 +2231,7 @@ var EmulatorPacket = class _EmulatorPacket {
|
|
|
2182
2231
|
return _EmulatorPacket.PACKET_TYPE;
|
|
2183
2232
|
}
|
|
2184
2233
|
serialize() {
|
|
2185
|
-
const writer = new
|
|
2234
|
+
const writer = new chunkPJR63FTK_cjs.BufferWriter();
|
|
2186
2235
|
writer.writeCompactSize(this.entries.length);
|
|
2187
2236
|
for (const entry of this.entries) {
|
|
2188
2237
|
writer.writeUint16LE(entry.vin);
|
|
@@ -2269,7 +2318,7 @@ var Extension = class _Extension {
|
|
|
2269
2318
|
`expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
|
|
2270
2319
|
);
|
|
2271
2320
|
}
|
|
2272
|
-
const reader = new
|
|
2321
|
+
const reader = new chunkPJR63FTK_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
|
|
2273
2322
|
const packets = [];
|
|
2274
2323
|
while (reader.remaining() > 0) {
|
|
2275
2324
|
const packetType = reader.readByte();
|
|
@@ -2343,7 +2392,7 @@ var Extension = class _Extension {
|
|
|
2343
2392
|
*/
|
|
2344
2393
|
getAssetPacket() {
|
|
2345
2394
|
for (const p of this.packets) {
|
|
2346
|
-
if (p instanceof
|
|
2395
|
+
if (p instanceof chunkPJR63FTK_cjs.Packet) {
|
|
2347
2396
|
return p;
|
|
2348
2397
|
}
|
|
2349
2398
|
}
|
|
@@ -2381,8 +2430,8 @@ var Extension = class _Extension {
|
|
|
2381
2430
|
};
|
|
2382
2431
|
function parsePacket(packetType, data) {
|
|
2383
2432
|
switch (packetType) {
|
|
2384
|
-
case
|
|
2385
|
-
return
|
|
2433
|
+
case chunkPJR63FTK_cjs.Packet.PACKET_TYPE:
|
|
2434
|
+
return chunkPJR63FTK_cjs.Packet.fromBytes(data);
|
|
2386
2435
|
case EmulatorPacket.PACKET_TYPE:
|
|
2387
2436
|
return EmulatorPacket.fromBytes(data);
|
|
2388
2437
|
default:
|
|
@@ -2429,16 +2478,16 @@ function buildOpReturnScript(data) {
|
|
|
2429
2478
|
}
|
|
2430
2479
|
return script;
|
|
2431
2480
|
}
|
|
2432
|
-
var ErrOffchainOutputNotFound = (address) => new
|
|
2433
|
-
var ErrInvalidAssetOutputAmount = (got, want, assetId) => new
|
|
2481
|
+
var ErrOffchainOutputNotFound = (address) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(`offchain send output not found: ${address}`);
|
|
2482
|
+
var ErrInvalidAssetOutputAmount = (got, want, assetId) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2434
2483
|
`invalid asset output amount for ${assetId}: got ${got}, want ${want}`
|
|
2435
2484
|
);
|
|
2436
|
-
var ErrAssetGroupNotFound = (assetId) => new
|
|
2437
|
-
var ErrAssetOutputNotFound = (assetId, outputIndex) => new
|
|
2485
|
+
var ErrAssetGroupNotFound = (assetId) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(`asset group not found in batch leaf: ${assetId}`);
|
|
2486
|
+
var ErrAssetOutputNotFound = (assetId, outputIndex) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2438
2487
|
`asset output not found in asset group ${assetId} at index ${outputIndex}`
|
|
2439
2488
|
);
|
|
2440
|
-
var ErrOnchainOutputNotFound = (address) => new
|
|
2441
|
-
var ErrUnvalidatedOffchainOutput = (address) => new
|
|
2489
|
+
var ErrOnchainOutputNotFound = (address) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(`onchain output not found: ${address}`);
|
|
2490
|
+
var ErrUnvalidatedOffchainOutput = (address) => new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2442
2491
|
`offchain output ${address} cannot be validated: virtual output tree signing did not run`
|
|
2443
2492
|
);
|
|
2444
2493
|
var ErrInvalidOnchainOutputAmount = (address) => new Error(`invalid onchain output amount: ${address}`);
|
|
@@ -2447,7 +2496,7 @@ var ErrInvalidOffchainOutputAmount = (address) => new Error(`invalid offchain ou
|
|
|
2447
2496
|
function assertFinalCommitmentMatchesValidated(finalCommitmentTx, validatedCommitmentTxid, context) {
|
|
2448
2497
|
if (!validatedCommitmentTxid) return;
|
|
2449
2498
|
if (finalCommitmentTx.id === validatedCommitmentTxid) return;
|
|
2450
|
-
throw new
|
|
2499
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2451
2500
|
`${context}: finalization commitment tx ${finalCommitmentTx.id} differs from the validated commitment tx ${validatedCommitmentTxid}`
|
|
2452
2501
|
);
|
|
2453
2502
|
}
|
|
@@ -2457,7 +2506,7 @@ function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, netwo
|
|
|
2457
2506
|
for (const recipient of recipients) {
|
|
2458
2507
|
let arkAddress;
|
|
2459
2508
|
try {
|
|
2460
|
-
arkAddress =
|
|
2509
|
+
arkAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(recipient.address);
|
|
2461
2510
|
} catch {
|
|
2462
2511
|
validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
|
|
2463
2512
|
continue;
|
|
@@ -2469,7 +2518,7 @@ function validateBatchRecipientsWithoutTree(commitmentTx, recipients, network) {
|
|
|
2469
2518
|
const usedOnchainOutputs = /* @__PURE__ */ new Set();
|
|
2470
2519
|
for (const recipient of recipients) {
|
|
2471
2520
|
try {
|
|
2472
|
-
|
|
2521
|
+
chunkEJOFL5WH_cjs.ArkAddress.decode(recipient.address);
|
|
2473
2522
|
} catch {
|
|
2474
2523
|
validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
|
|
2475
2524
|
continue;
|
|
@@ -2702,7 +2751,7 @@ function assetMintResolver() {
|
|
|
2702
2751
|
if (!tx.assets?.length || !tx.key.arkTxid) return void 0;
|
|
2703
2752
|
const minted = tx.assets.filter((a) => {
|
|
2704
2753
|
try {
|
|
2705
|
-
return base.hex.encode(
|
|
2754
|
+
return base.hex.encode(chunkPJR63FTK_cjs.AssetId.fromString(a.assetId).txid) === tx.key.arkTxid;
|
|
2706
2755
|
} catch {
|
|
2707
2756
|
return false;
|
|
2708
2757
|
}
|
|
@@ -2745,7 +2794,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2745
2794
|
const existing = inputsByAssetId.get(asset.assetId);
|
|
2746
2795
|
inputsByAssetId.set(asset.assetId, [
|
|
2747
2796
|
...existing ?? [],
|
|
2748
|
-
|
|
2797
|
+
chunkPJR63FTK_cjs.AssetInput.create(inputIndex, asset.amount)
|
|
2749
2798
|
]);
|
|
2750
2799
|
}
|
|
2751
2800
|
}
|
|
@@ -2757,7 +2806,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2757
2806
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
2758
2807
|
outputsByAssetId.set(asset.assetId, [
|
|
2759
2808
|
...existing ?? [],
|
|
2760
|
-
|
|
2809
|
+
chunkPJR63FTK_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
2761
2810
|
]);
|
|
2762
2811
|
}
|
|
2763
2812
|
}
|
|
@@ -2768,7 +2817,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2768
2817
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
2769
2818
|
outputsByAssetId.set(asset.assetId, [
|
|
2770
2819
|
...existing ?? [],
|
|
2771
|
-
|
|
2820
|
+
chunkPJR63FTK_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
2772
2821
|
]);
|
|
2773
2822
|
}
|
|
2774
2823
|
}
|
|
@@ -2777,11 +2826,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2777
2826
|
for (const assetIdStr of allAssetIds) {
|
|
2778
2827
|
const inputs = inputsByAssetId.get(assetIdStr);
|
|
2779
2828
|
const outputs = outputsByAssetId.get(assetIdStr);
|
|
2780
|
-
const assetId =
|
|
2781
|
-
const group =
|
|
2829
|
+
const assetId = chunkPJR63FTK_cjs.AssetId.fromString(assetIdStr);
|
|
2830
|
+
const group = chunkPJR63FTK_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
|
|
2782
2831
|
groups.push(group);
|
|
2783
2832
|
}
|
|
2784
|
-
return
|
|
2833
|
+
return chunkPJR63FTK_cjs.Packet.create(groups);
|
|
2785
2834
|
}
|
|
2786
2835
|
function selectCoinsWithAsset(coins, assetId, requiredAmount) {
|
|
2787
2836
|
const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
|
|
@@ -2818,7 +2867,7 @@ function selectedCoinsToAssetInputs(selectedCoins) {
|
|
|
2818
2867
|
}
|
|
2819
2868
|
function toXOnlySignerHex(pubkeyHex) {
|
|
2820
2869
|
const bytes = base.hex.decode(pubkeyHex);
|
|
2821
|
-
if (bytes.length === 32 || bytes.length === 33) return base.hex.encode(
|
|
2870
|
+
if (bytes.length === 32 || bytes.length === 33) return base.hex.encode(chunk6YUACVX4_cjs.toXOnly(bytes, "signer key"));
|
|
2822
2871
|
throw new Error(`invalid signer pubkey length: expected 32 or 33 bytes, got ${bytes.length}`);
|
|
2823
2872
|
}
|
|
2824
2873
|
function signerSetFromInfo(info) {
|
|
@@ -2865,13 +2914,13 @@ var toTimelock = (value) => ({
|
|
|
2865
2914
|
var toSeconds = (t) => t.type === "seconds" ? t.value : t.value * NOMINAL_BLOCK_SECONDS;
|
|
2866
2915
|
function assertTimelockInPolicy(timelock, policy, label, overrideOption) {
|
|
2867
2916
|
if (policy.requireSeconds && timelock.type === "blocks") {
|
|
2868
|
-
throw new
|
|
2917
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2869
2918
|
`${label} rejected: block-typed timelocks are not accepted (got ${timelock.value})`
|
|
2870
2919
|
);
|
|
2871
2920
|
}
|
|
2872
2921
|
const seconds = toSeconds(timelock);
|
|
2873
2922
|
if (seconds < policy.minSeconds) {
|
|
2874
|
-
throw new
|
|
2923
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2875
2924
|
`${label} rejected: ${timelock.value} ${timelock.type} is below the ${policy.minSeconds}s floor; pass ${overrideOption}: ${seconds}n to Wallet.create to lower it`
|
|
2876
2925
|
);
|
|
2877
2926
|
}
|
|
@@ -2892,7 +2941,7 @@ function resolveBatchExpiryPolicy(network, overrides) {
|
|
|
2892
2941
|
}
|
|
2893
2942
|
function assertValidBatchExpiry(batchExpiry, policy) {
|
|
2894
2943
|
if (policy.advertisedVtxoTreeExpiry !== void 0 && batchExpiry !== policy.advertisedVtxoTreeExpiry) {
|
|
2895
|
-
throw new
|
|
2944
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2896
2945
|
`batch expiry rejected: ${batchExpiry} does not match the advertised vtxoTreeExpiry ${policy.advertisedVtxoTreeExpiry}`
|
|
2897
2946
|
);
|
|
2898
2947
|
}
|
|
@@ -2922,21 +2971,21 @@ function resolveCheckpointExitDelayPolicy(network, overrides) {
|
|
|
2922
2971
|
function assertValidServerUnrollScript(checkpointTapscript, policy) {
|
|
2923
2972
|
let script;
|
|
2924
2973
|
try {
|
|
2925
|
-
script =
|
|
2974
|
+
script = chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(base.hex.decode(checkpointTapscript));
|
|
2926
2975
|
} catch (e) {
|
|
2927
|
-
throw new
|
|
2976
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2928
2977
|
`checkpoint exit delay rejected: invalid checkpointTapscript from server (${e instanceof Error ? e.message : String(e)})`
|
|
2929
2978
|
);
|
|
2930
2979
|
}
|
|
2931
2980
|
if (policy.advertisedForfeitPubkey !== void 0) {
|
|
2932
2981
|
const { pubkeys } = script.params;
|
|
2933
2982
|
if (pubkeys.length !== 1) {
|
|
2934
|
-
throw new
|
|
2983
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2935
2984
|
`checkpoint exit delay rejected: checkpointTapscript must commit to exactly one pubkey, got ${pubkeys.length} [${pubkeys.map(base.hex.encode).join(", ")}]`
|
|
2936
2985
|
);
|
|
2937
2986
|
}
|
|
2938
2987
|
if (!utils_js.equalBytes(pubkeys[0], policy.advertisedForfeitPubkey)) {
|
|
2939
|
-
throw new
|
|
2988
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
2940
2989
|
`checkpoint exit delay rejected: checkpointTapscript pubkey ${base.hex.encode(pubkeys[0])} does not match the advertised forfeitPubkey ${base.hex.encode(policy.advertisedForfeitPubkey)}`
|
|
2941
2990
|
);
|
|
2942
2991
|
}
|
|
@@ -2980,8 +3029,8 @@ function buildOffchainTx(inputs, outputs, serverUnrollScript) {
|
|
|
2980
3029
|
function buildVirtualTx(inputs, outputs) {
|
|
2981
3030
|
let lockTime = 0n;
|
|
2982
3031
|
for (const input of inputs) {
|
|
2983
|
-
const tapscript =
|
|
2984
|
-
if (
|
|
3032
|
+
const tapscript = chunkEJOFL5WH_cjs.decodeTapscript(chunkEJOFL5WH_cjs.scriptFromTapLeafScript(input.tapLeafScript));
|
|
3033
|
+
if (chunkEJOFL5WH_cjs.CLTVMultisigTapscript.is(tapscript)) {
|
|
2985
3034
|
if (lockTime !== 0n) {
|
|
2986
3035
|
if (isSeconds(lockTime) !== isSeconds(tapscript.params.absoluteTimelock)) {
|
|
2987
3036
|
throw new Error("cannot mix seconds and blocks locktime");
|
|
@@ -2992,7 +3041,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
2992
3041
|
}
|
|
2993
3042
|
}
|
|
2994
3043
|
}
|
|
2995
|
-
const tx = new
|
|
3044
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({
|
|
2996
3045
|
version: 3,
|
|
2997
3046
|
lockTime: Number(lockTime)
|
|
2998
3047
|
});
|
|
@@ -3002,12 +3051,12 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
3002
3051
|
index: input.vout,
|
|
3003
3052
|
sequence: lockTime ? btcSigner.DEFAULT_SEQUENCE - 1 : void 0,
|
|
3004
3053
|
witnessUtxo: {
|
|
3005
|
-
script:
|
|
3054
|
+
script: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript,
|
|
3006
3055
|
amount: BigInt(input.value)
|
|
3007
3056
|
},
|
|
3008
3057
|
tapLeafScript: [input.tapLeafScript]
|
|
3009
3058
|
});
|
|
3010
|
-
|
|
3059
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(tx, i, chunkEJOFL5WH_cjs.VtxoTaprootTree, input.tapTree);
|
|
3011
3060
|
}
|
|
3012
3061
|
for (const output of outputs) {
|
|
3013
3062
|
tx.addOutput(output);
|
|
@@ -3016,8 +3065,8 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
3016
3065
|
return tx;
|
|
3017
3066
|
}
|
|
3018
3067
|
function buildCheckpointTx(vtxo, serverUnrollScript) {
|
|
3019
|
-
const collaborativeClosure =
|
|
3020
|
-
const checkpointVtxoScript = new
|
|
3068
|
+
const collaborativeClosure = chunkEJOFL5WH_cjs.decodeTapscript(chunkEJOFL5WH_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
|
|
3069
|
+
const checkpointVtxoScript = new chunkEJOFL5WH_cjs.VtxoScript([
|
|
3021
3070
|
serverUnrollScript.script,
|
|
3022
3071
|
collaborativeClosure.script
|
|
3023
3072
|
]);
|
|
@@ -3060,9 +3109,6 @@ function hasBoardingTxExpired(coin, boardingTimelock, chainTipHeight) {
|
|
|
3060
3109
|
const blockTime = BigInt(Math.floor(coin.status.block_time));
|
|
3061
3110
|
return blockTime + boardingTimelock.value <= now;
|
|
3062
3111
|
}
|
|
3063
|
-
function formatSighash(type) {
|
|
3064
|
-
return `0x${type.toString(16).padStart(2, "0")}`;
|
|
3065
|
-
}
|
|
3066
3112
|
function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubkeys = [], allowedSighashTypes = [btcSigner.SigHash.DEFAULT], expectedLeafHash) {
|
|
3067
3113
|
const input = tx.getInput(inputIndex);
|
|
3068
3114
|
const prevoutScripts = [];
|
|
@@ -3096,7 +3142,7 @@ function verifyTapscriptSignatures(tx, inputIndex, requiredSigners, excludePubke
|
|
|
3096
3142
|
const sighashType = signature.length === 65 ? signature[64] : btcSigner.SigHash.DEFAULT;
|
|
3097
3143
|
const sig = signature.subarray(0, 64);
|
|
3098
3144
|
if (!allowedSighashTypes.includes(sighashType)) {
|
|
3099
|
-
const sighashName = formatSighash(sighashType);
|
|
3145
|
+
const sighashName = chunkEJOFL5WH_cjs.formatSighash(sighashType);
|
|
3100
3146
|
throw new Error(
|
|
3101
3147
|
`Unallowed sighash type ${sighashName} for input ${inputIndex}, pubkey ${pubKeyHex}.`
|
|
3102
3148
|
);
|
|
@@ -3170,7 +3216,7 @@ function combineTapscriptSigs(signedTx, originalTx) {
|
|
|
3170
3216
|
}
|
|
3171
3217
|
function isValidArkAddress(address) {
|
|
3172
3218
|
try {
|
|
3173
|
-
|
|
3219
|
+
chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
3174
3220
|
return true;
|
|
3175
3221
|
} catch (e) {
|
|
3176
3222
|
return false;
|
|
@@ -3178,16 +3224,16 @@ function isValidArkAddress(address) {
|
|
|
3178
3224
|
}
|
|
3179
3225
|
function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, context) {
|
|
3180
3226
|
if (serverCheckpointTxs.length !== expectedCheckpoints.length) {
|
|
3181
|
-
throw new
|
|
3227
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3182
3228
|
`${context} returned ${serverCheckpointTxs.length} checkpoints, expected ${expectedCheckpoints.length}`
|
|
3183
3229
|
);
|
|
3184
3230
|
}
|
|
3185
3231
|
const byTxid = new Map(expectedCheckpoints.map((c) => [c.id, c]));
|
|
3186
3232
|
return serverCheckpointTxs.map((encoded, index) => {
|
|
3187
|
-
const server =
|
|
3233
|
+
const server = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(encoded));
|
|
3188
3234
|
const local = byTxid.get(server.id);
|
|
3189
3235
|
if (!local) {
|
|
3190
|
-
throw new
|
|
3236
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3191
3237
|
`${context} checkpoint ${index} txid ${server.id} does not match any submitted checkpoint`
|
|
3192
3238
|
);
|
|
3193
3239
|
}
|
|
@@ -3197,14 +3243,14 @@ function matchServerCheckpoints(serverCheckpointTxs, expectedCheckpoints, contex
|
|
|
3197
3243
|
}
|
|
3198
3244
|
function assertSubmittedArkTxid(response, signedArkTx, context) {
|
|
3199
3245
|
if (response.arkTxid !== signedArkTx.id) {
|
|
3200
|
-
throw new
|
|
3246
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3201
3247
|
`${context} returned ark txid ${response.arkTxid}, expected ${signedArkTx.id}`
|
|
3202
3248
|
);
|
|
3203
3249
|
}
|
|
3204
3250
|
if (response.finalArkTx === void 0) return;
|
|
3205
|
-
const finalTxid =
|
|
3251
|
+
const finalTxid = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx)).id;
|
|
3206
3252
|
if (finalTxid !== signedArkTx.id) {
|
|
3207
|
-
throw new
|
|
3253
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3208
3254
|
`${context} returned final ark tx ${finalTxid}, expected ${signedArkTx.id}`
|
|
3209
3255
|
);
|
|
3210
3256
|
}
|
|
@@ -3223,10 +3269,10 @@ function assertServerSignedLeaf(serverTx, localTx, inputIndex, serverPubkeyHex,
|
|
|
3223
3269
|
[serverPubkeyHex],
|
|
3224
3270
|
void 0,
|
|
3225
3271
|
void 0,
|
|
3226
|
-
payment_js.tapLeafHash(
|
|
3272
|
+
payment_js.tapLeafHash(chunkEJOFL5WH_cjs.scriptFromTapLeafScript(leaf))
|
|
3227
3273
|
);
|
|
3228
3274
|
} catch (error) {
|
|
3229
|
-
throw new
|
|
3275
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3230
3276
|
`${context}: input ${inputIndex} is not signed by the server on the leaf being spent (${error instanceof Error ? error.message : String(error)})`
|
|
3231
3277
|
);
|
|
3232
3278
|
}
|
|
@@ -3235,20 +3281,20 @@ function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, con
|
|
|
3235
3281
|
const byOutpoint = new Map(inputs.map((input) => [`${input.txid}:${input.vout}`, input]));
|
|
3236
3282
|
for (const [index, checkpoint] of checkpoints.entries()) {
|
|
3237
3283
|
if (checkpoint.inputsLength !== 1) {
|
|
3238
|
-
throw new
|
|
3284
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3239
3285
|
`${context}: checkpoint ${index} spends ${checkpoint.inputsLength} inputs, expected 1`
|
|
3240
3286
|
);
|
|
3241
3287
|
}
|
|
3242
3288
|
const spent = checkpoint.getInput(0);
|
|
3243
3289
|
if (!spent.txid || spent.index === void 0) {
|
|
3244
|
-
throw new
|
|
3290
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3245
3291
|
`${context}: checkpoint ${index} has no input outpoint`
|
|
3246
3292
|
);
|
|
3247
3293
|
}
|
|
3248
3294
|
const outpoint = `${base.hex.encode(spent.txid)}:${spent.index}`;
|
|
3249
3295
|
const input = byOutpoint.get(outpoint);
|
|
3250
3296
|
if (!input) {
|
|
3251
|
-
throw new
|
|
3297
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3252
3298
|
`${context}: checkpoint ${index} spends ${outpoint}, which is not one of the requested virtual outputs`
|
|
3253
3299
|
);
|
|
3254
3300
|
}
|
|
@@ -3256,7 +3302,7 @@ function assertCheckpointsMatchInputs(checkpoints, inputs, unrollCandidates, con
|
|
|
3256
3302
|
(unroll) => buildCheckpointTx(input, unroll).tx.id === checkpoint.id
|
|
3257
3303
|
);
|
|
3258
3304
|
if (!rebuilt) {
|
|
3259
|
-
throw new
|
|
3305
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3260
3306
|
`${context}: checkpoint ${index} txid ${checkpoint.id} differs from the checkpoint built locally for ${outpoint}`
|
|
3261
3307
|
);
|
|
3262
3308
|
}
|
|
@@ -3280,15 +3326,24 @@ async function submitOffchainTx(provider, offchainTx, signer, hooks, options) {
|
|
|
3280
3326
|
assertSubmittedArkTxid(response, signedArkTx, "submitTx");
|
|
3281
3327
|
const { arkTxid, signedCheckpointTxs } = response;
|
|
3282
3328
|
const matched = matchServerCheckpoints(signedCheckpointTxs, offchainTx.checkpoints, "submitTx");
|
|
3329
|
+
matched.forEach(({ server }, index) => {
|
|
3330
|
+
try {
|
|
3331
|
+
chunkEJOFL5WH_cjs.assertAllowedSighashTypes(server);
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3334
|
+
`submitTx checkpoint ${index}: ${error instanceof Error ? error.message : String(error)}`
|
|
3335
|
+
);
|
|
3336
|
+
}
|
|
3337
|
+
});
|
|
3283
3338
|
const verify = options?.verifyServerSignatures;
|
|
3284
3339
|
if (verify) {
|
|
3285
3340
|
if (response.finalArkTx === void 0) {
|
|
3286
|
-
throw new
|
|
3341
|
+
throw new chunkEJOFL5WH_cjs.ServerResponseMismatchError(
|
|
3287
3342
|
"submitTx: server returned no final ark tx to verify its signatures against"
|
|
3288
3343
|
);
|
|
3289
3344
|
}
|
|
3290
|
-
const finalArkTx =
|
|
3291
|
-
const serverPubkeyHex = base.hex.encode(
|
|
3345
|
+
const finalArkTx = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(response.finalArkTx));
|
|
3346
|
+
const serverPubkeyHex = base.hex.encode(chunk6YUACVX4_cjs.toXOnly(verify.serverPubkey, "server key"));
|
|
3292
3347
|
for (let i = 0; i < offchainTx.arkTx.inputsLength; i++) {
|
|
3293
3348
|
assertServerSignedLeaf(
|
|
3294
3349
|
finalArkTx,
|
|
@@ -3344,12 +3399,12 @@ function claimWithPreimageIdentity(identity, preimage) {
|
|
|
3344
3399
|
return {
|
|
3345
3400
|
...identity,
|
|
3346
3401
|
sign: async (tx, inputIndexes) => {
|
|
3347
|
-
const signed =
|
|
3402
|
+
const signed = chunkEJOFL5WH_cjs.Transaction.fromPSBT(
|
|
3348
3403
|
(await identity.sign(tx.clone(), inputIndexes)).toPSBT()
|
|
3349
3404
|
);
|
|
3350
3405
|
const indexes = inputIndexes ?? Array.from({ length: signed.inputsLength }, (_, i) => i);
|
|
3351
3406
|
for (const index of indexes) {
|
|
3352
|
-
|
|
3407
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(signed, index, chunkEJOFL5WH_cjs.ConditionWitness, [preimage]);
|
|
3353
3408
|
}
|
|
3354
3409
|
return signed;
|
|
3355
3410
|
}
|
|
@@ -3541,7 +3596,7 @@ function extendCoinWithTapscript(boardingTapscript, utxo) {
|
|
|
3541
3596
|
};
|
|
3542
3597
|
}
|
|
3543
3598
|
function deriveContractTapscripts(contract) {
|
|
3544
|
-
const handler =
|
|
3599
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
3545
3600
|
if (!handler) {
|
|
3546
3601
|
throw new Error(`No handler for contract type '${contract.type}'`);
|
|
3547
3602
|
}
|
|
@@ -3612,7 +3667,7 @@ function getRandomId() {
|
|
|
3612
3667
|
}
|
|
3613
3668
|
function isValidArkAddress2(address) {
|
|
3614
3669
|
try {
|
|
3615
|
-
|
|
3670
|
+
chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
3616
3671
|
return true;
|
|
3617
3672
|
} catch (e) {
|
|
3618
3673
|
return false;
|
|
@@ -3640,7 +3695,7 @@ function assertRecipientArkAddress(encoded, address, context) {
|
|
|
3640
3695
|
function assertTapTreeDerivesAddress(encoded, tapTree, address) {
|
|
3641
3696
|
let derived;
|
|
3642
3697
|
try {
|
|
3643
|
-
derived =
|
|
3698
|
+
derived = chunkEJOFL5WH_cjs.VtxoScript.decode(tapTree).pkScript;
|
|
3644
3699
|
} catch (e) {
|
|
3645
3700
|
throw new Error(
|
|
3646
3701
|
`Invalid tapTree for ${encoded}: ${e instanceof Error ? e.message : String(e)}`
|
|
@@ -3657,7 +3712,7 @@ function validateRecipients(recipients, dustAmount, context) {
|
|
|
3657
3712
|
for (const recipient of recipients) {
|
|
3658
3713
|
let address;
|
|
3659
3714
|
try {
|
|
3660
|
-
address =
|
|
3715
|
+
address = chunkEJOFL5WH_cjs.ArkAddress.decode(recipient.address);
|
|
3661
3716
|
} catch (e) {
|
|
3662
3717
|
throw new Error(`Invalid Arkade address: ${recipient.address}`);
|
|
3663
3718
|
}
|
|
@@ -3682,7 +3737,7 @@ function validateRecipients(recipients, dustAmount, context) {
|
|
|
3682
3737
|
|
|
3683
3738
|
// src/contracts/spendability.ts
|
|
3684
3739
|
function isContractGenericallySpendable(contract) {
|
|
3685
|
-
return
|
|
3740
|
+
return chunk6YUACVX4_cjs.contractHandlers.get(contract.type)?.isGenericallySpendable?.(contract) === true;
|
|
3686
3741
|
}
|
|
3687
3742
|
function gatedContracts(contracts) {
|
|
3688
3743
|
const gated = /* @__PURE__ */ new Map();
|
|
@@ -3695,7 +3750,7 @@ function gateExclusion(gated) {
|
|
|
3695
3750
|
return (vtxo) => {
|
|
3696
3751
|
const type = vtxo.script === void 0 ? void 0 : gated.get(vtxo.script);
|
|
3697
3752
|
if (type === void 0) return void 0;
|
|
3698
|
-
if (!
|
|
3753
|
+
if (!chunk6YUACVX4_cjs.contractHandlers.has(type)) {
|
|
3699
3754
|
return `at ${vtxo.script} (contract type '${type}') has no handler registered in this build`;
|
|
3700
3755
|
}
|
|
3701
3756
|
return `at ${vtxo.script} (contract type '${type}') is not generically spendable`;
|
|
@@ -3731,7 +3786,9 @@ function selectPendingRecoveryOutpoints(contractsWithVtxos, signerSet, nowSecond
|
|
|
3731
3786
|
continue;
|
|
3732
3787
|
}
|
|
3733
3788
|
for (const v of vtxos) {
|
|
3734
|
-
if (!
|
|
3789
|
+
if (!chunkEJOFL5WH_cjs.hasTerminalSpend(v) && !v.isSwept && !v.isUnrolled) {
|
|
3790
|
+
out.add(`${v.txid}:${v.vout}`);
|
|
3791
|
+
}
|
|
3735
3792
|
}
|
|
3736
3793
|
}
|
|
3737
3794
|
return out;
|
|
@@ -3764,10 +3821,10 @@ function byValueDescending(vtxos) {
|
|
|
3764
3821
|
return [...vtxos].sort((a, b) => b.value - a.value);
|
|
3765
3822
|
}
|
|
3766
3823
|
async function fetchTimeHeight(wallet) {
|
|
3767
|
-
return
|
|
3824
|
+
return chunkEJOFL5WH_cjs.resolveTimeHeight(wallet.onchainProvider);
|
|
3768
3825
|
}
|
|
3769
3826
|
function canMigrateBySend(vtxo, now) {
|
|
3770
|
-
if (!
|
|
3827
|
+
if (!chunkEJOFL5WH_cjs.canSpendOffchain(vtxo, now)) return false;
|
|
3771
3828
|
return vtxo.expiresAt !== void 0 || vtxo.expiresAtHeight !== void 0;
|
|
3772
3829
|
}
|
|
3773
3830
|
function byExpiryAscending(vtxos, now) {
|
|
@@ -3775,7 +3832,7 @@ function byExpiryAscending(vtxos, now) {
|
|
|
3775
3832
|
if (vtxo.isSwept) return -Infinity;
|
|
3776
3833
|
if (vtxo.expiresAt !== void 0) return vtxo.expiresAt.getTime();
|
|
3777
3834
|
if (vtxo.expiresAtHeight !== void 0) {
|
|
3778
|
-
return
|
|
3835
|
+
return chunkEJOFL5WH_cjs.isPastExpiry(vtxo, now) ? -Infinity : Infinity;
|
|
3779
3836
|
}
|
|
3780
3837
|
return Infinity;
|
|
3781
3838
|
};
|
|
@@ -3802,7 +3859,7 @@ function priceSettlementInputs(vtxos, estimator) {
|
|
|
3802
3859
|
const payable = [];
|
|
3803
3860
|
const net = /* @__PURE__ */ new Map();
|
|
3804
3861
|
for (const vtxo of vtxos) {
|
|
3805
|
-
const inputFee = estimator.evalOffchainInput(
|
|
3862
|
+
const inputFee = estimator.evalOffchainInput(chunkEJOFL5WH_cjs.toOffchainInputFeeParams(vtxo));
|
|
3806
3863
|
if (inputFee.satoshis >= vtxo.value) {
|
|
3807
3864
|
continue;
|
|
3808
3865
|
}
|
|
@@ -3828,7 +3885,7 @@ function deductOffchainOutputFee(subtotal, estimator, arkAddress) {
|
|
|
3828
3885
|
}
|
|
3829
3886
|
const outputFee = estimator.evalOffchainOutput({
|
|
3830
3887
|
amount: subtotal,
|
|
3831
|
-
script: base.hex.encode(
|
|
3888
|
+
script: base.hex.encode(chunkEJOFL5WH_cjs.ArkAddress.decode(arkAddress).pkScript)
|
|
3832
3889
|
});
|
|
3833
3890
|
return subtotal - BigInt(outputFee.satoshis);
|
|
3834
3891
|
}
|
|
@@ -3846,10 +3903,10 @@ var DEFAULT_SETTLEMENT_CONFIG = {
|
|
|
3846
3903
|
};
|
|
3847
3904
|
function getRecoverableVtxos(vtxos, dustAmount, now) {
|
|
3848
3905
|
return vtxos.filter((vtxo) => {
|
|
3849
|
-
if (
|
|
3906
|
+
if (chunkEJOFL5WH_cjs.canRecoverOnchain(vtxo, now)) {
|
|
3850
3907
|
return true;
|
|
3851
3908
|
}
|
|
3852
|
-
if (
|
|
3909
|
+
if (chunkEJOFL5WH_cjs.canSpendOffchain(vtxo, now) && vtxo.isPreconfirmed && isSubdust(vtxo, dustAmount)) {
|
|
3853
3910
|
return true;
|
|
3854
3911
|
}
|
|
3855
3912
|
return false;
|
|
@@ -3879,8 +3936,9 @@ function getRecoverableWithSubdust(vtxos, dustAmount, now) {
|
|
|
3879
3936
|
};
|
|
3880
3937
|
}
|
|
3881
3938
|
function isVtxoExpiringSoon(vtxo, thresholdMs) {
|
|
3939
|
+
if (vtxo.isUnrolled) return false;
|
|
3882
3940
|
const realThresholdMs = thresholdMs <= 100 ? DEFAULT_THRESHOLD_MS : thresholdMs;
|
|
3883
|
-
const expiresAt =
|
|
3941
|
+
const expiresAt = chunkEJOFL5WH_cjs.normalizeVtxo(vtxo).expiresAt;
|
|
3884
3942
|
if (expiresAt === void 0) return false;
|
|
3885
3943
|
const now = Date.now();
|
|
3886
3944
|
const batchExpiry = expiresAt.getTime();
|
|
@@ -3889,7 +3947,9 @@ function isVtxoExpiringSoon(vtxo, thresholdMs) {
|
|
|
3889
3947
|
}
|
|
3890
3948
|
function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount, now) {
|
|
3891
3949
|
return vtxos.filter(
|
|
3892
|
-
|
|
3950
|
+
// The leading exclusion covers the `isSubdust` arm too, which is a value
|
|
3951
|
+
// property and would otherwise re-admit an exited coin on its own.
|
|
3952
|
+
(vtxo) => !vtxo.isUnrolled && (isVtxoExpiringSoon(vtxo, thresholdMs) || chunkEJOFL5WH_cjs.canRecoverOnchain(vtxo, now) || isSubdust(vtxo, dustAmount))
|
|
3893
3953
|
);
|
|
3894
3954
|
}
|
|
3895
3955
|
function isMigrationCapable(wallet) {
|
|
@@ -4488,11 +4548,11 @@ var VtxoManager = class _VtxoManager {
|
|
|
4488
4548
|
`Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
|
|
4489
4549
|
);
|
|
4490
4550
|
}
|
|
4491
|
-
const tx = new
|
|
4551
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction();
|
|
4492
4552
|
for (const utxo of expiredUtxos) {
|
|
4493
|
-
const utxoScript =
|
|
4553
|
+
const utxoScript = chunkEJOFL5WH_cjs.VtxoScript.decode(utxo.tapTree);
|
|
4494
4554
|
const utxoExitLeaf = utxoScript.leaves.find(
|
|
4495
|
-
(leaf) =>
|
|
4555
|
+
(leaf) => chunkEJOFL5WH_cjs.CSVMultisigTapscript.isScriptValid(chunkEJOFL5WH_cjs.scriptFromTapLeafScript(leaf)) === true
|
|
4496
4556
|
);
|
|
4497
4557
|
if (!utxoExitLeaf) {
|
|
4498
4558
|
throw new Error(
|
|
@@ -4507,7 +4567,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
4507
4567
|
amount: BigInt(utxo.value)
|
|
4508
4568
|
},
|
|
4509
4569
|
tapLeafScript: [utxoExitLeaf],
|
|
4510
|
-
sequence:
|
|
4570
|
+
sequence: chunkEJOFL5WH_cjs.getSequence(utxoExitLeaf)
|
|
4511
4571
|
});
|
|
4512
4572
|
}
|
|
4513
4573
|
tx.addOutputAddress(boardingAddress, outputAmount, this.getNetwork());
|
|
@@ -4540,6 +4600,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
4540
4600
|
async getDeprecatedSignerStatus() {
|
|
4541
4601
|
const wallet = this.requireMigrationCapableWallet();
|
|
4542
4602
|
const info = await wallet.arkProvider.getInfo();
|
|
4603
|
+
await wallet.settleServerInfoChanges?.();
|
|
4543
4604
|
const { reports: vtxoReports } = await this.classifyDeprecatedSignerContracts(info);
|
|
4544
4605
|
const { reports: boardingReports } = await this.classifyDeprecatedSignerBoarding(info);
|
|
4545
4606
|
return mergeSignerReports(vtxoReports, boardingReports);
|
|
@@ -4553,26 +4614,33 @@ var VtxoManager = class _VtxoManager {
|
|
|
4553
4614
|
*/
|
|
4554
4615
|
async migrateCore(options) {
|
|
4555
4616
|
const wallet = this.requireMigrationCapableWallet();
|
|
4617
|
+
const signerBeforeRefresh = base.hex.encode(wallet.arkServerPublicKey);
|
|
4556
4618
|
const info = await wallet.arkProvider.getInfo();
|
|
4619
|
+
await wallet.settleServerInfoChanges?.();
|
|
4620
|
+
const rotatedOnRefresh = signerBeforeRefresh !== base.hex.encode(wallet.arkServerPublicKey);
|
|
4557
4621
|
wallet.refreshDeprecatedSigners(info);
|
|
4558
4622
|
const signerSet = signerSetFromInfo(info);
|
|
4559
4623
|
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
4560
4624
|
const walletSignerHex = base.hex.encode(wallet.arkServerPublicKey);
|
|
4561
4625
|
const walletClass = classifyAgainstSignerSet(walletSignerHex, signerSet, nowSeconds);
|
|
4562
4626
|
if (signerSet.deprecated.size === 0 && walletClass.status === "CURRENT") {
|
|
4563
|
-
return { rotated:
|
|
4627
|
+
return { rotated: rotatedOnRefresh, expired: [], signers: [] };
|
|
4564
4628
|
}
|
|
4565
4629
|
if (walletClass.status === "UNKNOWN_SIGNER") {
|
|
4566
4630
|
const { reports: vtxoReports2 } = await this.classifyDeprecatedSignerContracts(info);
|
|
4567
4631
|
const { reports: boardingReports2 } = await this.classifyDeprecatedSignerBoarding(info);
|
|
4568
4632
|
return {
|
|
4569
|
-
|
|
4633
|
+
// Normally false here — a drained rotation targets the active
|
|
4634
|
+
// signer, which classifies CURRENT, not UNKNOWN. It is true only
|
|
4635
|
+
// when a second rotation landed inside the drain, leaving us on a
|
|
4636
|
+
// signer newer than `info`: still a rotation this pass applied.
|
|
4637
|
+
rotated: rotatedOnRefresh,
|
|
4570
4638
|
expired: [],
|
|
4571
4639
|
signers: mergeSignerReports(vtxoReports2, boardingReports2),
|
|
4572
4640
|
skipped: "unknown-wallet-signer"
|
|
4573
4641
|
};
|
|
4574
4642
|
}
|
|
4575
|
-
const rotated = await this.ensureReceiveOnActiveSigner(info);
|
|
4643
|
+
const rotated = await this.ensureReceiveOnActiveSigner(info) || rotatedOnRefresh;
|
|
4576
4644
|
const {
|
|
4577
4645
|
reports: vtxoReports,
|
|
4578
4646
|
migratable: vtxoMigratable,
|
|
@@ -4741,8 +4809,9 @@ var VtxoManager = class _VtxoManager {
|
|
|
4741
4809
|
if (!serverPubKey) continue;
|
|
4742
4810
|
const cls = classifyAgainstSignerSet(serverPubKey, signerSet, nowSeconds);
|
|
4743
4811
|
if (cls.status === "CURRENT") continue;
|
|
4744
|
-
const
|
|
4745
|
-
const
|
|
4812
|
+
const live = vtxos.filter((v) => !v.isUnrolled);
|
|
4813
|
+
const recoverable = live.filter((v) => v.isSwept && !chunkEJOFL5WH_cjs.hasTerminalSpend(v));
|
|
4814
|
+
const spendable = live.filter((v) => !chunkEJOFL5WH_cjs.hasTerminalSpend(v) && !v.isSwept);
|
|
4746
4815
|
const value = spendable.reduce((sum, v) => sum + v.value, 0);
|
|
4747
4816
|
let recoverableCount = 0;
|
|
4748
4817
|
let recoverableValue = 0;
|
|
@@ -4755,7 +4824,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
4755
4824
|
awaitingSweepCount = spendable.length;
|
|
4756
4825
|
awaitingSweepValue = value;
|
|
4757
4826
|
for (const v of spendable) {
|
|
4758
|
-
const exp =
|
|
4827
|
+
const exp = chunkEJOFL5WH_cjs.toBatchExpiry(v);
|
|
4759
4828
|
if (exp !== void 0 && (nextSweepEta === void 0 || exp < nextSweepEta)) {
|
|
4760
4829
|
nextSweepEta = exp;
|
|
4761
4830
|
}
|
|
@@ -5016,7 +5085,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
5016
5085
|
/** Decodes the boarding tapscript exit path to extract the CSV timelock. */
|
|
5017
5086
|
getBoardingTimelock() {
|
|
5018
5087
|
const wallet = this.getSweepWallet();
|
|
5019
|
-
const exitScript =
|
|
5088
|
+
const exitScript = chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(
|
|
5020
5089
|
base.hex.decode(wallet.boardingTapscript.exitScript)
|
|
5021
5090
|
);
|
|
5022
5091
|
return exitScript.params.timelock;
|
|
@@ -5147,8 +5216,8 @@ var VtxoManager = class _VtxoManager {
|
|
|
5147
5216
|
* or doesn't carry the metadata.
|
|
5148
5217
|
*/
|
|
5149
5218
|
extractSpentOutpoint(error) {
|
|
5150
|
-
const ark =
|
|
5151
|
-
if (!
|
|
5219
|
+
const ark = chunkEJOFL5WH_cjs.maybeArkError(error);
|
|
5220
|
+
if (!chunkEJOFL5WH_cjs.isArkError(ark, chunkEJOFL5WH_cjs.ArkErrorName.VTXO_ALREADY_SPENT)) return void 0;
|
|
5152
5221
|
const raw = ark.metadata?.vtxo_outpoint;
|
|
5153
5222
|
if (typeof raw !== "string") return void 0;
|
|
5154
5223
|
const [txid, voutStr] = raw.split(":");
|
|
@@ -5338,7 +5407,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
5338
5407
|
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
5339
5408
|
break;
|
|
5340
5409
|
}
|
|
5341
|
-
const inputFee = estimator.evalOffchainInput(
|
|
5410
|
+
const inputFee = estimator.evalOffchainInput(chunkEJOFL5WH_cjs.toOffchainInputFeeParams(v));
|
|
5342
5411
|
if (inputFee.satoshis >= v.value) {
|
|
5343
5412
|
continue;
|
|
5344
5413
|
}
|
|
@@ -5358,7 +5427,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
5358
5427
|
const arkAddress = await this.wallet.getAddress();
|
|
5359
5428
|
const outputFee = estimator.evalOffchainOutput({
|
|
5360
5429
|
amount: totalAmount,
|
|
5361
|
-
script: base.hex.encode(
|
|
5430
|
+
script: base.hex.encode(chunkEJOFL5WH_cjs.ArkAddress.decode(arkAddress).pkScript)
|
|
5362
5431
|
});
|
|
5363
5432
|
totalAmount -= BigInt(outputFee.satoshis);
|
|
5364
5433
|
if (totalAmount < dustAmount) return;
|
|
@@ -5438,7 +5507,7 @@ var ArkNote = class _ArkNote {
|
|
|
5438
5507
|
this.value = value;
|
|
5439
5508
|
this.HRP = HRP;
|
|
5440
5509
|
const preimageHash = utils_js.sha256(this.preimage);
|
|
5441
|
-
this.vtxoScript = new
|
|
5510
|
+
this.vtxoScript = new chunkEJOFL5WH_cjs.VtxoScript([noteTapscript(preimageHash)]);
|
|
5442
5511
|
const leaf = this.vtxoScript.leaves[0];
|
|
5443
5512
|
this.txid = base.hex.encode(new Uint8Array(preimageHash).reverse());
|
|
5444
5513
|
this.tapTree = this.vtxoScript.encode();
|
|
@@ -5605,7 +5674,7 @@ var ArkadeCash = class _ArkadeCash {
|
|
|
5605
5674
|
const privateKey = data.slice(1, 33);
|
|
5606
5675
|
const serverPubKey = data.slice(33, 65);
|
|
5607
5676
|
const sequence = new DataView(data.buffer, data.byteOffset + 65, 4).getUint32(0, false);
|
|
5608
|
-
const csvTimelock =
|
|
5677
|
+
const csvTimelock = chunkEJOFL5WH_cjs.sequenceToTimelock(sequence);
|
|
5609
5678
|
return new _ArkadeCash(privateKey, serverPubKey, csvTimelock, decoded.prefix);
|
|
5610
5679
|
}
|
|
5611
5680
|
toString() {
|
|
@@ -5613,7 +5682,7 @@ var ArkadeCash = class _ArkadeCash {
|
|
|
5613
5682
|
data[0] = _ArkadeCash.Version;
|
|
5614
5683
|
data.set(this._privateKey, 1);
|
|
5615
5684
|
data.set(this._serverPubKey, 33);
|
|
5616
|
-
const sequence =
|
|
5685
|
+
const sequence = chunkEJOFL5WH_cjs.timelockToSequence(this.csvTimelock);
|
|
5617
5686
|
new DataView(data.buffer, data.byteOffset + 65, 4).setUint32(0, sequence, false);
|
|
5618
5687
|
const words = base.bech32m.toWords(data);
|
|
5619
5688
|
return base.bech32m.encode(this.hrp, words, 1023);
|
|
@@ -5622,7 +5691,7 @@ var ArkadeCash = class _ArkadeCash {
|
|
|
5622
5691
|
return SingleKey.fromPrivateKey(this._privateKey);
|
|
5623
5692
|
}
|
|
5624
5693
|
get vtxoScript() {
|
|
5625
|
-
return new
|
|
5694
|
+
return new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
5626
5695
|
pubKey: this._publicKey,
|
|
5627
5696
|
serverPubKey: this._serverPubKey,
|
|
5628
5697
|
csvTimelock: this.csvTimelock
|
|
@@ -5883,7 +5952,7 @@ async function captureExitBranch(params) {
|
|
|
5883
5952
|
const nonCommitment = ordered.filter((c) => chainTxTypeToChainedExit(c.type) !== 1 /* Commitment */).map((c) => c.txid);
|
|
5884
5953
|
if (nonCommitment.length > 0) {
|
|
5885
5954
|
for (const psbt of await resolver.getVirtualTxs(nonCommitment)) {
|
|
5886
|
-
psbtByTxid.set(
|
|
5955
|
+
psbtByTxid.set(chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
5887
5956
|
}
|
|
5888
5957
|
}
|
|
5889
5958
|
}
|
|
@@ -5926,10 +5995,10 @@ var IndexerExitDataSource = class {
|
|
|
5926
5995
|
while (hasMore) {
|
|
5927
5996
|
const { chain: page, page: meta } = await this.indexer.getVtxoChain(
|
|
5928
5997
|
{ txid: vtxo.txid, vout: vtxo.vout },
|
|
5929
|
-
{ pageIndex, pageSize:
|
|
5998
|
+
{ pageIndex, pageSize: chunkEJOFL5WH_cjs.DEFAULT_PAGE_SIZE }
|
|
5930
5999
|
);
|
|
5931
6000
|
chain.push(...page);
|
|
5932
|
-
hasMore = meta ? page.length ===
|
|
6001
|
+
hasMore = meta ? page.length === chunkEJOFL5WH_cjs.DEFAULT_PAGE_SIZE : false;
|
|
5933
6002
|
pageIndex++;
|
|
5934
6003
|
}
|
|
5935
6004
|
return chain;
|
|
@@ -5941,12 +6010,12 @@ var IndexerExitDataSource = class {
|
|
|
5941
6010
|
while (hasMore) {
|
|
5942
6011
|
const { txs, page } = await this.indexer.getVirtualTxs(txids, {
|
|
5943
6012
|
pageIndex,
|
|
5944
|
-
pageSize:
|
|
6013
|
+
pageSize: chunkEJOFL5WH_cjs.DEFAULT_PAGE_SIZE
|
|
5945
6014
|
});
|
|
5946
6015
|
for (const psbt of txs) {
|
|
5947
|
-
out.set(
|
|
6016
|
+
out.set(chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
5948
6017
|
}
|
|
5949
|
-
hasMore = page ? txs.length ===
|
|
6018
|
+
hasMore = page ? txs.length === chunkEJOFL5WH_cjs.DEFAULT_PAGE_SIZE : false;
|
|
5950
6019
|
pageIndex++;
|
|
5951
6020
|
}
|
|
5952
6021
|
return out;
|
|
@@ -5967,7 +6036,7 @@ function chainedTxTypeToChainTxType(t) {
|
|
|
5967
6036
|
}
|
|
5968
6037
|
}
|
|
5969
6038
|
function psbtInputTxids(psbtBase64) {
|
|
5970
|
-
const tx =
|
|
6039
|
+
const tx = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
|
|
5971
6040
|
const ids = [];
|
|
5972
6041
|
for (let i = 0; i < tx.inputsLength; i++) {
|
|
5973
6042
|
const txid = tx.getInput(i).txid;
|
|
@@ -6326,10 +6395,10 @@ async function resolveArkInfo(arkProvider, walletRepository) {
|
|
|
6326
6395
|
try {
|
|
6327
6396
|
info = await arkProvider.getInfo();
|
|
6328
6397
|
} catch (err) {
|
|
6329
|
-
if (!
|
|
6398
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
6330
6399
|
const snapshot = await loadArkInfoSnapshot(walletRepository);
|
|
6331
6400
|
if (!snapshot) {
|
|
6332
|
-
throw new
|
|
6401
|
+
throw new chunkEJOFL5WH_cjs.ProviderUnavailableError(
|
|
6333
6402
|
"Arkade server info is unavailable and no cached snapshot exists",
|
|
6334
6403
|
{ cause: err }
|
|
6335
6404
|
);
|
|
@@ -6412,6 +6481,13 @@ var TxTree = class {
|
|
|
6412
6481
|
if (nbOfInputs !== 1) {
|
|
6413
6482
|
throw new Error(`unexpected number of inputs: ${nbOfInputs}, expected 1`);
|
|
6414
6483
|
}
|
|
6484
|
+
if (this.root.lockTime !== 0) {
|
|
6485
|
+
throw new Error(`unexpected locktime: ${this.root.lockTime}, expected 0`);
|
|
6486
|
+
}
|
|
6487
|
+
const sequence = this.root.getInput(0).sequence;
|
|
6488
|
+
if (sequence !== void 0 && sequence !== btcSigner.DEFAULT_SEQUENCE) {
|
|
6489
|
+
throw new Error(`unexpected sequence: ${sequence}, expected ${btcSigner.DEFAULT_SEQUENCE}`);
|
|
6490
|
+
}
|
|
6415
6491
|
if (this.children.size > nbOfOutputs - 1) {
|
|
6416
6492
|
throw new Error(
|
|
6417
6493
|
`unexpected number of children: ${this.children.size}, expected maximum ${nbOfOutputs - 1}`
|
|
@@ -6712,7 +6788,7 @@ function collectArkTxidsNeedingCreatedAt(vtxos) {
|
|
|
6712
6788
|
return [...txids];
|
|
6713
6789
|
}
|
|
6714
6790
|
async function buildTransactionHistory(vtxos, allBoardingTxs, commitmentsToIgnore, resolveTxCreatedAt) {
|
|
6715
|
-
const fromOldestVtxo = vtxos.map(
|
|
6791
|
+
const fromOldestVtxo = vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
6716
6792
|
const txidsNeedingCreatedAt = resolveTxCreatedAt ? collectArkTxidsNeedingCreatedAt(fromOldestVtxo) : [];
|
|
6717
6793
|
const resolvedCreatedAt = resolveTxCreatedAt && txidsNeedingCreatedAt.length > 0 ? await resolveTxCreatedAt(txidsNeedingCreatedAt) : /* @__PURE__ */ new Map();
|
|
6718
6794
|
const unmatchedSettledBoardingTxs = allBoardingTxs.filter(isSettledBoardingReceive).sort((a, b) => a.createdAt - b.createdAt);
|
|
@@ -6876,7 +6952,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
6876
6952
|
const virtualCoins = await this.wallet.getSpendableVtxos({
|
|
6877
6953
|
withRecoverable: false
|
|
6878
6954
|
});
|
|
6879
|
-
const controlAssetRef = params.controlAssetId ?
|
|
6955
|
+
const controlAssetRef = params.controlAssetId ? chunkPJR63FTK_cjs.AssetRef.fromId(chunkPJR63FTK_cjs.AssetId.fromString(params.controlAssetId)) : null;
|
|
6880
6956
|
const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
|
|
6881
6957
|
let totalBtcSelected = 0n;
|
|
6882
6958
|
const assetChanges = /* @__PURE__ */ new Map();
|
|
@@ -6889,8 +6965,8 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
6889
6965
|
}
|
|
6890
6966
|
}
|
|
6891
6967
|
const groups = [];
|
|
6892
|
-
const issuedAssetOutput =
|
|
6893
|
-
const issuedAssetGroup =
|
|
6968
|
+
const issuedAssetOutput = chunkPJR63FTK_cjs.AssetOutput.create(0, params.amount);
|
|
6969
|
+
const issuedAssetGroup = chunkPJR63FTK_cjs.AssetGroup.create(
|
|
6894
6970
|
null,
|
|
6895
6971
|
controlAssetRef,
|
|
6896
6972
|
[],
|
|
@@ -6905,28 +6981,28 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
6905
6981
|
for (const [inputIndex, assets] of assetInputs) {
|
|
6906
6982
|
for (const asset of assets) {
|
|
6907
6983
|
if (asset.assetId !== assetId) continue;
|
|
6908
|
-
changeInputs.push(
|
|
6984
|
+
changeInputs.push(chunkPJR63FTK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
6909
6985
|
}
|
|
6910
6986
|
}
|
|
6911
6987
|
groups.push(
|
|
6912
|
-
|
|
6913
|
-
|
|
6988
|
+
chunkPJR63FTK_cjs.AssetGroup.create(
|
|
6989
|
+
chunkPJR63FTK_cjs.AssetId.fromString(assetId),
|
|
6914
6990
|
null,
|
|
6915
6991
|
changeInputs,
|
|
6916
|
-
[
|
|
6992
|
+
[chunkPJR63FTK_cjs.AssetOutput.create(0, amount)],
|
|
6917
6993
|
[]
|
|
6918
6994
|
)
|
|
6919
6995
|
);
|
|
6920
6996
|
}
|
|
6921
6997
|
}
|
|
6922
6998
|
const address = await this.wallet.getAddress();
|
|
6923
|
-
const outputAddress =
|
|
6999
|
+
const outputAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
6924
7000
|
const outputs = [
|
|
6925
7001
|
{
|
|
6926
7002
|
script: outputAddress.pkScript,
|
|
6927
7003
|
amount: BigInt(totalBtcSelected)
|
|
6928
7004
|
},
|
|
6929
|
-
Extension.create([
|
|
7005
|
+
Extension.create([chunkPJR63FTK_cjs.Packet.create(groups)]).txOut()
|
|
6930
7006
|
];
|
|
6931
7007
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
|
|
6932
7008
|
coinSelection.inputs,
|
|
@@ -6934,7 +7010,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
6934
7010
|
);
|
|
6935
7011
|
return {
|
|
6936
7012
|
arkTxId: arkTxid,
|
|
6937
|
-
assetId:
|
|
7013
|
+
assetId: chunkPJR63FTK_cjs.AssetId.create(arkTxid, 0).toString()
|
|
6938
7014
|
};
|
|
6939
7015
|
}
|
|
6940
7016
|
/**
|
|
@@ -7006,16 +7082,16 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
7006
7082
|
for (const [inputIndex, assets] of assetInputs) {
|
|
7007
7083
|
for (const asset of assets) {
|
|
7008
7084
|
if (asset.assetId !== params.assetId) continue;
|
|
7009
|
-
reissueInputs.push(
|
|
7085
|
+
reissueInputs.push(chunkPJR63FTK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
7010
7086
|
}
|
|
7011
7087
|
}
|
|
7012
7088
|
const totalAssetAmount = assetToReissueAmount + params.amount;
|
|
7013
|
-
const reissueAssetIdObj =
|
|
7014
|
-
const reissueAssetGroup =
|
|
7089
|
+
const reissueAssetIdObj = chunkPJR63FTK_cjs.AssetId.fromString(params.assetId);
|
|
7090
|
+
const reissueAssetGroup = chunkPJR63FTK_cjs.AssetGroup.create(
|
|
7015
7091
|
reissueAssetIdObj,
|
|
7016
7092
|
null,
|
|
7017
7093
|
reissueInputs,
|
|
7018
|
-
[
|
|
7094
|
+
[chunkPJR63FTK_cjs.AssetOutput.create(0, totalAssetAmount)],
|
|
7019
7095
|
[]
|
|
7020
7096
|
);
|
|
7021
7097
|
const groups = [reissueAssetGroup];
|
|
@@ -7024,27 +7100,27 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
7024
7100
|
for (const [inputIndex, assets] of assetInputs) {
|
|
7025
7101
|
for (const asset of assets) {
|
|
7026
7102
|
if (asset.assetId !== assetId) continue;
|
|
7027
|
-
changeInputs.push(
|
|
7103
|
+
changeInputs.push(chunkPJR63FTK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
7028
7104
|
}
|
|
7029
7105
|
}
|
|
7030
7106
|
groups.push(
|
|
7031
|
-
|
|
7032
|
-
|
|
7107
|
+
chunkPJR63FTK_cjs.AssetGroup.create(
|
|
7108
|
+
chunkPJR63FTK_cjs.AssetId.fromString(assetId),
|
|
7033
7109
|
null,
|
|
7034
7110
|
changeInputs,
|
|
7035
|
-
[
|
|
7111
|
+
[chunkPJR63FTK_cjs.AssetOutput.create(0, amount)],
|
|
7036
7112
|
[]
|
|
7037
7113
|
)
|
|
7038
7114
|
);
|
|
7039
7115
|
}
|
|
7040
7116
|
const address = await this.wallet.getAddress();
|
|
7041
|
-
const outputAddress =
|
|
7117
|
+
const outputAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
7042
7118
|
const outputs = [
|
|
7043
7119
|
{
|
|
7044
7120
|
script: outputAddress.pkScript,
|
|
7045
7121
|
amount: BigInt(totalBtcSelected)
|
|
7046
7122
|
},
|
|
7047
|
-
Extension.create([
|
|
7123
|
+
Extension.create([chunkPJR63FTK_cjs.Packet.create(groups)]).txOut()
|
|
7048
7124
|
];
|
|
7049
7125
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
7050
7126
|
return arkTxid;
|
|
@@ -7111,27 +7187,27 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
7111
7187
|
for (const [inputIndex, assets] of assetInputs) {
|
|
7112
7188
|
for (const asset of assets) {
|
|
7113
7189
|
if (asset.assetId !== assetId) continue;
|
|
7114
|
-
changeInputs.push(
|
|
7190
|
+
changeInputs.push(chunkPJR63FTK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
7115
7191
|
}
|
|
7116
7192
|
}
|
|
7117
7193
|
groups.push(
|
|
7118
|
-
|
|
7119
|
-
|
|
7194
|
+
chunkPJR63FTK_cjs.AssetGroup.create(
|
|
7195
|
+
chunkPJR63FTK_cjs.AssetId.fromString(assetId),
|
|
7120
7196
|
null,
|
|
7121
7197
|
changeInputs,
|
|
7122
|
-
amount > 0n ? [
|
|
7198
|
+
amount > 0n ? [chunkPJR63FTK_cjs.AssetOutput.create(0, amount)] : [],
|
|
7123
7199
|
[]
|
|
7124
7200
|
)
|
|
7125
7201
|
);
|
|
7126
7202
|
}
|
|
7127
7203
|
const address = await this.wallet.getAddress();
|
|
7128
|
-
const outputAddress =
|
|
7204
|
+
const outputAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(address);
|
|
7129
7205
|
const outputs = [
|
|
7130
7206
|
{
|
|
7131
7207
|
script: outputAddress.pkScript,
|
|
7132
7208
|
amount: BigInt(totalBtcSelected)
|
|
7133
7209
|
},
|
|
7134
|
-
Extension.create([
|
|
7210
|
+
Extension.create([chunkPJR63FTK_cjs.Packet.create(groups)]).txOut()
|
|
7135
7211
|
];
|
|
7136
7212
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
7137
7213
|
return arkTxid;
|
|
@@ -7156,7 +7232,7 @@ function castMetadata(metadata) {
|
|
|
7156
7232
|
} else {
|
|
7157
7233
|
throw new Error("Invalid metadata value type");
|
|
7158
7234
|
}
|
|
7159
|
-
md.push(
|
|
7235
|
+
md.push(chunkPJR63FTK_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
|
|
7160
7236
|
}
|
|
7161
7237
|
return md;
|
|
7162
7238
|
}
|
|
@@ -7177,10 +7253,10 @@ var DelegateManagerImpl = class {
|
|
|
7177
7253
|
if (vtxos.length === 0) {
|
|
7178
7254
|
return { delegated: [], failed: [] };
|
|
7179
7255
|
}
|
|
7180
|
-
const destinationScript =
|
|
7256
|
+
const destinationScript = chunkEJOFL5WH_cjs.ArkAddress.decode(destination).pkScript;
|
|
7181
7257
|
const arkInfo = await this.arkInfoProvider.getInfo();
|
|
7182
7258
|
const delegateInfo = await this.delegateProvider.getDelegateInfo();
|
|
7183
|
-
const eligible = vtxos.map(
|
|
7259
|
+
const eligible = vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo).filter(
|
|
7184
7260
|
(v) => isAnnotated(v) && findDelegateTapLeaf(v, delegateInfo.pubkey) !== void 0
|
|
7185
7261
|
);
|
|
7186
7262
|
if (eligible.length === 0) {
|
|
@@ -7209,11 +7285,11 @@ var DelegateManagerImpl = class {
|
|
|
7209
7285
|
const groupByExpiry = /* @__PURE__ */ new Map();
|
|
7210
7286
|
let recoverableVtxos = [];
|
|
7211
7287
|
for (const vtxo of eligible) {
|
|
7212
|
-
if (
|
|
7288
|
+
if (chunkEJOFL5WH_cjs.canRecoverOnchain(vtxo, now)) {
|
|
7213
7289
|
recoverableVtxos.push(vtxo);
|
|
7214
7290
|
continue;
|
|
7215
7291
|
}
|
|
7216
|
-
const expiry =
|
|
7292
|
+
const expiry = chunkEJOFL5WH_cjs.toBatchExpiry(vtxo);
|
|
7217
7293
|
if (!expiry) continue;
|
|
7218
7294
|
const dayKey = getDayTimestamp(expiry);
|
|
7219
7295
|
groupByExpiry.set(dayKey, [...groupByExpiry.get(dayKey) ?? [], vtxo]);
|
|
@@ -7278,7 +7354,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
7278
7354
|
}
|
|
7279
7355
|
if (!delegateAt) {
|
|
7280
7356
|
const now = { timestamp: /* @__PURE__ */ new Date() };
|
|
7281
|
-
const expiryTimestamp = vtxos.filter((coin) => !
|
|
7357
|
+
const expiryTimestamp = vtxos.filter((coin) => !chunkEJOFL5WH_cjs.canRecoverOnchain(coin, now) && chunkEJOFL5WH_cjs.toBatchExpiry(coin)).reduce((min, coin) => Math.min(min, chunkEJOFL5WH_cjs.toBatchExpiry(coin)), Number.MAX_SAFE_INTEGER);
|
|
7282
7358
|
if (!expiryTimestamp || expiryTimestamp === Number.MAX_SAFE_INTEGER) {
|
|
7283
7359
|
delegateAt = new Date(Date.now() + 1 * 60 * 1e3);
|
|
7284
7360
|
} else {
|
|
@@ -7307,7 +7383,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
7307
7383
|
let amount = 0n;
|
|
7308
7384
|
for (const coin of vtxos) {
|
|
7309
7385
|
const inputFee = estimator.evalOffchainInput({
|
|
7310
|
-
...
|
|
7386
|
+
...chunkEJOFL5WH_cjs.toOffchainInputFeeParams(coin),
|
|
7311
7387
|
type: "vtxo"
|
|
7312
7388
|
});
|
|
7313
7389
|
if (inputFee.value >= coin.value) {
|
|
@@ -7321,7 +7397,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
7321
7397
|
const delegateFee = BigInt(Number(fee));
|
|
7322
7398
|
if (delegateFee > 0n) {
|
|
7323
7399
|
outputs.push({
|
|
7324
|
-
script:
|
|
7400
|
+
script: chunkEJOFL5WH_cjs.ArkAddress.decode(delegateAddress).pkScript,
|
|
7325
7401
|
amount: delegateFee
|
|
7326
7402
|
});
|
|
7327
7403
|
}
|
|
@@ -7354,10 +7430,10 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
7354
7430
|
destinationScript
|
|
7355
7431
|
);
|
|
7356
7432
|
const forfeitOutputScript = btcSigner.OutScript.encode(
|
|
7357
|
-
btcSigner.Address(
|
|
7433
|
+
btcSigner.Address(chunkEJOFL5WH_cjs.getNetwork(network)).decode(forfeitAddress)
|
|
7358
7434
|
);
|
|
7359
7435
|
const forfeits = await Promise.all(
|
|
7360
|
-
vtxos.filter((v) => !
|
|
7436
|
+
vtxos.filter((v) => !chunkEJOFL5WH_cjs.canRecoverOnchain(v, { timestamp: /* @__PURE__ */ new Date() })).map(async (coin) => {
|
|
7361
7437
|
const forfeit = await makeDelegateForfeitTx(
|
|
7362
7438
|
coin,
|
|
7363
7439
|
dust,
|
|
@@ -7382,7 +7458,7 @@ async function makeDelegateForfeitTx(input, connectorAmount, delegatePubkey, for
|
|
|
7382
7458
|
index: input.vout,
|
|
7383
7459
|
witnessUtxo: {
|
|
7384
7460
|
amount: BigInt(input.value),
|
|
7385
|
-
script:
|
|
7461
|
+
script: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
7386
7462
|
},
|
|
7387
7463
|
sighashType: btcSigner.SigHash.ALL_ANYONECANPAY,
|
|
7388
7464
|
tapLeafScript: [delegateTapLeaf]
|
|
@@ -7440,7 +7516,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
|
|
|
7440
7516
|
expire_at: 0,
|
|
7441
7517
|
cosigners_public_keys: cosignerPubKeys
|
|
7442
7518
|
};
|
|
7443
|
-
const proof =
|
|
7519
|
+
const proof = chunkEJOFL5WH_cjs.Intent.create(message, coins, outputs);
|
|
7444
7520
|
const signedProof = await identity.sign(proof);
|
|
7445
7521
|
return {
|
|
7446
7522
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -7458,10 +7534,10 @@ function getDayTimestamp(timestamp) {
|
|
|
7458
7534
|
function findDelegateTapLeaf(vtxo, delegatePubkey) {
|
|
7459
7535
|
if (!vtxo.tapTree) return void 0;
|
|
7460
7536
|
const pk = delegatePubkey.length === 66 ? delegatePubkey.slice(2) : delegatePubkey;
|
|
7461
|
-
const vtxoScript =
|
|
7537
|
+
const vtxoScript = chunkEJOFL5WH_cjs.VtxoScript.decode(vtxo.tapTree);
|
|
7462
7538
|
return vtxoScript.leaves.find((tapLeaf) => {
|
|
7463
|
-
const arkTapscript =
|
|
7464
|
-
if (!
|
|
7539
|
+
const arkTapscript = chunkEJOFL5WH_cjs.decodeTapscript(chunkEJOFL5WH_cjs.scriptFromTapLeafScript(tapLeaf));
|
|
7540
|
+
if (!chunkEJOFL5WH_cjs.MultisigTapscript.is(arkTapscript)) return false;
|
|
7465
7541
|
return arkTapscript.params.pubkeys.map(base.hex.encode).includes(pk);
|
|
7466
7542
|
});
|
|
7467
7543
|
}
|
|
@@ -7742,7 +7818,7 @@ function createManagedConnection(dbName, version, initDatabase2) {
|
|
|
7742
7818
|
};
|
|
7743
7819
|
}
|
|
7744
7820
|
function scriptFromArkAddress(address) {
|
|
7745
|
-
return base.hex.encode(
|
|
7821
|
+
return base.hex.encode(chunkEJOFL5WH_cjs.ArkAddress.decode(address).pkScript);
|
|
7746
7822
|
}
|
|
7747
7823
|
|
|
7748
7824
|
// src/repositories/indexedDB/schema.ts
|
|
@@ -8237,7 +8313,7 @@ function validateVtxosForScript(vtxos, script, context) {
|
|
|
8237
8313
|
}
|
|
8238
8314
|
async function getVtxosForContract(repo, contract) {
|
|
8239
8315
|
const vtxos = repo.getVtxosForScript ? await repo.getVtxosForScript(contract.script) : filterVtxosForScript(await repo.getVtxos(contract.address), contract.script);
|
|
8240
|
-
return vtxos.map(
|
|
8316
|
+
return vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
8241
8317
|
}
|
|
8242
8318
|
async function saveVtxosForContract(repo, contract, vtxos) {
|
|
8243
8319
|
if (repo.saveVtxosForScript) {
|
|
@@ -8379,7 +8455,7 @@ function decodeArkContract(encoded) {
|
|
|
8379
8455
|
}
|
|
8380
8456
|
function contractFromArkContract(encoded, options = {}) {
|
|
8381
8457
|
const parsed = decodeArkContract(encoded);
|
|
8382
|
-
const handler =
|
|
8458
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(parsed.type);
|
|
8383
8459
|
if (!handler) {
|
|
8384
8460
|
throw new Error(`No handler registered for contract type '${parsed.type}'`);
|
|
8385
8461
|
}
|
|
@@ -8393,9 +8469,9 @@ function contractFromArkContract(encoded, options = {}) {
|
|
|
8393
8469
|
metadata: options.metadata
|
|
8394
8470
|
};
|
|
8395
8471
|
}
|
|
8396
|
-
function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix =
|
|
8472
|
+
function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunkEJOFL5WH_cjs.DEFAULT_NETWORK.hrp, options = {}) {
|
|
8397
8473
|
const parsed = decodeArkContract(encoded);
|
|
8398
|
-
const handler =
|
|
8474
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.getOrThrow(parsed.type);
|
|
8399
8475
|
const params = parsed.data;
|
|
8400
8476
|
const vtxoScript = handler.createScript(params);
|
|
8401
8477
|
return {
|
|
@@ -8649,9 +8725,9 @@ var ContractWatcher = class {
|
|
|
8649
8725
|
this.connectionState = "connected";
|
|
8650
8726
|
this.reconnectAttempts = 0;
|
|
8651
8727
|
this.listenLoop().catch((e) => {
|
|
8652
|
-
if (
|
|
8728
|
+
if (chunkEJOFL5WH_cjs.isEventSourceError(e)) {
|
|
8653
8729
|
console.debug("ContractWatcher subscription disconnected; reconnecting");
|
|
8654
|
-
} else if (!
|
|
8730
|
+
} else if (!chunkEJOFL5WH_cjs.isEventSourceUnavailableError(e)) {
|
|
8655
8731
|
console.error(e);
|
|
8656
8732
|
}
|
|
8657
8733
|
this.connectionState = "disconnected";
|
|
@@ -8663,7 +8739,7 @@ var ContractWatcher = class {
|
|
|
8663
8739
|
this.scheduleReconnect();
|
|
8664
8740
|
});
|
|
8665
8741
|
} catch (error) {
|
|
8666
|
-
if (!
|
|
8742
|
+
if (!chunkEJOFL5WH_cjs.isEventSourceUnavailableError(error)) {
|
|
8667
8743
|
console.error("ContractWatcher connection failed:", error);
|
|
8668
8744
|
}
|
|
8669
8745
|
this.connectionState = "disconnected";
|
|
@@ -8689,7 +8765,7 @@ var ContractWatcher = class {
|
|
|
8689
8765
|
* slower; what it loses is push latency.
|
|
8690
8766
|
*/
|
|
8691
8767
|
reportEventSourceUnavailable(error) {
|
|
8692
|
-
if (!
|
|
8768
|
+
if (!chunkEJOFL5WH_cjs.isEventSourceUnavailableError(error)) return false;
|
|
8693
8769
|
if (!this.eventSourceReported) {
|
|
8694
8770
|
this.eventSourceReported = true;
|
|
8695
8771
|
console.warn(
|
|
@@ -8905,14 +8981,14 @@ var ContractWatcher = class {
|
|
|
8905
8981
|
const timestamp = Date.now();
|
|
8906
8982
|
if (update.newVtxos?.length) {
|
|
8907
8983
|
this.processSubscriptionVtxos(
|
|
8908
|
-
update.newVtxos.map(
|
|
8984
|
+
update.newVtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo),
|
|
8909
8985
|
"vtxo_received",
|
|
8910
8986
|
timestamp
|
|
8911
8987
|
);
|
|
8912
8988
|
}
|
|
8913
8989
|
if (update.spentVtxos?.length) {
|
|
8914
8990
|
this.processSubscriptionVtxos(
|
|
8915
|
-
update.spentVtxos.map(
|
|
8991
|
+
update.spentVtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo),
|
|
8916
8992
|
"vtxo_spent",
|
|
8917
8993
|
timestamp
|
|
8918
8994
|
);
|
|
@@ -9007,7 +9083,7 @@ var NON_TERMINAL_INTENT_STATES = ALL_INTENT_STATES.filter(
|
|
|
9007
9083
|
(s) => !isTerminalIntentState(s)
|
|
9008
9084
|
);
|
|
9009
9085
|
function isConsumed(vtxo) {
|
|
9010
|
-
return vtxo !== void 0 && (vtxo
|
|
9086
|
+
return vtxo !== void 0 && chunkEJOFL5WH_cjs.hasTerminalSpend(vtxo);
|
|
9011
9087
|
}
|
|
9012
9088
|
async function classifyIntent(intent, vtxosByOutpoint, now) {
|
|
9013
9089
|
if (isTerminalIntentState(intent.state)) return void 0;
|
|
@@ -9017,6 +9093,11 @@ async function classifyIntent(intent, vtxosByOutpoint, now) {
|
|
|
9017
9093
|
const commitmentTransactionId = intent.commitmentTransactionId ?? consumed.map((v) => v?.settledBy).find((s) => !!s);
|
|
9018
9094
|
return terminal(intent, "batch_succeeded", now, { commitmentTransactionId });
|
|
9019
9095
|
}
|
|
9096
|
+
if (consumed.some((vtxo) => vtxo?.isUnrolled)) {
|
|
9097
|
+
return terminal(intent, "cancelled", now, {
|
|
9098
|
+
cancellationReason: "reconciliation: an input was unilaterally exited"
|
|
9099
|
+
});
|
|
9100
|
+
}
|
|
9020
9101
|
if (intent.state === "waiting_to_submit") {
|
|
9021
9102
|
return terminal(intent, "cancelled", now, {
|
|
9022
9103
|
cancellationReason: "reconciliation: intent was never submitted before restart"
|
|
@@ -9045,7 +9126,7 @@ async function reconcileIntents(deps) {
|
|
|
9045
9126
|
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
9046
9127
|
if (outpoints.length > 0) {
|
|
9047
9128
|
try {
|
|
9048
|
-
const { vtxos } = await
|
|
9129
|
+
const { vtxos } = await chunkEJOFL5WH_cjs.getNormalizedVtxos(deps.indexerProvider, { outpoints });
|
|
9049
9130
|
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
9050
9131
|
} catch (e) {
|
|
9051
9132
|
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
@@ -9219,7 +9300,7 @@ var ContractManager = class _ContractManager {
|
|
|
9219
9300
|
await this.reconcileWatched();
|
|
9220
9301
|
this.markSyncOnline();
|
|
9221
9302
|
} catch (err) {
|
|
9222
|
-
if (!
|
|
9303
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
9223
9304
|
this.markSyncDegraded(err);
|
|
9224
9305
|
}
|
|
9225
9306
|
this.initialized = true;
|
|
@@ -9351,7 +9432,7 @@ var ContractManager = class _ContractManager {
|
|
|
9351
9432
|
const from = Math.max(0, watermark - lookAhead.size);
|
|
9352
9433
|
const to = watermark + lookAhead.size;
|
|
9353
9434
|
const deps = lookAhead.candidateDeps();
|
|
9354
|
-
const handlers =
|
|
9435
|
+
const handlers = chunk6YUACVX4_cjs.contractHandlers.getRegisteredTypes().map((t) => chunk6YUACVX4_cjs.contractHandlers.get(t)).filter(hasCandidates);
|
|
9355
9436
|
const band = /* @__PURE__ */ new Map();
|
|
9356
9437
|
for (let index = from; index <= to; index++) {
|
|
9357
9438
|
const descriptor = lookAhead.materialize(index);
|
|
@@ -9362,7 +9443,7 @@ var ContractManager = class _ContractManager {
|
|
|
9362
9443
|
index,
|
|
9363
9444
|
params: {
|
|
9364
9445
|
...candidate,
|
|
9365
|
-
...
|
|
9446
|
+
...chunk6YUACVX4_cjs.speculativeReceiveMetadata(descriptor)
|
|
9366
9447
|
}
|
|
9367
9448
|
});
|
|
9368
9449
|
}
|
|
@@ -9424,7 +9505,7 @@ var ContractManager = class _ContractManager {
|
|
|
9424
9505
|
});
|
|
9425
9506
|
for (const entry of pending) entry.catchUpPending = false;
|
|
9426
9507
|
} catch (err) {
|
|
9427
|
-
if (!
|
|
9508
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
9428
9509
|
this.markSyncDegraded(err);
|
|
9429
9510
|
}
|
|
9430
9511
|
}
|
|
@@ -9474,7 +9555,7 @@ var ContractManager = class _ContractManager {
|
|
|
9474
9555
|
await this.fetchContractVxosFromIndexer([contract]);
|
|
9475
9556
|
this.markSyncOnline();
|
|
9476
9557
|
} catch (err) {
|
|
9477
|
-
if (!
|
|
9558
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
9478
9559
|
this.markSyncDegraded(err);
|
|
9479
9560
|
}
|
|
9480
9561
|
await this.watcher.addContract(contract);
|
|
@@ -9511,7 +9592,7 @@ var ContractManager = class _ContractManager {
|
|
|
9511
9592
|
return result;
|
|
9512
9593
|
}
|
|
9513
9594
|
async upsertContractRow(params) {
|
|
9514
|
-
const handler =
|
|
9595
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(params.type);
|
|
9515
9596
|
if (!handler) {
|
|
9516
9597
|
throw new Error(`No handler registered for contract type '${params.type}'`);
|
|
9517
9598
|
}
|
|
@@ -9611,7 +9692,7 @@ var ContractManager = class _ContractManager {
|
|
|
9611
9692
|
`scanContracts: batchSize must be a positive integer (got ${String(opts.batchSize)})`
|
|
9612
9693
|
);
|
|
9613
9694
|
}
|
|
9614
|
-
const registered =
|
|
9695
|
+
const registered = chunk6YUACVX4_cjs.contractHandlers.getRegisteredTypes().map((t) => chunk6YUACVX4_cjs.contractHandlers.get(t)).filter(isDiscoverable);
|
|
9615
9696
|
const discoverables = [
|
|
9616
9697
|
...registered.filter((h) => h.type === "boarding"),
|
|
9617
9698
|
...registered.filter((h) => h.type !== "boarding")
|
|
@@ -9746,7 +9827,7 @@ var ContractManager = class _ContractManager {
|
|
|
9746
9827
|
await this.syncContracts({ contracts, pageSize });
|
|
9747
9828
|
this.markSyncOnline();
|
|
9748
9829
|
} catch (err) {
|
|
9749
|
-
if (!
|
|
9830
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
9750
9831
|
this.markSyncDegraded(err);
|
|
9751
9832
|
}
|
|
9752
9833
|
const vtxos = await this.getVtxosForContracts(contracts);
|
|
@@ -9767,7 +9848,7 @@ var ContractManager = class _ContractManager {
|
|
|
9767
9848
|
}
|
|
9768
9849
|
const tapscriptCache = tapscripts ?? /* @__PURE__ */ new Map();
|
|
9769
9850
|
return vtxos.map(
|
|
9770
|
-
(vtxo) => extendVirtualCoinForContract(
|
|
9851
|
+
(vtxo) => extendVirtualCoinForContract(chunkEJOFL5WH_cjs.normalizeVtxo(vtxo), byScript, tapscriptCache)
|
|
9771
9852
|
);
|
|
9772
9853
|
}
|
|
9773
9854
|
/** @inheritdoc */
|
|
@@ -9811,14 +9892,14 @@ var ContractManager = class _ContractManager {
|
|
|
9811
9892
|
const byScript = new Map(contracts.map((contract) => [contract.script, contract]));
|
|
9812
9893
|
const asking = vtxos.filter((vtxo) => {
|
|
9813
9894
|
const contract = byScript.get(vtxo.script);
|
|
9814
|
-
return contract !== void 0 &&
|
|
9895
|
+
return contract !== void 0 && chunk6YUACVX4_cjs.contractHandlers.get(contract.type)?.assertSpendableNow !== void 0;
|
|
9815
9896
|
});
|
|
9816
9897
|
if (asking.length === 0) return refused;
|
|
9817
9898
|
const tip = await this.currentChainTip();
|
|
9818
9899
|
const walletKey = await walletPubKey?.();
|
|
9819
9900
|
for (const vtxo of asking) {
|
|
9820
9901
|
const contract = byScript.get(vtxo.script);
|
|
9821
|
-
const handler =
|
|
9902
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
9822
9903
|
if (!handler?.assertSpendableNow) continue;
|
|
9823
9904
|
const context = {
|
|
9824
9905
|
collaborative: true,
|
|
@@ -9833,7 +9914,7 @@ var ContractManager = class _ContractManager {
|
|
|
9833
9914
|
// the next handler to answer a CSV question would meet a
|
|
9834
9915
|
// TypeError instead of a `false`. Carry the coin only when it
|
|
9835
9916
|
// really is one.
|
|
9836
|
-
vtxo:
|
|
9917
|
+
vtxo: chunkEJOFL5WH_cjs.isVirtualCoin(vtxo) && "status" in vtxo ? vtxo : void 0
|
|
9837
9918
|
};
|
|
9838
9919
|
try {
|
|
9839
9920
|
await handler.assertSpendableNow(
|
|
@@ -9989,7 +10070,7 @@ var ContractManager = class _ContractManager {
|
|
|
9989
10070
|
const { contractScript, collaborative = true, walletPubKey, vtxo } = options;
|
|
9990
10071
|
const [contract] = await this.getContracts({ script: contractScript });
|
|
9991
10072
|
if (!contract) return [];
|
|
9992
|
-
const handler =
|
|
10073
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
9993
10074
|
if (!handler) return [];
|
|
9994
10075
|
const script = handler.createScript(contract.params);
|
|
9995
10076
|
const tip = await this.currentChainTip();
|
|
@@ -10017,7 +10098,7 @@ var ContractManager = class _ContractManager {
|
|
|
10017
10098
|
const { contractScript, collaborative = true, walletPubKey } = options;
|
|
10018
10099
|
const [contract] = await this.getContracts({ script: contractScript });
|
|
10019
10100
|
if (!contract) return [];
|
|
10020
|
-
const handler =
|
|
10101
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
10021
10102
|
if (!handler) return [];
|
|
10022
10103
|
const script = handler.createScript(contract.params);
|
|
10023
10104
|
const context = {
|
|
@@ -10073,7 +10154,7 @@ var ContractManager = class _ContractManager {
|
|
|
10073
10154
|
}
|
|
10074
10155
|
async refreshOutpoints(outpoints) {
|
|
10075
10156
|
if (outpoints.length === 0) return;
|
|
10076
|
-
const { vtxos } = await
|
|
10157
|
+
const { vtxos } = await chunkEJOFL5WH_cjs.getNormalizedVtxos(this.config.indexerProvider, {
|
|
10077
10158
|
outpoints
|
|
10078
10159
|
});
|
|
10079
10160
|
if (vtxos.length === 0) return;
|
|
@@ -10152,7 +10233,7 @@ var ContractManager = class _ContractManager {
|
|
|
10152
10233
|
break;
|
|
10153
10234
|
}
|
|
10154
10235
|
} catch (err) {
|
|
10155
|
-
if (!
|
|
10236
|
+
if (!chunkEJOFL5WH_cjs.isRetryableProviderError(err)) throw err;
|
|
10156
10237
|
this.markSyncDegraded(err);
|
|
10157
10238
|
}
|
|
10158
10239
|
this.emitEvent(event);
|
|
@@ -10231,7 +10312,7 @@ var ContractManager = class _ContractManager {
|
|
|
10231
10312
|
*/
|
|
10232
10313
|
async reconcilePendingFrontier(contracts) {
|
|
10233
10314
|
const scriptToContract = new Map(contracts.map((c) => [c.script, c]));
|
|
10234
|
-
const vtxos = await
|
|
10315
|
+
const vtxos = await chunkEJOFL5WH_cjs.getAllNormalizedVtxos(
|
|
10235
10316
|
this.config.indexerProvider,
|
|
10236
10317
|
contracts.map((c) => c.script),
|
|
10237
10318
|
{ pendingOnly: true }
|
|
@@ -10314,7 +10395,7 @@ var ContractManager = class _ContractManager {
|
|
|
10314
10395
|
}
|
|
10315
10396
|
return result;
|
|
10316
10397
|
}
|
|
10317
|
-
async fetchContractVtxosBulk(contracts, pageSize =
|
|
10398
|
+
async fetchContractVtxosBulk(contracts, pageSize = chunkEJOFL5WH_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
|
|
10318
10399
|
if (contracts.length === 0) {
|
|
10319
10400
|
return { vtxosByScript: /* @__PURE__ */ new Map(), promoted: /* @__PURE__ */ new Map() };
|
|
10320
10401
|
}
|
|
@@ -10330,7 +10411,7 @@ var ContractManager = class _ContractManager {
|
|
|
10330
10411
|
before: syncWindow.before
|
|
10331
10412
|
}
|
|
10332
10413
|
} : {};
|
|
10333
|
-
const vtxos = await
|
|
10414
|
+
const vtxos = await chunkEJOFL5WH_cjs.getAllNormalizedVtxos(
|
|
10334
10415
|
this.config.indexerProvider,
|
|
10335
10416
|
contracts.map((c) => c.script),
|
|
10336
10417
|
{ ...windowOpts, pageSize }
|
|
@@ -10475,7 +10556,7 @@ var deserializeTapLeaf = (t) => {
|
|
|
10475
10556
|
const s = base.hex.decode(t.s);
|
|
10476
10557
|
return [cb, s];
|
|
10477
10558
|
};
|
|
10478
|
-
var deserializeVtxo = (o) =>
|
|
10559
|
+
var deserializeVtxo = (o) => chunkEJOFL5WH_cjs.normalizeVtxo({
|
|
10479
10560
|
...o,
|
|
10480
10561
|
createdAt: new Date(o.createdAt),
|
|
10481
10562
|
tapTree: base.hex.decode(o.tapTree),
|
|
@@ -11298,7 +11379,7 @@ var HDDescriptorProvider = class _HDDescriptorProvider {
|
|
|
11298
11379
|
*/
|
|
11299
11380
|
materializeDescriptorAt(index) {
|
|
11300
11381
|
const descriptor = this.identity.descriptor;
|
|
11301
|
-
const network =
|
|
11382
|
+
const network = chunk6YUACVX4_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
11302
11383
|
const expansion = descriptorsScure.expand({ descriptor, network, index });
|
|
11303
11384
|
const keyInfo = expansion.expansionMap?.["@0"];
|
|
11304
11385
|
if (!keyInfo?.keyExpression) {
|
|
@@ -11446,7 +11527,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
11446
11527
|
const provider = await resolveDescriptorProvider(config, setup.walletRepository);
|
|
11447
11528
|
if (!provider) return void 0;
|
|
11448
11529
|
const allowSilentFallback = (config.walletMode ?? "auto") === "auto";
|
|
11449
|
-
const expectedContractType = setup.offchainTapscript instanceof
|
|
11530
|
+
const expectedContractType = setup.offchainTapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? "delegate" : "default";
|
|
11450
11531
|
const factoryOpts = {
|
|
11451
11532
|
walletRepository: setup.walletRepository,
|
|
11452
11533
|
contractRepository: setup.contractRepository,
|
|
@@ -11626,7 +11707,9 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
11626
11707
|
const { tapscript: newTapscript, params } = buildReceiveContract(
|
|
11627
11708
|
wallet.offchainTapscript,
|
|
11628
11709
|
descriptor,
|
|
11629
|
-
wallet.network.hrp
|
|
11710
|
+
wallet.network.hrp,
|
|
11711
|
+
true
|
|
11712
|
+
);
|
|
11630
11713
|
const newScript = params.script;
|
|
11631
11714
|
const manager = await wallet.getContractManager();
|
|
11632
11715
|
await manager.createContract(params);
|
|
@@ -11645,7 +11728,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
11645
11728
|
};
|
|
11646
11729
|
function deriveLeafPubkey(descriptor) {
|
|
11647
11730
|
try {
|
|
11648
|
-
return
|
|
11731
|
+
return chunk6YUACVX4_cjs.deriveDescriptorLeafPubKey(descriptor);
|
|
11649
11732
|
} catch (e) {
|
|
11650
11733
|
throw new NonRangeableDescriptorError(
|
|
11651
11734
|
"Cannot derive leaf pubkey: descriptor is not a materialized, parsable tr(...) shape.",
|
|
@@ -11657,7 +11740,7 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
|
|
|
11657
11740
|
const pubKey = deriveLeafPubkey(descriptor);
|
|
11658
11741
|
const tapscript = rebuildTapscript(current, pubKey);
|
|
11659
11742
|
const serverPubKey = tapscript.options.serverPubKey;
|
|
11660
|
-
const csvTimelock =
|
|
11743
|
+
const csvTimelock = chunkEJOFL5WH_cjs.timelockToSequence(tapscript.options.csvTimelock).toString();
|
|
11661
11744
|
const base$1 = {
|
|
11662
11745
|
script: base.hex.encode(tapscript.pkScript),
|
|
11663
11746
|
address: tapscript.address(hrp, serverPubKey).encode(),
|
|
@@ -11668,11 +11751,11 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
|
|
|
11668
11751
|
// index-0 key. Without it, spends produce unsigned PSBTs that the
|
|
11669
11752
|
// server rejects with `INVALID_PSBT_INPUT (5): missing tapscript spend sig`.
|
|
11670
11753
|
metadata: {
|
|
11671
|
-
...{ source:
|
|
11754
|
+
...tagSource && { source: chunk6YUACVX4_cjs.WALLET_RECEIVE_SOURCE },
|
|
11672
11755
|
signingDescriptor: descriptor
|
|
11673
11756
|
}
|
|
11674
11757
|
};
|
|
11675
|
-
const params = tapscript instanceof
|
|
11758
|
+
const params = tapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? {
|
|
11676
11759
|
...base$1,
|
|
11677
11760
|
type: "delegate",
|
|
11678
11761
|
params: {
|
|
@@ -11693,10 +11776,10 @@ function buildReceiveContract(current, descriptor, hrp, tagSource) {
|
|
|
11693
11776
|
return { tapscript, params };
|
|
11694
11777
|
}
|
|
11695
11778
|
function rebuildTapscript(current, pubKey) {
|
|
11696
|
-
if (current instanceof
|
|
11697
|
-
return new
|
|
11779
|
+
if (current instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script) {
|
|
11780
|
+
return new chunk6YUACVX4_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
|
|
11698
11781
|
}
|
|
11699
|
-
return new
|
|
11782
|
+
return new chunk6YUACVX4_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
|
|
11700
11783
|
}
|
|
11701
11784
|
async function pickActiveReceive(contractRepository, serverPubKey, expectedType) {
|
|
11702
11785
|
const candidates = await contractRepository.getContracts({
|
|
@@ -11705,7 +11788,7 @@ async function pickActiveReceive(contractRepository, serverPubKey, expectedType)
|
|
|
11705
11788
|
});
|
|
11706
11789
|
const serverPubKeyHex = base.hex.encode(serverPubKey);
|
|
11707
11790
|
const matching = candidates.filter(
|
|
11708
|
-
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source ===
|
|
11791
|
+
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunk6YUACVX4_cjs.WALLET_RECEIVE_SOURCE
|
|
11709
11792
|
).sort((a, b) => {
|
|
11710
11793
|
if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
|
|
11711
11794
|
return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
|
|
@@ -11752,6 +11835,7 @@ function computeOffchainBalance(vtxos, caps) {
|
|
|
11752
11835
|
let intentLocked = 0;
|
|
11753
11836
|
let recoverable = 0;
|
|
11754
11837
|
let pendingRecovery = 0;
|
|
11838
|
+
let unrolled = 0;
|
|
11755
11839
|
const owned = /* @__PURE__ */ new Map();
|
|
11756
11840
|
const spendable = /* @__PURE__ */ new Map();
|
|
11757
11841
|
const addAssets = (into, vtxo) => {
|
|
@@ -11760,17 +11844,21 @@ function computeOffchainBalance(vtxos, caps) {
|
|
|
11760
11844
|
}
|
|
11761
11845
|
};
|
|
11762
11846
|
for (const vtxo of vtxos) {
|
|
11763
|
-
if (
|
|
11847
|
+
if (chunkEJOFL5WH_cjs.hasTerminalSpend(vtxo)) continue;
|
|
11764
11848
|
addAssets(owned, vtxo);
|
|
11849
|
+
if (vtxo.isUnrolled) {
|
|
11850
|
+
unrolled += vtxo.value;
|
|
11851
|
+
continue;
|
|
11852
|
+
}
|
|
11765
11853
|
if (isPendingRecovery(vtxo)) {
|
|
11766
11854
|
pendingRecovery += vtxo.value;
|
|
11767
11855
|
continue;
|
|
11768
11856
|
}
|
|
11769
|
-
if (
|
|
11857
|
+
if (chunkEJOFL5WH_cjs.canRecoverOnchain(vtxo, now)) {
|
|
11770
11858
|
recoverable += vtxo.value;
|
|
11771
11859
|
continue;
|
|
11772
11860
|
}
|
|
11773
|
-
if (!
|
|
11861
|
+
if (!chunkEJOFL5WH_cjs.canSpendOffchain(vtxo, now)) continue;
|
|
11774
11862
|
if (vtxo.isPreconfirmed) {
|
|
11775
11863
|
preconfirmed += vtxo.value;
|
|
11776
11864
|
} else {
|
|
@@ -11794,7 +11882,8 @@ function computeOffchainBalance(vtxos, caps) {
|
|
|
11794
11882
|
intentLocked,
|
|
11795
11883
|
recoverable,
|
|
11796
11884
|
pendingRecovery,
|
|
11797
|
-
|
|
11885
|
+
unrolled,
|
|
11886
|
+
total: settled + preconfirmed + recoverable + pendingRecovery + unrolled,
|
|
11798
11887
|
assets: toAssets(owned),
|
|
11799
11888
|
availableAssets: toAssets(spendable)
|
|
11800
11889
|
};
|
|
@@ -11939,12 +12028,12 @@ var InputSignerRouter = class {
|
|
|
11939
12028
|
};
|
|
11940
12029
|
|
|
11941
12030
|
// src/wallet/wallet.ts
|
|
11942
|
-
var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl ||
|
|
12031
|
+
var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunkEJOFL5WH_cjs.DEFAULT_ARKADE_SERVER_URL;
|
|
11943
12032
|
function intentProofJobs(coins) {
|
|
11944
12033
|
if (coins.length === 0) return [];
|
|
11945
12034
|
const coinJobs = coins.map((coin, i) => ({
|
|
11946
12035
|
index: i + 1,
|
|
11947
|
-
lookupScript:
|
|
12036
|
+
lookupScript: chunkEJOFL5WH_cjs.VtxoScript.decode(coin.tapTree).pkScript
|
|
11948
12037
|
}));
|
|
11949
12038
|
return [{ index: 0, lookupScript: coinJobs[0].lookupScript }, ...coinJobs];
|
|
11950
12039
|
}
|
|
@@ -11976,7 +12065,7 @@ function dedupeTimelocks(timelocks) {
|
|
|
11976
12065
|
const seen = /* @__PURE__ */ new Set();
|
|
11977
12066
|
const deduped = [];
|
|
11978
12067
|
for (const timelock of timelocks) {
|
|
11979
|
-
const sequence =
|
|
12068
|
+
const sequence = chunkEJOFL5WH_cjs.timelockToSequence(timelock).toString();
|
|
11980
12069
|
if (seen.has(sequence)) continue;
|
|
11981
12070
|
seen.add(sequence);
|
|
11982
12071
|
deduped.push(timelock);
|
|
@@ -11993,7 +12082,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
|
|
|
11993
12082
|
state: "active"
|
|
11994
12083
|
});
|
|
11995
12084
|
const newest = candidates.filter(
|
|
11996
|
-
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source ===
|
|
12085
|
+
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunk6YUACVX4_cjs.WALLET_RECEIVE_SOURCE
|
|
11997
12086
|
).sort((a, b) => {
|
|
11998
12087
|
if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
|
|
11999
12088
|
return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
|
|
@@ -12001,7 +12090,7 @@ async function resolveBoardingBootTapscript(contractRepository, serverPubKey, ba
|
|
|
12001
12090
|
if (!newest?.params.pubKey) return baseline;
|
|
12002
12091
|
try {
|
|
12003
12092
|
const pubKey = base.hex.decode(newest.params.pubKey);
|
|
12004
|
-
return new
|
|
12093
|
+
return new chunk6YUACVX4_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
|
|
12005
12094
|
} catch (e) {
|
|
12006
12095
|
console.warn("Skipping malformed boarding contract at boot", newest.script, e);
|
|
12007
12096
|
return baseline;
|
|
@@ -12017,16 +12106,20 @@ function filterSnapshotVtxos(snapshot, filter, pendingSpendOutpoints) {
|
|
|
12017
12106
|
if (pendingSpendOutpoints.has(`${vtxo.txid}:${vtxo.vout}`)) {
|
|
12018
12107
|
return false;
|
|
12019
12108
|
}
|
|
12020
|
-
if (
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
return
|
|
12109
|
+
if (vtxo.isUnrolled) {
|
|
12110
|
+
return !!f.withUnrolled;
|
|
12111
|
+
}
|
|
12112
|
+
if (chunkEJOFL5WH_cjs.hasTerminalSpend(vtxo)) {
|
|
12113
|
+
return false;
|
|
12114
|
+
}
|
|
12115
|
+
if (!f.withRecoverable && chunkEJOFL5WH_cjs.canRecoverOnchain(vtxo, now)) {
|
|
12116
|
+
return false;
|
|
12025
12117
|
}
|
|
12026
|
-
return
|
|
12118
|
+
return true;
|
|
12027
12119
|
});
|
|
12028
12120
|
}
|
|
12029
12121
|
var PENDING_RECOVERY_REASON = "is past its operator signer's rotation cutoff \u2014 the operator will not co-sign it until it recovers";
|
|
12122
|
+
var UNROLLED_REASON = "was unilaterally exited and lives onchain \u2014 `Unroll.completeUnroll` is the only spend that reaches it";
|
|
12030
12123
|
function omittedOutpoints(before, after) {
|
|
12031
12124
|
if (before.length === after.length) return /* @__PURE__ */ new Set();
|
|
12032
12125
|
const kept = new Set(after.map((vtxo) => `${vtxo.txid}:${vtxo.vout}`));
|
|
@@ -12359,7 +12452,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12359
12452
|
*/
|
|
12360
12453
|
static async setupWalletConfig(config, pubKey) {
|
|
12361
12454
|
const arkadeServerUrl = getArkadeServerUrl(config);
|
|
12362
|
-
const arkProvider = config.arkProvider || new
|
|
12455
|
+
const arkProvider = config.arkProvider || new chunkEJOFL5WH_cjs.RestArkProvider(arkadeServerUrl);
|
|
12363
12456
|
let indexerProvider = config.indexerProvider;
|
|
12364
12457
|
if (!indexerProvider) {
|
|
12365
12458
|
let indexerUrl = config.indexerUrl;
|
|
@@ -12376,7 +12469,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12376
12469
|
indexerUrl = arkadeServerUrl;
|
|
12377
12470
|
}
|
|
12378
12471
|
}
|
|
12379
|
-
indexerProvider = new
|
|
12472
|
+
indexerProvider = new chunkPJR63FTK_cjs.RestIndexerProvider(indexerUrl);
|
|
12380
12473
|
}
|
|
12381
12474
|
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
12382
12475
|
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
@@ -12385,7 +12478,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12385
12478
|
source: serverInfoSource,
|
|
12386
12479
|
lastOnlineAt: serverInfoLastOnlineAt
|
|
12387
12480
|
} = await resolveArkInfo(arkProvider, walletRepository);
|
|
12388
|
-
const network =
|
|
12481
|
+
const network = chunkEJOFL5WH_cjs.getNetwork(info.network);
|
|
12389
12482
|
if ("descriptor" in config.identity) {
|
|
12390
12483
|
const descriptor = config.identity.descriptor;
|
|
12391
12484
|
const identityIsMainnet = !descriptor.includes("tpub");
|
|
@@ -12425,18 +12518,18 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12425
12518
|
value: info.boardingExitDelay,
|
|
12426
12519
|
type: info.boardingExitDelay < 512n ? "blocks" : "seconds"
|
|
12427
12520
|
};
|
|
12428
|
-
const serverPubKey =
|
|
12429
|
-
const delegatePubKey = config.delegateProvider ? await config.delegateProvider.getDelegateInfo().then((info2) =>
|
|
12521
|
+
const serverPubKey = chunk6YUACVX4_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
|
|
12522
|
+
const delegatePubKey = config.delegateProvider ? await config.delegateProvider.getDelegateInfo().then((info2) => chunk6YUACVX4_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : config.delegatorProvider ? await config.delegatorProvider.getDelegateInfo().then((info2) => chunk6YUACVX4_cjs.toXOnly(base.hex.decode(info2.pubkey), "delegate key")).catch(() => void 0) : void 0;
|
|
12430
12523
|
const offchainOptions = {
|
|
12431
12524
|
pubKey,
|
|
12432
12525
|
serverPubKey,
|
|
12433
12526
|
csvTimelock: exitTimelock
|
|
12434
12527
|
};
|
|
12435
|
-
const offchainTapscript = !delegatePubKey ? new
|
|
12436
|
-
const boardingTapscript =
|
|
12528
|
+
const offchainTapscript = !delegatePubKey ? new chunk6YUACVX4_cjs.DefaultVtxo.Script(offchainOptions) : new chunk6YUACVX4_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
|
|
12529
|
+
const boardingTapscript = chunk6YUACVX4_cjs.BoardingContractHandler.createScript({
|
|
12437
12530
|
pubKey: base.hex.encode(pubKey),
|
|
12438
12531
|
serverPubKey: base.hex.encode(serverPubKey),
|
|
12439
|
-
csvTimelock:
|
|
12532
|
+
csvTimelock: chunkEJOFL5WH_cjs.timelockToSequence(boardingTimelock).toString()
|
|
12440
12533
|
});
|
|
12441
12534
|
return {
|
|
12442
12535
|
arkProvider,
|
|
@@ -12526,7 +12619,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12526
12619
|
this.getBoardingUtxos(),
|
|
12527
12620
|
this.contractSnapshot()
|
|
12528
12621
|
]);
|
|
12529
|
-
const vtxos = filterSnapshotVtxos(
|
|
12622
|
+
const vtxos = filterSnapshotVtxos(
|
|
12623
|
+
snapshot,
|
|
12624
|
+
{ withRecoverable: true, withUnrolled: true },
|
|
12625
|
+
this._pendingSpendOutpoints
|
|
12626
|
+
);
|
|
12530
12627
|
let confirmed = 0;
|
|
12531
12628
|
let unconfirmed = 0;
|
|
12532
12629
|
for (const utxo of boardingUtxos) {
|
|
@@ -12554,6 +12651,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12554
12651
|
intentLocked: offchain.intentLocked,
|
|
12555
12652
|
recoverable: offchain.recoverable,
|
|
12556
12653
|
pendingRecovery: offchain.pendingRecovery,
|
|
12654
|
+
unrolled: offchain.unrolled,
|
|
12557
12655
|
total: totalBoarding + offchain.total,
|
|
12558
12656
|
assets: offchain.assets,
|
|
12559
12657
|
availableAssets: offchain.availableAssets
|
|
@@ -12594,6 +12692,13 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12594
12692
|
"is locked by an in-flight settlement intent"
|
|
12595
12693
|
)
|
|
12596
12694
|
]);
|
|
12695
|
+
if (!filter?.withUnrolled) {
|
|
12696
|
+
logExcludedVtxos(
|
|
12697
|
+
"getSpendableVtxos",
|
|
12698
|
+
snapshot.flatMap((contract) => contract.vtxos).filter((vtxo) => vtxo.isUnrolled && !chunkEJOFL5WH_cjs.hasTerminalSpend(vtxo)),
|
|
12699
|
+
[() => UNROLLED_REASON]
|
|
12700
|
+
);
|
|
12701
|
+
}
|
|
12597
12702
|
return unlocked;
|
|
12598
12703
|
}
|
|
12599
12704
|
/**
|
|
@@ -12733,7 +12838,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12733
12838
|
const response = await contractManager.getContractsWithVtxos();
|
|
12734
12839
|
const allVtxos = response.flatMap((_) => _.vtxos);
|
|
12735
12840
|
const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
|
|
12736
|
-
const resolveTxCreatedAt = (txids) =>
|
|
12841
|
+
const resolveTxCreatedAt = (txids) => chunkEJOFL5WH_cjs.fetchVtxoCreatedAtByTxid(this.indexerProvider, txids);
|
|
12737
12842
|
return buildTransactionHistory(
|
|
12738
12843
|
allVtxos,
|
|
12739
12844
|
boardingTxs,
|
|
@@ -12827,7 +12932,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12827
12932
|
},
|
|
12828
12933
|
isUnrolled: true,
|
|
12829
12934
|
...boardingFacts,
|
|
12830
|
-
virtualStatus:
|
|
12935
|
+
virtualStatus: chunkEJOFL5WH_cjs.toVirtualStatus(boardingFacts),
|
|
12831
12936
|
spentBy: "",
|
|
12832
12937
|
createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
|
|
12833
12938
|
script: scriptHex
|
|
@@ -12883,9 +12988,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12883
12988
|
async getBoardingTapscripts(allowedSigners) {
|
|
12884
12989
|
const byScript = /* @__PURE__ */ new Map();
|
|
12885
12990
|
const add = (s) => byScript.set(base.hex.encode(s.pkScript), s);
|
|
12886
|
-
const boardingCsv = this.boardingTapscript.options.csvTimelock ??
|
|
12991
|
+
const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunk6YUACVX4_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
12887
12992
|
add(
|
|
12888
|
-
new
|
|
12993
|
+
new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
12889
12994
|
pubKey: await this.identity.xOnlyPublicKey(),
|
|
12890
12995
|
serverPubKey: this.boardingTapscript.options.serverPubKey,
|
|
12891
12996
|
csvTimelock: boardingCsv
|
|
@@ -12900,7 +13005,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12900
13005
|
for (const c of boardingContracts) {
|
|
12901
13006
|
if (!allowed.has(toXOnlySignerHex(c.params.serverPubKey))) continue;
|
|
12902
13007
|
try {
|
|
12903
|
-
add(
|
|
13008
|
+
add(chunk6YUACVX4_cjs.BoardingContractHandler.createScript(c.params));
|
|
12904
13009
|
} catch (e) {
|
|
12905
13010
|
console.warn("Skipping malformed boarding contract", c.script, e);
|
|
12906
13011
|
}
|
|
@@ -12938,7 +13043,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
12938
13043
|
// Per-row CSV delay decoded from THIS tapscript's exit leaf —
|
|
12939
13044
|
// not the wallet's current boarding timelock, which a signer
|
|
12940
13045
|
// rotation may have changed.
|
|
12941
|
-
csvTimelock:
|
|
13046
|
+
csvTimelock: chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(base.hex.decode(tapscript.exitScript)).params.timelock,
|
|
12942
13047
|
coins: utxos
|
|
12943
13048
|
});
|
|
12944
13049
|
}
|
|
@@ -13071,7 +13176,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13071
13176
|
/** Fetch Arkade transaction ids that are still pending final settlement. */
|
|
13072
13177
|
async fetchPendingTxs() {
|
|
13073
13178
|
const scripts = await this.getWalletScripts();
|
|
13074
|
-
const vtxos = await
|
|
13179
|
+
const vtxos = await chunkEJOFL5WH_cjs.getAllNormalizedVtxos(this.indexerProvider, scripts);
|
|
13075
13180
|
return vtxos.filter(
|
|
13076
13181
|
(vtxo) => (vtxo.isSpent || vtxo.isPreconfirmed && !vtxo.isSwept) && vtxo.arkTxId !== void 0
|
|
13077
13182
|
).map((_) => _.arkTxId);
|
|
@@ -13102,7 +13207,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13102
13207
|
});
|
|
13103
13208
|
for (const contract of contracts) {
|
|
13104
13209
|
if (map.has(contract.script)) continue;
|
|
13105
|
-
const handler =
|
|
13210
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
13106
13211
|
if (handler) {
|
|
13107
13212
|
const script = handler.createScript(contract.params);
|
|
13108
13213
|
map.set(contract.script, script);
|
|
@@ -13214,7 +13319,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13214
13319
|
}
|
|
13215
13320
|
});
|
|
13216
13321
|
const baselinePubkey = await this.identity.xOnlyPublicKey();
|
|
13217
|
-
const delegatePubKey = this.offchainTapscript instanceof
|
|
13322
|
+
const delegatePubKey = this.offchainTapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
|
|
13218
13323
|
const baselineSigners = [
|
|
13219
13324
|
this.offchainTapscript.options.serverPubKey,
|
|
13220
13325
|
...[...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h))
|
|
@@ -13222,8 +13327,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13222
13327
|
const seenBaselineScripts = /* @__PURE__ */ new Set();
|
|
13223
13328
|
for (const serverPubKey of baselineSigners) {
|
|
13224
13329
|
for (const csvTimelock of this.walletContractTimelocks) {
|
|
13225
|
-
const csvTimelockStr =
|
|
13226
|
-
const defaultScript = new
|
|
13330
|
+
const csvTimelockStr = chunkEJOFL5WH_cjs.timelockToSequence(csvTimelock).toString();
|
|
13331
|
+
const defaultScript = new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
13227
13332
|
pubKey: baselinePubkey,
|
|
13228
13333
|
serverPubKey,
|
|
13229
13334
|
csvTimelock
|
|
@@ -13244,7 +13349,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13244
13349
|
});
|
|
13245
13350
|
}
|
|
13246
13351
|
if (delegatePubKey) {
|
|
13247
|
-
const delegateScript = new
|
|
13352
|
+
const delegateScript = new chunk6YUACVX4_cjs.DelegateVtxo.Script({
|
|
13248
13353
|
pubKey: baselinePubkey,
|
|
13249
13354
|
serverPubKey,
|
|
13250
13355
|
delegatePubKey,
|
|
@@ -13268,9 +13373,9 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13268
13373
|
}
|
|
13269
13374
|
}
|
|
13270
13375
|
}
|
|
13271
|
-
const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ??
|
|
13376
|
+
const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunk6YUACVX4_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
13272
13377
|
for (const serverPubKey of baselineSigners) {
|
|
13273
|
-
const baselineBoarding = new
|
|
13378
|
+
const baselineBoarding = new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
13274
13379
|
pubKey: baselinePubkey,
|
|
13275
13380
|
serverPubKey,
|
|
13276
13381
|
csvTimelock: boardingCsvTimelock
|
|
@@ -13283,7 +13388,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
13283
13388
|
params: {
|
|
13284
13389
|
pubKey: base.hex.encode(baselineBoarding.options.pubKey),
|
|
13285
13390
|
serverPubKey: base.hex.encode(serverPubKey),
|
|
13286
|
-
csvTimelock:
|
|
13391
|
+
csvTimelock: chunkEJOFL5WH_cjs.timelockToSequence(boardingCsvTimelock).toString()
|
|
13287
13392
|
},
|
|
13288
13393
|
script: boardingScriptHex,
|
|
13289
13394
|
address: baselineBoarding.address(this.network.hrp, serverPubKey).encode(),
|
|
@@ -13413,6 +13518,27 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13413
13518
|
console.warn("server-signer rotation on info change failed", e);
|
|
13414
13519
|
}
|
|
13415
13520
|
}
|
|
13521
|
+
/**
|
|
13522
|
+
* Await an `onServerInfoChanged` handler still applying a rotation.
|
|
13523
|
+
*
|
|
13524
|
+
* The provider emits synchronously but {@link handleServerInfoChanged} runs
|
|
13525
|
+
* off the emit, so between the two a caller can observe a half-applied
|
|
13526
|
+
* rotation: {@link rotateServerSigner} persists the active signer's contract
|
|
13527
|
+
* rows *before* committing the tapscripts, so `arkServerPublicKey` still
|
|
13528
|
+
* reads the old key while the new key's rows are already in the repository.
|
|
13529
|
+
* A path that refreshes server info and then reads signer-derived state must
|
|
13530
|
+
* drain the chain first, or it both reads that torn state and races the
|
|
13531
|
+
* handler for the rotation itself.
|
|
13532
|
+
*
|
|
13533
|
+
* Resolves once the chain is idle; a handler that threw already logged, and
|
|
13534
|
+
* its rejection is swallowed here.
|
|
13535
|
+
*
|
|
13536
|
+
* @internal Invoked by {@link dispose} and the {@link VtxoManager} migration
|
|
13537
|
+
* pass; not part of the stable public API.
|
|
13538
|
+
*/
|
|
13539
|
+
async settleServerInfoChanges() {
|
|
13540
|
+
await this._serverInfoInFlight?.catch(() => void 0);
|
|
13541
|
+
}
|
|
13416
13542
|
_receiveRotatorInstalled = false;
|
|
13417
13543
|
/**
|
|
13418
13544
|
* Descriptor-aware signer used by {@link _signerRouter} to sign
|
|
@@ -13462,7 +13588,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13462
13588
|
serverPubKey: this.offchainTapscript.options.serverPubKey,
|
|
13463
13589
|
deprecatedSignerPubKeys: [...this._deprecatedSigners.keys()].map((h) => base.hex.decode(h)),
|
|
13464
13590
|
csvTimelocks: this.walletContractTimelocks,
|
|
13465
|
-
delegatePubKey: this.offchainTapscript instanceof
|
|
13591
|
+
delegatePubKey: this.offchainTapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0
|
|
13466
13592
|
};
|
|
13467
13593
|
}
|
|
13468
13594
|
_signerRouter;
|
|
@@ -13547,43 +13673,250 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13547
13673
|
* provider and keeps a single index-0 boarding address for its lifetime,
|
|
13548
13674
|
* so this returns the existing {@link getBoardingAddress} unchanged
|
|
13549
13675
|
* (no rotation, no index burned).
|
|
13676
|
+
*
|
|
13677
|
+
* **Behaviour change.** A wallet configured with a custom
|
|
13678
|
+
* {@link DescriptorProvider} (`walletMode: <provider>`) now rotates here.
|
|
13679
|
+
* It previously did not: allocation went through the contract manager,
|
|
13680
|
+
* which only wires an `allocate` hook for {@link HDDescriptorProvider}, so
|
|
13681
|
+
* such a wallet read as "declined to allocate" and silently kept its
|
|
13682
|
+
* index-0 boarding address forever. Those wallets now burn an index per
|
|
13683
|
+
* call — including via {@link maybeRotateBoardingAfterBoard}, which fires
|
|
13684
|
+
* on every settle that consumes a boarding UTXO. Funds at retired
|
|
13685
|
+
* addresses stay reachable: each rotation persists its `boarding` contract
|
|
13686
|
+
* before swapping, and {@link getBoardingUtxos} fans out over the full
|
|
13687
|
+
* historical set.
|
|
13688
|
+
*
|
|
13689
|
+
* @deprecated Use {@link getNewAddresses} — it mints any combination of
|
|
13690
|
+
* address types at one shared index, and reports the contract row behind
|
|
13691
|
+
* each. Note the difference in display behaviour: this method *swaps* the
|
|
13692
|
+
* advertised boarding address, where `getNewAddresses` mints side
|
|
13693
|
+
* addresses and leaves {@link getBoardingAddress} alone. To keep this
|
|
13694
|
+
* method's behaviour, keep calling this method.
|
|
13550
13695
|
*/
|
|
13551
13696
|
async getNewBoardingAddress() {
|
|
13552
|
-
const
|
|
13553
|
-
if (!
|
|
13554
|
-
|
|
13697
|
+
const [minted] = await this.allocateAddresses(["boarding"], false, true);
|
|
13698
|
+
if (!minted?.allocated) return this.getBoardingAddress();
|
|
13699
|
+
if (minted.type === "boarding") this.setBoardingTapscriptForRotation(minted.tapscript);
|
|
13700
|
+
return minted.address;
|
|
13701
|
+
}
|
|
13702
|
+
/**
|
|
13703
|
+
* Allocate a *fresh* address of each requested type, all derived from one
|
|
13704
|
+
* newly allocated HD index.
|
|
13705
|
+
*
|
|
13706
|
+
* This is the explicit allocator the receive path otherwise lacks:
|
|
13707
|
+
* {@link getAddress} and {@link getBoardingAddress} are stable reads of the
|
|
13708
|
+
* wallet's display addresses, and the display receive address only advances
|
|
13709
|
+
* when a payment arrives ({@link WalletReceiveRotator} rotates on
|
|
13710
|
+
* `vtxo_received`). Issuing a second address before the first is paid — one
|
|
13711
|
+
* invoice for Alice, another for Bob — has to go through here.
|
|
13712
|
+
*
|
|
13713
|
+
* Each call:
|
|
13714
|
+
*
|
|
13715
|
+
* - allocates **one** index from the shared HD stream, however many types
|
|
13716
|
+
* were asked for, so a `default` + `boarding` pair are siblings rather
|
|
13717
|
+
* than two burnt indices;
|
|
13718
|
+
* - builds each requested script at that index, preserving every other
|
|
13719
|
+
* option of the wallet's current script for that flavour (including a
|
|
13720
|
+
* delegate wallet's `delegate` shape);
|
|
13721
|
+
* - persists each as an `active` contract carrying its `signingDescriptor`,
|
|
13722
|
+
* so the ContractWatcher monitors it, the balance counts it, and
|
|
13723
|
+
* {@link signerForDescriptor} can recover the key;
|
|
13724
|
+
* - slides the look-ahead band, since the watermark moved past indices an
|
|
13725
|
+
* external issuer may still be handing out.
|
|
13726
|
+
*
|
|
13727
|
+
* The minted rows are deliberately left **untagged**: the boot lookups
|
|
13728
|
+
* adopt the newest {@link WALLET_RECEIVE_SOURCE}-tagged row as the display
|
|
13729
|
+
* address, and a side address issued to one counterparty must not become
|
|
13730
|
+
* the address the wallet advertises to everyone else. {@link getAddress}
|
|
13731
|
+
* and {@link getBoardingAddress} are unchanged by this call.
|
|
13732
|
+
*
|
|
13733
|
+
* A wallet with no HD stream (`walletMode: 'static'` / `'auto'`) has one
|
|
13734
|
+
* address per flavour for its lifetime. Without `forceNew` it returns those
|
|
13735
|
+
* — the real persisted rows, no index burned; with `forceNew` it throws
|
|
13736
|
+
* {@link WalletCannotAllocateAddressError} rather than hand back an address
|
|
13737
|
+
* that is not in fact fresh.
|
|
13738
|
+
*
|
|
13739
|
+
* @example
|
|
13740
|
+
* ```typescript
|
|
13741
|
+
* const [invoice] = await wallet.getNewAddresses({ forceNew: true });
|
|
13742
|
+
* // hand `invoice.address` to Alice, keep the descriptor with the invoice
|
|
13743
|
+
* const signer = await wallet.signerForDescriptor(invoice.signingDescriptor);
|
|
13744
|
+
* ```
|
|
13745
|
+
*/
|
|
13746
|
+
async getNewAddresses(opts) {
|
|
13747
|
+
const minted = await this.allocateAddresses(
|
|
13748
|
+
opts?.types ?? ["default"],
|
|
13749
|
+
opts?.forceNew ?? false,
|
|
13750
|
+
false
|
|
13751
|
+
);
|
|
13752
|
+
return minted.map(({ address, signingDescriptor, contract }) => ({
|
|
13753
|
+
address,
|
|
13754
|
+
signingDescriptor,
|
|
13755
|
+
contract
|
|
13756
|
+
}));
|
|
13757
|
+
}
|
|
13758
|
+
/**
|
|
13759
|
+
* Shared allocation core behind {@link getNewAddresses} and the deprecated
|
|
13760
|
+
* {@link getNewBoardingAddress}, so the two cannot drift on what an
|
|
13761
|
+
* allocation costs or what gets persisted.
|
|
13762
|
+
*
|
|
13763
|
+
* @param tagSource - Tag the persisted rows {@link WALLET_RECEIVE_SOURCE},
|
|
13764
|
+
* making the next boot adopt them as the display address. Only the
|
|
13765
|
+
* deprecated boarding allocator passes `true`; `getNewAddresses` mints side
|
|
13766
|
+
* addresses and must not hijack what the wallet advertises.
|
|
13767
|
+
*/
|
|
13768
|
+
async allocateAddresses(types, forceNew, tagSource) {
|
|
13769
|
+
if (types.length === 0) {
|
|
13770
|
+
throw new Error("getNewAddresses: `types` must name at least one address type");
|
|
13555
13771
|
}
|
|
13556
13772
|
const manager = await this.getContractManager();
|
|
13557
|
-
const
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13773
|
+
const provider = this._descriptorProvider;
|
|
13774
|
+
const descriptor = !provider ? void 0 : provider instanceof HDDescriptorProvider ? await manager.getNextSigningDescriptor() : await provider.getNextSigningDescriptor();
|
|
13775
|
+
if (!descriptor) {
|
|
13776
|
+
if (forceNew) {
|
|
13777
|
+
throw new WalletCannotAllocateAddressError(
|
|
13778
|
+
provider ? "the descriptor provider declined to allocate an index" : "this wallet has no HD stream (walletMode 'static' / 'auto')"
|
|
13779
|
+
);
|
|
13780
|
+
}
|
|
13781
|
+
return this.currentAddresses(manager, types);
|
|
13782
|
+
}
|
|
13783
|
+
const allocated = [];
|
|
13784
|
+
try {
|
|
13785
|
+
for (const type of types) {
|
|
13786
|
+
allocated.push(await this.mintAddress(manager, type, descriptor, tagSource, true));
|
|
13787
|
+
}
|
|
13788
|
+
} finally {
|
|
13789
|
+
try {
|
|
13790
|
+
await manager.refillLookAhead();
|
|
13791
|
+
} catch (e) {
|
|
13792
|
+
console.warn("look-ahead refill after address allocation failed", e);
|
|
13793
|
+
}
|
|
13794
|
+
}
|
|
13795
|
+
return allocated;
|
|
13796
|
+
}
|
|
13797
|
+
/**
|
|
13798
|
+
* The wallet's existing display addresses, as persisted contract rows —
|
|
13799
|
+
* the honest answer for a wallet with no index to burn.
|
|
13800
|
+
*
|
|
13801
|
+
* Each type is minted from the descriptor that already owns its display
|
|
13802
|
+
* script ({@link displayDescriptor}), not from the identity key, so the
|
|
13803
|
+
* returned `signingDescriptor` is the one that signs for the returned
|
|
13804
|
+
* `address` even on a wallet that has rotated.
|
|
13805
|
+
*/
|
|
13806
|
+
async currentAddresses(manager, types) {
|
|
13807
|
+
const out = [];
|
|
13808
|
+
for (const type of types) {
|
|
13809
|
+
const descriptor = await this.displayDescriptor(manager, type);
|
|
13810
|
+
out.push(await this.mintAddress(manager, type, descriptor, false, false));
|
|
13811
|
+
}
|
|
13812
|
+
return out;
|
|
13813
|
+
}
|
|
13814
|
+
/**
|
|
13815
|
+
* The descriptor that owns the wallet's current display script for `type`,
|
|
13816
|
+
* read off the row the wallet persisted when it adopted that script.
|
|
13817
|
+
*
|
|
13818
|
+
* Deriving it from the identity instead is only correct for a wallet that
|
|
13819
|
+
* never rotates. On one that has — an HD wallet whose provider later
|
|
13820
|
+
* declines to allocate — the display script belongs to an HD child, and
|
|
13821
|
+
* pairing its address with the identity descriptor hands the caller a
|
|
13822
|
+
* {@link NewAddress} whose `signingDescriptor` resolves, via
|
|
13823
|
+
* {@link signerForDescriptor}, to a signer holding the wrong key.
|
|
13824
|
+
*
|
|
13825
|
+
* Falls back to the identity's pathless `tr(pubkey)` when no row carries a
|
|
13826
|
+
* descriptor: the static / `auto` case, where the identity key genuinely
|
|
13827
|
+
* owns the display script and this is what `getNextSigningDescriptor`
|
|
13828
|
+
* answers too. (The index-0 baselines registered at construction carry no
|
|
13829
|
+
* `signingDescriptor` metadata, so those wallets take this path.)
|
|
13830
|
+
*/
|
|
13831
|
+
async displayDescriptor(manager, type) {
|
|
13832
|
+
const display = type === "boarding" ? this._boardingTapscript : this.offchainTapscript;
|
|
13833
|
+
const [row] = await manager.getContracts({ script: base.hex.encode(display.pkScript) });
|
|
13834
|
+
const persisted = row?.metadata?.signingDescriptor;
|
|
13835
|
+
if (typeof persisted === "string") return persisted;
|
|
13836
|
+
return chunk6YUACVX4_cjs.identityDescriptor(this.identity);
|
|
13837
|
+
}
|
|
13838
|
+
/**
|
|
13839
|
+
* Build, persist and shape one address of `type` owned by `descriptor` —
|
|
13840
|
+
* the single build-and-register path behind both {@link allocateAddresses}
|
|
13841
|
+
* and {@link currentAddresses}, so a freshly allocated address and a
|
|
13842
|
+
* re-registered display address cannot disagree on what gets written.
|
|
13843
|
+
*
|
|
13844
|
+
* The descriptor is the sole source of the script's owner key in both
|
|
13845
|
+
* branches. Deriving one flavour from the descriptor and the other from a
|
|
13846
|
+
* tapscript field is what lets `address` and `signingDescriptor` drift
|
|
13847
|
+
* apart.
|
|
13848
|
+
*/
|
|
13849
|
+
async mintAddress(manager, type, descriptor, tagSource, allocated) {
|
|
13850
|
+
if (type === "boarding") {
|
|
13851
|
+
const built2 = this.buildBoardingContract(
|
|
13852
|
+
chunk6YUACVX4_cjs.deriveDescriptorLeafPubKey(descriptor),
|
|
13853
|
+
descriptor,
|
|
13854
|
+
tagSource
|
|
13855
|
+
);
|
|
13856
|
+
const contract2 = await manager.createContract(built2.params);
|
|
13857
|
+
return {
|
|
13858
|
+
type,
|
|
13859
|
+
// `built.tapscript` is a `DefaultVtxo.Script` here without a
|
|
13860
|
+
// cast — the branch, not a widened local, does the narrowing.
|
|
13861
|
+
tapscript: built2.tapscript,
|
|
13862
|
+
// A boarding row persists the *ark* encoding of its script, so
|
|
13863
|
+
// `contract.address` is unusable for an onchain sender: the
|
|
13864
|
+
// onchain form has to be re-derived.
|
|
13865
|
+
address: built2.tapscript.onchainAddress(this.network),
|
|
13866
|
+
signingDescriptor: descriptor,
|
|
13867
|
+
contract: contract2,
|
|
13868
|
+
allocated
|
|
13869
|
+
};
|
|
13870
|
+
}
|
|
13871
|
+
const built = buildReceiveContract(
|
|
13872
|
+
this.offchainTapscript,
|
|
13873
|
+
descriptor,
|
|
13874
|
+
this.network.hrp,
|
|
13875
|
+
tagSource
|
|
13876
|
+
);
|
|
13877
|
+
const contract = await manager.createContract(built.params);
|
|
13878
|
+
return {
|
|
13879
|
+
type,
|
|
13880
|
+
tapscript: built.tapscript,
|
|
13881
|
+
// Offchain rows already store the address they advertise, and
|
|
13882
|
+
// reading it back keeps a coalesced row (`createContract` is
|
|
13883
|
+
// first-wins on script) honest about what was actually persisted.
|
|
13884
|
+
address: contract.address,
|
|
13885
|
+
signingDescriptor: descriptor,
|
|
13886
|
+
contract,
|
|
13887
|
+
allocated
|
|
13888
|
+
};
|
|
13889
|
+
}
|
|
13890
|
+
/**
|
|
13891
|
+
* Build the boarding contract owned by `pubKey`, keeping every other option
|
|
13892
|
+
* of the wallet's current boarding tapscript (notably the boarding-exit
|
|
13893
|
+
* CSV, which is index-independent). The offchain analogue lives in
|
|
13894
|
+
* {@link buildReceiveContract}.
|
|
13895
|
+
*/
|
|
13896
|
+
buildBoardingContract(pubKey, descriptor, tagSource) {
|
|
13897
|
+
const tapscript = new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
13561
13898
|
...this._boardingTapscript.options,
|
|
13562
13899
|
pubKey
|
|
13563
13900
|
});
|
|
13564
|
-
const csvTimelock =
|
|
13565
|
-
|
|
13566
|
-
|
|
13901
|
+
const csvTimelock = tapscript.options.csvTimelock ?? chunk6YUACVX4_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
13902
|
+
return {
|
|
13903
|
+
tapscript,
|
|
13567
13904
|
params: {
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13905
|
+
type: "boarding",
|
|
13906
|
+
params: {
|
|
13907
|
+
pubKey: base.hex.encode(pubKey),
|
|
13908
|
+
serverPubKey: base.hex.encode(tapscript.options.serverPubKey),
|
|
13909
|
+
csvTimelock: chunkEJOFL5WH_cjs.timelockToSequence(csvTimelock).toString()
|
|
13910
|
+
},
|
|
13911
|
+
script: base.hex.encode(tapscript.pkScript),
|
|
13912
|
+
address: tapscript.address(this.network.hrp, this.arkServerPublicKey).encode(),
|
|
13913
|
+
state: "active",
|
|
13914
|
+
metadata: {
|
|
13915
|
+
...tagSource && { source: chunk6YUACVX4_cjs.WALLET_RECEIVE_SOURCE },
|
|
13916
|
+
signingDescriptor: descriptor
|
|
13917
|
+
}
|
|
13578
13918
|
}
|
|
13579
|
-
}
|
|
13580
|
-
this.setBoardingTapscriptForRotation(newBoarding);
|
|
13581
|
-
try {
|
|
13582
|
-
await manager.refillLookAhead();
|
|
13583
|
-
} catch (e) {
|
|
13584
|
-
console.warn("look-ahead refill after boarding allocation failed", e);
|
|
13585
|
-
}
|
|
13586
|
-
return newBoarding.onchainAddress(this.network);
|
|
13919
|
+
};
|
|
13587
13920
|
}
|
|
13588
13921
|
/**
|
|
13589
13922
|
* @see HDWalletCapable.getCurrentSigningDescriptor
|
|
@@ -13608,7 +13941,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13608
13941
|
if (this._descriptorProvider instanceof HDDescriptorProvider) {
|
|
13609
13942
|
return (await this.getContractManager()).getNextSigningDescriptor();
|
|
13610
13943
|
}
|
|
13611
|
-
return
|
|
13944
|
+
return chunk6YUACVX4_cjs.identityDescriptor(this.identity);
|
|
13612
13945
|
}
|
|
13613
13946
|
/**
|
|
13614
13947
|
* @see HDAllocationCapable.advanceSigningDescriptorWatermark
|
|
@@ -13704,7 +14037,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13704
14037
|
* the stable public API.
|
|
13705
14038
|
*/
|
|
13706
14039
|
async rotateServerSigner(newServerPubKey, checkpointTapscript) {
|
|
13707
|
-
const xonly =
|
|
14040
|
+
const xonly = chunk6YUACVX4_cjs.toXOnly(newServerPubKey, "ark signer key");
|
|
13708
14041
|
const newServerUnrollScript = assertValidServerUnrollScript(
|
|
13709
14042
|
checkpointTapscript,
|
|
13710
14043
|
resolveCheckpointExitDelayPolicy(this.network, this.checkpointExitDelayPolicy)
|
|
@@ -13733,21 +14066,21 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13733
14066
|
const [currentBoardingRow] = await manager.getContracts({
|
|
13734
14067
|
script: currentBoardingScript
|
|
13735
14068
|
});
|
|
13736
|
-
const newOffchain = this.offchainTapscript instanceof
|
|
14069
|
+
const newOffchain = this.offchainTapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? new chunk6YUACVX4_cjs.DelegateVtxo.Script({
|
|
13737
14070
|
...this.offchainTapscript.options,
|
|
13738
14071
|
serverPubKey: xonly
|
|
13739
|
-
}) : new
|
|
14072
|
+
}) : new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
13740
14073
|
...this.offchainTapscript.options,
|
|
13741
14074
|
serverPubKey: xonly
|
|
13742
14075
|
});
|
|
13743
|
-
const newBoarding = new
|
|
14076
|
+
const newBoarding = new chunk6YUACVX4_cjs.DefaultVtxo.Script({
|
|
13744
14077
|
...this._boardingTapscript.options,
|
|
13745
14078
|
serverPubKey: xonly
|
|
13746
14079
|
});
|
|
13747
|
-
const offchainCsv =
|
|
14080
|
+
const offchainCsv = chunkEJOFL5WH_cjs.timelockToSequence(newOffchain.options.csvTimelock).toString();
|
|
13748
14081
|
const newOffchainScript = base.hex.encode(newOffchain.pkScript);
|
|
13749
14082
|
const newOffchainAddress = newOffchain.address(this.network.hrp, xonly).encode();
|
|
13750
|
-
if (newOffchain instanceof
|
|
14083
|
+
if (newOffchain instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script) {
|
|
13751
14084
|
await manager.createContract({
|
|
13752
14085
|
type: "delegate",
|
|
13753
14086
|
params: {
|
|
@@ -13775,13 +14108,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13775
14108
|
metadata: currentOffchainRow?.metadata
|
|
13776
14109
|
});
|
|
13777
14110
|
}
|
|
13778
|
-
const boardingCsv = newBoarding.options.csvTimelock ??
|
|
14111
|
+
const boardingCsv = newBoarding.options.csvTimelock ?? chunk6YUACVX4_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
13779
14112
|
await manager.createContract({
|
|
13780
14113
|
type: "boarding",
|
|
13781
14114
|
params: {
|
|
13782
14115
|
pubKey: base.hex.encode(newBoarding.options.pubKey),
|
|
13783
14116
|
serverPubKey: base.hex.encode(xonly),
|
|
13784
|
-
csvTimelock:
|
|
14117
|
+
csvTimelock: chunkEJOFL5WH_cjs.timelockToSequence(boardingCsv).toString()
|
|
13785
14118
|
},
|
|
13786
14119
|
script: base.hex.encode(newBoarding.pkScript),
|
|
13787
14120
|
address: newBoarding.address(this.network.hrp, xonly).encode(),
|
|
@@ -13814,14 +14147,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13814
14147
|
_restoreInFlight;
|
|
13815
14148
|
_addPendingSpends(inputs) {
|
|
13816
14149
|
for (const input of inputs) {
|
|
13817
|
-
if (
|
|
14150
|
+
if (chunkEJOFL5WH_cjs.isVirtualCoin(input)) {
|
|
13818
14151
|
this._pendingSpendOutpoints.add(`${input.txid}:${input.vout}`);
|
|
13819
14152
|
}
|
|
13820
14153
|
}
|
|
13821
14154
|
}
|
|
13822
14155
|
_removePendingSpends(inputs) {
|
|
13823
14156
|
for (const input of inputs) {
|
|
13824
|
-
if (
|
|
14157
|
+
if (chunkEJOFL5WH_cjs.isVirtualCoin(input)) {
|
|
13825
14158
|
this._pendingSpendOutpoints.delete(`${input.txid}:${input.vout}`);
|
|
13826
14159
|
}
|
|
13827
14160
|
}
|
|
@@ -13879,13 +14212,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13879
14212
|
const manager = await this.getContractManager();
|
|
13880
14213
|
const provider = this._descriptorProvider;
|
|
13881
14214
|
const hd = provider instanceof HDDescriptorProvider;
|
|
13882
|
-
const staticDescriptor = hd ? void 0 : await
|
|
14215
|
+
const staticDescriptor = hd ? void 0 : await chunk6YUACVX4_cjs.identityDescriptor(this.identity);
|
|
13883
14216
|
const materialize = (index) => hd ? provider.materializeDescriptorAt(index) : staticDescriptor;
|
|
13884
|
-
const delegatePubKey = this.offchainTapscript instanceof
|
|
14217
|
+
const delegatePubKey = this.offchainTapscript instanceof chunk6YUACVX4_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
|
|
13885
14218
|
const arkInfo = await this.arkProvider.getInfo();
|
|
13886
|
-
const currentSignerPubKey =
|
|
14219
|
+
const currentSignerPubKey = chunk6YUACVX4_cjs.toXOnly(base.hex.decode(arkInfo.signerPubkey), "ark signer key");
|
|
13887
14220
|
const deprecatedSignerPubKeys = arkInfo.deprecatedSigners.map(
|
|
13888
|
-
(s) =>
|
|
14221
|
+
(s) => chunk6YUACVX4_cjs.toXOnly(base.hex.decode(s.pubkey), "deprecated signer key")
|
|
13889
14222
|
);
|
|
13890
14223
|
const deps = {
|
|
13891
14224
|
indexerProvider: this.indexerProvider,
|
|
@@ -13900,7 +14233,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13900
14233
|
csvTimelocks: this.walletContractTimelocks,
|
|
13901
14234
|
// Boarding-exit CSV so the boarding handler can build its
|
|
13902
14235
|
// candidate script (distinct from the unilateral-exit matrix).
|
|
13903
|
-
boardingTimelock: this.boardingTapscript.options.csvTimelock ??
|
|
14236
|
+
boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunk6YUACVX4_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
|
|
13904
14237
|
delegatePubKey
|
|
13905
14238
|
};
|
|
13906
14239
|
const result = await manager.scanContracts({
|
|
@@ -13968,7 +14301,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
13968
14301
|
await this._restoreInFlight?.catch(() => void 0);
|
|
13969
14302
|
this._serverInfoUnsub?.();
|
|
13970
14303
|
this._serverInfoUnsub = void 0;
|
|
13971
|
-
await this.
|
|
14304
|
+
await this.settleServerInfoChanges();
|
|
13972
14305
|
let rotatorError;
|
|
13973
14306
|
try {
|
|
13974
14307
|
await this._receiveRotator?.dispose();
|
|
@@ -14014,7 +14347,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14014
14347
|
throw new Error("Invalid configured public key");
|
|
14015
14348
|
}
|
|
14016
14349
|
const setup = await ReadonlyWallet.setupWalletConfig(config, pubkey);
|
|
14017
|
-
const forfeitPubkey =
|
|
14350
|
+
const forfeitPubkey = chunk6YUACVX4_cjs.toXOnly(base.hex.decode(setup.info.forfeitPubkey), "forfeit key");
|
|
14018
14351
|
const forfeitAddress = btcSigner.Address(setup.network).decode(setup.info.forfeitAddress);
|
|
14019
14352
|
const forfeitOutputScript = btcSigner.OutScript.encode(forfeitAddress);
|
|
14020
14353
|
const checkpointExitDelayOverrides = {
|
|
@@ -14163,7 +14496,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14163
14496
|
inputs: params.selectedVtxos,
|
|
14164
14497
|
changeAmount: BigInt(changeAmount)
|
|
14165
14498
|
};
|
|
14166
|
-
const outputAddress =
|
|
14499
|
+
const outputAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(params.address);
|
|
14167
14500
|
assertRecipientArkAddress(
|
|
14168
14501
|
params.address,
|
|
14169
14502
|
outputAddress,
|
|
@@ -14229,13 +14562,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14229
14562
|
void this.logUngatedInputs("settle({ inputs })", params.inputs);
|
|
14230
14563
|
}
|
|
14231
14564
|
const offchainAddress = await this.getAddress();
|
|
14232
|
-
const offchainPkScript =
|
|
14565
|
+
const offchainPkScript = chunkEJOFL5WH_cjs.ArkAddress.decode(offchainAddress).pkScript;
|
|
14233
14566
|
const offchainOutputScript = base.hex.encode(offchainPkScript);
|
|
14234
14567
|
if (!params) {
|
|
14235
14568
|
const { fees, vtxoMaxAmount } = await this.arkProvider.getInfo();
|
|
14236
14569
|
const estimator = new Estimator(fees.intentFee);
|
|
14237
14570
|
let amount = 0;
|
|
14238
|
-
const exitScript =
|
|
14571
|
+
const exitScript = chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(
|
|
14239
14572
|
base.hex.decode(this.boardingTapscript.exitScript)
|
|
14240
14573
|
);
|
|
14241
14574
|
const boardingTimelock = exitScript.params.timelock;
|
|
@@ -14264,7 +14597,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14264
14597
|
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
14265
14598
|
break;
|
|
14266
14599
|
}
|
|
14267
|
-
const inputFee = estimator.evalOffchainInput(
|
|
14600
|
+
const inputFee = estimator.evalOffchainInput(chunkEJOFL5WH_cjs.toOffchainInputFeeParams(vtxo));
|
|
14268
14601
|
if (inputFee.satoshis >= vtxo.value) {
|
|
14269
14602
|
continue;
|
|
14270
14603
|
}
|
|
@@ -14311,7 +14644,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14311
14644
|
let script;
|
|
14312
14645
|
let arkAddress;
|
|
14313
14646
|
try {
|
|
14314
|
-
arkAddress =
|
|
14647
|
+
arkAddress = chunkEJOFL5WH_cjs.ArkAddress.decode(output.address);
|
|
14315
14648
|
} catch {
|
|
14316
14649
|
arkAddress = void 0;
|
|
14317
14650
|
}
|
|
@@ -14401,7 +14734,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14401
14734
|
const abortController = new AbortController();
|
|
14402
14735
|
let stream;
|
|
14403
14736
|
let committedTxid;
|
|
14404
|
-
const settleInputVtxos = params.inputs.filter(
|
|
14737
|
+
const settleInputVtxos = params.inputs.filter(chunkEJOFL5WH_cjs.isVirtualCoin);
|
|
14405
14738
|
const contractManager = await this.getContractManager();
|
|
14406
14739
|
await contractManager.assertAnnotatable(settleInputVtxos);
|
|
14407
14740
|
await contractManager.assertSpendableNow?.(
|
|
@@ -14500,7 +14833,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14500
14833
|
* `typeof` guard skips the arknote strings settle also accepts.
|
|
14501
14834
|
*
|
|
14502
14835
|
* No-ops for static / `auto` wallets (no descriptor provider — boarding
|
|
14503
|
-
* stays on its fixed index-0 address).
|
|
14836
|
+
* stays on its fixed index-0 address). Wallets on a custom
|
|
14837
|
+
* {@link DescriptorProvider} DO rotate here now, where they previously
|
|
14838
|
+
* no-opped — see the behaviour-change note on {@link
|
|
14839
|
+
* getNewBoardingAddress}. Best-effort and non-fatal: the
|
|
14504
14840
|
* settle has already committed and its txid must be returned, so a
|
|
14505
14841
|
* rotation failure is logged and swallowed rather than thrown. Funds at
|
|
14506
14842
|
* the retired boarding address remain discoverable — the old `boarding`
|
|
@@ -14510,7 +14846,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14510
14846
|
async maybeRotateBoardingAfterBoard(inputs) {
|
|
14511
14847
|
if (!this._descriptorProvider) return;
|
|
14512
14848
|
const consumedBoarding = inputs.some(
|
|
14513
|
-
(input) => typeof input !== "string" && !
|
|
14849
|
+
(input) => typeof input !== "string" && !chunkEJOFL5WH_cjs.isVirtualCoin(input)
|
|
14514
14850
|
);
|
|
14515
14851
|
if (!consumedBoarding) return;
|
|
14516
14852
|
try {
|
|
@@ -14534,7 +14870,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14534
14870
|
let connectorIndex = 0;
|
|
14535
14871
|
const connectorsLeaves = connectorsGraph?.leaves() || [];
|
|
14536
14872
|
for (const input of inputs) {
|
|
14537
|
-
if (!
|
|
14873
|
+
if (!chunkEJOFL5WH_cjs.isVirtualCoin(input)) {
|
|
14538
14874
|
for (let i = 0; i < settlementPsbt.inputsLength; i++) {
|
|
14539
14875
|
const settlementInput = settlementPsbt.getInput(i);
|
|
14540
14876
|
if (!settlementInput.txid || settlementInput.index === void 0) {
|
|
@@ -14565,7 +14901,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14565
14901
|
}
|
|
14566
14902
|
continue;
|
|
14567
14903
|
}
|
|
14568
|
-
if (
|
|
14904
|
+
if (chunkEJOFL5WH_cjs.canRecoverOnchain(input, { timestamp: /* @__PURE__ */ new Date() }) || isSubdust({ value: input.value }, this.dustAmount)) {
|
|
14569
14905
|
continue;
|
|
14570
14906
|
}
|
|
14571
14907
|
if (connectorsLeaves.length === 0) {
|
|
@@ -14593,7 +14929,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14593
14929
|
index: input.vout,
|
|
14594
14930
|
witnessUtxo: {
|
|
14595
14931
|
amount: BigInt(input.value),
|
|
14596
|
-
script:
|
|
14932
|
+
script: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
14597
14933
|
},
|
|
14598
14934
|
sighashType: btcSigner.SigHash.DEFAULT,
|
|
14599
14935
|
tapLeafScript: [input.forfeitTapLeafScript]
|
|
@@ -14612,7 +14948,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14612
14948
|
forfeitTx = await this._signerRouter.sign(forfeitTx, [
|
|
14613
14949
|
{
|
|
14614
14950
|
index: 0,
|
|
14615
|
-
lookupScript:
|
|
14951
|
+
lookupScript: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
14616
14952
|
}
|
|
14617
14953
|
]);
|
|
14618
14954
|
signedForfeits.push(base.base64.encode(forfeitTx.toPSBT()));
|
|
@@ -14670,7 +15006,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14670
15006
|
resolveBatchExpiryPolicy(this.network, this.batchExpiryPolicy)
|
|
14671
15007
|
);
|
|
14672
15008
|
await this.arkProvider.confirmRegistration(intentId);
|
|
14673
|
-
const sweepTapscript =
|
|
15009
|
+
const sweepTapscript = chunkEJOFL5WH_cjs.CSVMultisigTapscript.encode({
|
|
14674
15010
|
timelock,
|
|
14675
15011
|
pubkeys: [this.forfeitPubkey]
|
|
14676
15012
|
}).script;
|
|
@@ -14685,10 +15021,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14685
15021
|
throw new Error("Sweep tap tree root not set");
|
|
14686
15022
|
}
|
|
14687
15023
|
const xOnlyPublicKeys = event.cosignersPublicKeys.map(
|
|
14688
|
-
(k) => base.hex.encode(
|
|
15024
|
+
(k) => base.hex.encode(chunk6YUACVX4_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
|
|
14689
15025
|
);
|
|
14690
15026
|
const signerPublicKey = await session.getPublicKey();
|
|
14691
|
-
const xonlySignerPublicKey =
|
|
15027
|
+
const xonlySignerPublicKey = chunk6YUACVX4_cjs.toXOnly(signerPublicKey, "signer key");
|
|
14692
15028
|
if (!xOnlyPublicKeys.includes(base.hex.encode(xonlySignerPublicKey))) {
|
|
14693
15029
|
return { skip: true };
|
|
14694
15030
|
}
|
|
@@ -14778,9 +15114,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14778
15114
|
...existing ?? {},
|
|
14779
15115
|
intentTxId,
|
|
14780
15116
|
registerProof: intent.proof,
|
|
14781
|
-
registerProofMessage:
|
|
15117
|
+
registerProofMessage: chunkEJOFL5WH_cjs.Intent.encodeMessage(intent.message),
|
|
14782
15118
|
deleteProof: deleteIntent.proof,
|
|
14783
|
-
deleteProofMessage:
|
|
15119
|
+
deleteProofMessage: chunkEJOFL5WH_cjs.Intent.encodeMessage(deleteIntent.message),
|
|
14784
15120
|
intentVtxos: inputs.map((i) => ({
|
|
14785
15121
|
txid: i.txid,
|
|
14786
15122
|
vout: i.vout
|
|
@@ -14812,7 +15148,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14812
15148
|
try {
|
|
14813
15149
|
return await this.arkProvider.registerIntent(intent);
|
|
14814
15150
|
} catch (error) {
|
|
14815
|
-
if (error instanceof
|
|
15151
|
+
if (error instanceof chunkEJOFL5WH_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
|
|
14816
15152
|
const deleteIntent = await this.makeDeleteIntentSignature(inputs);
|
|
14817
15153
|
await this.arkProvider.deleteIntent(deleteIntent);
|
|
14818
15154
|
return this.arkProvider.registerIntent(intent);
|
|
@@ -14828,7 +15164,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14828
15164
|
expire_at: 0,
|
|
14829
15165
|
cosigners_public_keys: cosignerPubKeys
|
|
14830
15166
|
};
|
|
14831
|
-
const proof =
|
|
15167
|
+
const proof = chunkEJOFL5WH_cjs.Intent.create(message, coins, outputs);
|
|
14832
15168
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
14833
15169
|
return {
|
|
14834
15170
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -14840,7 +15176,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14840
15176
|
type: "delete",
|
|
14841
15177
|
expire_at: 0
|
|
14842
15178
|
};
|
|
14843
|
-
const proof =
|
|
15179
|
+
const proof = chunkEJOFL5WH_cjs.Intent.create(message, coins, []);
|
|
14844
15180
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
14845
15181
|
return {
|
|
14846
15182
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -14852,7 +15188,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14852
15188
|
type: "get-pending-tx",
|
|
14853
15189
|
expire_at: 0
|
|
14854
15190
|
};
|
|
14855
|
-
const proof =
|
|
15191
|
+
const proof = chunkEJOFL5WH_cjs.Intent.create(message, coins, []);
|
|
14856
15192
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
14857
15193
|
return {
|
|
14858
15194
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -14873,7 +15209,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14873
15209
|
if (!vtxos || vtxos.length === 0) {
|
|
14874
15210
|
const scriptMap = await this.getScriptMap();
|
|
14875
15211
|
const allExtended = [];
|
|
14876
|
-
const fetchedVtxos = await
|
|
15212
|
+
const fetchedVtxos = await chunkEJOFL5WH_cjs.getAllNormalizedVtxos(this.indexerProvider, [
|
|
14877
15213
|
...scriptMap.keys()
|
|
14878
15214
|
]);
|
|
14879
15215
|
for (const vtxo of fetchedVtxos) {
|
|
@@ -14915,9 +15251,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14915
15251
|
seen.add(pendingTx.arkTxid);
|
|
14916
15252
|
batchPending.push(pendingTx.arkTxid);
|
|
14917
15253
|
try {
|
|
14918
|
-
const checkpointTxs = pendingTx.signedCheckpointTxs.map(
|
|
14919
|
-
|
|
14920
|
-
|
|
15254
|
+
const checkpointTxs = pendingTx.signedCheckpointTxs.map((c) => {
|
|
15255
|
+
const tx = btcSigner.Transaction.fromPSBT(base.base64.decode(c));
|
|
15256
|
+
chunkEJOFL5WH_cjs.assertAllowedSighashTypes(tx);
|
|
15257
|
+
return tx;
|
|
15258
|
+
});
|
|
14921
15259
|
assertCheckpointsMatchInputs(
|
|
14922
15260
|
checkpointTxs,
|
|
14923
15261
|
checkpointInputs,
|
|
@@ -14987,11 +15325,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
14987
15325
|
* against the current key alone would leave it pending forever.
|
|
14988
15326
|
*/
|
|
14989
15327
|
checkpointUnrollCandidates(info) {
|
|
14990
|
-
const current =
|
|
15328
|
+
const current = chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
|
|
14991
15329
|
const candidates = [this._serverUnrollScript, current];
|
|
14992
15330
|
for (const deprecated of signerSetFromInfo(info).deprecated.keys()) {
|
|
14993
15331
|
candidates.push(
|
|
14994
|
-
|
|
15332
|
+
chunkEJOFL5WH_cjs.CSVMultisigTapscript.encode({
|
|
14995
15333
|
...current.params,
|
|
14996
15334
|
pubkeys: [base.hex.decode(deprecated)]
|
|
14997
15335
|
})
|
|
@@ -15082,10 +15420,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15082
15420
|
if (vtxos.length === 0) {
|
|
15083
15421
|
throw new Error("No VTXOs found for this arkadeCash");
|
|
15084
15422
|
}
|
|
15085
|
-
const myPkScript =
|
|
15423
|
+
const myPkScript = chunkEJOFL5WH_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
|
|
15086
15424
|
let { spendable, unclaimed } = this.classifyCashVtxos(vtxos);
|
|
15087
15425
|
let swept = 0;
|
|
15088
|
-
const drainable = vtxos.filter(
|
|
15426
|
+
const drainable = vtxos.filter(
|
|
15427
|
+
(vtxo) => !isSubdust(vtxo, this.dustAmount) && !vtxo.isUnrolled
|
|
15428
|
+
);
|
|
15089
15429
|
if (drainable.length > 0) {
|
|
15090
15430
|
let drained = { count: 0, swept: 0, claimed: /* @__PURE__ */ new Set() };
|
|
15091
15431
|
try {
|
|
@@ -15156,8 +15496,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15156
15496
|
const spendable = [];
|
|
15157
15497
|
const unclaimed = [];
|
|
15158
15498
|
for (const vtxo of vtxos) {
|
|
15159
|
-
if (
|
|
15499
|
+
if (chunkEJOFL5WH_cjs.hasTerminalSpend(vtxo)) {
|
|
15160
15500
|
unclaimed.push(cashReport(vtxo, "already-spent"));
|
|
15501
|
+
} else if (vtxo.isUnrolled) {
|
|
15502
|
+
unclaimed.push(cashReport(vtxo, "exited"));
|
|
15161
15503
|
} else if (isSubdust(vtxo, this.dustAmount)) {
|
|
15162
15504
|
unclaimed.push(cashReport(vtxo, "subdust"));
|
|
15163
15505
|
} else if (vtxo.isSwept) {
|
|
@@ -15176,7 +15518,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15176
15518
|
const all = [];
|
|
15177
15519
|
const seen = /* @__PURE__ */ new Set();
|
|
15178
15520
|
for (let pageIndex = 0; ; pageIndex++) {
|
|
15179
|
-
const { vtxos, page } = await
|
|
15521
|
+
const { vtxos, page } = await chunkEJOFL5WH_cjs.getNormalizedVtxos(this.indexerProvider, {
|
|
15180
15522
|
scripts,
|
|
15181
15523
|
pageIndex,
|
|
15182
15524
|
pageSize
|
|
@@ -15223,7 +15565,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15223
15565
|
for (let i = 0; i < inputs.length; i += MAX_INPUTS_PER_INTENT) {
|
|
15224
15566
|
const batch = inputs.slice(i, i + MAX_INPUTS_PER_INTENT);
|
|
15225
15567
|
const message = { type: "get-pending-tx", expire_at: 0 };
|
|
15226
|
-
const proof =
|
|
15568
|
+
const proof = chunkEJOFL5WH_cjs.Intent.create(message, batch, []);
|
|
15227
15569
|
const signedProof = await identity.sign(
|
|
15228
15570
|
proof,
|
|
15229
15571
|
Array.from({ length: batch.length + 1 }, (_, j) => j)
|
|
@@ -15243,9 +15585,11 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15243
15585
|
const unrollCandidates = this.checkpointUnrollCandidates(await this.arkProvider.getInfo());
|
|
15244
15586
|
for (const pendingTx of pendingTxs) {
|
|
15245
15587
|
try {
|
|
15246
|
-
const checkpointTxs = pendingTx.signedCheckpointTxs.map(
|
|
15247
|
-
|
|
15248
|
-
|
|
15588
|
+
const checkpointTxs = pendingTx.signedCheckpointTxs.map((checkpoint) => {
|
|
15589
|
+
const tx = btcSigner.Transaction.fromPSBT(base.base64.decode(checkpoint));
|
|
15590
|
+
chunkEJOFL5WH_cjs.assertAllowedSighashTypes(tx);
|
|
15591
|
+
return tx;
|
|
15592
|
+
});
|
|
15249
15593
|
assertCheckpointsMatchInputs(
|
|
15250
15594
|
checkpointTxs,
|
|
15251
15595
|
inputs.map((input) => ({
|
|
@@ -15442,7 +15786,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15442
15786
|
script: recipient.script,
|
|
15443
15787
|
amount: BigInt(recipient.amount),
|
|
15444
15788
|
// Already checked against the recipient address in `validateRecipients`.
|
|
15445
|
-
...recipient.tapTree ? { tapTree:
|
|
15789
|
+
...recipient.tapTree ? { tapTree: chunkEJOFL5WH_cjs.TapTreeCoder.decode(recipient.tapTree) } : {}
|
|
15446
15790
|
}));
|
|
15447
15791
|
const totalBtcOutput = outputs.reduce((sum, o) => sum + Number(o.amount), 0);
|
|
15448
15792
|
let changeAmount = totalBtcSelected - totalBtcOutput;
|
|
@@ -15586,10 +15930,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15586
15930
|
const serverPubKey = this.arkServerPublicKey;
|
|
15587
15931
|
const serverUnrollScript = this.serverUnrollScript;
|
|
15588
15932
|
const arkAddress = offchainTapscript.address(this.network.hrp, serverPubKey);
|
|
15589
|
-
const normalizedInputs = inputs.map(
|
|
15590
|
-
const at = now ?? await
|
|
15933
|
+
const normalizedInputs = inputs.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
15934
|
+
const at = now ?? await chunkEJOFL5WH_cjs.resolveTimeHeight(this.onchainProvider);
|
|
15591
15935
|
for (const input of normalizedInputs) {
|
|
15592
|
-
if (!
|
|
15936
|
+
if (!chunkEJOFL5WH_cjs.canSpendOffchain(input, at)) {
|
|
15593
15937
|
throw new Error(
|
|
15594
15938
|
`sendSelectedVtxosToSelf: input ${input.txid}:${input.vout} is not cooperatively spendable`
|
|
15595
15939
|
);
|
|
@@ -15659,7 +16003,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15659
16003
|
);
|
|
15660
16004
|
const arkTxJobs = inputs.map((input, index) => ({
|
|
15661
16005
|
index,
|
|
15662
|
-
lookupScript:
|
|
16006
|
+
lookupScript: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
15663
16007
|
}));
|
|
15664
16008
|
const identity = this.identity;
|
|
15665
16009
|
const signer = {
|
|
@@ -15745,14 +16089,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15745
16089
|
const spentBy = checkpointIdByOutpoint.get(`${vtxo.txid}:${vtxo.vout}`);
|
|
15746
16090
|
spentVtxos.push({
|
|
15747
16091
|
...spentFacts,
|
|
15748
|
-
virtualStatus:
|
|
16092
|
+
virtualStatus: chunkEJOFL5WH_cjs.toVirtualStatus(spentFacts),
|
|
15749
16093
|
...spentBy ? { spentBy } : {},
|
|
15750
16094
|
arkTxId: arkTxid
|
|
15751
16095
|
});
|
|
15752
16096
|
for (const id of vtxo.commitmentTxIds) {
|
|
15753
16097
|
commitmentTxIds.add(id);
|
|
15754
16098
|
}
|
|
15755
|
-
const vtxoExpiry =
|
|
16099
|
+
const vtxoExpiry = chunkEJOFL5WH_cjs.toBatchExpiry(vtxo);
|
|
15756
16100
|
if (vtxoExpiry) {
|
|
15757
16101
|
batchExpiry = Math.min(batchExpiry, vtxoExpiry);
|
|
15758
16102
|
}
|
|
@@ -15765,7 +16109,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15765
16109
|
isSwept: false,
|
|
15766
16110
|
isPreconfirmed: true,
|
|
15767
16111
|
commitmentTxIds: Array.from(commitmentTxIds),
|
|
15768
|
-
...
|
|
16112
|
+
...chunkEJOFL5WH_cjs.parseLegacyExpiry(batchExpiry)
|
|
15769
16113
|
};
|
|
15770
16114
|
changeVtxo = {
|
|
15771
16115
|
txid: arkTxid,
|
|
@@ -15777,7 +16121,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15777
16121
|
tapTree: offchainTapscript.encode(),
|
|
15778
16122
|
value: Number(changeAmount),
|
|
15779
16123
|
...changeFacts,
|
|
15780
|
-
virtualStatus:
|
|
16124
|
+
virtualStatus: chunkEJOFL5WH_cjs.toVirtualStatus(changeFacts),
|
|
15781
16125
|
spentBy: "",
|
|
15782
16126
|
status: {
|
|
15783
16127
|
confirmed: false
|
|
@@ -15846,12 +16190,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15846
16190
|
const spentVtxos = [];
|
|
15847
16191
|
const inputArkTxIds = /* @__PURE__ */ new Set();
|
|
15848
16192
|
const boardingRemovalsByAddress = /* @__PURE__ */ new Map();
|
|
15849
|
-
const vtxoInputs = inputs.filter(
|
|
16193
|
+
const vtxoInputs = inputs.filter(chunkEJOFL5WH_cjs.isVirtualCoin);
|
|
15850
16194
|
const cm = await this.getContractManager();
|
|
15851
16195
|
const annotatedVtxos = await cm.annotateVtxos(vtxoInputs);
|
|
15852
16196
|
const annotatedByKey = new Map(annotatedVtxos.map((v) => [`${v.txid}:${v.vout}`, v]));
|
|
15853
16197
|
for (const input of inputs) {
|
|
15854
|
-
if (
|
|
16198
|
+
if (chunkEJOFL5WH_cjs.isVirtualCoin(input)) {
|
|
15855
16199
|
const outpoint = `${input.txid}:${input.vout}`;
|
|
15856
16200
|
const vtxo = annotatedByKey.get(outpoint);
|
|
15857
16201
|
if (!vtxo) {
|
|
@@ -15863,13 +16207,13 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15863
16207
|
const settledFacts = { ...vtxo, isSpent: true };
|
|
15864
16208
|
spentVtxos.push({
|
|
15865
16209
|
...settledFacts,
|
|
15866
|
-
virtualStatus:
|
|
16210
|
+
virtualStatus: chunkEJOFL5WH_cjs.toVirtualStatus(settledFacts),
|
|
15867
16211
|
settledBy: commitmentTxid
|
|
15868
16212
|
});
|
|
15869
16213
|
} else {
|
|
15870
16214
|
let sourceAddress;
|
|
15871
16215
|
try {
|
|
15872
|
-
sourceAddress =
|
|
16216
|
+
sourceAddress = chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
|
|
15873
16217
|
this.network
|
|
15874
16218
|
);
|
|
15875
16219
|
} catch {
|
|
@@ -15927,9 +16271,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
15927
16271
|
}
|
|
15928
16272
|
};
|
|
15929
16273
|
function selectVirtualCoins(coins, targetAmount) {
|
|
15930
|
-
const sortedCoins = coins.map(
|
|
15931
|
-
const expiryA =
|
|
15932
|
-
const expiryB =
|
|
16274
|
+
const sortedCoins = coins.map(chunkEJOFL5WH_cjs.normalizeVtxo).sort((a, b) => {
|
|
16275
|
+
const expiryA = chunkEJOFL5WH_cjs.toBatchExpiry(a) || Number.MAX_SAFE_INTEGER;
|
|
16276
|
+
const expiryB = chunkEJOFL5WH_cjs.toBatchExpiry(b) || Number.MAX_SAFE_INTEGER;
|
|
15933
16277
|
if (expiryA !== expiryB) {
|
|
15934
16278
|
return expiryA - expiryB;
|
|
15935
16279
|
}
|
|
@@ -16048,6 +16392,11 @@ var MessageBus = class {
|
|
|
16048
16392
|
buildServicesFn;
|
|
16049
16393
|
boundOnMessage = this.onMessage.bind(this);
|
|
16050
16394
|
intentRepository;
|
|
16395
|
+
/** Pending broadcasts, drained FIFO by a single {@link drain} loop. */
|
|
16396
|
+
broadcastQueue = [];
|
|
16397
|
+
draining = false;
|
|
16398
|
+
/** Bumped wherever the generation owning the queued broadcasts ends. */
|
|
16399
|
+
broadcastEpoch = 0;
|
|
16051
16400
|
/** Start the message bus and attach service-worker event listeners. */
|
|
16052
16401
|
async start() {
|
|
16053
16402
|
if (this.running) return;
|
|
@@ -16070,6 +16419,7 @@ var MessageBus = class {
|
|
|
16070
16419
|
this.running = false;
|
|
16071
16420
|
this.tickInProgress = false;
|
|
16072
16421
|
this.initialized = false;
|
|
16422
|
+
this.invalidateBroadcasts();
|
|
16073
16423
|
if (this.tickTimeout !== null) {
|
|
16074
16424
|
self.clearTimeout(this.tickTimeout);
|
|
16075
16425
|
this.tickTimeout = null;
|
|
@@ -16082,6 +16432,78 @@ var MessageBus = class {
|
|
|
16082
16432
|
self.removeEventListener("message", this.boundOnMessage);
|
|
16083
16433
|
await Promise.all(Array.from(this.handlers.values()).map((updater) => updater.stop()));
|
|
16084
16434
|
}
|
|
16435
|
+
/** Invalidate every broadcast belonging to the outgoing generation. */
|
|
16436
|
+
invalidateBroadcasts() {
|
|
16437
|
+
this.broadcastEpoch++;
|
|
16438
|
+
this.broadcastQueue.length = 0;
|
|
16439
|
+
}
|
|
16440
|
+
broadcastToClients(responses) {
|
|
16441
|
+
this.broadcastQueue.push(...responses);
|
|
16442
|
+
void this.drain();
|
|
16443
|
+
}
|
|
16444
|
+
/**
|
|
16445
|
+
* Single fan-out loop, so pushes and tick responses keep one FIFO order.
|
|
16446
|
+
* A helper posting per response would race: `clients.matchAll()` gives no
|
|
16447
|
+
* cross-call resolution order, and it would de-batch `runTick`.
|
|
16448
|
+
*/
|
|
16449
|
+
async drain() {
|
|
16450
|
+
if (this.draining) return;
|
|
16451
|
+
this.draining = true;
|
|
16452
|
+
try {
|
|
16453
|
+
while (this.broadcastQueue.length) {
|
|
16454
|
+
const epoch = this.broadcastEpoch;
|
|
16455
|
+
const batch = this.broadcastQueue.splice(0);
|
|
16456
|
+
if (!this.running) {
|
|
16457
|
+
this.logDroppedBroadcasts(batch, "bus stopped");
|
|
16458
|
+
return;
|
|
16459
|
+
}
|
|
16460
|
+
let clients;
|
|
16461
|
+
try {
|
|
16462
|
+
clients = await self.clients.matchAll({
|
|
16463
|
+
includeUncontrolled: true,
|
|
16464
|
+
type: "window"
|
|
16465
|
+
});
|
|
16466
|
+
} catch (err) {
|
|
16467
|
+
this.logDroppedBroadcasts(batch, "clients.matchAll failed", err);
|
|
16468
|
+
continue;
|
|
16469
|
+
}
|
|
16470
|
+
if (!this.running) {
|
|
16471
|
+
this.logDroppedBroadcasts(batch, "bus stopped during matchAll");
|
|
16472
|
+
return;
|
|
16473
|
+
}
|
|
16474
|
+
if (this.broadcastEpoch !== epoch) {
|
|
16475
|
+
this.logDroppedBroadcasts(batch, "re-init landed during matchAll");
|
|
16476
|
+
continue;
|
|
16477
|
+
}
|
|
16478
|
+
for (const message of batch) {
|
|
16479
|
+
for (const client of clients) {
|
|
16480
|
+
try {
|
|
16481
|
+
client.postMessage(message);
|
|
16482
|
+
} catch (err) {
|
|
16483
|
+
if (this.debug)
|
|
16484
|
+
console.warn(`[${message.tag}] broadcast to client failed`, err);
|
|
16485
|
+
}
|
|
16486
|
+
}
|
|
16487
|
+
}
|
|
16488
|
+
}
|
|
16489
|
+
} catch {
|
|
16490
|
+
} finally {
|
|
16491
|
+
this.draining = false;
|
|
16492
|
+
if (this.running && this.broadcastQueue.length) void this.drain();
|
|
16493
|
+
}
|
|
16494
|
+
}
|
|
16495
|
+
/**
|
|
16496
|
+
* A dropped batch has no periodic recovery to fall back on now that events
|
|
16497
|
+
* no longer ride the tick, so name the loss under {@link Options.debug}.
|
|
16498
|
+
*/
|
|
16499
|
+
logDroppedBroadcasts(batch, reason, ...error) {
|
|
16500
|
+
if (!this.debug) return;
|
|
16501
|
+
console.warn(
|
|
16502
|
+
`dropping ${batch.length} broadcast(s): ${reason}`,
|
|
16503
|
+
batch.map((response) => response.tag),
|
|
16504
|
+
...error
|
|
16505
|
+
);
|
|
16506
|
+
}
|
|
16085
16507
|
scheduleNextTick() {
|
|
16086
16508
|
if (!this.running) return;
|
|
16087
16509
|
if (this.tickTimeout !== null) return;
|
|
@@ -16110,16 +16532,7 @@ var MessageBus = class {
|
|
|
16110
16532
|
if (this.debug)
|
|
16111
16533
|
console.log(`[${updater.messageTag}] outgoing tick response:`, response);
|
|
16112
16534
|
if (response && response.length > 0) {
|
|
16113
|
-
|
|
16114
|
-
includeUncontrolled: true,
|
|
16115
|
-
type: "window"
|
|
16116
|
-
}).then((clients) => {
|
|
16117
|
-
for (const message of response) {
|
|
16118
|
-
clients.forEach((client) => {
|
|
16119
|
-
client.postMessage(message);
|
|
16120
|
-
});
|
|
16121
|
-
}
|
|
16122
|
-
});
|
|
16535
|
+
this.broadcastToClients(response);
|
|
16123
16536
|
}
|
|
16124
16537
|
} catch (err) {
|
|
16125
16538
|
if (this.debug) console.error(`[${updater.messageTag}] tick failed`, err);
|
|
@@ -16158,6 +16571,14 @@ var MessageBus = class {
|
|
|
16158
16571
|
self.clearTimeout(this.tickTimeout);
|
|
16159
16572
|
this.tickTimeout = null;
|
|
16160
16573
|
}
|
|
16574
|
+
this.invalidateBroadcasts();
|
|
16575
|
+
const epoch = this.broadcastEpoch;
|
|
16576
|
+
const channel = {
|
|
16577
|
+
broadcast: (response) => {
|
|
16578
|
+
if (epoch !== this.broadcastEpoch) return;
|
|
16579
|
+
this.broadcastToClients([response]);
|
|
16580
|
+
}
|
|
16581
|
+
};
|
|
16161
16582
|
if (this.initialized) {
|
|
16162
16583
|
this.initialized = false;
|
|
16163
16584
|
await Promise.all(
|
|
@@ -16174,9 +16595,7 @@ var MessageBus = class {
|
|
|
16174
16595
|
try {
|
|
16175
16596
|
for (const updater of this.handlers.values()) {
|
|
16176
16597
|
if (this.debug) console.log(`Starting updater: ${updater.messageTag}`);
|
|
16177
|
-
await updater.start(services, {
|
|
16178
|
-
walletRepository: this.walletRepository
|
|
16179
|
-
});
|
|
16598
|
+
await updater.start(services, { walletRepository: this.walletRepository }, channel);
|
|
16180
16599
|
started.push(updater);
|
|
16181
16600
|
}
|
|
16182
16601
|
} catch (err) {
|
|
@@ -16189,7 +16608,7 @@ var MessageBus = class {
|
|
|
16189
16608
|
this.initialized = true;
|
|
16190
16609
|
}
|
|
16191
16610
|
async buildServices(config) {
|
|
16192
|
-
const arkProvider = new
|
|
16611
|
+
const arkProvider = new chunkEJOFL5WH_cjs.RestArkProvider(config.arkServer.url);
|
|
16193
16612
|
const storage = {
|
|
16194
16613
|
walletRepository: this.walletRepository,
|
|
16195
16614
|
contractRepository: this.contractRepository,
|
|
@@ -16531,7 +16950,7 @@ var offboardNetworkNames = [
|
|
|
16531
16950
|
function offboardDestinationScript(destinationAddress) {
|
|
16532
16951
|
for (const networkName of offboardNetworkNames) {
|
|
16533
16952
|
try {
|
|
16534
|
-
const network =
|
|
16953
|
+
const network = chunkEJOFL5WH_cjs.networks[networkName];
|
|
16535
16954
|
const addr = btcSigner.Address(network).decode(destinationAddress);
|
|
16536
16955
|
return btcSigner.OutScript.encode(addr);
|
|
16537
16956
|
} catch {
|
|
@@ -16595,7 +17014,7 @@ var Ramps = class {
|
|
|
16595
17014
|
}
|
|
16596
17015
|
amount = amount ?? totalAmount;
|
|
16597
17016
|
const offchainAddress = await this.wallet.getAddress();
|
|
16598
|
-
const offchainAddr =
|
|
17017
|
+
const offchainAddr = chunkEJOFL5WH_cjs.ArkAddress.decode(offchainAddress);
|
|
16599
17018
|
const offchainScript = base.hex.encode(offchainAddr.pkScript);
|
|
16600
17019
|
const outputFee = estimator.evalOffchainOutput({
|
|
16601
17020
|
amount,
|
|
@@ -16655,7 +17074,7 @@ var Ramps = class {
|
|
|
16655
17074
|
const filteredVtxos = [];
|
|
16656
17075
|
let totalAmount = 0n;
|
|
16657
17076
|
for (const vtxo of vtxos) {
|
|
16658
|
-
const inputFee = estimator.evalOffchainInput(
|
|
17077
|
+
const inputFee = estimator.evalOffchainInput(chunkEJOFL5WH_cjs.toOffchainInputFeeParams(vtxo));
|
|
16659
17078
|
if (inputFee.satoshis >= vtxo.value) {
|
|
16660
17079
|
continue;
|
|
16661
17080
|
}
|
|
@@ -16846,6 +17265,17 @@ var WalletMessageHandler = class {
|
|
|
16846
17265
|
incomingFundsSubscription;
|
|
16847
17266
|
contractEventsSubscription;
|
|
16848
17267
|
onNextTick = [];
|
|
17268
|
+
channel;
|
|
17269
|
+
// One counter per subscription field, bumped exactly where that field is
|
|
17270
|
+
// dropped — never where a neighbour's is. They cannot be merged:
|
|
17271
|
+
// `onWalletInitialized` re-subscribes incoming funds while
|
|
17272
|
+
// `ensureContractEventBroadcasting` deliberately keeps its subscription, so
|
|
17273
|
+
// a shared bump would leave the live contract-event emitter permanently
|
|
17274
|
+
// stale, and folding requests in would truncate an in-flight settle.
|
|
17275
|
+
incomingFundsEpoch = 0;
|
|
17276
|
+
contractEventsEpoch = 0;
|
|
17277
|
+
/** Per-request progress callbacks: ends with the handler, not with a re-init. */
|
|
17278
|
+
requestEpoch = 0;
|
|
16849
17279
|
/**
|
|
16850
17280
|
* Instantiate a new WalletUpdater.
|
|
16851
17281
|
* Can override the default `messageTag` allowing more than one updater to run in parallel.
|
|
@@ -16856,13 +17286,20 @@ var WalletMessageHandler = class {
|
|
|
16856
17286
|
}
|
|
16857
17287
|
// lifecycle methods
|
|
16858
17288
|
async start(...params) {
|
|
16859
|
-
const [services, repositories] = params;
|
|
17289
|
+
const [services, repositories, channel] = params;
|
|
16860
17290
|
this.readonlyWallet = services.readonlyWallet;
|
|
16861
17291
|
this.wallet = services.wallet;
|
|
16862
17292
|
this.arkProvider = services.arkProvider;
|
|
16863
17293
|
this.walletRepository = repositories.walletRepository;
|
|
17294
|
+
this.channel = channel;
|
|
17295
|
+
this.onNextTick = [];
|
|
16864
17296
|
}
|
|
16865
17297
|
async stop() {
|
|
17298
|
+
this.requestEpoch++;
|
|
17299
|
+
this.incomingFundsEpoch++;
|
|
17300
|
+
this.contractEventsEpoch++;
|
|
17301
|
+
this.channel = void 0;
|
|
17302
|
+
this.onNextTick = [];
|
|
16866
17303
|
if (this.incomingFundsSubscription) {
|
|
16867
17304
|
this.incomingFundsSubscription();
|
|
16868
17305
|
this.incomingFundsSubscription = void 0;
|
|
@@ -16885,8 +17322,8 @@ var WalletMessageHandler = class {
|
|
|
16885
17322
|
this.indexerProvider = void 0;
|
|
16886
17323
|
}
|
|
16887
17324
|
async tick(_now) {
|
|
16888
|
-
const
|
|
16889
|
-
|
|
17325
|
+
const pending = this.onNextTick.splice(0);
|
|
17326
|
+
const results = await Promise.allSettled(pending.map((fn) => fn()));
|
|
16890
17327
|
return results.map((result) => {
|
|
16891
17328
|
if (result.status === "fulfilled") {
|
|
16892
17329
|
return result.value;
|
|
@@ -16896,8 +17333,46 @@ var WalletMessageHandler = class {
|
|
|
16896
17333
|
}
|
|
16897
17334
|
}).filter((response) => response !== null);
|
|
16898
17335
|
}
|
|
16899
|
-
|
|
16900
|
-
|
|
17336
|
+
epochOf(scope) {
|
|
17337
|
+
switch (scope) {
|
|
17338
|
+
case "incomingFunds":
|
|
17339
|
+
return this.incomingFundsEpoch;
|
|
17340
|
+
case "contractEvents":
|
|
17341
|
+
return this.contractEventsEpoch;
|
|
17342
|
+
case "request":
|
|
17343
|
+
return this.requestEpoch;
|
|
17344
|
+
default: {
|
|
17345
|
+
const _exhaustive = scope;
|
|
17346
|
+
throw new Error(`Unknown scope: ${_exhaustive}`);
|
|
17347
|
+
}
|
|
17348
|
+
}
|
|
17349
|
+
}
|
|
17350
|
+
newGeneration(scope) {
|
|
17351
|
+
const born = this.epochOf(scope);
|
|
17352
|
+
const stale = () => born !== this.epochOf(scope);
|
|
17353
|
+
return {
|
|
17354
|
+
get stale() {
|
|
17355
|
+
return stale();
|
|
17356
|
+
}
|
|
17357
|
+
};
|
|
17358
|
+
}
|
|
17359
|
+
/**
|
|
17360
|
+
* A handle rather than a `broadcast(response, epoch)` call, because it can
|
|
17361
|
+
* only be written where the closure it guards is created — an epoch passed
|
|
17362
|
+
* at the call site reads identically whether it guards anything or not.
|
|
17363
|
+
*/
|
|
17364
|
+
newEmitter(scope) {
|
|
17365
|
+
const gen = this.newGeneration(scope);
|
|
17366
|
+
return {
|
|
17367
|
+
get stale() {
|
|
17368
|
+
return gen.stale;
|
|
17369
|
+
},
|
|
17370
|
+
emit: (response) => {
|
|
17371
|
+
if (!response || gen.stale) return;
|
|
17372
|
+
if (this.channel) return this.channel.broadcast(response);
|
|
17373
|
+
this.onNextTick.push(() => response);
|
|
17374
|
+
}
|
|
17375
|
+
};
|
|
16901
17376
|
}
|
|
16902
17377
|
requireWallet() {
|
|
16903
17378
|
if (!this.wallet) {
|
|
@@ -16926,6 +17401,7 @@ var WalletMessageHandler = class {
|
|
|
16926
17401
|
}
|
|
16927
17402
|
async handleMessage(message) {
|
|
16928
17403
|
const id = message.id;
|
|
17404
|
+
const emitter = this.newEmitter("request");
|
|
16929
17405
|
if (message.type === "INIT_WALLET") {
|
|
16930
17406
|
await this.handleInitWallet(message);
|
|
16931
17407
|
return this.tagged({
|
|
@@ -17194,6 +17670,18 @@ var WalletMessageHandler = class {
|
|
|
17194
17670
|
payload: { descriptor }
|
|
17195
17671
|
});
|
|
17196
17672
|
}
|
|
17673
|
+
case "GET_NEW_ADDRESSES": {
|
|
17674
|
+
const wallet = this.wallet;
|
|
17675
|
+
if (!wallet) throw new WalletNotInitializedError();
|
|
17676
|
+
const addresses = await wallet.getNewAddresses(
|
|
17677
|
+
message.payload
|
|
17678
|
+
);
|
|
17679
|
+
return this.tagged({
|
|
17680
|
+
id,
|
|
17681
|
+
type: "NEW_ADDRESSES",
|
|
17682
|
+
payload: { addresses }
|
|
17683
|
+
});
|
|
17684
|
+
}
|
|
17197
17685
|
case "GET_USED_SIGNING_DESCRIPTORS": {
|
|
17198
17686
|
const wallet = this.wallet;
|
|
17199
17687
|
const descriptors = isHDWalletCapable(wallet) ? await wallet.getUsedSigningDescriptors(
|
|
@@ -17284,8 +17772,8 @@ var WalletMessageHandler = class {
|
|
|
17284
17772
|
const wallet = this.requireWallet();
|
|
17285
17773
|
const vtxoManager = await wallet.getVtxoManager();
|
|
17286
17774
|
const txid = await vtxoManager.recoverVtxos((e) => {
|
|
17287
|
-
|
|
17288
|
-
|
|
17775
|
+
emitter.emit(
|
|
17776
|
+
this.tagged({
|
|
17289
17777
|
id,
|
|
17290
17778
|
type: "RECOVER_VTXOS_EVENT",
|
|
17291
17779
|
payload: e
|
|
@@ -17329,8 +17817,8 @@ var WalletMessageHandler = class {
|
|
|
17329
17817
|
const wallet = this.requireWallet();
|
|
17330
17818
|
const vtxoManager = await wallet.getVtxoManager();
|
|
17331
17819
|
const txid = await vtxoManager.renewVtxos((e) => {
|
|
17332
|
-
|
|
17333
|
-
|
|
17820
|
+
emitter.emit(
|
|
17821
|
+
this.tagged({
|
|
17334
17822
|
id,
|
|
17335
17823
|
type: "RENEW_VTXOS_EVENT",
|
|
17336
17824
|
payload: e
|
|
@@ -17368,8 +17856,8 @@ var WalletMessageHandler = class {
|
|
|
17368
17856
|
const vtxoManager = await wallet.getVtxoManager();
|
|
17369
17857
|
const report = await vtxoManager.migrateDeprecatedSignerVtxos({
|
|
17370
17858
|
eventCallback: (e) => {
|
|
17371
|
-
|
|
17372
|
-
|
|
17859
|
+
emitter.emit(
|
|
17860
|
+
this.tagged({
|
|
17373
17861
|
id,
|
|
17374
17862
|
type: "MIGRATE_DEPRECATED_SIGNER_VTXOS_EVENT",
|
|
17375
17863
|
payload: e
|
|
@@ -17422,7 +17910,7 @@ var WalletMessageHandler = class {
|
|
|
17422
17910
|
// Wallet methods
|
|
17423
17911
|
async handleInitWallet({ payload }) {
|
|
17424
17912
|
const { arkServerUrl } = payload;
|
|
17425
|
-
this.indexerProvider = new
|
|
17913
|
+
this.indexerProvider = new chunkPJR63FTK_cjs.RestIndexerProvider(arkServerUrl);
|
|
17426
17914
|
await this.onWalletInitialized();
|
|
17427
17915
|
}
|
|
17428
17916
|
/**
|
|
@@ -17472,6 +17960,7 @@ var WalletMessageHandler = class {
|
|
|
17472
17960
|
intentLocked: offchain.intentLocked,
|
|
17473
17961
|
recoverable: offchain.recoverable,
|
|
17474
17962
|
pendingRecovery: offchain.pendingRecovery,
|
|
17963
|
+
unrolled: offchain.unrolled,
|
|
17475
17964
|
total: totalBoarding + offchain.total,
|
|
17476
17965
|
assets: offchain.assets,
|
|
17477
17966
|
availableAssets: offchain.availableAssets
|
|
@@ -17482,11 +17971,15 @@ var WalletMessageHandler = class {
|
|
|
17482
17971
|
return this.readonlyWallet.getBoardingUtxos();
|
|
17483
17972
|
}
|
|
17484
17973
|
async onWalletInitialized() {
|
|
17485
|
-
|
|
17974
|
+
const wallet = this.readonlyWallet;
|
|
17975
|
+
if (!wallet || !this.arkProvider || !this.indexerProvider || !this.walletRepository) {
|
|
17486
17976
|
return;
|
|
17487
17977
|
}
|
|
17978
|
+
const init = this.newGeneration("incomingFunds");
|
|
17488
17979
|
await this.ensureContractEventBroadcasting();
|
|
17980
|
+
if (init.stale) return;
|
|
17489
17981
|
await this.refreshCachedData();
|
|
17982
|
+
if (init.stale) return;
|
|
17490
17983
|
if (this.wallet) {
|
|
17491
17984
|
try {
|
|
17492
17985
|
const vtxos = await this.getVtxosFromRepo();
|
|
@@ -17499,72 +17992,81 @@ var WalletMessageHandler = class {
|
|
|
17499
17992
|
} catch (error) {
|
|
17500
17993
|
console.error("Error recovering pending transactions:", error);
|
|
17501
17994
|
}
|
|
17995
|
+
if (init.stale) return;
|
|
17502
17996
|
}
|
|
17503
17997
|
if (this.incomingFundsSubscription) this.incomingFundsSubscription();
|
|
17504
|
-
|
|
17505
|
-
this.
|
|
17506
|
-
|
|
17507
|
-
|
|
17508
|
-
|
|
17509
|
-
|
|
17510
|
-
|
|
17511
|
-
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
|
|
17517
|
-
|
|
17518
|
-
const arr = byScript.get(v.script) ?? [];
|
|
17519
|
-
arr.push(v);
|
|
17520
|
-
byScript.set(v.script, arr);
|
|
17521
|
-
}
|
|
17522
|
-
let walletScript;
|
|
17523
|
-
try {
|
|
17524
|
-
walletScript = scriptFromArkAddress(address);
|
|
17525
|
-
} catch {
|
|
17526
|
-
walletScript = void 0;
|
|
17527
|
-
}
|
|
17528
|
-
const cm = await this.readonlyWallet.getContractManager();
|
|
17529
|
-
const contracts = await cm.getContracts();
|
|
17530
|
-
const addrByScript = new Map(contracts.map((c) => [c.script, c.address]));
|
|
17531
|
-
for (const [script, vtxos] of byScript) {
|
|
17532
|
-
const filtered = warnAndFilterVtxosForScript(
|
|
17533
|
-
vtxos,
|
|
17534
|
-
script,
|
|
17535
|
-
"WalletMessageHandler.notifyIncomingFunds"
|
|
17998
|
+
this.incomingFundsSubscription = void 0;
|
|
17999
|
+
this.incomingFundsEpoch++;
|
|
18000
|
+
const emitter = this.newEmitter("incomingFunds");
|
|
18001
|
+
const address = await wallet.getAddress();
|
|
18002
|
+
const unsubscribe = await wallet.notifyIncomingFunds(async (funds) => {
|
|
18003
|
+
if (emitter.stale) return;
|
|
18004
|
+
if (funds.type === "vtxo") {
|
|
18005
|
+
const { newVtxos, spentVtxos } = funds;
|
|
18006
|
+
if (newVtxos.length + spentVtxos.length === 0) return;
|
|
18007
|
+
const byScript = /* @__PURE__ */ new Map();
|
|
18008
|
+
for (const v of [...newVtxos, ...spentVtxos]) {
|
|
18009
|
+
if (!v.script) {
|
|
18010
|
+
console.warn(
|
|
18011
|
+
`WalletMessageHandler.notifyIncomingFunds: dropping VTXO without script ${v.txid}:${v.vout}`
|
|
17536
18012
|
);
|
|
17537
|
-
|
|
17538
|
-
const targetAddress = script === walletScript ? address : addrByScript.get(script);
|
|
17539
|
-
if (!targetAddress) continue;
|
|
17540
|
-
if (this.walletRepository) {
|
|
17541
|
-
await saveVtxosForContract(
|
|
17542
|
-
this.walletRepository,
|
|
17543
|
-
{ script, address: targetAddress },
|
|
17544
|
-
filtered
|
|
17545
|
-
);
|
|
17546
|
-
}
|
|
18013
|
+
continue;
|
|
17547
18014
|
}
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
|
|
17551
|
-
broadcast: true,
|
|
17552
|
-
payload: { newVtxos, spentVtxos }
|
|
17553
|
-
})
|
|
17554
|
-
);
|
|
18015
|
+
const arr = byScript.get(v.script) ?? [];
|
|
18016
|
+
arr.push(v);
|
|
18017
|
+
byScript.set(v.script, arr);
|
|
17555
18018
|
}
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
|
|
18019
|
+
let walletScript;
|
|
18020
|
+
try {
|
|
18021
|
+
walletScript = scriptFromArkAddress(address);
|
|
18022
|
+
} catch {
|
|
18023
|
+
walletScript = void 0;
|
|
18024
|
+
}
|
|
18025
|
+
const cm = await wallet.getContractManager();
|
|
18026
|
+
if (emitter.stale) return;
|
|
18027
|
+
const contracts = await cm.getContracts();
|
|
18028
|
+
if (emitter.stale) return;
|
|
18029
|
+
const addrByScript = new Map(contracts.map((c) => [c.script, c.address]));
|
|
18030
|
+
for (const [script, vtxos] of byScript) {
|
|
18031
|
+
const filtered = warnAndFilterVtxosForScript(
|
|
18032
|
+
vtxos,
|
|
18033
|
+
script,
|
|
18034
|
+
"WalletMessageHandler.notifyIncomingFunds"
|
|
17564
18035
|
);
|
|
18036
|
+
if (filtered.length === 0) continue;
|
|
18037
|
+
const targetAddress = script === walletScript ? address : addrByScript.get(script);
|
|
18038
|
+
if (!targetAddress) continue;
|
|
18039
|
+
if (this.walletRepository) {
|
|
18040
|
+
if (emitter.stale) return;
|
|
18041
|
+
await saveVtxosForContract(
|
|
18042
|
+
this.walletRepository,
|
|
18043
|
+
{ script, address: targetAddress },
|
|
18044
|
+
filtered
|
|
18045
|
+
);
|
|
18046
|
+
}
|
|
17565
18047
|
}
|
|
18048
|
+
emitter.emit(
|
|
18049
|
+
this.tagged({
|
|
18050
|
+
type: "VTXO_UPDATE",
|
|
18051
|
+
broadcast: true,
|
|
18052
|
+
payload: { newVtxos, spentVtxos }
|
|
18053
|
+
})
|
|
18054
|
+
);
|
|
17566
18055
|
}
|
|
17567
|
-
|
|
18056
|
+
if (funds.type === "utxo") {
|
|
18057
|
+
if (emitter.stale) return;
|
|
18058
|
+
const utxos = await wallet.getBoardingUtxos();
|
|
18059
|
+
emitter.emit(
|
|
18060
|
+
this.tagged({
|
|
18061
|
+
type: "UTXO_UPDATE",
|
|
18062
|
+
broadcast: true,
|
|
18063
|
+
payload: { coins: utxos }
|
|
18064
|
+
})
|
|
18065
|
+
);
|
|
18066
|
+
}
|
|
18067
|
+
});
|
|
18068
|
+
if (emitter.stale) return unsubscribe();
|
|
18069
|
+
this.incomingFundsSubscription = unsubscribe;
|
|
17568
18070
|
if (this.wallet) {
|
|
17569
18071
|
try {
|
|
17570
18072
|
await this.wallet.getVtxoManager();
|
|
@@ -17609,10 +18111,11 @@ var WalletMessageHandler = class {
|
|
|
17609
18111
|
await this.refreshCachedData();
|
|
17610
18112
|
}
|
|
17611
18113
|
async handleSettle(message) {
|
|
18114
|
+
const emitter = this.newEmitter("request");
|
|
17612
18115
|
const wallet = this.requireWallet();
|
|
17613
18116
|
const txid = await wallet.settle(message.payload.params, (e) => {
|
|
17614
|
-
|
|
17615
|
-
|
|
18117
|
+
emitter.emit(
|
|
18118
|
+
this.tagged({
|
|
17616
18119
|
id: message.id,
|
|
17617
18120
|
type: "SETTLE_EVENT",
|
|
17618
18121
|
payload: e
|
|
@@ -17689,30 +18192,39 @@ var WalletMessageHandler = class {
|
|
|
17689
18192
|
throw new WalletNotInitializedError();
|
|
17690
18193
|
}
|
|
17691
18194
|
const allVtxos = await this.getVtxosFromRepo();
|
|
17692
|
-
const vtxos = allVtxos.filter((v) => !chunkZIRFXBKL_cjs.hasTerminalSpend(v));
|
|
17693
18195
|
const dustAmount = this.readonlyWallet.dustAmount;
|
|
18196
|
+
const withUnrolled = message.payload.filter?.withUnrolled ?? false;
|
|
17694
18197
|
const includeRecoverable = message.payload.filter?.withRecoverable ?? false;
|
|
17695
|
-
|
|
18198
|
+
return allVtxos.filter((v) => {
|
|
18199
|
+
if (v.isUnrolled) {
|
|
18200
|
+
return withUnrolled;
|
|
18201
|
+
}
|
|
18202
|
+
if (chunkEJOFL5WH_cjs.hasTerminalSpend(v)) {
|
|
18203
|
+
return false;
|
|
18204
|
+
}
|
|
18205
|
+
if (includeRecoverable) {
|
|
18206
|
+
return true;
|
|
18207
|
+
}
|
|
17696
18208
|
if (dustAmount != null && isSubdust(v, dustAmount)) {
|
|
17697
18209
|
return false;
|
|
17698
18210
|
}
|
|
17699
|
-
if (
|
|
18211
|
+
if (chunkEJOFL5WH_cjs.isRecoverable(v)) {
|
|
17700
18212
|
return false;
|
|
17701
18213
|
}
|
|
17702
|
-
if (
|
|
18214
|
+
if (chunkEJOFL5WH_cjs.isExpired(v)) {
|
|
17703
18215
|
return false;
|
|
17704
18216
|
}
|
|
17705
18217
|
return true;
|
|
17706
18218
|
});
|
|
17707
|
-
if (!message.payload.filter?.withUnrolled) {
|
|
17708
|
-
return filteredVtxos;
|
|
17709
|
-
}
|
|
17710
|
-
return filteredVtxos.concat(allVtxos.filter((v) => chunkZIRFXBKL_cjs.hasTerminalSpend(v) && v.isUnrolled));
|
|
17711
18219
|
}
|
|
17712
18220
|
/** Tear down handler subscriptions, then delegate the full wipe to the wallet. */
|
|
17713
18221
|
async clear() {
|
|
17714
18222
|
const wallet = this.wallet ?? this.readonlyWallet;
|
|
17715
18223
|
if (!wallet) return;
|
|
18224
|
+
this.requestEpoch++;
|
|
18225
|
+
this.incomingFundsEpoch++;
|
|
18226
|
+
this.contractEventsEpoch++;
|
|
18227
|
+
this.onNextTick = [];
|
|
17716
18228
|
if (this.incomingFundsSubscription) {
|
|
17717
18229
|
this.incomingFundsSubscription();
|
|
17718
18230
|
this.incomingFundsSubscription = void 0;
|
|
@@ -17797,17 +18309,21 @@ var WalletMessageHandler = class {
|
|
|
17797
18309
|
if (!this.readonlyWallet) return null;
|
|
17798
18310
|
const { boardingTxs, commitmentsToIgnore } = await this.readonlyWallet.getBoardingTxs();
|
|
17799
18311
|
const indexerProvider = this.indexerProvider;
|
|
17800
|
-
const resolveTxCreatedAt = indexerProvider ? (txids) =>
|
|
18312
|
+
const resolveTxCreatedAt = indexerProvider ? (txids) => chunkEJOFL5WH_cjs.fetchVtxoCreatedAtByTxid(indexerProvider, txids) : void 0;
|
|
17801
18313
|
return buildTransactionHistory(vtxos, boardingTxs, commitmentsToIgnore, resolveTxCreatedAt);
|
|
17802
18314
|
}
|
|
17803
18315
|
async ensureContractEventBroadcasting() {
|
|
17804
|
-
|
|
18316
|
+
const wallet = this.readonlyWallet;
|
|
18317
|
+
if (!wallet) return;
|
|
17805
18318
|
if (this.contractEventsSubscription) return;
|
|
18319
|
+
const gen = this.newGeneration("contractEvents");
|
|
17806
18320
|
try {
|
|
17807
|
-
const manager = await
|
|
18321
|
+
const manager = await wallet.getContractManager();
|
|
18322
|
+
if (gen.stale || this.contractEventsSubscription) return;
|
|
18323
|
+
const emitter = this.newEmitter("contractEvents");
|
|
17808
18324
|
this.contractEventsSubscription = manager.onContractEvent((event) => {
|
|
17809
|
-
|
|
17810
|
-
|
|
18325
|
+
emitter.emit(
|
|
18326
|
+
this.tagged({
|
|
17811
18327
|
type: "CONTRACT_EVENT",
|
|
17812
18328
|
broadcast: true,
|
|
17813
18329
|
payload: { event }
|
|
@@ -17838,6 +18354,9 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
|
|
|
17838
18354
|
// Allocation is a local repository write plus a fire-and-forget band
|
|
17839
18355
|
// slide — no indexer round trip on the request path.
|
|
17840
18356
|
GET_NEXT_SIGNING_DESCRIPTOR: 1e4,
|
|
18357
|
+
// Same shape as the bare allocation above, plus one contract write per
|
|
18358
|
+
// requested type — still local, still no indexer round trip.
|
|
18359
|
+
GET_NEW_ADDRESSES: 1e4,
|
|
17841
18360
|
GET_USED_SIGNING_DESCRIPTORS: 2e4,
|
|
17842
18361
|
ADVANCE_SIGNING_DESCRIPTOR_WATERMARK: 1e4,
|
|
17843
18362
|
// Medium reads — may involve indexer queries
|
|
@@ -18486,7 +19005,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
18486
19005
|
};
|
|
18487
19006
|
try {
|
|
18488
19007
|
const response = await this.sendMessage(message);
|
|
18489
|
-
return response.payload.vtxos.map(
|
|
19008
|
+
return response.payload.vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
18490
19009
|
} catch (error) {
|
|
18491
19010
|
throw new Error(`Failed to get vtxos: ${error}`);
|
|
18492
19011
|
}
|
|
@@ -18511,7 +19030,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
18511
19030
|
};
|
|
18512
19031
|
try {
|
|
18513
19032
|
const response = await this.sendMessage(message);
|
|
18514
|
-
return response.payload.vtxos.map(
|
|
19033
|
+
return response.payload.vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
18515
19034
|
} catch (error) {
|
|
18516
19035
|
throw new Error(`Failed to get spendable vtxos: ${error}`);
|
|
18517
19036
|
}
|
|
@@ -18642,7 +19161,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
18642
19161
|
};
|
|
18643
19162
|
try {
|
|
18644
19163
|
const response = await sendContractMessage(message);
|
|
18645
|
-
return response.payload.vtxos.map(
|
|
19164
|
+
return response.payload.vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
18646
19165
|
} catch (e) {
|
|
18647
19166
|
throw new Error("Failed to annotate vtxos");
|
|
18648
19167
|
}
|
|
@@ -18983,6 +19502,35 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
|
|
|
18983
19502
|
throw new Error(`Failed to allocate next signing descriptor: ${error}`);
|
|
18984
19503
|
}
|
|
18985
19504
|
}
|
|
19505
|
+
/**
|
|
19506
|
+
* @see Wallet.getNewAddresses
|
|
19507
|
+
*
|
|
19508
|
+
* Proxied as a single request rather than rebuilt page-side out of
|
|
19509
|
+
* {@link getNextSigningDescriptor}: the worker owns the HD watermark *and*
|
|
19510
|
+
* the contract repository, so splitting the operation would let a page burn
|
|
19511
|
+
* an index and then fail to register the script, leaving an address nothing
|
|
19512
|
+
* watches.
|
|
19513
|
+
*
|
|
19514
|
+
* Note the error shape — `WalletCannotAllocateAddressError` is thrown
|
|
19515
|
+
* worker-side and cannot cross the message boundary as a class, so a
|
|
19516
|
+
* `forceNew` refusal surfaces here as a plain `Error` carrying its message
|
|
19517
|
+
* (and the worker-side error as `cause`). Callers that must branch on the
|
|
19518
|
+
* refusal match the message rather than `instanceof`.
|
|
19519
|
+
*/
|
|
19520
|
+
async getNewAddresses(opts) {
|
|
19521
|
+
const message = {
|
|
19522
|
+
id: getRandomId(),
|
|
19523
|
+
tag: this.messageTag,
|
|
19524
|
+
type: "GET_NEW_ADDRESSES",
|
|
19525
|
+
...opts ? { payload: opts } : {}
|
|
19526
|
+
};
|
|
19527
|
+
try {
|
|
19528
|
+
const response = await this.sendMessage(message);
|
|
19529
|
+
return response.payload.addresses;
|
|
19530
|
+
} catch (error) {
|
|
19531
|
+
throw new Error(`Failed to allocate new addresses: ${error}`, { cause: error });
|
|
19532
|
+
}
|
|
19533
|
+
}
|
|
18986
19534
|
/** @see HDWalletCapable.getUsedSigningDescriptors */
|
|
18987
19535
|
async getUsedSigningDescriptors(opts) {
|
|
18988
19536
|
const message = {
|
|
@@ -19214,7 +19762,7 @@ var ServiceWorkerWallet = class _ServiceWorkerWallet extends ServiceWorkerReadon
|
|
|
19214
19762
|
};
|
|
19215
19763
|
try {
|
|
19216
19764
|
const response = await wallet.sendMessage(message);
|
|
19217
|
-
return response.payload.vtxos.map(
|
|
19765
|
+
return response.payload.vtxos.map(chunkEJOFL5WH_cjs.normalizeVtxo);
|
|
19218
19766
|
} catch (e) {
|
|
19219
19767
|
throw new Error(`Failed to get expiring vtxos: ${e}`);
|
|
19220
19768
|
}
|
|
@@ -19326,12 +19874,12 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
19326
19874
|
* @returns Configured onchain wallet
|
|
19327
19875
|
* @throws Error if the configured identity cannot produce a valid x-only public key
|
|
19328
19876
|
*/
|
|
19329
|
-
static async create(identity, networkName =
|
|
19877
|
+
static async create(identity, networkName = chunkEJOFL5WH_cjs.DEFAULT_NETWORK_NAME, provider) {
|
|
19330
19878
|
const pubkey = await identity.xOnlyPublicKey();
|
|
19331
19879
|
if (!pubkey) {
|
|
19332
19880
|
throw new Error("Invalid configured public key");
|
|
19333
19881
|
}
|
|
19334
|
-
const network =
|
|
19882
|
+
const network = chunkEJOFL5WH_cjs.getNetwork(networkName);
|
|
19335
19883
|
const onchainProvider = provider || new EsploraProvider(ESPLORA_URL[networkName]);
|
|
19336
19884
|
const onchainP2TR = btcSigner.p2tr(pubkey, void 0, network);
|
|
19337
19885
|
return new _OnchainWallet(identity, network, onchainP2TR, onchainProvider);
|
|
@@ -19437,7 +19985,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
19437
19985
|
if (!inputs) {
|
|
19438
19986
|
throw new Error("Fee estimation failed");
|
|
19439
19987
|
}
|
|
19440
|
-
let tx = new
|
|
19988
|
+
let tx = new chunkEJOFL5WH_cjs.Transaction();
|
|
19441
19989
|
for (const input of inputs) {
|
|
19442
19990
|
tx.addInput({
|
|
19443
19991
|
txid: input.txid,
|
|
@@ -19495,7 +20043,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
19495
20043
|
* @throws If the parent has no anchor, or funding cannot be selected/signed
|
|
19496
20044
|
*/
|
|
19497
20045
|
async bumpAnchor(parentHex, feeRate) {
|
|
19498
|
-
const parent =
|
|
20046
|
+
const parent = chunkEJOFL5WH_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
|
|
19499
20047
|
const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
|
|
19500
20048
|
const child = await this.buildBumpPackage(parent, feeRate, coins);
|
|
19501
20049
|
return [parent.hex, child.hex];
|
|
@@ -19949,6 +20497,10 @@ var ElectrumOnchainProvider = class {
|
|
|
19949
20497
|
}
|
|
19950
20498
|
throw new Error("Only 1 or 1P1C package can be broadcast");
|
|
19951
20499
|
}
|
|
20500
|
+
async getRawTransaction(txid) {
|
|
20501
|
+
const [tx] = await this.chain.fetchTransactions([txid]);
|
|
20502
|
+
return base.hex.decode(tx.hex);
|
|
20503
|
+
}
|
|
19952
20504
|
async getTxOutspends(txid) {
|
|
19953
20505
|
const [txResult] = await this.chain.fetchTransactions([txid]);
|
|
19954
20506
|
const tx = btcSigner.Transaction.fromRaw(base.hex.decode(txResult.hex), {
|
|
@@ -20254,13 +20806,190 @@ function childTxidFromHex(txHex) {
|
|
|
20254
20806
|
});
|
|
20255
20807
|
return tx.id;
|
|
20256
20808
|
}
|
|
20809
|
+
|
|
20810
|
+
// src/providers/cachingArk.ts
|
|
20811
|
+
var DEFAULT_TTL_MS = 6e4;
|
|
20812
|
+
var CachingArkProvider = class {
|
|
20813
|
+
constructor(inner, ttlMs = DEFAULT_TTL_MS) {
|
|
20814
|
+
this.inner = inner;
|
|
20815
|
+
this.ttlMs = ttlMs;
|
|
20816
|
+
this.unsubscribe = inner.onServerInfoChanged?.((info) => {
|
|
20817
|
+
this.cached = info;
|
|
20818
|
+
this.expiresAt = Date.now() + this.ttlMs;
|
|
20819
|
+
this.generation++;
|
|
20820
|
+
}) ?? (() => {
|
|
20821
|
+
});
|
|
20822
|
+
}
|
|
20823
|
+
inner;
|
|
20824
|
+
ttlMs;
|
|
20825
|
+
cached;
|
|
20826
|
+
expiresAt = 0;
|
|
20827
|
+
inflight;
|
|
20828
|
+
/** Bumped on every event-driven cache write; see {@link getInfo}. */
|
|
20829
|
+
generation = 0;
|
|
20830
|
+
unsubscribe;
|
|
20831
|
+
/** Releases the inner provider's server-info subscription. */
|
|
20832
|
+
dispose() {
|
|
20833
|
+
this.unsubscribe();
|
|
20834
|
+
}
|
|
20835
|
+
get serverUrl() {
|
|
20836
|
+
const url = this.inner.serverUrl;
|
|
20837
|
+
return typeof url === "string" ? url : void 0;
|
|
20838
|
+
}
|
|
20839
|
+
async getInfo() {
|
|
20840
|
+
if (this.cached && Date.now() < this.expiresAt) return this.cached;
|
|
20841
|
+
if (!this.inflight) {
|
|
20842
|
+
const generation = this.generation;
|
|
20843
|
+
this.inflight = this.inner.getInfo().then((info) => {
|
|
20844
|
+
if (this.generation !== generation) return this.cached ?? info;
|
|
20845
|
+
this.cached = info;
|
|
20846
|
+
this.expiresAt = Date.now() + this.ttlMs;
|
|
20847
|
+
return info;
|
|
20848
|
+
}).finally(() => {
|
|
20849
|
+
this.inflight = void 0;
|
|
20850
|
+
});
|
|
20851
|
+
}
|
|
20852
|
+
return this.inflight;
|
|
20853
|
+
}
|
|
20854
|
+
submitTx(signedArkTx, checkpointTxs) {
|
|
20855
|
+
return this.inner.submitTx(signedArkTx, checkpointTxs);
|
|
20856
|
+
}
|
|
20857
|
+
finalizeTx(arkTxid, finalCheckpointTxs) {
|
|
20858
|
+
return this.inner.finalizeTx(arkTxid, finalCheckpointTxs);
|
|
20859
|
+
}
|
|
20860
|
+
registerIntent(intent) {
|
|
20861
|
+
return this.inner.registerIntent(intent);
|
|
20862
|
+
}
|
|
20863
|
+
deleteIntent(intent) {
|
|
20864
|
+
return this.inner.deleteIntent(intent);
|
|
20865
|
+
}
|
|
20866
|
+
confirmRegistration(intentId) {
|
|
20867
|
+
return this.inner.confirmRegistration(intentId);
|
|
20868
|
+
}
|
|
20869
|
+
submitTreeNonces(batchId, pubkey, nonces) {
|
|
20870
|
+
return this.inner.submitTreeNonces(batchId, pubkey, nonces);
|
|
20871
|
+
}
|
|
20872
|
+
submitTreeSignatures(batchId, pubkey, signatures) {
|
|
20873
|
+
return this.inner.submitTreeSignatures(batchId, pubkey, signatures);
|
|
20874
|
+
}
|
|
20875
|
+
submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx) {
|
|
20876
|
+
return this.inner.submitSignedForfeitTxs(signedForfeitTxs, signedCommitmentTx);
|
|
20877
|
+
}
|
|
20878
|
+
getEventStream(signal, topics) {
|
|
20879
|
+
return this.inner.getEventStream(signal, topics);
|
|
20880
|
+
}
|
|
20881
|
+
getTransactionsStream(signal) {
|
|
20882
|
+
return this.inner.getTransactionsStream(signal);
|
|
20883
|
+
}
|
|
20884
|
+
getPendingTxs(intent) {
|
|
20885
|
+
return this.inner.getPendingTxs(intent);
|
|
20886
|
+
}
|
|
20887
|
+
onServerInfoChanged(listener) {
|
|
20888
|
+
return this.inner.onServerInfoChanged?.(listener) ?? (() => {
|
|
20889
|
+
});
|
|
20890
|
+
}
|
|
20891
|
+
};
|
|
20892
|
+
var PrevTxUnavailableError = class extends Error {
|
|
20893
|
+
constructor(message, txids = []) {
|
|
20894
|
+
super(message);
|
|
20895
|
+
this.txids = txids;
|
|
20896
|
+
this.name = "PrevTxUnavailableError";
|
|
20897
|
+
}
|
|
20898
|
+
txids;
|
|
20899
|
+
};
|
|
20900
|
+
async function resolvePrevTxs(txids, source, onchain) {
|
|
20901
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
20902
|
+
const wanted = [...new Set(txids)];
|
|
20903
|
+
if (wanted.length === 0) return resolved;
|
|
20904
|
+
try {
|
|
20905
|
+
const { txs } = await source.getVirtualTxs(wanted);
|
|
20906
|
+
for (const psbt of txs) {
|
|
20907
|
+
const tx = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbt));
|
|
20908
|
+
resolved.set(tx.id, tx.toBytes());
|
|
20909
|
+
}
|
|
20910
|
+
} catch (err) {
|
|
20911
|
+
if (!onchain) throw err;
|
|
20912
|
+
}
|
|
20913
|
+
let missing = wanted.filter((txid) => !resolved.has(txid));
|
|
20914
|
+
if (missing.length > 0 && onchain) {
|
|
20915
|
+
const raw = await Promise.all(
|
|
20916
|
+
missing.map(async (txid) => {
|
|
20917
|
+
try {
|
|
20918
|
+
return await onchain.getRawTransaction(txid);
|
|
20919
|
+
} catch {
|
|
20920
|
+
return void 0;
|
|
20921
|
+
}
|
|
20922
|
+
})
|
|
20923
|
+
);
|
|
20924
|
+
for (const [i, bytes] of raw.entries()) {
|
|
20925
|
+
if (bytes) resolved.set(missing[i], bytes);
|
|
20926
|
+
}
|
|
20927
|
+
missing = missing.filter((txid) => !resolved.has(txid));
|
|
20928
|
+
}
|
|
20929
|
+
if (missing.length > 0) {
|
|
20930
|
+
throw new PrevTxUnavailableError(
|
|
20931
|
+
`cannot resolve the previous transaction of ${missing.join(", ")}` + (onchain ? "" : " (no onchain source configured)"),
|
|
20932
|
+
missing
|
|
20933
|
+
);
|
|
20934
|
+
}
|
|
20935
|
+
return resolved;
|
|
20936
|
+
}
|
|
20937
|
+
async function attachPrevArkTxs(tx, txids, source, onchain) {
|
|
20938
|
+
const pending = [];
|
|
20939
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
20940
|
+
if (chunkEJOFL5WH_cjs.getArkPsbtFields(tx, i, chunkEJOFL5WH_cjs.PrevArkTxField).length === 0) pending.push(i);
|
|
20941
|
+
}
|
|
20942
|
+
if (pending.length === 0) return;
|
|
20943
|
+
const resolved = await resolvePrevTxs(
|
|
20944
|
+
pending.map((i) => txidAt(txids, i)),
|
|
20945
|
+
source,
|
|
20946
|
+
onchain
|
|
20947
|
+
);
|
|
20948
|
+
for (const i of pending) {
|
|
20949
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(tx, i, chunkEJOFL5WH_cjs.PrevArkTxField, resolved.get(txidAt(txids, i)));
|
|
20950
|
+
}
|
|
20951
|
+
}
|
|
20952
|
+
async function attachPrevoutTxs(tx, source) {
|
|
20953
|
+
const pending = [];
|
|
20954
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
20955
|
+
if (chunkEJOFL5WH_cjs.getArkPsbtFields(tx, i, chunkEJOFL5WH_cjs.PrevoutTxField).length > 0) continue;
|
|
20956
|
+
const input = tx.getInput(i);
|
|
20957
|
+
if (!input?.txid) throw new PrevTxUnavailableError(`input ${i} has no outpoint`);
|
|
20958
|
+
pending.push({ index: i, txid: base.hex.encode(input.txid) });
|
|
20959
|
+
}
|
|
20960
|
+
if (pending.length === 0) return;
|
|
20961
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
20962
|
+
for (const txid of new Set(pending.map((p) => p.txid))) {
|
|
20963
|
+
resolved.set(txid, await source.getRawTransaction(txid));
|
|
20964
|
+
}
|
|
20965
|
+
for (const { index, txid } of pending) {
|
|
20966
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(tx, index, chunkEJOFL5WH_cjs.PrevoutTxField, resolved.get(txid));
|
|
20967
|
+
}
|
|
20968
|
+
}
|
|
20969
|
+
async function withPrevTxs(coins, source, onchain) {
|
|
20970
|
+
const pending = coins.filter((c) => !c.prevTx);
|
|
20971
|
+
if (pending.length === 0) return coins;
|
|
20972
|
+
const resolved = await resolvePrevTxs(
|
|
20973
|
+
pending.map((c) => c.txid),
|
|
20974
|
+
source,
|
|
20975
|
+
onchain
|
|
20976
|
+
);
|
|
20977
|
+
return coins.map((c) => c.prevTx ? c : { ...c, prevTx: resolved.get(c.txid) });
|
|
20978
|
+
}
|
|
20979
|
+
function txidAt(txids, index) {
|
|
20980
|
+
const txid = txids[index];
|
|
20981
|
+
if (txid === void 0) {
|
|
20982
|
+
throw new PrevTxUnavailableError(`no source txid supplied for input ${index}`);
|
|
20983
|
+
}
|
|
20984
|
+
return txid;
|
|
20985
|
+
}
|
|
20257
20986
|
var TAG_BIP322 = "BIP0322-signed-message";
|
|
20258
20987
|
exports.BIP322 = void 0;
|
|
20259
20988
|
((BIP3222) => {
|
|
20260
20989
|
async function sign2(message, identity, network) {
|
|
20261
20990
|
const xOnlyPubKey = await identity.xOnlyPublicKey();
|
|
20262
20991
|
const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
|
|
20263
|
-
const toSpend =
|
|
20992
|
+
const toSpend = chunkEJOFL5WH_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
|
|
20264
20993
|
const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
|
|
20265
20994
|
const signed = await identity.sign(toSign, [0]);
|
|
20266
20995
|
signed.finalizeIdx(0);
|
|
@@ -20318,7 +21047,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
|
|
|
20318
21047
|
if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
|
|
20319
21048
|
return false;
|
|
20320
21049
|
}
|
|
20321
|
-
const toSpend =
|
|
21050
|
+
const toSpend = chunkEJOFL5WH_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
20322
21051
|
const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
|
|
20323
21052
|
const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
|
|
20324
21053
|
const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
|
|
@@ -20339,7 +21068,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
|
|
|
20339
21068
|
}
|
|
20340
21069
|
const sighashType = sigWithHash[sigWithHash.length - 1];
|
|
20341
21070
|
const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
|
|
20342
|
-
const toSpend =
|
|
21071
|
+
const toSpend = chunkEJOFL5WH_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
20343
21072
|
const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
|
|
20344
21073
|
const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
|
|
20345
21074
|
const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
|
|
@@ -20392,7 +21121,7 @@ function encodeCompactSize(n) {
|
|
|
20392
21121
|
return buf;
|
|
20393
21122
|
}
|
|
20394
21123
|
function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
20395
|
-
const tx = new
|
|
21124
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({ version: 0 });
|
|
20396
21125
|
tx.addInput({
|
|
20397
21126
|
txid: toSpend.id,
|
|
20398
21127
|
index: 0,
|
|
@@ -20406,12 +21135,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
|
20406
21135
|
});
|
|
20407
21136
|
tx.addOutput({
|
|
20408
21137
|
amount: 0n,
|
|
20409
|
-
script:
|
|
21138
|
+
script: chunkEJOFL5WH_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
20410
21139
|
});
|
|
20411
21140
|
return tx;
|
|
20412
21141
|
}
|
|
20413
21142
|
function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
20414
|
-
const tx = new
|
|
21143
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({ version: 0 });
|
|
20415
21144
|
tx.addInput({
|
|
20416
21145
|
txid: toSpend.id,
|
|
20417
21146
|
index: 0,
|
|
@@ -20423,7 +21152,7 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
|
20423
21152
|
});
|
|
20424
21153
|
tx.addOutput({
|
|
20425
21154
|
amount: 0n,
|
|
20426
|
-
script:
|
|
21155
|
+
script: chunkEJOFL5WH_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
20427
21156
|
});
|
|
20428
21157
|
return tx;
|
|
20429
21158
|
}
|
|
@@ -20554,7 +21283,7 @@ var RestEmulatorProvider = class {
|
|
|
20554
21283
|
}
|
|
20555
21284
|
};
|
|
20556
21285
|
function finalizeVirtualTx(type, psbtBase64) {
|
|
20557
|
-
const tx =
|
|
21286
|
+
const tx = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
|
|
20558
21287
|
if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
|
|
20559
21288
|
const input = tx.getInput(0);
|
|
20560
21289
|
if (!input) {
|
|
@@ -20581,14 +21310,14 @@ var ExitPathError = class extends Error {
|
|
|
20581
21310
|
reason;
|
|
20582
21311
|
};
|
|
20583
21312
|
function delayWeight(sequence) {
|
|
20584
|
-
const t =
|
|
21313
|
+
const t = chunkEJOFL5WH_cjs.sequenceToTimelock(sequence);
|
|
20585
21314
|
return t.type === "blocks" ? Number(t.value) : Number(t.value) / 600;
|
|
20586
21315
|
}
|
|
20587
21316
|
async function resolveUnilateralPath(params) {
|
|
20588
21317
|
const { vtxo, scriptHex, contractRepository } = params;
|
|
20589
21318
|
const contract = contractRepository ? (await contractRepository.getContracts({ script: scriptHex }))[0] : void 0;
|
|
20590
21319
|
if (contract) {
|
|
20591
|
-
const handler =
|
|
21320
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
20592
21321
|
if (!handler) {
|
|
20593
21322
|
throw new ExitPathError(
|
|
20594
21323
|
"no-handler",
|
|
@@ -20611,12 +21340,12 @@ async function resolveUnilateralPath(params) {
|
|
|
20611
21340
|
paths.sort((a, b) => delayWeight(a.sequence) - delayWeight(b.sequence));
|
|
20612
21341
|
return { selection: paths[0], label: `${contract.type}:unilateral` };
|
|
20613
21342
|
}
|
|
20614
|
-
const decoded =
|
|
21343
|
+
const decoded = chunkEJOFL5WH_cjs.VtxoScript.decode(vtxo.tapTree);
|
|
20615
21344
|
let best;
|
|
20616
21345
|
for (const exit of decoded.exitPaths()) {
|
|
20617
21346
|
const leaf = decoded.findLeaf(base.hex.encode(exit.script));
|
|
20618
21347
|
if (!leaf) continue;
|
|
20619
|
-
const sequence =
|
|
21348
|
+
const sequence = chunkEJOFL5WH_cjs.timelockToSequence(exit.params.timelock);
|
|
20620
21349
|
const weight = delayWeight(sequence);
|
|
20621
21350
|
if (!best || weight < best.weight) {
|
|
20622
21351
|
best = { selection: { leaf, sequence }, weight };
|
|
@@ -20631,6 +21360,22 @@ async function resolveUnilateralPath(params) {
|
|
|
20631
21360
|
return { selection: best.selection, label: "default:exit" };
|
|
20632
21361
|
}
|
|
20633
21362
|
|
|
21363
|
+
// src/wallet/exitObserver.ts
|
|
21364
|
+
function exitObserverFor(manager) {
|
|
21365
|
+
return (outpoint) => manager.refreshOutpoints([outpoint]);
|
|
21366
|
+
}
|
|
21367
|
+
async function notifyExitObserved(onExitObserved, outpoint) {
|
|
21368
|
+
if (!onExitObserved) return;
|
|
21369
|
+
try {
|
|
21370
|
+
await onExitObserved(outpoint);
|
|
21371
|
+
} catch (e) {
|
|
21372
|
+
console.error(
|
|
21373
|
+
`exit observer failed for ${outpoint.txid}:${outpoint.vout} \u2014 the exit is unaffected`,
|
|
21374
|
+
e
|
|
21375
|
+
);
|
|
21376
|
+
}
|
|
21377
|
+
}
|
|
21378
|
+
|
|
20634
21379
|
// src/wallet/unroll.ts
|
|
20635
21380
|
function chainTxTypeToChainedExit2(t) {
|
|
20636
21381
|
switch (t) {
|
|
@@ -20655,27 +21400,30 @@ exports.Unroll = void 0;
|
|
|
20655
21400
|
})(Unroll2.StepType || (Unroll2.StepType = {}));
|
|
20656
21401
|
class Session2 {
|
|
20657
21402
|
/** Create an unroll session from a virtual output outpoint and its dependency chain. */
|
|
20658
|
-
constructor(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
|
|
21403
|
+
constructor(toUnroll, bumper, explorer, indexer, virtualTxRepository, onExitObserved) {
|
|
20659
21404
|
this.toUnroll = toUnroll;
|
|
20660
21405
|
this.bumper = bumper;
|
|
20661
21406
|
this.explorer = explorer;
|
|
20662
21407
|
this.indexer = indexer;
|
|
20663
21408
|
this.virtualTxRepository = virtualTxRepository;
|
|
21409
|
+
this.onExitObserved = onExitObserved;
|
|
20664
21410
|
}
|
|
20665
21411
|
toUnroll;
|
|
20666
21412
|
bumper;
|
|
20667
21413
|
explorer;
|
|
20668
21414
|
indexer;
|
|
20669
21415
|
virtualTxRepository;
|
|
21416
|
+
onExitObserved;
|
|
20670
21417
|
/** Create an unroll session by loading the virtual output chain from the indexer. */
|
|
20671
|
-
static async create(toUnroll, bumper, explorer, indexer, virtualTxRepository) {
|
|
21418
|
+
static async create(toUnroll, bumper, explorer, indexer, virtualTxRepository, onExitObserved) {
|
|
20672
21419
|
const { chain } = await indexer.getVtxoChain(toUnroll);
|
|
20673
21420
|
return new Session2(
|
|
20674
21421
|
{ ...toUnroll, chain },
|
|
20675
21422
|
bumper,
|
|
20676
21423
|
explorer,
|
|
20677
21424
|
indexer,
|
|
20678
|
-
virtualTxRepository
|
|
21425
|
+
virtualTxRepository,
|
|
21426
|
+
onExitObserved
|
|
20679
21427
|
);
|
|
20680
21428
|
}
|
|
20681
21429
|
/**
|
|
@@ -20711,6 +21459,14 @@ exports.Unroll = void 0;
|
|
|
20711
21459
|
}
|
|
20712
21460
|
/**
|
|
20713
21461
|
* Get the next step to be executed
|
|
21462
|
+
*
|
|
21463
|
+
* @remarks
|
|
21464
|
+
* `do()` is the step, not a formality: every effect lives there, and at
|
|
21465
|
+
* `StepType.DONE` that includes firing {@link onExitObserved}. A caller
|
|
21466
|
+
* driving `next()` by hand must always await it — the async iterator
|
|
21467
|
+
* below does. Reading `type` and skipping `do()` leaves the exit
|
|
21468
|
+
* unobserved, and on the other step kinds unbroadcast.
|
|
21469
|
+
*
|
|
20714
21470
|
* @returns The next step to be executed + the function to execute it
|
|
20715
21471
|
*/
|
|
20716
21472
|
async next() {
|
|
@@ -20739,7 +21495,12 @@ exports.Unroll = void 0;
|
|
|
20739
21495
|
return {
|
|
20740
21496
|
type: 2 /* DONE */,
|
|
20741
21497
|
vtxoTxid: this.toUnroll.txid,
|
|
20742
|
-
do
|
|
21498
|
+
// The observation rides on `do` rather than the iterator so
|
|
21499
|
+
// a caller driving `next()` by hand fires it too.
|
|
21500
|
+
do: () => notifyExitObserved(this.onExitObserved, {
|
|
21501
|
+
txid: this.toUnroll.txid,
|
|
21502
|
+
vout: this.toUnroll.vout
|
|
21503
|
+
})
|
|
20743
21504
|
};
|
|
20744
21505
|
}
|
|
20745
21506
|
const virtualTxBase64 = await this.resolveVirtualTxBase64(nextTxToBroadcast);
|
|
@@ -20773,9 +21534,22 @@ exports.Unroll = void 0;
|
|
|
20773
21534
|
}
|
|
20774
21535
|
}
|
|
20775
21536
|
Unroll2.Session = Session2;
|
|
21537
|
+
async function sessionFor(wallet, toUnroll, bumper) {
|
|
21538
|
+
const manager = await wallet.getContractManager();
|
|
21539
|
+
return Session2.create(
|
|
21540
|
+
toUnroll,
|
|
21541
|
+
bumper,
|
|
21542
|
+
wallet.onchainProvider,
|
|
21543
|
+
wallet.indexerProvider,
|
|
21544
|
+
wallet.virtualTxRepository,
|
|
21545
|
+
exitObserverFor(manager)
|
|
21546
|
+
);
|
|
21547
|
+
}
|
|
21548
|
+
Unroll2.sessionFor = sessionFor;
|
|
20776
21549
|
async function completeUnroll(wallet, vtxoTxids, outputAddress) {
|
|
20777
21550
|
const signedTx = await prepareUnrollTransaction(wallet, vtxoTxids, outputAddress);
|
|
20778
21551
|
await wallet.onchainProvider.broadcastTransaction(signedTx.hex);
|
|
21552
|
+
await refreshSpentExitOutputs(wallet, signedTx);
|
|
20779
21553
|
return signedTx.id;
|
|
20780
21554
|
}
|
|
20781
21555
|
Unroll2.completeUnroll = completeUnroll;
|
|
@@ -20791,9 +21565,9 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
20791
21565
|
let totalAmount = 0n;
|
|
20792
21566
|
const txWeightEstimator = TxWeightEstimator.create();
|
|
20793
21567
|
for (const vtxo of vtxos) {
|
|
20794
|
-
if (!vtxo
|
|
21568
|
+
if (!chunkEJOFL5WH_cjs.canSweepOnchain(vtxo)) {
|
|
20795
21569
|
throw new Error(
|
|
20796
|
-
`Vtxo ${vtxo.txid}:${vtxo.vout} is not fully unrolled
|
|
21570
|
+
`Vtxo ${vtxo.txid}:${vtxo.vout} cannot be swept onchain: it is not fully unrolled (use unroll first), or its exit output was already spent`
|
|
20797
21571
|
);
|
|
20798
21572
|
}
|
|
20799
21573
|
const txStatus = await wallet.onchainProvider.getTxStatus(vtxo.txid);
|
|
@@ -20802,14 +21576,14 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
20802
21576
|
}
|
|
20803
21577
|
const resolved = await resolveUnilateralPath({
|
|
20804
21578
|
vtxo,
|
|
20805
|
-
scriptHex: base.hex.encode(
|
|
21579
|
+
scriptHex: base.hex.encode(chunkEJOFL5WH_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
|
|
20806
21580
|
contractRepository: wallet.contractRepository,
|
|
20807
21581
|
walletPubKeyHex: base.hex.encode(await wallet.identity.xOnlyPublicKey()),
|
|
20808
21582
|
currentTime: Date.now()
|
|
20809
21583
|
});
|
|
20810
21584
|
const spendingLeaf = resolved.selection.leaf;
|
|
20811
21585
|
const sequence = resolved.selection.sequence;
|
|
20812
|
-
const timelock =
|
|
21586
|
+
const timelock = chunkEJOFL5WH_cjs.sequenceToTimelock(sequence);
|
|
20813
21587
|
const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
|
|
20814
21588
|
if (!elapsed) {
|
|
20815
21589
|
throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
|
|
@@ -20822,7 +21596,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
20822
21596
|
sequence,
|
|
20823
21597
|
witnessUtxo: {
|
|
20824
21598
|
amount: BigInt(vtxo.value),
|
|
20825
|
-
script:
|
|
21599
|
+
script: chunkEJOFL5WH_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
|
|
20826
21600
|
},
|
|
20827
21601
|
sighashType: btcSigner.SigHash.DEFAULT
|
|
20828
21602
|
});
|
|
@@ -20832,7 +21606,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
20832
21606
|
btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
|
|
20833
21607
|
);
|
|
20834
21608
|
}
|
|
20835
|
-
const tx = new
|
|
21609
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({ version: 2 });
|
|
20836
21610
|
for (const input of inputs) {
|
|
20837
21611
|
tx.addInput(input);
|
|
20838
21612
|
}
|
|
@@ -20854,6 +21628,22 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
20854
21628
|
signedTx.finalize();
|
|
20855
21629
|
return signedTx;
|
|
20856
21630
|
}
|
|
21631
|
+
async function refreshSpentExitOutputs(wallet, signedTx) {
|
|
21632
|
+
const outpoints = [];
|
|
21633
|
+
for (let i = 0; i < signedTx.inputsLength; i++) {
|
|
21634
|
+
const input = signedTx.getInput(i);
|
|
21635
|
+
if (input.txid && input.index !== void 0) {
|
|
21636
|
+
outpoints.push({ txid: base.hex.encode(input.txid), vout: input.index });
|
|
21637
|
+
}
|
|
21638
|
+
}
|
|
21639
|
+
if (outpoints.length === 0) return;
|
|
21640
|
+
try {
|
|
21641
|
+
const manager = await wallet.getContractManager();
|
|
21642
|
+
await manager.refreshOutpoints(outpoints);
|
|
21643
|
+
} catch (e) {
|
|
21644
|
+
console.error("completeUnroll: failed to refresh the spent exit outputs", e);
|
|
21645
|
+
}
|
|
21646
|
+
}
|
|
20857
21647
|
function sleep2(ms) {
|
|
20858
21648
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
20859
21649
|
}
|
|
@@ -20899,7 +21689,7 @@ async function buildSignedSweep(params) {
|
|
|
20899
21689
|
`uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
|
|
20900
21690
|
);
|
|
20901
21691
|
}
|
|
20902
|
-
const tx = new
|
|
21692
|
+
const tx = new chunkEJOFL5WH_cjs.Transaction({ version: 2 });
|
|
20903
21693
|
tx.addInput({
|
|
20904
21694
|
txid: vtxo.txid,
|
|
20905
21695
|
index: vtxo.vout,
|
|
@@ -20924,7 +21714,7 @@ async function buildSignedSweep(params) {
|
|
|
20924
21714
|
finalScriptWitness: [
|
|
20925
21715
|
tapScriptSig[0][1],
|
|
20926
21716
|
...path.extraWitness,
|
|
20927
|
-
|
|
21717
|
+
chunkEJOFL5WH_cjs.scriptFromTapLeafScript(path.leaf),
|
|
20928
21718
|
btcSigner.TaprootControlBlock.encode(controlBlock)
|
|
20929
21719
|
]
|
|
20930
21720
|
});
|
|
@@ -20932,7 +21722,7 @@ async function buildSignedSweep(params) {
|
|
|
20932
21722
|
}
|
|
20933
21723
|
|
|
20934
21724
|
// src/wallet/exit/estimate.ts
|
|
20935
|
-
var CHILD_OUTPUT_DUST =
|
|
21725
|
+
var CHILD_OUTPUT_DUST = CHILD_DUST_AMOUNT;
|
|
20936
21726
|
function stepFundingAmount(stepFee) {
|
|
20937
21727
|
return stepFee + CHILD_OUTPUT_DUST;
|
|
20938
21728
|
}
|
|
@@ -20954,7 +21744,7 @@ async function resolveFeeRate(opts) {
|
|
|
20954
21744
|
}
|
|
20955
21745
|
async function selectExitVtxos(opts) {
|
|
20956
21746
|
if (!opts.vtxos) return opts.wallet.getVtxos();
|
|
20957
|
-
const res = await
|
|
21747
|
+
const res = await chunkEJOFL5WH_cjs.getNormalizedVtxos(opts.wallet.indexerProvider, { outpoints: opts.vtxos });
|
|
20958
21748
|
const tapTrees = /* @__PURE__ */ new Map();
|
|
20959
21749
|
const out = [];
|
|
20960
21750
|
for (const vtxo of res.vtxos) {
|
|
@@ -20969,7 +21759,7 @@ async function selectExitVtxos(opts) {
|
|
|
20969
21759
|
`no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
|
|
20970
21760
|
);
|
|
20971
21761
|
}
|
|
20972
|
-
const handler =
|
|
21762
|
+
const handler = chunk6YUACVX4_cjs.contractHandlers.get(contract.type);
|
|
20973
21763
|
if (!handler) {
|
|
20974
21764
|
throw new Error(`no contract handler registered for type '${contract.type}'`);
|
|
20975
21765
|
}
|
|
@@ -20999,7 +21789,7 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
20999
21789
|
if (pendingNodes.length > 0) {
|
|
21000
21790
|
const txs = await resolver.getVirtualTxs(pendingNodes.map((n) => n.txid));
|
|
21001
21791
|
for (const psbt of txs) {
|
|
21002
|
-
psbts.set(
|
|
21792
|
+
psbts.set(chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
21003
21793
|
}
|
|
21004
21794
|
}
|
|
21005
21795
|
const childVsize = Number(
|
|
@@ -21035,7 +21825,7 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
21035
21825
|
try {
|
|
21036
21826
|
const resolved = await resolveUnilateralPath({
|
|
21037
21827
|
vtxo,
|
|
21038
|
-
scriptHex: base.hex.encode(
|
|
21828
|
+
scriptHex: base.hex.encode(chunkEJOFL5WH_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
|
|
21039
21829
|
contractRepository: wallet.contractRepository,
|
|
21040
21830
|
walletPubKeyHex,
|
|
21041
21831
|
currentTime: Date.now()
|
|
@@ -21054,7 +21844,7 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
21054
21844
|
});
|
|
21055
21845
|
continue;
|
|
21056
21846
|
}
|
|
21057
|
-
const t =
|
|
21847
|
+
const t = chunkEJOFL5WH_cjs.sequenceToTimelock(resolved.selection.sequence);
|
|
21058
21848
|
const delay = { type: t.type, value: Number(t.value) };
|
|
21059
21849
|
infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
|
|
21060
21850
|
sweeps.push({ vtxo, resolved, sweepFee, delay });
|
|
@@ -21093,10 +21883,18 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
21093
21883
|
// splitter. funded: + 1 splitter tx and pre-signed children.
|
|
21094
21884
|
txCount: (graph ? 0 : steps.length > 0 ? 1 : 0) + steps.length * 2 + sweeps.length,
|
|
21095
21885
|
totalFeeSats: splitterFee + stepFees + sweepFees,
|
|
21096
|
-
// graph funding is what the executor sends to its own fee address:
|
|
21097
|
-
//
|
|
21098
|
-
//
|
|
21099
|
-
|
|
21886
|
+
// graph funding is what the executor sends to its own fee address: the
|
|
21887
|
+
// CPFP fees, plus one dust floor. Change recycles through that single
|
|
21888
|
+
// address, so each bump hands its remainder to the next and only the
|
|
21889
|
+
// *final* change has to clear `CHILD_DUST_AMOUNT` — but it does have to,
|
|
21890
|
+
// and `buildAnchorChild` throws rather than absorbing a short remainder
|
|
21891
|
+
// into the fee. Quoting bare fees quotes an amount that strands the last
|
|
21892
|
+
// bump and every sweep behind it.
|
|
21893
|
+
//
|
|
21894
|
+
// funded reserves the same floor per step instead of once overall (see
|
|
21895
|
+
// `stepFundingAmount`), because it pre-funds each child separately
|
|
21896
|
+
// through the splitter rather than recycling one output.
|
|
21897
|
+
fundingRequiredSats: graph ? steps.length > 0 ? stepFees + CHILD_OUTPUT_DUST : 0 : splitterFee + fundingTotal,
|
|
21100
21898
|
recoveredSats: sweeps.reduce((s, x) => s + (x.vtxo.value - x.sweepFee), 0)
|
|
21101
21899
|
};
|
|
21102
21900
|
const expiries = pendingNodes.map((n) => n.expiresAt).filter((x) => x !== void 0);
|
|
@@ -21156,12 +21954,32 @@ var Executor = class {
|
|
|
21156
21954
|
this.pollIntervalMs = opts?.pollIntervalMs ?? 5e3;
|
|
21157
21955
|
this.feeWallet = opts?.feeWallet;
|
|
21158
21956
|
this.signal = opts?.signal;
|
|
21957
|
+
this.onExitObserved = opts?.onExitObserved;
|
|
21159
21958
|
}
|
|
21160
21959
|
pkg;
|
|
21161
21960
|
provider;
|
|
21162
21961
|
pollIntervalMs;
|
|
21163
21962
|
feeWallet;
|
|
21164
21963
|
signal;
|
|
21964
|
+
onExitObserved;
|
|
21965
|
+
/**
|
|
21966
|
+
* Per-VTXO branch progress, which the executor otherwise does not track:
|
|
21967
|
+
* `dead` / `done` are per-step, and a VTXO is only onchain once EVERY
|
|
21968
|
+
* `package`/`bump` step naming it has confirmed. (`broadcast` — the funding
|
|
21969
|
+
* splitter — carries no `forVtxos` and serves no single VTXO.)
|
|
21970
|
+
*/
|
|
21971
|
+
branchSteps() {
|
|
21972
|
+
const byVtxo = /* @__PURE__ */ new Map();
|
|
21973
|
+
this.pkg.steps.forEach((step, i) => {
|
|
21974
|
+
if (step.kind !== "package" && step.kind !== "bump") return;
|
|
21975
|
+
for (const vtxo of step.forVtxos) {
|
|
21976
|
+
let steps = byVtxo.get(vtxo);
|
|
21977
|
+
if (!steps) byVtxo.set(vtxo, steps = /* @__PURE__ */ new Set());
|
|
21978
|
+
steps.add(i);
|
|
21979
|
+
}
|
|
21980
|
+
});
|
|
21981
|
+
return byVtxo;
|
|
21982
|
+
}
|
|
21165
21983
|
/**
|
|
21166
21984
|
* Poll delay. Nearly all wall-clock time is spent here, so it must be the
|
|
21167
21985
|
* thing that reacts to abort — checking only between polls would leave
|
|
@@ -21201,6 +22019,19 @@ var Executor = class {
|
|
|
21201
22019
|
async *[Symbol.asyncIterator]() {
|
|
21202
22020
|
throwIfAborted(this.signal);
|
|
21203
22021
|
const dead = /* @__PURE__ */ new Set();
|
|
22022
|
+
const branchSteps = this.branchSteps();
|
|
22023
|
+
const onchainSteps = /* @__PURE__ */ new Set();
|
|
22024
|
+
const branchObserved = /* @__PURE__ */ new Set();
|
|
22025
|
+
const observeBranch = async (stepIndex, forVtxos) => {
|
|
22026
|
+
onchainSteps.add(stepIndex);
|
|
22027
|
+
for (const vtxo of forVtxos ?? []) {
|
|
22028
|
+
if (branchObserved.has(vtxo)) continue;
|
|
22029
|
+
const steps = branchSteps.get(vtxo);
|
|
22030
|
+
if (!steps || ![...steps].every((i) => onchainSteps.has(i))) continue;
|
|
22031
|
+
branchObserved.add(vtxo);
|
|
22032
|
+
await this.observe(vtxo);
|
|
22033
|
+
}
|
|
22034
|
+
};
|
|
21204
22035
|
if (this.pkg.validUntil && Date.now() / 1e3 > this.pkg.validUntil) {
|
|
21205
22036
|
yield {
|
|
21206
22037
|
stepIndex: -1,
|
|
@@ -21230,6 +22061,7 @@ var Executor = class {
|
|
|
21230
22061
|
const anchorTxid = step.kind === "package" || step.kind === "bump" ? step.parentTxid : step.txid;
|
|
21231
22062
|
const existing = await this.status(anchorTxid);
|
|
21232
22063
|
if (existing?.confirmed) {
|
|
22064
|
+
await observeBranch(i, forVtxos);
|
|
21233
22065
|
yield {
|
|
21234
22066
|
stepIndex: i,
|
|
21235
22067
|
kind: step.kind,
|
|
@@ -21285,6 +22117,7 @@ var Executor = class {
|
|
|
21285
22117
|
}
|
|
21286
22118
|
}
|
|
21287
22119
|
await this.waitConfirmed(anchorTxid);
|
|
22120
|
+
await observeBranch(i, forVtxos);
|
|
21288
22121
|
yield {
|
|
21289
22122
|
stepIndex: i,
|
|
21290
22123
|
kind: step.kind,
|
|
@@ -21315,6 +22148,7 @@ var Executor = class {
|
|
|
21315
22148
|
const swept = await this.status(step.txid);
|
|
21316
22149
|
if (swept?.confirmed) {
|
|
21317
22150
|
done.add(index);
|
|
22151
|
+
await this.observe(step.vtxo);
|
|
21318
22152
|
yield {
|
|
21319
22153
|
stepIndex: index,
|
|
21320
22154
|
kind: "sweep",
|
|
@@ -21371,7 +22205,25 @@ var Executor = class {
|
|
|
21371
22205
|
if (done.size < pending.length) await this.sleep();
|
|
21372
22206
|
}
|
|
21373
22207
|
}
|
|
22208
|
+
/** `"txid:vout"` -> outpoint, then hand it to the hook. A malformed entry is skipped. */
|
|
22209
|
+
async observe(outpoint) {
|
|
22210
|
+
if (!this.onExitObserved) return;
|
|
22211
|
+
const sep = outpoint.lastIndexOf(":");
|
|
22212
|
+
const rest = outpoint.slice(sep + 1);
|
|
22213
|
+
const vout = Number(rest);
|
|
22214
|
+
if (sep <= 0 || rest === "" || !Number.isInteger(vout)) return;
|
|
22215
|
+
await notifyExitObserved(this.onExitObserved, { txid: outpoint.slice(0, sep), vout });
|
|
22216
|
+
}
|
|
21374
22217
|
};
|
|
22218
|
+
|
|
22219
|
+
// src/wallet/exit/execute.ts
|
|
22220
|
+
async function execute(wallet, pkg, opts) {
|
|
22221
|
+
const manager = await wallet.getContractManager();
|
|
22222
|
+
return new Executor(pkg, opts?.provider ?? wallet.onchainProvider, {
|
|
22223
|
+
...opts,
|
|
22224
|
+
onExitObserved: opts?.onExitObserved ?? exitObserverFor(manager)
|
|
22225
|
+
});
|
|
22226
|
+
}
|
|
21375
22227
|
async function prepare(opts) {
|
|
21376
22228
|
const { wallet, onchainWallet } = opts;
|
|
21377
22229
|
const feeRate = await resolveFeeRate(opts);
|
|
@@ -21393,7 +22245,7 @@ async function prepare(opts) {
|
|
|
21393
22245
|
txid: sweep.vtxo.txid,
|
|
21394
22246
|
vout: sweep.vtxo.vout,
|
|
21395
22247
|
value: sweep.vtxo.value,
|
|
21396
|
-
pkScript:
|
|
22248
|
+
pkScript: chunkEJOFL5WH_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
|
|
21397
22249
|
},
|
|
21398
22250
|
path: sweep.resolved.selection,
|
|
21399
22251
|
outputAddress: opts.sweepAddress,
|
|
@@ -21446,7 +22298,10 @@ async function prepare(opts) {
|
|
|
21446
22298
|
totals: {
|
|
21447
22299
|
txCount: bumpSteps.length * 2 + sweepSteps.length,
|
|
21448
22300
|
totalFeeSats: stepFees2 + sweepFees2,
|
|
21449
|
-
|
|
22301
|
+
// Fees plus the single dust floor the recycling change output
|
|
22302
|
+
// must keep clear; see the note in `estimate.ts`. Must match
|
|
22303
|
+
// the quote `estimate` gives for the same package.
|
|
22304
|
+
fundingRequiredSats: bumpSteps.length > 0 ? stepFees2 + CHILD_OUTPUT_DUST : 0,
|
|
21450
22305
|
recoveredSats: recovered2
|
|
21451
22306
|
},
|
|
21452
22307
|
vtxos: layout.infos,
|
|
@@ -21478,7 +22333,7 @@ async function prepare(opts) {
|
|
|
21478
22333
|
if (newFee <= splitterFee) break;
|
|
21479
22334
|
splitterFee = newFee;
|
|
21480
22335
|
}
|
|
21481
|
-
const splitter = new
|
|
22336
|
+
const splitter = new chunkEJOFL5WH_cjs.Transaction({ version: 2 });
|
|
21482
22337
|
for (const coin of selected.inputs) {
|
|
21483
22338
|
splitter.addInput({
|
|
21484
22339
|
txid: coin.txid,
|
|
@@ -21615,47 +22470,48 @@ function isValidStep(step) {
|
|
|
21615
22470
|
var UnilateralExit = {
|
|
21616
22471
|
estimate,
|
|
21617
22472
|
prepare,
|
|
22473
|
+
execute,
|
|
21618
22474
|
Executor
|
|
21619
22475
|
};
|
|
21620
22476
|
|
|
21621
22477
|
// src/arkade/index.ts
|
|
21622
22478
|
var arkade_exports = {};
|
|
21623
22479
|
chunk5BLDMQED_cjs.__export(arkade_exports, {
|
|
21624
|
-
ARKADE_OP: () =>
|
|
21625
|
-
ARKADE_OPCODES: () =>
|
|
21626
|
-
ARKADE_OPCODE_NAMES: () =>
|
|
21627
|
-
ARKADE_OPCODE_VALUES: () =>
|
|
21628
|
-
ARKADE_OPS: () =>
|
|
22480
|
+
ARKADE_OP: () => chunk6YUACVX4_cjs.ARKADE_OP,
|
|
22481
|
+
ARKADE_OPCODES: () => chunk6YUACVX4_cjs.ARKADE_OPCODES,
|
|
22482
|
+
ARKADE_OPCODE_NAMES: () => chunk6YUACVX4_cjs.ARKADE_OPCODE_NAMES,
|
|
22483
|
+
ARKADE_OPCODE_VALUES: () => chunk6YUACVX4_cjs.ARKADE_OPCODE_VALUES,
|
|
22484
|
+
ARKADE_OPS: () => chunk6YUACVX4_cjs.ARKADE_OPS,
|
|
21629
22485
|
Arkade: () => Arkade,
|
|
21630
22486
|
ArkadeContract: () => ArkadeContract,
|
|
21631
|
-
ArkadeProgramScript: () =>
|
|
21632
|
-
ArkadeScript: () =>
|
|
22487
|
+
ArkadeProgramScript: () => chunk6YUACVX4_cjs.ArkadeProgramScript,
|
|
22488
|
+
ArkadeScript: () => chunk6YUACVX4_cjs.ArkadeScript,
|
|
21633
22489
|
ArkadeTransactionBuilder: () => ArkadeTransactionBuilder,
|
|
21634
|
-
BigNum: () =>
|
|
22490
|
+
BigNum: () => chunk6YUACVX4_cjs.bignum_exports,
|
|
21635
22491
|
OP: () => btcSigner.OP,
|
|
21636
|
-
OPCODE_NAMES: () =>
|
|
21637
|
-
OPCODE_VALUES: () =>
|
|
21638
|
-
SUPPORTED_PROGRAM_VERSION: () =>
|
|
22492
|
+
OPCODE_NAMES: () => chunk6YUACVX4_cjs.OPCODE_NAMES,
|
|
22493
|
+
OPCODE_VALUES: () => chunk6YUACVX4_cjs.OPCODE_VALUES,
|
|
22494
|
+
SUPPORTED_PROGRAM_VERSION: () => chunk6YUACVX4_cjs.SUPPORTED_PROGRAM_VERSION,
|
|
21639
22495
|
Script: () => btcSigner.Script,
|
|
21640
|
-
arkadeScriptHash: () =>
|
|
21641
|
-
arkadeWitnessHash: () =>
|
|
21642
|
-
asmToBytes: () =>
|
|
21643
|
-
bytesToASM: () =>
|
|
21644
|
-
computeArkadeScriptPublicKey: () =>
|
|
22496
|
+
arkadeScriptHash: () => chunk6YUACVX4_cjs.arkadeScriptHash,
|
|
22497
|
+
arkadeWitnessHash: () => chunk6YUACVX4_cjs.arkadeWitnessHash,
|
|
22498
|
+
asmToBytes: () => chunk6YUACVX4_cjs.asmToBytes,
|
|
22499
|
+
bytesToASM: () => chunk6YUACVX4_cjs.bytesToASM,
|
|
22500
|
+
computeArkadeScriptPublicKey: () => chunk6YUACVX4_cjs.computeArkadeScriptPublicKey,
|
|
21645
22501
|
createArkadeBatchHandler: () => createArkadeBatchHandler,
|
|
21646
|
-
deserializeArkadeContractParams: () =>
|
|
21647
|
-
fromASM: () =>
|
|
21648
|
-
getOpcodeName: () =>
|
|
21649
|
-
getOpcodeValue: () =>
|
|
21650
|
-
parseArtifact: () =>
|
|
21651
|
-
resolveAsm: () =>
|
|
21652
|
-
serializeArkadeContractParams: () =>
|
|
21653
|
-
stringifyArtifact: () =>
|
|
21654
|
-
toASM: () =>
|
|
21655
|
-
validateProgram: () =>
|
|
21656
|
-
witnessRefToBytes: () =>
|
|
22502
|
+
deserializeArkadeContractParams: () => chunk6YUACVX4_cjs.deserializeArkadeContractParams,
|
|
22503
|
+
fromASM: () => chunk6YUACVX4_cjs.fromASM,
|
|
22504
|
+
getOpcodeName: () => chunk6YUACVX4_cjs.getOpcodeName,
|
|
22505
|
+
getOpcodeValue: () => chunk6YUACVX4_cjs.getOpcodeValue,
|
|
22506
|
+
parseArtifact: () => chunk6YUACVX4_cjs.parseArtifact,
|
|
22507
|
+
resolveAsm: () => chunk6YUACVX4_cjs.resolveAsm,
|
|
22508
|
+
serializeArkadeContractParams: () => chunk6YUACVX4_cjs.serializeArkadeContractParams,
|
|
22509
|
+
stringifyArtifact: () => chunk6YUACVX4_cjs.stringifyArtifact,
|
|
22510
|
+
toASM: () => chunk6YUACVX4_cjs.toASM,
|
|
22511
|
+
validateProgram: () => chunk6YUACVX4_cjs.validateProgram,
|
|
22512
|
+
witnessRefToBytes: () => chunk6YUACVX4_cjs.witnessRefToBytes
|
|
21657
22513
|
});
|
|
21658
|
-
var isVtxoCoin = (input) =>
|
|
22514
|
+
var isVtxoCoin = (input) => chunkEJOFL5WH_cjs.isVirtualCoin(input);
|
|
21659
22515
|
function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message, session, arkProvider, emulator, network, recipients, batchExpiryPolicy) {
|
|
21660
22516
|
let batchId;
|
|
21661
22517
|
let sweepTapTreeRoot;
|
|
@@ -21676,23 +22532,23 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
21676
22532
|
);
|
|
21677
22533
|
await arkProvider.confirmRegistration(intentId);
|
|
21678
22534
|
batchId = event.id;
|
|
21679
|
-
const sweepTapscript =
|
|
22535
|
+
const sweepTapscript = chunkEJOFL5WH_cjs.CSVMultisigTapscript.encode({
|
|
21680
22536
|
timelock,
|
|
21681
|
-
pubkeys: [
|
|
22537
|
+
pubkeys: [chunk6YUACVX4_cjs.toXOnly(base.hex.decode(info.forfeitPubkey), "forfeit key")]
|
|
21682
22538
|
}).script;
|
|
21683
22539
|
sweepTapTreeRoot = payment_js.tapLeafHash(sweepTapscript);
|
|
21684
22540
|
return { skip: false };
|
|
21685
22541
|
},
|
|
21686
22542
|
onTreeSigningStarted: async (event, vtxoTree) => {
|
|
21687
22543
|
const signerPubKey = await session.getPublicKey();
|
|
21688
|
-
const xonlySignerPubKey =
|
|
22544
|
+
const xonlySignerPubKey = chunk6YUACVX4_cjs.toXOnly(signerPubKey, "signer key");
|
|
21689
22545
|
const xOnlyPubkeys = event.cosignersPublicKeys.map(
|
|
21690
|
-
(k) => base.hex.encode(
|
|
22546
|
+
(k) => base.hex.encode(chunk6YUACVX4_cjs.toXOnly(base.hex.decode(k), "cosigner key"))
|
|
21691
22547
|
);
|
|
21692
22548
|
if (!xOnlyPubkeys.includes(base.hex.encode(xonlySignerPubKey))) {
|
|
21693
22549
|
return { skip: true };
|
|
21694
22550
|
}
|
|
21695
|
-
const commitmentTx =
|
|
22551
|
+
const commitmentTx = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(event.unsignedCommitmentTx));
|
|
21696
22552
|
validateVtxoTxGraph(vtxoTree, commitmentTx, sweepTapTreeRoot);
|
|
21697
22553
|
if (recipients && recipients.length > 0) {
|
|
21698
22554
|
validateBatchRecipients(commitmentTx, vtxoTree.leaves(), recipients, network);
|
|
@@ -21724,7 +22580,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
21724
22580
|
if (connectorTree) {
|
|
21725
22581
|
validateConnectorsTxGraph(event.commitmentTx, connectorTree);
|
|
21726
22582
|
}
|
|
21727
|
-
let commitmentPsbt =
|
|
22583
|
+
let commitmentPsbt = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(event.commitmentTx));
|
|
21728
22584
|
assertFinalCommitmentMatchesValidated(
|
|
21729
22585
|
commitmentPsbt,
|
|
21730
22586
|
validatedCommitmentTxid,
|
|
@@ -21759,7 +22615,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
21759
22615
|
boardingIndices.push(boardingIdx);
|
|
21760
22616
|
continue;
|
|
21761
22617
|
}
|
|
21762
|
-
if (
|
|
22618
|
+
if (chunkEJOFL5WH_cjs.isRecoverable(input) || isSubdust(input, info.dust)) {
|
|
21763
22619
|
continue;
|
|
21764
22620
|
}
|
|
21765
22621
|
if (connectorIndex >= connectorLeaves.length) {
|
|
@@ -21780,7 +22636,7 @@ function createArkadeBatchHandler(intentId, inputs, signer, signedProof, message
|
|
|
21780
22636
|
index: input.vout,
|
|
21781
22637
|
witnessUtxo: {
|
|
21782
22638
|
amount: BigInt(input.value),
|
|
21783
|
-
script:
|
|
22639
|
+
script: chunkEJOFL5WH_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
21784
22640
|
},
|
|
21785
22641
|
sighashType: btcSigner.SigHash.DEFAULT,
|
|
21786
22642
|
tapLeafScript: [input.forfeitTapLeafScript]
|
|
@@ -21871,16 +22727,16 @@ var Arkade = class _Arkade {
|
|
|
21871
22727
|
/** Connect and resolve the server key, checkpoint closure and (if present) the co-signer key. */
|
|
21872
22728
|
static async connect(opts) {
|
|
21873
22729
|
const info = await opts.arkade.getInfo();
|
|
21874
|
-
const serverKey =
|
|
21875
|
-
const checkpoint =
|
|
21876
|
-
const network = opts.network ??
|
|
22730
|
+
const serverKey = chunk6YUACVX4_cjs.toXOnly(base.hex.decode(info.signerPubkey), "ark signer key");
|
|
22731
|
+
const checkpoint = chunkEJOFL5WH_cjs.CSVMultisigTapscript.decode(base.hex.decode(info.checkpointTapscript));
|
|
22732
|
+
const network = opts.network ?? chunkEJOFL5WH_cjs.DEFAULT_NETWORK;
|
|
21877
22733
|
let emulatorKey;
|
|
21878
22734
|
if (opts.emulator) {
|
|
21879
|
-
emulatorKey = base.hex.decode(
|
|
22735
|
+
emulatorKey = base.hex.decode(chunkEJOFL5WH_cjs.resolveEmulatorPubkey(network, opts.emulatorPubkey));
|
|
21880
22736
|
}
|
|
21881
22737
|
let userKey;
|
|
21882
22738
|
if (opts.identity) {
|
|
21883
|
-
userKey =
|
|
22739
|
+
userKey = chunk6YUACVX4_cjs.toXOnly(await opts.identity.xOnlyPublicKey(), "identity key");
|
|
21884
22740
|
}
|
|
21885
22741
|
return new _Arkade({
|
|
21886
22742
|
arkProvider: opts.arkade,
|
|
@@ -21906,7 +22762,7 @@ var Arkade = class _Arkade {
|
|
|
21906
22762
|
* key respectively; explicit args always win.
|
|
21907
22763
|
*/
|
|
21908
22764
|
contract(program, args = {}) {
|
|
21909
|
-
const declared = (program.params ?? []).map(
|
|
22765
|
+
const declared = (program.params ?? []).map(chunk6YUACVX4_cjs.inputName);
|
|
21910
22766
|
if (declared.includes("server") && args.server === void 0) {
|
|
21911
22767
|
args = { ...args, server: this.serverKey };
|
|
21912
22768
|
}
|
|
@@ -21926,7 +22782,7 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
21926
22782
|
userKey: client.userKey,
|
|
21927
22783
|
emulatorKey: client.emulatorKey
|
|
21928
22784
|
};
|
|
21929
|
-
this.vtxoScript = new
|
|
22785
|
+
this.vtxoScript = new chunk6YUACVX4_cjs.ArkadeProgramScript(program, args, this.keys);
|
|
21930
22786
|
this.tapTree = this.vtxoScript.encode();
|
|
21931
22787
|
this.compiled = this.vtxoScript.compiled;
|
|
21932
22788
|
}
|
|
@@ -21954,7 +22810,7 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
21954
22810
|
`ArkadeContract.fromContract: expected contract type 'arkade', got '${contract.type}'`
|
|
21955
22811
|
);
|
|
21956
22812
|
}
|
|
21957
|
-
const typed =
|
|
22813
|
+
const typed = chunk6YUACVX4_cjs.deserializeArkadeContractParams(contract.params);
|
|
21958
22814
|
return new _ArkadeContract(client, typed.program, typed.args, {
|
|
21959
22815
|
serverKey: typed.serverKey,
|
|
21960
22816
|
userKey: typed.userKey,
|
|
@@ -21995,7 +22851,7 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
21995
22851
|
toContractParams() {
|
|
21996
22852
|
return {
|
|
21997
22853
|
type: "arkade",
|
|
21998
|
-
params:
|
|
22854
|
+
params: chunk6YUACVX4_cjs.serializeArkadeContractParams({
|
|
21999
22855
|
program: this.program,
|
|
22000
22856
|
args: this.args,
|
|
22001
22857
|
serverKey: this.keys.serverKey,
|
|
@@ -22032,6 +22888,10 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
22032
22888
|
* When a `contractManager` is configured and this contract is registered,
|
|
22033
22889
|
* reads the repository-backed state (offline-first, kept fresh by the
|
|
22034
22890
|
* contract watcher). Otherwise falls back to a direct indexer query.
|
|
22891
|
+
*
|
|
22892
|
+
* Both branches refuse a spent or unilaterally exited output. They are not
|
|
22893
|
+
* otherwise interchangeable: the fallback asks `spendableOnly`, which also
|
|
22894
|
+
* drops swept coins — the manager branch keeps those.
|
|
22035
22895
|
*/
|
|
22036
22896
|
async getUtxos() {
|
|
22037
22897
|
const manager = this.client.contractManager;
|
|
@@ -22040,17 +22900,19 @@ var ArkadeContract = class _ArkadeContract {
|
|
|
22040
22900
|
const [registered] = await manager.getContracts({ script: scriptHex });
|
|
22041
22901
|
if (registered) {
|
|
22042
22902
|
const [withVtxos] = await manager.getContractsWithVtxos({ script: scriptHex });
|
|
22043
|
-
return (withVtxos?.vtxos ?? []).filter(
|
|
22903
|
+
return (withVtxos?.vtxos ?? []).filter(
|
|
22904
|
+
(v) => !chunkEJOFL5WH_cjs.hasTerminalSpend(v) && !v.isUnrolled
|
|
22905
|
+
);
|
|
22044
22906
|
}
|
|
22045
22907
|
}
|
|
22046
22908
|
if (!this.client.indexer) {
|
|
22047
22909
|
throw new Error("ArkadeContract.getUtxos: an indexer is required");
|
|
22048
22910
|
}
|
|
22049
|
-
const { vtxos } = await
|
|
22911
|
+
const { vtxos } = await chunkEJOFL5WH_cjs.getNormalizedVtxos(this.client.indexer, {
|
|
22050
22912
|
scripts: [scriptHex],
|
|
22051
22913
|
spendableOnly: true
|
|
22052
22914
|
});
|
|
22053
|
-
return vtxos;
|
|
22915
|
+
return vtxos.filter((v) => !chunkEJOFL5WH_cjs.hasTerminalSpend(v) && !v.isUnrolled);
|
|
22054
22916
|
}
|
|
22055
22917
|
/** Total spendable balance (requires an indexer). */
|
|
22056
22918
|
async getBalance() {
|
|
@@ -22148,12 +23010,25 @@ var ArkadeTransactionBuilder = class {
|
|
|
22148
23010
|
this.contract.client.checkpoint
|
|
22149
23011
|
);
|
|
22150
23012
|
if (coin.sourceTx) {
|
|
22151
|
-
|
|
23013
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(arkTx, 0, chunkEJOFL5WH_cjs.PrevArkTxField, coin.sourceTx);
|
|
23014
|
+
}
|
|
23015
|
+
if (this.fn.arkadeScript) {
|
|
23016
|
+
const indexer = this.contract.client.indexer;
|
|
23017
|
+
if (!indexer) {
|
|
23018
|
+
throw new PrevTxUnavailableError(
|
|
23019
|
+
"covenant spends require an `indexer` on the Arkade client to resolve the previous ark tx of each input"
|
|
23020
|
+
);
|
|
23021
|
+
}
|
|
23022
|
+
await attachPrevArkTxs(
|
|
23023
|
+
arkTx,
|
|
23024
|
+
[coin.txid, ...this.fundingCoins.map((c) => c.txid)],
|
|
23025
|
+
indexer
|
|
23026
|
+
);
|
|
22152
23027
|
}
|
|
22153
23028
|
const condition = (def.tapscript.witness ?? []).map((w) => this.witnessBytes(w));
|
|
22154
23029
|
if (condition.length > 0) {
|
|
22155
|
-
|
|
22156
|
-
|
|
23030
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(arkTx, 0, chunkEJOFL5WH_cjs.ConditionWitness, condition);
|
|
23031
|
+
chunkEJOFL5WH_cjs.setArkPsbtField(checkpoints[0], 0, chunkEJOFL5WH_cjs.ConditionWitness, condition);
|
|
22157
23032
|
}
|
|
22158
23033
|
const packets = [];
|
|
22159
23034
|
if (this.assetSpecs.length > 0) {
|
|
@@ -22192,7 +23067,7 @@ var ArkadeTransactionBuilder = class {
|
|
|
22192
23067
|
base.base64.encode(signedArk2.toPSBT()),
|
|
22193
23068
|
signedCps.map((c) => base.base64.encode(c.toPSBT()))
|
|
22194
23069
|
);
|
|
22195
|
-
const txid =
|
|
23070
|
+
const txid = chunkEJOFL5WH_cjs.Transaction.fromPSBT(base.base64.decode(res2.signedArkTx)).id;
|
|
22196
23071
|
return {
|
|
22197
23072
|
txid,
|
|
22198
23073
|
signedArkTx: res2.signedArkTx,
|
|
@@ -22251,23 +23126,23 @@ var ArkadeTransactionBuilder = class {
|
|
|
22251
23126
|
}
|
|
22252
23127
|
buildAssetPacket() {
|
|
22253
23128
|
const groups = this.assetSpecs.map((s) => {
|
|
22254
|
-
const id = typeof s.assetId === "string" ?
|
|
22255
|
-
return
|
|
23129
|
+
const id = typeof s.assetId === "string" ? chunkPJR63FTK_cjs.AssetId.fromString(s.assetId) : chunkPJR63FTK_cjs.AssetId.fromBytes(s.assetId);
|
|
23130
|
+
return chunkPJR63FTK_cjs.AssetGroup.create(
|
|
22256
23131
|
id,
|
|
22257
23132
|
null,
|
|
22258
|
-
s.inputs.map((i) =>
|
|
22259
|
-
s.outputs.map((o) =>
|
|
22260
|
-
(s.metadata ?? []).map((m) =>
|
|
23133
|
+
s.inputs.map((i) => chunkPJR63FTK_cjs.AssetInput.create(i.vin, i.amount)),
|
|
23134
|
+
s.outputs.map((o) => chunkPJR63FTK_cjs.AssetOutput.create(o.vout, o.amount)),
|
|
23135
|
+
(s.metadata ?? []).map((m) => chunkPJR63FTK_cjs.Metadata.create(m.key, m.value))
|
|
22261
23136
|
);
|
|
22262
23137
|
});
|
|
22263
|
-
return
|
|
23138
|
+
return chunkPJR63FTK_cjs.Packet.create(groups);
|
|
22264
23139
|
}
|
|
22265
23140
|
witnessBytes(ref) {
|
|
22266
|
-
return
|
|
23141
|
+
return chunk6YUACVX4_cjs.witnessRefToBytes(ref, this.args, this.contract.args);
|
|
22267
23142
|
}
|
|
22268
23143
|
};
|
|
22269
23144
|
function bindInputs(fn, callArgs) {
|
|
22270
|
-
const names = (fn.def.inputs ?? []).map(
|
|
23145
|
+
const names = (fn.def.inputs ?? []).map(chunk6YUACVX4_cjs.inputName);
|
|
22271
23146
|
if (callArgs.length !== names.length) {
|
|
22272
23147
|
throw new Error(`${fn.name}: expected ${names.length} argument(s), got ${callArgs.length}`);
|
|
22273
23148
|
}
|
|
@@ -22667,6 +23542,7 @@ exports.AssetManager = AssetManager;
|
|
|
22667
23542
|
exports.BIP21 = BIP21;
|
|
22668
23543
|
exports.BIP21Error = BIP21Error;
|
|
22669
23544
|
exports.BLOCKED_UPGRADE_TIMEOUT_MS = BLOCKED_UPGRADE_TIMEOUT_MS;
|
|
23545
|
+
exports.CachingArkProvider = CachingArkProvider;
|
|
22670
23546
|
exports.ChainedTxType = ChainedTxType;
|
|
22671
23547
|
exports.ConnectionDisposedError = ConnectionDisposedError;
|
|
22672
23548
|
exports.ContractManager = ContractManager;
|
|
@@ -22717,6 +23593,7 @@ exports.MnemonicIdentity = MnemonicIdentity;
|
|
|
22717
23593
|
exports.OnchainWallet = OnchainWallet;
|
|
22718
23594
|
exports.P2A = P2A;
|
|
22719
23595
|
exports.PaymentRouter = PaymentRouter;
|
|
23596
|
+
exports.PrevTxUnavailableError = PrevTxUnavailableError;
|
|
22720
23597
|
exports.REGTEST_MIN_BATCH_EXPIRY_SECONDS = REGTEST_MIN_BATCH_EXPIRY_SECONDS;
|
|
22721
23598
|
exports.REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS = REGTEST_MIN_CHECKPOINT_EXIT_DELAY_SECONDS;
|
|
22722
23599
|
exports.Ramps = Ramps;
|
|
@@ -22742,6 +23619,7 @@ exports.UnilateralExit = UnilateralExit;
|
|
|
22742
23619
|
exports.UnknownPacket = UnknownPacket;
|
|
22743
23620
|
exports.VtxoManager = VtxoManager;
|
|
22744
23621
|
exports.Wallet = Wallet2;
|
|
23622
|
+
exports.WalletCannotAllocateAddressError = WalletCannotAllocateAddressError;
|
|
22745
23623
|
exports.WalletCannotSignError = WalletCannotSignError;
|
|
22746
23624
|
exports.WalletMessageHandler = WalletMessageHandler;
|
|
22747
23625
|
exports.WalletNotInitializedError = WalletNotInitializedError;
|
|
@@ -22758,6 +23636,8 @@ exports.assertSubmittedArkTxid = assertSubmittedArkTxid;
|
|
|
22758
23636
|
exports.assertValidBatchExpiry = assertValidBatchExpiry;
|
|
22759
23637
|
exports.assertValidServerUnrollScript = assertValidServerUnrollScript;
|
|
22760
23638
|
exports.assetMintResolver = assetMintResolver;
|
|
23639
|
+
exports.attachPrevArkTxs = attachPrevArkTxs;
|
|
23640
|
+
exports.attachPrevoutTxs = attachPrevoutTxs;
|
|
22761
23641
|
exports.awaitTransaction = awaitTransaction;
|
|
22762
23642
|
exports.boardingResolver = boardingResolver;
|
|
22763
23643
|
exports.btcTarget = btcTarget;
|
|
@@ -22789,7 +23669,9 @@ exports.deserializeExitPackage = deserializeExitPackage;
|
|
|
22789
23669
|
exports.deserializeUtxo = deserializeUtxo;
|
|
22790
23670
|
exports.deserializeVtxo = deserializeVtxo;
|
|
22791
23671
|
exports.encodeArkContract = encodeArkContract;
|
|
23672
|
+
exports.exitObserverFor = exitObserverFor;
|
|
22792
23673
|
exports.extendVirtualCoinForContract = extendVirtualCoinForContract;
|
|
23674
|
+
exports.extractArkProviderUrl = extractArkProviderUrl;
|
|
22793
23675
|
exports.gateExclusion = gateExclusion;
|
|
22794
23676
|
exports.gatedContracts = gatedContracts;
|
|
22795
23677
|
exports.getAllByIndexValues = getAllByIndexValues;
|
|
@@ -22800,6 +23682,7 @@ exports.hasCandidates = hasCandidates;
|
|
|
22800
23682
|
exports.intentMatchesFilter = intentMatchesFilter;
|
|
22801
23683
|
exports.intentPageBounds = intentPageBounds;
|
|
22802
23684
|
exports.invoiceTarget = invoiceTarget;
|
|
23685
|
+
exports.isAddressAllocationCapable = isAddressAllocationCapable;
|
|
22803
23686
|
exports.isArkContract = isArkContract;
|
|
22804
23687
|
exports.isBatchSignable = isBatchSignable;
|
|
22805
23688
|
exports.isBtcAddress = isBtcAddress;
|
|
@@ -22827,6 +23710,7 @@ exports.makeHandle = makeHandle;
|
|
|
22827
23710
|
exports.matchServerCheckpoints = matchServerCheckpoints;
|
|
22828
23711
|
exports.mergeChainedTxType = mergeChainedTxType;
|
|
22829
23712
|
exports.migrateWalletRepository = migrateWalletRepository;
|
|
23713
|
+
exports.notifyExitObserved = notifyExitObserved;
|
|
22830
23714
|
exports.onchainRail = onchainRail;
|
|
22831
23715
|
exports.openDatabase = openDatabase;
|
|
22832
23716
|
exports.outpointExclusion = outpointExclusion;
|
|
@@ -22838,6 +23722,7 @@ exports.requiresMigration = requiresMigration;
|
|
|
22838
23722
|
exports.resolveBatchExpiryPolicy = resolveBatchExpiryPolicy;
|
|
22839
23723
|
exports.resolveCheckpointExitDelayPolicy = resolveCheckpointExitDelayPolicy;
|
|
22840
23724
|
exports.resolveDescriptorSigner = resolveDescriptorSigner;
|
|
23725
|
+
exports.resolvePrevTxs = resolvePrevTxs;
|
|
22841
23726
|
exports.resolveSendAmount = resolveSendAmount;
|
|
22842
23727
|
exports.rollbackMigration = rollbackMigration;
|
|
22843
23728
|
exports.saveVtxosForContract = saveVtxosForContract;
|
|
@@ -22861,5 +23746,6 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
|
22861
23746
|
exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
|
|
22862
23747
|
exports.waitForIncomingFunds = waitForIncomingFunds;
|
|
22863
23748
|
exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
|
|
22864
|
-
|
|
22865
|
-
//# sourceMappingURL=chunk-
|
|
23749
|
+
exports.withPrevTxs = withPrevTxs;
|
|
23750
|
+
//# sourceMappingURL=chunk-WCJVKFAP.cjs.map
|
|
23751
|
+
//# sourceMappingURL=chunk-WCJVKFAP.cjs.map
|