@arkade-os/sdk 0.4.43 → 0.4.44
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 +65 -0
- package/dist/adapters/expo.cjs +4 -4
- package/dist/adapters/expo.js +2 -2
- package/dist/adapters/indexedDB.cjs +3 -3
- package/dist/adapters/indexedDB.js +2 -2
- package/dist/{asyncStorageTaskQueue-CjoL-35w.d.ts → asyncStorageTaskQueue-BtSOVZFn.d.ts} +2 -2
- package/dist/{asyncStorageTaskQueue-D1FfHfgK.d.cts → asyncStorageTaskQueue-Dap7qUlF.d.cts} +2 -2
- package/dist/{chunk-B4R36PRN.js → chunk-FMI2GKYO.js} +1088 -181
- package/dist/chunk-FMI2GKYO.js.map +1 -0
- package/dist/{chunk-US274KZO.js → chunk-LCQQPOIT.js} +3 -3
- package/dist/{chunk-US274KZO.js.map → chunk-LCQQPOIT.js.map} +1 -1
- package/dist/{chunk-763XHDAJ.js → chunk-LJ35HPJW.js} +3 -3
- package/dist/{chunk-763XHDAJ.js.map → chunk-LJ35HPJW.js.map} +1 -1
- package/dist/{chunk-JIWCE2IK.cjs → chunk-RJ6XVCX4.cjs} +7 -7
- package/dist/{chunk-JIWCE2IK.cjs.map → chunk-RJ6XVCX4.cjs.map} +1 -1
- package/dist/{chunk-3AQNLQPM.cjs → chunk-UBYY2TPK.cjs} +3 -3
- package/dist/{chunk-3AQNLQPM.cjs.map → chunk-UBYY2TPK.cjs.map} +1 -1
- package/dist/{chunk-VKKLOT2E.js → chunk-V7WIZR2B.js} +3 -3
- package/dist/{chunk-VKKLOT2E.js.map → chunk-V7WIZR2B.js.map} +1 -1
- package/dist/{chunk-PLJZRIFZ.cjs → chunk-X37EKDIH.cjs} +11 -11
- package/dist/{chunk-PLJZRIFZ.cjs.map → chunk-X37EKDIH.cjs.map} +1 -1
- package/dist/{chunk-QGNTDGMN.cjs → chunk-XIVCG6EP.cjs} +1163 -253
- package/dist/chunk-XIVCG6EP.cjs.map +1 -0
- package/dist/index.cjs +138 -126
- package/dist/index.d.cts +232 -1
- package/dist/index.d.ts +232 -1
- package/dist/index.js +2 -2
- package/dist/repositories/realm/index.cjs +17 -17
- package/dist/repositories/realm/index.js +3 -3
- package/dist/repositories/sqlite/index.cjs +16 -16
- package/dist/repositories/sqlite/index.js +3 -3
- package/dist/{taskRunner-Djlhfgi1.d.ts → taskRunner-Bptw9UMa.d.ts} +1 -1
- package/dist/{taskRunner-BSnslNmq.d.cts → taskRunner-CeFxKhSH.d.cts} +1 -1
- package/dist/wallet/expo/background.cjs +12 -12
- package/dist/wallet/expo/background.d.cts +2 -2
- package/dist/wallet/expo/background.d.ts +2 -2
- package/dist/wallet/expo/background.js +4 -4
- package/dist/wallet/expo/index.cjs +12 -12
- package/dist/wallet/expo/index.d.cts +1 -1
- package/dist/wallet/expo/index.d.ts +1 -1
- package/dist/wallet/expo/index.js +3 -3
- package/dist/worker/expo/index.cjs +7 -7
- package/dist/worker/expo/index.d.cts +3 -3
- package/dist/worker/expo/index.d.ts +3 -3
- package/dist/worker/expo/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-B4R36PRN.js.map +0 -1
- package/dist/chunk-QGNTDGMN.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkUBYY2TPK_cjs = require('./chunk-UBYY2TPK.cjs');
|
|
4
4
|
var chunk32YKLQPS_cjs = require('./chunk-32YKLQPS.cjs');
|
|
5
5
|
var chunkHXDZ2QTW_cjs = require('./chunk-HXDZ2QTW.cjs');
|
|
6
6
|
var utils_js = require('@scure/btc-signer/utils.js');
|
|
@@ -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 = chunkUBYY2TPK_cjs.getArkPsbtFields(tx.root, 0, chunkUBYY2TPK_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 = chunkUBYY2TPK_cjs.getArkPsbtFields(g.root, 0, chunkUBYY2TPK_cjs.CosignerPublicKey).map((c) => c.key);
|
|
237
237
|
const { finalKey } = aggregateKeys(cosigners, true, {
|
|
238
238
|
taprootTweak: this.scriptRoot
|
|
239
239
|
});
|
|
@@ -980,14 +980,14 @@ var RestDelegateProvider = class {
|
|
|
980
980
|
*/
|
|
981
981
|
async delegate(intent, forfeitTxs, options) {
|
|
982
982
|
const url = `${this.url}/v1/delegate`;
|
|
983
|
-
const response = await
|
|
983
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(url, {
|
|
984
984
|
method: "POST",
|
|
985
985
|
headers: {
|
|
986
986
|
"Content-Type": "application/json"
|
|
987
987
|
},
|
|
988
988
|
body: JSON.stringify({
|
|
989
989
|
intent: {
|
|
990
|
-
message:
|
|
990
|
+
message: chunkUBYY2TPK_cjs.Intent.encodeMessage(intent.message),
|
|
991
991
|
proof: intent.proof
|
|
992
992
|
},
|
|
993
993
|
forfeit_txs: forfeitTxs,
|
|
@@ -1007,7 +1007,7 @@ var RestDelegateProvider = class {
|
|
|
1007
1007
|
*/
|
|
1008
1008
|
async getDelegateInfo() {
|
|
1009
1009
|
const url = `${this.url}/v1/delegator/info`;
|
|
1010
|
-
const response = await
|
|
1010
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(url);
|
|
1011
1011
|
if (!response.ok) {
|
|
1012
1012
|
const errorText2 = await response.text();
|
|
1013
1013
|
throw new Error(`Failed to get delegate info: ${errorText2}`);
|
|
@@ -1042,14 +1042,14 @@ var EsploraProvider = class {
|
|
|
1042
1042
|
pollingInterval;
|
|
1043
1043
|
forcePolling;
|
|
1044
1044
|
async getCoins(address) {
|
|
1045
|
-
const response = await
|
|
1045
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/address/${address}/utxo`);
|
|
1046
1046
|
if (!response.ok) {
|
|
1047
1047
|
throw new Error(`Failed to fetch UTXOs: ${response.statusText}`);
|
|
1048
1048
|
}
|
|
1049
1049
|
return response.json();
|
|
1050
1050
|
}
|
|
1051
1051
|
async getFeeRate() {
|
|
1052
|
-
const response = await
|
|
1052
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/fee-estimates`);
|
|
1053
1053
|
if (response.status === 404) {
|
|
1054
1054
|
return void 0;
|
|
1055
1055
|
}
|
|
@@ -1070,7 +1070,7 @@ var EsploraProvider = class {
|
|
|
1070
1070
|
}
|
|
1071
1071
|
}
|
|
1072
1072
|
async getTxOutspends(txid) {
|
|
1073
|
-
const response = await
|
|
1073
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/outspends`);
|
|
1074
1074
|
if (!response.ok) {
|
|
1075
1075
|
const error = await response.text();
|
|
1076
1076
|
throw new Error(`Failed to get transaction outspends: ${error}`);
|
|
@@ -1078,7 +1078,7 @@ var EsploraProvider = class {
|
|
|
1078
1078
|
return response.json();
|
|
1079
1079
|
}
|
|
1080
1080
|
async getTransactions(address) {
|
|
1081
|
-
const response = await
|
|
1081
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/address/${address}/txs`);
|
|
1082
1082
|
if (!response.ok) {
|
|
1083
1083
|
const error = await response.text();
|
|
1084
1084
|
throw new Error(`Failed to get transactions: ${error}`);
|
|
@@ -1086,7 +1086,7 @@ var EsploraProvider = class {
|
|
|
1086
1086
|
return response.json();
|
|
1087
1087
|
}
|
|
1088
1088
|
async getTxStatus(txid) {
|
|
1089
|
-
const txresponse = await
|
|
1089
|
+
const txresponse = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/tx/${txid}`);
|
|
1090
1090
|
if (!txresponse.ok) {
|
|
1091
1091
|
throw new Error(txresponse.statusText);
|
|
1092
1092
|
}
|
|
@@ -1094,7 +1094,7 @@ var EsploraProvider = class {
|
|
|
1094
1094
|
if (!tx.status.confirmed) {
|
|
1095
1095
|
return { confirmed: false };
|
|
1096
1096
|
}
|
|
1097
|
-
const response = await
|
|
1097
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/tx/${txid}/status`);
|
|
1098
1098
|
if (!response.ok) {
|
|
1099
1099
|
throw new Error(`Failed to get transaction status: ${response.statusText}`);
|
|
1100
1100
|
}
|
|
@@ -1178,7 +1178,7 @@ var EsploraProvider = class {
|
|
|
1178
1178
|
return stopFunc;
|
|
1179
1179
|
}
|
|
1180
1180
|
async getChainTip() {
|
|
1181
|
-
const tipBlocks = await
|
|
1181
|
+
const tipBlocks = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/blocks`);
|
|
1182
1182
|
if (!tipBlocks.ok) {
|
|
1183
1183
|
throw new Error(`Failed to get chain tip: ${tipBlocks.statusText}`);
|
|
1184
1184
|
}
|
|
@@ -1197,7 +1197,7 @@ var EsploraProvider = class {
|
|
|
1197
1197
|
};
|
|
1198
1198
|
}
|
|
1199
1199
|
async broadcastPackage(parent, child) {
|
|
1200
|
-
const response = await
|
|
1200
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/txs/package`, {
|
|
1201
1201
|
method: "POST",
|
|
1202
1202
|
headers: {
|
|
1203
1203
|
"Content-Type": "application/json"
|
|
@@ -1211,7 +1211,7 @@ var EsploraProvider = class {
|
|
|
1211
1211
|
return response.json();
|
|
1212
1212
|
}
|
|
1213
1213
|
async broadcastTx(tx) {
|
|
1214
|
-
const response = await
|
|
1214
|
+
const response = await chunkUBYY2TPK_cjs.baseFetch(`${this.baseUrl}/tx`, {
|
|
1215
1215
|
method: "POST",
|
|
1216
1216
|
headers: {
|
|
1217
1217
|
"Content-Type": "text/plain"
|
|
@@ -1237,6 +1237,114 @@ var isExplorerTransaction = (tx) => {
|
|
|
1237
1237
|
(vout) => typeof vout.scriptpubkey_address === "string" && typeof vout.value === "number"
|
|
1238
1238
|
) && typeof tx.status === "object" && typeof tx.status.confirmed === "boolean";
|
|
1239
1239
|
};
|
|
1240
|
+
var getVarIntSize = (n) => {
|
|
1241
|
+
if (n < 253) return 1;
|
|
1242
|
+
if (n <= 65535) return 3;
|
|
1243
|
+
if (n <= 4294967295) return 5;
|
|
1244
|
+
return 9;
|
|
1245
|
+
};
|
|
1246
|
+
var TxWeightEstimator = class _TxWeightEstimator {
|
|
1247
|
+
static P2PKH_SCRIPT_SIG_SIZE = 1 + 73 + 1 + 33;
|
|
1248
|
+
static INPUT_SIZE = 32 + 4 + 1 + 4;
|
|
1249
|
+
static BASE_CONTROL_BLOCK_SIZE = 1 + 32;
|
|
1250
|
+
static OUTPUT_SIZE = 8 + 1;
|
|
1251
|
+
static P2WPKH_OUTPUT_SIZE = 1 + 1 + 20;
|
|
1252
|
+
static BASE_TX_SIZE = 8 + 2;
|
|
1253
|
+
// Version + LockTime
|
|
1254
|
+
static WITNESS_HEADER_SIZE = 2;
|
|
1255
|
+
// Flag + Marker
|
|
1256
|
+
static WITNESS_SCALE_FACTOR = 4;
|
|
1257
|
+
static P2TR_OUTPUT_SIZE = 1 + 1 + 32;
|
|
1258
|
+
hasWitness;
|
|
1259
|
+
inputCount;
|
|
1260
|
+
outputCount;
|
|
1261
|
+
inputSize;
|
|
1262
|
+
inputWitnessSize;
|
|
1263
|
+
outputSize;
|
|
1264
|
+
constructor(hasWitness, inputCount, outputCount, inputSize, inputWitnessSize, outputSize) {
|
|
1265
|
+
this.hasWitness = hasWitness;
|
|
1266
|
+
this.inputCount = inputCount;
|
|
1267
|
+
this.outputCount = outputCount;
|
|
1268
|
+
this.inputSize = inputSize;
|
|
1269
|
+
this.inputWitnessSize = inputWitnessSize;
|
|
1270
|
+
this.outputSize = outputSize;
|
|
1271
|
+
}
|
|
1272
|
+
static create() {
|
|
1273
|
+
return new _TxWeightEstimator(false, 0, 0, 0, 0, 0);
|
|
1274
|
+
}
|
|
1275
|
+
addP2AInput() {
|
|
1276
|
+
this.inputCount++;
|
|
1277
|
+
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
1278
|
+
return this;
|
|
1279
|
+
}
|
|
1280
|
+
addKeySpendInput(isDefault = true) {
|
|
1281
|
+
this.inputCount++;
|
|
1282
|
+
this.inputWitnessSize += 64 + 1 + (isDefault ? 0 : 1);
|
|
1283
|
+
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
1284
|
+
this.hasWitness = true;
|
|
1285
|
+
return this;
|
|
1286
|
+
}
|
|
1287
|
+
addP2PKHInput() {
|
|
1288
|
+
this.inputCount++;
|
|
1289
|
+
this.inputWitnessSize++;
|
|
1290
|
+
this.inputSize += _TxWeightEstimator.INPUT_SIZE + _TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE;
|
|
1291
|
+
return this;
|
|
1292
|
+
}
|
|
1293
|
+
addTapscriptInput(leafWitnessSize, leafScriptSize, leafControlBlockSize) {
|
|
1294
|
+
const controlBlockWitnessSize = 1 + _TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE + 1 + leafScriptSize + 1 + leafControlBlockSize;
|
|
1295
|
+
this.inputCount++;
|
|
1296
|
+
this.inputWitnessSize += leafWitnessSize + 1 + controlBlockWitnessSize;
|
|
1297
|
+
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
1298
|
+
this.hasWitness = true;
|
|
1299
|
+
return this;
|
|
1300
|
+
}
|
|
1301
|
+
addP2WPKHOutput() {
|
|
1302
|
+
this.outputCount++;
|
|
1303
|
+
this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2WPKH_OUTPUT_SIZE;
|
|
1304
|
+
return this;
|
|
1305
|
+
}
|
|
1306
|
+
addP2TROutput() {
|
|
1307
|
+
this.outputCount++;
|
|
1308
|
+
this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2TR_OUTPUT_SIZE;
|
|
1309
|
+
return this;
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Adds an output given a raw script.
|
|
1313
|
+
* Cost = 8 bytes (amount) + varint(scriptLen) + scriptLen
|
|
1314
|
+
*/
|
|
1315
|
+
addOutputScript(script) {
|
|
1316
|
+
this.outputCount++;
|
|
1317
|
+
this.outputSize += 8 + getVarIntSize(script.length) + script.length;
|
|
1318
|
+
return this;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Adds an output by decoding the address to get the exact script size.
|
|
1322
|
+
*/
|
|
1323
|
+
addOutputAddress(address, network) {
|
|
1324
|
+
const payment = btcSigner.Address(network).decode(address);
|
|
1325
|
+
const script = btcSigner.OutScript.encode(payment);
|
|
1326
|
+
return this.addOutputScript(script);
|
|
1327
|
+
}
|
|
1328
|
+
vsize() {
|
|
1329
|
+
const inputCount = getVarIntSize(this.inputCount);
|
|
1330
|
+
const outputCount = getVarIntSize(this.outputCount);
|
|
1331
|
+
const txSizeStripped = _TxWeightEstimator.BASE_TX_SIZE + inputCount + this.inputSize + outputCount + this.outputSize;
|
|
1332
|
+
let weight = txSizeStripped * _TxWeightEstimator.WITNESS_SCALE_FACTOR;
|
|
1333
|
+
if (this.hasWitness) {
|
|
1334
|
+
weight += _TxWeightEstimator.WITNESS_HEADER_SIZE + this.inputWitnessSize;
|
|
1335
|
+
}
|
|
1336
|
+
return vsize(weight);
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
var vsize = (weight) => {
|
|
1340
|
+
const value = BigInt(Math.ceil(weight / TxWeightEstimator.WITNESS_SCALE_FACTOR));
|
|
1341
|
+
return {
|
|
1342
|
+
value,
|
|
1343
|
+
fee: (feeRate) => feeRate * value
|
|
1344
|
+
};
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1347
|
+
// src/utils/anchor.ts
|
|
1240
1348
|
var ANCHOR_VALUE = 0n;
|
|
1241
1349
|
var ANCHOR_PKSCRIPT = new Uint8Array([81, 2, 78, 115]);
|
|
1242
1350
|
var P2A = {
|
|
@@ -1262,6 +1370,37 @@ function findP2AOutput(tx) {
|
|
|
1262
1370
|
}
|
|
1263
1371
|
throw new Error("P2A output not found");
|
|
1264
1372
|
}
|
|
1373
|
+
var CHILD_DUST_AMOUNT = 546;
|
|
1374
|
+
function buildAnchorChild(params) {
|
|
1375
|
+
const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
|
|
1376
|
+
const child = new chunkUBYY2TPK_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
|
|
1377
|
+
child.addInput(findP2AOutput(parent));
|
|
1378
|
+
const estimator = TxWeightEstimator.create().addP2AInput();
|
|
1379
|
+
for (const _ of fundingCoins) {
|
|
1380
|
+
estimator.addKeySpendInput(true);
|
|
1381
|
+
}
|
|
1382
|
+
estimator.addOutputAddress(changeAddress, network);
|
|
1383
|
+
const childVsize = Number(estimator.vsize().value);
|
|
1384
|
+
const fee = Math.ceil(feeRate * (parent.vsize + childVsize));
|
|
1385
|
+
let total = 0n;
|
|
1386
|
+
for (const coin of fundingCoins) {
|
|
1387
|
+
total += BigInt(coin.value);
|
|
1388
|
+
child.addInput({
|
|
1389
|
+
txid: coin.txid,
|
|
1390
|
+
index: coin.vout,
|
|
1391
|
+
witnessUtxo: { script: params.changeScript, amount: BigInt(coin.value) },
|
|
1392
|
+
tapInternalKey
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
const change = total + P2A.amount - BigInt(fee);
|
|
1396
|
+
if (change < BigInt(CHILD_DUST_AMOUNT)) {
|
|
1397
|
+
throw new Error(
|
|
1398
|
+
`insufficient funding for anchor child: need change >= ${CHILD_DUST_AMOUNT}, got ${change}`
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
child.addOutputAddress(changeAddress, change, network);
|
|
1402
|
+
return { child, fee };
|
|
1403
|
+
}
|
|
1265
1404
|
|
|
1266
1405
|
// src/forfeit.ts
|
|
1267
1406
|
function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
|
|
@@ -1282,7 +1421,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
|
|
|
1282
1421
|
);
|
|
1283
1422
|
}
|
|
1284
1423
|
function buildForfeitTxWithOutput(inputs, output, txLocktime) {
|
|
1285
|
-
const tx = new
|
|
1424
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({
|
|
1286
1425
|
version: 3,
|
|
1287
1426
|
lockTime: txLocktime
|
|
1288
1427
|
});
|
|
@@ -1358,7 +1497,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
1358
1497
|
if (previousScriptKey.length !== 32) {
|
|
1359
1498
|
throw new Error(`parent output ${childIndex} has invalid script`);
|
|
1360
1499
|
}
|
|
1361
|
-
const cosigners =
|
|
1500
|
+
const cosigners = chunkUBYY2TPK_cjs.getArkPsbtFields(child.root, 0, chunkUBYY2TPK_cjs.CosignerPublicKey);
|
|
1362
1501
|
if (cosigners.length === 0) {
|
|
1363
1502
|
throw ErrMissingCosignersPublicKeys;
|
|
1364
1503
|
}
|
|
@@ -1458,7 +1597,7 @@ var Extension = class _Extension {
|
|
|
1458
1597
|
`expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
|
|
1459
1598
|
);
|
|
1460
1599
|
}
|
|
1461
|
-
const reader = new
|
|
1600
|
+
const reader = new chunkUBYY2TPK_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
|
|
1462
1601
|
const packets = [];
|
|
1463
1602
|
while (reader.remaining() > 0) {
|
|
1464
1603
|
const packetType = reader.readByte();
|
|
@@ -1532,7 +1671,7 @@ var Extension = class _Extension {
|
|
|
1532
1671
|
*/
|
|
1533
1672
|
getAssetPacket() {
|
|
1534
1673
|
for (const p of this.packets) {
|
|
1535
|
-
if (p instanceof
|
|
1674
|
+
if (p instanceof chunkUBYY2TPK_cjs.Packet) {
|
|
1536
1675
|
return p;
|
|
1537
1676
|
}
|
|
1538
1677
|
}
|
|
@@ -1540,8 +1679,8 @@ var Extension = class _Extension {
|
|
|
1540
1679
|
}
|
|
1541
1680
|
};
|
|
1542
1681
|
function parsePacket(packetType, data) {
|
|
1543
|
-
if (packetType ===
|
|
1544
|
-
return
|
|
1682
|
+
if (packetType === chunkUBYY2TPK_cjs.Packet.PACKET_TYPE) {
|
|
1683
|
+
return chunkUBYY2TPK_cjs.Packet.fromBytes(data);
|
|
1545
1684
|
}
|
|
1546
1685
|
return new UnknownPacket(packetType, data);
|
|
1547
1686
|
}
|
|
@@ -1848,7 +1987,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1848
1987
|
const existing = inputsByAssetId.get(asset.assetId);
|
|
1849
1988
|
inputsByAssetId.set(asset.assetId, [
|
|
1850
1989
|
...existing ?? [],
|
|
1851
|
-
|
|
1990
|
+
chunkUBYY2TPK_cjs.AssetInput.create(inputIndex, asset.amount)
|
|
1852
1991
|
]);
|
|
1853
1992
|
}
|
|
1854
1993
|
}
|
|
@@ -1860,7 +1999,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1860
1999
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
1861
2000
|
outputsByAssetId.set(asset.assetId, [
|
|
1862
2001
|
...existing ?? [],
|
|
1863
|
-
|
|
2002
|
+
chunkUBYY2TPK_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
1864
2003
|
]);
|
|
1865
2004
|
}
|
|
1866
2005
|
}
|
|
@@ -1871,7 +2010,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1871
2010
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
1872
2011
|
outputsByAssetId.set(asset.assetId, [
|
|
1873
2012
|
...existing ?? [],
|
|
1874
|
-
|
|
2013
|
+
chunkUBYY2TPK_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
1875
2014
|
]);
|
|
1876
2015
|
}
|
|
1877
2016
|
}
|
|
@@ -1880,11 +2019,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1880
2019
|
for (const assetIdStr of allAssetIds) {
|
|
1881
2020
|
const inputs = inputsByAssetId.get(assetIdStr);
|
|
1882
2021
|
const outputs = outputsByAssetId.get(assetIdStr);
|
|
1883
|
-
const assetId =
|
|
1884
|
-
const group =
|
|
2022
|
+
const assetId = chunkUBYY2TPK_cjs.AssetId.fromString(assetIdStr);
|
|
2023
|
+
const group = chunkUBYY2TPK_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
|
|
1885
2024
|
groups.push(group);
|
|
1886
2025
|
}
|
|
1887
|
-
return
|
|
2026
|
+
return chunkUBYY2TPK_cjs.Packet.create(groups);
|
|
1888
2027
|
}
|
|
1889
2028
|
function selectCoinsWithAsset(coins, assetId, requiredAmount) {
|
|
1890
2029
|
const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
|
|
@@ -2001,7 +2140,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
2001
2140
|
}
|
|
2002
2141
|
}
|
|
2003
2142
|
}
|
|
2004
|
-
const tx = new
|
|
2143
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({
|
|
2005
2144
|
version: 3,
|
|
2006
2145
|
lockTime: Number(lockTime)
|
|
2007
2146
|
});
|
|
@@ -2016,7 +2155,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
2016
2155
|
},
|
|
2017
2156
|
tapLeafScript: [input.tapLeafScript]
|
|
2018
2157
|
});
|
|
2019
|
-
|
|
2158
|
+
chunkUBYY2TPK_cjs.setArkPsbtField(tx, i, chunkUBYY2TPK_cjs.VtxoTaprootTree, input.tapTree);
|
|
2020
2159
|
}
|
|
2021
2160
|
for (const output of outputs) {
|
|
2022
2161
|
tx.addOutput(output);
|
|
@@ -2176,112 +2315,6 @@ function isValidArkAddress(address) {
|
|
|
2176
2315
|
return false;
|
|
2177
2316
|
}
|
|
2178
2317
|
}
|
|
2179
|
-
var getVarIntSize = (n) => {
|
|
2180
|
-
if (n < 253) return 1;
|
|
2181
|
-
if (n <= 65535) return 3;
|
|
2182
|
-
if (n <= 4294967295) return 5;
|
|
2183
|
-
return 9;
|
|
2184
|
-
};
|
|
2185
|
-
var TxWeightEstimator = class _TxWeightEstimator {
|
|
2186
|
-
static P2PKH_SCRIPT_SIG_SIZE = 1 + 73 + 1 + 33;
|
|
2187
|
-
static INPUT_SIZE = 32 + 4 + 1 + 4;
|
|
2188
|
-
static BASE_CONTROL_BLOCK_SIZE = 1 + 32;
|
|
2189
|
-
static OUTPUT_SIZE = 8 + 1;
|
|
2190
|
-
static P2WPKH_OUTPUT_SIZE = 1 + 1 + 20;
|
|
2191
|
-
static BASE_TX_SIZE = 8 + 2;
|
|
2192
|
-
// Version + LockTime
|
|
2193
|
-
static WITNESS_HEADER_SIZE = 2;
|
|
2194
|
-
// Flag + Marker
|
|
2195
|
-
static WITNESS_SCALE_FACTOR = 4;
|
|
2196
|
-
static P2TR_OUTPUT_SIZE = 1 + 1 + 32;
|
|
2197
|
-
hasWitness;
|
|
2198
|
-
inputCount;
|
|
2199
|
-
outputCount;
|
|
2200
|
-
inputSize;
|
|
2201
|
-
inputWitnessSize;
|
|
2202
|
-
outputSize;
|
|
2203
|
-
constructor(hasWitness, inputCount, outputCount, inputSize, inputWitnessSize, outputSize) {
|
|
2204
|
-
this.hasWitness = hasWitness;
|
|
2205
|
-
this.inputCount = inputCount;
|
|
2206
|
-
this.outputCount = outputCount;
|
|
2207
|
-
this.inputSize = inputSize;
|
|
2208
|
-
this.inputWitnessSize = inputWitnessSize;
|
|
2209
|
-
this.outputSize = outputSize;
|
|
2210
|
-
}
|
|
2211
|
-
static create() {
|
|
2212
|
-
return new _TxWeightEstimator(false, 0, 0, 0, 0, 0);
|
|
2213
|
-
}
|
|
2214
|
-
addP2AInput() {
|
|
2215
|
-
this.inputCount++;
|
|
2216
|
-
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
2217
|
-
return this;
|
|
2218
|
-
}
|
|
2219
|
-
addKeySpendInput(isDefault = true) {
|
|
2220
|
-
this.inputCount++;
|
|
2221
|
-
this.inputWitnessSize += 64 + 1 + (isDefault ? 0 : 1);
|
|
2222
|
-
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
2223
|
-
this.hasWitness = true;
|
|
2224
|
-
return this;
|
|
2225
|
-
}
|
|
2226
|
-
addP2PKHInput() {
|
|
2227
|
-
this.inputCount++;
|
|
2228
|
-
this.inputWitnessSize++;
|
|
2229
|
-
this.inputSize += _TxWeightEstimator.INPUT_SIZE + _TxWeightEstimator.P2PKH_SCRIPT_SIG_SIZE;
|
|
2230
|
-
return this;
|
|
2231
|
-
}
|
|
2232
|
-
addTapscriptInput(leafWitnessSize, leafScriptSize, leafControlBlockSize) {
|
|
2233
|
-
const controlBlockWitnessSize = 1 + _TxWeightEstimator.BASE_CONTROL_BLOCK_SIZE + 1 + leafScriptSize + 1 + leafControlBlockSize;
|
|
2234
|
-
this.inputCount++;
|
|
2235
|
-
this.inputWitnessSize += leafWitnessSize + 1 + controlBlockWitnessSize;
|
|
2236
|
-
this.inputSize += _TxWeightEstimator.INPUT_SIZE;
|
|
2237
|
-
this.hasWitness = true;
|
|
2238
|
-
return this;
|
|
2239
|
-
}
|
|
2240
|
-
addP2WPKHOutput() {
|
|
2241
|
-
this.outputCount++;
|
|
2242
|
-
this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2WPKH_OUTPUT_SIZE;
|
|
2243
|
-
return this;
|
|
2244
|
-
}
|
|
2245
|
-
addP2TROutput() {
|
|
2246
|
-
this.outputCount++;
|
|
2247
|
-
this.outputSize += _TxWeightEstimator.OUTPUT_SIZE + _TxWeightEstimator.P2TR_OUTPUT_SIZE;
|
|
2248
|
-
return this;
|
|
2249
|
-
}
|
|
2250
|
-
/**
|
|
2251
|
-
* Adds an output given a raw script.
|
|
2252
|
-
* Cost = 8 bytes (amount) + varint(scriptLen) + scriptLen
|
|
2253
|
-
*/
|
|
2254
|
-
addOutputScript(script) {
|
|
2255
|
-
this.outputCount++;
|
|
2256
|
-
this.outputSize += 8 + getVarIntSize(script.length) + script.length;
|
|
2257
|
-
return this;
|
|
2258
|
-
}
|
|
2259
|
-
/**
|
|
2260
|
-
* Adds an output by decoding the address to get the exact script size.
|
|
2261
|
-
*/
|
|
2262
|
-
addOutputAddress(address, network) {
|
|
2263
|
-
const payment = btcSigner.Address(network).decode(address);
|
|
2264
|
-
const script = btcSigner.OutScript.encode(payment);
|
|
2265
|
-
return this.addOutputScript(script);
|
|
2266
|
-
}
|
|
2267
|
-
vsize() {
|
|
2268
|
-
const inputCount = getVarIntSize(this.inputCount);
|
|
2269
|
-
const outputCount = getVarIntSize(this.outputCount);
|
|
2270
|
-
const txSizeStripped = _TxWeightEstimator.BASE_TX_SIZE + inputCount + this.inputSize + outputCount + this.outputSize;
|
|
2271
|
-
let weight = txSizeStripped * _TxWeightEstimator.WITNESS_SCALE_FACTOR;
|
|
2272
|
-
if (this.hasWitness) {
|
|
2273
|
-
weight += _TxWeightEstimator.WITNESS_HEADER_SIZE + this.inputWitnessSize;
|
|
2274
|
-
}
|
|
2275
|
-
return vsize(weight);
|
|
2276
|
-
}
|
|
2277
|
-
};
|
|
2278
|
-
var vsize = (weight) => {
|
|
2279
|
-
const value = BigInt(Math.ceil(weight / TxWeightEstimator.WITNESS_SCALE_FACTOR));
|
|
2280
|
-
return {
|
|
2281
|
-
value,
|
|
2282
|
-
fee: (feeRate) => feeRate * value
|
|
2283
|
-
};
|
|
2284
|
-
};
|
|
2285
2318
|
var AmountVariableName = "amount";
|
|
2286
2319
|
var ExpiryVariableName = "expiry";
|
|
2287
2320
|
var BirthVariableName = "birth";
|
|
@@ -3124,7 +3157,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3124
3157
|
`Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
|
|
3125
3158
|
);
|
|
3126
3159
|
}
|
|
3127
|
-
const tx = new
|
|
3160
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction();
|
|
3128
3161
|
for (const utxo of expiredUtxos) {
|
|
3129
3162
|
const utxoScript = chunkHXDZ2QTW_cjs.VtxoScript.decode(utxo.tapTree);
|
|
3130
3163
|
const utxoExitLeaf = utxoScript.leaves.find(
|
|
@@ -3763,7 +3796,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3763
3796
|
* or doesn't carry the metadata.
|
|
3764
3797
|
*/
|
|
3765
3798
|
extractSpentOutpoint(error) {
|
|
3766
|
-
const ark =
|
|
3799
|
+
const ark = chunkUBYY2TPK_cjs.maybeArkError(error);
|
|
3767
3800
|
if (!ark || ark.name !== "VTXO_ALREADY_SPENT") return void 0;
|
|
3768
3801
|
const raw = ark.metadata?.vtxo_outpoint;
|
|
3769
3802
|
if (typeof raw !== "string") return void 0;
|
|
@@ -4791,7 +4824,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4791
4824
|
const virtualCoins = await this.wallet.getVtxos({
|
|
4792
4825
|
withRecoverable: false
|
|
4793
4826
|
});
|
|
4794
|
-
const controlAssetRef = params.controlAssetId ?
|
|
4827
|
+
const controlAssetRef = params.controlAssetId ? chunkUBYY2TPK_cjs.AssetRef.fromId(chunkUBYY2TPK_cjs.AssetId.fromString(params.controlAssetId)) : null;
|
|
4795
4828
|
const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
|
|
4796
4829
|
let totalBtcSelected = 0n;
|
|
4797
4830
|
const assetChanges = /* @__PURE__ */ new Map();
|
|
@@ -4804,8 +4837,8 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4804
4837
|
}
|
|
4805
4838
|
}
|
|
4806
4839
|
const groups = [];
|
|
4807
|
-
const issuedAssetOutput =
|
|
4808
|
-
const issuedAssetGroup =
|
|
4840
|
+
const issuedAssetOutput = chunkUBYY2TPK_cjs.AssetOutput.create(0, params.amount);
|
|
4841
|
+
const issuedAssetGroup = chunkUBYY2TPK_cjs.AssetGroup.create(
|
|
4809
4842
|
null,
|
|
4810
4843
|
controlAssetRef,
|
|
4811
4844
|
[],
|
|
@@ -4820,15 +4853,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4820
4853
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4821
4854
|
for (const asset of assets) {
|
|
4822
4855
|
if (asset.assetId !== assetId) continue;
|
|
4823
|
-
changeInputs.push(
|
|
4856
|
+
changeInputs.push(chunkUBYY2TPK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4824
4857
|
}
|
|
4825
4858
|
}
|
|
4826
4859
|
groups.push(
|
|
4827
|
-
|
|
4828
|
-
|
|
4860
|
+
chunkUBYY2TPK_cjs.AssetGroup.create(
|
|
4861
|
+
chunkUBYY2TPK_cjs.AssetId.fromString(assetId),
|
|
4829
4862
|
null,
|
|
4830
4863
|
changeInputs,
|
|
4831
|
-
[
|
|
4864
|
+
[chunkUBYY2TPK_cjs.AssetOutput.create(0, amount)],
|
|
4832
4865
|
[]
|
|
4833
4866
|
)
|
|
4834
4867
|
);
|
|
@@ -4841,7 +4874,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4841
4874
|
script: outputAddress.pkScript,
|
|
4842
4875
|
amount: BigInt(totalBtcSelected)
|
|
4843
4876
|
},
|
|
4844
|
-
Extension.create([
|
|
4877
|
+
Extension.create([chunkUBYY2TPK_cjs.Packet.create(groups)]).txOut()
|
|
4845
4878
|
];
|
|
4846
4879
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
|
|
4847
4880
|
coinSelection.inputs,
|
|
@@ -4849,7 +4882,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4849
4882
|
);
|
|
4850
4883
|
return {
|
|
4851
4884
|
arkTxId: arkTxid,
|
|
4852
|
-
assetId:
|
|
4885
|
+
assetId: chunkUBYY2TPK_cjs.AssetId.create(arkTxid, 0).toString()
|
|
4853
4886
|
};
|
|
4854
4887
|
}
|
|
4855
4888
|
/**
|
|
@@ -4921,16 +4954,16 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4921
4954
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4922
4955
|
for (const asset of assets) {
|
|
4923
4956
|
if (asset.assetId !== params.assetId) continue;
|
|
4924
|
-
reissueInputs.push(
|
|
4957
|
+
reissueInputs.push(chunkUBYY2TPK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4925
4958
|
}
|
|
4926
4959
|
}
|
|
4927
4960
|
const totalAssetAmount = assetToReissueAmount + params.amount;
|
|
4928
|
-
const reissueAssetIdObj =
|
|
4929
|
-
const reissueAssetGroup =
|
|
4961
|
+
const reissueAssetIdObj = chunkUBYY2TPK_cjs.AssetId.fromString(params.assetId);
|
|
4962
|
+
const reissueAssetGroup = chunkUBYY2TPK_cjs.AssetGroup.create(
|
|
4930
4963
|
reissueAssetIdObj,
|
|
4931
4964
|
null,
|
|
4932
4965
|
reissueInputs,
|
|
4933
|
-
[
|
|
4966
|
+
[chunkUBYY2TPK_cjs.AssetOutput.create(0, totalAssetAmount)],
|
|
4934
4967
|
[]
|
|
4935
4968
|
);
|
|
4936
4969
|
const groups = [reissueAssetGroup];
|
|
@@ -4939,15 +4972,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4939
4972
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4940
4973
|
for (const asset of assets) {
|
|
4941
4974
|
if (asset.assetId !== assetId) continue;
|
|
4942
|
-
changeInputs.push(
|
|
4975
|
+
changeInputs.push(chunkUBYY2TPK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4943
4976
|
}
|
|
4944
4977
|
}
|
|
4945
4978
|
groups.push(
|
|
4946
|
-
|
|
4947
|
-
|
|
4979
|
+
chunkUBYY2TPK_cjs.AssetGroup.create(
|
|
4980
|
+
chunkUBYY2TPK_cjs.AssetId.fromString(assetId),
|
|
4948
4981
|
null,
|
|
4949
4982
|
changeInputs,
|
|
4950
|
-
[
|
|
4983
|
+
[chunkUBYY2TPK_cjs.AssetOutput.create(0, amount)],
|
|
4951
4984
|
[]
|
|
4952
4985
|
)
|
|
4953
4986
|
);
|
|
@@ -4959,7 +4992,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4959
4992
|
script: outputAddress.pkScript,
|
|
4960
4993
|
amount: BigInt(totalBtcSelected)
|
|
4961
4994
|
},
|
|
4962
|
-
Extension.create([
|
|
4995
|
+
Extension.create([chunkUBYY2TPK_cjs.Packet.create(groups)]).txOut()
|
|
4963
4996
|
];
|
|
4964
4997
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
4965
4998
|
return arkTxid;
|
|
@@ -5026,15 +5059,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
5026
5059
|
for (const [inputIndex, assets] of assetInputs) {
|
|
5027
5060
|
for (const asset of assets) {
|
|
5028
5061
|
if (asset.assetId !== assetId) continue;
|
|
5029
|
-
changeInputs.push(
|
|
5062
|
+
changeInputs.push(chunkUBYY2TPK_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
5030
5063
|
}
|
|
5031
5064
|
}
|
|
5032
5065
|
groups.push(
|
|
5033
|
-
|
|
5034
|
-
|
|
5066
|
+
chunkUBYY2TPK_cjs.AssetGroup.create(
|
|
5067
|
+
chunkUBYY2TPK_cjs.AssetId.fromString(assetId),
|
|
5035
5068
|
null,
|
|
5036
5069
|
changeInputs,
|
|
5037
|
-
amount > 0n ? [
|
|
5070
|
+
amount > 0n ? [chunkUBYY2TPK_cjs.AssetOutput.create(0, amount)] : [],
|
|
5038
5071
|
[]
|
|
5039
5072
|
)
|
|
5040
5073
|
);
|
|
@@ -5046,7 +5079,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
5046
5079
|
script: outputAddress.pkScript,
|
|
5047
5080
|
amount: BigInt(totalBtcSelected)
|
|
5048
5081
|
},
|
|
5049
|
-
Extension.create([
|
|
5082
|
+
Extension.create([chunkUBYY2TPK_cjs.Packet.create(groups)]).txOut()
|
|
5050
5083
|
];
|
|
5051
5084
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
5052
5085
|
return arkTxid;
|
|
@@ -5071,7 +5104,7 @@ function castMetadata(metadata) {
|
|
|
5071
5104
|
} else {
|
|
5072
5105
|
throw new Error("Invalid metadata value type");
|
|
5073
5106
|
}
|
|
5074
|
-
md.push(
|
|
5107
|
+
md.push(chunkUBYY2TPK_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
|
|
5075
5108
|
}
|
|
5076
5109
|
return md;
|
|
5077
5110
|
}
|
|
@@ -5356,7 +5389,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
|
|
|
5356
5389
|
expire_at: 0,
|
|
5357
5390
|
cosigners_public_keys: cosignerPubKeys
|
|
5358
5391
|
};
|
|
5359
|
-
const proof =
|
|
5392
|
+
const proof = chunkUBYY2TPK_cjs.Intent.create(message, coins, outputs);
|
|
5360
5393
|
const signedProof = await identity.sign(proof);
|
|
5361
5394
|
return {
|
|
5362
5395
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -7454,7 +7487,7 @@ var ContractWatcher = class {
|
|
|
7454
7487
|
this.connectionState = "connected";
|
|
7455
7488
|
this.reconnectAttempts = 0;
|
|
7456
7489
|
this.listenLoop().catch((e) => {
|
|
7457
|
-
if (
|
|
7490
|
+
if (chunkUBYY2TPK_cjs.isEventSourceError(e)) {
|
|
7458
7491
|
console.debug("ContractWatcher subscription disconnected; reconnecting");
|
|
7459
7492
|
} else {
|
|
7460
7493
|
console.error(e);
|
|
@@ -9548,7 +9581,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9548
9581
|
*/
|
|
9549
9582
|
static async setupWalletConfig(config, pubKey) {
|
|
9550
9583
|
const arkadeServerUrl = getArkadeServerUrl(config);
|
|
9551
|
-
const arkProvider = config.arkProvider || new
|
|
9584
|
+
const arkProvider = config.arkProvider || new chunkUBYY2TPK_cjs.RestArkProvider(arkadeServerUrl);
|
|
9552
9585
|
let indexerProvider = config.indexerProvider;
|
|
9553
9586
|
if (!indexerProvider) {
|
|
9554
9587
|
let indexerUrl = config.indexerUrl;
|
|
@@ -9565,7 +9598,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9565
9598
|
indexerUrl = arkadeServerUrl;
|
|
9566
9599
|
}
|
|
9567
9600
|
}
|
|
9568
|
-
indexerProvider = new
|
|
9601
|
+
indexerProvider = new chunkUBYY2TPK_cjs.RestIndexerProvider(indexerUrl);
|
|
9569
9602
|
}
|
|
9570
9603
|
const info = await arkProvider.getInfo();
|
|
9571
9604
|
const network = chunkHXDZ2QTW_cjs.getNetwork(info.network);
|
|
@@ -11580,9 +11613,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11580
11613
|
...existing ?? {},
|
|
11581
11614
|
intentTxId,
|
|
11582
11615
|
registerProof: intent.proof,
|
|
11583
|
-
registerProofMessage:
|
|
11616
|
+
registerProofMessage: chunkUBYY2TPK_cjs.Intent.encodeMessage(intent.message),
|
|
11584
11617
|
deleteProof: deleteIntent.proof,
|
|
11585
|
-
deleteProofMessage:
|
|
11618
|
+
deleteProofMessage: chunkUBYY2TPK_cjs.Intent.encodeMessage(deleteIntent.message),
|
|
11586
11619
|
intentVtxos: inputs.map((i) => ({
|
|
11587
11620
|
txid: i.txid,
|
|
11588
11621
|
vout: i.vout
|
|
@@ -11614,7 +11647,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11614
11647
|
try {
|
|
11615
11648
|
return await this.arkProvider.registerIntent(intent);
|
|
11616
11649
|
} catch (error) {
|
|
11617
|
-
if (error instanceof
|
|
11650
|
+
if (error instanceof chunkUBYY2TPK_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
|
|
11618
11651
|
const deleteIntent = await this.makeDeleteIntentSignature(inputs);
|
|
11619
11652
|
await this.arkProvider.deleteIntent(deleteIntent);
|
|
11620
11653
|
return this.arkProvider.registerIntent(intent);
|
|
@@ -11630,7 +11663,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11630
11663
|
expire_at: 0,
|
|
11631
11664
|
cosigners_public_keys: cosignerPubKeys
|
|
11632
11665
|
};
|
|
11633
|
-
const proof =
|
|
11666
|
+
const proof = chunkUBYY2TPK_cjs.Intent.create(message, coins, outputs);
|
|
11634
11667
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11635
11668
|
return {
|
|
11636
11669
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -11642,7 +11675,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11642
11675
|
type: "delete",
|
|
11643
11676
|
expire_at: 0
|
|
11644
11677
|
};
|
|
11645
|
-
const proof =
|
|
11678
|
+
const proof = chunkUBYY2TPK_cjs.Intent.create(message, coins, []);
|
|
11646
11679
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11647
11680
|
return {
|
|
11648
11681
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -11654,7 +11687,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11654
11687
|
type: "get-pending-tx",
|
|
11655
11688
|
expire_at: 0
|
|
11656
11689
|
};
|
|
11657
|
-
const proof =
|
|
11690
|
+
const proof = chunkUBYY2TPK_cjs.Intent.create(message, coins, []);
|
|
11658
11691
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11659
11692
|
return {
|
|
11660
11693
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -12612,7 +12645,7 @@ var MessageBus = class {
|
|
|
12612
12645
|
this.initialized = true;
|
|
12613
12646
|
}
|
|
12614
12647
|
async buildServices(config) {
|
|
12615
|
-
const arkProvider = new
|
|
12648
|
+
const arkProvider = new chunkUBYY2TPK_cjs.RestArkProvider(config.arkServer.url);
|
|
12616
12649
|
const storage = {
|
|
12617
12650
|
walletRepository: this.walletRepository,
|
|
12618
12651
|
contractRepository: this.contractRepository
|
|
@@ -13769,7 +13802,7 @@ var WalletMessageHandler = class {
|
|
|
13769
13802
|
// Wallet methods
|
|
13770
13803
|
async handleInitWallet({ payload }) {
|
|
13771
13804
|
const { arkServerUrl } = payload;
|
|
13772
|
-
this.indexerProvider = new
|
|
13805
|
+
this.indexerProvider = new chunkUBYY2TPK_cjs.RestIndexerProvider(arkServerUrl);
|
|
13773
13806
|
await this.onWalletInitialized();
|
|
13774
13807
|
}
|
|
13775
13808
|
async handleGetBalance() {
|
|
@@ -15576,7 +15609,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
15576
15609
|
if (!inputs) {
|
|
15577
15610
|
throw new Error("Fee estimation failed");
|
|
15578
15611
|
}
|
|
15579
|
-
let tx = new
|
|
15612
|
+
let tx = new chunkUBYY2TPK_cjs.Transaction();
|
|
15580
15613
|
for (const input of inputs) {
|
|
15581
15614
|
tx.addInput({
|
|
15582
15615
|
txid: input.txid,
|
|
@@ -15606,42 +15639,11 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
15606
15639
|
* @see send
|
|
15607
15640
|
*/
|
|
15608
15641
|
async bumpP2A(parent) {
|
|
15609
|
-
const parentVsize = parent.vsize;
|
|
15610
|
-
let child = new chunk3AQNLQPM_cjs.Transaction({
|
|
15611
|
-
version: 3,
|
|
15612
|
-
allowLegacyWitnessUtxo: true
|
|
15613
|
-
});
|
|
15614
|
-
child.addInput(findP2AOutput(parent));
|
|
15615
|
-
const childVsize = TxWeightEstimator.create().addKeySpendInput(true).addP2AInput().addOutputAddress(this.address, this.network).vsize().value;
|
|
15616
|
-
const packageVSize = parentVsize + Number(childVsize);
|
|
15617
15642
|
let feeRate = await this.provider.getFeeRate();
|
|
15618
15643
|
if (!feeRate || feeRate < _OnchainWallet.MIN_FEE_RATE) {
|
|
15619
15644
|
feeRate = _OnchainWallet.MIN_FEE_RATE;
|
|
15620
15645
|
}
|
|
15621
|
-
const
|
|
15622
|
-
if (!fee) {
|
|
15623
|
-
throw new Error(
|
|
15624
|
-
`invalid fee, got ${fee} with vsize ${packageVSize}, feeRate ${feeRate}`
|
|
15625
|
-
);
|
|
15626
|
-
}
|
|
15627
|
-
const coins = await this.getCoins();
|
|
15628
|
-
const selected = selectCoins(coins, fee, true);
|
|
15629
|
-
for (const input of selected.inputs) {
|
|
15630
|
-
child.addInput({
|
|
15631
|
-
txid: input.txid,
|
|
15632
|
-
index: input.vout,
|
|
15633
|
-
witnessUtxo: {
|
|
15634
|
-
script: this.onchainP2TR.script,
|
|
15635
|
-
amount: BigInt(input.value)
|
|
15636
|
-
},
|
|
15637
|
-
tapInternalKey: this.onchainP2TR.tapInternalKey
|
|
15638
|
-
});
|
|
15639
|
-
}
|
|
15640
|
-
child.addOutputAddress(this.address, P2A.amount + selected.changeAmount, this.network);
|
|
15641
|
-
child = await this.identity.sign(child);
|
|
15642
|
-
for (let i = 1; i < child.inputsLength; i++) {
|
|
15643
|
-
child.finalizeIdx(i);
|
|
15644
|
-
}
|
|
15646
|
+
const child = await this.buildBumpPackage(parent, feeRate, await this.getCoins());
|
|
15645
15647
|
try {
|
|
15646
15648
|
await this.provider.broadcastTransaction(parent.hex, child.hex);
|
|
15647
15649
|
} catch (error) {
|
|
@@ -15650,6 +15652,59 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
15650
15652
|
return [parent.hex, child.hex];
|
|
15651
15653
|
}
|
|
15652
15654
|
}
|
|
15655
|
+
/**
|
|
15656
|
+
* Build and sign a CPFP fee child for a parent tx (given as raw hex)
|
|
15657
|
+
* carrying a P2A anchor, funding it from this wallet's **confirmed**
|
|
15658
|
+
* coins, and return the 1P1C package hexes WITHOUT broadcasting.
|
|
15659
|
+
*
|
|
15660
|
+
* This is the graph-mode fee source ({@link ExitFeeWallet}): the exit
|
|
15661
|
+
* executor calls it to bump each transported virtual tx at execution
|
|
15662
|
+
* time, so funding can be deferred rather than pre-signed.
|
|
15663
|
+
*
|
|
15664
|
+
* @param parentHex - Finalized parent transaction, raw network hex
|
|
15665
|
+
* @param feeRate - sat/vB floor for the package (raised to MIN_FEE_RATE)
|
|
15666
|
+
* @returns Tuple of parent hex (unchanged) and signed child hex
|
|
15667
|
+
* @throws If the parent has no anchor, or funding cannot be selected/signed
|
|
15668
|
+
*/
|
|
15669
|
+
async bumpAnchor(parentHex, feeRate) {
|
|
15670
|
+
const parent = chunkUBYY2TPK_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
|
|
15671
|
+
const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
|
|
15672
|
+
const child = await this.buildBumpPackage(parent, feeRate, coins);
|
|
15673
|
+
return [parent.hex, child.hex];
|
|
15674
|
+
}
|
|
15675
|
+
/**
|
|
15676
|
+
* Shared core of {@link bumpP2A} and {@link bumpAnchor}: probe the package
|
|
15677
|
+
* fee with a single-input child, select coins for it, then build and sign
|
|
15678
|
+
* with the actual selection (the fee grows per extra input).
|
|
15679
|
+
*/
|
|
15680
|
+
async buildBumpPackage(parent, feeRate, coins) {
|
|
15681
|
+
let rate = feeRate;
|
|
15682
|
+
if (!rate || rate < _OnchainWallet.MIN_FEE_RATE) {
|
|
15683
|
+
rate = _OnchainWallet.MIN_FEE_RATE;
|
|
15684
|
+
}
|
|
15685
|
+
const probeVsize = TxWeightEstimator.create().addKeySpendInput(true).addP2AInput().addOutputAddress(this.address, this.network).vsize().value;
|
|
15686
|
+
const probeFee = Math.ceil(rate * (parent.vsize + Number(probeVsize)));
|
|
15687
|
+
if (!probeFee) {
|
|
15688
|
+
throw new Error(
|
|
15689
|
+
`invalid fee, got ${probeFee} with vsize ${parent.vsize + Number(probeVsize)}, feeRate ${rate}`
|
|
15690
|
+
);
|
|
15691
|
+
}
|
|
15692
|
+
const selected = selectCoins(coins, probeFee, true);
|
|
15693
|
+
const { child } = buildAnchorChild({
|
|
15694
|
+
parent,
|
|
15695
|
+
feeRate: rate,
|
|
15696
|
+
fundingCoins: selected.inputs,
|
|
15697
|
+
changeAddress: this.address,
|
|
15698
|
+
changeScript: this.onchainP2TR.script,
|
|
15699
|
+
tapInternalKey: this.onchainP2TR.tapInternalKey,
|
|
15700
|
+
network: this.network
|
|
15701
|
+
});
|
|
15702
|
+
const signed = await this.identity.sign(child);
|
|
15703
|
+
for (let i = 1; i < signed.inputsLength; i++) {
|
|
15704
|
+
signed.finalizeIdx(i);
|
|
15705
|
+
}
|
|
15706
|
+
return signed;
|
|
15707
|
+
}
|
|
15653
15708
|
};
|
|
15654
15709
|
function selectCoins(coins, targetAmount, forceChange = false) {
|
|
15655
15710
|
if (isNaN(targetAmount)) {
|
|
@@ -16373,7 +16428,7 @@ exports.BIP322 = void 0;
|
|
|
16373
16428
|
async function sign2(message, identity, network) {
|
|
16374
16429
|
const xOnlyPubKey = await identity.xOnlyPublicKey();
|
|
16375
16430
|
const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
|
|
16376
|
-
const toSpend =
|
|
16431
|
+
const toSpend = chunkUBYY2TPK_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
|
|
16377
16432
|
const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
|
|
16378
16433
|
const signed = await identity.sign(toSign, [0]);
|
|
16379
16434
|
signed.finalizeIdx(0);
|
|
@@ -16431,7 +16486,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
|
|
|
16431
16486
|
if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
|
|
16432
16487
|
return false;
|
|
16433
16488
|
}
|
|
16434
|
-
const toSpend =
|
|
16489
|
+
const toSpend = chunkUBYY2TPK_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
16435
16490
|
const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
|
|
16436
16491
|
const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
|
|
16437
16492
|
const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
|
|
@@ -16452,7 +16507,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
|
|
|
16452
16507
|
}
|
|
16453
16508
|
const sighashType = sigWithHash[sigWithHash.length - 1];
|
|
16454
16509
|
const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
|
|
16455
|
-
const toSpend =
|
|
16510
|
+
const toSpend = chunkUBYY2TPK_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
16456
16511
|
const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
|
|
16457
16512
|
const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
|
|
16458
16513
|
const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
|
|
@@ -16505,7 +16560,7 @@ function encodeCompactSize(n) {
|
|
|
16505
16560
|
return buf;
|
|
16506
16561
|
}
|
|
16507
16562
|
function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
16508
|
-
const tx = new
|
|
16563
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({ version: 0 });
|
|
16509
16564
|
tx.addInput({
|
|
16510
16565
|
txid: toSpend.id,
|
|
16511
16566
|
index: 0,
|
|
@@ -16519,12 +16574,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
|
16519
16574
|
});
|
|
16520
16575
|
tx.addOutput({
|
|
16521
16576
|
amount: 0n,
|
|
16522
|
-
script:
|
|
16577
|
+
script: chunkUBYY2TPK_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
16523
16578
|
});
|
|
16524
16579
|
return tx;
|
|
16525
16580
|
}
|
|
16526
16581
|
function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
16527
|
-
const tx = new
|
|
16582
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({ version: 0 });
|
|
16528
16583
|
tx.addInput({
|
|
16529
16584
|
txid: toSpend.id,
|
|
16530
16585
|
index: 0,
|
|
@@ -16536,10 +16591,88 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
|
16536
16591
|
});
|
|
16537
16592
|
tx.addOutput({
|
|
16538
16593
|
amount: 0n,
|
|
16539
|
-
script:
|
|
16594
|
+
script: chunkUBYY2TPK_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
16540
16595
|
});
|
|
16541
16596
|
return tx;
|
|
16542
16597
|
}
|
|
16598
|
+
function finalizeVirtualTx(type, psbtBase64) {
|
|
16599
|
+
const tx = chunkUBYY2TPK_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
|
|
16600
|
+
if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
|
|
16601
|
+
const input = tx.getInput(0);
|
|
16602
|
+
if (!input) {
|
|
16603
|
+
throw new Error("Input not found");
|
|
16604
|
+
}
|
|
16605
|
+
const tapKeySig = input.tapKeySig;
|
|
16606
|
+
if (!tapKeySig) {
|
|
16607
|
+
throw new Error("Tap key sig not found");
|
|
16608
|
+
}
|
|
16609
|
+
tx.updateInput(0, {
|
|
16610
|
+
finalScriptWitness: [tapKeySig]
|
|
16611
|
+
});
|
|
16612
|
+
return tx;
|
|
16613
|
+
}
|
|
16614
|
+
tx.finalize();
|
|
16615
|
+
return tx;
|
|
16616
|
+
}
|
|
16617
|
+
var ExitPathError = class extends Error {
|
|
16618
|
+
constructor(reason, message) {
|
|
16619
|
+
super(message);
|
|
16620
|
+
this.reason = reason;
|
|
16621
|
+
this.name = "ExitPathError";
|
|
16622
|
+
}
|
|
16623
|
+
};
|
|
16624
|
+
function delayWeight(sequence) {
|
|
16625
|
+
const t = chunkHXDZ2QTW_cjs.sequenceToTimelock(sequence);
|
|
16626
|
+
return t.type === "blocks" ? Number(t.value) : Number(t.value) / 600;
|
|
16627
|
+
}
|
|
16628
|
+
async function resolveUnilateralPath(params) {
|
|
16629
|
+
const { vtxo, scriptHex, contractRepository } = params;
|
|
16630
|
+
const contract = contractRepository ? (await contractRepository.getContracts({ script: scriptHex }))[0] : void 0;
|
|
16631
|
+
if (contract) {
|
|
16632
|
+
const handler = chunk32YKLQPS_cjs.contractHandlers.get(contract.type);
|
|
16633
|
+
if (!handler) {
|
|
16634
|
+
throw new ExitPathError(
|
|
16635
|
+
"no-handler",
|
|
16636
|
+
`no contract handler registered for type '${contract.type}'`
|
|
16637
|
+
);
|
|
16638
|
+
}
|
|
16639
|
+
const script = handler.createScript(contract.params);
|
|
16640
|
+
const paths = handler.getAllSpendingPaths(script, contract, {
|
|
16641
|
+
collaborative: false,
|
|
16642
|
+
currentTime: params.currentTime,
|
|
16643
|
+
walletDescriptor: params.walletDescriptor,
|
|
16644
|
+
walletPubKey: params.walletPubKeyHex
|
|
16645
|
+
}).filter((p) => p.sequence !== void 0);
|
|
16646
|
+
if (paths.length === 0) {
|
|
16647
|
+
throw new ExitPathError(
|
|
16648
|
+
"no-unilateral-path",
|
|
16649
|
+
`no unilateral path for vtxo ${vtxo.txid}:${vtxo.vout} (type '${contract.type}')`
|
|
16650
|
+
);
|
|
16651
|
+
}
|
|
16652
|
+
paths.sort((a, b) => delayWeight(a.sequence) - delayWeight(b.sequence));
|
|
16653
|
+
return { selection: paths[0], label: `${contract.type}:unilateral` };
|
|
16654
|
+
}
|
|
16655
|
+
const decoded = chunkHXDZ2QTW_cjs.VtxoScript.decode(vtxo.tapTree);
|
|
16656
|
+
let best;
|
|
16657
|
+
for (const exit of decoded.exitPaths()) {
|
|
16658
|
+
const leaf = decoded.findLeaf(base.hex.encode(exit.script));
|
|
16659
|
+
if (!leaf) continue;
|
|
16660
|
+
const sequence = chunkHXDZ2QTW_cjs.timelockToSequence(exit.params.timelock);
|
|
16661
|
+
const weight = delayWeight(sequence);
|
|
16662
|
+
if (!best || weight < best.weight) {
|
|
16663
|
+
best = { selection: { leaf, sequence }, weight };
|
|
16664
|
+
}
|
|
16665
|
+
}
|
|
16666
|
+
if (!best) {
|
|
16667
|
+
throw new ExitPathError(
|
|
16668
|
+
"no-unilateral-path",
|
|
16669
|
+
`no exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`
|
|
16670
|
+
);
|
|
16671
|
+
}
|
|
16672
|
+
return { selection: best.selection, label: "default:exit" };
|
|
16673
|
+
}
|
|
16674
|
+
|
|
16675
|
+
// src/wallet/unroll.ts
|
|
16543
16676
|
function chainTxTypeToChainedExit(t) {
|
|
16544
16677
|
switch (t) {
|
|
16545
16678
|
case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
|
|
@@ -16649,22 +16782,7 @@ exports.Unroll = void 0;
|
|
|
16649
16782
|
if (!virtualTxBase64) {
|
|
16650
16783
|
throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
|
|
16651
16784
|
}
|
|
16652
|
-
const tx =
|
|
16653
|
-
if (nextTxToBroadcast.type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
|
|
16654
|
-
const input = tx.getInput(0);
|
|
16655
|
-
if (!input) {
|
|
16656
|
-
throw new Error("Input not found");
|
|
16657
|
-
}
|
|
16658
|
-
const tapKeySig = input.tapKeySig;
|
|
16659
|
-
if (!tapKeySig) {
|
|
16660
|
-
throw new Error("Tap key sig not found");
|
|
16661
|
-
}
|
|
16662
|
-
tx.updateInput(0, {
|
|
16663
|
-
finalScriptWitness: [tapKeySig]
|
|
16664
|
-
});
|
|
16665
|
-
} else {
|
|
16666
|
-
tx.finalize();
|
|
16667
|
-
}
|
|
16785
|
+
const tx = finalizeVirtualTx(nextTxToBroadcast.type, virtualTxBase64);
|
|
16668
16786
|
const pkg = await this.bumper.bumpP2A(tx);
|
|
16669
16787
|
return {
|
|
16670
16788
|
type: 0 /* UNROLL */,
|
|
@@ -16718,20 +16836,21 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
16718
16836
|
if (!txStatus.confirmed) {
|
|
16719
16837
|
throw new Error(`tx ${vtxo.txid} is not confirmed`);
|
|
16720
16838
|
}
|
|
16721
|
-
const
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16839
|
+
const resolved = await resolveUnilateralPath({
|
|
16840
|
+
vtxo,
|
|
16841
|
+
scriptHex: base.hex.encode(chunkHXDZ2QTW_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
|
|
16842
|
+
contractRepository: wallet.contractRepository,
|
|
16843
|
+
walletPubKeyHex: base.hex.encode(await wallet.identity.xOnlyPublicKey()),
|
|
16844
|
+
currentTime: Date.now()
|
|
16845
|
+
});
|
|
16846
|
+
const spendingLeaf = resolved.selection.leaf;
|
|
16847
|
+
const sequence = resolved.selection.sequence;
|
|
16848
|
+
const timelock = chunkHXDZ2QTW_cjs.sequenceToTimelock(sequence);
|
|
16849
|
+
const elapsed = timelock.type === "blocks" ? chainTip.height >= txStatus.blockHeight + Number(timelock.value) : chainTip.time >= txStatus.blockTime + Number(timelock.value);
|
|
16850
|
+
if (!elapsed) {
|
|
16727
16851
|
throw new Error(`no available exit path found for vtxo ${vtxo.txid}:${vtxo.vout}`);
|
|
16728
16852
|
}
|
|
16729
|
-
const spendingLeaf = chunkHXDZ2QTW_cjs.VtxoScript.decode(vtxo.tapTree).findLeaf(base.hex.encode(exit.script));
|
|
16730
|
-
if (!spendingLeaf) {
|
|
16731
|
-
throw new Error(`spending leaf not found for vtxo ${vtxo.txid}:${vtxo.vout}`);
|
|
16732
|
-
}
|
|
16733
16853
|
totalAmount += BigInt(vtxo.value);
|
|
16734
|
-
const sequence = chunkHXDZ2QTW_cjs.timelockToSequence(exit.params.timelock);
|
|
16735
16854
|
inputs.push({
|
|
16736
16855
|
txid: vtxo.txid,
|
|
16737
16856
|
index: vtxo.vout,
|
|
@@ -16749,7 +16868,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
16749
16868
|
btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
|
|
16750
16869
|
);
|
|
16751
16870
|
}
|
|
16752
|
-
const tx = new
|
|
16871
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({ version: 2 });
|
|
16753
16872
|
for (const input of inputs) {
|
|
16754
16873
|
tx.addInput(input);
|
|
16755
16874
|
}
|
|
@@ -16795,21 +16914,809 @@ function doWait(onchainProvider, txid) {
|
|
|
16795
16914
|
});
|
|
16796
16915
|
};
|
|
16797
16916
|
}
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16917
|
+
|
|
16918
|
+
// src/wallet/exit/chain.ts
|
|
16919
|
+
var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
16920
|
+
async function buildExitDag(params) {
|
|
16921
|
+
const byTxid = /* @__PURE__ */ new Map();
|
|
16922
|
+
for (const vtxo of params.vtxos) {
|
|
16923
|
+
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
16924
|
+
let pageIndex = 0;
|
|
16925
|
+
let hasMore = true;
|
|
16926
|
+
while (hasMore) {
|
|
16927
|
+
const { chain, page } = await params.indexer.getVtxoChain(
|
|
16928
|
+
{ txid: vtxo.txid, vout: vtxo.vout },
|
|
16929
|
+
{ pageIndex, pageSize: chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE }
|
|
16930
|
+
);
|
|
16931
|
+
for (const chainTx of chain) {
|
|
16932
|
+
const existing = byTxid.get(chainTx.txid);
|
|
16933
|
+
if (existing) {
|
|
16934
|
+
existing.forVtxos.add(outpoint);
|
|
16935
|
+
} else {
|
|
16936
|
+
byTxid.set(chainTx.txid, { ...chainTx, forVtxos: /* @__PURE__ */ new Set([outpoint]) });
|
|
16937
|
+
}
|
|
16804
16938
|
}
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16939
|
+
hasMore = page ? chain.length === chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE : false;
|
|
16940
|
+
pageIndex++;
|
|
16941
|
+
}
|
|
16942
|
+
}
|
|
16943
|
+
const pending = new Map(
|
|
16944
|
+
[...byTxid.values()].filter((tx) => !isCommitment(tx.type)).map((tx) => [tx.txid, tx])
|
|
16945
|
+
);
|
|
16946
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
16947
|
+
for (const tx of pending.values()) {
|
|
16948
|
+
const parents = tx.spends.filter((p) => pending.has(p));
|
|
16949
|
+
inDegree.set(tx.txid, parents.length);
|
|
16950
|
+
}
|
|
16951
|
+
const order = [];
|
|
16952
|
+
const queue = [...pending.values()].filter((tx) => inDegree.get(tx.txid) === 0).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
16953
|
+
while (queue.length > 0) {
|
|
16954
|
+
const tx = queue.shift();
|
|
16955
|
+
order.push(tx);
|
|
16956
|
+
const children = [...pending.values()].filter((c) => c.spends.includes(tx.txid)).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
16957
|
+
for (const child of children) {
|
|
16958
|
+
const deg = inDegree.get(child.txid) - 1;
|
|
16959
|
+
inDegree.set(child.txid, deg);
|
|
16960
|
+
if (deg === 0) queue.push(child);
|
|
16961
|
+
}
|
|
16962
|
+
}
|
|
16963
|
+
if (order.length !== pending.size) {
|
|
16964
|
+
throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
|
|
16965
|
+
}
|
|
16966
|
+
const nodes = [];
|
|
16967
|
+
for (const tx of order) {
|
|
16968
|
+
let confirmed = false;
|
|
16969
|
+
try {
|
|
16970
|
+
const status = await params.onchain.getTxStatus(tx.txid);
|
|
16971
|
+
confirmed = status.confirmed;
|
|
16972
|
+
} catch {
|
|
16973
|
+
confirmed = false;
|
|
16974
|
+
}
|
|
16975
|
+
const expires = Number(tx.expiresAt);
|
|
16976
|
+
nodes.push({
|
|
16977
|
+
txid: tx.txid,
|
|
16978
|
+
type: tx.type,
|
|
16979
|
+
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
|
|
16980
|
+
forVtxos: [...tx.forVtxos].sort(),
|
|
16981
|
+
confirmed
|
|
16982
|
+
});
|
|
16983
|
+
}
|
|
16984
|
+
return nodes;
|
|
16985
|
+
}
|
|
16986
|
+
function topoSortByDeps(items, idOf, depsOf) {
|
|
16987
|
+
const produced = new Set(items.map(idOf));
|
|
16988
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
16989
|
+
const ordered = [];
|
|
16990
|
+
let remaining = items;
|
|
16991
|
+
while (remaining.length > 0) {
|
|
16992
|
+
const next = [];
|
|
16993
|
+
let progress = false;
|
|
16994
|
+
for (const item of remaining) {
|
|
16995
|
+
if (depsOf(item).every((d) => !produced.has(d) || emitted.has(d))) {
|
|
16996
|
+
ordered.push(item);
|
|
16997
|
+
emitted.add(idOf(item));
|
|
16998
|
+
progress = true;
|
|
16999
|
+
} else {
|
|
17000
|
+
next.push(item);
|
|
16808
17001
|
}
|
|
16809
17002
|
}
|
|
17003
|
+
if (!progress) {
|
|
17004
|
+
throw new Error("topological sort: cycle or unsatisfiable dependency");
|
|
17005
|
+
}
|
|
17006
|
+
remaining = next;
|
|
16810
17007
|
}
|
|
16811
|
-
return
|
|
17008
|
+
return ordered;
|
|
17009
|
+
}
|
|
17010
|
+
function extraWitnessSize(path) {
|
|
17011
|
+
return (path.extraWitness ?? []).reduce((sum, item) => sum + 1 + item.length, 0);
|
|
17012
|
+
}
|
|
17013
|
+
function sweepFeeFor(path, outputAddress, network, feeRate) {
|
|
17014
|
+
const [controlBlock, scriptWithVersion] = path.leaf;
|
|
17015
|
+
const estimator = TxWeightEstimator.create().addTapscriptInput(
|
|
17016
|
+
64 + extraWitnessSize(path),
|
|
17017
|
+
scriptWithVersion.length,
|
|
17018
|
+
btcSigner.TaprootControlBlock.encode(controlBlock).length
|
|
17019
|
+
).addOutputAddress(outputAddress, network);
|
|
17020
|
+
return Number(estimator.vsize().fee(BigInt(Math.ceil(feeRate))));
|
|
16812
17021
|
}
|
|
17022
|
+
async function buildSignedSweep(params) {
|
|
17023
|
+
const { vtxo, path, outputAddress, feeRate, network, identity } = params;
|
|
17024
|
+
const fee = sweepFeeFor(path, outputAddress, network, feeRate);
|
|
17025
|
+
const sendAmount = BigInt(vtxo.value) - BigInt(fee);
|
|
17026
|
+
if (sendAmount < BigInt(DUST_AMOUNT)) {
|
|
17027
|
+
throw new Error(
|
|
17028
|
+
`uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
|
|
17029
|
+
);
|
|
17030
|
+
}
|
|
17031
|
+
const tx = new chunkUBYY2TPK_cjs.Transaction({ version: 2 });
|
|
17032
|
+
tx.addInput({
|
|
17033
|
+
txid: vtxo.txid,
|
|
17034
|
+
index: vtxo.vout,
|
|
17035
|
+
tapLeafScript: [path.leaf],
|
|
17036
|
+
sequence: path.sequence,
|
|
17037
|
+
witnessUtxo: { amount: BigInt(vtxo.value), script: vtxo.pkScript },
|
|
17038
|
+
sighashType: btcSigner.SigHash.DEFAULT
|
|
17039
|
+
});
|
|
17040
|
+
tx.addOutputAddress(outputAddress, sendAmount, network);
|
|
17041
|
+
const signed = await identity.sign(tx);
|
|
17042
|
+
if (!path.extraWitness || path.extraWitness.length === 0) {
|
|
17043
|
+
signed.finalize();
|
|
17044
|
+
return { tx: signed, fee };
|
|
17045
|
+
}
|
|
17046
|
+
const input = signed.getInput(0);
|
|
17047
|
+
const tapScriptSig = input.tapScriptSig;
|
|
17048
|
+
if (!tapScriptSig || tapScriptSig.length === 0) {
|
|
17049
|
+
throw new Error("exit path requires additional signers");
|
|
17050
|
+
}
|
|
17051
|
+
const [controlBlock] = path.leaf;
|
|
17052
|
+
signed.updateInput(0, {
|
|
17053
|
+
finalScriptWitness: [
|
|
17054
|
+
tapScriptSig[0][1],
|
|
17055
|
+
...path.extraWitness,
|
|
17056
|
+
chunkHXDZ2QTW_cjs.scriptFromTapLeafScript(path.leaf),
|
|
17057
|
+
btcSigner.TaprootControlBlock.encode(controlBlock)
|
|
17058
|
+
]
|
|
17059
|
+
});
|
|
17060
|
+
return { tx: signed, fee };
|
|
17061
|
+
}
|
|
17062
|
+
|
|
17063
|
+
// src/wallet/exit/estimate.ts
|
|
17064
|
+
var CHILD_OUTPUT_DUST = 546;
|
|
17065
|
+
function stepFundingAmount(stepFee) {
|
|
17066
|
+
return stepFee + CHILD_OUTPUT_DUST;
|
|
17067
|
+
}
|
|
17068
|
+
function resolveMode(opts) {
|
|
17069
|
+
return opts.mode ?? "funded";
|
|
17070
|
+
}
|
|
17071
|
+
function resolveNetworkName(opts) {
|
|
17072
|
+
if (opts.networkName) return opts.networkName;
|
|
17073
|
+
const { bech32 } = opts.wallet.network;
|
|
17074
|
+
if (bech32 === "bc") return "bitcoin";
|
|
17075
|
+
if (bech32 === "bcrt") return "regtest";
|
|
17076
|
+
return "testnet";
|
|
17077
|
+
}
|
|
17078
|
+
async function resolveFeeRate(opts) {
|
|
17079
|
+
if (opts.feeRate) return Math.ceil(opts.feeRate);
|
|
17080
|
+
const feeRate = await opts.wallet.onchainProvider.getFeeRate();
|
|
17081
|
+
if (!feeRate || feeRate < OnchainWallet.MIN_FEE_RATE) return OnchainWallet.MIN_FEE_RATE;
|
|
17082
|
+
return Math.ceil(feeRate);
|
|
17083
|
+
}
|
|
17084
|
+
async function selectExitVtxos(opts) {
|
|
17085
|
+
if (!opts.vtxos) return opts.wallet.getVtxos();
|
|
17086
|
+
const res = await opts.wallet.indexerProvider.getVtxos({ outpoints: opts.vtxos });
|
|
17087
|
+
const tapTrees = /* @__PURE__ */ new Map();
|
|
17088
|
+
const out = [];
|
|
17089
|
+
for (const vtxo of res.vtxos) {
|
|
17090
|
+
if (vtxo.isSpent) continue;
|
|
17091
|
+
let tapTree = tapTrees.get(vtxo.script);
|
|
17092
|
+
if (!tapTree) {
|
|
17093
|
+
const [contract] = await opts.wallet.contractRepository.getContracts({
|
|
17094
|
+
script: vtxo.script
|
|
17095
|
+
});
|
|
17096
|
+
if (!contract) {
|
|
17097
|
+
throw new Error(
|
|
17098
|
+
`no contract registered for vtxo script ${vtxo.script} \u2014 register the contract before exiting`
|
|
17099
|
+
);
|
|
17100
|
+
}
|
|
17101
|
+
const handler = chunk32YKLQPS_cjs.contractHandlers.get(contract.type);
|
|
17102
|
+
if (!handler) {
|
|
17103
|
+
throw new Error(`no contract handler registered for type '${contract.type}'`);
|
|
17104
|
+
}
|
|
17105
|
+
tapTree = handler.createScript(contract.params).encode();
|
|
17106
|
+
tapTrees.set(vtxo.script, tapTree);
|
|
17107
|
+
}
|
|
17108
|
+
out.push({ txid: vtxo.txid, vout: vtxo.vout, value: vtxo.value, tapTree });
|
|
17109
|
+
}
|
|
17110
|
+
return out;
|
|
17111
|
+
}
|
|
17112
|
+
async function computeExitLayout(opts, feeRate) {
|
|
17113
|
+
const { wallet, onchainWallet } = opts;
|
|
17114
|
+
const vtxos = await selectExitVtxos(opts);
|
|
17115
|
+
if (vtxos.length === 0) throw new Error("no vtxos to exit");
|
|
17116
|
+
const dag = await buildExitDag({
|
|
17117
|
+
vtxos,
|
|
17118
|
+
indexer: wallet.indexerProvider,
|
|
17119
|
+
onchain: wallet.onchainProvider
|
|
17120
|
+
});
|
|
17121
|
+
const pendingNodes = dag.filter((n) => !n.confirmed);
|
|
17122
|
+
const psbts = /* @__PURE__ */ new Map();
|
|
17123
|
+
if (pendingNodes.length > 0) {
|
|
17124
|
+
const txids = pendingNodes.map((n) => n.txid);
|
|
17125
|
+
let pageIndex = 0;
|
|
17126
|
+
let hasMore = true;
|
|
17127
|
+
while (hasMore) {
|
|
17128
|
+
const { txs, page } = await wallet.indexerProvider.getVirtualTxs(txids, {
|
|
17129
|
+
pageIndex,
|
|
17130
|
+
pageSize: chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE
|
|
17131
|
+
});
|
|
17132
|
+
for (const psbt of txs) {
|
|
17133
|
+
psbts.set(chunkUBYY2TPK_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
17134
|
+
}
|
|
17135
|
+
hasMore = page ? txs.length === chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE : false;
|
|
17136
|
+
pageIndex++;
|
|
17137
|
+
}
|
|
17138
|
+
}
|
|
17139
|
+
const childVsize = Number(
|
|
17140
|
+
TxWeightEstimator.create().addP2AInput().addKeySpendInput(true).addOutputAddress(onchainWallet.address, wallet.network).vsize().value
|
|
17141
|
+
);
|
|
17142
|
+
const rawSteps = pendingNodes.map((node) => {
|
|
17143
|
+
const psbt = psbts.get(node.txid);
|
|
17144
|
+
if (!psbt) {
|
|
17145
|
+
throw new Error(`indexer did not return virtual tx ${node.txid}`);
|
|
17146
|
+
}
|
|
17147
|
+
const parent = finalizeVirtualTx(node.type, psbt);
|
|
17148
|
+
const stepFee = Math.ceil(feeRate * (parent.vsize + childVsize));
|
|
17149
|
+
return { node, parent, stepFee, funding: stepFundingAmount(stepFee) };
|
|
17150
|
+
});
|
|
17151
|
+
const parentInputTxids = (tx) => {
|
|
17152
|
+
const ids = [];
|
|
17153
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
17154
|
+
const txid = tx.getInput(i).txid;
|
|
17155
|
+
if (txid) ids.push(base.hex.encode(txid));
|
|
17156
|
+
}
|
|
17157
|
+
return ids;
|
|
17158
|
+
};
|
|
17159
|
+
const steps = topoSortByDeps(
|
|
17160
|
+
rawSteps,
|
|
17161
|
+
(s) => s.parent.id,
|
|
17162
|
+
(s) => parentInputTxids(s.parent)
|
|
17163
|
+
);
|
|
17164
|
+
const walletPubKeyHex = base.hex.encode(await wallet.identity.xOnlyPublicKey());
|
|
17165
|
+
const infos = [];
|
|
17166
|
+
const sweeps = [];
|
|
17167
|
+
for (const vtxo of vtxos) {
|
|
17168
|
+
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
17169
|
+
try {
|
|
17170
|
+
const resolved = await resolveUnilateralPath({
|
|
17171
|
+
vtxo,
|
|
17172
|
+
scriptHex: base.hex.encode(chunkHXDZ2QTW_cjs.VtxoScript.decode(vtxo.tapTree).pkScript),
|
|
17173
|
+
contractRepository: wallet.contractRepository,
|
|
17174
|
+
walletPubKeyHex,
|
|
17175
|
+
currentTime: Date.now()
|
|
17176
|
+
});
|
|
17177
|
+
const sweepFee = sweepFeeFor(
|
|
17178
|
+
resolved.selection,
|
|
17179
|
+
opts.sweepAddress,
|
|
17180
|
+
wallet.network,
|
|
17181
|
+
feeRate
|
|
17182
|
+
);
|
|
17183
|
+
if (vtxo.value - sweepFee < CHILD_OUTPUT_DUST) {
|
|
17184
|
+
infos.push({
|
|
17185
|
+
outpoint,
|
|
17186
|
+
value: vtxo.value,
|
|
17187
|
+
skipped: `uneconomic: value ${vtxo.value} <= sweep fee + dust`
|
|
17188
|
+
});
|
|
17189
|
+
continue;
|
|
17190
|
+
}
|
|
17191
|
+
const t = chunkHXDZ2QTW_cjs.sequenceToTimelock(resolved.selection.sequence);
|
|
17192
|
+
const delay = { type: t.type, value: Number(t.value) };
|
|
17193
|
+
infos.push({ outpoint, value: vtxo.value, sweepFee, path: resolved.label, delay });
|
|
17194
|
+
sweeps.push({ vtxo, resolved, sweepFee, delay });
|
|
17195
|
+
} catch (e) {
|
|
17196
|
+
if (e instanceof ExitPathError) {
|
|
17197
|
+
infos.push({ outpoint, value: vtxo.value, skipped: e.message });
|
|
17198
|
+
continue;
|
|
17199
|
+
}
|
|
17200
|
+
throw e;
|
|
17201
|
+
}
|
|
17202
|
+
}
|
|
17203
|
+
const coins = (await onchainWallet.getCoins()).filter((c) => c.status.confirmed);
|
|
17204
|
+
const balance = coins.reduce((sum, c) => sum + c.value, 0);
|
|
17205
|
+
const fundingTotal = steps.reduce((sum, s) => sum + s.funding, 0);
|
|
17206
|
+
const splitterFeeFor = (inputCount) => {
|
|
17207
|
+
if (steps.length === 0) return 0;
|
|
17208
|
+
const est = TxWeightEstimator.create();
|
|
17209
|
+
for (let i = 0; i < inputCount; i++) est.addKeySpendInput(true);
|
|
17210
|
+
for (let i = 0; i < steps.length + 1; i++) {
|
|
17211
|
+
est.addOutputAddress(onchainWallet.address, wallet.network);
|
|
17212
|
+
}
|
|
17213
|
+
return Number(est.vsize().fee(BigInt(feeRate)));
|
|
17214
|
+
};
|
|
17215
|
+
const graph = resolveMode(opts) === "graph";
|
|
17216
|
+
let splitterFee = 0;
|
|
17217
|
+
if (!graph) {
|
|
17218
|
+
splitterFee = splitterFeeFor(Math.max(1, coins.length));
|
|
17219
|
+
if (steps.length > 0 && balance < fundingTotal + splitterFee) {
|
|
17220
|
+
splitterFee = splitterFeeFor(coins.length + 1);
|
|
17221
|
+
}
|
|
17222
|
+
}
|
|
17223
|
+
const stepFees = steps.reduce((s, x) => s + x.stepFee, 0);
|
|
17224
|
+
const sweepFees = sweeps.reduce((s, x) => s + x.sweepFee, 0);
|
|
17225
|
+
const totals = {
|
|
17226
|
+
// graph: each unroll step is parent + a live-built child (2 txs), no
|
|
17227
|
+
// splitter. funded: + 1 splitter tx and pre-signed children.
|
|
17228
|
+
txCount: (graph ? 0 : steps.length > 0 ? 1 : 0) + steps.length * 2 + sweeps.length,
|
|
17229
|
+
totalFeeSats: splitterFee + stepFees + sweepFees,
|
|
17230
|
+
// graph funding is what the executor sends to its own fee address:
|
|
17231
|
+
// just the CPFP fees (change recycles); funded also locks the
|
|
17232
|
+
// per-child dust into the splitter.
|
|
17233
|
+
fundingRequiredSats: graph ? stepFees : splitterFee + fundingTotal,
|
|
17234
|
+
recoveredSats: sweeps.reduce((s, x) => s + (x.vtxo.value - x.sweepFee), 0)
|
|
17235
|
+
};
|
|
17236
|
+
const expiries = pendingNodes.map((n) => n.expiresAt).filter((x) => x !== void 0);
|
|
17237
|
+
const validUntil = expiries.length > 0 ? Math.min(...expiries) : void 0;
|
|
17238
|
+
return {
|
|
17239
|
+
vtxos,
|
|
17240
|
+
dag,
|
|
17241
|
+
steps,
|
|
17242
|
+
sweeps,
|
|
17243
|
+
infos,
|
|
17244
|
+
totals,
|
|
17245
|
+
splitterFee,
|
|
17246
|
+
validUntil,
|
|
17247
|
+
balance,
|
|
17248
|
+
coins
|
|
17249
|
+
};
|
|
17250
|
+
}
|
|
17251
|
+
async function estimate(opts) {
|
|
17252
|
+
const feeRate = await resolveFeeRate(opts);
|
|
17253
|
+
const layout = await computeExitLayout(opts, feeRate);
|
|
17254
|
+
if (resolveMode(opts) === "graph") {
|
|
17255
|
+
return {
|
|
17256
|
+
feeRate,
|
|
17257
|
+
fundingAddress: "",
|
|
17258
|
+
currentBalanceSats: 0,
|
|
17259
|
+
shortfallSats: layout.totals.fundingRequiredSats,
|
|
17260
|
+
validUntil: layout.validUntil,
|
|
17261
|
+
totals: layout.totals,
|
|
17262
|
+
vtxos: layout.infos
|
|
17263
|
+
};
|
|
17264
|
+
}
|
|
17265
|
+
return {
|
|
17266
|
+
feeRate,
|
|
17267
|
+
fundingAddress: opts.onchainWallet.address,
|
|
17268
|
+
currentBalanceSats: layout.balance,
|
|
17269
|
+
shortfallSats: Math.max(0, layout.totals.fundingRequiredSats - layout.balance),
|
|
17270
|
+
validUntil: layout.validUntil,
|
|
17271
|
+
totals: layout.totals,
|
|
17272
|
+
vtxos: layout.infos
|
|
17273
|
+
};
|
|
17274
|
+
}
|
|
17275
|
+
|
|
17276
|
+
// src/wallet/exit/executor.ts
|
|
17277
|
+
var Executor = class {
|
|
17278
|
+
constructor(pkg, provider, opts) {
|
|
17279
|
+
this.pkg = pkg;
|
|
17280
|
+
this.provider = provider;
|
|
17281
|
+
this.pollIntervalMs = opts?.pollIntervalMs ?? 5e3;
|
|
17282
|
+
this.feeWallet = opts?.feeWallet;
|
|
17283
|
+
}
|
|
17284
|
+
pollIntervalMs;
|
|
17285
|
+
feeWallet;
|
|
17286
|
+
sleep() {
|
|
17287
|
+
return new Promise((r) => setTimeout(r, this.pollIntervalMs));
|
|
17288
|
+
}
|
|
17289
|
+
async status(txid) {
|
|
17290
|
+
try {
|
|
17291
|
+
return await this.provider.getTxStatus(txid);
|
|
17292
|
+
} catch {
|
|
17293
|
+
return void 0;
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17296
|
+
async waitConfirmed(txid) {
|
|
17297
|
+
for (; ; ) {
|
|
17298
|
+
const s = await this.status(txid);
|
|
17299
|
+
if (s?.confirmed) return s;
|
|
17300
|
+
await this.sleep();
|
|
17301
|
+
}
|
|
17302
|
+
}
|
|
17303
|
+
async *[Symbol.asyncIterator]() {
|
|
17304
|
+
const dead = /* @__PURE__ */ new Set();
|
|
17305
|
+
if (this.pkg.validUntil && Date.now() / 1e3 > this.pkg.validUntil) {
|
|
17306
|
+
yield {
|
|
17307
|
+
stepIndex: -1,
|
|
17308
|
+
kind: "broadcast",
|
|
17309
|
+
status: "warning",
|
|
17310
|
+
reason: `package validUntil ${this.pkg.validUntil} has passed; the operator may have swept \u2014 attempting anyway`
|
|
17311
|
+
};
|
|
17312
|
+
}
|
|
17313
|
+
const sweeps = [];
|
|
17314
|
+
for (let i = 0; i < this.pkg.steps.length; i++) {
|
|
17315
|
+
const step = this.pkg.steps[i];
|
|
17316
|
+
if (step.kind === "sweep") {
|
|
17317
|
+
sweeps.push({ index: i, step });
|
|
17318
|
+
continue;
|
|
17319
|
+
}
|
|
17320
|
+
const forVtxos = step.kind === "package" || step.kind === "bump" ? step.forVtxos : void 0;
|
|
17321
|
+
if (forVtxos && forVtxos.every((v) => dead.has(v))) {
|
|
17322
|
+
yield {
|
|
17323
|
+
stepIndex: i,
|
|
17324
|
+
kind: step.kind,
|
|
17325
|
+
status: "skipped",
|
|
17326
|
+
forVtxos,
|
|
17327
|
+
reason: "branch failed earlier"
|
|
17328
|
+
};
|
|
17329
|
+
continue;
|
|
17330
|
+
}
|
|
17331
|
+
const anchorTxid = step.kind === "package" || step.kind === "bump" ? step.parentTxid : step.txid;
|
|
17332
|
+
const existing = await this.status(anchorTxid);
|
|
17333
|
+
if (existing?.confirmed) {
|
|
17334
|
+
yield {
|
|
17335
|
+
stepIndex: i,
|
|
17336
|
+
kind: step.kind,
|
|
17337
|
+
status: "skipped",
|
|
17338
|
+
txid: anchorTxid,
|
|
17339
|
+
forVtxos
|
|
17340
|
+
};
|
|
17341
|
+
continue;
|
|
17342
|
+
}
|
|
17343
|
+
if (!existing) {
|
|
17344
|
+
try {
|
|
17345
|
+
if (step.kind === "package") {
|
|
17346
|
+
await this.provider.broadcastTransaction(step.parentHex, step.childHex);
|
|
17347
|
+
} else if (step.kind === "bump") {
|
|
17348
|
+
if (!this.feeWallet) {
|
|
17349
|
+
throw new Error(
|
|
17350
|
+
"graph package requires a fee wallet (opts.feeWallet) to fund CPFP bumps"
|
|
17351
|
+
);
|
|
17352
|
+
}
|
|
17353
|
+
const [parentHex, childHex] = await this.feeWallet.bumpAnchor(
|
|
17354
|
+
step.parentHex,
|
|
17355
|
+
this.pkg.feeRate
|
|
17356
|
+
);
|
|
17357
|
+
await this.provider.broadcastTransaction(parentHex, childHex);
|
|
17358
|
+
} else {
|
|
17359
|
+
await this.provider.broadcastTransaction(step.hex);
|
|
17360
|
+
}
|
|
17361
|
+
yield {
|
|
17362
|
+
stepIndex: i,
|
|
17363
|
+
kind: step.kind,
|
|
17364
|
+
status: "broadcast",
|
|
17365
|
+
txid: anchorTxid,
|
|
17366
|
+
forVtxos
|
|
17367
|
+
};
|
|
17368
|
+
} catch (e) {
|
|
17369
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
17370
|
+
if (step.kind === "broadcast") {
|
|
17371
|
+
for (const s of this.pkg.steps) {
|
|
17372
|
+
if (s.kind === "package") s.forVtxos.forEach((v) => dead.add(v));
|
|
17373
|
+
}
|
|
17374
|
+
} else if (step.kind === "package" || step.kind === "bump") {
|
|
17375
|
+
step.forVtxos.forEach((v) => dead.add(v));
|
|
17376
|
+
}
|
|
17377
|
+
yield {
|
|
17378
|
+
stepIndex: i,
|
|
17379
|
+
kind: step.kind,
|
|
17380
|
+
status: "failed",
|
|
17381
|
+
txid: anchorTxid,
|
|
17382
|
+
forVtxos,
|
|
17383
|
+
reason
|
|
17384
|
+
};
|
|
17385
|
+
continue;
|
|
17386
|
+
}
|
|
17387
|
+
}
|
|
17388
|
+
await this.waitConfirmed(anchorTxid);
|
|
17389
|
+
yield {
|
|
17390
|
+
stepIndex: i,
|
|
17391
|
+
kind: step.kind,
|
|
17392
|
+
status: "confirmed",
|
|
17393
|
+
txid: anchorTxid,
|
|
17394
|
+
forVtxos
|
|
17395
|
+
};
|
|
17396
|
+
}
|
|
17397
|
+
for (const { index, step } of sweeps) {
|
|
17398
|
+
if (dead.has(step.vtxo)) {
|
|
17399
|
+
yield {
|
|
17400
|
+
stepIndex: index,
|
|
17401
|
+
kind: "sweep",
|
|
17402
|
+
status: "failed",
|
|
17403
|
+
txid: step.txid,
|
|
17404
|
+
forVtxos: [step.vtxo],
|
|
17405
|
+
reason: "branch failed earlier"
|
|
17406
|
+
};
|
|
17407
|
+
}
|
|
17408
|
+
}
|
|
17409
|
+
const pending = sweeps.filter(({ step }) => !dead.has(step.vtxo));
|
|
17410
|
+
const waitingAnnounced = /* @__PURE__ */ new Set();
|
|
17411
|
+
const done = /* @__PURE__ */ new Set();
|
|
17412
|
+
while (done.size < pending.length) {
|
|
17413
|
+
for (const { index, step } of pending) {
|
|
17414
|
+
if (done.has(index)) continue;
|
|
17415
|
+
const swept = await this.status(step.txid);
|
|
17416
|
+
if (swept?.confirmed) {
|
|
17417
|
+
done.add(index);
|
|
17418
|
+
yield {
|
|
17419
|
+
stepIndex: index,
|
|
17420
|
+
kind: "sweep",
|
|
17421
|
+
status: "confirmed",
|
|
17422
|
+
txid: step.txid,
|
|
17423
|
+
forVtxos: [step.vtxo]
|
|
17424
|
+
};
|
|
17425
|
+
continue;
|
|
17426
|
+
}
|
|
17427
|
+
if (swept) continue;
|
|
17428
|
+
const dep = await this.status(step.dependsOnTxid);
|
|
17429
|
+
if (!dep?.confirmed) continue;
|
|
17430
|
+
const tip = await this.provider.getChainTip();
|
|
17431
|
+
const mature = step.delay.type === "blocks" ? tip.height >= (dep.blockHeight ?? 0) + step.delay.value : tip.time >= (dep.blockTime ?? 0) + step.delay.value;
|
|
17432
|
+
if (!mature) {
|
|
17433
|
+
if (!waitingAnnounced.has(index)) {
|
|
17434
|
+
waitingAnnounced.add(index);
|
|
17435
|
+
yield {
|
|
17436
|
+
stepIndex: index,
|
|
17437
|
+
kind: "sweep",
|
|
17438
|
+
status: "waiting_csv",
|
|
17439
|
+
txid: step.txid,
|
|
17440
|
+
forVtxos: [step.vtxo],
|
|
17441
|
+
...step.delay.type === "blocks" ? { maturesAtHeight: (dep.blockHeight ?? 0) + step.delay.value } : { maturesAtTime: (dep.blockTime ?? 0) + step.delay.value }
|
|
17442
|
+
};
|
|
17443
|
+
}
|
|
17444
|
+
continue;
|
|
17445
|
+
}
|
|
17446
|
+
try {
|
|
17447
|
+
await this.provider.broadcastTransaction(step.hex);
|
|
17448
|
+
yield {
|
|
17449
|
+
stepIndex: index,
|
|
17450
|
+
kind: "sweep",
|
|
17451
|
+
status: "broadcast",
|
|
17452
|
+
txid: step.txid,
|
|
17453
|
+
forVtxos: [step.vtxo]
|
|
17454
|
+
};
|
|
17455
|
+
} catch (e) {
|
|
17456
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
17457
|
+
if (/non-?bip68|non-?final|premature/i.test(reason)) {
|
|
17458
|
+
continue;
|
|
17459
|
+
}
|
|
17460
|
+
done.add(index);
|
|
17461
|
+
yield {
|
|
17462
|
+
stepIndex: index,
|
|
17463
|
+
kind: "sweep",
|
|
17464
|
+
status: "failed",
|
|
17465
|
+
txid: step.txid,
|
|
17466
|
+
forVtxos: [step.vtxo],
|
|
17467
|
+
reason
|
|
17468
|
+
};
|
|
17469
|
+
}
|
|
17470
|
+
}
|
|
17471
|
+
if (done.size < pending.length) await this.sleep();
|
|
17472
|
+
}
|
|
17473
|
+
}
|
|
17474
|
+
};
|
|
17475
|
+
async function prepare(opts) {
|
|
17476
|
+
const { wallet, onchainWallet } = opts;
|
|
17477
|
+
const feeRate = await resolveFeeRate(opts);
|
|
17478
|
+
const mode = resolveMode(opts);
|
|
17479
|
+
if (mode === "funded") {
|
|
17480
|
+
const walletKey = await wallet.identity.xOnlyPublicKey();
|
|
17481
|
+
if (base.hex.encode(onchainWallet.onchainP2TR.tapInternalKey) !== base.hex.encode(walletKey)) {
|
|
17482
|
+
throw new Error("onchainWallet must share the wallet identity");
|
|
17483
|
+
}
|
|
17484
|
+
}
|
|
17485
|
+
const layout = await computeExitLayout(opts, feeRate);
|
|
17486
|
+
const sweepSteps = [];
|
|
17487
|
+
const activeOutpoints = /* @__PURE__ */ new Set();
|
|
17488
|
+
for (const sweep of layout.sweeps) {
|
|
17489
|
+
const outpoint = `${sweep.vtxo.txid}:${sweep.vtxo.vout}`;
|
|
17490
|
+
try {
|
|
17491
|
+
const { tx } = await buildSignedSweep({
|
|
17492
|
+
vtxo: {
|
|
17493
|
+
txid: sweep.vtxo.txid,
|
|
17494
|
+
vout: sweep.vtxo.vout,
|
|
17495
|
+
value: sweep.vtxo.value,
|
|
17496
|
+
pkScript: chunkHXDZ2QTW_cjs.VtxoScript.decode(sweep.vtxo.tapTree).pkScript
|
|
17497
|
+
},
|
|
17498
|
+
path: sweep.resolved.selection,
|
|
17499
|
+
outputAddress: opts.sweepAddress,
|
|
17500
|
+
feeRate,
|
|
17501
|
+
network: wallet.network,
|
|
17502
|
+
identity: wallet.identity
|
|
17503
|
+
});
|
|
17504
|
+
activeOutpoints.add(outpoint);
|
|
17505
|
+
sweepSteps.push({
|
|
17506
|
+
kind: "sweep",
|
|
17507
|
+
vtxo: outpoint,
|
|
17508
|
+
txid: tx.id,
|
|
17509
|
+
hex: tx.hex,
|
|
17510
|
+
dependsOnTxid: sweep.vtxo.txid,
|
|
17511
|
+
delay: sweep.delay
|
|
17512
|
+
});
|
|
17513
|
+
} catch (e) {
|
|
17514
|
+
const info = layout.infos.find((i) => i.outpoint === outpoint);
|
|
17515
|
+
if (info) {
|
|
17516
|
+
info.skipped = e instanceof Error ? e.message : String(e);
|
|
17517
|
+
delete info.sweepFee;
|
|
17518
|
+
delete info.path;
|
|
17519
|
+
delete info.delay;
|
|
17520
|
+
}
|
|
17521
|
+
}
|
|
17522
|
+
}
|
|
17523
|
+
const steps = layout.steps.filter((s) => s.node.forVtxos.some((v) => activeOutpoints.has(v)));
|
|
17524
|
+
if (steps.length === 0 && sweepSteps.length === 0) {
|
|
17525
|
+
throw new Error("no exitable vtxos (all skipped)");
|
|
17526
|
+
}
|
|
17527
|
+
if (mode === "graph") {
|
|
17528
|
+
const bumpSteps = steps.map((step) => ({
|
|
17529
|
+
kind: "bump",
|
|
17530
|
+
parentTxid: step.parent.id,
|
|
17531
|
+
parentHex: step.parent.hex,
|
|
17532
|
+
forVtxos: step.node.forVtxos.filter((v) => activeOutpoints.has(v))
|
|
17533
|
+
}));
|
|
17534
|
+
const stepFees2 = steps.reduce((s, x) => s + x.stepFee, 0);
|
|
17535
|
+
const activeInfos2 = layout.infos.filter((i) => !i.skipped);
|
|
17536
|
+
const sweepFees2 = activeInfos2.reduce((s, i) => s + (i.sweepFee ?? 0), 0);
|
|
17537
|
+
const recovered2 = activeInfos2.reduce((s, i) => s + (i.value ?? 0) - (i.sweepFee ?? 0), 0);
|
|
17538
|
+
return {
|
|
17539
|
+
version: 1,
|
|
17540
|
+
mode: "graph",
|
|
17541
|
+
network: resolveNetworkName(opts),
|
|
17542
|
+
createdAt: Math.floor(Date.now() / 1e3),
|
|
17543
|
+
validUntil: layout.validUntil,
|
|
17544
|
+
feeRate,
|
|
17545
|
+
sweepAddress: opts.sweepAddress,
|
|
17546
|
+
totals: {
|
|
17547
|
+
txCount: bumpSteps.length * 2 + sweepSteps.length,
|
|
17548
|
+
totalFeeSats: stepFees2 + sweepFees2,
|
|
17549
|
+
fundingRequiredSats: stepFees2,
|
|
17550
|
+
recoveredSats: recovered2
|
|
17551
|
+
},
|
|
17552
|
+
vtxos: layout.infos,
|
|
17553
|
+
steps: [...bumpSteps, ...sweepSteps]
|
|
17554
|
+
};
|
|
17555
|
+
}
|
|
17556
|
+
const packageSteps = [];
|
|
17557
|
+
let broadcastStep;
|
|
17558
|
+
let splitterFee = 0;
|
|
17559
|
+
if (steps.length > 0) {
|
|
17560
|
+
const fundingTotal = steps.reduce((sum, s) => sum + s.funding, 0);
|
|
17561
|
+
let selected = { inputs: [], changeAmount: 0n };
|
|
17562
|
+
for (let i = 0; i < 10; i++) {
|
|
17563
|
+
const target = fundingTotal + splitterFee;
|
|
17564
|
+
try {
|
|
17565
|
+
selected = selectCoins(layout.coins, target);
|
|
17566
|
+
} catch {
|
|
17567
|
+
throw new Error(
|
|
17568
|
+
`insufficient confirmed onchain funds: need ${target} sats, have ${layout.balance} (deposit the shortfall to ${onchainWallet.address})`
|
|
17569
|
+
);
|
|
17570
|
+
}
|
|
17571
|
+
const est = TxWeightEstimator.create();
|
|
17572
|
+
for (const _ of selected.inputs) est.addKeySpendInput(true);
|
|
17573
|
+
for (const _ of steps) est.addOutputAddress(onchainWallet.address, wallet.network);
|
|
17574
|
+
if (selected.changeAmount >= BigInt(DUST_AMOUNT)) {
|
|
17575
|
+
est.addOutputAddress(onchainWallet.address, wallet.network);
|
|
17576
|
+
}
|
|
17577
|
+
const newFee = Number(est.vsize().fee(BigInt(feeRate)));
|
|
17578
|
+
if (newFee <= splitterFee) break;
|
|
17579
|
+
splitterFee = newFee;
|
|
17580
|
+
}
|
|
17581
|
+
const splitter = new chunkUBYY2TPK_cjs.Transaction({ version: 2 });
|
|
17582
|
+
for (const coin of selected.inputs) {
|
|
17583
|
+
splitter.addInput({
|
|
17584
|
+
txid: coin.txid,
|
|
17585
|
+
index: coin.vout,
|
|
17586
|
+
witnessUtxo: {
|
|
17587
|
+
script: onchainWallet.onchainP2TR.script,
|
|
17588
|
+
amount: BigInt(coin.value)
|
|
17589
|
+
},
|
|
17590
|
+
tapInternalKey: onchainWallet.onchainP2TR.tapInternalKey
|
|
17591
|
+
});
|
|
17592
|
+
}
|
|
17593
|
+
for (const step of steps) {
|
|
17594
|
+
splitter.addOutputAddress(onchainWallet.address, BigInt(step.funding), wallet.network);
|
|
17595
|
+
}
|
|
17596
|
+
const inputSum = selected.inputs.reduce((s, c) => s + c.value, 0);
|
|
17597
|
+
const change = BigInt(inputSum - fundingTotal - splitterFee);
|
|
17598
|
+
if (change < 0n) {
|
|
17599
|
+
throw new Error(
|
|
17600
|
+
`insufficient confirmed onchain funds for the splitter fee: need ${fundingTotal + splitterFee} sats, have ${inputSum} (deposit the shortfall to ${onchainWallet.address})`
|
|
17601
|
+
);
|
|
17602
|
+
}
|
|
17603
|
+
if (change >= BigInt(DUST_AMOUNT)) {
|
|
17604
|
+
splitter.addOutputAddress(onchainWallet.address, change, wallet.network);
|
|
17605
|
+
} else if (change > 0n) {
|
|
17606
|
+
splitterFee += Number(change);
|
|
17607
|
+
}
|
|
17608
|
+
const signedSplitter = await wallet.identity.sign(splitter);
|
|
17609
|
+
signedSplitter.finalize();
|
|
17610
|
+
for (let k = 0; k < steps.length; k++) {
|
|
17611
|
+
const step = steps[k];
|
|
17612
|
+
const { child } = buildAnchorChild({
|
|
17613
|
+
parent: step.parent,
|
|
17614
|
+
feeRate,
|
|
17615
|
+
fundingCoins: [{ txid: signedSplitter.id, vout: k, value: step.funding }],
|
|
17616
|
+
changeAddress: onchainWallet.address,
|
|
17617
|
+
changeScript: onchainWallet.onchainP2TR.script,
|
|
17618
|
+
tapInternalKey: onchainWallet.onchainP2TR.tapInternalKey,
|
|
17619
|
+
network: wallet.network
|
|
17620
|
+
});
|
|
17621
|
+
const signedChild = await wallet.identity.sign(child);
|
|
17622
|
+
for (let i = 1; i < signedChild.inputsLength; i++) {
|
|
17623
|
+
signedChild.finalizeIdx(i);
|
|
17624
|
+
}
|
|
17625
|
+
packageSteps.push({
|
|
17626
|
+
kind: "package",
|
|
17627
|
+
parentTxid: step.parent.id,
|
|
17628
|
+
parentHex: step.parent.hex,
|
|
17629
|
+
childTxid: signedChild.id,
|
|
17630
|
+
childHex: signedChild.hex,
|
|
17631
|
+
forVtxos: step.node.forVtxos.filter((v) => activeOutpoints.has(v))
|
|
17632
|
+
});
|
|
17633
|
+
}
|
|
17634
|
+
broadcastStep = { kind: "broadcast", txid: signedSplitter.id, hex: signedSplitter.hex };
|
|
17635
|
+
await onchainWallet.provider.broadcastTransaction(signedSplitter.hex);
|
|
17636
|
+
}
|
|
17637
|
+
const stepFees = steps.reduce((s, x) => s + x.stepFee, 0);
|
|
17638
|
+
const activeInfos = layout.infos.filter((i) => !i.skipped);
|
|
17639
|
+
const sweepFees = activeInfos.reduce((s, i) => s + (i.sweepFee ?? 0), 0);
|
|
17640
|
+
const recovered = activeInfos.reduce((s, i) => s + (i.value ?? 0) - (i.sweepFee ?? 0), 0);
|
|
17641
|
+
const fundingRequired = splitterFee + steps.reduce((s, x) => s + x.funding, 0);
|
|
17642
|
+
return {
|
|
17643
|
+
version: 1,
|
|
17644
|
+
mode: "funded",
|
|
17645
|
+
network: resolveNetworkName(opts),
|
|
17646
|
+
createdAt: Math.floor(Date.now() / 1e3),
|
|
17647
|
+
validUntil: layout.validUntil,
|
|
17648
|
+
feeRate,
|
|
17649
|
+
sweepAddress: opts.sweepAddress,
|
|
17650
|
+
totals: {
|
|
17651
|
+
txCount: (broadcastStep ? 1 : 0) + packageSteps.length * 2 + sweepSteps.length,
|
|
17652
|
+
totalFeeSats: splitterFee + stepFees + sweepFees,
|
|
17653
|
+
fundingRequiredSats: fundingRequired,
|
|
17654
|
+
recoveredSats: recovered
|
|
17655
|
+
},
|
|
17656
|
+
vtxos: layout.infos,
|
|
17657
|
+
steps: [...broadcastStep ? [broadcastStep] : [], ...packageSteps, ...sweepSteps]
|
|
17658
|
+
};
|
|
17659
|
+
}
|
|
17660
|
+
|
|
17661
|
+
// src/wallet/exit/types.ts
|
|
17662
|
+
function serializeExitPackage(pkg) {
|
|
17663
|
+
return JSON.stringify(pkg);
|
|
17664
|
+
}
|
|
17665
|
+
function deserializeExitPackage(json) {
|
|
17666
|
+
const data = JSON.parse(json);
|
|
17667
|
+
if (data?.version !== 1) {
|
|
17668
|
+
throw new Error(`unsupported exit package version: ${data?.version}`);
|
|
17669
|
+
}
|
|
17670
|
+
if (typeof data.network !== "string" || typeof data.sweepAddress !== "string") {
|
|
17671
|
+
throw new Error("invalid exit package: missing network or sweepAddress");
|
|
17672
|
+
}
|
|
17673
|
+
if (typeof data.feeRate !== "number" || typeof data.createdAt !== "number") {
|
|
17674
|
+
throw new Error("invalid exit package: missing feeRate or createdAt");
|
|
17675
|
+
}
|
|
17676
|
+
if (!Array.isArray(data.steps) || !Array.isArray(data.vtxos)) {
|
|
17677
|
+
throw new Error("invalid exit package: steps and vtxos must be arrays");
|
|
17678
|
+
}
|
|
17679
|
+
if (!isValidTotals(data.totals)) {
|
|
17680
|
+
throw new Error("invalid exit package: malformed totals");
|
|
17681
|
+
}
|
|
17682
|
+
for (const step of data.steps) {
|
|
17683
|
+
if (!isValidStep(step)) {
|
|
17684
|
+
throw new Error(`invalid step: ${JSON.stringify(step)}`);
|
|
17685
|
+
}
|
|
17686
|
+
}
|
|
17687
|
+
return data;
|
|
17688
|
+
}
|
|
17689
|
+
function isValidDelay(d) {
|
|
17690
|
+
const delay = d;
|
|
17691
|
+
return !!delay && (delay.type === "blocks" || delay.type === "seconds") && typeof delay.value === "number";
|
|
17692
|
+
}
|
|
17693
|
+
function isValidTotals(t) {
|
|
17694
|
+
const totals = t;
|
|
17695
|
+
return !!totals && typeof totals === "object" && typeof totals.txCount === "number" && typeof totals.totalFeeSats === "number" && typeof totals.fundingRequiredSats === "number" && typeof totals.recoveredSats === "number";
|
|
17696
|
+
}
|
|
17697
|
+
function isValidStep(step) {
|
|
17698
|
+
const s = step;
|
|
17699
|
+
if (!s || typeof s !== "object") return false;
|
|
17700
|
+
switch (s.kind) {
|
|
17701
|
+
case "broadcast":
|
|
17702
|
+
return typeof s.txid === "string" && typeof s.hex === "string";
|
|
17703
|
+
case "package":
|
|
17704
|
+
return typeof s.parentTxid === "string" && typeof s.parentHex === "string" && typeof s.childTxid === "string" && typeof s.childHex === "string" && Array.isArray(s.forVtxos);
|
|
17705
|
+
case "bump":
|
|
17706
|
+
return typeof s.parentTxid === "string" && typeof s.parentHex === "string" && Array.isArray(s.forVtxos);
|
|
17707
|
+
case "sweep":
|
|
17708
|
+
return typeof s.vtxo === "string" && typeof s.txid === "string" && typeof s.hex === "string" && typeof s.dependsOnTxid === "string" && isValidDelay(s.delay);
|
|
17709
|
+
default:
|
|
17710
|
+
return false;
|
|
17711
|
+
}
|
|
17712
|
+
}
|
|
17713
|
+
|
|
17714
|
+
// src/wallet/exit/index.ts
|
|
17715
|
+
var UnilateralExit = {
|
|
17716
|
+
estimate,
|
|
17717
|
+
prepare,
|
|
17718
|
+
Executor
|
|
17719
|
+
};
|
|
16813
17720
|
var ARKCONTRACT_PREFIX = "arkcontract";
|
|
16814
17721
|
function encodeArkContract(contract) {
|
|
16815
17722
|
const params = new URLSearchParams();
|
|
@@ -16926,6 +17833,7 @@ exports.SingleKey = SingleKey;
|
|
|
16926
17833
|
exports.TxTree = TxTree;
|
|
16927
17834
|
exports.TxType = TxType;
|
|
16928
17835
|
exports.TxWeightEstimator = TxWeightEstimator;
|
|
17836
|
+
exports.UnilateralExit = UnilateralExit;
|
|
16929
17837
|
exports.VtxoManager = VtxoManager;
|
|
16930
17838
|
exports.Wallet = Wallet2;
|
|
16931
17839
|
exports.WalletMessageHandler = WalletMessageHandler;
|
|
@@ -16945,6 +17853,7 @@ exports.contractFromArkContractWithAddress = contractFromArkContractWithAddress;
|
|
|
16945
17853
|
exports.createDefaultActivityRegistry = createDefaultActivityRegistry;
|
|
16946
17854
|
exports.decodeArkContract = decodeArkContract;
|
|
16947
17855
|
exports.deserializeAssets = deserializeAssets;
|
|
17856
|
+
exports.deserializeExitPackage = deserializeExitPackage;
|
|
16948
17857
|
exports.deserializeUtxo = deserializeUtxo;
|
|
16949
17858
|
exports.deserializeVtxo = deserializeVtxo;
|
|
16950
17859
|
exports.encodeArkContract = encodeArkContract;
|
|
@@ -16974,6 +17883,7 @@ exports.rollbackMigration = rollbackMigration;
|
|
|
16974
17883
|
exports.saveVtxosForContract = saveVtxosForContract;
|
|
16975
17884
|
exports.scriptFromArkAddress = scriptFromArkAddress;
|
|
16976
17885
|
exports.serializeAssets = serializeAssets;
|
|
17886
|
+
exports.serializeExitPackage = serializeExitPackage;
|
|
16977
17887
|
exports.serializeUtxo = serializeUtxo;
|
|
16978
17888
|
exports.serializeVtxo = serializeVtxo;
|
|
16979
17889
|
exports.setupServiceWorker = setupServiceWorker;
|
|
@@ -16984,5 +17894,5 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
|
16984
17894
|
exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
|
|
16985
17895
|
exports.waitForIncomingFunds = waitForIncomingFunds;
|
|
16986
17896
|
exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
|
|
16987
|
-
//# sourceMappingURL=chunk-
|
|
16988
|
-
//# sourceMappingURL=chunk-
|
|
17897
|
+
//# sourceMappingURL=chunk-XIVCG6EP.cjs.map
|
|
17898
|
+
//# sourceMappingURL=chunk-XIVCG6EP.cjs.map
|