@arkade-os/sdk 0.4.15 → 0.4.16
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 +102 -96
- package/dist/cjs/arkfee/estimator.js +1 -1
- package/dist/cjs/arkfee/types.js +2 -1
- package/dist/cjs/arknote/index.js +43 -4
- package/dist/cjs/bip322/index.js +1 -1
- package/dist/cjs/contracts/arkcontract.js +1 -1
- package/dist/cjs/contracts/contractManager.js +40 -24
- package/dist/cjs/contracts/contractWatcher.js +29 -22
- package/dist/cjs/contracts/handlers/default.js +1 -1
- package/dist/cjs/contracts/handlers/delegate.js +1 -1
- package/dist/cjs/contracts/handlers/helpers.js +1 -1
- package/dist/cjs/extension/asset/assetGroup.js +92 -5
- package/dist/cjs/extension/asset/assetId.js +67 -3
- package/dist/cjs/extension/asset/assetInput.js +18 -0
- package/dist/cjs/extension/asset/assetOutput.js +15 -0
- package/dist/cjs/extension/asset/assetRef.js +66 -0
- package/dist/cjs/extension/asset/metadata.js +15 -0
- package/dist/cjs/extension/asset/packet.js +4 -1
- package/dist/cjs/extension/index.js +1 -1
- package/dist/cjs/forfeit.js +14 -0
- package/dist/cjs/identity/seedIdentity.js +2 -2
- package/dist/cjs/identity/singleKey.js +4 -0
- package/dist/cjs/intent/index.js +28 -12
- package/dist/cjs/providers/ark.js +3 -2
- package/dist/cjs/providers/delegator.js +20 -1
- package/dist/cjs/providers/expoArk.js +2 -2
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/providers/onchain.js +2 -1
- package/dist/cjs/repositories/realm/schemas.js +2 -2
- package/dist/cjs/repositories/realm/types.js +1 -1
- package/dist/cjs/script/address.js +37 -6
- package/dist/cjs/script/base.js +70 -1
- package/dist/cjs/script/default.js +3 -0
- package/dist/cjs/script/delegate.js +4 -0
- package/dist/cjs/script/tapscript.js +17 -2
- package/dist/cjs/script/vhtlc.js +35 -27
- package/dist/cjs/storage/fileSystem.js +1 -1
- package/dist/cjs/storage/inMemory.js +1 -1
- package/dist/cjs/storage/indexedDB.js +1 -1
- package/dist/cjs/storage/localStorage.js +1 -1
- package/dist/cjs/tree/validation.js +1 -1
- package/dist/cjs/utils/arkTransaction.js +5 -5
- package/dist/cjs/utils/bip21.js +16 -3
- package/dist/cjs/utils/syncCursors.js +4 -4
- package/dist/cjs/utils/transaction.js +1 -1
- package/dist/cjs/utils/transactionHistory.js +11 -11
- package/dist/cjs/utils/unknownFields.js +3 -3
- package/dist/cjs/wallet/asset-manager.js +4 -4
- package/dist/cjs/wallet/batch.js +5 -5
- package/dist/cjs/wallet/delegator.js +9 -8
- package/dist/cjs/wallet/expo/background.js +3 -3
- package/dist/cjs/wallet/expo/wallet.js +7 -7
- package/dist/cjs/wallet/index.js +43 -0
- package/dist/cjs/wallet/onchain.js +43 -5
- package/dist/cjs/wallet/ramps.js +44 -14
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
- package/dist/cjs/wallet/unroll.js +12 -8
- package/dist/cjs/wallet/utils.js +1 -1
- package/dist/cjs/wallet/vtxo-manager.js +122 -82
- package/dist/cjs/wallet/wallet.js +125 -67
- package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/cjs/worker/expo/taskRunner.js +3 -3
- package/dist/cjs/worker/messageBus.js +3 -0
- package/dist/esm/arkfee/estimator.js +1 -1
- package/dist/esm/arkfee/types.js +2 -1
- package/dist/esm/arknote/index.js +43 -4
- package/dist/esm/bip322/index.js +1 -1
- package/dist/esm/contracts/arkcontract.js +1 -1
- package/dist/esm/contracts/contractManager.js +40 -24
- package/dist/esm/contracts/contractWatcher.js +29 -22
- package/dist/esm/contracts/handlers/default.js +1 -1
- package/dist/esm/contracts/handlers/delegate.js +1 -1
- package/dist/esm/contracts/handlers/helpers.js +1 -1
- package/dist/esm/extension/asset/assetGroup.js +92 -5
- package/dist/esm/extension/asset/assetId.js +67 -3
- package/dist/esm/extension/asset/assetInput.js +18 -0
- package/dist/esm/extension/asset/assetOutput.js +15 -0
- package/dist/esm/extension/asset/assetRef.js +66 -0
- package/dist/esm/extension/asset/metadata.js +15 -0
- package/dist/esm/extension/asset/packet.js +4 -1
- package/dist/esm/extension/index.js +1 -1
- package/dist/esm/forfeit.js +14 -0
- package/dist/esm/identity/seedIdentity.js +2 -2
- package/dist/esm/identity/singleKey.js +4 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/intent/index.js +28 -12
- package/dist/esm/providers/ark.js +3 -2
- package/dist/esm/providers/delegator.js +20 -1
- package/dist/esm/providers/expoArk.js +2 -2
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/providers/onchain.js +2 -1
- package/dist/esm/repositories/realm/schemas.js +2 -2
- package/dist/esm/repositories/realm/types.js +1 -1
- package/dist/esm/script/address.js +37 -6
- package/dist/esm/script/base.js +70 -1
- package/dist/esm/script/default.js +3 -0
- package/dist/esm/script/delegate.js +4 -0
- package/dist/esm/script/tapscript.js +17 -2
- package/dist/esm/script/vhtlc.js +35 -27
- package/dist/esm/storage/fileSystem.js +1 -1
- package/dist/esm/storage/inMemory.js +1 -1
- package/dist/esm/storage/indexedDB.js +1 -1
- package/dist/esm/storage/localStorage.js +1 -1
- package/dist/esm/tree/validation.js +1 -1
- package/dist/esm/utils/arkTransaction.js +5 -5
- package/dist/esm/utils/bip21.js +16 -3
- package/dist/esm/utils/syncCursors.js +4 -4
- package/dist/esm/utils/transaction.js +1 -1
- package/dist/esm/utils/transactionHistory.js +11 -11
- package/dist/esm/utils/unknownFields.js +3 -3
- package/dist/esm/wallet/asset-manager.js +4 -4
- package/dist/esm/wallet/batch.js +5 -5
- package/dist/esm/wallet/delegator.js +9 -8
- package/dist/esm/wallet/expo/background.js +3 -3
- package/dist/esm/wallet/expo/wallet.js +7 -7
- package/dist/esm/wallet/index.js +43 -0
- package/dist/esm/wallet/onchain.js +43 -5
- package/dist/esm/wallet/ramps.js +44 -14
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
- package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
- package/dist/esm/wallet/unroll.js +12 -8
- package/dist/esm/wallet/utils.js +1 -1
- package/dist/esm/wallet/vtxo-manager.js +121 -81
- package/dist/esm/wallet/wallet.js +125 -67
- package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
- package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
- package/dist/esm/worker/expo/taskRunner.js +3 -3
- package/dist/esm/worker/messageBus.js +3 -0
- package/dist/types/arkfee/estimator.d.ts +1 -1
- package/dist/types/arkfee/types.d.ts +2 -1
- package/dist/types/arknote/index.d.ts +44 -4
- package/dist/types/bip322/index.d.ts +1 -1
- package/dist/types/contracts/arkcontract.d.ts +1 -1
- package/dist/types/contracts/contractManager.d.ts +40 -63
- package/dist/types/contracts/contractWatcher.d.ts +39 -18
- package/dist/types/contracts/handlers/default.d.ts +1 -1
- package/dist/types/contracts/handlers/delegate.d.ts +1 -1
- package/dist/types/contracts/handlers/helpers.d.ts +1 -1
- package/dist/types/contracts/types.d.ts +36 -26
- package/dist/types/extension/asset/assetGroup.d.ts +92 -1
- package/dist/types/extension/asset/assetId.d.ts +67 -3
- package/dist/types/extension/asset/assetInput.d.ts +18 -0
- package/dist/types/extension/asset/assetOutput.d.ts +15 -0
- package/dist/types/extension/asset/assetRef.d.ts +66 -0
- package/dist/types/extension/asset/metadata.d.ts +15 -0
- package/dist/types/extension/asset/packet.d.ts +4 -1
- package/dist/types/extension/index.d.ts +1 -1
- package/dist/types/forfeit.d.ts +14 -0
- package/dist/types/identity/index.d.ts +16 -0
- package/dist/types/identity/seedIdentity.d.ts +8 -6
- package/dist/types/identity/singleKey.d.ts +4 -0
- package/dist/types/intent/index.d.ts +19 -6
- package/dist/types/providers/ark.d.ts +40 -2
- package/dist/types/providers/delegator.d.ts +54 -1
- package/dist/types/providers/expoArk.d.ts +2 -2
- package/dist/types/providers/indexer.d.ts +105 -2
- package/dist/types/providers/onchain.d.ts +62 -1
- package/dist/types/repositories/realm/schemas.d.ts +2 -2
- package/dist/types/repositories/realm/types.d.ts +2 -2
- package/dist/types/repositories/walletRepository.d.ts +16 -0
- package/dist/types/script/address.d.ts +35 -2
- package/dist/types/script/base.d.ts +66 -1
- package/dist/types/script/default.d.ts +3 -0
- package/dist/types/script/delegate.d.ts +4 -0
- package/dist/types/script/tapscript.d.ts +17 -2
- package/dist/types/script/vhtlc.d.ts +35 -27
- package/dist/types/storage/fileSystem.d.ts +1 -1
- package/dist/types/storage/inMemory.d.ts +1 -1
- package/dist/types/storage/index.d.ts +1 -1
- package/dist/types/storage/indexedDB.d.ts +1 -1
- package/dist/types/storage/localStorage.d.ts +1 -1
- package/dist/types/utils/arkTransaction.d.ts +3 -3
- package/dist/types/utils/bip21.d.ts +17 -0
- package/dist/types/utils/syncCursors.d.ts +4 -4
- package/dist/types/utils/transaction.d.ts +1 -1
- package/dist/types/utils/transactionHistory.d.ts +3 -3
- package/dist/types/utils/unknownFields.d.ts +5 -5
- package/dist/types/wallet/asset-manager.d.ts +3 -3
- package/dist/types/wallet/batch.d.ts +27 -7
- package/dist/types/wallet/delegator.d.ts +10 -0
- package/dist/types/wallet/expo/background.d.ts +4 -4
- package/dist/types/wallet/expo/wallet.d.ts +10 -10
- package/dist/types/wallet/index.d.ts +457 -25
- package/dist/types/wallet/onchain.d.ts +42 -4
- package/dist/types/wallet/ramps.d.ts +40 -10
- package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
- package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
- package/dist/types/wallet/unroll.d.ts +8 -6
- package/dist/types/wallet/vtxo-manager.d.ts +146 -93
- package/dist/types/wallet/wallet.d.ts +91 -33
- package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
- package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
- package/dist/types/worker/expo/taskRunner.d.ts +6 -6
- package/dist/types/worker/messageBus.d.ts +5 -3
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VtxoManager = exports.DEFAULT_SETTLEMENT_CONFIG = exports.DEFAULT_RENEWAL_CONFIG = exports.
|
|
3
|
+
exports.VtxoManager = exports.DEFAULT_SETTLEMENT_CONFIG = exports.DEFAULT_RENEWAL_CONFIG = exports.DEFAULT_THRESHOLD_MS = exports.DEFAULT_THRESHOLD_SECONDS = void 0;
|
|
4
4
|
exports.isVtxoExpiringSoon = isVtxoExpiringSoon;
|
|
5
5
|
exports.getExpiringAndRecoverableVtxos = getExpiringAndRecoverableVtxos;
|
|
6
6
|
const _1 = require(".");
|
|
@@ -10,29 +10,57 @@ const base_1 = require("@scure/base");
|
|
|
10
10
|
const base_2 = require("../script/base");
|
|
11
11
|
const transaction_1 = require("../utils/transaction");
|
|
12
12
|
const txSizeEstimator_1 = require("../utils/txSizeEstimator");
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Return whether a wallet exposes the properties required for boarding input sweep operations.
|
|
15
|
+
*
|
|
16
|
+
* @param wallet - Wallet to inspect
|
|
17
|
+
* @returns `true` when the wallet supports boarding input sweep operations.
|
|
18
|
+
*/
|
|
14
19
|
function isSweepCapable(wallet) {
|
|
15
20
|
return ("boardingTapscript" in wallet &&
|
|
16
21
|
"onchainProvider" in wallet &&
|
|
17
22
|
"network" in wallet);
|
|
18
23
|
}
|
|
19
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Assert that the wallet supports boarding input sweep operations.
|
|
26
|
+
*
|
|
27
|
+
* @param wallet - Wallet to inspect
|
|
28
|
+
* @throws Error if the wallet does not support boarding input sweep operations.
|
|
29
|
+
*/
|
|
20
30
|
function assertSweepCapable(wallet) {
|
|
21
31
|
if (!isSweepCapable(wallet)) {
|
|
22
32
|
throw new Error("Boarding UTXO sweep requires a Wallet instance with boardingTapscript, onchainProvider, and network");
|
|
23
33
|
}
|
|
24
34
|
}
|
|
25
|
-
|
|
26
|
-
exports.DEFAULT_THRESHOLD_SECONDS = 3 * 24 * 60 * 60;
|
|
35
|
+
/** Default renewal threshold in seconds (3 days). */
|
|
36
|
+
exports.DEFAULT_THRESHOLD_SECONDS = 3 * 24 * 60 * 60;
|
|
27
37
|
/**
|
|
28
|
-
* Default renewal
|
|
29
|
-
|
|
38
|
+
* Default renewal threshold in milliseconds (3 days).
|
|
39
|
+
*/
|
|
40
|
+
exports.DEFAULT_THRESHOLD_MS = exports.DEFAULT_THRESHOLD_SECONDS * 1000;
|
|
41
|
+
/**
|
|
42
|
+
* Default renewal configuration values.
|
|
43
|
+
*
|
|
44
|
+
* @see RenewalConfig
|
|
45
|
+
* @deprecated Leave `renewalConfig` undefined and use `settlementConfig` instead.
|
|
46
|
+
* @see SettlementConfig
|
|
30
47
|
*/
|
|
31
48
|
exports.DEFAULT_RENEWAL_CONFIG = {
|
|
32
49
|
thresholdMs: exports.DEFAULT_THRESHOLD_MS, // 3 days
|
|
33
50
|
};
|
|
34
51
|
/**
|
|
35
|
-
* Default settlement configuration values
|
|
52
|
+
* Default settlement configuration values.
|
|
53
|
+
*
|
|
54
|
+
* @see SettlementConfig
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const wallet = await Wallet.create({
|
|
59
|
+
* identity,
|
|
60
|
+
* arkServerUrl: 'https://arkade.computer',
|
|
61
|
+
* settlementConfig: DEFAULT_SETTLEMENT_CONFIG,
|
|
62
|
+
* })
|
|
63
|
+
* ```
|
|
36
64
|
*/
|
|
37
65
|
exports.DEFAULT_SETTLEMENT_CONFIG = {
|
|
38
66
|
vtxoThreshold: exports.DEFAULT_THRESHOLD_SECONDS,
|
|
@@ -44,23 +72,23 @@ function getDustAmount(wallet) {
|
|
|
44
72
|
return "dustAmount" in wallet ? wallet.dustAmount : 330n;
|
|
45
73
|
}
|
|
46
74
|
/**
|
|
47
|
-
* Filter
|
|
75
|
+
* Filter virtual outputs that are recoverable (swept and still spendable, or preconfirmed subdust)
|
|
48
76
|
*
|
|
49
77
|
* Recovery strategy:
|
|
50
|
-
* - Always recover swept
|
|
51
|
-
* - Only recover subdust preconfirmed
|
|
78
|
+
* - Always recover swept virtual outputs (they've been taken by the server)
|
|
79
|
+
* - Only recover subdust preconfirmed virtual outputs (to avoid locking liquidity on settled virtual outputs with long expiry)
|
|
52
80
|
*
|
|
53
|
-
* @param vtxos - Array of virtual
|
|
81
|
+
* @param vtxos - Array of virtual outputs to check
|
|
54
82
|
* @param dustAmount - Dust threshold to identify subdust
|
|
55
|
-
* @returns Array of recoverable
|
|
83
|
+
* @returns Array of recoverable virtual outputs
|
|
56
84
|
*/
|
|
57
85
|
function getRecoverableVtxos(vtxos, dustAmount) {
|
|
58
86
|
return vtxos.filter((vtxo) => {
|
|
59
|
-
// Always recover swept
|
|
87
|
+
// Always recover swept virtual outputs
|
|
60
88
|
if ((0, _1.isRecoverable)(vtxo)) {
|
|
61
89
|
return true;
|
|
62
90
|
}
|
|
63
|
-
// also include
|
|
91
|
+
// also include virtual outputs that are not swept but expired
|
|
64
92
|
if ((0, _1.isSpendable)(vtxo) && (0, _1.isExpired)(vtxo)) {
|
|
65
93
|
return true;
|
|
66
94
|
}
|
|
@@ -73,14 +101,14 @@ function getRecoverableVtxos(vtxos, dustAmount) {
|
|
|
73
101
|
});
|
|
74
102
|
}
|
|
75
103
|
/**
|
|
76
|
-
* Get recoverable
|
|
104
|
+
* Get recoverable virtual outputs including subdust outputs if the total value exceeds dust threshold.
|
|
77
105
|
*
|
|
78
|
-
* Decision is based on the combined total of ALL recoverable
|
|
106
|
+
* Decision is based on the combined total of ALL recoverable virtual outputs (regular + subdust),
|
|
79
107
|
* not just the subdust portion alone.
|
|
80
108
|
*
|
|
81
|
-
* @param vtxos - Array of virtual
|
|
109
|
+
* @param vtxos - Array of virtual outputs to check
|
|
82
110
|
* @param dustAmount - Dust threshold amount in satoshis
|
|
83
|
-
* @returns Object containing recoverable
|
|
111
|
+
* @returns Object containing recoverable virtual outputs and whether subdust should be included
|
|
84
112
|
*/
|
|
85
113
|
function getRecoverableWithSubdust(vtxos, dustAmount) {
|
|
86
114
|
const recoverableVtxos = getRecoverableVtxos(vtxos, dustAmount);
|
|
@@ -110,11 +138,11 @@ function getRecoverableWithSubdust(vtxos, dustAmount) {
|
|
|
110
138
|
};
|
|
111
139
|
}
|
|
112
140
|
/**
|
|
113
|
-
* Check if a
|
|
141
|
+
* Check if a virtual output is expiring soon based on threshold
|
|
114
142
|
*
|
|
115
|
-
* @param vtxo - The virtual
|
|
143
|
+
* @param vtxo - The virtual output to check
|
|
116
144
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
117
|
-
* @returns true if
|
|
145
|
+
* @returns true if virtual output expires within threshold, false otherwise
|
|
118
146
|
*/
|
|
119
147
|
function isVtxoExpiringSoon(vtxo, thresholdMs // in milliseconds
|
|
120
148
|
) {
|
|
@@ -135,12 +163,12 @@ function isVtxoExpiringSoon(vtxo, thresholdMs // in milliseconds
|
|
|
135
163
|
return batchExpiry - now <= realThresholdMs;
|
|
136
164
|
}
|
|
137
165
|
/**
|
|
138
|
-
* Filter
|
|
166
|
+
* Filter virtual outputs that are expiring soon or are recoverable/subdust
|
|
139
167
|
*
|
|
140
|
-
* @param vtxos - Array of virtual
|
|
168
|
+
* @param vtxos - Array of virtual outputs to check
|
|
141
169
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
142
170
|
* @param dustAmount - Dust threshold amount in satoshis
|
|
143
|
-
* @returns Array of
|
|
171
|
+
* @returns Array of virtual outputs expiring within threshold
|
|
144
172
|
*/
|
|
145
173
|
function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount) {
|
|
146
174
|
return vtxos.filter((vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) ||
|
|
@@ -190,24 +218,24 @@ class VtxoManager {
|
|
|
190
218
|
}
|
|
191
219
|
// ========== Recovery Methods ==========
|
|
192
220
|
/**
|
|
193
|
-
* Recover swept/expired
|
|
221
|
+
* Recover swept/expired virtual outputs by settling them back to the wallet's Arkade address.
|
|
194
222
|
*
|
|
195
223
|
* This method:
|
|
196
|
-
* 1. Fetches all
|
|
197
|
-
* 2. Filters for swept but still spendable
|
|
198
|
-
* 3. Includes subdust
|
|
199
|
-
* 4. Settles everything back to the wallet's
|
|
224
|
+
* 1. Fetches all virtual outputs (including recoverable ones)
|
|
225
|
+
* 2. Filters for swept but still spendable virtual outputs and preconfirmed subdust
|
|
226
|
+
* 3. Includes subdust virtual outputs if the total value >= dust threshold
|
|
227
|
+
* 4. Settles everything back to the wallet's Arkade address
|
|
200
228
|
*
|
|
201
|
-
* Note: Settled
|
|
229
|
+
* Note: Settled virtual outputs with long expiry are NOT recovered to avoid locking liquidity unnecessarily.
|
|
202
230
|
* Only preconfirmed subdust is recovered to consolidate small amounts.
|
|
203
231
|
*
|
|
204
232
|
* @param eventCallback - Optional callback to receive settlement events
|
|
205
233
|
* @returns Settlement transaction ID
|
|
206
|
-
* @throws Error if no recoverable
|
|
234
|
+
* @throws Error if no recoverable virtual outputs found
|
|
207
235
|
*
|
|
208
236
|
* @example
|
|
209
237
|
* ```typescript
|
|
210
|
-
* const manager =
|
|
238
|
+
* const manager = await wallet.getVtxoManager();
|
|
211
239
|
*
|
|
212
240
|
* // Simple recovery
|
|
213
241
|
* const txid = await manager.recoverVtxos();
|
|
@@ -219,20 +247,20 @@ class VtxoManager {
|
|
|
219
247
|
* ```
|
|
220
248
|
*/
|
|
221
249
|
async recoverVtxos(eventCallback) {
|
|
222
|
-
// Get all
|
|
250
|
+
// Get all virtual outputs including recoverable ones
|
|
223
251
|
const allVtxos = await this.wallet.getVtxos({
|
|
224
252
|
withRecoverable: true,
|
|
225
253
|
withUnrolled: false,
|
|
226
254
|
});
|
|
227
255
|
// Get dust amount from wallet
|
|
228
256
|
const dustAmount = getDustAmount(this.wallet);
|
|
229
|
-
// Filter recoverable
|
|
257
|
+
// Filter recoverable virtual outputs and handle subdust logic
|
|
230
258
|
const { vtxosToRecover, totalAmount } = getRecoverableWithSubdust(allVtxos, dustAmount);
|
|
231
259
|
if (vtxosToRecover.length === 0) {
|
|
232
260
|
throw new Error("No recoverable VTXOs found");
|
|
233
261
|
}
|
|
234
262
|
const arkAddress = await this.wallet.getAddress();
|
|
235
|
-
// Settle all recoverable
|
|
263
|
+
// Settle all recoverable virtual outputs back to the wallet
|
|
236
264
|
return this.wallet.settle({
|
|
237
265
|
inputs: vtxosToRecover,
|
|
238
266
|
outputs: [
|
|
@@ -252,13 +280,13 @@ class VtxoManager {
|
|
|
252
280
|
*
|
|
253
281
|
* @example
|
|
254
282
|
* ```typescript
|
|
255
|
-
* const manager =
|
|
283
|
+
* const manager = await wallet.getVtxoManager();
|
|
256
284
|
* const balance = await manager.getRecoverableBalance();
|
|
257
285
|
*
|
|
258
286
|
* if (balance.recoverable > 0n) {
|
|
259
287
|
* console.log(`You can recover ${balance.recoverable} sats`);
|
|
260
288
|
* if (balance.includesSubdust) {
|
|
261
|
-
* console.log(`This includes ${balance.subdust} sats from subdust
|
|
289
|
+
* console.log(`This includes ${balance.subdust} sats from subdust virtual outputs`);
|
|
262
290
|
* }
|
|
263
291
|
* }
|
|
264
292
|
* ```
|
|
@@ -283,17 +311,24 @@ class VtxoManager {
|
|
|
283
311
|
}
|
|
284
312
|
// ========== Renewal Methods ==========
|
|
285
313
|
/**
|
|
286
|
-
* Get
|
|
314
|
+
* Get virtual outputs that are expiring soon based on renewal configuration
|
|
287
315
|
*
|
|
288
316
|
* @param thresholdMs - Optional override for threshold in milliseconds
|
|
289
|
-
* @returns Array of expiring
|
|
317
|
+
* @returns Array of expiring virtual outputs, empty array if renewal is disabled or no virtual outputs expiring
|
|
290
318
|
*
|
|
291
319
|
* @example
|
|
292
320
|
* ```typescript
|
|
293
|
-
* const
|
|
321
|
+
* const wallet = await Wallet.create({
|
|
322
|
+
* identity,
|
|
323
|
+
* arkServerUrl: 'https://arkade.computer',
|
|
324
|
+
* settlementConfig: {
|
|
325
|
+
* vtxoThreshold: 86_400 // 24 hours
|
|
326
|
+
* },
|
|
327
|
+
* });
|
|
328
|
+
* const manager = await wallet.getVtxoManager();
|
|
294
329
|
* const expiringVtxos = await manager.getExpiringVtxos();
|
|
295
330
|
* if (expiringVtxos.length > 0) {
|
|
296
|
-
* console.log(`${expiringVtxos.length}
|
|
331
|
+
* console.log(`${expiringVtxos.length} virtual outputs expiring soon`);
|
|
297
332
|
* }
|
|
298
333
|
* ```
|
|
299
334
|
*/
|
|
@@ -321,20 +356,20 @@ class VtxoManager {
|
|
|
321
356
|
return getExpiringAndRecoverableVtxos(vtxos, threshold, getDustAmount(this.wallet));
|
|
322
357
|
}
|
|
323
358
|
/**
|
|
324
|
-
* Renew expiring
|
|
359
|
+
* Renew expiring virtual outputs by settling them back to the wallet's address
|
|
325
360
|
*
|
|
326
|
-
* This method collects all expiring spendable
|
|
361
|
+
* This method collects all expiring spendable virtual outputs (including recoverable ones) and settles
|
|
327
362
|
* them back to the wallet, effectively refreshing their expiration time. This is the
|
|
328
|
-
* primary way to prevent
|
|
363
|
+
* primary way to prevent virtual outputs from expiring.
|
|
329
364
|
*
|
|
330
365
|
* @param eventCallback - Optional callback for settlement events
|
|
331
366
|
* @returns Settlement transaction ID
|
|
332
|
-
* @throws Error if no
|
|
367
|
+
* @throws Error if no virtual outputs available to renew
|
|
333
368
|
* @throws Error if total amount is below dust threshold
|
|
334
369
|
*
|
|
335
370
|
* @example
|
|
336
371
|
* ```typescript
|
|
337
|
-
* const manager =
|
|
372
|
+
* const manager = await wallet.getVtxoManager();
|
|
338
373
|
*
|
|
339
374
|
* // Simple renewal
|
|
340
375
|
* const txid = await manager.renewVtxos();
|
|
@@ -351,7 +386,7 @@ class VtxoManager {
|
|
|
351
386
|
}
|
|
352
387
|
this.renewalInProgress = true;
|
|
353
388
|
try {
|
|
354
|
-
// Get all
|
|
389
|
+
// Get all virtual outputs (including recoverable ones)
|
|
355
390
|
// Use default threshold to bypass settlementConfig gate (manual API should always work)
|
|
356
391
|
const vtxos = await this.getExpiringVtxos(this.settlementConfig !== false &&
|
|
357
392
|
this.settlementConfig?.vtxoThreshold !== undefined
|
|
@@ -384,21 +419,21 @@ class VtxoManager {
|
|
|
384
419
|
this.renewalInProgress = false;
|
|
385
420
|
}
|
|
386
421
|
}
|
|
387
|
-
// ========== Boarding
|
|
422
|
+
// ========== Boarding Input Sweep Methods ==========
|
|
388
423
|
/**
|
|
389
|
-
* Get boarding
|
|
424
|
+
* Get boarding inputs whose timelock has expired.
|
|
390
425
|
*
|
|
391
|
-
* These
|
|
426
|
+
* These inputs can no longer be onboarded cooperatively via `settle()` and
|
|
392
427
|
* must be swept back to a fresh boarding address using the unilateral exit path.
|
|
393
428
|
*
|
|
394
|
-
* @returns Array of expired boarding
|
|
429
|
+
* @returns Array of expired boarding inputs
|
|
395
430
|
*
|
|
396
431
|
* @example
|
|
397
432
|
* ```typescript
|
|
398
|
-
* const manager =
|
|
433
|
+
* const manager = await wallet.getVtxoManager();
|
|
399
434
|
* const expired = await manager.getExpiredBoardingUtxos();
|
|
400
435
|
* if (expired.length > 0) {
|
|
401
|
-
* console.log(`${expired.length} expired boarding
|
|
436
|
+
* console.log(`${expired.length} expired boarding inputs to sweep`);
|
|
402
437
|
* }
|
|
403
438
|
* ```
|
|
404
439
|
*/
|
|
@@ -414,31 +449,36 @@ class VtxoManager {
|
|
|
414
449
|
return boardingUtxos.filter((utxo) => (0, arkTransaction_1.hasBoardingTxExpired)(utxo, boardingTimelock, chainTipHeight));
|
|
415
450
|
}
|
|
416
451
|
/**
|
|
417
|
-
* Sweep expired boarding
|
|
418
|
-
* the unilateral exit path (
|
|
452
|
+
* Sweep expired boarding inputs back to a fresh boarding address via
|
|
453
|
+
* the unilateral exit path (onchain self-spend).
|
|
419
454
|
*
|
|
420
|
-
* This builds a raw
|
|
421
|
-
* - Uses all expired boarding
|
|
455
|
+
* This builds a raw onchain transaction that:
|
|
456
|
+
* - Uses all expired boarding inputs as inputs (spent via the CSV exit script path)
|
|
422
457
|
* - Has a single output to the wallet's boarding address (restarts the timelock)
|
|
423
|
-
* - Batches multiple expired
|
|
458
|
+
* - Batches multiple expired boarding inputs into one transaction
|
|
424
459
|
* - Skips the sweep if the output after fees would be below dust
|
|
425
460
|
*
|
|
426
|
-
* No
|
|
461
|
+
* No Arkade server involvement is needed — this is a pure onchain transaction.
|
|
427
462
|
*
|
|
428
463
|
* @returns The broadcast transaction ID
|
|
429
|
-
* @throws Error if no expired boarding
|
|
464
|
+
* @throws Error if no expired boarding inputs are found
|
|
430
465
|
* @throws Error if output after fees is below dust (not economical to sweep)
|
|
431
|
-
* @throws Error if boarding
|
|
466
|
+
* @throws Error if boarding input sweep is not enabled in settlementConfig
|
|
432
467
|
*
|
|
433
468
|
* @example
|
|
434
469
|
* ```typescript
|
|
435
|
-
* const
|
|
436
|
-
*
|
|
470
|
+
* const wallet = await Wallet.create({
|
|
471
|
+
* identity,
|
|
472
|
+
* arkServerUrl: 'https://arkade.computer',
|
|
473
|
+
* settlementConfig: {
|
|
474
|
+
* boardingUtxoSweep: true,
|
|
475
|
+
* },
|
|
437
476
|
* });
|
|
477
|
+
* const manager = await wallet.getVtxoManager();
|
|
438
478
|
*
|
|
439
479
|
* try {
|
|
440
480
|
* const txid = await manager.sweepExpiredBoardingUtxos();
|
|
441
|
-
* console.log('Swept expired boarding
|
|
481
|
+
* console.log('Swept expired boarding inputs:', txid);
|
|
442
482
|
* } catch (e) {
|
|
443
483
|
* console.log('No sweep needed or not economical');
|
|
444
484
|
* }
|
|
@@ -452,7 +492,7 @@ class VtxoManager {
|
|
|
452
492
|
throw new Error("Boarding UTXO sweep is not enabled in settlementConfig");
|
|
453
493
|
}
|
|
454
494
|
const allExpired = await this.getExpiredBoardingUtxos(prefetchedUtxos);
|
|
455
|
-
// Filter out
|
|
495
|
+
// Filter out inputs already swept (tx broadcast but not yet confirmed).
|
|
456
496
|
const expiredUtxos = allExpired.filter((u) => !this.sweptBoardingUtxos.has(`${u.txid}:${u.vout}`));
|
|
457
497
|
if (expiredUtxos.length === 0) {
|
|
458
498
|
throw new Error("No expired boarding UTXOs to sweep");
|
|
@@ -503,12 +543,12 @@ class VtxoManager {
|
|
|
503
543
|
signedTx.finalize();
|
|
504
544
|
// Broadcast
|
|
505
545
|
const txid = await this.getOnchainProvider().broadcastTransaction(signedTx.hex);
|
|
506
|
-
// Mark
|
|
546
|
+
// Mark boarding inputs as swept to prevent duplicate broadcasts on next poll
|
|
507
547
|
for (const u of expiredUtxos) {
|
|
508
548
|
this.sweptBoardingUtxos.add(`${u.txid}:${u.vout}`);
|
|
509
549
|
}
|
|
510
550
|
// Mark the sweep output as "known" so the next poll doesn't try to
|
|
511
|
-
// auto-settle it back into
|
|
551
|
+
// auto-settle it back into Arkade (it lands at the same boarding address).
|
|
512
552
|
this.knownBoardingUtxos.add(`${txid}:0`);
|
|
513
553
|
return txid;
|
|
514
554
|
}
|
|
@@ -532,7 +572,7 @@ class VtxoManager {
|
|
|
532
572
|
getBoardingOutputScript() {
|
|
533
573
|
return this.getSweepWallet().boardingTapscript.pkScript;
|
|
534
574
|
}
|
|
535
|
-
/** Returns the
|
|
575
|
+
/** Returns the onchain provider for fee estimation and broadcasting. */
|
|
536
576
|
getOnchainProvider() {
|
|
537
577
|
return this.getSweepWallet().onchainProvider;
|
|
538
578
|
}
|
|
@@ -548,7 +588,7 @@ class VtxoManager {
|
|
|
548
588
|
if (this.settlementConfig === false) {
|
|
549
589
|
return undefined;
|
|
550
590
|
}
|
|
551
|
-
// Start polling for boarding
|
|
591
|
+
// Start polling for boarding inputs independently of contract manager
|
|
552
592
|
// SSE setup. Use a short delay to let the wallet finish construction.
|
|
553
593
|
this.startupPollTimeoutId = setTimeout(() => {
|
|
554
594
|
if (this.disposed)
|
|
@@ -572,18 +612,18 @@ class VtxoManager {
|
|
|
572
612
|
this.renewVtxos().catch((e) => {
|
|
573
613
|
if (e instanceof Error) {
|
|
574
614
|
if (e.message.includes("No VTXOs available to renew")) {
|
|
575
|
-
// Not an error, just no
|
|
615
|
+
// Not an error, just no virtual outputs eligible for renewal.
|
|
576
616
|
return;
|
|
577
617
|
}
|
|
578
618
|
if (e.message.includes("is below dust threshold")) {
|
|
579
619
|
// Not an error, just below dust threshold.
|
|
580
|
-
// As more
|
|
620
|
+
// As more virtual outputs are received, the threshold will be raised.
|
|
581
621
|
return;
|
|
582
622
|
}
|
|
583
623
|
if (e.message.includes("VTXO_ALREADY_REGISTERED") ||
|
|
584
624
|
e.message.includes("VTXO_ALREADY_SPENT") ||
|
|
585
625
|
e.message.includes("duplicated input")) {
|
|
586
|
-
//
|
|
626
|
+
// Virtual output is already being used in a concurrent
|
|
587
627
|
// user-initiated operation. Skip silently — the
|
|
588
628
|
// wallet's tx lock serializes these, but the
|
|
589
629
|
// renewal will retry on the next cycle.
|
|
@@ -619,8 +659,8 @@ class VtxoManager {
|
|
|
619
659
|
}
|
|
620
660
|
/**
|
|
621
661
|
* Starts a polling loop that:
|
|
622
|
-
* 1. Auto-settles new boarding
|
|
623
|
-
* 2. Sweeps expired boarding
|
|
662
|
+
* 1. Auto-settles new boarding inputs into Arkade
|
|
663
|
+
* 2. Sweeps expired boarding inputs (when boardingUtxoSweep is enabled)
|
|
624
664
|
*
|
|
625
665
|
* Uses setTimeout chaining (not setInterval) so a slow/blocked poll
|
|
626
666
|
* cannot stack up and the next delay can incorporate backoff.
|
|
@@ -638,7 +678,7 @@ class VtxoManager {
|
|
|
638
678
|
this.pollTimeoutId = setTimeout(() => this.pollBoardingUtxos(), delay);
|
|
639
679
|
}
|
|
640
680
|
async pollBoardingUtxos() {
|
|
641
|
-
// Guard: wallet must support boarding
|
|
681
|
+
// Guard: wallet must support boarding input + sweep operations
|
|
642
682
|
if (!isSweepCapable(this.wallet))
|
|
643
683
|
return;
|
|
644
684
|
// Skip if disposed or a previous poll is still running
|
|
@@ -653,11 +693,11 @@ class VtxoManager {
|
|
|
653
693
|
this.pollDone = { promise, resolve: resolve };
|
|
654
694
|
let hadError = false;
|
|
655
695
|
try {
|
|
656
|
-
// Fetch boarding
|
|
696
|
+
// Fetch boarding inputs once for the entire poll cycle so that
|
|
657
697
|
// settle and sweep don't each hit the network independently.
|
|
658
698
|
const boardingUtxos = await this.wallet.getBoardingUtxos();
|
|
659
|
-
// Settle new (unexpired)
|
|
660
|
-
// Sequential to avoid racing for the same
|
|
699
|
+
// Settle new (unexpired) boarding inputs first, then sweep expired ones.
|
|
700
|
+
// Sequential to avoid racing for the same inputs.
|
|
661
701
|
try {
|
|
662
702
|
await this.settleBoardingUtxos(boardingUtxos);
|
|
663
703
|
}
|
|
@@ -699,16 +739,16 @@ class VtxoManager {
|
|
|
699
739
|
}
|
|
700
740
|
}
|
|
701
741
|
/**
|
|
702
|
-
* Auto-settle new (unexpired) boarding
|
|
742
|
+
* Auto-settle new (unexpired) boarding inputs into Arkade.
|
|
703
743
|
* Skips UTXOs that are already expired (those are handled by sweep).
|
|
704
744
|
* Only settles UTXOs not already in-flight (tracked in knownBoardingUtxos).
|
|
705
745
|
* UTXOs are marked as known only after a successful settle, so failed
|
|
706
746
|
* attempts will be retried on the next poll.
|
|
707
747
|
*/
|
|
708
748
|
async settleBoardingUtxos(boardingUtxos) {
|
|
709
|
-
// Exclude expired
|
|
749
|
+
// Exclude expired boarding inputs — those should be swept, not settled.
|
|
710
750
|
// If we can't determine expired status, bail out entirely to avoid
|
|
711
|
-
// accidentally settling expired
|
|
751
|
+
// accidentally settling expired inputs (which would conflict with sweep).
|
|
712
752
|
let expiredSet;
|
|
713
753
|
try {
|
|
714
754
|
const boardingTimelock = this.getBoardingTimelock();
|