@arkade-os/sdk 0.4.44 → 0.4.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dist/adapters/expo.cjs +4 -4
- package/dist/adapters/expo.d.cts +2 -2
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +2 -2
- package/dist/adapters/indexedDB.cjs +3 -3
- package/dist/adapters/indexedDB.js +2 -2
- package/dist/{ark-I8jfe5VE.d.cts → ark-C-PjOngm.d.cts} +89 -1
- package/dist/{ark-I8jfe5VE.d.ts → ark-C-PjOngm.d.ts} +89 -1
- package/dist/{asyncStorageTaskQueue-Dap7qUlF.d.cts → asyncStorageTaskQueue-BmBPvTyh.d.cts} +2 -2
- package/dist/{asyncStorageTaskQueue-BtSOVZFn.d.ts → asyncStorageTaskQueue-CHpI3moJ.d.ts} +2 -2
- package/dist/{chunk-V7WIZR2B.js → chunk-BOA4SHCD.js} +3 -3
- package/dist/{chunk-V7WIZR2B.js.map → chunk-BOA4SHCD.js.map} +1 -1
- package/dist/{chunk-X37EKDIH.cjs → chunk-HZ7VIN7P.cjs} +11 -11
- package/dist/{chunk-X37EKDIH.cjs.map → chunk-HZ7VIN7P.cjs.map} +1 -1
- package/dist/{chunk-RJ6XVCX4.cjs → chunk-OFQGANH2.cjs} +7 -7
- package/dist/{chunk-RJ6XVCX4.cjs.map → chunk-OFQGANH2.cjs.map} +1 -1
- package/dist/{chunk-LCQQPOIT.js → chunk-QZ6HZZZK.js} +3 -3
- package/dist/{chunk-LCQQPOIT.js.map → chunk-QZ6HZZZK.js.map} +1 -1
- package/dist/{chunk-XIVCG6EP.cjs → chunk-SRCWBFSZ.cjs} +1000 -322
- package/dist/chunk-SRCWBFSZ.cjs.map +1 -0
- package/dist/{chunk-FMI2GKYO.js → chunk-TGRJ5WAX.js} +919 -243
- package/dist/chunk-TGRJ5WAX.js.map +1 -0
- package/dist/{chunk-UBYY2TPK.cjs → chunk-UHOHLN3C.cjs} +119 -69
- package/dist/chunk-UHOHLN3C.cjs.map +1 -0
- package/dist/{chunk-LJ35HPJW.js → chunk-YBQV7XBC.js} +119 -70
- package/dist/chunk-YBQV7XBC.js.map +1 -0
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/{delegate-CgjVjYOP.d.ts → delegate-BKNqva1j.d.ts} +1 -1
- package/dist/{delegate-BRqbh2fW.d.cts → delegate-DOEobYwH.d.cts} +1 -1
- package/dist/{index-DHuXlDEg.d.cts → index-BlW4I30l.d.cts} +2 -2
- package/dist/{index-DvWNB_rl.d.ts → index-Cm2fGeox.d.ts} +2 -2
- package/dist/index.cjs +141 -129
- package/dist/index.d.cts +45 -20
- package/dist/index.d.ts +45 -20
- package/dist/index.js +2 -2
- package/dist/repositories/realm/index.cjs +17 -17
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/realm/index.js +3 -3
- package/dist/repositories/sqlite/index.cjs +16 -16
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.js +3 -3
- package/dist/{taskRunner-Bptw9UMa.d.ts → taskRunner-BngWSFMi.d.ts} +2 -2
- package/dist/{taskRunner-CeFxKhSH.d.cts → taskRunner-DOiyRuJa.d.cts} +2 -2
- package/dist/wallet/expo/background.cjs +12 -12
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +4 -4
- package/dist/wallet/expo/index.cjs +21 -12
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +11 -4
- package/dist/wallet/expo/index.d.ts +11 -4
- package/dist/wallet/expo/index.js +12 -3
- package/dist/wallet/expo/index.js.map +1 -1
- package/dist/{wallet-BsqRU8KM.d.cts → wallet-B3awP1Nj.d.ts} +105 -3
- package/dist/{wallet-D9z7wssl.d.ts → wallet-DBjumS42.d.cts} +105 -3
- package/dist/worker/expo/index.cjs +7 -7
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-FMI2GKYO.js.map +0 -1
- package/dist/chunk-LJ35HPJW.js.map +0 -1
- package/dist/chunk-UBYY2TPK.cjs.map +0 -1
- package/dist/chunk-XIVCG6EP.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkUHOHLN3C_cjs = require('./chunk-UHOHLN3C.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 = chunkUHOHLN3C_cjs.getArkPsbtFields(tx.root, 0, chunkUHOHLN3C_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 = chunkUHOHLN3C_cjs.getArkPsbtFields(g.root, 0, chunkUHOHLN3C_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 chunkUHOHLN3C_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: chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_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 chunkUHOHLN3C_cjs.baseFetch(`${this.baseUrl}/tx`, {
|
|
1215
1215
|
method: "POST",
|
|
1216
1216
|
headers: {
|
|
1217
1217
|
"Content-Type": "text/plain"
|
|
@@ -1373,7 +1373,7 @@ function findP2AOutput(tx) {
|
|
|
1373
1373
|
var CHILD_DUST_AMOUNT = 546;
|
|
1374
1374
|
function buildAnchorChild(params) {
|
|
1375
1375
|
const { parent, feeRate, fundingCoins, changeAddress, tapInternalKey, network } = params;
|
|
1376
|
-
const child = new
|
|
1376
|
+
const child = new chunkUHOHLN3C_cjs.Transaction({ version: 3, allowLegacyWitnessUtxo: true });
|
|
1377
1377
|
child.addInput(findP2AOutput(parent));
|
|
1378
1378
|
const estimator = TxWeightEstimator.create().addP2AInput();
|
|
1379
1379
|
for (const _ of fundingCoins) {
|
|
@@ -1421,7 +1421,7 @@ function buildForfeitTx(inputs, forfeitPkScript, txLocktime) {
|
|
|
1421
1421
|
);
|
|
1422
1422
|
}
|
|
1423
1423
|
function buildForfeitTxWithOutput(inputs, output, txLocktime) {
|
|
1424
|
-
const tx = new
|
|
1424
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({
|
|
1425
1425
|
version: 3,
|
|
1426
1426
|
lockTime: txLocktime
|
|
1427
1427
|
});
|
|
@@ -1497,7 +1497,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
|
|
|
1497
1497
|
if (previousScriptKey.length !== 32) {
|
|
1498
1498
|
throw new Error(`parent output ${childIndex} has invalid script`);
|
|
1499
1499
|
}
|
|
1500
|
-
const cosigners =
|
|
1500
|
+
const cosigners = chunkUHOHLN3C_cjs.getArkPsbtFields(child.root, 0, chunkUHOHLN3C_cjs.CosignerPublicKey);
|
|
1501
1501
|
if (cosigners.length === 0) {
|
|
1502
1502
|
throw ErrMissingCosignersPublicKeys;
|
|
1503
1503
|
}
|
|
@@ -1597,7 +1597,7 @@ var Extension = class _Extension {
|
|
|
1597
1597
|
`expected magic prefix ${base.hex.encode(ARKADE_MAGIC)}, got ${base.hex.encode(payload.slice(0, Math.min(payload.length, ARKADE_MAGIC.length)))}`
|
|
1598
1598
|
);
|
|
1599
1599
|
}
|
|
1600
|
-
const reader = new
|
|
1600
|
+
const reader = new chunkUHOHLN3C_cjs.BufferReader(payload.slice(ARKADE_MAGIC.length));
|
|
1601
1601
|
const packets = [];
|
|
1602
1602
|
while (reader.remaining() > 0) {
|
|
1603
1603
|
const packetType = reader.readByte();
|
|
@@ -1671,7 +1671,7 @@ var Extension = class _Extension {
|
|
|
1671
1671
|
*/
|
|
1672
1672
|
getAssetPacket() {
|
|
1673
1673
|
for (const p of this.packets) {
|
|
1674
|
-
if (p instanceof
|
|
1674
|
+
if (p instanceof chunkUHOHLN3C_cjs.Packet) {
|
|
1675
1675
|
return p;
|
|
1676
1676
|
}
|
|
1677
1677
|
}
|
|
@@ -1679,8 +1679,8 @@ var Extension = class _Extension {
|
|
|
1679
1679
|
}
|
|
1680
1680
|
};
|
|
1681
1681
|
function parsePacket(packetType, data) {
|
|
1682
|
-
if (packetType ===
|
|
1683
|
-
return
|
|
1682
|
+
if (packetType === chunkUHOHLN3C_cjs.Packet.PACKET_TYPE) {
|
|
1683
|
+
return chunkUHOHLN3C_cjs.Packet.fromBytes(data);
|
|
1684
1684
|
}
|
|
1685
1685
|
return new UnknownPacket(packetType, data);
|
|
1686
1686
|
}
|
|
@@ -1987,7 +1987,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1987
1987
|
const existing = inputsByAssetId.get(asset.assetId);
|
|
1988
1988
|
inputsByAssetId.set(asset.assetId, [
|
|
1989
1989
|
...existing ?? [],
|
|
1990
|
-
|
|
1990
|
+
chunkUHOHLN3C_cjs.AssetInput.create(inputIndex, asset.amount)
|
|
1991
1991
|
]);
|
|
1992
1992
|
}
|
|
1993
1993
|
}
|
|
@@ -1999,7 +1999,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
1999
1999
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
2000
2000
|
outputsByAssetId.set(asset.assetId, [
|
|
2001
2001
|
...existing ?? [],
|
|
2002
|
-
|
|
2002
|
+
chunkUHOHLN3C_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
2003
2003
|
]);
|
|
2004
2004
|
}
|
|
2005
2005
|
}
|
|
@@ -2010,7 +2010,7 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2010
2010
|
const existing = outputsByAssetId.get(asset.assetId);
|
|
2011
2011
|
outputsByAssetId.set(asset.assetId, [
|
|
2012
2012
|
...existing ?? [],
|
|
2013
|
-
|
|
2013
|
+
chunkUHOHLN3C_cjs.AssetOutput.create(outputIndex, asset.amount)
|
|
2014
2014
|
]);
|
|
2015
2015
|
}
|
|
2016
2016
|
}
|
|
@@ -2019,11 +2019,11 @@ function createAssetPacket(assetInputs, receivers, changeReceiver) {
|
|
|
2019
2019
|
for (const assetIdStr of allAssetIds) {
|
|
2020
2020
|
const inputs = inputsByAssetId.get(assetIdStr);
|
|
2021
2021
|
const outputs = outputsByAssetId.get(assetIdStr);
|
|
2022
|
-
const assetId =
|
|
2023
|
-
const group =
|
|
2022
|
+
const assetId = chunkUHOHLN3C_cjs.AssetId.fromString(assetIdStr);
|
|
2023
|
+
const group = chunkUHOHLN3C_cjs.AssetGroup.create(assetId, null, inputs ?? [], outputs ?? [], []);
|
|
2024
2024
|
groups.push(group);
|
|
2025
2025
|
}
|
|
2026
|
-
return
|
|
2026
|
+
return chunkUHOHLN3C_cjs.Packet.create(groups);
|
|
2027
2027
|
}
|
|
2028
2028
|
function selectCoinsWithAsset(coins, assetId, requiredAmount) {
|
|
2029
2029
|
const coinsWithAsset = coins.filter((coin) => coin.assets?.some((a) => a.assetId === assetId));
|
|
@@ -2140,7 +2140,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
2140
2140
|
}
|
|
2141
2141
|
}
|
|
2142
2142
|
}
|
|
2143
|
-
const tx = new
|
|
2143
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({
|
|
2144
2144
|
version: 3,
|
|
2145
2145
|
lockTime: Number(lockTime)
|
|
2146
2146
|
});
|
|
@@ -2155,7 +2155,7 @@ function buildVirtualTx(inputs, outputs) {
|
|
|
2155
2155
|
},
|
|
2156
2156
|
tapLeafScript: [input.tapLeafScript]
|
|
2157
2157
|
});
|
|
2158
|
-
|
|
2158
|
+
chunkUHOHLN3C_cjs.setArkPsbtField(tx, i, chunkUHOHLN3C_cjs.VtxoTaprootTree, input.tapTree);
|
|
2159
2159
|
}
|
|
2160
2160
|
for (const output of outputs) {
|
|
2161
2161
|
tx.addOutput(output);
|
|
@@ -3157,7 +3157,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3157
3157
|
`Sweep not economical: output ${outputAmount} sats after ${fee} sats fee is below dust (${dustAmount} sats)`
|
|
3158
3158
|
);
|
|
3159
3159
|
}
|
|
3160
|
-
const tx = new
|
|
3160
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction();
|
|
3161
3161
|
for (const utxo of expiredUtxos) {
|
|
3162
3162
|
const utxoScript = chunkHXDZ2QTW_cjs.VtxoScript.decode(utxo.tapTree);
|
|
3163
3163
|
const utxoExitLeaf = utxoScript.leaves.find(
|
|
@@ -3796,7 +3796,7 @@ var VtxoManager = class _VtxoManager {
|
|
|
3796
3796
|
* or doesn't carry the metadata.
|
|
3797
3797
|
*/
|
|
3798
3798
|
extractSpentOutpoint(error) {
|
|
3799
|
-
const ark =
|
|
3799
|
+
const ark = chunkUHOHLN3C_cjs.maybeArkError(error);
|
|
3800
3800
|
if (!ark || ark.name !== "VTXO_ALREADY_SPENT") return void 0;
|
|
3801
3801
|
const raw = ark.metadata?.vtxo_outpoint;
|
|
3802
3802
|
if (typeof raw !== "string") return void 0;
|
|
@@ -4309,6 +4309,592 @@ function wrapHandlerWithIntentPersistence(base, deps) {
|
|
|
4309
4309
|
}
|
|
4310
4310
|
};
|
|
4311
4311
|
}
|
|
4312
|
+
|
|
4313
|
+
// src/repositories/virtualTxRepository.ts
|
|
4314
|
+
var ChainedTxType = /* @__PURE__ */ ((ChainedTxType2) => {
|
|
4315
|
+
ChainedTxType2[ChainedTxType2["Unspecified"] = 0] = "Unspecified";
|
|
4316
|
+
ChainedTxType2[ChainedTxType2["Commitment"] = 1] = "Commitment";
|
|
4317
|
+
ChainedTxType2[ChainedTxType2["Ark"] = 2] = "Ark";
|
|
4318
|
+
ChainedTxType2[ChainedTxType2["Tree"] = 3] = "Tree";
|
|
4319
|
+
ChainedTxType2[ChainedTxType2["Checkpoint"] = 4] = "Checkpoint";
|
|
4320
|
+
return ChainedTxType2;
|
|
4321
|
+
})(ChainedTxType || {});
|
|
4322
|
+
function mergeChainedTxType(incoming, prev) {
|
|
4323
|
+
if (incoming !== 0 /* Unspecified */) return incoming;
|
|
4324
|
+
return prev ?? 0 /* Unspecified */;
|
|
4325
|
+
}
|
|
4326
|
+
|
|
4327
|
+
// src/wallet/exit/chain.ts
|
|
4328
|
+
var isCommitment = (t) => t === "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */ || t === "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
4329
|
+
async function buildExitDag(params) {
|
|
4330
|
+
const byTxid = /* @__PURE__ */ new Map();
|
|
4331
|
+
for (const vtxo of params.vtxos) {
|
|
4332
|
+
const outpoint = `${vtxo.txid}:${vtxo.vout}`;
|
|
4333
|
+
const chain = await params.chain.getVtxoChain({ txid: vtxo.txid, vout: vtxo.vout });
|
|
4334
|
+
for (const chainTx of chain) {
|
|
4335
|
+
const existing = byTxid.get(chainTx.txid);
|
|
4336
|
+
if (existing) {
|
|
4337
|
+
existing.forVtxos.add(outpoint);
|
|
4338
|
+
} else {
|
|
4339
|
+
byTxid.set(chainTx.txid, { ...chainTx, forVtxos: /* @__PURE__ */ new Set([outpoint]) });
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
const pending = new Map(
|
|
4344
|
+
[...byTxid.values()].filter((tx) => !isCommitment(tx.type)).map((tx) => [tx.txid, tx])
|
|
4345
|
+
);
|
|
4346
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
4347
|
+
for (const tx of pending.values()) {
|
|
4348
|
+
const parents = tx.spends.filter((p) => pending.has(p));
|
|
4349
|
+
inDegree.set(tx.txid, parents.length);
|
|
4350
|
+
}
|
|
4351
|
+
const order = [];
|
|
4352
|
+
const queue = [...pending.values()].filter((tx) => inDegree.get(tx.txid) === 0).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
4353
|
+
while (queue.length > 0) {
|
|
4354
|
+
const tx = queue.shift();
|
|
4355
|
+
order.push(tx);
|
|
4356
|
+
const children = [...pending.values()].filter((c) => c.spends.includes(tx.txid)).sort((a, b) => a.txid.localeCompare(b.txid));
|
|
4357
|
+
for (const child of children) {
|
|
4358
|
+
const deg = inDegree.get(child.txid) - 1;
|
|
4359
|
+
inDegree.set(child.txid, deg);
|
|
4360
|
+
if (deg === 0) queue.push(child);
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
if (order.length !== pending.size) {
|
|
4364
|
+
throw new Error("inconsistent vtxo chain from indexer (cycle detected)");
|
|
4365
|
+
}
|
|
4366
|
+
const nodes = [];
|
|
4367
|
+
for (const tx of order) {
|
|
4368
|
+
let confirmed = false;
|
|
4369
|
+
try {
|
|
4370
|
+
const status = await params.onchain.getTxStatus(tx.txid);
|
|
4371
|
+
confirmed = status.confirmed;
|
|
4372
|
+
} catch {
|
|
4373
|
+
confirmed = false;
|
|
4374
|
+
}
|
|
4375
|
+
const expires = Number(tx.expiresAt);
|
|
4376
|
+
nodes.push({
|
|
4377
|
+
txid: tx.txid,
|
|
4378
|
+
type: tx.type,
|
|
4379
|
+
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : void 0,
|
|
4380
|
+
forVtxos: [...tx.forVtxos].sort(),
|
|
4381
|
+
confirmed
|
|
4382
|
+
});
|
|
4383
|
+
}
|
|
4384
|
+
return nodes;
|
|
4385
|
+
}
|
|
4386
|
+
function topoSortByDeps(items, idOf, depsOf) {
|
|
4387
|
+
const produced = new Set(items.map(idOf));
|
|
4388
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4389
|
+
const ordered = [];
|
|
4390
|
+
let remaining = items;
|
|
4391
|
+
while (remaining.length > 0) {
|
|
4392
|
+
const next = [];
|
|
4393
|
+
let progress = false;
|
|
4394
|
+
for (const item of remaining) {
|
|
4395
|
+
if (depsOf(item).every((d) => !produced.has(d) || emitted.has(d))) {
|
|
4396
|
+
ordered.push(item);
|
|
4397
|
+
emitted.add(idOf(item));
|
|
4398
|
+
progress = true;
|
|
4399
|
+
} else {
|
|
4400
|
+
next.push(item);
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
if (!progress) {
|
|
4404
|
+
throw new Error("topological sort: cycle or unsatisfiable dependency");
|
|
4405
|
+
}
|
|
4406
|
+
remaining = next;
|
|
4407
|
+
}
|
|
4408
|
+
return ordered;
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4411
|
+
// src/wallet/exit/capture.ts
|
|
4412
|
+
var DEFAULT_MIN_EXIT_WORTH_SATS = 1e3;
|
|
4413
|
+
var DEFAULT_EXIT_CAPTURE_MODE = "lite";
|
|
4414
|
+
function chainTxTypeToChainedExit(t) {
|
|
4415
|
+
switch (t) {
|
|
4416
|
+
case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
|
|
4417
|
+
return 1 /* Commitment */;
|
|
4418
|
+
case "INDEXER_CHAINED_TX_TYPE_ARK" /* ARK */:
|
|
4419
|
+
return 2 /* Ark */;
|
|
4420
|
+
case "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */:
|
|
4421
|
+
return 3 /* Tree */;
|
|
4422
|
+
case "INDEXER_CHAINED_TX_TYPE_CHECKPOINT" /* CHECKPOINT */:
|
|
4423
|
+
return 4 /* Checkpoint */;
|
|
4424
|
+
default:
|
|
4425
|
+
return 0 /* Unspecified */;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
function orderAncestryFirst(chain) {
|
|
4429
|
+
const ids = new Set(chain.map((c) => c.txid));
|
|
4430
|
+
return topoSortByDeps(
|
|
4431
|
+
chain,
|
|
4432
|
+
(c) => c.txid,
|
|
4433
|
+
(c) => c.spends.filter((s) => ids.has(s))
|
|
4434
|
+
);
|
|
4435
|
+
}
|
|
4436
|
+
async function captureExitBranch(params) {
|
|
4437
|
+
const { resolver, repository, vtxo, value, mode, minExitWorthSats } = params;
|
|
4438
|
+
if (value < minExitWorthSats) return;
|
|
4439
|
+
if (await repository.hasBranch(vtxo)) return;
|
|
4440
|
+
const ordered = orderAncestryFirst(await resolver.getVtxoChain(vtxo));
|
|
4441
|
+
const psbtByTxid = /* @__PURE__ */ new Map();
|
|
4442
|
+
if (mode === "full") {
|
|
4443
|
+
const nonCommitment = ordered.filter((c) => chainTxTypeToChainedExit(c.type) !== 1 /* Commitment */).map((c) => c.txid);
|
|
4444
|
+
if (nonCommitment.length > 0) {
|
|
4445
|
+
for (const psbt of await resolver.getVirtualTxs(nonCommitment)) {
|
|
4446
|
+
psbtByTxid.set(chunkUHOHLN3C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4449
|
+
}
|
|
4450
|
+
const virtualTxs = ordered.map((c) => {
|
|
4451
|
+
const expires = Number(c.expiresAt);
|
|
4452
|
+
return {
|
|
4453
|
+
txid: c.txid,
|
|
4454
|
+
psbt: psbtByTxid.get(c.txid) ?? null,
|
|
4455
|
+
expiresAt: Number.isFinite(expires) && expires > 0 ? expires : null,
|
|
4456
|
+
type: chainTxTypeToChainedExit(c.type)
|
|
4457
|
+
};
|
|
4458
|
+
});
|
|
4459
|
+
const branch = ordered.map((c, i) => ({
|
|
4460
|
+
vtxoTxid: vtxo.txid,
|
|
4461
|
+
vtxoVout: vtxo.vout,
|
|
4462
|
+
virtualTxid: c.txid,
|
|
4463
|
+
position: i
|
|
4464
|
+
}));
|
|
4465
|
+
await repository.upsertVirtualTxs(virtualTxs);
|
|
4466
|
+
await repository.setBranch(vtxo, branch);
|
|
4467
|
+
}
|
|
4468
|
+
async function pruneExitBranches(repository, outpoints) {
|
|
4469
|
+
for (const outpoint of outpoints) {
|
|
4470
|
+
try {
|
|
4471
|
+
await repository.pruneForSpentVtxo(outpoint);
|
|
4472
|
+
} catch {
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
var IndexerExitDataSource = class {
|
|
4477
|
+
constructor(indexer) {
|
|
4478
|
+
this.indexer = indexer;
|
|
4479
|
+
}
|
|
4480
|
+
name = "indexer";
|
|
4481
|
+
async getVtxoChain(vtxo) {
|
|
4482
|
+
const chain = [];
|
|
4483
|
+
let pageIndex = 0;
|
|
4484
|
+
let hasMore = true;
|
|
4485
|
+
while (hasMore) {
|
|
4486
|
+
const { chain: page, page: meta } = await this.indexer.getVtxoChain(
|
|
4487
|
+
{ txid: vtxo.txid, vout: vtxo.vout },
|
|
4488
|
+
{ pageIndex, pageSize: chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE }
|
|
4489
|
+
);
|
|
4490
|
+
chain.push(...page);
|
|
4491
|
+
hasMore = meta ? page.length === chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE : false;
|
|
4492
|
+
pageIndex++;
|
|
4493
|
+
}
|
|
4494
|
+
return chain;
|
|
4495
|
+
}
|
|
4496
|
+
async getVirtualTxs(txids) {
|
|
4497
|
+
const out = /* @__PURE__ */ new Map();
|
|
4498
|
+
let pageIndex = 0;
|
|
4499
|
+
let hasMore = true;
|
|
4500
|
+
while (hasMore) {
|
|
4501
|
+
const { txs, page } = await this.indexer.getVirtualTxs(txids, {
|
|
4502
|
+
pageIndex,
|
|
4503
|
+
pageSize: chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE
|
|
4504
|
+
});
|
|
4505
|
+
for (const psbt of txs) {
|
|
4506
|
+
out.set(chunkUHOHLN3C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
4507
|
+
}
|
|
4508
|
+
hasMore = page ? txs.length === chunk32YKLQPS_cjs.DEFAULT_PAGE_SIZE : false;
|
|
4509
|
+
pageIndex++;
|
|
4510
|
+
}
|
|
4511
|
+
return out;
|
|
4512
|
+
}
|
|
4513
|
+
};
|
|
4514
|
+
function chainedTxTypeToChainTxType(t) {
|
|
4515
|
+
switch (t) {
|
|
4516
|
+
case 1 /* Commitment */:
|
|
4517
|
+
return "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */;
|
|
4518
|
+
case 2 /* Ark */:
|
|
4519
|
+
return "INDEXER_CHAINED_TX_TYPE_ARK" /* ARK */;
|
|
4520
|
+
case 3 /* Tree */:
|
|
4521
|
+
return "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */;
|
|
4522
|
+
case 4 /* Checkpoint */:
|
|
4523
|
+
return "INDEXER_CHAINED_TX_TYPE_CHECKPOINT" /* CHECKPOINT */;
|
|
4524
|
+
default:
|
|
4525
|
+
return "INDEXER_CHAINED_TX_TYPE_UNSPECIFIED" /* UNSPECIFIED */;
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
function psbtInputTxids(psbtBase64) {
|
|
4529
|
+
const tx = chunkUHOHLN3C_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
|
|
4530
|
+
const ids = [];
|
|
4531
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
4532
|
+
const txid = tx.getInput(i).txid;
|
|
4533
|
+
if (txid) ids.push(base.hex.encode(txid));
|
|
4534
|
+
}
|
|
4535
|
+
return ids;
|
|
4536
|
+
}
|
|
4537
|
+
var RepositoryExitDataSource = class {
|
|
4538
|
+
constructor(repo) {
|
|
4539
|
+
this.repo = repo;
|
|
4540
|
+
}
|
|
4541
|
+
name = "repository";
|
|
4542
|
+
async getVtxoChain(vtxo) {
|
|
4543
|
+
const branch = await this.repo.getBranch(vtxo);
|
|
4544
|
+
if (branch.length === 0) return null;
|
|
4545
|
+
const chain = [];
|
|
4546
|
+
for (const v of branch) {
|
|
4547
|
+
const type = chainedTxTypeToChainTxType(v.type);
|
|
4548
|
+
let spends = [];
|
|
4549
|
+
if (v.type !== 1 /* Commitment */) {
|
|
4550
|
+
if (!v.psbt) return null;
|
|
4551
|
+
spends = psbtInputTxids(v.psbt);
|
|
4552
|
+
}
|
|
4553
|
+
chain.push({
|
|
4554
|
+
txid: v.txid,
|
|
4555
|
+
type,
|
|
4556
|
+
expiresAt: v.expiresAt != null ? String(v.expiresAt) : "",
|
|
4557
|
+
spends
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4560
|
+
return chain;
|
|
4561
|
+
}
|
|
4562
|
+
async getVirtualTxs(txids) {
|
|
4563
|
+
const out = /* @__PURE__ */ new Map();
|
|
4564
|
+
for (const txid of txids) {
|
|
4565
|
+
const stored = await this.repo.getVirtualTx(txid);
|
|
4566
|
+
if (stored?.psbt) out.set(txid, stored.psbt);
|
|
4567
|
+
}
|
|
4568
|
+
return out;
|
|
4569
|
+
}
|
|
4570
|
+
};
|
|
4571
|
+
|
|
4572
|
+
// src/wallet/exit/resolver.ts
|
|
4573
|
+
var OrderedExitChainResolver = class {
|
|
4574
|
+
constructor(sources, persist) {
|
|
4575
|
+
this.sources = sources;
|
|
4576
|
+
this.persist = persist;
|
|
4577
|
+
}
|
|
4578
|
+
async getVtxoChain(vtxo) {
|
|
4579
|
+
let lastErr;
|
|
4580
|
+
for (const source of this.sources) {
|
|
4581
|
+
try {
|
|
4582
|
+
const chain = await source.getVtxoChain(vtxo);
|
|
4583
|
+
if (chain) return chain;
|
|
4584
|
+
} catch (e) {
|
|
4585
|
+
lastErr = e;
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
if (lastErr) throw lastErr;
|
|
4589
|
+
throw new Error(`no exit-data source resolved the chain for ${vtxo.txid}:${vtxo.vout}`);
|
|
4590
|
+
}
|
|
4591
|
+
async getVirtualTxs(txids) {
|
|
4592
|
+
const found = /* @__PURE__ */ new Map();
|
|
4593
|
+
let remaining = txids;
|
|
4594
|
+
for (const [i, source] of this.sources.entries()) {
|
|
4595
|
+
if (remaining.length === 0) break;
|
|
4596
|
+
let got;
|
|
4597
|
+
try {
|
|
4598
|
+
got = await source.getVirtualTxs(remaining);
|
|
4599
|
+
} catch {
|
|
4600
|
+
continue;
|
|
4601
|
+
}
|
|
4602
|
+
const fresh = [];
|
|
4603
|
+
for (const [txid, psbt] of got) {
|
|
4604
|
+
if (found.has(txid)) continue;
|
|
4605
|
+
found.set(txid, psbt);
|
|
4606
|
+
fresh.push({ txid, psbt, expiresAt: null, type: 0 /* Unspecified */ });
|
|
4607
|
+
}
|
|
4608
|
+
if (i > 0 && this.persist && fresh.length > 0) {
|
|
4609
|
+
try {
|
|
4610
|
+
await this.persist.upsertVirtualTxs(fresh);
|
|
4611
|
+
} catch {
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
remaining = txids.filter((t) => !found.has(t));
|
|
4615
|
+
}
|
|
4616
|
+
return [...found.values()];
|
|
4617
|
+
}
|
|
4618
|
+
};
|
|
4619
|
+
function createExitChainResolver(params) {
|
|
4620
|
+
const sources = [];
|
|
4621
|
+
if (params.repository) sources.push(new RepositoryExitDataSource(params.repository));
|
|
4622
|
+
if (params.extraSources) sources.push(...params.extraSources);
|
|
4623
|
+
sources.push(new IndexerExitDataSource(params.indexer));
|
|
4624
|
+
return new OrderedExitChainResolver(sources, params.repository);
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
// src/providers/availability.ts
|
|
4628
|
+
function isRetryableProviderError(error) {
|
|
4629
|
+
return error instanceof chunkUHOHLN3C_cjs.ProviderUnavailableError || error instanceof chunkUHOHLN3C_cjs.FetchError || chunkUHOHLN3C_cjs.isFetchTimeoutError(error);
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4632
|
+
// src/utils/syncCursors.ts
|
|
4633
|
+
var SAFETY_LAG_MS = 3e4;
|
|
4634
|
+
var OVERLAP_MS = 24 * 60 * 60 * 1e3;
|
|
4635
|
+
var walletStateLocks = /* @__PURE__ */ new WeakMap();
|
|
4636
|
+
async function updateWalletState(repo, updater) {
|
|
4637
|
+
const prev = walletStateLocks.get(repo) ?? Promise.resolve();
|
|
4638
|
+
const op = prev.then(async () => {
|
|
4639
|
+
const state = await repo.getWalletState() ?? {};
|
|
4640
|
+
await repo.saveWalletState(updater(state));
|
|
4641
|
+
});
|
|
4642
|
+
walletStateLocks.set(
|
|
4643
|
+
repo,
|
|
4644
|
+
op.catch(() => {
|
|
4645
|
+
})
|
|
4646
|
+
);
|
|
4647
|
+
return op;
|
|
4648
|
+
}
|
|
4649
|
+
var CURSOR_MIGRATED_KEY = "vtxoCursorMigrated";
|
|
4650
|
+
function hasMigrationMarker(state) {
|
|
4651
|
+
return state?.settings?.[CURSOR_MIGRATED_KEY] === true;
|
|
4652
|
+
}
|
|
4653
|
+
async function getSyncCursor(repo) {
|
|
4654
|
+
const state = await repo.getWalletState();
|
|
4655
|
+
if (!hasMigrationMarker(state)) return 0;
|
|
4656
|
+
return state?.lastSyncTime ?? 0;
|
|
4657
|
+
}
|
|
4658
|
+
async function advanceSyncCursor(repo, lastUpdatedAt) {
|
|
4659
|
+
await updateWalletState(repo, (state) => {
|
|
4660
|
+
const current = hasMigrationMarker(state) ? state.lastSyncTime ?? 0 : 0;
|
|
4661
|
+
return {
|
|
4662
|
+
...state,
|
|
4663
|
+
lastSyncTime: Math.max(current, lastUpdatedAt),
|
|
4664
|
+
settings: {
|
|
4665
|
+
...state.settings ?? {},
|
|
4666
|
+
[CURSOR_MIGRATED_KEY]: true
|
|
4667
|
+
}
|
|
4668
|
+
};
|
|
4669
|
+
});
|
|
4670
|
+
}
|
|
4671
|
+
async function clearSyncCursor(repo) {
|
|
4672
|
+
await updateWalletState(repo, (state) => {
|
|
4673
|
+
const { [CURSOR_MIGRATED_KEY]: _, ...restSettings } = state.settings ?? {};
|
|
4674
|
+
return {
|
|
4675
|
+
...state,
|
|
4676
|
+
lastSyncTime: void 0,
|
|
4677
|
+
settings: restSettings
|
|
4678
|
+
};
|
|
4679
|
+
});
|
|
4680
|
+
}
|
|
4681
|
+
function computeSyncWindow(cursor) {
|
|
4682
|
+
const after = Math.max(0, cursor - OVERLAP_MS);
|
|
4683
|
+
return { after };
|
|
4684
|
+
}
|
|
4685
|
+
function cursorCutoff(requestStartedAt) {
|
|
4686
|
+
return (requestStartedAt ?? Date.now()) - SAFETY_LAG_MS;
|
|
4687
|
+
}
|
|
4688
|
+
|
|
4689
|
+
// src/wallet/arkInfoSnapshot.ts
|
|
4690
|
+
var ARK_INFO_SNAPSHOT_KEY = "arkInfoSnapshot";
|
|
4691
|
+
var MalformedArkInfoSnapshotError = class extends Error {
|
|
4692
|
+
constructor(message, options) {
|
|
4693
|
+
super(message, { cause: options?.cause });
|
|
4694
|
+
this.name = "MalformedArkInfoSnapshotError";
|
|
4695
|
+
}
|
|
4696
|
+
};
|
|
4697
|
+
var CURRENT_VERSION = 1;
|
|
4698
|
+
function serializeArkInfoSnapshot(info, savedAt) {
|
|
4699
|
+
return {
|
|
4700
|
+
version: CURRENT_VERSION,
|
|
4701
|
+
savedAt,
|
|
4702
|
+
source: "arkade.getInfo",
|
|
4703
|
+
arkInfo: {
|
|
4704
|
+
network: info.network,
|
|
4705
|
+
signerPubkey: info.signerPubkey,
|
|
4706
|
+
checkpointTapscript: info.checkpointTapscript,
|
|
4707
|
+
forfeitAddress: info.forfeitAddress,
|
|
4708
|
+
forfeitPubkey: info.forfeitPubkey,
|
|
4709
|
+
unilateralExitDelay: info.unilateralExitDelay.toString(),
|
|
4710
|
+
boardingExitDelay: info.boardingExitDelay.toString(),
|
|
4711
|
+
sessionDuration: info.sessionDuration.toString(),
|
|
4712
|
+
dust: info.dust.toString(),
|
|
4713
|
+
fees: info.fees,
|
|
4714
|
+
digest: info.digest,
|
|
4715
|
+
version: info.version,
|
|
4716
|
+
vtxoMinAmount: info.vtxoMinAmount.toString(),
|
|
4717
|
+
vtxoMaxAmount: info.vtxoMaxAmount.toString(),
|
|
4718
|
+
utxoMinAmount: info.utxoMinAmount.toString(),
|
|
4719
|
+
utxoMaxAmount: info.utxoMaxAmount.toString(),
|
|
4720
|
+
deprecatedSigners: info.deprecatedSigners.map((s) => ({
|
|
4721
|
+
pubkey: s.pubkey,
|
|
4722
|
+
cutoffDate: s.cutoffDate.toString()
|
|
4723
|
+
})),
|
|
4724
|
+
scheduledSession: info.scheduledSession ? {
|
|
4725
|
+
duration: info.scheduledSession.duration.toString(),
|
|
4726
|
+
fees: info.scheduledSession.fees,
|
|
4727
|
+
nextEndTime: info.scheduledSession.nextEndTime.toString(),
|
|
4728
|
+
nextStartTime: info.scheduledSession.nextStartTime.toString(),
|
|
4729
|
+
period: info.scheduledSession.period.toString()
|
|
4730
|
+
} : void 0
|
|
4731
|
+
}
|
|
4732
|
+
};
|
|
4733
|
+
}
|
|
4734
|
+
function hydrateArkInfo(snapshot) {
|
|
4735
|
+
const a = snapshot.arkInfo;
|
|
4736
|
+
return {
|
|
4737
|
+
boardingExitDelay: BigInt(a.boardingExitDelay),
|
|
4738
|
+
checkpointTapscript: a.checkpointTapscript,
|
|
4739
|
+
deprecatedSigners: a.deprecatedSigners.map((s) => ({
|
|
4740
|
+
cutoffDate: BigInt(s.cutoffDate),
|
|
4741
|
+
pubkey: s.pubkey
|
|
4742
|
+
})),
|
|
4743
|
+
digest: a.digest,
|
|
4744
|
+
dust: BigInt(a.dust),
|
|
4745
|
+
fees: a.fees,
|
|
4746
|
+
forfeitAddress: a.forfeitAddress,
|
|
4747
|
+
forfeitPubkey: a.forfeitPubkey,
|
|
4748
|
+
network: a.network,
|
|
4749
|
+
scheduledSession: a.scheduledSession ? {
|
|
4750
|
+
duration: BigInt(a.scheduledSession.duration),
|
|
4751
|
+
fees: a.scheduledSession.fees,
|
|
4752
|
+
nextEndTime: BigInt(a.scheduledSession.nextEndTime),
|
|
4753
|
+
nextStartTime: BigInt(a.scheduledSession.nextStartTime),
|
|
4754
|
+
period: BigInt(a.scheduledSession.period)
|
|
4755
|
+
} : void 0,
|
|
4756
|
+
serviceStatus: {},
|
|
4757
|
+
sessionDuration: BigInt(a.sessionDuration),
|
|
4758
|
+
signerPubkey: a.signerPubkey,
|
|
4759
|
+
unilateralExitDelay: BigInt(a.unilateralExitDelay),
|
|
4760
|
+
utxoMaxAmount: BigInt(a.utxoMaxAmount),
|
|
4761
|
+
utxoMinAmount: BigInt(a.utxoMinAmount),
|
|
4762
|
+
version: a.version,
|
|
4763
|
+
vtxoMaxAmount: BigInt(a.vtxoMaxAmount),
|
|
4764
|
+
vtxoMinAmount: BigInt(a.vtxoMinAmount)
|
|
4765
|
+
};
|
|
4766
|
+
}
|
|
4767
|
+
var DECIMAL_STRING = /^-?\d+$/;
|
|
4768
|
+
function assertString(value, path) {
|
|
4769
|
+
if (typeof value !== "string") {
|
|
4770
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be a string`);
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
function assertDecimalString(value, path) {
|
|
4774
|
+
assertString(value, path);
|
|
4775
|
+
if (!DECIMAL_STRING.test(value)) {
|
|
4776
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be a decimal integer string`);
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
function assertFeeInfo(value, path) {
|
|
4780
|
+
if (typeof value !== "object" || value === null) {
|
|
4781
|
+
throw new MalformedArkInfoSnapshotError(`${path} must be an object`);
|
|
4782
|
+
}
|
|
4783
|
+
const fees = value;
|
|
4784
|
+
assertString(fees.txFeeRate, `${path}.txFeeRate`);
|
|
4785
|
+
if (typeof fees.intentFee !== "object" || fees.intentFee === null) {
|
|
4786
|
+
throw new MalformedArkInfoSnapshotError(`${path}.intentFee must be an object`);
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
function parseStoredArkInfoSnapshot(raw) {
|
|
4790
|
+
if (typeof raw !== "object" || raw === null) {
|
|
4791
|
+
throw new MalformedArkInfoSnapshotError("snapshot must be an object");
|
|
4792
|
+
}
|
|
4793
|
+
const snap = raw;
|
|
4794
|
+
if (snap.version !== CURRENT_VERSION) {
|
|
4795
|
+
throw new MalformedArkInfoSnapshotError(
|
|
4796
|
+
`unsupported snapshot version: ${String(snap.version)}`
|
|
4797
|
+
);
|
|
4798
|
+
}
|
|
4799
|
+
if (typeof snap.savedAt !== "number") {
|
|
4800
|
+
throw new MalformedArkInfoSnapshotError("savedAt must be a number");
|
|
4801
|
+
}
|
|
4802
|
+
if (snap.source !== "arkade.getInfo") {
|
|
4803
|
+
throw new MalformedArkInfoSnapshotError(`unexpected source: ${String(snap.source)}`);
|
|
4804
|
+
}
|
|
4805
|
+
if (typeof snap.arkInfo !== "object" || snap.arkInfo === null) {
|
|
4806
|
+
throw new MalformedArkInfoSnapshotError("arkInfo must be an object");
|
|
4807
|
+
}
|
|
4808
|
+
const a = snap.arkInfo;
|
|
4809
|
+
for (const field of [
|
|
4810
|
+
"network",
|
|
4811
|
+
"signerPubkey",
|
|
4812
|
+
"checkpointTapscript",
|
|
4813
|
+
"forfeitAddress",
|
|
4814
|
+
"forfeitPubkey",
|
|
4815
|
+
"digest",
|
|
4816
|
+
"version"
|
|
4817
|
+
]) {
|
|
4818
|
+
assertString(a[field], `arkInfo.${field}`);
|
|
4819
|
+
}
|
|
4820
|
+
for (const field of [
|
|
4821
|
+
"unilateralExitDelay",
|
|
4822
|
+
"boardingExitDelay",
|
|
4823
|
+
"sessionDuration",
|
|
4824
|
+
"dust",
|
|
4825
|
+
"vtxoMinAmount",
|
|
4826
|
+
"vtxoMaxAmount",
|
|
4827
|
+
"utxoMinAmount",
|
|
4828
|
+
"utxoMaxAmount"
|
|
4829
|
+
]) {
|
|
4830
|
+
assertDecimalString(a[field], `arkInfo.${field}`);
|
|
4831
|
+
}
|
|
4832
|
+
assertFeeInfo(a.fees, "arkInfo.fees");
|
|
4833
|
+
if (!Array.isArray(a.deprecatedSigners)) {
|
|
4834
|
+
throw new MalformedArkInfoSnapshotError("arkInfo.deprecatedSigners must be an array");
|
|
4835
|
+
}
|
|
4836
|
+
a.deprecatedSigners.forEach((s, i) => {
|
|
4837
|
+
if (typeof s !== "object" || s === null) {
|
|
4838
|
+
throw new MalformedArkInfoSnapshotError(
|
|
4839
|
+
`arkInfo.deprecatedSigners[${i}] must be an object`
|
|
4840
|
+
);
|
|
4841
|
+
}
|
|
4842
|
+
const signer = s;
|
|
4843
|
+
assertString(signer.pubkey, `arkInfo.deprecatedSigners[${i}].pubkey`);
|
|
4844
|
+
assertDecimalString(signer.cutoffDate, `arkInfo.deprecatedSigners[${i}].cutoffDate`);
|
|
4845
|
+
});
|
|
4846
|
+
if (a.scheduledSession !== void 0) {
|
|
4847
|
+
if (typeof a.scheduledSession !== "object" || a.scheduledSession === null) {
|
|
4848
|
+
throw new MalformedArkInfoSnapshotError("arkInfo.scheduledSession must be an object");
|
|
4849
|
+
}
|
|
4850
|
+
const s = a.scheduledSession;
|
|
4851
|
+
for (const field of ["duration", "nextEndTime", "nextStartTime", "period"]) {
|
|
4852
|
+
assertDecimalString(s[field], `arkInfo.scheduledSession.${field}`);
|
|
4853
|
+
}
|
|
4854
|
+
assertFeeInfo(s.fees, "arkInfo.scheduledSession.fees");
|
|
4855
|
+
}
|
|
4856
|
+
return raw;
|
|
4857
|
+
}
|
|
4858
|
+
async function loadArkInfoSnapshot(repo) {
|
|
4859
|
+
const state = await repo.getWalletState();
|
|
4860
|
+
const raw = state?.settings?.[ARK_INFO_SNAPSHOT_KEY];
|
|
4861
|
+
if (raw === void 0 || raw === null) return null;
|
|
4862
|
+
return parseStoredArkInfoSnapshot(raw);
|
|
4863
|
+
}
|
|
4864
|
+
async function saveArkInfoSnapshot(repo, info, savedAt) {
|
|
4865
|
+
const snapshot = serializeArkInfoSnapshot(info, savedAt);
|
|
4866
|
+
await updateWalletState(repo, (state) => ({
|
|
4867
|
+
...state,
|
|
4868
|
+
settings: {
|
|
4869
|
+
...state.settings ?? {},
|
|
4870
|
+
[ARK_INFO_SNAPSHOT_KEY]: snapshot
|
|
4871
|
+
}
|
|
4872
|
+
}));
|
|
4873
|
+
}
|
|
4874
|
+
async function resolveArkInfo(arkProvider, walletRepository) {
|
|
4875
|
+
let info;
|
|
4876
|
+
try {
|
|
4877
|
+
info = await arkProvider.getInfo();
|
|
4878
|
+
} catch (err) {
|
|
4879
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
4880
|
+
const snapshot = await loadArkInfoSnapshot(walletRepository);
|
|
4881
|
+
if (!snapshot) {
|
|
4882
|
+
throw new chunkUHOHLN3C_cjs.ProviderUnavailableError(
|
|
4883
|
+
"Arkade server info is unavailable and no cached snapshot exists",
|
|
4884
|
+
{ cause: err }
|
|
4885
|
+
);
|
|
4886
|
+
}
|
|
4887
|
+
return { info: hydrateArkInfo(snapshot), source: "cache", lastOnlineAt: snapshot.savedAt };
|
|
4888
|
+
}
|
|
4889
|
+
return { info, source: "live" };
|
|
4890
|
+
}
|
|
4891
|
+
async function saveValidatedArkInfoSnapshot(repo, info, savedAt) {
|
|
4892
|
+
try {
|
|
4893
|
+
await saveArkInfoSnapshot(repo, info, savedAt);
|
|
4894
|
+
} catch (err) {
|
|
4895
|
+
console.warn("Failed to persist Ark info snapshot", err);
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4312
4898
|
var TxTree = class {
|
|
4313
4899
|
constructor(root, children = /* @__PURE__ */ new Map()) {
|
|
4314
4900
|
this.root = root;
|
|
@@ -4824,7 +5410,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4824
5410
|
const virtualCoins = await this.wallet.getVtxos({
|
|
4825
5411
|
withRecoverable: false
|
|
4826
5412
|
});
|
|
4827
|
-
const controlAssetRef = params.controlAssetId ?
|
|
5413
|
+
const controlAssetRef = params.controlAssetId ? chunkUHOHLN3C_cjs.AssetRef.fromId(chunkUHOHLN3C_cjs.AssetId.fromString(params.controlAssetId)) : null;
|
|
4828
5414
|
const coinSelection = selectVirtualCoins(virtualCoins, Number(this.wallet.dustAmount));
|
|
4829
5415
|
let totalBtcSelected = 0n;
|
|
4830
5416
|
const assetChanges = /* @__PURE__ */ new Map();
|
|
@@ -4837,8 +5423,8 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4837
5423
|
}
|
|
4838
5424
|
}
|
|
4839
5425
|
const groups = [];
|
|
4840
|
-
const issuedAssetOutput =
|
|
4841
|
-
const issuedAssetGroup =
|
|
5426
|
+
const issuedAssetOutput = chunkUHOHLN3C_cjs.AssetOutput.create(0, params.amount);
|
|
5427
|
+
const issuedAssetGroup = chunkUHOHLN3C_cjs.AssetGroup.create(
|
|
4842
5428
|
null,
|
|
4843
5429
|
controlAssetRef,
|
|
4844
5430
|
[],
|
|
@@ -4853,15 +5439,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4853
5439
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4854
5440
|
for (const asset of assets) {
|
|
4855
5441
|
if (asset.assetId !== assetId) continue;
|
|
4856
|
-
changeInputs.push(
|
|
5442
|
+
changeInputs.push(chunkUHOHLN3C_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4857
5443
|
}
|
|
4858
5444
|
}
|
|
4859
5445
|
groups.push(
|
|
4860
|
-
|
|
4861
|
-
|
|
5446
|
+
chunkUHOHLN3C_cjs.AssetGroup.create(
|
|
5447
|
+
chunkUHOHLN3C_cjs.AssetId.fromString(assetId),
|
|
4862
5448
|
null,
|
|
4863
5449
|
changeInputs,
|
|
4864
|
-
[
|
|
5450
|
+
[chunkUHOHLN3C_cjs.AssetOutput.create(0, amount)],
|
|
4865
5451
|
[]
|
|
4866
5452
|
)
|
|
4867
5453
|
);
|
|
@@ -4874,7 +5460,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4874
5460
|
script: outputAddress.pkScript,
|
|
4875
5461
|
amount: BigInt(totalBtcSelected)
|
|
4876
5462
|
},
|
|
4877
|
-
Extension.create([
|
|
5463
|
+
Extension.create([chunkUHOHLN3C_cjs.Packet.create(groups)]).txOut()
|
|
4878
5464
|
];
|
|
4879
5465
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(
|
|
4880
5466
|
coinSelection.inputs,
|
|
@@ -4882,7 +5468,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4882
5468
|
);
|
|
4883
5469
|
return {
|
|
4884
5470
|
arkTxId: arkTxid,
|
|
4885
|
-
assetId:
|
|
5471
|
+
assetId: chunkUHOHLN3C_cjs.AssetId.create(arkTxid, 0).toString()
|
|
4886
5472
|
};
|
|
4887
5473
|
}
|
|
4888
5474
|
/**
|
|
@@ -4954,16 +5540,16 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4954
5540
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4955
5541
|
for (const asset of assets) {
|
|
4956
5542
|
if (asset.assetId !== params.assetId) continue;
|
|
4957
|
-
reissueInputs.push(
|
|
5543
|
+
reissueInputs.push(chunkUHOHLN3C_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4958
5544
|
}
|
|
4959
5545
|
}
|
|
4960
5546
|
const totalAssetAmount = assetToReissueAmount + params.amount;
|
|
4961
|
-
const reissueAssetIdObj =
|
|
4962
|
-
const reissueAssetGroup =
|
|
5547
|
+
const reissueAssetIdObj = chunkUHOHLN3C_cjs.AssetId.fromString(params.assetId);
|
|
5548
|
+
const reissueAssetGroup = chunkUHOHLN3C_cjs.AssetGroup.create(
|
|
4963
5549
|
reissueAssetIdObj,
|
|
4964
5550
|
null,
|
|
4965
5551
|
reissueInputs,
|
|
4966
|
-
[
|
|
5552
|
+
[chunkUHOHLN3C_cjs.AssetOutput.create(0, totalAssetAmount)],
|
|
4967
5553
|
[]
|
|
4968
5554
|
);
|
|
4969
5555
|
const groups = [reissueAssetGroup];
|
|
@@ -4972,15 +5558,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4972
5558
|
for (const [inputIndex, assets] of assetInputs) {
|
|
4973
5559
|
for (const asset of assets) {
|
|
4974
5560
|
if (asset.assetId !== assetId) continue;
|
|
4975
|
-
changeInputs.push(
|
|
5561
|
+
changeInputs.push(chunkUHOHLN3C_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
4976
5562
|
}
|
|
4977
5563
|
}
|
|
4978
5564
|
groups.push(
|
|
4979
|
-
|
|
4980
|
-
|
|
5565
|
+
chunkUHOHLN3C_cjs.AssetGroup.create(
|
|
5566
|
+
chunkUHOHLN3C_cjs.AssetId.fromString(assetId),
|
|
4981
5567
|
null,
|
|
4982
5568
|
changeInputs,
|
|
4983
|
-
[
|
|
5569
|
+
[chunkUHOHLN3C_cjs.AssetOutput.create(0, amount)],
|
|
4984
5570
|
[]
|
|
4985
5571
|
)
|
|
4986
5572
|
);
|
|
@@ -4992,7 +5578,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
4992
5578
|
script: outputAddress.pkScript,
|
|
4993
5579
|
amount: BigInt(totalBtcSelected)
|
|
4994
5580
|
},
|
|
4995
|
-
Extension.create([
|
|
5581
|
+
Extension.create([chunkUHOHLN3C_cjs.Packet.create(groups)]).txOut()
|
|
4996
5582
|
];
|
|
4997
5583
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
4998
5584
|
return arkTxid;
|
|
@@ -5059,15 +5645,15 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
5059
5645
|
for (const [inputIndex, assets] of assetInputs) {
|
|
5060
5646
|
for (const asset of assets) {
|
|
5061
5647
|
if (asset.assetId !== assetId) continue;
|
|
5062
|
-
changeInputs.push(
|
|
5648
|
+
changeInputs.push(chunkUHOHLN3C_cjs.AssetInput.create(inputIndex, asset.amount));
|
|
5063
5649
|
}
|
|
5064
5650
|
}
|
|
5065
5651
|
groups.push(
|
|
5066
|
-
|
|
5067
|
-
|
|
5652
|
+
chunkUHOHLN3C_cjs.AssetGroup.create(
|
|
5653
|
+
chunkUHOHLN3C_cjs.AssetId.fromString(assetId),
|
|
5068
5654
|
null,
|
|
5069
5655
|
changeInputs,
|
|
5070
|
-
amount > 0n ? [
|
|
5656
|
+
amount > 0n ? [chunkUHOHLN3C_cjs.AssetOutput.create(0, amount)] : [],
|
|
5071
5657
|
[]
|
|
5072
5658
|
)
|
|
5073
5659
|
);
|
|
@@ -5079,7 +5665,7 @@ var AssetManager = class extends ReadonlyAssetManager {
|
|
|
5079
5665
|
script: outputAddress.pkScript,
|
|
5080
5666
|
amount: BigInt(totalBtcSelected)
|
|
5081
5667
|
},
|
|
5082
|
-
Extension.create([
|
|
5668
|
+
Extension.create([chunkUHOHLN3C_cjs.Packet.create(groups)]).txOut()
|
|
5083
5669
|
];
|
|
5084
5670
|
const { arkTxid } = await this.wallet.buildAndSubmitOffchainTx(selectedCoins, outputs);
|
|
5085
5671
|
return arkTxid;
|
|
@@ -5104,7 +5690,7 @@ function castMetadata(metadata) {
|
|
|
5104
5690
|
} else {
|
|
5105
5691
|
throw new Error("Invalid metadata value type");
|
|
5106
5692
|
}
|
|
5107
|
-
md.push(
|
|
5693
|
+
md.push(chunkUHOHLN3C_cjs.Metadata.create(textEncoder.encode(key), valueBytes));
|
|
5108
5694
|
}
|
|
5109
5695
|
return md;
|
|
5110
5696
|
}
|
|
@@ -5389,7 +5975,7 @@ async function makeSignedDelegateIntent(identity, coins, outputs, onchainOutputs
|
|
|
5389
5975
|
expire_at: 0,
|
|
5390
5976
|
cosigners_public_keys: cosignerPubKeys
|
|
5391
5977
|
};
|
|
5392
|
-
const proof =
|
|
5978
|
+
const proof = chunkUHOHLN3C_cjs.Intent.create(message, coins, outputs);
|
|
5393
5979
|
const signedProof = await identity.sign(proof);
|
|
5394
5980
|
return {
|
|
5395
5981
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -5418,20 +6004,6 @@ function isAnnotated(v) {
|
|
|
5418
6004
|
return v.tapTree !== void 0 && v.forfeitTapLeafScript !== void 0 && v.intentTapLeafScript !== void 0;
|
|
5419
6005
|
}
|
|
5420
6006
|
|
|
5421
|
-
// src/repositories/virtualTxRepository.ts
|
|
5422
|
-
var ChainedTxType = /* @__PURE__ */ ((ChainedTxType2) => {
|
|
5423
|
-
ChainedTxType2[ChainedTxType2["Unspecified"] = 0] = "Unspecified";
|
|
5424
|
-
ChainedTxType2[ChainedTxType2["Commitment"] = 1] = "Commitment";
|
|
5425
|
-
ChainedTxType2[ChainedTxType2["Ark"] = 2] = "Ark";
|
|
5426
|
-
ChainedTxType2[ChainedTxType2["Tree"] = 3] = "Tree";
|
|
5427
|
-
ChainedTxType2[ChainedTxType2["Checkpoint"] = 4] = "Checkpoint";
|
|
5428
|
-
return ChainedTxType2;
|
|
5429
|
-
})(ChainedTxType || {});
|
|
5430
|
-
function mergeChainedTxType(incoming, prev) {
|
|
5431
|
-
if (incoming !== 0 /* Unspecified */) return incoming;
|
|
5432
|
-
return prev ?? 0 /* Unspecified */;
|
|
5433
|
-
}
|
|
5434
|
-
|
|
5435
6007
|
// src/repositories/inMemory/intentRepository.ts
|
|
5436
6008
|
var InMemoryIntentRepository = class {
|
|
5437
6009
|
version = 1;
|
|
@@ -7487,7 +8059,7 @@ var ContractWatcher = class {
|
|
|
7487
8059
|
this.connectionState = "connected";
|
|
7488
8060
|
this.reconnectAttempts = 0;
|
|
7489
8061
|
this.listenLoop().catch((e) => {
|
|
7490
|
-
if (
|
|
8062
|
+
if (chunkUHOHLN3C_cjs.isEventSourceError(e)) {
|
|
7491
8063
|
console.debug("ContractWatcher subscription disconnected; reconnecting");
|
|
7492
8064
|
} else {
|
|
7493
8065
|
console.error(e);
|
|
@@ -7806,106 +8378,49 @@ async function reconcileIntents(deps) {
|
|
|
7806
8378
|
console.error("reconcileIntents: failed to read non-terminal intents", e);
|
|
7807
8379
|
return;
|
|
7808
8380
|
}
|
|
7809
|
-
if (intents.length === 0) return;
|
|
7810
|
-
const outpoints = dedupeOutpoints(intents.flatMap((i) => i.intentVtxos));
|
|
7811
|
-
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
7812
|
-
if (outpoints.length > 0) {
|
|
7813
|
-
try {
|
|
7814
|
-
const { vtxos } = await deps.indexerProvider.getVtxos({ outpoints });
|
|
7815
|
-
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
7816
|
-
} catch (e) {
|
|
7817
|
-
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
7818
|
-
return;
|
|
7819
|
-
}
|
|
7820
|
-
}
|
|
7821
|
-
const nowMs = now();
|
|
7822
|
-
for (const intent of intents) {
|
|
7823
|
-
try {
|
|
7824
|
-
const next = await classifyIntent(intent, vtxosByOutpoint, nowMs);
|
|
7825
|
-
if (!next) continue;
|
|
7826
|
-
const [fresh] = await deps.intentRepository.getIntents({
|
|
7827
|
-
intentTxIds: [intent.intentTxId]
|
|
7828
|
-
});
|
|
7829
|
-
if (!fresh || fresh.state !== intent.state) continue;
|
|
7830
|
-
await deps.intentRepository.saveIntent(next);
|
|
7831
|
-
} catch (e) {
|
|
7832
|
-
console.error(`reconcileIntents: failed to reconcile intent ${intent.intentTxId}`, e);
|
|
7833
|
-
}
|
|
7834
|
-
}
|
|
7835
|
-
}
|
|
7836
|
-
function terminal(intent, state, now, patch) {
|
|
7837
|
-
return { ...intent, ...patch, state, updatedAt: now };
|
|
7838
|
-
}
|
|
7839
|
-
function outpointKey(o) {
|
|
7840
|
-
return `${o.txid}:${o.vout}`;
|
|
7841
|
-
}
|
|
7842
|
-
function dedupeOutpoints(outpoints) {
|
|
7843
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7844
|
-
const out = [];
|
|
7845
|
-
for (const o of outpoints) {
|
|
7846
|
-
const k = outpointKey(o);
|
|
7847
|
-
if (seen.has(k)) continue;
|
|
7848
|
-
seen.add(k);
|
|
7849
|
-
out.push(o);
|
|
7850
|
-
}
|
|
7851
|
-
return out;
|
|
7852
|
-
}
|
|
7853
|
-
|
|
7854
|
-
// src/utils/syncCursors.ts
|
|
7855
|
-
var SAFETY_LAG_MS = 3e4;
|
|
7856
|
-
var OVERLAP_MS = 24 * 60 * 60 * 1e3;
|
|
7857
|
-
var walletStateLocks = /* @__PURE__ */ new WeakMap();
|
|
7858
|
-
async function updateWalletState(repo, updater) {
|
|
7859
|
-
const prev = walletStateLocks.get(repo) ?? Promise.resolve();
|
|
7860
|
-
const op = prev.then(async () => {
|
|
7861
|
-
const state = await repo.getWalletState() ?? {};
|
|
7862
|
-
await repo.saveWalletState(updater(state));
|
|
7863
|
-
});
|
|
7864
|
-
walletStateLocks.set(
|
|
7865
|
-
repo,
|
|
7866
|
-
op.catch(() => {
|
|
7867
|
-
})
|
|
7868
|
-
);
|
|
7869
|
-
return op;
|
|
7870
|
-
}
|
|
7871
|
-
var CURSOR_MIGRATED_KEY = "vtxoCursorMigrated";
|
|
7872
|
-
function hasMigrationMarker(state) {
|
|
7873
|
-
return state?.settings?.[CURSOR_MIGRATED_KEY] === true;
|
|
7874
|
-
}
|
|
7875
|
-
async function getSyncCursor(repo) {
|
|
7876
|
-
const state = await repo.getWalletState();
|
|
7877
|
-
if (!hasMigrationMarker(state)) return 0;
|
|
7878
|
-
return state?.lastSyncTime ?? 0;
|
|
7879
|
-
}
|
|
7880
|
-
async function advanceSyncCursor(repo, lastUpdatedAt) {
|
|
7881
|
-
await updateWalletState(repo, (state) => {
|
|
7882
|
-
const current = hasMigrationMarker(state) ? state.lastSyncTime ?? 0 : 0;
|
|
7883
|
-
return {
|
|
7884
|
-
...state,
|
|
7885
|
-
lastSyncTime: Math.max(current, lastUpdatedAt),
|
|
7886
|
-
settings: {
|
|
7887
|
-
...state.settings ?? {},
|
|
7888
|
-
[CURSOR_MIGRATED_KEY]: true
|
|
7889
|
-
}
|
|
7890
|
-
};
|
|
7891
|
-
});
|
|
8381
|
+
if (intents.length === 0) return;
|
|
8382
|
+
const outpoints = dedupeOutpoints(intents.flatMap((i) => i.intentVtxos));
|
|
8383
|
+
let vtxosByOutpoint = /* @__PURE__ */ new Map();
|
|
8384
|
+
if (outpoints.length > 0) {
|
|
8385
|
+
try {
|
|
8386
|
+
const { vtxos } = await deps.indexerProvider.getVtxos({ outpoints });
|
|
8387
|
+
vtxosByOutpoint = new Map(vtxos.map((v) => [outpointKey(v), v]));
|
|
8388
|
+
} catch (e) {
|
|
8389
|
+
console.error("reconcileIntents: failed to fetch input VTXO state", e);
|
|
8390
|
+
return;
|
|
8391
|
+
}
|
|
8392
|
+
}
|
|
8393
|
+
const nowMs = now();
|
|
8394
|
+
for (const intent of intents) {
|
|
8395
|
+
try {
|
|
8396
|
+
const next = await classifyIntent(intent, vtxosByOutpoint, nowMs);
|
|
8397
|
+
if (!next) continue;
|
|
8398
|
+
const [fresh] = await deps.intentRepository.getIntents({
|
|
8399
|
+
intentTxIds: [intent.intentTxId]
|
|
8400
|
+
});
|
|
8401
|
+
if (!fresh || fresh.state !== intent.state) continue;
|
|
8402
|
+
await deps.intentRepository.saveIntent(next);
|
|
8403
|
+
} catch (e) {
|
|
8404
|
+
console.error(`reconcileIntents: failed to reconcile intent ${intent.intentTxId}`, e);
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
7892
8407
|
}
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
const { [CURSOR_MIGRATED_KEY]: _, ...restSettings } = state.settings ?? {};
|
|
7896
|
-
return {
|
|
7897
|
-
...state,
|
|
7898
|
-
lastSyncTime: void 0,
|
|
7899
|
-
settings: restSettings
|
|
7900
|
-
};
|
|
7901
|
-
});
|
|
8408
|
+
function terminal(intent, state, now, patch) {
|
|
8409
|
+
return { ...intent, ...patch, state, updatedAt: now };
|
|
7902
8410
|
}
|
|
7903
|
-
function
|
|
7904
|
-
|
|
7905
|
-
return { after };
|
|
8411
|
+
function outpointKey(o) {
|
|
8412
|
+
return `${o.txid}:${o.vout}`;
|
|
7906
8413
|
}
|
|
7907
|
-
function
|
|
7908
|
-
|
|
8414
|
+
function dedupeOutpoints(outpoints) {
|
|
8415
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8416
|
+
const out = [];
|
|
8417
|
+
for (const o of outpoints) {
|
|
8418
|
+
const k = outpointKey(o);
|
|
8419
|
+
if (seen.has(k)) continue;
|
|
8420
|
+
seen.add(k);
|
|
8421
|
+
out.push(o);
|
|
8422
|
+
}
|
|
8423
|
+
return out;
|
|
7909
8424
|
}
|
|
7910
8425
|
|
|
7911
8426
|
// src/contracts/contractManager.ts
|
|
@@ -7920,6 +8435,10 @@ var ContractManager = class _ContractManager {
|
|
|
7920
8435
|
initialized = false;
|
|
7921
8436
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
7922
8437
|
stopWatcherFn;
|
|
8438
|
+
/** `undefined` while online; the failure reason once a sync degrades. */
|
|
8439
|
+
syncDegradedReason;
|
|
8440
|
+
/** Epoch-ms of the last successful provider sync, if any. */
|
|
8441
|
+
lastSyncedAt;
|
|
7923
8442
|
constructor(config) {
|
|
7924
8443
|
this.config = config;
|
|
7925
8444
|
this.watcher = new ContractWatcher({
|
|
@@ -7942,6 +8461,26 @@ var ContractManager = class _ContractManager {
|
|
|
7942
8461
|
await cm.initialize();
|
|
7943
8462
|
return cm;
|
|
7944
8463
|
}
|
|
8464
|
+
/**
|
|
8465
|
+
* Latest provider-sync health. See {@link ContractSyncState}. Degradation is
|
|
8466
|
+
* recorded by {@link initialize}, {@link getContractsWithVtxos}, and
|
|
8467
|
+
* {@link createContract}; it flips back to `online` on the next successful
|
|
8468
|
+
* sync. Purely a freshness signal — not a source of truth for wallet data.
|
|
8469
|
+
*/
|
|
8470
|
+
getSyncState() {
|
|
8471
|
+
return this.syncDegradedReason === void 0 ? { mode: "online", lastSyncedAt: this.lastSyncedAt } : {
|
|
8472
|
+
mode: "degraded",
|
|
8473
|
+
reason: this.syncDegradedReason,
|
|
8474
|
+
lastSyncedAt: this.lastSyncedAt
|
|
8475
|
+
};
|
|
8476
|
+
}
|
|
8477
|
+
markSyncOnline() {
|
|
8478
|
+
this.syncDegradedReason = void 0;
|
|
8479
|
+
this.lastSyncedAt = Date.now();
|
|
8480
|
+
}
|
|
8481
|
+
markSyncDegraded(err) {
|
|
8482
|
+
this.syncDegradedReason = err instanceof Error ? err.message : String(err);
|
|
8483
|
+
}
|
|
7945
8484
|
async initialize() {
|
|
7946
8485
|
if (this.initialized) {
|
|
7947
8486
|
return;
|
|
@@ -7950,7 +8489,13 @@ var ContractManager = class _ContractManager {
|
|
|
7950
8489
|
for (const contract of contracts) {
|
|
7951
8490
|
await this.watcher.addContract(contract);
|
|
7952
8491
|
}
|
|
7953
|
-
|
|
8492
|
+
try {
|
|
8493
|
+
await this.reconcileWatched();
|
|
8494
|
+
this.markSyncOnline();
|
|
8495
|
+
} catch (err) {
|
|
8496
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8497
|
+
this.markSyncDegraded(err);
|
|
8498
|
+
}
|
|
7954
8499
|
this.initialized = true;
|
|
7955
8500
|
this.stopWatcherFn = await this.watcher.startWatching((event) => {
|
|
7956
8501
|
this.handleContractEvent(event).catch((error) => {
|
|
@@ -8004,7 +8549,13 @@ var ContractManager = class _ContractManager {
|
|
|
8004
8549
|
async createContract(params) {
|
|
8005
8550
|
const { contract, persisted } = await this.upsertContract(params);
|
|
8006
8551
|
if (persisted) {
|
|
8007
|
-
|
|
8552
|
+
try {
|
|
8553
|
+
await this.fetchContractVxosFromIndexer([contract]);
|
|
8554
|
+
this.markSyncOnline();
|
|
8555
|
+
} catch (err) {
|
|
8556
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8557
|
+
this.markSyncDegraded(err);
|
|
8558
|
+
}
|
|
8008
8559
|
await this.watcher.addContract(contract);
|
|
8009
8560
|
}
|
|
8010
8561
|
return contract;
|
|
@@ -8203,7 +8754,13 @@ var ContractManager = class _ContractManager {
|
|
|
8203
8754
|
}
|
|
8204
8755
|
async getContractsWithVtxos(filter, pageSize) {
|
|
8205
8756
|
const contracts = await this.getContracts(filter);
|
|
8206
|
-
|
|
8757
|
+
try {
|
|
8758
|
+
await this.syncContracts({ contracts, pageSize });
|
|
8759
|
+
this.markSyncOnline();
|
|
8760
|
+
} catch (err) {
|
|
8761
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
8762
|
+
this.markSyncDegraded(err);
|
|
8763
|
+
}
|
|
8207
8764
|
const vtxos = await this.getVtxosForContracts(contracts);
|
|
8208
8765
|
return contracts.map((contract) => ({
|
|
8209
8766
|
contract,
|
|
@@ -8441,15 +8998,33 @@ var ContractManager = class _ContractManager {
|
|
|
8441
8998
|
* Handle events from the watcher.
|
|
8442
8999
|
*/
|
|
8443
9000
|
async handleContractEvent(event) {
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
9001
|
+
try {
|
|
9002
|
+
switch (event.type) {
|
|
9003
|
+
// Delta-sync only the changed virtual outputs for this contract.
|
|
9004
|
+
case "vtxo_received":
|
|
9005
|
+
await this.syncContracts({ contracts: [event.contract] });
|
|
9006
|
+
this.markSyncOnline();
|
|
9007
|
+
break;
|
|
9008
|
+
case "vtxo_spent":
|
|
9009
|
+
await this.syncContracts({ contracts: [event.contract] });
|
|
9010
|
+
this.markSyncOnline();
|
|
9011
|
+
if (this.config.onVtxosSpent) {
|
|
9012
|
+
try {
|
|
9013
|
+
await this.config.onVtxosSpent(
|
|
9014
|
+
event.vtxos.map((v) => ({ txid: v.txid, vout: v.vout }))
|
|
9015
|
+
);
|
|
9016
|
+
} catch {
|
|
9017
|
+
}
|
|
9018
|
+
}
|
|
9019
|
+
break;
|
|
9020
|
+
case "connection_reset":
|
|
9021
|
+
await this.reconcileWatched();
|
|
9022
|
+
this.markSyncOnline();
|
|
9023
|
+
break;
|
|
9024
|
+
}
|
|
9025
|
+
} catch (err) {
|
|
9026
|
+
if (!isRetryableProviderError(err)) throw err;
|
|
9027
|
+
this.markSyncDegraded(err);
|
|
8453
9028
|
}
|
|
8454
9029
|
this.emitEvent(event);
|
|
8455
9030
|
}
|
|
@@ -8531,6 +9106,12 @@ var ContractManager = class _ContractManager {
|
|
|
8531
9106
|
contract,
|
|
8532
9107
|
filtered
|
|
8533
9108
|
);
|
|
9109
|
+
if (this.config.onVtxosPersisted) {
|
|
9110
|
+
try {
|
|
9111
|
+
await this.config.onVtxosPersisted(contract, filtered);
|
|
9112
|
+
} catch {
|
|
9113
|
+
}
|
|
9114
|
+
}
|
|
8534
9115
|
}
|
|
8535
9116
|
}
|
|
8536
9117
|
async fetchContractVxosFromIndexer(contracts, pageSize, syncWindow) {
|
|
@@ -8551,6 +9132,15 @@ var ContractManager = class _ContractManager {
|
|
|
8551
9132
|
contract,
|
|
8552
9133
|
filtered
|
|
8553
9134
|
);
|
|
9135
|
+
if (this.config.onVtxosPersisted) {
|
|
9136
|
+
try {
|
|
9137
|
+
await this.config.onVtxosPersisted(
|
|
9138
|
+
contract,
|
|
9139
|
+
filtered
|
|
9140
|
+
);
|
|
9141
|
+
} catch {
|
|
9142
|
+
}
|
|
9143
|
+
}
|
|
8554
9144
|
}
|
|
8555
9145
|
}
|
|
8556
9146
|
return result;
|
|
@@ -9424,6 +10014,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9424
10014
|
* (ContractManager isn't given it); `undefined` ⇒ no-op.
|
|
9425
10015
|
*/
|
|
9426
10016
|
virtualTxRepository;
|
|
10017
|
+
/** Opt-in exit-data capture settings; see {@link StorageConfig.exitDataCapture}. */
|
|
10018
|
+
exitDataCapture;
|
|
9427
10019
|
_assetManager;
|
|
9428
10020
|
walletContractTimelocks;
|
|
9429
10021
|
// Outpoints ("txid:vout") committed to an in-flight settle/send. Filtered
|
|
@@ -9466,6 +10058,72 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9466
10058
|
* construction-time snapshot for their lifetime.
|
|
9467
10059
|
*/
|
|
9468
10060
|
_arkServerPublicKey;
|
|
10061
|
+
/**
|
|
10062
|
+
* Whether this wallet was constructed from live operator server-info
|
|
10063
|
+
* (`"live"`) or from a cached snapshot because the operator was unreachable
|
|
10064
|
+
* (`"cache"`). Freshness signal for {@link getProviderConnectionState}.
|
|
10065
|
+
*/
|
|
10066
|
+
_serverInfoSource = "live";
|
|
10067
|
+
/**
|
|
10068
|
+
* Epoch-ms of the last known live operator contact: construction time on the
|
|
10069
|
+
* `live` boot path, the cached snapshot's `savedAt` on the `cache` path.
|
|
10070
|
+
*/
|
|
10071
|
+
_serverInfoLastOnlineAt;
|
|
10072
|
+
/** @see {@link _serverInfoSource} */
|
|
10073
|
+
get serverInfoSource() {
|
|
10074
|
+
return this._serverInfoSource;
|
|
10075
|
+
}
|
|
10076
|
+
/**
|
|
10077
|
+
* Composed provider-connection freshness: the boot server-info source
|
|
10078
|
+
* (Arkade) combined with the contract-manager's indexer-sync health, if the
|
|
10079
|
+
* manager has been initialized. Reads no live provider state — it never
|
|
10080
|
+
* forces a `ContractManager` to construct — so it is safe for readonly
|
|
10081
|
+
* callers that only use address/balance APIs.
|
|
10082
|
+
*
|
|
10083
|
+
* - Boot fell back to a cached snapshot → degraded on `arkade` (`cache`).
|
|
10084
|
+
* - Otherwise, if the contract manager has degraded to repository data →
|
|
10085
|
+
* degraded on `indexer` (`repository`).
|
|
10086
|
+
* - Otherwise online.
|
|
10087
|
+
*
|
|
10088
|
+
* This only describes sync freshness; wallet balances/VTXOs are always read
|
|
10089
|
+
* from the repository regardless of this state.
|
|
10090
|
+
*/
|
|
10091
|
+
getProviderConnectionState() {
|
|
10092
|
+
if (this._serverInfoSource === "cache") {
|
|
10093
|
+
return {
|
|
10094
|
+
mode: "degraded",
|
|
10095
|
+
source: "cache",
|
|
10096
|
+
provider: "arkade",
|
|
10097
|
+
reason: "constructed from cached server-info; operator was unreachable at boot",
|
|
10098
|
+
lastOnlineAt: this._serverInfoLastOnlineAt
|
|
10099
|
+
};
|
|
10100
|
+
}
|
|
10101
|
+
const sync = this._contractManager?.getSyncState();
|
|
10102
|
+
if (sync?.mode === "degraded") {
|
|
10103
|
+
return {
|
|
10104
|
+
mode: "degraded",
|
|
10105
|
+
source: "repository",
|
|
10106
|
+
provider: "indexer",
|
|
10107
|
+
reason: sync.reason,
|
|
10108
|
+
lastOnlineAt: sync.lastSyncedAt ?? this._serverInfoLastOnlineAt
|
|
10109
|
+
};
|
|
10110
|
+
}
|
|
10111
|
+
return {
|
|
10112
|
+
mode: "online",
|
|
10113
|
+
source: "live",
|
|
10114
|
+
lastOnlineAt: sync?.lastSyncedAt ?? this._serverInfoLastOnlineAt ?? 0
|
|
10115
|
+
};
|
|
10116
|
+
}
|
|
10117
|
+
/**
|
|
10118
|
+
* The contract-manager's current provider-sync health **without forcing it
|
|
10119
|
+
* to initialize** — reads the already-constructed manager, or reports
|
|
10120
|
+
* `online` when none exists yet. Unlike {@link getContractManager}, this
|
|
10121
|
+
* never triggers a remote sync, so it is safe on a pure diagnostics path
|
|
10122
|
+
* (e.g. the service-worker sync-state message).
|
|
10123
|
+
*/
|
|
10124
|
+
getContractSyncState() {
|
|
10125
|
+
return this._contractManager?.getSyncState() ?? { mode: "online" };
|
|
10126
|
+
}
|
|
9469
10127
|
/**
|
|
9470
10128
|
* x-only hex of the operator's deprecated signer keys (from
|
|
9471
10129
|
* `ArkInfo.deprecatedSigners`), cached for the OFFLINE read/watch paths.
|
|
@@ -9581,7 +10239,7 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9581
10239
|
*/
|
|
9582
10240
|
static async setupWalletConfig(config, pubKey) {
|
|
9583
10241
|
const arkadeServerUrl = getArkadeServerUrl(config);
|
|
9584
|
-
const arkProvider = config.arkProvider || new
|
|
10242
|
+
const arkProvider = config.arkProvider || new chunkUHOHLN3C_cjs.RestArkProvider(arkadeServerUrl);
|
|
9585
10243
|
let indexerProvider = config.indexerProvider;
|
|
9586
10244
|
if (!indexerProvider) {
|
|
9587
10245
|
let indexerUrl = config.indexerUrl;
|
|
@@ -9598,9 +10256,15 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9598
10256
|
indexerUrl = arkadeServerUrl;
|
|
9599
10257
|
}
|
|
9600
10258
|
}
|
|
9601
|
-
indexerProvider = new
|
|
10259
|
+
indexerProvider = new chunkUHOHLN3C_cjs.RestIndexerProvider(indexerUrl);
|
|
9602
10260
|
}
|
|
9603
|
-
const
|
|
10261
|
+
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
10262
|
+
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
10263
|
+
const {
|
|
10264
|
+
info,
|
|
10265
|
+
source: serverInfoSource,
|
|
10266
|
+
lastOnlineAt: serverInfoLastOnlineAt
|
|
10267
|
+
} = await resolveArkInfo(arkProvider, walletRepository);
|
|
9604
10268
|
const network = chunkHXDZ2QTW_cjs.getNetwork(info.network);
|
|
9605
10269
|
if ("descriptor" in config.identity) {
|
|
9606
10270
|
const descriptor = config.identity.descriptor;
|
|
@@ -9654,8 +10318,6 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9654
10318
|
serverPubKey: base.hex.encode(serverPubKey),
|
|
9655
10319
|
csvTimelock: chunkHXDZ2QTW_cjs.timelockToSequence(boardingTimelock).toString()
|
|
9656
10320
|
});
|
|
9657
|
-
const walletRepository = config.storage?.walletRepository ?? new IndexedDBWalletRepository();
|
|
9658
|
-
const contractRepository = config.storage?.contractRepository ?? new IndexedDBContractRepository();
|
|
9659
10321
|
return {
|
|
9660
10322
|
arkProvider,
|
|
9661
10323
|
indexerProvider,
|
|
@@ -9669,6 +10331,8 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9669
10331
|
walletRepository,
|
|
9670
10332
|
contractRepository,
|
|
9671
10333
|
info,
|
|
10334
|
+
serverInfoSource,
|
|
10335
|
+
serverInfoLastOnlineAt,
|
|
9672
10336
|
delegateProvider: config.delegateProvider || config.delegatorProvider,
|
|
9673
10337
|
/** @deprecated alias for `delegateProvider` */
|
|
9674
10338
|
delegatorProvider: config.delegateProvider || config.delegatorProvider,
|
|
@@ -9704,6 +10368,15 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9704
10368
|
);
|
|
9705
10369
|
wallet.intentRepository = config.storage?.intentRepository;
|
|
9706
10370
|
wallet.virtualTxRepository = config.storage?.virtualTxRepository;
|
|
10371
|
+
wallet.exitDataCapture = config.storage?.exitDataCapture;
|
|
10372
|
+
wallet._serverInfoSource = setup.serverInfoSource;
|
|
10373
|
+
if (setup.serverInfoSource === "live") {
|
|
10374
|
+
const now = Date.now();
|
|
10375
|
+
await saveValidatedArkInfoSnapshot(setup.walletRepository, setup.info, now);
|
|
10376
|
+
wallet._serverInfoLastOnlineAt = now;
|
|
10377
|
+
} else {
|
|
10378
|
+
wallet._serverInfoLastOnlineAt = setup.serverInfoLastOnlineAt;
|
|
10379
|
+
}
|
|
9707
10380
|
wallet.refreshDeprecatedSigners(setup.info);
|
|
9708
10381
|
return wallet;
|
|
9709
10382
|
}
|
|
@@ -9834,7 +10507,10 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
9834
10507
|
const response = await contractManager.getContractsWithVtxos();
|
|
9835
10508
|
const allVtxos = response.flatMap((_) => _.vtxos);
|
|
9836
10509
|
const { boardingTxs, commitmentsToIgnore } = await this.getBoardingTxs();
|
|
9837
|
-
const getTxCreatedAt = (txid) => this.indexerProvider.getVtxos({ outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime())
|
|
10510
|
+
const getTxCreatedAt = (txid) => this.indexerProvider.getVtxos({ outpoints: [{ txid, vout: 0 }] }).then((res) => res.vtxos[0]?.createdAt.getTime()).catch((err) => {
|
|
10511
|
+
if (isRetryableProviderError(err)) return void 0;
|
|
10512
|
+
throw err;
|
|
10513
|
+
});
|
|
9838
10514
|
return buildTransactionHistory(allVtxos, boardingTxs, commitmentsToIgnore, getTxCreatedAt);
|
|
9839
10515
|
}
|
|
9840
10516
|
/**
|
|
@@ -10253,11 +10929,39 @@ var ReadonlyWallet = class _ReadonlyWallet {
|
|
|
10253
10929
|
}
|
|
10254
10930
|
}
|
|
10255
10931
|
async initializeContractManager() {
|
|
10932
|
+
const virtualTxRepository = this.virtualTxRepository;
|
|
10933
|
+
let onVtxosPersisted;
|
|
10934
|
+
let onVtxosSpent;
|
|
10935
|
+
if (virtualTxRepository) {
|
|
10936
|
+
const capture = this.exitDataCapture;
|
|
10937
|
+
const resolver = createExitChainResolver({
|
|
10938
|
+
indexer: this.indexerProvider,
|
|
10939
|
+
repository: virtualTxRepository,
|
|
10940
|
+
extraSources: capture?.sources
|
|
10941
|
+
});
|
|
10942
|
+
onVtxosPersisted = async (_contract, vtxos) => {
|
|
10943
|
+
for (const v of vtxos) {
|
|
10944
|
+
if (v.virtualStatus.state === "spent") continue;
|
|
10945
|
+
await captureExitBranch({
|
|
10946
|
+
resolver,
|
|
10947
|
+
repository: virtualTxRepository,
|
|
10948
|
+
vtxo: { txid: v.txid, vout: v.vout },
|
|
10949
|
+
value: v.value,
|
|
10950
|
+
mode: capture?.mode ?? DEFAULT_EXIT_CAPTURE_MODE,
|
|
10951
|
+
minExitWorthSats: capture?.minExitWorthSats ?? DEFAULT_MIN_EXIT_WORTH_SATS
|
|
10952
|
+
}).catch(() => {
|
|
10953
|
+
});
|
|
10954
|
+
}
|
|
10955
|
+
};
|
|
10956
|
+
onVtxosSpent = (vtxos) => pruneExitBranches(virtualTxRepository, vtxos);
|
|
10957
|
+
}
|
|
10256
10958
|
const manager = await ContractManager.create({
|
|
10257
10959
|
indexerProvider: this.indexerProvider,
|
|
10258
10960
|
contractRepository: this.contractRepository,
|
|
10259
10961
|
walletRepository: this.walletRepository,
|
|
10260
10962
|
intentRepository: this.intentRepository,
|
|
10963
|
+
onVtxosPersisted,
|
|
10964
|
+
onVtxosSpent,
|
|
10261
10965
|
watcherConfig: this.watcherConfig
|
|
10262
10966
|
});
|
|
10263
10967
|
const baselinePubkey = await this.identity.xOnlyPublicKey();
|
|
@@ -10932,6 +11636,14 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
10932
11636
|
boot?.rotator,
|
|
10933
11637
|
boot?.provider
|
|
10934
11638
|
);
|
|
11639
|
+
wallet._serverInfoSource = setup.serverInfoSource;
|
|
11640
|
+
if (setup.serverInfoSource === "live") {
|
|
11641
|
+
const now = Date.now();
|
|
11642
|
+
await saveValidatedArkInfoSnapshot(setup.walletRepository, setup.info, now);
|
|
11643
|
+
wallet._serverInfoLastOnlineAt = now;
|
|
11644
|
+
} else {
|
|
11645
|
+
wallet._serverInfoLastOnlineAt = setup.serverInfoLastOnlineAt;
|
|
11646
|
+
}
|
|
10935
11647
|
wallet.refreshDeprecatedSigners(setup.info);
|
|
10936
11648
|
{
|
|
10937
11649
|
const ap = setup.arkProvider;
|
|
@@ -10953,6 +11665,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
10953
11665
|
}
|
|
10954
11666
|
wallet.intentRepository = config.storage?.intentRepository;
|
|
10955
11667
|
wallet.virtualTxRepository = config.storage?.virtualTxRepository;
|
|
11668
|
+
wallet.exitDataCapture = config.storage?.exitDataCapture;
|
|
10956
11669
|
await wallet.getVtxoManager();
|
|
10957
11670
|
return wallet;
|
|
10958
11671
|
}
|
|
@@ -11613,9 +12326,9 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11613
12326
|
...existing ?? {},
|
|
11614
12327
|
intentTxId,
|
|
11615
12328
|
registerProof: intent.proof,
|
|
11616
|
-
registerProofMessage:
|
|
12329
|
+
registerProofMessage: chunkUHOHLN3C_cjs.Intent.encodeMessage(intent.message),
|
|
11617
12330
|
deleteProof: deleteIntent.proof,
|
|
11618
|
-
deleteProofMessage:
|
|
12331
|
+
deleteProofMessage: chunkUHOHLN3C_cjs.Intent.encodeMessage(deleteIntent.message),
|
|
11619
12332
|
intentVtxos: inputs.map((i) => ({
|
|
11620
12333
|
txid: i.txid,
|
|
11621
12334
|
vout: i.vout
|
|
@@ -11647,7 +12360,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11647
12360
|
try {
|
|
11648
12361
|
return await this.arkProvider.registerIntent(intent);
|
|
11649
12362
|
} catch (error) {
|
|
11650
|
-
if (error instanceof
|
|
12363
|
+
if (error instanceof chunkUHOHLN3C_cjs.ArkError && error.code === 0 && error.message.includes("duplicated input")) {
|
|
11651
12364
|
const deleteIntent = await this.makeDeleteIntentSignature(inputs);
|
|
11652
12365
|
await this.arkProvider.deleteIntent(deleteIntent);
|
|
11653
12366
|
return this.arkProvider.registerIntent(intent);
|
|
@@ -11663,7 +12376,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11663
12376
|
expire_at: 0,
|
|
11664
12377
|
cosigners_public_keys: cosignerPubKeys
|
|
11665
12378
|
};
|
|
11666
|
-
const proof =
|
|
12379
|
+
const proof = chunkUHOHLN3C_cjs.Intent.create(message, coins, outputs);
|
|
11667
12380
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11668
12381
|
return {
|
|
11669
12382
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -11675,7 +12388,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11675
12388
|
type: "delete",
|
|
11676
12389
|
expire_at: 0
|
|
11677
12390
|
};
|
|
11678
|
-
const proof =
|
|
12391
|
+
const proof = chunkUHOHLN3C_cjs.Intent.create(message, coins, []);
|
|
11679
12392
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11680
12393
|
return {
|
|
11681
12394
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -11687,7 +12400,7 @@ var Wallet2 = class _Wallet extends ReadonlyWallet {
|
|
|
11687
12400
|
type: "get-pending-tx",
|
|
11688
12401
|
expire_at: 0
|
|
11689
12402
|
};
|
|
11690
|
-
const proof =
|
|
12403
|
+
const proof = chunkUHOHLN3C_cjs.Intent.create(message, coins, []);
|
|
11691
12404
|
const signedProof = await this._signerRouter.sign(proof, intentProofJobs(coins));
|
|
11692
12405
|
return {
|
|
11693
12406
|
proof: base.base64.encode(signedProof.toPSBT()),
|
|
@@ -12645,7 +13358,7 @@ var MessageBus = class {
|
|
|
12645
13358
|
this.initialized = true;
|
|
12646
13359
|
}
|
|
12647
13360
|
async buildServices(config) {
|
|
12648
|
-
const arkProvider = new
|
|
13361
|
+
const arkProvider = new chunkUHOHLN3C_cjs.RestArkProvider(config.arkServer.url);
|
|
12649
13362
|
const storage = {
|
|
12650
13363
|
walletRepository: this.walletRepository,
|
|
12651
13364
|
contractRepository: this.contractRepository
|
|
@@ -13470,10 +14183,18 @@ var WalletMessageHandler = class {
|
|
|
13470
14183
|
type: "WALLET_STATUS",
|
|
13471
14184
|
payload: {
|
|
13472
14185
|
walletInitialized: true,
|
|
13473
|
-
xOnlyPublicKey: pubKey
|
|
14186
|
+
xOnlyPublicKey: pubKey,
|
|
14187
|
+
providerConnectionState: this.readonlyWallet.getProviderConnectionState()
|
|
13474
14188
|
}
|
|
13475
14189
|
});
|
|
13476
14190
|
}
|
|
14191
|
+
case "GET_CONTRACT_SYNC_STATE": {
|
|
14192
|
+
return this.tagged({
|
|
14193
|
+
id,
|
|
14194
|
+
type: "CONTRACT_SYNC_STATE",
|
|
14195
|
+
payload: { syncState: this.readonlyWallet.getContractSyncState() }
|
|
14196
|
+
});
|
|
14197
|
+
}
|
|
13477
14198
|
case "CLEAR": {
|
|
13478
14199
|
await this.clear();
|
|
13479
14200
|
return this.tagged({
|
|
@@ -13802,7 +14523,7 @@ var WalletMessageHandler = class {
|
|
|
13802
14523
|
// Wallet methods
|
|
13803
14524
|
async handleInitWallet({ payload }) {
|
|
13804
14525
|
const { arkServerUrl } = payload;
|
|
13805
|
-
this.indexerProvider = new
|
|
14526
|
+
this.indexerProvider = new chunkUHOHLN3C_cjs.RestIndexerProvider(arkServerUrl);
|
|
13806
14527
|
await this.onWalletInitialized();
|
|
13807
14528
|
}
|
|
13808
14529
|
async handleGetBalance() {
|
|
@@ -14236,6 +14957,7 @@ var DEFAULT_MESSAGE_TIMEOUTS = {
|
|
|
14236
14957
|
GET_BALANCE: 1e4,
|
|
14237
14958
|
GET_BOARDING_ADDRESS: 1e4,
|
|
14238
14959
|
GET_STATUS: 1e4,
|
|
14960
|
+
GET_CONTRACT_SYNC_STATE: 1e4,
|
|
14239
14961
|
GET_DELEGATE_INFO: 1e4,
|
|
14240
14962
|
IS_CONTRACT_MANAGER_WATCHING: 1e4,
|
|
14241
14963
|
// Medium reads — may involve indexer queries
|
|
@@ -14844,6 +15566,19 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14844
15566
|
throw new Error(`Failed to get status: ${error}`);
|
|
14845
15567
|
}
|
|
14846
15568
|
}
|
|
15569
|
+
/**
|
|
15570
|
+
* Wallet-level provider-connection freshness, delegated to the worker via
|
|
15571
|
+
* `GET_STATUS`. Async by necessity (the worker boundary is asynchronous); no
|
|
15572
|
+
* synchronous variant is offered because it would have the same transport
|
|
15573
|
+
* mismatch as the contract-manager proxy's cached `getSyncState()`.
|
|
15574
|
+
*/
|
|
15575
|
+
async getProviderConnectionState() {
|
|
15576
|
+
const { providerConnectionState } = await this.getStatus();
|
|
15577
|
+
if (!providerConnectionState) {
|
|
15578
|
+
throw new Error("Worker did not report provider connection state");
|
|
15579
|
+
}
|
|
15580
|
+
return providerConnectionState;
|
|
15581
|
+
}
|
|
14847
15582
|
async getActivityHistory() {
|
|
14848
15583
|
return buildActivities(await this.getTransactionHistory(), this.activity.all());
|
|
14849
15584
|
}
|
|
@@ -14898,6 +15633,32 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14898
15633
|
return wallet.sendMessage(message);
|
|
14899
15634
|
};
|
|
14900
15635
|
const messageTag = this.messageTag;
|
|
15636
|
+
const fetchSyncState = async () => {
|
|
15637
|
+
const message = {
|
|
15638
|
+
type: "GET_CONTRACT_SYNC_STATE",
|
|
15639
|
+
id: getRandomId(),
|
|
15640
|
+
tag: messageTag
|
|
15641
|
+
};
|
|
15642
|
+
const response = await sendContractMessage(message);
|
|
15643
|
+
return response.payload.syncState;
|
|
15644
|
+
};
|
|
15645
|
+
const UNKNOWN_STATE = {
|
|
15646
|
+
mode: "degraded",
|
|
15647
|
+
reason: "contract sync state unavailable from the worker"
|
|
15648
|
+
};
|
|
15649
|
+
let syncState = UNKNOWN_STATE;
|
|
15650
|
+
let everProbed = false;
|
|
15651
|
+
const refreshSyncState = async () => {
|
|
15652
|
+
try {
|
|
15653
|
+
syncState = await fetchSyncState();
|
|
15654
|
+
everProbed = true;
|
|
15655
|
+
} catch {
|
|
15656
|
+
if (!everProbed) {
|
|
15657
|
+
syncState = UNKNOWN_STATE;
|
|
15658
|
+
}
|
|
15659
|
+
}
|
|
15660
|
+
};
|
|
15661
|
+
await refreshSyncState();
|
|
14901
15662
|
const manager = {
|
|
14902
15663
|
async createContract(params) {
|
|
14903
15664
|
const message = {
|
|
@@ -14908,6 +15669,7 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14908
15669
|
};
|
|
14909
15670
|
try {
|
|
14910
15671
|
const response = await sendContractMessage(message);
|
|
15672
|
+
await refreshSyncState();
|
|
14911
15673
|
return response.payload.contract;
|
|
14912
15674
|
} catch (e) {
|
|
14913
15675
|
throw new Error("Failed to create contract");
|
|
@@ -14936,11 +15698,15 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
14936
15698
|
};
|
|
14937
15699
|
try {
|
|
14938
15700
|
const response = await sendContractMessage(message);
|
|
15701
|
+
await refreshSyncState();
|
|
14939
15702
|
return response.payload.contracts;
|
|
14940
15703
|
} catch (e) {
|
|
14941
15704
|
throw new Error("Failed to get contracts with vtxos");
|
|
14942
15705
|
}
|
|
14943
15706
|
},
|
|
15707
|
+
getSyncState() {
|
|
15708
|
+
return syncState;
|
|
15709
|
+
},
|
|
14944
15710
|
async annotateVtxos(vtxos) {
|
|
14945
15711
|
if (vtxos.length === 0) return [];
|
|
14946
15712
|
const message = {
|
|
@@ -15049,7 +15815,11 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
15049
15815
|
tag: messageTag,
|
|
15050
15816
|
payload: opts
|
|
15051
15817
|
};
|
|
15052
|
-
|
|
15818
|
+
try {
|
|
15819
|
+
await sendContractMessage(message);
|
|
15820
|
+
} finally {
|
|
15821
|
+
await refreshSyncState();
|
|
15822
|
+
}
|
|
15053
15823
|
},
|
|
15054
15824
|
async refreshOutpoints(outpoints) {
|
|
15055
15825
|
const message = {
|
|
@@ -15058,7 +15828,11 @@ var ServiceWorkerReadonlyWallet = class _ServiceWorkerReadonlyWallet {
|
|
|
15058
15828
|
tag: messageTag,
|
|
15059
15829
|
payload: { outpoints }
|
|
15060
15830
|
};
|
|
15061
|
-
|
|
15831
|
+
try {
|
|
15832
|
+
await sendContractMessage(message);
|
|
15833
|
+
} finally {
|
|
15834
|
+
await refreshSyncState();
|
|
15835
|
+
}
|
|
15062
15836
|
},
|
|
15063
15837
|
scanContracts() {
|
|
15064
15838
|
return Promise.reject(
|
|
@@ -15609,7 +16383,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
15609
16383
|
if (!inputs) {
|
|
15610
16384
|
throw new Error("Fee estimation failed");
|
|
15611
16385
|
}
|
|
15612
|
-
let tx = new
|
|
16386
|
+
let tx = new chunkUHOHLN3C_cjs.Transaction();
|
|
15613
16387
|
for (const input of inputs) {
|
|
15614
16388
|
tx.addInput({
|
|
15615
16389
|
txid: input.txid,
|
|
@@ -15667,7 +16441,7 @@ var OnchainWallet = class _OnchainWallet {
|
|
|
15667
16441
|
* @throws If the parent has no anchor, or funding cannot be selected/signed
|
|
15668
16442
|
*/
|
|
15669
16443
|
async bumpAnchor(parentHex, feeRate) {
|
|
15670
|
-
const parent =
|
|
16444
|
+
const parent = chunkUHOHLN3C_cjs.Transaction.fromRaw(base.hex.decode(parentHex));
|
|
15671
16445
|
const coins = (await this.getCoins()).filter((c) => c.status.confirmed);
|
|
15672
16446
|
const child = await this.buildBumpPackage(parent, feeRate, coins);
|
|
15673
16447
|
return [parent.hex, child.hex];
|
|
@@ -16428,7 +17202,7 @@ exports.BIP322 = void 0;
|
|
|
16428
17202
|
async function sign2(message, identity, network) {
|
|
16429
17203
|
const xOnlyPubKey = await identity.xOnlyPublicKey();
|
|
16430
17204
|
const payment = btcSigner.p2tr(xOnlyPubKey, void 0, network);
|
|
16431
|
-
const toSpend =
|
|
17205
|
+
const toSpend = chunkUHOHLN3C_cjs.craftToSpendTx(message, payment.script, TAG_BIP322);
|
|
16432
17206
|
const toSign = craftBIP322ToSignP2TR(toSpend, payment.script, xOnlyPubKey);
|
|
16433
17207
|
const signed = await identity.sign(toSign, [0]);
|
|
16434
17208
|
signed.finalizeIdx(0);
|
|
@@ -16486,7 +17260,7 @@ function verifyP2TR(message, witnessItems, pkScript, pubkey) {
|
|
|
16486
17260
|
if (sighashType !== btcSigner.SigHash.DEFAULT && sighashType !== btcSigner.SigHash.ALL) {
|
|
16487
17261
|
return false;
|
|
16488
17262
|
}
|
|
16489
|
-
const toSpend =
|
|
17263
|
+
const toSpend = chunkUHOHLN3C_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
16490
17264
|
const toSign = craftBIP322ToSignP2TR(toSpend, pkScript, pubkey);
|
|
16491
17265
|
const sighash = toSign.preimageWitnessV1(0, [pkScript], sighashType, [0n]);
|
|
16492
17266
|
const rawSig = sig.length === 65 ? sig.subarray(0, 64) : sig;
|
|
@@ -16507,7 +17281,7 @@ function verifyP2WPKH(message, witnessItems, pkScript, addressHash) {
|
|
|
16507
17281
|
}
|
|
16508
17282
|
const sighashType = sigWithHash[sigWithHash.length - 1];
|
|
16509
17283
|
const derSig = sigWithHash.subarray(0, sigWithHash.length - 1);
|
|
16510
|
-
const toSpend =
|
|
17284
|
+
const toSpend = chunkUHOHLN3C_cjs.craftToSpendTx(message, pkScript, TAG_BIP322);
|
|
16511
17285
|
const toSign = craftBIP322ToSignSimple(toSpend, pkScript);
|
|
16512
17286
|
const scriptCode = btcSigner.OutScript.encode({ type: "pkh", hash: addressHash });
|
|
16513
17287
|
const sighash = toSign.preimageWitnessV0(0, scriptCode, sighashType, 0n);
|
|
@@ -16560,7 +17334,7 @@ function encodeCompactSize(n) {
|
|
|
16560
17334
|
return buf;
|
|
16561
17335
|
}
|
|
16562
17336
|
function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
16563
|
-
const tx = new
|
|
17337
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({ version: 0 });
|
|
16564
17338
|
tx.addInput({
|
|
16565
17339
|
txid: toSpend.id,
|
|
16566
17340
|
index: 0,
|
|
@@ -16574,12 +17348,12 @@ function craftBIP322ToSignP2TR(toSpend, pkScript, tapInternalKey) {
|
|
|
16574
17348
|
});
|
|
16575
17349
|
tx.addOutput({
|
|
16576
17350
|
amount: 0n,
|
|
16577
|
-
script:
|
|
17351
|
+
script: chunkUHOHLN3C_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
16578
17352
|
});
|
|
16579
17353
|
return tx;
|
|
16580
17354
|
}
|
|
16581
17355
|
function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
16582
|
-
const tx = new
|
|
17356
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({ version: 0 });
|
|
16583
17357
|
tx.addInput({
|
|
16584
17358
|
txid: toSpend.id,
|
|
16585
17359
|
index: 0,
|
|
@@ -16591,12 +17365,12 @@ function craftBIP322ToSignSimple(toSpend, pkScript) {
|
|
|
16591
17365
|
});
|
|
16592
17366
|
tx.addOutput({
|
|
16593
17367
|
amount: 0n,
|
|
16594
|
-
script:
|
|
17368
|
+
script: chunkUHOHLN3C_cjs.OP_RETURN_EMPTY_PKSCRIPT
|
|
16595
17369
|
});
|
|
16596
17370
|
return tx;
|
|
16597
17371
|
}
|
|
16598
17372
|
function finalizeVirtualTx(type, psbtBase64) {
|
|
16599
|
-
const tx =
|
|
17373
|
+
const tx = chunkUHOHLN3C_cjs.Transaction.fromPSBT(base.base64.decode(psbtBase64));
|
|
16600
17374
|
if (type === "INDEXER_CHAINED_TX_TYPE_TREE" /* TREE */) {
|
|
16601
17375
|
const input = tx.getInput(0);
|
|
16602
17376
|
if (!input) {
|
|
@@ -16673,7 +17447,7 @@ async function resolveUnilateralPath(params) {
|
|
|
16673
17447
|
}
|
|
16674
17448
|
|
|
16675
17449
|
// src/wallet/unroll.ts
|
|
16676
|
-
function
|
|
17450
|
+
function chainTxTypeToChainedExit2(t) {
|
|
16677
17451
|
switch (t) {
|
|
16678
17452
|
case "INDEXER_CHAINED_TX_TYPE_COMMITMENT" /* COMMITMENT */:
|
|
16679
17453
|
return 1 /* Commitment */;
|
|
@@ -16736,7 +17510,7 @@ exports.Unroll = void 0;
|
|
|
16736
17510
|
txid: next.txid,
|
|
16737
17511
|
psbt,
|
|
16738
17512
|
expiresAt: null,
|
|
16739
|
-
type:
|
|
17513
|
+
type: chainTxTypeToChainedExit2(next.type)
|
|
16740
17514
|
};
|
|
16741
17515
|
try {
|
|
16742
17516
|
await repo.upsertVirtualTxs([cached]);
|
|
@@ -16868,7 +17642,7 @@ async function prepareUnrollTransaction(wallet, vtxoTxIds, outputAddress) {
|
|
|
16868
17642
|
btcSigner.TaprootControlBlock.encode(spendingLeaf[0]).length
|
|
16869
17643
|
);
|
|
16870
17644
|
}
|
|
16871
|
-
const tx = new
|
|
17645
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({ version: 2 });
|
|
16872
17646
|
for (const input of inputs) {
|
|
16873
17647
|
tx.addInput(input);
|
|
16874
17648
|
}
|
|
@@ -16914,99 +17688,6 @@ function doWait(onchainProvider, txid) {
|
|
|
16914
17688
|
});
|
|
16915
17689
|
};
|
|
16916
17690
|
}
|
|
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
|
-
}
|
|
16938
|
-
}
|
|
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);
|
|
17001
|
-
}
|
|
17002
|
-
}
|
|
17003
|
-
if (!progress) {
|
|
17004
|
-
throw new Error("topological sort: cycle or unsatisfiable dependency");
|
|
17005
|
-
}
|
|
17006
|
-
remaining = next;
|
|
17007
|
-
}
|
|
17008
|
-
return ordered;
|
|
17009
|
-
}
|
|
17010
17691
|
function extraWitnessSize(path) {
|
|
17011
17692
|
return (path.extraWitness ?? []).reduce((sum, item) => sum + 1 + item.length, 0);
|
|
17012
17693
|
}
|
|
@@ -17028,7 +17709,7 @@ async function buildSignedSweep(params) {
|
|
|
17028
17709
|
`uneconomic vtxo ${vtxo.txid}:${vtxo.vout}: value ${vtxo.value} - fee ${fee} < dust`
|
|
17029
17710
|
);
|
|
17030
17711
|
}
|
|
17031
|
-
const tx = new
|
|
17712
|
+
const tx = new chunkUHOHLN3C_cjs.Transaction({ version: 2 });
|
|
17032
17713
|
tx.addInput({
|
|
17033
17714
|
txid: vtxo.txid,
|
|
17034
17715
|
index: vtxo.vout,
|
|
@@ -17113,27 +17794,22 @@ async function computeExitLayout(opts, feeRate) {
|
|
|
17113
17794
|
const { wallet, onchainWallet } = opts;
|
|
17114
17795
|
const vtxos = await selectExitVtxos(opts);
|
|
17115
17796
|
if (vtxos.length === 0) throw new Error("no vtxos to exit");
|
|
17797
|
+
const resolver = createExitChainResolver({
|
|
17798
|
+
indexer: wallet.indexerProvider,
|
|
17799
|
+
repository: wallet.virtualTxRepository,
|
|
17800
|
+
extraSources: wallet.exitDataCapture?.sources
|
|
17801
|
+
});
|
|
17116
17802
|
const dag = await buildExitDag({
|
|
17117
17803
|
vtxos,
|
|
17118
|
-
|
|
17804
|
+
chain: resolver,
|
|
17119
17805
|
onchain: wallet.onchainProvider
|
|
17120
17806
|
});
|
|
17121
17807
|
const pendingNodes = dag.filter((n) => !n.confirmed);
|
|
17122
17808
|
const psbts = /* @__PURE__ */ new Map();
|
|
17123
17809
|
if (pendingNodes.length > 0) {
|
|
17124
|
-
const
|
|
17125
|
-
|
|
17126
|
-
|
|
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++;
|
|
17810
|
+
const txs = await resolver.getVirtualTxs(pendingNodes.map((n) => n.txid));
|
|
17811
|
+
for (const psbt of txs) {
|
|
17812
|
+
psbts.set(chunkUHOHLN3C_cjs.Transaction.fromPSBT(base.base64.decode(psbt)).id, psbt);
|
|
17137
17813
|
}
|
|
17138
17814
|
}
|
|
17139
17815
|
const childVsize = Number(
|
|
@@ -17578,7 +18254,7 @@ async function prepare(opts) {
|
|
|
17578
18254
|
if (newFee <= splitterFee) break;
|
|
17579
18255
|
splitterFee = newFee;
|
|
17580
18256
|
}
|
|
17581
|
-
const splitter = new
|
|
18257
|
+
const splitter = new chunkUHOHLN3C_cjs.Transaction({ version: 2 });
|
|
17582
18258
|
for (const coin of selected.inputs) {
|
|
17583
18259
|
splitter.addInput({
|
|
17584
18260
|
txid: coin.txid,
|
|
@@ -17851,6 +18527,7 @@ exports.combineTapscriptSigs = combineTapscriptSigs;
|
|
|
17851
18527
|
exports.contractFromArkContract = contractFromArkContract;
|
|
17852
18528
|
exports.contractFromArkContractWithAddress = contractFromArkContractWithAddress;
|
|
17853
18529
|
exports.createDefaultActivityRegistry = createDefaultActivityRegistry;
|
|
18530
|
+
exports.createExitChainResolver = createExitChainResolver;
|
|
17854
18531
|
exports.decodeArkContract = decodeArkContract;
|
|
17855
18532
|
exports.deserializeAssets = deserializeAssets;
|
|
17856
18533
|
exports.deserializeExitPackage = deserializeExitPackage;
|
|
@@ -17869,6 +18546,7 @@ exports.isCooperativelyMigratable = isCooperativelyMigratable;
|
|
|
17869
18546
|
exports.isDiscoverable = isDiscoverable;
|
|
17870
18547
|
exports.isExpired = isExpired;
|
|
17871
18548
|
exports.isRecoverable = isRecoverable;
|
|
18549
|
+
exports.isRetryableProviderError = isRetryableProviderError;
|
|
17872
18550
|
exports.isSpendable = isSpendable;
|
|
17873
18551
|
exports.isSubdust = isSubdust;
|
|
17874
18552
|
exports.isTerminalIntentState = isTerminalIntentState;
|
|
@@ -17894,5 +18572,5 @@ exports.validateVtxoTxGraph = validateVtxoTxGraph;
|
|
|
17894
18572
|
exports.verifyTapscriptSignatures = verifyTapscriptSignatures;
|
|
17895
18573
|
exports.waitForIncomingFunds = waitForIncomingFunds;
|
|
17896
18574
|
exports.warnAndFilterVtxosForScript = warnAndFilterVtxosForScript;
|
|
17897
|
-
//# sourceMappingURL=chunk-
|
|
17898
|
-
//# sourceMappingURL=chunk-
|
|
18575
|
+
//# sourceMappingURL=chunk-SRCWBFSZ.cjs.map
|
|
18576
|
+
//# sourceMappingURL=chunk-SRCWBFSZ.cjs.map
|