@arkade-os/sdk 0.4.33 → 0.4.34
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 +1 -1
- 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/{ark-DEsDMYGv.d.cts → ark-Dsv5Jq4E.d.cts} +65 -7
- package/dist/{ark-DEsDMYGv.d.ts → ark-Dsv5Jq4E.d.ts} +65 -7
- package/dist/{asyncStorageTaskQueue-CMrTYlKG.d.ts → asyncStorageTaskQueue-BH-zuth5.d.ts} +1 -1
- package/dist/{asyncStorageTaskQueue-D8T1VXEx.d.cts → asyncStorageTaskQueue-D92ch8yI.d.cts} +1 -1
- package/dist/{chunk-L6ZETTX3.js → chunk-5WDBHWX3.js} +4 -4
- package/dist/{chunk-L6ZETTX3.js.map → chunk-5WDBHWX3.js.map} +1 -1
- package/dist/{chunk-5CCRRL5S.cjs → chunk-CCLNFHJ5.cjs} +11 -11
- package/dist/{chunk-5CCRRL5S.cjs.map → chunk-CCLNFHJ5.cjs.map} +1 -1
- package/dist/{chunk-WMIPYZSB.cjs → chunk-CMPJR3HS.cjs} +42 -9
- package/dist/chunk-CMPJR3HS.cjs.map +1 -0
- package/dist/{chunk-AOJUURHM.js → chunk-CUSABEUQ.js} +141 -37
- package/dist/chunk-CUSABEUQ.js.map +1 -0
- package/dist/{chunk-SPDNHPM4.cjs → chunk-FSAXPBGP.cjs} +8 -8
- package/dist/{chunk-SPDNHPM4.cjs.map → chunk-FSAXPBGP.cjs.map} +1 -1
- package/dist/{chunk-E22HEKLN.js → chunk-FXFBPXV3.js} +3 -3
- package/dist/{chunk-E22HEKLN.js.map → chunk-FXFBPXV3.js.map} +1 -1
- package/dist/{chunk-GYSK5R57.cjs → chunk-GUTKJMSF.cjs} +164 -59
- package/dist/chunk-GUTKJMSF.cjs.map +1 -0
- package/dist/{chunk-DSS2GQUG.js → chunk-HFXEUW55.js} +575 -155
- package/dist/chunk-HFXEUW55.js.map +1 -0
- package/dist/{chunk-TU3LVAPX.js → chunk-OUVTG72A.js} +43 -11
- package/dist/chunk-OUVTG72A.js.map +1 -0
- package/dist/{chunk-BU3BU6XK.js → chunk-VVGD3JIP.js} +3 -3
- package/dist/{chunk-BU3BU6XK.js.map → chunk-VVGD3JIP.js.map} +1 -1
- package/dist/{chunk-7K3ROJF6.cjs → chunk-XCHBQVMK.cjs} +718 -298
- package/dist/chunk-XCHBQVMK.cjs.map +1 -0
- package/dist/{chunk-HAVA4XB7.cjs → chunk-ZS3OZHC7.cjs} +7 -7
- package/dist/{chunk-HAVA4XB7.cjs.map → chunk-ZS3OZHC7.cjs.map} +1 -1
- package/dist/contracts/handlers/index.cjs +7 -7
- 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-BJeBNP5a.d.cts → delegate-BaS5SCIW.d.cts} +1 -1
- package/dist/{delegate-EXN2mfkb.d.ts → delegate-Baz_hb83.d.ts} +1 -1
- package/dist/{index-BG2ooYKO.d.ts → index-FwXZveaX.d.ts} +22 -16
- package/dist/{index-DHjEeHEp.d.cts → index-lNZ6qaO3.d.cts} +22 -16
- package/dist/index.cjs +134 -130
- package/dist/index.d.cts +63 -14
- package/dist/index.d.ts +63 -14
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +13 -13
- package/dist/repositories/realm/index.d.cts +1 -1
- package/dist/repositories/realm/index.d.ts +1 -1
- package/dist/repositories/realm/index.js +4 -4
- package/dist/repositories/sqlite/index.cjs +13 -13
- package/dist/repositories/sqlite/index.d.cts +1 -1
- package/dist/repositories/sqlite/index.d.ts +1 -1
- package/dist/repositories/sqlite/index.js +4 -4
- package/dist/{taskRunner-B7lBU45X.d.ts → taskRunner-B1NUWyWR.d.ts} +1 -1
- package/dist/{taskRunner-pIGyarFG.d.cts → taskRunner-vFRA3F9b.d.cts} +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 +13 -13
- package/dist/wallet/expo/index.d.cts +5 -5
- package/dist/wallet/expo/index.d.ts +5 -5
- package/dist/wallet/expo/index.js +5 -5
- package/dist/{wallet-C4L_X0i6.d.ts → wallet-By9HIo0Q.d.cts} +160 -5
- package/dist/{wallet-D4Dll5Gu.d.cts → wallet-D6uoBLmS.d.ts} +160 -5
- 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 +4 -4
- package/dist/chunk-7K3ROJF6.cjs.map +0 -1
- package/dist/chunk-AOJUURHM.js.map +0 -1
- package/dist/chunk-DSS2GQUG.js.map +0 -1
- package/dist/chunk-GYSK5R57.cjs.map +0 -1
- package/dist/chunk-TU3LVAPX.js.map +0 -1
- package/dist/chunk-WMIPYZSB.cjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkFSAXPBGP_cjs = require('./chunk-FSAXPBGP.cjs');
|
|
4
|
+
var chunkGUTKJMSF_cjs = require('./chunk-GUTKJMSF.cjs');
|
|
5
|
+
var chunkCMPJR3HS_cjs = require('./chunk-CMPJR3HS.cjs');
|
|
6
6
|
var utils_js = require('@scure/btc-signer/utils.js');
|
|
7
7
|
var btcSigner = require('@scure/btc-signer');
|
|
8
8
|
var base = require('@scure/base');
|
|
@@ -181,7 +181,7 @@ var TreeSignerSession = class _TreeSignerSession {
|
|
|
181
181
|
noncesByPubkey.set(base.hex.encode(myPublicKey.subarray(1)), myNonce);
|
|
182
182
|
const tx = this.graph.find(txid);
|
|
183
183
|
if (!tx) throw new Error(`missing tx for txid ${txid}`);
|
|
184
|
-
const cosigners =
|
|
184
|
+
const cosigners = chunkFSAXPBGP_cjs.getArkPsbtFields(tx.root, 0, chunkFSAXPBGP_cjs.CosignerPublicKey).map(
|
|
185
185
|
(c) => base.hex.encode(c.key.subarray(1))
|
|
186
186
|
// xonly pubkey
|
|
187
187
|
);
|
|
@@ -233,7 +233,7 @@ var TreeSignerSession = class _TreeSignerSession {
|
|
|
233
233
|
if (!aggNonce) throw new Error("missing aggregate nonce");
|
|
234
234
|
const prevoutAmounts = [];
|
|
235
235
|
const prevoutScripts = [];
|
|
236
|
-
const cosigners =
|
|
236
|
+
const cosigners = chunkFSAXPBGP_cjs.getArkPsbtFields(g.root, 0, chunkFSAXPBGP_cjs.CosignerPublicKey).map((c) => c.key);
|
|
237
237
|
const { finalKey } = aggregateKeys(cosigners, true, {
|
|
238
238
|
taprootTweak: this.scriptRoot
|
|
239
239
|
});
|
|
@@ -411,7 +411,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
411
411
|
let network;
|
|
412
412
|
if ("descriptor" in opts && typeof opts.descriptor === "string") {
|
|
413
413
|
descriptor = opts.descriptor;
|
|
414
|
-
network =
|
|
414
|
+
network = chunkGUTKJMSF_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
415
415
|
} else {
|
|
416
416
|
network = opts.isMainnet ?? true ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
417
417
|
descriptor = descriptorsScure.scriptExpressions.trBIP32({
|
|
@@ -496,7 +496,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
496
496
|
* `StaticDescriptorProvider` for legacy single-key wallets.
|
|
497
497
|
*/
|
|
498
498
|
isOurs(descriptor) {
|
|
499
|
-
return
|
|
499
|
+
return chunkGUTKJMSF_cjs.descriptorIsOurs(descriptor, this.descriptor, utils_js.pubSchnorr(this.derivedKey));
|
|
500
500
|
}
|
|
501
501
|
/**
|
|
502
502
|
* Signs each request with the key derived from its descriptor.
|
|
@@ -533,7 +533,7 @@ var SeedIdentity = class _SeedIdentity {
|
|
|
533
533
|
}
|
|
534
534
|
// ── internal helpers ─────────────────────────────────────────────
|
|
535
535
|
derivePrivateKeyForDescriptor(descriptor) {
|
|
536
|
-
const network =
|
|
536
|
+
const network = chunkGUTKJMSF_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
537
537
|
const expansion = descriptorsScure.expand({ descriptor, network });
|
|
538
538
|
if (expansion.isRanged) {
|
|
539
539
|
throw new Error(
|
|
@@ -619,7 +619,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
|
|
|
619
619
|
*/
|
|
620
620
|
descriptor;
|
|
621
621
|
constructor(descriptor) {
|
|
622
|
-
const network =
|
|
622
|
+
const network = chunkGUTKJMSF_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
623
623
|
let expansion;
|
|
624
624
|
try {
|
|
625
625
|
expansion = descriptorsScure.expand({ descriptor, network, index: 0 });
|
|
@@ -669,7 +669,7 @@ var ReadonlyDescriptorIdentity = class _ReadonlyDescriptorIdentity {
|
|
|
669
669
|
* `StaticDescriptorProvider` for legacy single-key wallets.
|
|
670
670
|
*/
|
|
671
671
|
isOurs(descriptor) {
|
|
672
|
-
return
|
|
672
|
+
return chunkGUTKJMSF_cjs.descriptorIsOurs(descriptor, this.descriptor, this.indexZero.pubkey);
|
|
673
673
|
}
|
|
674
674
|
};
|
|
675
675
|
function serializeSeedOwnedSigningIdentity(identity) {
|
|
@@ -987,7 +987,7 @@ var RestDelegateProvider = class {
|
|
|
987
987
|
},
|
|
988
988
|
body: JSON.stringify({
|
|
989
989
|
intent: {
|
|
990
|
-
message:
|
|
990
|
+
message: chunkFSAXPBGP_cjs.Intent.encodeMessage(intent.message),
|
|
991
991
|
proof: intent.proof
|
|
992
992
|
},
|
|
993
993
|
forfeit_txs: forfeitTxs,
|
|
@@ -1031,10 +1031,10 @@ var ESPLORA_URL = {
|
|
|
1031
1031
|
testnet: "https://mempool.space/testnet/api",
|
|
1032
1032
|
signet: "https://mempool.signet.arkade.sh/api",
|
|
1033
1033
|
mutinynet: "https://mempool.mutinynet.arkade.sh/api",
|
|
1034
|
-
regtest: "http://localhost:3000"
|
|
1034
|
+
regtest: "http://localhost:3000/api"
|
|
1035
1035
|
};
|
|
1036
1036
|
var EsploraProvider = class {
|
|
1037
|
-
constructor(baseUrl = ESPLORA_URL[
|
|
1037
|
+
constructor(baseUrl = ESPLORA_URL[chunkCMPJR3HS_cjs.DEFAULT_NETWORK_NAME], opts) {
|
|
1038
1038
|
this.baseUrl = baseUrl;
|
|
1039
1039
|
this.pollingInterval = opts?.pollingInterval ?? 15e3;
|
|
1040
1040
|
this.forcePolling = opts?.forcePolling ?? false;
|
|
@@ -1050,6 +1050,9 @@ var EsploraProvider = class {
|
|
|
1050
1050
|
}
|
|
1051
1051
|
async getFeeRate() {
|
|
1052
1052
|
const response = await fetch(`${this.baseUrl}/fee-estimates`);
|
|
1053
|
+
if (response.status === 404) {
|
|
1054
|
+
return void 0;
|
|
1055
|
+
}
|
|
1053
1056
|
if (!response.ok) {
|
|
1054
1057
|
throw new Error(`Failed to fetch fee rate: ${response.statusText}`);
|
|
1055
1058
|
}
|
|
@@ -1175,7 +1178,7 @@ var EsploraProvider = class {
|
|
|
1175
1178
|
return stopFunc;
|
|
1176
1179
|
}
|
|
1177
1180
|
async getChainTip() {
|
|
1178
|
-
const tipBlocks = await fetch(`${this.baseUrl}/blocks
|
|
1181
|
+
const tipBlocks = await fetch(`${this.baseUrl}/blocks`);
|
|
1179
1182
|
if (!tipBlocks.ok) {
|
|
1180
1183
|
throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
|
|
1181
1184
|
}
|
|
@@ -1277,7 +1280,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
|
|
|
1277
1280
|
);
|
|
1278
1281
|
}
|
|
1279
1282
|
function buildForfeitTxWithOutput(inputs, output, txLocktime) {
|
|
1280
|
-
const tx = new
|
|
1283
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction({
|
|
1281
1284
|
version: 3,
|
|
1282
1285
|
lockTime: txLocktime
|
|
1283
1286
|
});
|
|
@@ -1353,7 +1356,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
1353
1356
|
if (previousScriptKey.length !== 32) {
|
|
1354
1357
|
throw new Error(`parent output ${childIndex} has invalid script`);
|
|
1355
1358
|
}
|
|
1356
|
-
const cosigners =
|
|
1359
|
+
const cosigners = chunkFSAXPBGP_cjs.getArkPsbtFields(child.root, 0, chunkFSAXPBGP_cjs.CosignerPublicKey);
|
|
1357
1360
|
if (cosigners.length === 0) {
|
|
1358
1361
|
throw ErrMissingCosignersPublicKeys;
|
|
1359
1362
|
}
|
|
@@ -1453,7 +1456,7 @@ var Extension = class _Extension {
|
|
|
1453
1456
|
`expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
|
|
1454
1457
|
);
|
|
1455
1458
|
}
|
|
1456
|
-
const reader = new
|
|
1459
|
+
const reader = new chunkFSAXPBGP_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
|
|
1457
1460
|
const packets = [];
|
|
1458
1461
|
while (reader.remaining() > 0) {
|
|
1459
1462
|
const packetType = reader.readByte();
|
|
@@ -1527,7 +1530,7 @@ var Extension = class _Extension {
|
|
|
1527
1530
|
*/
|
|
1528
1531
|
getAssetPacket() {
|
|
1529
1532
|
for (const p of this.packets) {
|
|
1530
|
-
if (p instanceof
|
|
1533
|
+
if (p instanceof chunkFSAXPBGP_cjs.Packet) {
|
|
1531
1534
|
return p;
|
|
1532
1535
|
}
|
|
1533
1536
|
}
|
|
@@ -1535,8 +1538,8 @@ var Extension = class _Extension {
|
|
|
1535
1538
|
}
|
|
1536
1539
|
};
|
|
1537
1540
|
function parsePacket(packetType, data) {
|
|
1538
|
-
if (packetType ===
|
|
1539
|
-
return
|
|
1541
|
+
if (packetType === chunkFSAXPBGP_cjs.Packet.PACKET_TYPE) {
|
|
1542
|
+
return chunkFSAXPBGP_cjs.Packet.fromBytes(data);
|
|
1540
1543
|
}
|
|
1541
1544
|
return new UnknownPacket(packetType, data);
|
|
1542
1545
|
}
|
|
@@ -1594,7 +1597,7 @@ function validateBatchRecipients(commitmentTx, vtxoTreeLeaves, recipients, netwo
|
|
|
1594
1597
|
for (const recipient of recipients) {
|
|
1595
1598
|
let arkAddress;
|
|
1596
1599
|
try {
|
|
1597
|
-
arkAddress =
|
|
1600
|
+
arkAddress = chunkCMPJR3HS_cjs.ArkAddress.decode(recipient.address);
|
|
1598
1601
|
} catch {
|
|
1599
1602
|
validateOnchainRecipient(commitmentTx, recipient, network, usedOnchainOutputs);
|
|
1600
1603
|
continue;
|
|
@@ -1727,7 +1730,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1727
1730
|
const existing = inputsByAssetId.get(asset.assetId);
|
|
1728
1731
|
inputsByAssetId.set(asset.assetId, [
|
|
1729
1732
|
...existing ?? [],
|
|
1730
|
-
|
|
1733
|
+
chunkFSAXPBGP_cjs.AssetInput.create(inputIndex, asset.amount)
|
|
1731
1734
|
]);
|
|
1732
1735
|
}
|
|
1733
1736
|
}
|
|
@@ -1739,7 +1742,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1739
1742
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
1740
1743
|
outputsByAssetId.set(asset.assetId, [
|
|
1741
1744
|
...existing ?? [],
|
|
1742
|
-
|
|
1745
|
+
chunkFSAXPBGP_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
1743
1746
|
]);
|
|
1744
1747
|
}
|
|
1745
1748
|
}
|
|
@@ -1750,7 +1753,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1750
1753
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
1751
1754
|
outputsByAssetId.set(asset.assetId, [
|
|
1752
1755
|
...existing ?? [],
|
|
1753
|
-
|
|
1756
|
+
chunkFSAXPBGP_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
1754
1757
|
]);
|
|
1755
1758
|
}
|
|
1756
1759
|
}
|
|
@@ -1759,11 +1762,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1759
1762
|
for (const assetIdStr of allAssetIds) {
|
|
1760
1763
|
const inputs = inputsByAssetId.get(assetIdStr);
|
|
1761
1764
|
const outputs = outputsByAssetId.get(assetIdStr);
|
|
1762
|
-
const assetId =
|
|
1763
|
-
const group =
|
|
1765
|
+
const assetId = chunkFSAXPBGP_cjs.AssetId.fromString(assetIdStr);
|
|
1766
|
+
const group = chunkFSAXPBGP_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
|
|
1764
1767
|
groups.push(group);
|
|
1765
1768
|
}
|
|
1766
|
-
return
|
|
1769
|
+
return chunkFSAXPBGP_cjs.Packet.create(groups);
|
|
1767
1770
|
}
|
|
1768
1771
|
function selectCoinsWithAsset(coins, assetId, requiredAmount) {
|
|
1769
1772
|
const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
|
|
@@ -1829,8 +1832,8 @@ function buildOffchainTx(inputs, outputs, serverUnrollScript) {
|
|
|
1829
1832
|
function buildVirtualTx(inputs, outputs) {
|
|
1830
1833
|
let lockTime = 0n;
|
|
1831
1834
|
for (const input of inputs) {
|
|
1832
|
-
const tapscript =
|
|
1833
|
-
if (
|
|
1835
|
+
const tapscript = chunkCMPJR3HS_cjs.decodeTapscript(chunkCMPJR3HS_cjs.scriptFromTapLeafScript(input.tapLeafScript));
|
|
1836
|
+
if (chunkCMPJR3HS_cjs.CLTVMultisigTapscript.is(tapscript)) {
|
|
1834
1837
|
if (lockTime !== 0n) {
|
|
1835
1838
|
if (isSeconds(lockTime) !== isSeconds(tapscript.params.absoluteTimelock)) {
|
|
1836
1839
|
throw new Error("cannot mix seconds and blocks locktime");
|
|
@@ -1841,7 +1844,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
1841
1844
|
}
|
|
1842
1845
|
}
|
|
1843
1846
|
}
|
|
1844
|
-
const tx = new
|
|
1847
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction({
|
|
1845
1848
|
version: 3,
|
|
1846
1849
|
lockTime: Number(lockTime)
|
|
1847
1850
|
});
|
|
@@ -1851,12 +1854,12 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
1851
1854
|
index: input.vout,
|
|
1852
1855
|
sequence: lockTime ? btcSigner.DEFAULT_SEQUENCE - 1 : void 0,
|
|
1853
1856
|
witnessUtxo: {
|
|
1854
|
-
script:
|
|
1857
|
+
script: chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).pkScript,
|
|
1855
1858
|
amount: BigInt(input.value)
|
|
1856
1859
|
},
|
|
1857
1860
|
tapLeafScript: [input.tapLeafScript]
|
|
1858
1861
|
});
|
|
1859
|
-
|
|
1862
|
+
chunkFSAXPBGP_cjs.setArkPsbtField(tx, i, chunkFSAXPBGP_cjs.VtxoTaprootTree, input.tapTree);
|
|
1860
1863
|
}
|
|
1861
1864
|
for (const output of outputs) {
|
|
1862
1865
|
tx.addOutput(output);
|
|
@@ -1865,8 +1868,8 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
1865
1868
|
return tx;
|
|
1866
1869
|
}
|
|
1867
1870
|
function buildCheckpointTx(vtxo, serverUnrollScript) {
|
|
1868
|
-
const collaborativeClosure =
|
|
1869
|
-
const checkpointVtxoScript = new
|
|
1871
|
+
const collaborativeClosure = chunkCMPJR3HS_cjs.decodeTapscript(chunkCMPJR3HS_cjs.scriptFromTapLeafScript(vtxo.tapLeafScript));
|
|
1872
|
+
const checkpointVtxoScript = new chunkCMPJR3HS_cjs.VtxoScript([
|
|
1870
1873
|
serverUnrollScript.script,
|
|
1871
1874
|
collaborativeClosure.script
|
|
1872
1875
|
]);
|
|
@@ -2010,7 +2013,7 @@ function combineTapscriptSigs(signedTx, originalTx) {
|
|
|
2010
2013
|
}
|
|
2011
2014
|
function isValidArkAddress(address) {
|
|
2012
2015
|
try {
|
|
2013
|
-
|
|
2016
|
+
chunkCMPJR3HS_cjs.ArkAddress.decode(address);
|
|
2014
2017
|
return true;
|
|
2015
2018
|
} catch (e) {
|
|
2016
2019
|
return false;
|
|
@@ -2280,16 +2283,16 @@ var FALLBACK_WALLET_DUST_AMOUNT = 330n;
|
|
|
2280
2283
|
function getDustAmount(wallet) {
|
|
2281
2284
|
return "dustAmount" in wallet ? wallet.dustAmount : FALLBACK_WALLET_DUST_AMOUNT;
|
|
2282
2285
|
}
|
|
2283
|
-
function
|
|
2286
|
+
function extendCoinWithTapscript(boardingTapscript, utxo) {
|
|
2284
2287
|
return {
|
|
2285
2288
|
...utxo,
|
|
2286
|
-
forfeitTapLeafScript:
|
|
2287
|
-
intentTapLeafScript:
|
|
2288
|
-
tapTree:
|
|
2289
|
+
forfeitTapLeafScript: boardingTapscript.forfeit(),
|
|
2290
|
+
intentTapLeafScript: boardingTapscript.forfeit(),
|
|
2291
|
+
tapTree: boardingTapscript.encode()
|
|
2289
2292
|
};
|
|
2290
2293
|
}
|
|
2291
2294
|
function deriveContractTapscripts(contract) {
|
|
2292
|
-
const handler =
|
|
2295
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(contract.type);
|
|
2293
2296
|
if (!handler) {
|
|
2294
2297
|
throw new Error(`No handler for contract type '${contract.type}'`);
|
|
2295
2298
|
}
|
|
@@ -2359,7 +2362,7 @@ function validateRecipients(recipients, dustAmount) {
|
|
|
2359
2362
|
for (const recipient of recipients) {
|
|
2360
2363
|
let address;
|
|
2361
2364
|
try {
|
|
2362
|
-
address =
|
|
2365
|
+
address = chunkCMPJR3HS_cjs.ArkAddress.decode(recipient.address);
|
|
2363
2366
|
} catch (e) {
|
|
2364
2367
|
throw new Error(`Invalid Arkade address: ${recipient.address}`);
|
|
2365
2368
|
}
|
|
@@ -2379,12 +2382,12 @@ function validateRecipients(recipients, dustAmount) {
|
|
|
2379
2382
|
|
|
2380
2383
|
// src/wallet/vtxo-manager.ts
|
|
2381
2384
|
function isSweepCapable(wallet) {
|
|
2382
|
-
return "boardingTapscript" in wallet && "onchainProvider" in wallet && "arkProvider" in wallet && "network" in wallet;
|
|
2385
|
+
return "boardingTapscript" in wallet && "onchainProvider" in wallet && "arkProvider" in wallet && "network" in wallet && "signOnchainBoardingTx" in wallet;
|
|
2383
2386
|
}
|
|
2384
2387
|
function assertSweepCapable(wallet) {
|
|
2385
2388
|
if (!isSweepCapable(wallet)) {
|
|
2386
2389
|
throw new Error(
|
|
2387
|
-
"Boarding UTXO sweep requires a Wallet instance with boardingTapscript, onchainProvider, arkProvider, and
|
|
2390
|
+
"Boarding UTXO sweep requires a Wallet instance with boardingTapscript, onchainProvider, arkProvider, network, and signOnchainBoardingTx"
|
|
2388
2391
|
);
|
|
2389
2392
|
}
|
|
2390
2393
|
}
|
|
@@ -2400,6 +2403,21 @@ async function runWithCrossInstanceLock(name, fn) {
|
|
|
2400
2403
|
await fn();
|
|
2401
2404
|
});
|
|
2402
2405
|
}
|
|
2406
|
+
var MAX_VTXOS_PER_SETTLEMENT = 50;
|
|
2407
|
+
function byValueDescending(vtxos) {
|
|
2408
|
+
return [...vtxos].sort((a, b) => b.value - a.value);
|
|
2409
|
+
}
|
|
2410
|
+
function byExpiryAscending(vtxos) {
|
|
2411
|
+
const expiryKey = (vtxo) => {
|
|
2412
|
+
if (isRecoverable(vtxo)) return -Infinity;
|
|
2413
|
+
const batchExpiry = vtxo.virtualStatus.batchExpiry;
|
|
2414
|
+
if (isExpired(vtxo)) return batchExpiry ?? -Infinity;
|
|
2415
|
+
if (!batchExpiry) return Infinity;
|
|
2416
|
+
if (new Date(batchExpiry).getFullYear() < 2025) return Infinity;
|
|
2417
|
+
return batchExpiry;
|
|
2418
|
+
};
|
|
2419
|
+
return [...vtxos].sort((a, b) => expiryKey(a) - expiryKey(b));
|
|
2420
|
+
}
|
|
2403
2421
|
var DEFAULT_THRESHOLD_SECONDS = 259200;
|
|
2404
2422
|
var DEFAULT_THRESHOLD_MS = DEFAULT_THRESHOLD_SECONDS * 1e3;
|
|
2405
2423
|
var DEFAULT_RENEWAL_CONFIG = {
|
|
@@ -2559,10 +2577,20 @@ var VtxoManager = class _VtxoManager {
|
|
|
2559
2577
|
withUnrolled: false
|
|
2560
2578
|
});
|
|
2561
2579
|
const dustAmount = getDustAmount(this.wallet);
|
|
2562
|
-
|
|
2580
|
+
let { vtxosToRecover, totalAmount } = getRecoverableWithSubdust(allVtxos, dustAmount);
|
|
2563
2581
|
if (vtxosToRecover.length === 0) {
|
|
2564
2582
|
throw new Error("No recoverable VTXOs found");
|
|
2565
2583
|
}
|
|
2584
|
+
if (vtxosToRecover.length > MAX_VTXOS_PER_SETTLEMENT) {
|
|
2585
|
+
const recoverableCount = vtxosToRecover.length;
|
|
2586
|
+
const capped = byValueDescending(vtxosToRecover).slice(0, MAX_VTXOS_PER_SETTLEMENT);
|
|
2587
|
+
({ vtxosToRecover, totalAmount } = getRecoverableWithSubdust(capped, dustAmount));
|
|
2588
|
+
if (vtxosToRecover.length === 0) {
|
|
2589
|
+
throw new Error(
|
|
2590
|
+
`Capped recovery batch (highest-value ${MAX_VTXOS_PER_SETTLEMENT} of ${recoverableCount} recoverable VTXOs) is below the dust threshold ${dustAmount}`
|
|
2591
|
+
);
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2566
2594
|
const arkAddress = await this.wallet.getAddress();
|
|
2567
2595
|
return this.wallet.settle(
|
|
2568
2596
|
{
|
|
@@ -2712,6 +2740,9 @@ var VtxoManager = class _VtxoManager {
|
|
|
2712
2740
|
if (vtxos.length === 0) {
|
|
2713
2741
|
throw new Error("No VTXOs available to renew");
|
|
2714
2742
|
}
|
|
2743
|
+
if (vtxos.length > MAX_VTXOS_PER_SETTLEMENT) {
|
|
2744
|
+
vtxos = byExpiryAscending(vtxos).slice(0, MAX_VTXOS_PER_SETTLEMENT);
|
|
2745
|
+
}
|
|
2715
2746
|
const totalAmount = vtxos.reduce((sum, vtxo) => sum + vtxo.value, 0);
|
|
2716
2747
|
const dustAmount = getDustAmount(this.wallet);
|
|
2717
2748
|
if (BigInt(totalAmount) < dustAmount) {
|
|
@@ -2819,7 +2850,6 @@ var VtxoManager = class _VtxoManager {
|
|
|
2819
2850
|
const boardingAddress = await this.wallet.getBoardingAddress();
|
|
2820
2851
|
const feeRate = await this.getOnchainProvider().getFeeRate() ?? 1;
|
|
2821
2852
|
const exitTapLeafScript = this.getBoardingExitLeaf();
|
|
2822
|
-
const sequence = chunkWMIPYZSB_cjs.getSequence(exitTapLeafScript);
|
|
2823
2853
|
const leafScript = exitTapLeafScript[1];
|
|
2824
2854
|
const leafScriptSize = leafScript.length - 1;
|
|
2825
2855
|
const controlBlockSize = exitTapLeafScript[0].merklePath.length * 32;
|
|
@@ -2838,21 +2868,30 @@ var VtxoManager = class _VtxoManager {
|
|
|
2838
2868
|
`Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
|
|
2839
2869
|
);
|
|
2840
2870
|
}
|
|
2841
|
-
const tx = new
|
|
2871
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction();
|
|
2842
2872
|
for (const utxo of expiredUtxos) {
|
|
2873
|
+
const utxoScript = chunkCMPJR3HS_cjs.VtxoScript.decode(utxo.tapTree);
|
|
2874
|
+
const utxoExitLeaf = utxoScript.leaves.find(
|
|
2875
|
+
(leaf) => chunkCMPJR3HS_cjs.CSVMultisigTapscript.isScriptValid(chunkCMPJR3HS_cjs.scriptFromTapLeafScript(leaf)) === true
|
|
2876
|
+
);
|
|
2877
|
+
if (!utxoExitLeaf) {
|
|
2878
|
+
throw new Error(
|
|
2879
|
+
`Boarding sweep: no CSV exit leaf for UTXO ${utxo.txid}:${utxo.vout}`
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2843
2882
|
tx.addInput({
|
|
2844
2883
|
txid: utxo.txid,
|
|
2845
2884
|
index: utxo.vout,
|
|
2846
2885
|
witnessUtxo: {
|
|
2847
|
-
script:
|
|
2886
|
+
script: utxoScript.pkScript,
|
|
2848
2887
|
amount: BigInt(utxo.value)
|
|
2849
2888
|
},
|
|
2850
|
-
tapLeafScript: [
|
|
2851
|
-
sequence
|
|
2889
|
+
tapLeafScript: [utxoExitLeaf],
|
|
2890
|
+
sequence: chunkCMPJR3HS_cjs.getSequence(utxoExitLeaf)
|
|
2852
2891
|
});
|
|
2853
2892
|
}
|
|
2854
2893
|
tx.addOutputAddress(boardingAddress, outputAmount, this.getNetwork());
|
|
2855
|
-
const signedTx = await this.
|
|
2894
|
+
const signedTx = await this.getSweepWallet().signOnchainBoardingTx(tx);
|
|
2856
2895
|
signedTx.finalize();
|
|
2857
2896
|
const txid = await this.getOnchainProvider().broadcastTransaction(signedTx.hex);
|
|
2858
2897
|
for (const u of expiredUtxos) {
|
|
@@ -2870,7 +2909,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
2870
2909
|
/** Decodes the boarding tapscript exit path to extract the CSV timelock. */
|
|
2871
2910
|
getBoardingTimelock() {
|
|
2872
2911
|
const wallet = this.getSweepWallet();
|
|
2873
|
-
const exitScript =
|
|
2912
|
+
const exitScript = chunkCMPJR3HS_cjs.CSVMultisigTapscript.decode(
|
|
2874
2913
|
base.hex.decode(wallet.boardingTapscript.exitScript)
|
|
2875
2914
|
);
|
|
2876
2915
|
return exitScript.params.timelock;
|
|
@@ -2879,10 +2918,6 @@ var VtxoManager = class _VtxoManager {
|
|
|
2879
2918
|
getBoardingExitLeaf() {
|
|
2880
2919
|
return this.getSweepWallet().boardingTapscript.exit();
|
|
2881
2920
|
}
|
|
2882
|
-
/** Returns the pkScript (output script) of the boarding tapscript. */
|
|
2883
|
-
getBoardingOutputScript() {
|
|
2884
|
-
return this.getSweepWallet().boardingTapscript.pkScript;
|
|
2885
|
-
}
|
|
2886
2921
|
/** Returns the onchain provider for fee estimation and broadcasting. */
|
|
2887
2922
|
getOnchainProvider() {
|
|
2888
2923
|
return this.getSweepWallet().onchainProvider;
|
|
@@ -2895,10 +2930,6 @@ var VtxoManager = class _VtxoManager {
|
|
|
2895
2930
|
getNetwork() {
|
|
2896
2931
|
return this.getSweepWallet().network;
|
|
2897
2932
|
}
|
|
2898
|
-
/** Returns the wallet's identity for transaction signing. */
|
|
2899
|
-
getIdentity() {
|
|
2900
|
-
return this.wallet.identity;
|
|
2901
|
-
}
|
|
2902
2933
|
async initializeSubscription() {
|
|
2903
2934
|
if (this.settlementConfig === false) {
|
|
2904
2935
|
return void 0;
|
|
@@ -2999,7 +3030,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
2999
3030
|
* or doesn't carry the metadata.
|
|
3000
3031
|
*/
|
|
3001
3032
|
extractSpentOutpoint(error) {
|
|
3002
|
-
const ark =
|
|
3033
|
+
const ark = chunkFSAXPBGP_cjs.maybeArkError(error);
|
|
3003
3034
|
if (!ark || ark.name !== "VTXO_ALREADY_SPENT") return void 0;
|
|
3004
3035
|
const raw = ark.metadata?.vtxo_outpoint;
|
|
3005
3036
|
if (typeof raw !== "string") return void 0;
|
|
@@ -3179,7 +3210,10 @@ var VtxoManager = class _VtxoManager {
|
|
|
3179
3210
|
totalAmount += BigInt(u.value) - BigInt(inputFee.satoshis);
|
|
3180
3211
|
}
|
|
3181
3212
|
const filteredVtxos = [];
|
|
3182
|
-
for (const v of expiringVtxos) {
|
|
3213
|
+
for (const v of byExpiryAscending(expiringVtxos)) {
|
|
3214
|
+
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
3215
|
+
break;
|
|
3216
|
+
}
|
|
3183
3217
|
const inputFee = estimator.evalOffchainInput({
|
|
3184
3218
|
amount: BigInt(v.value),
|
|
3185
3219
|
type: v.virtualStatus.state === "swept" ? "recoverable" : "vtxo",
|
|
@@ -3199,7 +3233,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3199
3233
|
const arkAddress = await this.wallet.getAddress();
|
|
3200
3234
|
const outputFee = estimator.evalOffchainOutput({
|
|
3201
3235
|
amount: totalAmount,
|
|
3202
|
-
script: base.hex.encode(
|
|
3236
|
+
script: base.hex.encode(chunkCMPJR3HS_cjs.ArkAddress.decode(arkAddress).pkScript)
|
|
3203
3237
|
});
|
|
3204
3238
|
totalAmount -= BigInt(outputFee.satoshis);
|
|
3205
3239
|
if (totalAmount < dustAmount) return;
|
|
@@ -3280,7 +3314,7 @@ var ArkNote = class _ArkNote {
|
|
|
3280
3314
|
this.value = value;
|
|
3281
3315
|
this.HRP = HRP;
|
|
3282
3316
|
const preimageHash = utils_js.sha256(this.preimage);
|
|
3283
|
-
this.vtxoScript = new
|
|
3317
|
+
this.vtxoScript = new chunkCMPJR3HS_cjs.VtxoScript([noteTapscript(preimageHash)]);
|
|
3284
3318
|
const leaf = this.vtxoScript.leaves[0];
|
|
3285
3319
|
this.txid = base.hex.encode(new Uint8Array(preimageHash).reverse());
|
|
3286
3320
|
this.tapTree = this.vtxoScript.encode();
|
|
@@ -3894,7 +3928,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
3894
3928
|
const virtualCoins = await this.wallet.getVtxos({
|
|
3895
3929
|
withRecoverable: false
|
|
3896
3930
|
});
|
|
3897
|
-
const controlAssetRef = params.controlAssetId ?
|
|
3931
|
+
const controlAssetRef = params.controlAssetId ? chunkFSAXPBGP_cjs.AssetRef.fromId(chunkFSAXPBGP_cjs.AssetId.fromString(params.controlAssetId)) : null;
|
|
3898
3932
|
const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
|
|
3899
3933
|
let totalBtcSelected = 0n;
|
|
3900
3934
|
const assetChanges = /* @__PURE__ */ new Map();
|
|
@@ -3907,8 +3941,8 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
3907
3941
|
}
|
|
3908
3942
|
}
|
|
3909
3943
|
const groups = [];
|
|
3910
|
-
const issuedAssetOutput =
|
|
3911
|
-
const issuedAssetGroup =
|
|
3944
|
+
const issuedAssetOutput = chunkFSAXPBGP_cjs.AssetOutput.create(0, params.amount);
|
|
3945
|
+
const issuedAssetGroup = chunkFSAXPBGP_cjs.AssetGroup.create(
|
|
3912
3946
|
null,
|
|
3913
3947
|
controlAssetRef,
|
|
3914
3948
|
[],
|
|
@@ -3923,28 +3957,28 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
3923
3957
|
for (const [inputIndex, assets] of assetInputs) {
|
|
3924
3958
|
for (const asset of assets) {
|
|
3925
3959
|
if (asset.assetId !== assetId) continue;
|
|
3926
|
-
changeInputs.push(
|
|
3960
|
+
changeInputs.push(chunkFSAXPBGP_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
3927
3961
|
}
|
|
3928
3962
|
}
|
|
3929
3963
|
groups.push(
|
|
3930
|
-
|
|
3931
|
-
|
|
3964
|
+
chunkFSAXPBGP_cjs.AssetGroup.create(
|
|
3965
|
+
chunkFSAXPBGP_cjs.AssetId.fromString(assetId),
|
|
3932
3966
|
null,
|
|
3933
3967
|
changeInputs,
|
|
3934
|
-
[
|
|
3968
|
+
[chunkFSAXPBGP_cjs.AssetOutput.create(0, amount)],
|
|
3935
3969
|
[]
|
|
3936
3970
|
)
|
|
3937
3971
|
);
|
|
3938
3972
|
}
|
|
3939
3973
|
}
|
|
3940
3974
|
const address = await this.wallet.getAddress();
|
|
3941
|
-
const outputAddress =
|
|
3975
|
+
const outputAddress = chunkCMPJR3HS_cjs.ArkAddress.decode(address);
|
|
3942
3976
|
const outputs = [
|
|
3943
3977
|
{
|
|
3944
3978
|
script: outputAddress.pkScript,
|
|
3945
3979
|
amount: BigInt(totalBtcSelected)
|
|
3946
3980
|
},
|
|
3947
|
-
Extension.create([
|
|
3981
|
+
Extension.create([chunkFSAXPBGP_cjs.Packet.create(groups)]).txOut()
|
|
3948
3982
|
];
|
|
3949
3983
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
|
|
3950
3984
|
coinSelection.inputs,
|
|
@@ -3952,7 +3986,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
3952
3986
|
);
|
|
3953
3987
|
return {
|
|
3954
3988
|
arkTxId: arkTxid,
|
|
3955
|
-
assetId:
|
|
3989
|
+
assetId: chunkFSAXPBGP_cjs.AssetId.create(arkTxid, 0).toString()
|
|
3956
3990
|
};
|
|
3957
3991
|
}
|
|
3958
3992
|
/**
|
|
@@ -4024,16 +4058,16 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4024
4058
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4025
4059
|
for (const asset of assets) {
|
|
4026
4060
|
if (asset.assetId !== params.assetId) continue;
|
|
4027
|
-
reissueInputs.push(
|
|
4061
|
+
reissueInputs.push(chunkFSAXPBGP_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4028
4062
|
}
|
|
4029
4063
|
}
|
|
4030
4064
|
const totalAssetAmount = assetToReissueAmount + params.amount;
|
|
4031
|
-
const reissueAssetIdObj =
|
|
4032
|
-
const reissueAssetGroup =
|
|
4065
|
+
const reissueAssetIdObj = chunkFSAXPBGP_cjs.AssetId.fromString(params.assetId);
|
|
4066
|
+
const reissueAssetGroup = chunkFSAXPBGP_cjs.AssetGroup.create(
|
|
4033
4067
|
reissueAssetIdObj,
|
|
4034
4068
|
null,
|
|
4035
4069
|
reissueInputs,
|
|
4036
|
-
[
|
|
4070
|
+
[chunkFSAXPBGP_cjs.AssetOutput.create(0, totalAssetAmount)],
|
|
4037
4071
|
[]
|
|
4038
4072
|
);
|
|
4039
4073
|
const groups = [reissueAssetGroup];
|
|
@@ -4042,27 +4076,27 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4042
4076
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4043
4077
|
for (const asset of assets) {
|
|
4044
4078
|
if (asset.assetId !== assetId) continue;
|
|
4045
|
-
changeInputs.push(
|
|
4079
|
+
changeInputs.push(chunkFSAXPBGP_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4046
4080
|
}
|
|
4047
4081
|
}
|
|
4048
4082
|
groups.push(
|
|
4049
|
-
|
|
4050
|
-
|
|
4083
|
+
chunkFSAXPBGP_cjs.AssetGroup.create(
|
|
4084
|
+
chunkFSAXPBGP_cjs.AssetId.fromString(assetId),
|
|
4051
4085
|
null,
|
|
4052
4086
|
changeInputs,
|
|
4053
|
-
[
|
|
4087
|
+
[chunkFSAXPBGP_cjs.AssetOutput.create(0, amount)],
|
|
4054
4088
|
[]
|
|
4055
4089
|
)
|
|
4056
4090
|
);
|
|
4057
4091
|
}
|
|
4058
4092
|
const address = await this.wallet.getAddress();
|
|
4059
|
-
const outputAddress =
|
|
4093
|
+
const outputAddress = chunkCMPJR3HS_cjs.ArkAddress.decode(address);
|
|
4060
4094
|
const outputs = [
|
|
4061
4095
|
{
|
|
4062
4096
|
script: outputAddress.pkScript,
|
|
4063
4097
|
amount: BigInt(totalBtcSelected)
|
|
4064
4098
|
},
|
|
4065
|
-
Extension.create([
|
|
4099
|
+
Extension.create([chunkFSAXPBGP_cjs.Packet.create(groups)]).txOut()
|
|
4066
4100
|
];
|
|
4067
4101
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
4068
4102
|
return arkTxid;
|
|
@@ -4129,27 +4163,27 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4129
4163
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4130
4164
|
for (const asset of assets) {
|
|
4131
4165
|
if (asset.assetId !== assetId) continue;
|
|
4132
|
-
changeInputs.push(
|
|
4166
|
+
changeInputs.push(chunkFSAXPBGP_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4133
4167
|
}
|
|
4134
4168
|
}
|
|
4135
4169
|
groups.push(
|
|
4136
|
-
|
|
4137
|
-
|
|
4170
|
+
chunkFSAXPBGP_cjs.AssetGroup.create(
|
|
4171
|
+
chunkFSAXPBGP_cjs.AssetId.fromString(assetId),
|
|
4138
4172
|
null,
|
|
4139
4173
|
changeInputs,
|
|
4140
|
-
amount > 0n ? [
|
|
4174
|
+
amount > 0n ? [chunkFSAXPBGP_cjs.AssetOutput.create(0, amount)] : [],
|
|
4141
4175
|
[]
|
|
4142
4176
|
)
|
|
4143
4177
|
);
|
|
4144
4178
|
}
|
|
4145
4179
|
const address = await this.wallet.getAddress();
|
|
4146
|
-
const outputAddress =
|
|
4180
|
+
const outputAddress = chunkCMPJR3HS_cjs.ArkAddress.decode(address);
|
|
4147
4181
|
const outputs = [
|
|
4148
4182
|
{
|
|
4149
4183
|
script: outputAddress.pkScript,
|
|
4150
4184
|
amount: BigInt(totalBtcSelected)
|
|
4151
4185
|
},
|
|
4152
|
-
Extension.create([
|
|
4186
|
+
Extension.create([chunkFSAXPBGP_cjs.Packet.create(groups)]).txOut()
|
|
4153
4187
|
];
|
|
4154
4188
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
4155
4189
|
return arkTxid;
|
|
@@ -4174,7 +4208,7 @@ function castMetadata(metadata) {
|
|
|
4174
4208
|
} else {
|
|
4175
4209
|
throw new Error("Invalid metadata value type");
|
|
4176
4210
|
}
|
|
4177
|
-
md.push(
|
|
4211
|
+
md.push(chunkFSAXPBGP_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
|
|
4178
4212
|
}
|
|
4179
4213
|
return md;
|
|
4180
4214
|
}
|
|
@@ -4192,7 +4226,7 @@ var DelegateManagerImpl = class {
|
|
|
4192
4226
|
if (vtxos.length === 0) {
|
|
4193
4227
|
return { delegated: [], failed: [] };
|
|
4194
4228
|
}
|
|
4195
|
-
const destinationScript =
|
|
4229
|
+
const destinationScript = chunkCMPJR3HS_cjs.ArkAddress.decode(destination).pkScript;
|
|
4196
4230
|
const arkInfo = await this.arkInfoProvider.getInfo();
|
|
4197
4231
|
const delegateInfo = await this.delegateProvider.getDelegateInfo();
|
|
4198
4232
|
const eligible = vtxos.filter(
|
|
@@ -4340,7 +4374,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
4340
4374
|
const delegateFee = BigInt(Number(fee));
|
|
4341
4375
|
if (delegateFee > 0n) {
|
|
4342
4376
|
outputs.push({
|
|
4343
|
-
script:
|
|
4377
|
+
script: chunkCMPJR3HS_cjs.ArkAddress.decode(delegateAddress).pkScript,
|
|
4344
4378
|
amount: delegateFee
|
|
4345
4379
|
});
|
|
4346
4380
|
}
|
|
@@ -4373,7 +4407,7 @@ async function delegate(identity, delegateProvider, arkInfo, delegateInfo, vtxos
|
|
|
4373
4407
|
destinationScript
|
|
4374
4408
|
);
|
|
4375
4409
|
const forfeitOutputScript = btcSigner.OutScript.encode(
|
|
4376
|
-
btcSigner.Address(
|
|
4410
|
+
btcSigner.Address(chunkCMPJR3HS_cjs.getNetwork(network)).decode(forfeitAddress)
|
|
4377
4411
|
);
|
|
4378
4412
|
const forfeits = await Promise.all(
|
|
4379
4413
|
vtxos.filter((v) => !isRecoverable(v)).map(async (coin) => {
|
|
@@ -4401,7 +4435,7 @@ async function makeDelegateForfeitTx(input, connectorAmount, delegatePubkey, for
|
|
|
4401
4435
|
index: input.vout,
|
|
4402
4436
|
witnessUtxo: {
|
|
4403
4437
|
amount: BigInt(input.value),
|
|
4404
|
-
script:
|
|
4438
|
+
script: chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
4405
4439
|
},
|
|
4406
4440
|
sighashType: btcSigner.SigHash.ALL_ANYONECANPAY,
|
|
4407
4441
|
tapLeafScript: [delegateTapLeaf]
|
|
@@ -4459,7 +4493,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
|
|
|
4459
4493
|
expire_at: 0,
|
|
4460
4494
|
cosigners_public_keys: cosignerPubKeys
|
|
4461
4495
|
};
|
|
4462
|
-
const proof =
|
|
4496
|
+
const proof = chunkFSAXPBGP_cjs.Intent.create(message, coins, outputs);
|
|
4463
4497
|
const signedProof = await identity.sign(proof);
|
|
4464
4498
|
return {
|
|
4465
4499
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -4477,10 +4511,10 @@ function getDayTimestamp(timestamp) {
|
|
|
4477
4511
|
function findDelegateTapLeaf(vtxo, delegatePubkey) {
|
|
4478
4512
|
if (!vtxo.tapTree) return void 0;
|
|
4479
4513
|
const pk = delegatePubkey.length === 66 ? delegatePubkey.slice(2) : delegatePubkey;
|
|
4480
|
-
const vtxoScript =
|
|
4514
|
+
const vtxoScript = chunkCMPJR3HS_cjs.VtxoScript.decode(vtxo.tapTree);
|
|
4481
4515
|
return vtxoScript.leaves.find((tapLeaf) => {
|
|
4482
|
-
const arkTapscript =
|
|
4483
|
-
if (!
|
|
4516
|
+
const arkTapscript = chunkCMPJR3HS_cjs.decodeTapscript(chunkCMPJR3HS_cjs.scriptFromTapLeafScript(tapLeaf));
|
|
4517
|
+
if (!chunkCMPJR3HS_cjs.MultisigTapscript.is(arkTapscript)) return false;
|
|
4484
4518
|
return arkTapscript.params.pubkeys.map(base.hex.encode).includes(pk);
|
|
4485
4519
|
});
|
|
4486
4520
|
}
|
|
@@ -4684,7 +4718,7 @@ var InMemoryContractRepository = class {
|
|
|
4684
4718
|
}
|
|
4685
4719
|
};
|
|
4686
4720
|
function scriptFromArkAddress(address) {
|
|
4687
|
-
return base.hex.encode(
|
|
4721
|
+
return base.hex.encode(chunkCMPJR3HS_cjs.ArkAddress.decode(address).pkScript);
|
|
4688
4722
|
}
|
|
4689
4723
|
|
|
4690
4724
|
// src/repositories/indexedDB/schema.ts
|
|
@@ -6199,7 +6233,7 @@ var ContractWatcher = class {
|
|
|
6199
6233
|
this.connectionState = "connected";
|
|
6200
6234
|
this.reconnectAttempts = 0;
|
|
6201
6235
|
this.listenLoop().catch((e) => {
|
|
6202
|
-
if (
|
|
6236
|
+
if (chunkFSAXPBGP_cjs.isEventSourceError(e)) {
|
|
6203
6237
|
console.debug("ContractWatcher subscription disconnected; reconnecting");
|
|
6204
6238
|
} else {
|
|
6205
6239
|
console.error(e);
|
|
@@ -6537,8 +6571,11 @@ function cursorCutoff(requestStartedAt) {
|
|
|
6537
6571
|
}
|
|
6538
6572
|
|
|
6539
6573
|
// src/contracts/contractManager.ts
|
|
6540
|
-
|
|
6574
|
+
function areCoalescibleContractTypes(a, b) {
|
|
6575
|
+
return a === "default" && b === "boarding" || a === "boarding" && b === "default";
|
|
6576
|
+
}
|
|
6541
6577
|
var SCAN_MAX_INDEX = 1e4;
|
|
6578
|
+
var DEFAULT_SCAN_BATCH = 10;
|
|
6542
6579
|
var ContractManager = class _ContractManager {
|
|
6543
6580
|
config;
|
|
6544
6581
|
watcher;
|
|
@@ -6639,7 +6676,7 @@ var ContractManager = class _ContractManager {
|
|
|
6639
6676
|
* `persisted` is `true`.
|
|
6640
6677
|
*/
|
|
6641
6678
|
async upsertContract(params) {
|
|
6642
|
-
const handler =
|
|
6679
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(params.type);
|
|
6643
6680
|
if (!handler) {
|
|
6644
6681
|
throw new Error(`No handler registered for contract type '${params.type}'`);
|
|
6645
6682
|
}
|
|
@@ -6662,8 +6699,11 @@ var ContractManager = class _ContractManager {
|
|
|
6662
6699
|
const [existing] = await this.getContracts({ script: params.script });
|
|
6663
6700
|
if (existing) {
|
|
6664
6701
|
if (existing.type === params.type) return { contract: existing, persisted: false };
|
|
6702
|
+
if (areCoalescibleContractTypes(existing.type, params.type)) {
|
|
6703
|
+
return { contract: existing, persisted: false };
|
|
6704
|
+
}
|
|
6665
6705
|
throw new Error(
|
|
6666
|
-
`Contract with script ${params.script} already exists with
|
|
6706
|
+
`Contract with script ${params.script} already exists with type ${existing.type}.`
|
|
6667
6707
|
);
|
|
6668
6708
|
}
|
|
6669
6709
|
const contract = {
|
|
@@ -6692,6 +6732,19 @@ var ContractManager = class _ContractManager {
|
|
|
6692
6732
|
* other handler hit it).
|
|
6693
6733
|
* - `persistAndWatchContract` rejecting is operational/fatal and
|
|
6694
6734
|
* propagates (only `discoverAt` is guarded).
|
|
6735
|
+
* - Within an index the handler probes run concurrently (independent
|
|
6736
|
+
* network reads); their hits are persisted sequentially in
|
|
6737
|
+
* `discoverables` order to preserve the first-wins collision tie-break.
|
|
6738
|
+
* - Indices are probed `batchSize` at a time (a second concurrency layer
|
|
6739
|
+
* over the per-index probes), but each window is CAPPED to
|
|
6740
|
+
* `gapLimit - unused` indices — the most a serial scan could still reach
|
|
6741
|
+
* before the gap window is guaranteed to close. So every index probed in
|
|
6742
|
+
* a window is one a one-index-at-a-time scan would also reach: nothing is
|
|
6743
|
+
* over-scanned, nothing is discarded, and `materialize`/`discoverAt` are
|
|
6744
|
+
* invoked on exactly the same index set. The window's hits are still
|
|
6745
|
+
* processed strictly in ascending index order, so the discovered set,
|
|
6746
|
+
* persisted rows, `lastIndexUsed`, and `handlerErrors` are byte-for-byte
|
|
6747
|
+
* identical to the serial path — only the wall-clock differs.
|
|
6695
6748
|
*/
|
|
6696
6749
|
async scanContracts(opts) {
|
|
6697
6750
|
const gapLimit = opts.gapLimit ?? 20;
|
|
@@ -6700,35 +6753,69 @@ var ContractManager = class _ContractManager {
|
|
|
6700
6753
|
`scanContracts: gapLimit must be a positive integer (got ${String(opts.gapLimit)})`
|
|
6701
6754
|
);
|
|
6702
6755
|
}
|
|
6703
|
-
const
|
|
6756
|
+
const batchSize = opts.batchSize ?? DEFAULT_SCAN_BATCH;
|
|
6757
|
+
if (!Number.isInteger(batchSize) || batchSize <= 0) {
|
|
6758
|
+
throw new Error(
|
|
6759
|
+
`scanContracts: batchSize must be a positive integer (got ${String(opts.batchSize)})`
|
|
6760
|
+
);
|
|
6761
|
+
}
|
|
6762
|
+
const registered = chunkGUTKJMSF_cjs.contractHandlers.getRegisteredTypes().map((t) => chunkGUTKJMSF_cjs.contractHandlers.get(t)).filter(isDiscoverable);
|
|
6763
|
+
const discoverables = [
|
|
6764
|
+
...registered.filter((h) => h.type === "boarding"),
|
|
6765
|
+
...registered.filter((h) => h.type !== "boarding")
|
|
6766
|
+
];
|
|
6704
6767
|
const maxIdx = opts.hd ? SCAN_MAX_INDEX : 0;
|
|
6705
6768
|
const handlerErrors = [];
|
|
6706
6769
|
let lastIndexUsed = -1;
|
|
6707
6770
|
let unused = 0;
|
|
6708
6771
|
let i = 0;
|
|
6772
|
+
const probeIndex = async (index) => {
|
|
6773
|
+
const descriptor = opts.materialize(index);
|
|
6774
|
+
return Promise.all(
|
|
6775
|
+
discoverables.map(async (h) => {
|
|
6776
|
+
try {
|
|
6777
|
+
return {
|
|
6778
|
+
ok: true,
|
|
6779
|
+
found: await h.discoverAt(index, descriptor, opts.deps)
|
|
6780
|
+
};
|
|
6781
|
+
} catch (error) {
|
|
6782
|
+
return { ok: false, error };
|
|
6783
|
+
}
|
|
6784
|
+
})
|
|
6785
|
+
);
|
|
6786
|
+
};
|
|
6709
6787
|
while (i <= maxIdx && unused < gapLimit) {
|
|
6710
|
-
const
|
|
6711
|
-
|
|
6712
|
-
for (
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6788
|
+
const windowEnd = Math.min(maxIdx, i + Math.min(batchSize, gapLimit - unused) - 1);
|
|
6789
|
+
const windowIndices = [];
|
|
6790
|
+
for (let idx = i; idx <= windowEnd; idx++) windowIndices.push(idx);
|
|
6791
|
+
const windowProbes = await Promise.all(windowIndices.map(probeIndex));
|
|
6792
|
+
for (let w = 0; w < windowIndices.length; w++) {
|
|
6793
|
+
const index = windowIndices[w];
|
|
6794
|
+
const probes = windowProbes[w];
|
|
6795
|
+
let hitAtThisIndex = false;
|
|
6796
|
+
for (let h = 0; h < discoverables.length; h++) {
|
|
6797
|
+
const probe = probes[h];
|
|
6798
|
+
if (!probe.ok) {
|
|
6799
|
+
handlerErrors.push({
|
|
6800
|
+
handler: discoverables[h].type,
|
|
6801
|
+
index,
|
|
6802
|
+
error: probe.error
|
|
6803
|
+
});
|
|
6804
|
+
continue;
|
|
6805
|
+
}
|
|
6806
|
+
for (const c of probe.found) {
|
|
6807
|
+
await this.persistAndWatchContract(c);
|
|
6808
|
+
hitAtThisIndex = true;
|
|
6809
|
+
}
|
|
6719
6810
|
}
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6811
|
+
if (hitAtThisIndex) {
|
|
6812
|
+
lastIndexUsed = index;
|
|
6813
|
+
unused = 0;
|
|
6814
|
+
} else {
|
|
6815
|
+
unused += 1;
|
|
6723
6816
|
}
|
|
6724
6817
|
}
|
|
6725
|
-
|
|
6726
|
-
lastIndexUsed = i;
|
|
6727
|
-
unused = 0;
|
|
6728
|
-
} else {
|
|
6729
|
-
unused += 1;
|
|
6730
|
-
}
|
|
6731
|
-
i += 1;
|
|
6818
|
+
i = windowEnd + 1;
|
|
6732
6819
|
}
|
|
6733
6820
|
if (opts.hd && i > maxIdx && unused < gapLimit) {
|
|
6734
6821
|
throw new Error(
|
|
@@ -6856,7 +6943,7 @@ var ContractManager = class _ContractManager {
|
|
|
6856
6943
|
const { contractScript, collaborative = true, walletPubKey, vtxo } = options;
|
|
6857
6944
|
const [contract] = await this.getContracts({ script: contractScript });
|
|
6858
6945
|
if (!contract) return [];
|
|
6859
|
-
const handler =
|
|
6946
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(contract.type);
|
|
6860
6947
|
if (!handler) return [];
|
|
6861
6948
|
const script = handler.createScript(contract.params);
|
|
6862
6949
|
const context = {
|
|
@@ -6876,7 +6963,7 @@ var ContractManager = class _ContractManager {
|
|
|
6876
6963
|
const { contractScript, collaborative = true, walletPubKey } = options;
|
|
6877
6964
|
const [contract] = await this.getContracts({ script: contractScript });
|
|
6878
6965
|
if (!contract) return [];
|
|
6879
|
-
const handler =
|
|
6966
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(contract.type);
|
|
6880
6967
|
if (!handler) return [];
|
|
6881
6968
|
const script = handler.createScript(contract.params);
|
|
6882
6969
|
const context = {
|
|
@@ -7110,7 +7197,7 @@ var ContractManager = class _ContractManager {
|
|
|
7110
7197
|
}
|
|
7111
7198
|
return result;
|
|
7112
7199
|
}
|
|
7113
|
-
async fetchContractVtxosBulk(contracts, pageSize = DEFAULT_PAGE_SIZE, syncWindow) {
|
|
7200
|
+
async fetchContractVtxosBulk(contracts, pageSize = chunkGUTKJMSF_cjs.DEFAULT_PAGE_SIZE, syncWindow) {
|
|
7114
7201
|
if (contracts.length === 0) {
|
|
7115
7202
|
return /* @__PURE__ */ new Map();
|
|
7116
7203
|
}
|
|
@@ -7286,7 +7373,7 @@ var HDDescriptorProvider = class _HDDescriptorProvider {
|
|
|
7286
7373
|
*/
|
|
7287
7374
|
materializeDescriptorAt(index) {
|
|
7288
7375
|
const descriptor = this.identity.descriptor;
|
|
7289
|
-
const network =
|
|
7376
|
+
const network = chunkGUTKJMSF_cjs.isMainnetDescriptor(descriptor) ? descriptorsScure.networks.bitcoin : descriptorsScure.networks.testnet;
|
|
7290
7377
|
const expansion = descriptorsScure.expand({ descriptor, network, index });
|
|
7291
7378
|
const keyInfo = expansion.expansionMap?.["@0"];
|
|
7292
7379
|
if (!keyInfo?.keyExpression) {
|
|
@@ -7429,12 +7516,13 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
7429
7516
|
const provider = await resolveDescriptorProvider(config, setup.walletRepository);
|
|
7430
7517
|
if (!provider) return void 0;
|
|
7431
7518
|
const allowSilentFallback = (config.walletMode ?? "auto") === "auto";
|
|
7432
|
-
const expectedContractType = setup.offchainTapscript instanceof
|
|
7519
|
+
const expectedContractType = setup.offchainTapscript instanceof chunkGUTKJMSF_cjs.DelegateVtxo.Script ? "delegate" : "default";
|
|
7433
7520
|
const factoryOpts = {
|
|
7434
7521
|
walletRepository: setup.walletRepository,
|
|
7435
7522
|
contractRepository: setup.contractRepository,
|
|
7436
7523
|
serverPubKey: setup.serverPubKey,
|
|
7437
|
-
expectedContractType
|
|
7524
|
+
expectedContractType,
|
|
7525
|
+
baselineReceivePubKey: setup.offchainTapscript.options.pubKey
|
|
7438
7526
|
};
|
|
7439
7527
|
let boot;
|
|
7440
7528
|
try {
|
|
@@ -7479,14 +7567,17 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
7479
7567
|
receivePubkey: existing.pubKey
|
|
7480
7568
|
};
|
|
7481
7569
|
}
|
|
7482
|
-
|
|
7483
|
-
if (
|
|
7484
|
-
descriptor = await provider.
|
|
7570
|
+
const current = hasPeekableDescriptor(provider) ? await provider.getCurrentSigningDescriptor() : void 0;
|
|
7571
|
+
if (current === void 0) {
|
|
7572
|
+
const descriptor = await provider.getNextSigningDescriptor();
|
|
7573
|
+
return {
|
|
7574
|
+
rotator: new _WalletReceiveRotator(provider, void 0, opts.logger),
|
|
7575
|
+
receivePubkey: deriveLeafPubkey(descriptor)
|
|
7576
|
+
};
|
|
7485
7577
|
}
|
|
7486
|
-
descriptor ??= await provider.getNextSigningDescriptor();
|
|
7487
7578
|
return {
|
|
7488
7579
|
rotator: new _WalletReceiveRotator(provider, void 0, opts.logger),
|
|
7489
|
-
receivePubkey: deriveLeafPubkey(
|
|
7580
|
+
receivePubkey: opts.baselineReceivePubKey ?? deriveLeafPubkey(current)
|
|
7490
7581
|
};
|
|
7491
7582
|
}
|
|
7492
7583
|
/**
|
|
@@ -7592,7 +7683,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
7592
7683
|
const newAddress = newTapscript.address(wallet.network.hrp, wallet.arkServerPublicKey).encode();
|
|
7593
7684
|
const manager = await wallet.getContractManager();
|
|
7594
7685
|
const csvTimelock = newTapscript.options.csvTimelock;
|
|
7595
|
-
const csvTimelockStr =
|
|
7686
|
+
const csvTimelockStr = chunkCMPJR3HS_cjs.timelockToSequence(csvTimelock).toString();
|
|
7596
7687
|
const serverPubKeyHex = base.hex.encode(newTapscript.options.serverPubKey);
|
|
7597
7688
|
const baseParams = {
|
|
7598
7689
|
script: newScript,
|
|
@@ -7606,11 +7697,11 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
7606
7697
|
// produce unsigned PSBTs that the server rejects with
|
|
7607
7698
|
// `INVALID_PSBT_INPUT (5): missing tapscript spend sig`.
|
|
7608
7699
|
metadata: {
|
|
7609
|
-
source:
|
|
7700
|
+
source: chunkGUTKJMSF_cjs.WALLET_RECEIVE_SOURCE,
|
|
7610
7701
|
signingDescriptor: descriptor
|
|
7611
7702
|
}
|
|
7612
7703
|
};
|
|
7613
|
-
if (newTapscript instanceof
|
|
7704
|
+
if (newTapscript instanceof chunkGUTKJMSF_cjs.DelegateVtxo.Script) {
|
|
7614
7705
|
await manager.createContract({
|
|
7615
7706
|
...baseParams,
|
|
7616
7707
|
type: "delegate",
|
|
@@ -7642,7 +7733,7 @@ var WalletReceiveRotator = class _WalletReceiveRotator {
|
|
|
7642
7733
|
};
|
|
7643
7734
|
function deriveLeafPubkey(descriptor) {
|
|
7644
7735
|
try {
|
|
7645
|
-
return
|
|
7736
|
+
return chunkGUTKJMSF_cjs.deriveDescriptorLeafPubKey(descriptor);
|
|
7646
7737
|
} catch (e) {
|
|
7647
7738
|
throw new NonRangeableDescriptorError(
|
|
7648
7739
|
"Cannot derive leaf pubkey: descriptor is not a materialized, parsable tr(...) shape.",
|
|
@@ -7651,10 +7742,10 @@ function deriveLeafPubkey(descriptor) {
|
|
|
7651
7742
|
}
|
|
7652
7743
|
}
|
|
7653
7744
|
function rebuildTapscript(current, pubKey) {
|
|
7654
|
-
if (current instanceof
|
|
7655
|
-
return new
|
|
7745
|
+
if (current instanceof chunkGUTKJMSF_cjs.DelegateVtxo.Script) {
|
|
7746
|
+
return new chunkGUTKJMSF_cjs.DelegateVtxo.Script({ ...current.options, pubKey });
|
|
7656
7747
|
}
|
|
7657
|
-
return new
|
|
7748
|
+
return new chunkGUTKJMSF_cjs.DefaultVtxo.Script({ ...current.options, pubKey });
|
|
7658
7749
|
}
|
|
7659
7750
|
async function pickActiveReceive(contractRepository, serverPubKey, expectedType) {
|
|
7660
7751
|
const candidates = await contractRepository.getContracts({
|
|
@@ -7663,7 +7754,7 @@ async function pickActiveReceive(contractRepository, serverPubKey, expectedType)
|
|
|
7663
7754
|
});
|
|
7664
7755
|
const serverPubKeyHex = base.hex.encode(serverPubKey);
|
|
7665
7756
|
const matching = candidates.filter(
|
|
7666
|
-
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source ===
|
|
7757
|
+
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkGUTKJMSF_cjs.WALLET_RECEIVE_SOURCE
|
|
7667
7758
|
).sort((a, b) => {
|
|
7668
7759
|
if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
|
|
7669
7760
|
return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
|
|
@@ -7719,7 +7810,7 @@ var DescriptorSigningProviderMissingError = class extends Error {
|
|
|
7719
7810
|
};
|
|
7720
7811
|
|
|
7721
7812
|
// src/wallet/inputSignerRouter.ts
|
|
7722
|
-
var DESCRIPTOR_CAPABLE_CONTRACT_TYPES = /* @__PURE__ */ new Set(["default", "delegate"]);
|
|
7813
|
+
var DESCRIPTOR_CAPABLE_CONTRACT_TYPES = /* @__PURE__ */ new Set(["default", "delegate", "boarding"]);
|
|
7723
7814
|
var InputSignerRouter = class {
|
|
7724
7815
|
constructor(deps) {
|
|
7725
7816
|
this.deps = deps;
|
|
@@ -7837,12 +7928,12 @@ var InputSignerRouter = class {
|
|
|
7837
7928
|
};
|
|
7838
7929
|
|
|
7839
7930
|
// src/wallet/wallet.ts
|
|
7840
|
-
var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl ||
|
|
7931
|
+
var getArkadeServerUrl = ({ arkServerUrl }) => arkServerUrl || chunkCMPJR3HS_cjs.DEFAULT_ARKADE_SERVER_URL;
|
|
7841
7932
|
function intentProofJobs(coins) {
|
|
7842
7933
|
if (coins.length === 0) return [];
|
|
7843
7934
|
const coinJobs = coins.map((coin, i) => ({
|
|
7844
7935
|
index: i + 1,
|
|
7845
|
-
lookupScript:
|
|
7936
|
+
lookupScript: chunkCMPJR3HS_cjs.VtxoScript.decode(coin.tapTree).pkScript
|
|
7846
7937
|
}));
|
|
7847
7938
|
return [{ index: 0, lookupScript: coinJobs[0].lookupScript }, ...coinJobs];
|
|
7848
7939
|
}
|
|
@@ -7851,6 +7942,11 @@ function extractArkProviderUrl(provider) {
|
|
|
7851
7942
|
return typeof serverUrl === "string" && serverUrl.length > 0 ? serverUrl : void 0;
|
|
7852
7943
|
}
|
|
7853
7944
|
var MAINNET_UNILATERAL_EXIT_DELAY = 605184n;
|
|
7945
|
+
function toXOnlyPubKey(pubkey) {
|
|
7946
|
+
if (pubkey.length === 33) return pubkey.slice(1);
|
|
7947
|
+
if (pubkey.length === 32) return pubkey;
|
|
7948
|
+
throw new Error(`invalid signer pubkey length: expected 32 or 33, got ${pubkey.length}`);
|
|
7949
|
+
}
|
|
7854
7950
|
function delayToTimelock(delay) {
|
|
7855
7951
|
return {
|
|
7856
7952
|
value: delay,
|
|
@@ -7861,27 +7957,37 @@ function dedupeTimelocks(timelocks) {
|
|
|
7861
7957
|
const seen = /* @__PURE__ */ new Set();
|
|
7862
7958
|
const deduped = [];
|
|
7863
7959
|
for (const timelock of timelocks) {
|
|
7864
|
-
const sequence =
|
|
7960
|
+
const sequence = chunkCMPJR3HS_cjs.timelockToSequence(timelock).toString();
|
|
7865
7961
|
if (seen.has(sequence)) continue;
|
|
7866
7962
|
seen.add(sequence);
|
|
7867
7963
|
deduped.push(timelock);
|
|
7868
7964
|
}
|
|
7869
7965
|
return deduped;
|
|
7870
7966
|
}
|
|
7871
|
-
function areSameScriptBaselineTypesCompatible(existingType, requestedType) {
|
|
7872
|
-
if (existingType === requestedType) return true;
|
|
7873
|
-
return existingType === "default" && requestedType === "boarding" || existingType === "boarding" && requestedType === "default";
|
|
7874
|
-
}
|
|
7875
7967
|
async function ensureWalletContract(manager, params) {
|
|
7876
|
-
const [existing] = await manager.getContracts({ script: params.script });
|
|
7877
|
-
if (existing && existing.type !== params.type && areSameScriptBaselineTypesCompatible(existing.type, params.type)) {
|
|
7878
|
-
if (params.type === "default" && existing.type === "boarding") {
|
|
7879
|
-
await manager.updateContract(params.script, { type: "default" });
|
|
7880
|
-
}
|
|
7881
|
-
return;
|
|
7882
|
-
}
|
|
7883
7968
|
await manager.createContract(params);
|
|
7884
7969
|
}
|
|
7970
|
+
async function resolveBoardingBootTapscript(contractRepository, serverPubKey, baseline) {
|
|
7971
|
+
const serverPubKeyHex = base.hex.encode(serverPubKey);
|
|
7972
|
+
const candidates = await contractRepository.getContracts({
|
|
7973
|
+
type: ["boarding"],
|
|
7974
|
+
state: "active"
|
|
7975
|
+
});
|
|
7976
|
+
const newest = candidates.filter(
|
|
7977
|
+
(c) => c.params.serverPubKey === serverPubKeyHex && c.metadata?.source === chunkGUTKJMSF_cjs.WALLET_RECEIVE_SOURCE
|
|
7978
|
+
).sort((a, b) => {
|
|
7979
|
+
if (b.createdAt !== a.createdAt) return b.createdAt - a.createdAt;
|
|
7980
|
+
return signingDescriptorIndex(b.metadata?.signingDescriptor) - signingDescriptorIndex(a.metadata?.signingDescriptor);
|
|
7981
|
+
})[0];
|
|
7982
|
+
if (!newest?.params.pubKey) return baseline;
|
|
7983
|
+
try {
|
|
7984
|
+
const pubKey = base.hex.decode(newest.params.pubKey);
|
|
7985
|
+
return new chunkGUTKJMSF_cjs.DefaultVtxo.Script({ ...baseline.options, pubKey });
|
|
7986
|
+
} catch (e) {
|
|
7987
|
+
console.warn("Skipping malformed boarding contract at boot", newest.script, e);
|
|
7988
|
+
return baseline;
|
|
7989
|
+
}
|
|
7990
|
+
}
|
|
7885
7991
|
function hasToReadonly(identity) {
|
|
7886
7992
|
return typeof identity === "object" && identity !== null && "toReadonly" in identity && typeof identity.toReadonly === "function";
|
|
7887
7993
|
}
|
|
@@ -7892,7 +7998,6 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
7892
7998
|
this.onchainProvider = onchainProvider;
|
|
7893
7999
|
this.indexerProvider = indexerProvider;
|
|
7894
8000
|
this.arkServerPublicKey = arkServerPublicKey;
|
|
7895
|
-
this.boardingTapscript = boardingTapscript;
|
|
7896
8001
|
this.dustAmount = dustAmount;
|
|
7897
8002
|
this.walletRepository = walletRepository;
|
|
7898
8003
|
this.contractRepository = contractRepository;
|
|
@@ -7908,6 +8013,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
7908
8013
|
}
|
|
7909
8014
|
}
|
|
7910
8015
|
this._offchainTapscript = offchainTapscript;
|
|
8016
|
+
this._boardingTapscript = boardingTapscript;
|
|
7911
8017
|
this.watcherConfig = watcherConfig;
|
|
7912
8018
|
this._assetManager = new ReadonlyAssetManager(this.indexerProvider);
|
|
7913
8019
|
this.walletContractTimelocks = walletContractTimelocks && walletContractTimelocks.length > 0 ? dedupeTimelocks(walletContractTimelocks) : [this.offchainTapscript.options.csvTimelock];
|
|
@@ -7934,6 +8040,17 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
7934
8040
|
* {@link WalletReceiveRotator.rotate} is the sole intended caller of.
|
|
7935
8041
|
*/
|
|
7936
8042
|
_offchainTapscript;
|
|
8043
|
+
/**
|
|
8044
|
+
* Backing field for the current boarding tapscript (the QR / onboarding
|
|
8045
|
+
* target). Read via the public `boardingTapscript` getter; written only
|
|
8046
|
+
* by {@link Wallet.setBoardingTapscriptForRotation}, the sanctioned
|
|
8047
|
+
* boarding-rotation write path (analogue of `_offchainTapscript`). It is
|
|
8048
|
+
* a *current value*, not a fixed setup constant, because per-derivation
|
|
8049
|
+
* boarding rotation (plan §6-II) swaps it when a fresh boarding address
|
|
8050
|
+
* is explicitly allocated. Static / `auto` wallets never rotate it, so
|
|
8051
|
+
* it stays the index-0 baseline for their lifetime.
|
|
8052
|
+
*/
|
|
8053
|
+
_boardingTapscript;
|
|
7937
8054
|
/**
|
|
7938
8055
|
* Currently-active receive tapscript. Read-only from the outside;
|
|
7939
8056
|
* mutated only via {@link Wallet.setOffchainTapscriptForRotation}
|
|
@@ -7942,13 +8059,59 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
7942
8059
|
get offchainTapscript() {
|
|
7943
8060
|
return this._offchainTapscript;
|
|
7944
8061
|
}
|
|
8062
|
+
/**
|
|
8063
|
+
* The wallet's current boarding tapscript (the on-chain onboarding
|
|
8064
|
+
* target). Read-only from the outside; mutated only via
|
|
8065
|
+
* {@link Wallet.setBoardingTapscriptForRotation} when a fresh boarding
|
|
8066
|
+
* address is explicitly allocated. Single-valued for static / `auto`
|
|
8067
|
+
* wallets.
|
|
8068
|
+
*/
|
|
8069
|
+
get boardingTapscript() {
|
|
8070
|
+
return this._boardingTapscript;
|
|
8071
|
+
}
|
|
8072
|
+
/**
|
|
8073
|
+
* Listeners fired after the boarding tapscript rotates to a fresh index
|
|
8074
|
+
* (see {@link Wallet.setBoardingTapscriptForRotation}). A live
|
|
8075
|
+
* {@link notifyIncomingFunds} onchain watcher registers one so it can
|
|
8076
|
+
* re-subscribe to include the newly allocated boarding address within the
|
|
8077
|
+
* same session — without it, a deposit to the fresh address wouldn't fire
|
|
8078
|
+
* a notification until the watcher's next re-init. Always empty for
|
|
8079
|
+
* readonly / static / `auto` wallets, which never rotate boarding.
|
|
8080
|
+
*/
|
|
8081
|
+
_boardingRotationListeners = /* @__PURE__ */ new Set();
|
|
8082
|
+
/**
|
|
8083
|
+
* Register a listener invoked synchronously after each boarding rotation.
|
|
8084
|
+
* Returns an unsubscribe function. Protected: only internal subscribers
|
|
8085
|
+
* (the incoming-funds watcher) participate.
|
|
8086
|
+
*/
|
|
8087
|
+
onBoardingRotation(listener) {
|
|
8088
|
+
this._boardingRotationListeners.add(listener);
|
|
8089
|
+
return () => {
|
|
8090
|
+
this._boardingRotationListeners.delete(listener);
|
|
8091
|
+
};
|
|
8092
|
+
}
|
|
8093
|
+
/**
|
|
8094
|
+
* Notify boarding-rotation listeners. Called by the boarding-rotation
|
|
8095
|
+
* write path ({@link Wallet.setBoardingTapscriptForRotation}) once the new
|
|
8096
|
+
* tapscript is in place. A throwing listener is isolated so it can neither
|
|
8097
|
+
* break the rotation nor starve sibling listeners.
|
|
8098
|
+
*/
|
|
8099
|
+
notifyBoardingRotation() {
|
|
8100
|
+
for (const listener of this._boardingRotationListeners) {
|
|
8101
|
+
try {
|
|
8102
|
+
listener();
|
|
8103
|
+
} catch (e) {
|
|
8104
|
+
console.warn("Boarding-rotation listener failed", e);
|
|
8105
|
+
}
|
|
8106
|
+
}
|
|
8107
|
+
}
|
|
7945
8108
|
/**
|
|
7946
8109
|
* Protected helper to set up shared wallet configuration.
|
|
7947
8110
|
* Extracts common logic used by both ReadonlyWallet.create() and Wallet.create().
|
|
7948
8111
|
*/
|
|
7949
8112
|
static async setupWalletConfig(config, pubKey) {
|
|
7950
8113
|
const arkadeServerUrl = getArkadeServerUrl(config);
|
|
7951
|
-
const arkProvider = config.arkProvider || new
|
|
8114
|
+
const arkProvider = config.arkProvider || new chunkFSAXPBGP_cjs.RestArkProvider(arkadeServerUrl);
|
|
7952
8115
|
let indexerProvider = config.indexerProvider;
|
|
7953
8116
|
if (!indexerProvider) {
|
|
7954
8117
|
let indexerUrl = config.indexerUrl;
|
|
@@ -7965,10 +8128,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
7965
8128
|
indexerUrl = arkadeServerUrl;
|
|
7966
8129
|
}
|
|
7967
8130
|
}
|
|
7968
|
-
indexerProvider = new
|
|
8131
|
+
indexerProvider = new chunkFSAXPBGP_cjs.RestIndexerProvider(indexerUrl);
|
|
7969
8132
|
}
|
|
7970
8133
|
const info = await arkProvider.getInfo();
|
|
7971
|
-
const network =
|
|
8134
|
+
const network = chunkCMPJR3HS_cjs.getNetwork(info.network);
|
|
7972
8135
|
if ("descriptor" in config.identity) {
|
|
7973
8136
|
const descriptor = config.identity.descriptor;
|
|
7974
8137
|
const identityIsMainnet = !descriptor.includes("tpub");
|
|
@@ -8015,11 +8178,11 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8015
8178
|
serverPubKey,
|
|
8016
8179
|
csvTimelock: exitTimelock
|
|
8017
8180
|
};
|
|
8018
|
-
const offchainTapscript = !delegatePubKey ? new
|
|
8019
|
-
const boardingTapscript =
|
|
8181
|
+
const offchainTapscript = !delegatePubKey ? new chunkGUTKJMSF_cjs.DefaultVtxo.Script(offchainOptions) : new chunkGUTKJMSF_cjs.DelegateVtxo.Script({ ...offchainOptions, delegatePubKey });
|
|
8182
|
+
const boardingTapscript = chunkGUTKJMSF_cjs.BoardingContractHandler.createScript({
|
|
8020
8183
|
pubKey: base.hex.encode(pubKey),
|
|
8021
8184
|
serverPubKey: base.hex.encode(serverPubKey),
|
|
8022
|
-
csvTimelock:
|
|
8185
|
+
csvTimelock: chunkCMPJR3HS_cjs.timelockToSequence(boardingTimelock).toString()
|
|
8023
8186
|
});
|
|
8024
8187
|
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
8025
8188
|
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
@@ -8182,43 +8345,59 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8182
8345
|
await clearSyncCursor(this.walletRepository);
|
|
8183
8346
|
}
|
|
8184
8347
|
/**
|
|
8185
|
-
*
|
|
8348
|
+
* The on-chain (P2TR) addresses of every boarding tapscript this wallet
|
|
8349
|
+
* uses — the current address plus any historical rotated boarding
|
|
8350
|
+
* addresses. The aggregating boarding readers (history, notifications) fan
|
|
8351
|
+
* out over this set so deposits at previous boarding addresses are still
|
|
8352
|
+
* surfaced (plan §6-IV); {@link getBoardingAddress} stays single-valued.
|
|
8353
|
+
*/
|
|
8354
|
+
async getBoardingAddresses() {
|
|
8355
|
+
const tapscripts = await this.getBoardingTapscripts();
|
|
8356
|
+
return tapscripts.map((t) => t.onchainAddress(this.network));
|
|
8357
|
+
}
|
|
8358
|
+
/**
|
|
8359
|
+
* Build a transaction history view across the wallet's boarding addresses
|
|
8360
|
+
* (current + historical rotated; plan §6-IV.1).
|
|
8186
8361
|
*/
|
|
8187
8362
|
async getBoardingTxs() {
|
|
8188
8363
|
const utxos = [];
|
|
8189
8364
|
const commitmentsToIgnore = /* @__PURE__ */ new Set();
|
|
8190
|
-
const
|
|
8191
|
-
const txs = await this.onchainProvider.getTransactions(boardingAddress);
|
|
8365
|
+
const tapscripts = await this.getBoardingTapscripts();
|
|
8192
8366
|
const outspendCache = /* @__PURE__ */ new Map();
|
|
8193
|
-
for (const
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8367
|
+
for (const tapscript of tapscripts) {
|
|
8368
|
+
const boardingAddress = tapscript.onchainAddress(this.network);
|
|
8369
|
+
const scriptHex = base.hex.encode(tapscript.pkScript);
|
|
8370
|
+
const txs = await this.onchainProvider.getTransactions(boardingAddress);
|
|
8371
|
+
for (const tx of txs) {
|
|
8372
|
+
for (let i = 0; i < tx.vout.length; i++) {
|
|
8373
|
+
const vout = tx.vout[i];
|
|
8374
|
+
if (vout.scriptpubkey_address === boardingAddress) {
|
|
8375
|
+
let spentStatuses = outspendCache.get(tx.txid);
|
|
8376
|
+
if (!spentStatuses) {
|
|
8377
|
+
spentStatuses = await this.onchainProvider.getTxOutspends(tx.txid);
|
|
8378
|
+
outspendCache.set(tx.txid, spentStatuses);
|
|
8379
|
+
}
|
|
8380
|
+
const spentStatus = spentStatuses[i];
|
|
8381
|
+
if (spentStatus?.spent) {
|
|
8382
|
+
commitmentsToIgnore.add(spentStatus.txid);
|
|
8383
|
+
}
|
|
8384
|
+
utxos.push({
|
|
8385
|
+
txid: tx.txid,
|
|
8386
|
+
vout: i,
|
|
8387
|
+
value: Number(vout.value),
|
|
8388
|
+
status: {
|
|
8389
|
+
confirmed: tx.status.confirmed,
|
|
8390
|
+
block_time: tx.status.block_time
|
|
8391
|
+
},
|
|
8392
|
+
isUnrolled: true,
|
|
8393
|
+
virtualStatus: {
|
|
8394
|
+
state: spentStatus?.spent ? "spent" : "settled",
|
|
8395
|
+
commitmentTxIds: spentStatus?.spent ? [spentStatus.txid] : void 0
|
|
8396
|
+
},
|
|
8397
|
+
createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
|
|
8398
|
+
script: scriptHex
|
|
8399
|
+
});
|
|
8205
8400
|
}
|
|
8206
|
-
utxos.push({
|
|
8207
|
-
txid: tx.txid,
|
|
8208
|
-
vout: i,
|
|
8209
|
-
value: Number(vout.value),
|
|
8210
|
-
status: {
|
|
8211
|
-
confirmed: tx.status.confirmed,
|
|
8212
|
-
block_time: tx.status.block_time
|
|
8213
|
-
},
|
|
8214
|
-
isUnrolled: true,
|
|
8215
|
-
virtualStatus: {
|
|
8216
|
-
state: spentStatus?.spent ? "spent" : "settled",
|
|
8217
|
-
commitmentTxIds: spentStatus?.spent ? [spentStatus.txid] : void 0
|
|
8218
|
-
},
|
|
8219
|
-
createdAt: tx.status.confirmed ? new Date(tx.status.block_time * 1e3) : /* @__PURE__ */ new Date(0),
|
|
8220
|
-
script: base.hex.encode(this.boardingTapscript.pkScript)
|
|
8221
|
-
});
|
|
8222
8401
|
}
|
|
8223
8402
|
}
|
|
8224
8403
|
}
|
|
@@ -8248,48 +8427,130 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8248
8427
|
};
|
|
8249
8428
|
}
|
|
8250
8429
|
/**
|
|
8251
|
-
*
|
|
8430
|
+
* The set of boarding tapscripts whose on-chain UTXOs belong to this
|
|
8431
|
+
* wallet — the current display tapscript plus every historical boarding
|
|
8432
|
+
* address it has used. Under per-derivation rotation (plan §6-II) a wallet
|
|
8433
|
+
* can hold unspent boarding UTXOs at several addresses at once, so fund
|
|
8434
|
+
* discovery / spending must enumerate them all, not just the current one
|
|
8435
|
+
* (plan §6-III.1). Deduplicated by scriptPubKey.
|
|
8436
|
+
*
|
|
8437
|
+
* Always includes the index-0 baseline (identity x-only key), which covers
|
|
8438
|
+
* the degenerate equal-delay case where the index-0 boarding row is
|
|
8439
|
+
* coalesced onto a `default` row and so isn't a `boarding`-typed contract.
|
|
8252
8440
|
*/
|
|
8253
|
-
async
|
|
8254
|
-
const
|
|
8255
|
-
const
|
|
8256
|
-
const
|
|
8257
|
-
|
|
8441
|
+
async getBoardingTapscripts() {
|
|
8442
|
+
const byScript = /* @__PURE__ */ new Map();
|
|
8443
|
+
const add = (s) => byScript.set(base.hex.encode(s.pkScript), s);
|
|
8444
|
+
const boardingCsv = this.boardingTapscript.options.csvTimelock ?? chunkGUTKJMSF_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
8445
|
+
add(
|
|
8446
|
+
new chunkGUTKJMSF_cjs.DefaultVtxo.Script({
|
|
8447
|
+
pubKey: await this.identity.xOnlyPublicKey(),
|
|
8448
|
+
serverPubKey: this.boardingTapscript.options.serverPubKey,
|
|
8449
|
+
csvTimelock: boardingCsv
|
|
8450
|
+
})
|
|
8451
|
+
);
|
|
8452
|
+
add(this.boardingTapscript);
|
|
8453
|
+
const serverPubKeyHex = base.hex.encode(this.boardingTapscript.options.serverPubKey);
|
|
8454
|
+
const boardingContracts = await this.contractRepository.getContracts({
|
|
8455
|
+
type: ["boarding"]
|
|
8258
8456
|
});
|
|
8259
|
-
|
|
8260
|
-
|
|
8457
|
+
for (const c of boardingContracts) {
|
|
8458
|
+
if (c.params.serverPubKey !== serverPubKeyHex) continue;
|
|
8459
|
+
try {
|
|
8460
|
+
add(chunkGUTKJMSF_cjs.BoardingContractHandler.createScript(c.params));
|
|
8461
|
+
} catch (e) {
|
|
8462
|
+
console.warn("Skipping malformed boarding contract", c.script, e);
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8465
|
+
return [...byScript.values()];
|
|
8466
|
+
}
|
|
8467
|
+
/**
|
|
8468
|
+
* Fetch and cache onchain inputs (UTXOs) received at the wallet's boarding
|
|
8469
|
+
* addresses — the current address plus any historical rotated boarding
|
|
8470
|
+
* addresses that still hold unspent UTXOs (plan §6-III.1). Each UTXO is
|
|
8471
|
+
* annotated with the tapscript of the address it actually sits on, so the
|
|
8472
|
+
* spending path forfeits / exits it with the correct per-index leaves.
|
|
8473
|
+
*/
|
|
8474
|
+
async getBoardingUtxos() {
|
|
8475
|
+
const tapscripts = await this.getBoardingTapscripts();
|
|
8476
|
+
const all = [];
|
|
8477
|
+
for (const tapscript of tapscripts) {
|
|
8478
|
+
const address = tapscript.onchainAddress(this.network);
|
|
8479
|
+
const coins = await this.onchainProvider.getCoins(address);
|
|
8480
|
+
const utxos = coins.map((utxo) => extendCoinWithTapscript(tapscript, utxo));
|
|
8481
|
+
await this.walletRepository.saveUtxos(address, utxos);
|
|
8482
|
+
all.push(...utxos);
|
|
8483
|
+
}
|
|
8484
|
+
return all;
|
|
8261
8485
|
}
|
|
8262
8486
|
/**
|
|
8263
8487
|
* Subscribe to onchain and offchain notifications for newly received funds.
|
|
8264
8488
|
*
|
|
8489
|
+
* The onchain watcher tracks the full boarding-address set (current +
|
|
8490
|
+
* historical rotated). When boarding rotates *after* subscribing — e.g.
|
|
8491
|
+
* rotate-on-board allocates a fresh address via
|
|
8492
|
+
* {@link getNewBoardingAddress} — the watcher automatically re-subscribes
|
|
8493
|
+
* to widen its set, so a deposit to the new address fires a notification
|
|
8494
|
+
* within the same session (no watcher re-init required). The re-subscribe
|
|
8495
|
+
* is driven by {@link onBoardingRotation}; static / `auto` / readonly
|
|
8496
|
+
* wallets never rotate boarding, so it never fires for them.
|
|
8497
|
+
*
|
|
8265
8498
|
* @param eventCallback - Callback invoked when matching funds are detected
|
|
8266
8499
|
* @returns A function that stops the subscriptions
|
|
8267
8500
|
*/
|
|
8268
8501
|
async notifyIncomingFunds(eventCallback) {
|
|
8269
8502
|
const arkAddress = await this.getAddress();
|
|
8270
|
-
const boardingAddress = await this.getBoardingAddress();
|
|
8271
8503
|
let onchainStopFunc;
|
|
8272
8504
|
let indexerStopFunc;
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
(
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8505
|
+
let boardingRotationStopFunc;
|
|
8506
|
+
let stopped = false;
|
|
8507
|
+
let onchainChain = Promise.resolve();
|
|
8508
|
+
const subscribeOnchain = () => {
|
|
8509
|
+
onchainChain = onchainChain.then(async () => {
|
|
8510
|
+
if (stopped || !this.onchainProvider) return;
|
|
8511
|
+
const boardingAddresses = await this.getBoardingAddresses();
|
|
8512
|
+
if (boardingAddresses.length === 0) return;
|
|
8513
|
+
const boardingAddressSet = new Set(boardingAddresses);
|
|
8514
|
+
const previousStop = onchainStopFunc;
|
|
8515
|
+
const stop = await this.onchainProvider.watchAddresses(
|
|
8516
|
+
boardingAddresses,
|
|
8517
|
+
(txs) => {
|
|
8518
|
+
const coins = txs.flatMap((tx) => {
|
|
8519
|
+
const { txid, status } = tx;
|
|
8520
|
+
const matched = [];
|
|
8521
|
+
tx.vout.forEach((v, vout) => {
|
|
8522
|
+
if (boardingAddressSet.has(v.scriptpubkey_address)) {
|
|
8523
|
+
matched.push({
|
|
8524
|
+
txid,
|
|
8525
|
+
vout,
|
|
8526
|
+
value: Number(v.value),
|
|
8527
|
+
status
|
|
8528
|
+
});
|
|
8529
|
+
}
|
|
8530
|
+
});
|
|
8531
|
+
return matched;
|
|
8532
|
+
});
|
|
8533
|
+
eventCallback({
|
|
8534
|
+
type: "utxo",
|
|
8535
|
+
coins
|
|
8536
|
+
});
|
|
8537
|
+
}
|
|
8538
|
+
);
|
|
8539
|
+
if (stopped) {
|
|
8540
|
+
stop();
|
|
8541
|
+
return;
|
|
8290
8542
|
}
|
|
8291
|
-
|
|
8292
|
-
|
|
8543
|
+
onchainStopFunc = stop;
|
|
8544
|
+
previousStop?.();
|
|
8545
|
+
}).catch((e) => {
|
|
8546
|
+
console.warn("Failed to (re)subscribe boarding-funds watcher", e);
|
|
8547
|
+
});
|
|
8548
|
+
return onchainChain;
|
|
8549
|
+
};
|
|
8550
|
+
boardingRotationStopFunc = this.onBoardingRotation(() => {
|
|
8551
|
+
void subscribeOnchain();
|
|
8552
|
+
});
|
|
8553
|
+
await subscribeOnchain();
|
|
8293
8554
|
if (this.indexerProvider && arkAddress) {
|
|
8294
8555
|
const cm = await this.getContractManager();
|
|
8295
8556
|
let annotationQueue = Promise.resolve();
|
|
@@ -8318,7 +8579,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8318
8579
|
});
|
|
8319
8580
|
}
|
|
8320
8581
|
const stopFunc = () => {
|
|
8582
|
+
stopped = true;
|
|
8583
|
+
boardingRotationStopFunc?.();
|
|
8321
8584
|
onchainStopFunc?.();
|
|
8585
|
+
onchainStopFunc = void 0;
|
|
8322
8586
|
indexerStopFunc?.();
|
|
8323
8587
|
};
|
|
8324
8588
|
return stopFunc;
|
|
@@ -8359,7 +8623,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8359
8623
|
});
|
|
8360
8624
|
for (const contract of contracts) {
|
|
8361
8625
|
if (map.has(contract.script)) continue;
|
|
8362
|
-
const handler =
|
|
8626
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(contract.type);
|
|
8363
8627
|
if (handler) {
|
|
8364
8628
|
const script = handler.createScript(contract.params);
|
|
8365
8629
|
map.set(contract.script, script);
|
|
@@ -8425,8 +8689,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8425
8689
|
});
|
|
8426
8690
|
const baselinePubkey = await this.identity.xOnlyPublicKey();
|
|
8427
8691
|
for (const csvTimelock of this.walletContractTimelocks) {
|
|
8428
|
-
const csvTimelockStr =
|
|
8429
|
-
const defaultScript = new
|
|
8692
|
+
const csvTimelockStr = chunkCMPJR3HS_cjs.timelockToSequence(csvTimelock).toString();
|
|
8693
|
+
const defaultScript = new chunkGUTKJMSF_cjs.DefaultVtxo.Script({
|
|
8430
8694
|
pubKey: baselinePubkey,
|
|
8431
8695
|
serverPubKey: this.offchainTapscript.options.serverPubKey,
|
|
8432
8696
|
csvTimelock
|
|
@@ -8443,8 +8707,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8443
8707
|
address: defaultScript.address(this.network.hrp, this.arkServerPublicKey).encode(),
|
|
8444
8708
|
state: "active"
|
|
8445
8709
|
});
|
|
8446
|
-
if (this.offchainTapscript instanceof
|
|
8447
|
-
const delegateScript = new
|
|
8710
|
+
if (this.offchainTapscript instanceof chunkGUTKJMSF_cjs.DelegateVtxo.Script) {
|
|
8711
|
+
const delegateScript = new chunkGUTKJMSF_cjs.DelegateVtxo.Script({
|
|
8448
8712
|
pubKey: baselinePubkey,
|
|
8449
8713
|
serverPubKey: this.offchainTapscript.options.serverPubKey,
|
|
8450
8714
|
delegatePubKey: this.offchainTapscript.options.delegatePubKey,
|
|
@@ -8465,17 +8729,21 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
8465
8729
|
});
|
|
8466
8730
|
}
|
|
8467
8731
|
}
|
|
8468
|
-
const
|
|
8469
|
-
const
|
|
8732
|
+
const boardingCsvTimelock = this.boardingTapscript.options.csvTimelock ?? chunkGUTKJMSF_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
8733
|
+
const baselineBoarding = new chunkGUTKJMSF_cjs.DefaultVtxo.Script({
|
|
8734
|
+
pubKey: baselinePubkey,
|
|
8735
|
+
serverPubKey: this.boardingTapscript.options.serverPubKey,
|
|
8736
|
+
csvTimelock: boardingCsvTimelock
|
|
8737
|
+
});
|
|
8470
8738
|
await ensureWalletContract(manager, {
|
|
8471
8739
|
type: "boarding",
|
|
8472
8740
|
params: {
|
|
8473
|
-
pubKey: base.hex.encode(
|
|
8474
|
-
serverPubKey: base.hex.encode(
|
|
8475
|
-
csvTimelock:
|
|
8741
|
+
pubKey: base.hex.encode(baselineBoarding.options.pubKey),
|
|
8742
|
+
serverPubKey: base.hex.encode(baselineBoarding.options.serverPubKey),
|
|
8743
|
+
csvTimelock: chunkCMPJR3HS_cjs.timelockToSequence(boardingCsvTimelock).toString()
|
|
8476
8744
|
},
|
|
8477
|
-
script:
|
|
8478
|
-
address:
|
|
8745
|
+
script: base.hex.encode(baselineBoarding.pkScript),
|
|
8746
|
+
address: baselineBoarding.address(this.network.hrp, this.arkServerPublicKey).encode(),
|
|
8479
8747
|
state: "active"
|
|
8480
8748
|
});
|
|
8481
8749
|
return manager;
|
|
@@ -8575,6 +8843,72 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8575
8843
|
setOffchainTapscriptForRotation(tapscript) {
|
|
8576
8844
|
this._offchainTapscript = tapscript;
|
|
8577
8845
|
}
|
|
8846
|
+
/**
|
|
8847
|
+
* @internal Sole write path for `boardingTapscript` after construction.
|
|
8848
|
+
* Called by {@link Wallet.getNewBoardingAddress} once the rotated
|
|
8849
|
+
* boarding contract has been persisted. External code must treat
|
|
8850
|
+
* `boardingTapscript` as read-only.
|
|
8851
|
+
*/
|
|
8852
|
+
setBoardingTapscriptForRotation(tapscript) {
|
|
8853
|
+
this._boardingTapscript = tapscript;
|
|
8854
|
+
this.notifyBoardingRotation();
|
|
8855
|
+
}
|
|
8856
|
+
/**
|
|
8857
|
+
* Allocate and return a *fresh* on-chain boarding address, rotating the
|
|
8858
|
+
* wallet's current boarding tapscript to a new HD index.
|
|
8859
|
+
*
|
|
8860
|
+
* This is the explicit boarding allocator — the analogue of dotnet's
|
|
8861
|
+
* `GetNextContract(NextContractPurpose.Boarding)`. Unlike
|
|
8862
|
+
* {@link getBoardingAddress} (a stable read of the current display
|
|
8863
|
+
* address that never burns an index), each call here:
|
|
8864
|
+
*
|
|
8865
|
+
* - allocates the next index from the shared HD stream (so boarding and
|
|
8866
|
+
* L2 receive interleave on one monotonic index);
|
|
8867
|
+
* - builds the boarding tapscript at that index with the boarding-exit
|
|
8868
|
+
* CSV;
|
|
8869
|
+
* - persists an `active` `boarding` contract tagged
|
|
8870
|
+
* {@link WALLET_RECEIVE_SOURCE} (with its `signingDescriptor`) so the
|
|
8871
|
+
* ContractWatcher monitors it, boot can restore it as the current
|
|
8872
|
+
* boarding address, and descriptor-aware signing can recover the
|
|
8873
|
+
* per-index key;
|
|
8874
|
+
* - swaps the wallet's current `boardingTapscript`.
|
|
8875
|
+
*
|
|
8876
|
+
* Gated by `walletMode`: a static / `auto` wallet has no descriptor
|
|
8877
|
+
* provider and keeps a single index-0 boarding address for its lifetime,
|
|
8878
|
+
* so this returns the existing {@link getBoardingAddress} unchanged
|
|
8879
|
+
* (no rotation, no index burned).
|
|
8880
|
+
*/
|
|
8881
|
+
async getNewBoardingAddress() {
|
|
8882
|
+
const provider = this._descriptorProvider;
|
|
8883
|
+
if (!provider) {
|
|
8884
|
+
return this.getBoardingAddress();
|
|
8885
|
+
}
|
|
8886
|
+
const descriptor = await provider.getNextSigningDescriptor();
|
|
8887
|
+
const pubKey = chunkGUTKJMSF_cjs.deriveDescriptorLeafPubKey(descriptor);
|
|
8888
|
+
const newBoarding = new chunkGUTKJMSF_cjs.DefaultVtxo.Script({
|
|
8889
|
+
...this._boardingTapscript.options,
|
|
8890
|
+
pubKey
|
|
8891
|
+
});
|
|
8892
|
+
const csvTimelock = newBoarding.options.csvTimelock ?? chunkGUTKJMSF_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK;
|
|
8893
|
+
const manager = await this.getContractManager();
|
|
8894
|
+
await manager.createContract({
|
|
8895
|
+
type: "boarding",
|
|
8896
|
+
params: {
|
|
8897
|
+
pubKey: base.hex.encode(pubKey),
|
|
8898
|
+
serverPubKey: base.hex.encode(newBoarding.options.serverPubKey),
|
|
8899
|
+
csvTimelock: chunkCMPJR3HS_cjs.timelockToSequence(csvTimelock).toString()
|
|
8900
|
+
},
|
|
8901
|
+
script: base.hex.encode(newBoarding.pkScript),
|
|
8902
|
+
address: newBoarding.address(this.network.hrp, this.arkServerPublicKey).encode(),
|
|
8903
|
+
state: "active",
|
|
8904
|
+
metadata: {
|
|
8905
|
+
source: chunkGUTKJMSF_cjs.WALLET_RECEIVE_SOURCE,
|
|
8906
|
+
signingDescriptor: descriptor
|
|
8907
|
+
}
|
|
8908
|
+
});
|
|
8909
|
+
this.setBoardingTapscriptForRotation(newBoarding);
|
|
8910
|
+
return newBoarding.onchainAddress(this.network);
|
|
8911
|
+
}
|
|
8578
8912
|
/**
|
|
8579
8913
|
* Async mutex that serializes all operations submitting VTXOs to the Arkade
|
|
8580
8914
|
* server (`settle`, `send`, `sendBitcoin`). This prevents VtxoManager's
|
|
@@ -8658,13 +8992,26 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8658
8992
|
const hd = provider instanceof HDDescriptorProvider;
|
|
8659
8993
|
const staticDescriptor = hd ? void 0 : `tr(${base.hex.encode(await this.identity.xOnlyPublicKey())})`;
|
|
8660
8994
|
const materialize = (index) => hd ? provider.materializeDescriptorAt(index) : staticDescriptor;
|
|
8661
|
-
const delegatePubKey = this.offchainTapscript instanceof
|
|
8995
|
+
const delegatePubKey = this.offchainTapscript instanceof chunkGUTKJMSF_cjs.DelegateVtxo.Script ? this.offchainTapscript.options.delegatePubKey : void 0;
|
|
8996
|
+
const arkInfo = await this.arkProvider.getInfo();
|
|
8997
|
+
const currentSignerPubKey = toXOnlyPubKey(base.hex.decode(arkInfo.signerPubkey));
|
|
8998
|
+
const deprecatedSignerPubKeys = arkInfo.deprecatedSigners.map(
|
|
8999
|
+
(s) => toXOnlyPubKey(base.hex.decode(s.pubkey))
|
|
9000
|
+
);
|
|
8662
9001
|
const deps = {
|
|
8663
9002
|
indexerProvider: this.indexerProvider,
|
|
8664
9003
|
onchainProvider: this.onchainProvider,
|
|
8665
9004
|
network: { hrp: this.network.hrp },
|
|
8666
|
-
|
|
9005
|
+
// Full network for the boarding on-chain (P2TR) probe — the
|
|
9006
|
+
// `{ hrp }` shape above lacks the `bech32` data
|
|
9007
|
+
// `VtxoScript.onchainAddress` needs (plan §6-I.1).
|
|
9008
|
+
onchainNetwork: this.network,
|
|
9009
|
+
serverPubKey: currentSignerPubKey,
|
|
9010
|
+
deprecatedSignerPubKeys,
|
|
8667
9011
|
csvTimelocks: this.walletContractTimelocks,
|
|
9012
|
+
// Boarding-exit CSV so the boarding handler can build its
|
|
9013
|
+
// candidate script (distinct from the unilateral-exit matrix).
|
|
9014
|
+
boardingTimelock: this.boardingTapscript.options.csvTimelock ?? chunkGUTKJMSF_cjs.DefaultVtxo.Script.DEFAULT_TIMELOCK,
|
|
8668
9015
|
delegatePubKey
|
|
8669
9016
|
};
|
|
8670
9017
|
const result = await manager.scanContracts({
|
|
@@ -8765,7 +9112,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8765
9112
|
let serverUnrollScript;
|
|
8766
9113
|
try {
|
|
8767
9114
|
const raw = base.hex.decode(setup.info.checkpointTapscript);
|
|
8768
|
-
serverUnrollScript =
|
|
9115
|
+
serverUnrollScript = chunkCMPJR3HS_cjs.CSVMultisigTapscript.decode(raw);
|
|
8769
9116
|
} catch (e) {
|
|
8770
9117
|
throw new Error("Invalid checkpointTapscript from server");
|
|
8771
9118
|
}
|
|
@@ -8796,6 +9143,16 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8796
9143
|
boot?.rotator,
|
|
8797
9144
|
boot?.provider
|
|
8798
9145
|
);
|
|
9146
|
+
if (boot?.provider) {
|
|
9147
|
+
const resolvedBoarding = await resolveBoardingBootTapscript(
|
|
9148
|
+
setup.contractRepository,
|
|
9149
|
+
setup.serverPubKey,
|
|
9150
|
+
setup.boardingTapscript
|
|
9151
|
+
);
|
|
9152
|
+
if (resolvedBoarding !== setup.boardingTapscript) {
|
|
9153
|
+
wallet.setBoardingTapscriptForRotation(resolvedBoarding);
|
|
9154
|
+
}
|
|
9155
|
+
}
|
|
8799
9156
|
await wallet.getVtxoManager();
|
|
8800
9157
|
return wallet;
|
|
8801
9158
|
}
|
|
@@ -8871,7 +9228,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8871
9228
|
inputs: params.selectedVtxos,
|
|
8872
9229
|
changeAmount: BigInt(changeAmount)
|
|
8873
9230
|
};
|
|
8874
|
-
const outputAddress =
|
|
9231
|
+
const outputAddress = chunkCMPJR3HS_cjs.ArkAddress.decode(params.address);
|
|
8875
9232
|
const outputScript = BigInt(params.amount) < this.dustAmount ? outputAddress.subdustPkScript : outputAddress.pkScript;
|
|
8876
9233
|
const outputs = [
|
|
8877
9234
|
{
|
|
@@ -8938,7 +9295,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8938
9295
|
const { fees } = await this.arkProvider.getInfo();
|
|
8939
9296
|
const estimator = new Estimator(fees.intentFee);
|
|
8940
9297
|
let amount = 0;
|
|
8941
|
-
const exitScript =
|
|
9298
|
+
const exitScript = chunkCMPJR3HS_cjs.CSVMultisigTapscript.decode(
|
|
8942
9299
|
base.hex.decode(this.boardingTapscript.exitScript)
|
|
8943
9300
|
);
|
|
8944
9301
|
const boardingTimelock = exitScript.params.timelock;
|
|
@@ -8963,7 +9320,10 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8963
9320
|
}
|
|
8964
9321
|
const vtxos = await this.getVtxos({ withRecoverable: true });
|
|
8965
9322
|
const filteredVtxos = [];
|
|
8966
|
-
for (const vtxo of vtxos) {
|
|
9323
|
+
for (const vtxo of byValueDescending(vtxos)) {
|
|
9324
|
+
if (filteredVtxos.length >= MAX_VTXOS_PER_SETTLEMENT) {
|
|
9325
|
+
break;
|
|
9326
|
+
}
|
|
8967
9327
|
const inputFee = estimator.evalOffchainInput({
|
|
8968
9328
|
amount: BigInt(vtxo.value),
|
|
8969
9329
|
type: vtxo.virtualStatus.state === "swept" ? "recoverable" : "vtxo",
|
|
@@ -8987,7 +9347,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
8987
9347
|
};
|
|
8988
9348
|
const outputFee = estimator.evalOffchainOutput({
|
|
8989
9349
|
amount: output.amount,
|
|
8990
|
-
script: base.hex.encode(
|
|
9350
|
+
script: base.hex.encode(chunkCMPJR3HS_cjs.ArkAddress.decode(output.address).pkScript)
|
|
8991
9351
|
});
|
|
8992
9352
|
output.amount -= BigInt(outputFee.satoshis);
|
|
8993
9353
|
if (output.amount <= this.dustAmount) {
|
|
@@ -9004,7 +9364,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9004
9364
|
for (const [index, output] of params.outputs.entries()) {
|
|
9005
9365
|
let script;
|
|
9006
9366
|
try {
|
|
9007
|
-
const addr =
|
|
9367
|
+
const addr = chunkCMPJR3HS_cjs.ArkAddress.decode(output.address);
|
|
9008
9368
|
script = addr.pkScript;
|
|
9009
9369
|
hasOffchainOutputs = true;
|
|
9010
9370
|
} catch {
|
|
@@ -9027,7 +9387,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9027
9387
|
}
|
|
9028
9388
|
}
|
|
9029
9389
|
let outputAssets;
|
|
9030
|
-
const destinationScript =
|
|
9390
|
+
const destinationScript = chunkCMPJR3HS_cjs.ArkAddress.decode(await this.getAddress()).pkScript;
|
|
9031
9391
|
const assetOutputIndex = findDestinationOutputIndex(outputs, destinationScript);
|
|
9032
9392
|
if (assetInputs.size > 0) {
|
|
9033
9393
|
if (assetOutputIndex === -1) {
|
|
@@ -9096,6 +9456,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9096
9456
|
eventCallback: eventCallback ? (event) => Promise.resolve(eventCallback(event)) : void 0
|
|
9097
9457
|
});
|
|
9098
9458
|
await this.updateDbAfterSettle(params.inputs, commitmentTxid);
|
|
9459
|
+
await this.maybeRotateBoardingAfterBoard(params.inputs);
|
|
9099
9460
|
return commitmentTxid;
|
|
9100
9461
|
} catch (error) {
|
|
9101
9462
|
const inputIds = params.inputs.map((i) => `${i.txid}:${i.vout}`).join(",");
|
|
@@ -9113,6 +9474,41 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9113
9474
|
});
|
|
9114
9475
|
}
|
|
9115
9476
|
}
|
|
9477
|
+
/**
|
|
9478
|
+
* Rotate the boarding address after a board (rotate-on-board trigger).
|
|
9479
|
+
*
|
|
9480
|
+
* Mirrors {@link WalletReceiveRotator}'s L2 rotation, but driven by a
|
|
9481
|
+
* board instead of a `vtxo_received` event: when a settle consumes at
|
|
9482
|
+
* least one boarding (on-chain) UTXO, the current boarding address has
|
|
9483
|
+
* served its purpose, so we allocate a fresh one via
|
|
9484
|
+
* {@link getNewBoardingAddress}. A settle that consumed only VTXOs (a
|
|
9485
|
+
* renewal / offboard) is not a board and leaves the boarding address
|
|
9486
|
+
* untouched.
|
|
9487
|
+
*
|
|
9488
|
+
* Boarding inputs are the non-VTXO coins (no `virtualStatus`), the same
|
|
9489
|
+
* discriminator {@link handleSettlementFinalizationEvent} uses; the
|
|
9490
|
+
* `typeof` guard skips arknote string inputs before the `in` test.
|
|
9491
|
+
*
|
|
9492
|
+
* No-ops for static / `auto` wallets (no descriptor provider — boarding
|
|
9493
|
+
* stays on its fixed index-0 address). Best-effort and non-fatal: the
|
|
9494
|
+
* settle has already committed and its txid must be returned, so a
|
|
9495
|
+
* rotation failure is logged and swallowed rather than thrown. Funds at
|
|
9496
|
+
* the retired boarding address remain discoverable — the old `boarding`
|
|
9497
|
+
* contract stays active and {@link getBoardingUtxos} fans out over the
|
|
9498
|
+
* full historical boarding set.
|
|
9499
|
+
*/
|
|
9500
|
+
async maybeRotateBoardingAfterBoard(inputs) {
|
|
9501
|
+
if (!this._descriptorProvider) return;
|
|
9502
|
+
const consumedBoarding = inputs.some(
|
|
9503
|
+
(input) => typeof input !== "string" && !("virtualStatus" in input)
|
|
9504
|
+
);
|
|
9505
|
+
if (!consumedBoarding) return;
|
|
9506
|
+
try {
|
|
9507
|
+
await this.getNewBoardingAddress();
|
|
9508
|
+
} catch (e) {
|
|
9509
|
+
console.warn("Failed to rotate boarding address after board", e);
|
|
9510
|
+
}
|
|
9511
|
+
}
|
|
9116
9512
|
async handleSettlementFinalizationEvent(event, inputs, forfeitOutputScript, connectorsGraph) {
|
|
9117
9513
|
const signedForfeits = [];
|
|
9118
9514
|
const isVtxo = (input) => "virtualStatus" in input;
|
|
@@ -9177,7 +9573,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9177
9573
|
index: input.vout,
|
|
9178
9574
|
witnessUtxo: {
|
|
9179
9575
|
amount: BigInt(input.value),
|
|
9180
|
-
script:
|
|
9576
|
+
script: chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
9181
9577
|
},
|
|
9182
9578
|
sighashType: btcSigner.SigHash.DEFAULT,
|
|
9183
9579
|
tapLeafScript: [input.forfeitTapLeafScript]
|
|
@@ -9196,7 +9592,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9196
9592
|
forfeitTx = await this._signerRouter.sign(forfeitTx, [
|
|
9197
9593
|
{
|
|
9198
9594
|
index: 0,
|
|
9199
|
-
lookupScript:
|
|
9595
|
+
lookupScript: chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
9200
9596
|
}
|
|
9201
9597
|
]);
|
|
9202
9598
|
signedForfeits.push(base.base64.encode(forfeitTx.toPSBT()));
|
|
@@ -9236,7 +9632,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9236
9632
|
if (skip) {
|
|
9237
9633
|
return { skip };
|
|
9238
9634
|
}
|
|
9239
|
-
const sweepTapscript =
|
|
9635
|
+
const sweepTapscript = chunkCMPJR3HS_cjs.CSVMultisigTapscript.encode({
|
|
9240
9636
|
timelock: {
|
|
9241
9637
|
value: event.batchExpiry,
|
|
9242
9638
|
type: event.batchExpiry >= 512n ? "seconds" : "blocks"
|
|
@@ -9323,11 +9719,24 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9323
9719
|
}
|
|
9324
9720
|
return jobs;
|
|
9325
9721
|
}
|
|
9722
|
+
/**
|
|
9723
|
+
* @internal Sign an on-chain boarding exit / sweep transaction, routing
|
|
9724
|
+
* each input to the correct key by its `witnessUtxo.script`: the identity
|
|
9725
|
+
* for index-0 / static boarding, the per-index descriptor for a rotated
|
|
9726
|
+
* boarding UTXO (plan §6-III.3). Used by
|
|
9727
|
+
* {@link VtxoManager.sweepExpiredBoardingUtxos}; without it, the
|
|
9728
|
+
* unilateral exit of a rotated boarding UTXO would be signed with the
|
|
9729
|
+
* wrong (index-0) key and rejected.
|
|
9730
|
+
*/
|
|
9731
|
+
async signOnchainBoardingTx(tx) {
|
|
9732
|
+
const signed = await this._signerRouter.sign(tx, this.inputSigningJobsFromWitnessUtxos(tx));
|
|
9733
|
+
return signed;
|
|
9734
|
+
}
|
|
9326
9735
|
async safeRegisterIntent(intent, inputs) {
|
|
9327
9736
|
try {
|
|
9328
9737
|
return await this.arkProvider.registerIntent(intent);
|
|
9329
9738
|
} catch (error) {
|
|
9330
|
-
if (error instanceof
|
|
9739
|
+
if (error instanceof chunkFSAXPBGP_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
|
|
9331
9740
|
const deleteIntent = await this.makeDeleteIntentSignature(inputs);
|
|
9332
9741
|
await this.arkProvider.deleteIntent(deleteIntent);
|
|
9333
9742
|
return this.arkProvider.registerIntent(intent);
|
|
@@ -9343,7 +9752,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9343
9752
|
expire_at: 0,
|
|
9344
9753
|
cosigners_public_keys: cosignerPubKeys
|
|
9345
9754
|
};
|
|
9346
|
-
const proof =
|
|
9755
|
+
const proof = chunkFSAXPBGP_cjs.Intent.create(message, coins, outputs);
|
|
9347
9756
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
9348
9757
|
return {
|
|
9349
9758
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -9355,7 +9764,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9355
9764
|
type: "delete",
|
|
9356
9765
|
expire_at: 0
|
|
9357
9766
|
};
|
|
9358
|
-
const proof =
|
|
9767
|
+
const proof = chunkFSAXPBGP_cjs.Intent.create(message, coins, []);
|
|
9359
9768
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
9360
9769
|
return {
|
|
9361
9770
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -9367,7 +9776,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9367
9776
|
type: "get-pending-tx",
|
|
9368
9777
|
expire_at: 0
|
|
9369
9778
|
};
|
|
9370
|
-
const proof =
|
|
9779
|
+
const proof = chunkFSAXPBGP_cjs.Intent.create(message, coins, []);
|
|
9371
9780
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
9372
9781
|
return {
|
|
9373
9782
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -9684,7 +10093,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9684
10093
|
);
|
|
9685
10094
|
const arkTxJobs = inputs.map((input, index) => ({
|
|
9686
10095
|
index,
|
|
9687
|
-
lookupScript:
|
|
10096
|
+
lookupScript: chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).pkScript
|
|
9688
10097
|
}));
|
|
9689
10098
|
const checkpointJobs = offchainTx.checkpoints.map(
|
|
9690
10099
|
(c) => this.inputSigningJobsFromWitnessUtxos(c)
|
|
@@ -9889,10 +10298,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9889
10298
|
// mark virtual outputs as spent/settled, remove boarding inputs
|
|
9890
10299
|
async updateDbAfterSettle(inputs, commitmentTxid) {
|
|
9891
10300
|
try {
|
|
9892
|
-
const boardingAddress = await this.getBoardingAddress();
|
|
9893
10301
|
const spentVtxos = [];
|
|
9894
10302
|
const inputArkTxIds = /* @__PURE__ */ new Set();
|
|
9895
|
-
const
|
|
10303
|
+
const boardingRemovalsByAddress = /* @__PURE__ */ new Map();
|
|
9896
10304
|
const isVtxo = (input) => "virtualStatus" in input;
|
|
9897
10305
|
const vtxoInputs = inputs.filter(isVtxo);
|
|
9898
10306
|
const cm = await this.getContractManager();
|
|
@@ -9914,7 +10322,20 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9914
10322
|
isSpent: true
|
|
9915
10323
|
});
|
|
9916
10324
|
} else {
|
|
9917
|
-
|
|
10325
|
+
let sourceAddress;
|
|
10326
|
+
try {
|
|
10327
|
+
sourceAddress = chunkCMPJR3HS_cjs.VtxoScript.decode(input.tapTree).onchainAddress(
|
|
10328
|
+
this.network
|
|
10329
|
+
);
|
|
10330
|
+
} catch {
|
|
10331
|
+
sourceAddress = this.boardingTapscript.onchainAddress(this.network);
|
|
10332
|
+
}
|
|
10333
|
+
let set = boardingRemovalsByAddress.get(sourceAddress);
|
|
10334
|
+
if (!set) {
|
|
10335
|
+
set = /* @__PURE__ */ new Set();
|
|
10336
|
+
boardingRemovalsByAddress.set(sourceAddress, set);
|
|
10337
|
+
}
|
|
10338
|
+
set.add(`${input.txid}:${input.vout}`);
|
|
9918
10339
|
}
|
|
9919
10340
|
}
|
|
9920
10341
|
if (spentVtxos.length > 0) {
|
|
@@ -9946,14 +10367,12 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
9946
10367
|
);
|
|
9947
10368
|
}
|
|
9948
10369
|
}
|
|
9949
|
-
|
|
9950
|
-
const currentUtxos = await this.walletRepository.getUtxos(
|
|
9951
|
-
const filtered = currentUtxos.filter(
|
|
9952
|
-
|
|
9953
|
-
);
|
|
9954
|
-
await this.walletRepository.deleteUtxos(boardingAddress);
|
|
10370
|
+
for (const [address, toRemove] of boardingRemovalsByAddress) {
|
|
10371
|
+
const currentUtxos = await this.walletRepository.getUtxos(address);
|
|
10372
|
+
const filtered = currentUtxos.filter((u) => !toRemove.has(`${u.txid}:${u.vout}`));
|
|
10373
|
+
await this.walletRepository.deleteUtxos(address);
|
|
9955
10374
|
if (filtered.length > 0) {
|
|
9956
|
-
await this.walletRepository.saveUtxos(
|
|
10375
|
+
await this.walletRepository.saveUtxos(address, filtered);
|
|
9957
10376
|
}
|
|
9958
10377
|
}
|
|
9959
10378
|
} catch (e) {
|
|
@@ -10161,7 +10580,7 @@ var MessageBus = class {
|
|
|
10161
10580
|
this.initialized = true;
|
|
10162
10581
|
}
|
|
10163
10582
|
async buildServices(config) {
|
|
10164
|
-
const arkProvider = new
|
|
10583
|
+
const arkProvider = new chunkFSAXPBGP_cjs.RestArkProvider(config.arkServer.url);
|
|
10165
10584
|
const storage = {
|
|
10166
10585
|
walletRepository: this.walletRepository,
|
|
10167
10586
|
contractRepository: this.contractRepository
|
|
@@ -10537,7 +10956,7 @@ var Ramps = class {
|
|
|
10537
10956
|
}
|
|
10538
10957
|
amount = amount ?? totalAmount;
|
|
10539
10958
|
const offchainAddress = await this.wallet.getAddress();
|
|
10540
|
-
const offchainAddr =
|
|
10959
|
+
const offchainAddr = chunkCMPJR3HS_cjs.ArkAddress.decode(offchainAddress);
|
|
10541
10960
|
const offchainScript = base.hex.encode(offchainAddr.pkScript);
|
|
10542
10961
|
const outputFee = estimator.evalOffchainOutput({
|
|
10543
10962
|
amount,
|
|
@@ -10635,7 +11054,7 @@ var Ramps = class {
|
|
|
10635
11054
|
let destinationScript;
|
|
10636
11055
|
for (const networkName of networkNames) {
|
|
10637
11056
|
try {
|
|
10638
|
-
const network =
|
|
11057
|
+
const network = chunkCMPJR3HS_cjs.networks[networkName];
|
|
10639
11058
|
const addr = btcSigner.Address(network).decode(destinationAddress);
|
|
10640
11059
|
destinationScript = btcSigner.OutScript.encode(addr);
|
|
10641
11060
|
break;
|
|
@@ -11204,7 +11623,7 @@ var WalletMessageHandler = class {
|
|
|
11204
11623
|
// Wallet methods
|
|
11205
11624
|
async handleInitWallet({ payload }) {
|
|
11206
11625
|
const { arkServerUrl } = payload;
|
|
11207
|
-
this.indexerProvider = new
|
|
11626
|
+
this.indexerProvider = new chunkFSAXPBGP_cjs.RestIndexerProvider(arkServerUrl);
|
|
11208
11627
|
await this.onWalletInitialized();
|
|
11209
11628
|
}
|
|
11210
11629
|
async handleGetBalance() {
|
|
@@ -11353,9 +11772,7 @@ var WalletMessageHandler = class {
|
|
|
11353
11772
|
);
|
|
11354
11773
|
}
|
|
11355
11774
|
if (funds.type === "utxo") {
|
|
11356
|
-
const utxos =
|
|
11357
|
-
const boardingAddress = await this.readonlyWallet.getBoardingAddress();
|
|
11358
|
-
await this.walletRepository?.saveUtxos(boardingAddress, utxos);
|
|
11775
|
+
const utxos = await this.readonlyWallet.getBoardingUtxos();
|
|
11359
11776
|
this.scheduleForNextTick(
|
|
11360
11777
|
() => this.tagged({
|
|
11361
11778
|
type: "UTXO_UPDATE",
|
|
@@ -11384,13 +11801,16 @@ var WalletMessageHandler = class {
|
|
|
11384
11801
|
return;
|
|
11385
11802
|
}
|
|
11386
11803
|
const vtxos = await this.getVtxosFromRepo();
|
|
11387
|
-
const
|
|
11388
|
-
const
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11804
|
+
const boardingAddresses = await this.readonlyWallet.getBoardingAddresses();
|
|
11805
|
+
const fresh = await this.readonlyWallet.getBoardingUtxos();
|
|
11806
|
+
const freshKeys = new Set(fresh.map((u) => `${u.txid}:${u.vout}`));
|
|
11807
|
+
for (const addr of boardingAddresses) {
|
|
11808
|
+
const cached = await this.walletRepository.getUtxos(addr);
|
|
11809
|
+
const kept = cached.filter((u) => freshKeys.has(`${u.txid}:${u.vout}`));
|
|
11810
|
+
if (kept.length === cached.length) continue;
|
|
11811
|
+
await this.walletRepository.deleteUtxos(addr);
|
|
11812
|
+
if (kept.length > 0) await this.walletRepository.saveUtxos(addr, kept);
|
|
11813
|
+
}
|
|
11394
11814
|
const address = await this.readonlyWallet.getAddress();
|
|
11395
11815
|
const txs = await this.buildTransactionHistoryFromCache(vtxos);
|
|
11396
11816
|
if (txs) await this.walletRepository.saveTransactions(address, txs);
|
|
@@ -12837,12 +13257,12 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
12837
13257
|
* @returns Configured onchain wallet
|
|
12838
13258
|
* @throws Error if the configured identity cannot produce a valid x-only public key
|
|
12839
13259
|
*/
|
|
12840
|
-
static async create(identity, networkName =
|
|
13260
|
+
static async create(identity, networkName = chunkCMPJR3HS_cjs.DEFAULT_NETWORK_NAME, provider) {
|
|
12841
13261
|
const pubkey = await identity.xOnlyPublicKey();
|
|
12842
13262
|
if (!pubkey) {
|
|
12843
13263
|
throw new Error("Invalid configured public key");
|
|
12844
13264
|
}
|
|
12845
|
-
const network =
|
|
13265
|
+
const network = chunkCMPJR3HS_cjs.getNetwork(networkName);
|
|
12846
13266
|
const onchainProvider = provider || new EsploraProvider(ESPLORA_URL[networkName]);
|
|
12847
13267
|
const onchainP2TR = btcSigner.p2tr(pubkey, void 0, network);
|
|
12848
13268
|
return new _OnchainWallet(identity, network, onchainP2TR, onchainProvider);
|
|
@@ -12948,7 +13368,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
12948
13368
|
if (!inputs) {
|
|
12949
13369
|
throw new Error("Fee estimation failed");
|
|
12950
13370
|
}
|
|
12951
|
-
let tx = new
|
|
13371
|
+
let tx = new chunkFSAXPBGP_cjs.Transaction();
|
|
12952
13372
|
for (const input of inputs) {
|
|
12953
13373
|
tx.addInput({
|
|
12954
13374
|
txid: input.txid,
|
|
@@ -12979,7 +13399,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
12979
13399
|
*/
|
|
12980
13400
|
async bumpP2A(parent) {
|
|
12981
13401
|
const parentVsize = parent.vsize;
|
|
12982
|
-
let child = new
|
|
13402
|
+
let child = new chunkFSAXPBGP_cjs.Transaction({
|
|
12983
13403
|
version: 3,
|
|
12984
13404
|
allowLegacyWitnessUtxo: true
|
|
12985
13405
|
});
|
|
@@ -13736,7 +14156,7 @@ exports.BIP322 = void 0;
|
|
|
13736
14156
|
async function sign2(message, identity, network) {
|
|
13737
14157
|
const xOnlyPubKey = await identity.xOnlyPublicKey();
|
|
13738
14158
|
const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
|
|
13739
|
-
const toSpend =
|
|
14159
|
+
const toSpend = chunkFSAXPBGP_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
|
|
13740
14160
|
const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
|
|
13741
14161
|
const signed = await identity.sign(toSign, [0]);
|
|
13742
14162
|
signed.finalizeIdx(0);
|
|
@@ -13794,7 +14214,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
|
|
|
13794
14214
|
if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
|
|
13795
14215
|
return false;
|
|
13796
14216
|
}
|
|
13797
|
-
const toSpend =
|
|
14217
|
+
const toSpend = chunkFSAXPBGP_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
13798
14218
|
const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
|
|
13799
14219
|
const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
|
|
13800
14220
|
const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
|
|
@@ -13815,7 +14235,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
|
|
|
13815
14235
|
}
|
|
13816
14236
|
const sighashType = sigWithHash[sigWithHash.length - 1];
|
|
13817
14237
|
const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
|
|
13818
|
-
const toSpend =
|
|
14238
|
+
const toSpend = chunkFSAXPBGP_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
13819
14239
|
const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
|
|
13820
14240
|
const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
|
|
13821
14241
|
const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
|
|
@@ -13868,7 +14288,7 @@ function encodeCompactSize(n) {
|
|
|
13868
14288
|
return buf;
|
|
13869
14289
|
}
|
|
13870
14290
|
function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
13871
|
-
const tx = new
|
|
14291
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction({ version: 0 });
|
|
13872
14292
|
tx.addInput({
|
|
13873
14293
|
txid: toSpend.id,
|
|
13874
14294
|
index: 0,
|
|
@@ -13882,12 +14302,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
|
13882
14302
|
});
|
|
13883
14303
|
tx.addOutput({
|
|
13884
14304
|
amount: 0n,
|
|
13885
|
-
script:
|
|
14305
|
+
script: chunkFSAXPBGP_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
13886
14306
|
});
|
|
13887
14307
|
return tx;
|
|
13888
14308
|
}
|
|
13889
14309
|
function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
13890
|
-
const tx = new
|
|
14310
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction({ version: 0 });
|
|
13891
14311
|
tx.addInput({
|
|
13892
14312
|
txid: toSpend.id,
|
|
13893
14313
|
index: 0,
|
|
@@ -13899,7 +14319,7 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
|
13899
14319
|
});
|
|
13900
14320
|
tx.addOutput({
|
|
13901
14321
|
amount: 0n,
|
|
13902
|
-
script:
|
|
14322
|
+
script: chunkFSAXPBGP_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
13903
14323
|
});
|
|
13904
14324
|
return tx;
|
|
13905
14325
|
}
|
|
@@ -13960,7 +14380,7 @@ exports.Unroll = void 0;
|
|
|
13960
14380
|
if (virtualTxs.txs.length === 0) {
|
|
13961
14381
|
throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
|
|
13962
14382
|
}
|
|
13963
|
-
const tx =
|
|
14383
|
+
const tx = chunkFSAXPBGP_cjs.Transaction.fromPSBT(base.base64.decode(virtualTxs.txs[0]));
|
|
13964
14384
|
if (nextTxToBroadcast.type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
|
|
13965
14385
|
const input = tx.getInput(0);
|
|
13966
14386
|
if (!input) {
|
|
@@ -14037,12 +14457,12 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
14037
14457
|
if (!exit) {
|
|
14038
14458
|
throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
|
|
14039
14459
|
}
|
|
14040
|
-
const spendingLeaf =
|
|
14460
|
+
const spendingLeaf = chunkCMPJR3HS_cjs.VtxoScript.decode(vtxo.tapTree).findLeaf(base.hex.encode(exit.script));
|
|
14041
14461
|
if (!spendingLeaf) {
|
|
14042
14462
|
throw new Error(`spending leaf not found for vtxo ${vtxo.txid}:${vtxo.vout}`);
|
|
14043
14463
|
}
|
|
14044
14464
|
totalAmount += BigInt(vtxo.value);
|
|
14045
|
-
const sequence =
|
|
14465
|
+
const sequence = chunkCMPJR3HS_cjs.timelockToSequence(exit.params.timelock);
|
|
14046
14466
|
inputs.push({
|
|
14047
14467
|
txid: vtxo.txid,
|
|
14048
14468
|
index: vtxo.vout,
|
|
@@ -14050,7 +14470,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
14050
14470
|
sequence,
|
|
14051
14471
|
witnessUtxo: {
|
|
14052
14472
|
amount: BigInt(vtxo.value),
|
|
14053
|
-
script:
|
|
14473
|
+
script: chunkCMPJR3HS_cjs.VtxoScript.decode(vtxo.tapTree).pkScript
|
|
14054
14474
|
},
|
|
14055
14475
|
sighashType: btcSigner.SigHash.DEFAULT
|
|
14056
14476
|
});
|
|
@@ -14060,7 +14480,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
14060
14480
|
btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
|
|
14061
14481
|
);
|
|
14062
14482
|
}
|
|
14063
|
-
const tx = new
|
|
14483
|
+
const tx = new chunkFSAXPBGP_cjs.Transaction({ version: 2 });
|
|
14064
14484
|
for (const input of inputs) {
|
|
14065
14485
|
tx.addInput(input);
|
|
14066
14486
|
}
|
|
@@ -14107,7 +14527,7 @@ function doWait(onchainProvider, txid) {
|
|
|
14107
14527
|
};
|
|
14108
14528
|
}
|
|
14109
14529
|
function availableExitPath(confirmedAt, current, vtxo) {
|
|
14110
|
-
const exits =
|
|
14530
|
+
const exits = chunkCMPJR3HS_cjs.VtxoScript.decode(vtxo.tapTree).exitPaths();
|
|
14111
14531
|
for (const exit of exits) {
|
|
14112
14532
|
if (exit.params.timelock.type === "blocks") {
|
|
14113
14533
|
if (current.height >= confirmedAt.height + Number(exit.params.timelock.value)) {
|
|
@@ -14146,7 +14566,7 @@ function decodeArkContract(encoded) {
|
|
|
14146
14566
|
}
|
|
14147
14567
|
function contractFromArkContract(encoded, options = {}) {
|
|
14148
14568
|
const parsed = decodeArkContract(encoded);
|
|
14149
|
-
const handler =
|
|
14569
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.get(parsed.type);
|
|
14150
14570
|
if (!handler) {
|
|
14151
14571
|
throw new Error(`No handler registered for contract type '${parsed.type}'`);
|
|
14152
14572
|
}
|
|
@@ -14160,9 +14580,9 @@ function contractFromArkContract(encoded, options = {}) {
|
|
|
14160
14580
|
metadata: options.metadata
|
|
14161
14581
|
};
|
|
14162
14582
|
}
|
|
14163
|
-
function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix =
|
|
14583
|
+
function contractFromArkContractWithAddress(encoded, serverPubKey, addressPrefix = chunkCMPJR3HS_cjs.DEFAULT_NETWORK.hrp, options = {}) {
|
|
14164
14584
|
const parsed = decodeArkContract(encoded);
|
|
14165
|
-
const handler =
|
|
14585
|
+
const handler = chunkGUTKJMSF_cjs.contractHandlers.getOrThrow(parsed.type);
|
|
14166
14586
|
const params = parsed.data;
|
|
14167
14587
|
const vtxoScript = handler.createScript(params);
|
|
14168
14588
|
return {
|
|
@@ -14274,5 +14694,5 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
|
14274
14694
|
exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
|
|
14275
14695
|
exports.waitForIncomingFunds = waitForIncomingFunds;
|
|
14276
14696
|
exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
|
|
14277
|
-
//# sourceMappingURL=chunk-
|
|
14278
|
-
//# sourceMappingURL=chunk-
|
|
14697
|
+
//# sourceMappingURL=chunk-XCHBQVMK.cjs.map
|
|
14698
|
+
//# sourceMappingURL=chunk-XCHBQVMK.cjs.map
|