@arkade-os/sdk 0.3.1-alpha.4 → 0.3.1-alpha.6
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 +11 -27
- package/dist/cjs/forfeit.js +2 -5
- package/dist/cjs/identity/singleKey.js +4 -5
- package/dist/cjs/index.js +5 -4
- package/dist/cjs/intent/index.js +3 -8
- package/dist/cjs/providers/onchain.js +19 -20
- package/dist/cjs/repositories/walletRepository.js +64 -2
- package/dist/cjs/script/base.js +14 -5
- package/dist/cjs/utils/arkTransaction.js +3 -5
- package/dist/cjs/utils/transaction.js +28 -0
- package/dist/cjs/wallet/onchain.js +4 -4
- package/dist/cjs/wallet/serviceWorker/worker.js +19 -2
- package/dist/cjs/wallet/unroll.js +3 -4
- package/dist/cjs/wallet/utils.js +9 -0
- package/dist/cjs/wallet/vtxo-manager.js +31 -89
- package/dist/cjs/wallet/wallet.js +11 -13
- package/dist/esm/forfeit.js +1 -4
- package/dist/esm/identity/singleKey.js +3 -4
- package/dist/esm/index.js +3 -3
- package/dist/esm/intent/index.js +2 -7
- package/dist/esm/providers/onchain.js +19 -20
- package/dist/esm/repositories/walletRepository.js +64 -2
- package/dist/esm/script/base.js +11 -2
- package/dist/esm/utils/arkTransaction.js +3 -5
- package/dist/esm/utils/transaction.js +24 -0
- package/dist/esm/wallet/onchain.js +3 -3
- package/dist/esm/wallet/serviceWorker/worker.js +21 -4
- package/dist/esm/wallet/unroll.js +4 -5
- package/dist/esm/wallet/utils.js +8 -0
- package/dist/esm/wallet/vtxo-manager.js +30 -85
- package/dist/esm/wallet/wallet.js +12 -14
- package/dist/types/forfeit.d.ts +1 -1
- package/dist/types/identity/index.d.ts +1 -1
- package/dist/types/identity/singleKey.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/intent/index.d.ts +1 -1
- package/dist/types/providers/onchain.d.ts +6 -2
- package/dist/types/repositories/walletRepository.d.ts +9 -1
- package/dist/types/script/base.d.ts +2 -0
- package/dist/types/utils/arkTransaction.d.ts +1 -3
- package/dist/types/utils/transaction.d.ts +13 -0
- package/dist/types/wallet/onchain.d.ts +1 -1
- package/dist/types/wallet/serviceWorker/worker.d.ts +4 -0
- package/dist/types/wallet/unroll.d.ts +1 -1
- package/dist/types/wallet/utils.d.ts +2 -1
- package/dist/types/wallet/vtxo-manager.d.ts +7 -35
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { base64, hex } from "@scure/base";
|
|
2
|
-
import { SigHash,
|
|
2
|
+
import { SigHash, TaprootControlBlock } from "@scure/btc-signer";
|
|
3
3
|
import { ChainTxType } from '../providers/indexer.js';
|
|
4
4
|
import { VtxoScript } from '../script/base.js';
|
|
5
5
|
import { TxWeightEstimator } from '../utils/txSizeEstimator.js';
|
|
6
6
|
import { Wallet } from './wallet.js';
|
|
7
|
+
import { Transaction } from '../utils/transaction.js';
|
|
7
8
|
export var Unroll;
|
|
8
9
|
(function (Unroll) {
|
|
9
10
|
let StepType;
|
|
@@ -102,9 +103,7 @@ export var Unroll;
|
|
|
102
103
|
if (virtualTxs.txs.length === 0) {
|
|
103
104
|
throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
|
|
104
105
|
}
|
|
105
|
-
const tx = Transaction.fromPSBT(base64.decode(virtualTxs.txs[0])
|
|
106
|
-
allowUnknownInputs: true,
|
|
107
|
-
});
|
|
106
|
+
const tx = Transaction.fromPSBT(base64.decode(virtualTxs.txs[0]));
|
|
108
107
|
// finalize the tree transaction
|
|
109
108
|
if (nextTxToBroadcast.type === ChainTxType.TREE) {
|
|
110
109
|
const input = tx.getInput(0);
|
|
@@ -197,7 +196,7 @@ export var Unroll;
|
|
|
197
196
|
});
|
|
198
197
|
txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, TaprootControlBlock.encode(spendingLeaf[0]).length);
|
|
199
198
|
}
|
|
200
|
-
const tx = new Transaction({
|
|
199
|
+
const tx = new Transaction({ version: 2 });
|
|
201
200
|
for (const input of inputs) {
|
|
202
201
|
tx.addInput(input);
|
|
203
202
|
}
|
package/dist/esm/wallet/utils.js
CHANGED
|
@@ -6,3 +6,11 @@ export function extendVirtualCoin(wallet, vtxo) {
|
|
|
6
6
|
tapTree: wallet.offchainTapscript.encode(),
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
+
export function extendCoin(wallet, utxo) {
|
|
10
|
+
return {
|
|
11
|
+
...utxo,
|
|
12
|
+
forfeitTapLeafScript: wallet.boardingTapscript.forfeit(),
|
|
13
|
+
intentTapLeafScript: wallet.boardingTapscript.exit(),
|
|
14
|
+
tapTree: wallet.boardingTapscript.encode(),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -5,6 +5,9 @@ import { isRecoverable, isSubdust } from './index.js';
|
|
|
5
5
|
export const DEFAULT_RENEWAL_CONFIG = {
|
|
6
6
|
thresholdPercentage: 10,
|
|
7
7
|
};
|
|
8
|
+
function getDustAmount(wallet) {
|
|
9
|
+
return "dustAmount" in wallet ? wallet.dustAmount : 330n;
|
|
10
|
+
}
|
|
8
11
|
/**
|
|
9
12
|
* Filter VTXOs that are recoverable (swept and still spendable, or preconfirmed subdust)
|
|
10
13
|
*
|
|
@@ -74,80 +77,35 @@ function getRecoverableWithSubdust(vtxos, dustAmount) {
|
|
|
74
77
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
75
78
|
* @returns true if VTXO expires within threshold, false otherwise
|
|
76
79
|
*/
|
|
77
|
-
export function isVtxoExpiringSoon(vtxo,
|
|
80
|
+
export function isVtxoExpiringSoon(vtxo, percentage) {
|
|
78
81
|
const { batchExpiry } = vtxo.virtualStatus;
|
|
79
|
-
// No expiry set means it doesn't expire
|
|
80
82
|
if (!batchExpiry) {
|
|
81
|
-
return false;
|
|
83
|
+
return false; // it doesn't expire
|
|
82
84
|
}
|
|
83
85
|
const now = Date.now();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
if (batchExpiry <= now) {
|
|
87
|
+
return false; // already expired
|
|
88
|
+
}
|
|
89
|
+
// It shouldn't happen, but let's be safe
|
|
90
|
+
if (!vtxo.createdAt) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const duration = batchExpiry - vtxo.createdAt.getTime();
|
|
94
|
+
const softExpiry = batchExpiry - (duration * percentage) / 100;
|
|
95
|
+
return softExpiry > 0 && softExpiry <= now;
|
|
86
96
|
}
|
|
87
97
|
/**
|
|
88
|
-
* Filter VTXOs that are expiring soon
|
|
98
|
+
* Filter VTXOs that are expiring soon or are recoverable/subdust
|
|
89
99
|
*
|
|
90
100
|
* @param vtxos - Array of virtual coins to check
|
|
91
101
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
102
|
+
* @param dustAmount - Dust threshold amount in satoshis
|
|
92
103
|
* @returns Array of VTXOs expiring within threshold
|
|
93
104
|
*/
|
|
94
|
-
export function
|
|
95
|
-
return vtxos.filter((vtxo) => isVtxoExpiringSoon(vtxo,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* Calculate expiry threshold in milliseconds based on batch expiry and percentage
|
|
99
|
-
*
|
|
100
|
-
* @param batchExpiry - Batch expiry timestamp in milliseconds
|
|
101
|
-
* @param percentage - Percentage of total time (0-100)
|
|
102
|
-
* @returns Threshold timestamp in milliseconds from now
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* // VTXO expires in 10 days, threshold is 10%
|
|
106
|
-
* const expiry = Date.now() + 10 * 24 * 60 * 60 * 1000;
|
|
107
|
-
* const threshold = calculateExpiryThreshold(expiry, 10);
|
|
108
|
-
* // Returns 1 day in milliseconds (10% of 10 days)
|
|
109
|
-
*/
|
|
110
|
-
export function calculateExpiryThreshold(batchExpiry, percentage) {
|
|
111
|
-
if (percentage < 0 || percentage > 100) {
|
|
112
|
-
throw new Error("Percentage must be between 0 and 100");
|
|
113
|
-
}
|
|
114
|
-
const now = Date.now();
|
|
115
|
-
const totalTime = batchExpiry - now;
|
|
116
|
-
if (totalTime <= 0) {
|
|
117
|
-
// Already expired
|
|
118
|
-
return 0;
|
|
119
|
-
}
|
|
120
|
-
// Calculate threshold as percentage of total time
|
|
121
|
-
return Math.floor((totalTime * percentage) / 100);
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Get the minimum expiry time from a list of VTXOs
|
|
125
|
-
*
|
|
126
|
-
* @param vtxos - Array of virtual coins
|
|
127
|
-
* @returns Minimum batch expiry timestamp, or undefined if no VTXOs have expiry
|
|
128
|
-
*/
|
|
129
|
-
export function getMinimumExpiry(vtxos) {
|
|
130
|
-
const expiries = vtxos
|
|
131
|
-
.map((v) => v.virtualStatus.batchExpiry)
|
|
132
|
-
.filter((e) => e !== undefined);
|
|
133
|
-
if (expiries.length === 0) {
|
|
134
|
-
return undefined;
|
|
135
|
-
}
|
|
136
|
-
return Math.min(...expiries);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Calculate dynamic threshold based on the earliest expiring VTXO
|
|
140
|
-
*
|
|
141
|
-
* @param vtxos - Array of virtual coins
|
|
142
|
-
* @param percentage - Percentage of time until expiry (0-100)
|
|
143
|
-
* @returns Threshold in milliseconds, or undefined if no VTXOs have expiry
|
|
144
|
-
*/
|
|
145
|
-
export function calculateDynamicThreshold(vtxos, percentage) {
|
|
146
|
-
const minExpiry = getMinimumExpiry(vtxos);
|
|
147
|
-
if (!minExpiry) {
|
|
148
|
-
return undefined;
|
|
149
|
-
}
|
|
150
|
-
return calculateExpiryThreshold(minExpiry, percentage);
|
|
105
|
+
export function getExpiringAndRecoverableVtxos(vtxos, percentage, dustAmount) {
|
|
106
|
+
return vtxos.filter((vtxo) => isVtxoExpiringSoon(vtxo, percentage) ||
|
|
107
|
+
isRecoverable(vtxo) ||
|
|
108
|
+
isSubdust(vtxo, dustAmount));
|
|
151
109
|
}
|
|
152
110
|
/**
|
|
153
111
|
* VtxoManager is a unified class for managing VTXO lifecycle operations including
|
|
@@ -228,9 +186,7 @@ export class VtxoManager {
|
|
|
228
186
|
withUnrolled: false,
|
|
229
187
|
});
|
|
230
188
|
// Get dust amount from wallet
|
|
231
|
-
const dustAmount =
|
|
232
|
-
? this.wallet.dustAmount
|
|
233
|
-
: 1000n;
|
|
189
|
+
const dustAmount = getDustAmount(this.wallet);
|
|
234
190
|
// Filter recoverable VTXOs and handle subdust logic
|
|
235
191
|
const { vtxosToRecover, includesSubdust, totalAmount } = getRecoverableWithSubdust(allVtxos, dustAmount);
|
|
236
192
|
if (vtxosToRecover.length === 0) {
|
|
@@ -273,9 +229,7 @@ export class VtxoManager {
|
|
|
273
229
|
withRecoverable: true,
|
|
274
230
|
withUnrolled: false,
|
|
275
231
|
});
|
|
276
|
-
const dustAmount =
|
|
277
|
-
? this.wallet.dustAmount
|
|
278
|
-
: 1000n;
|
|
232
|
+
const dustAmount = getDustAmount(this.wallet);
|
|
279
233
|
const { vtxosToRecover, includesSubdust, totalAmount } = getRecoverableWithSubdust(allVtxos, dustAmount);
|
|
280
234
|
// Calculate subdust amount separately for reporting
|
|
281
235
|
const subdustAmount = vtxosToRecover
|
|
@@ -305,23 +259,16 @@ export class VtxoManager {
|
|
|
305
259
|
* ```
|
|
306
260
|
*/
|
|
307
261
|
async getExpiringVtxos(thresholdPercentage) {
|
|
308
|
-
|
|
309
|
-
return [];
|
|
310
|
-
}
|
|
311
|
-
const vtxos = await this.wallet.getVtxos();
|
|
262
|
+
const vtxos = await this.wallet.getVtxos({ withRecoverable: true });
|
|
312
263
|
const percentage = thresholdPercentage ??
|
|
313
|
-
this.renewalConfig
|
|
264
|
+
this.renewalConfig?.thresholdPercentage ??
|
|
314
265
|
DEFAULT_RENEWAL_CONFIG.thresholdPercentage;
|
|
315
|
-
|
|
316
|
-
if (!threshold) {
|
|
317
|
-
return [];
|
|
318
|
-
}
|
|
319
|
-
return getExpiringVtxos(vtxos, threshold);
|
|
266
|
+
return getExpiringAndRecoverableVtxos(vtxos, percentage, getDustAmount(this.wallet));
|
|
320
267
|
}
|
|
321
268
|
/**
|
|
322
|
-
* Renew VTXOs by settling them back to the wallet's address
|
|
269
|
+
* Renew expiring VTXOs by settling them back to the wallet's address
|
|
323
270
|
*
|
|
324
|
-
* This method collects all spendable VTXOs (including recoverable ones) and settles
|
|
271
|
+
* This method collects all expiring spendable VTXOs (including recoverable ones) and settles
|
|
325
272
|
* them back to the wallet, effectively refreshing their expiration time. This is the
|
|
326
273
|
* primary way to prevent VTXOs from expiring.
|
|
327
274
|
*
|
|
@@ -345,15 +292,13 @@ export class VtxoManager {
|
|
|
345
292
|
*/
|
|
346
293
|
async renewVtxos(eventCallback) {
|
|
347
294
|
// Get all VTXOs (including recoverable ones)
|
|
348
|
-
const vtxos = await this.
|
|
295
|
+
const vtxos = await this.getExpiringVtxos();
|
|
349
296
|
if (vtxos.length === 0) {
|
|
350
297
|
throw new Error("No VTXOs available to renew");
|
|
351
298
|
}
|
|
352
299
|
const totalAmount = vtxos.reduce((sum, vtxo) => sum + vtxo.value, 0);
|
|
353
300
|
// Get dust amount from wallet
|
|
354
|
-
const dustAmount =
|
|
355
|
-
? this.wallet.dustAmount
|
|
356
|
-
: 1000n;
|
|
301
|
+
const dustAmount = getDustAmount(this.wallet);
|
|
357
302
|
// Check if total amount is above dust threshold
|
|
358
303
|
if (BigInt(totalAmount) < dustAmount) {
|
|
359
304
|
throw new Error(`Total amount ${totalAmount} is below dust threshold ${dustAmount}`);
|
|
@@ -24,7 +24,7 @@ import { ConditionWitness, VtxoTaprootTree } from '../utils/unknownFields.js';
|
|
|
24
24
|
import { InMemoryStorageAdapter } from '../storage/inMemory.js';
|
|
25
25
|
import { WalletRepositoryImpl, } from '../repositories/walletRepository.js';
|
|
26
26
|
import { ContractRepositoryImpl, } from '../repositories/contractRepository.js';
|
|
27
|
-
import { extendVirtualCoin } from './utils.js';
|
|
27
|
+
import { extendCoin, extendVirtualCoin } from './utils.js';
|
|
28
28
|
/**
|
|
29
29
|
* Main wallet implementation for Bitcoin transactions with Ark protocol support.
|
|
30
30
|
* The wallet does not store any data locally and relies on Ark and onchain
|
|
@@ -333,15 +333,12 @@ export class Wallet {
|
|
|
333
333
|
async getBoardingUtxos() {
|
|
334
334
|
const boardingAddress = await this.getBoardingAddress();
|
|
335
335
|
const boardingUtxos = await this.onchainProvider.getCoins(boardingAddress);
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
intentTapLeafScript: exit,
|
|
343
|
-
tapTree: encodedBoardingTapscript,
|
|
344
|
-
}));
|
|
336
|
+
const utxos = boardingUtxos.map((utxo) => {
|
|
337
|
+
return extendCoin(this, utxo);
|
|
338
|
+
});
|
|
339
|
+
// Save boardingUtxos using unified repository
|
|
340
|
+
await this.walletRepository.saveUtxos(boardingAddress, utxos);
|
|
341
|
+
return utxos;
|
|
345
342
|
}
|
|
346
343
|
async sendBitcoin(params) {
|
|
347
344
|
if (params.amount <= 0) {
|
|
@@ -761,8 +758,6 @@ export class Wallet {
|
|
|
761
758
|
const vtxo = vtxos.find((vtxo) => vtxo.txid === input.txid && vtxo.vout === input.vout);
|
|
762
759
|
// boarding utxo, we need to sign the settlement tx
|
|
763
760
|
if (!vtxo) {
|
|
764
|
-
hasBoardingUtxos = true;
|
|
765
|
-
const inputIndexes = [];
|
|
766
761
|
for (let i = 0; i < settlementPsbt.inputsLength; i++) {
|
|
767
762
|
const settlementInput = settlementPsbt.getInput(i);
|
|
768
763
|
if (!settlementInput.txid ||
|
|
@@ -778,9 +773,12 @@ export class Wallet {
|
|
|
778
773
|
settlementPsbt.updateInput(i, {
|
|
779
774
|
tapLeafScript: [input.forfeitTapLeafScript],
|
|
780
775
|
});
|
|
781
|
-
|
|
776
|
+
settlementPsbt = await this.identity.sign(settlementPsbt, [
|
|
777
|
+
i,
|
|
778
|
+
]);
|
|
779
|
+
hasBoardingUtxos = true;
|
|
780
|
+
break;
|
|
782
781
|
}
|
|
783
|
-
settlementPsbt = await this.identity.sign(settlementPsbt, inputIndexes);
|
|
784
782
|
continue;
|
|
785
783
|
}
|
|
786
784
|
if (isRecoverable(vtxo) || isSubdust(vtxo, this.dustAmount)) {
|
package/dist/types/forfeit.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Transaction } from "
|
|
1
|
+
import { Transaction } from "./utils/transaction";
|
|
2
2
|
import { TransactionInputUpdate } from "@scure/btc-signer/psbt.js";
|
|
3
3
|
export declare function buildForfeitTx(inputs: TransactionInputUpdate[], forfeitPkScript: Uint8Array, txLocktime?: number): Transaction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer/transaction.js";
|
|
2
1
|
import { Identity } from ".";
|
|
2
|
+
import { Transaction } from "../utils/transaction";
|
|
3
3
|
import { SignerSession } from "../tree/signingSession";
|
|
4
4
|
/**
|
|
5
5
|
* In-memory single key implementation for Bitcoin transaction signing.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Transaction } from "
|
|
1
|
+
import { Transaction } from "./utils/transaction";
|
|
2
2
|
import { SingleKey } from "./identity/singleKey";
|
|
3
3
|
import { Identity } from "./identity";
|
|
4
4
|
import { ArkAddress } from "./script/address";
|
|
5
5
|
import { VHTLC } from "./script/vhtlc";
|
|
6
6
|
import { DefaultVtxo } from "./script/default";
|
|
7
|
-
import { VtxoScript, EncodedVtxoScript, TapLeafScript } from "./script/base";
|
|
7
|
+
import { VtxoScript, EncodedVtxoScript, TapLeafScript, TapTreeCoder } from "./script/base";
|
|
8
8
|
import { TxType, IWallet, WalletConfig, ProviderClass, ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, WalletBalance, SendBitcoinParams, Recipient, SettleParams, Status, VirtualStatus, Outpoint, VirtualCoin, TxKey, GetVtxosFilter, TapLeaves } from "./wallet";
|
|
9
9
|
import { Wallet, waitForIncomingFunds, IncomingFunds } from "./wallet/wallet";
|
|
10
10
|
import { TxTree, TxTreeNode } from "./tree/txTree";
|
|
@@ -33,5 +33,5 @@ import { Unroll } from "./wallet/unroll";
|
|
|
33
33
|
import { WalletRepositoryImpl } from "./repositories/walletRepository";
|
|
34
34
|
import { ContractRepositoryImpl } from "./repositories/contractRepository";
|
|
35
35
|
import { ArkError, maybeArkError } from "./providers/errors";
|
|
36
|
-
export { Wallet, SingleKey, OnchainWallet, Ramps, VtxoManager, ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider, ArkAddress, DefaultVtxo, VtxoScript, VHTLC, TxType, IndexerTxType, ChainTxType, SettlementEventType, setupServiceWorker, Worker, ServiceWorkerWallet, Request, Response, decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness, buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, ArkNote, networks, WalletRepositoryImpl, ContractRepositoryImpl, Intent, TxTree, P2A, Unroll, Transaction, ArkError, maybeArkError, };
|
|
36
|
+
export { Wallet, SingleKey, OnchainWallet, Ramps, VtxoManager, ESPLORA_URL, EsploraProvider, RestArkProvider, RestIndexerProvider, ArkAddress, DefaultVtxo, VtxoScript, VHTLC, TxType, IndexerTxType, ChainTxType, SettlementEventType, setupServiceWorker, Worker, ServiceWorkerWallet, Request, Response, decodeTapscript, MultisigTapscript, CSVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CLTVMultisigTapscript, TapTreeCoder, ArkPsbtFieldKey, ArkPsbtFieldKeyType, setArkPsbtField, getArkPsbtFields, CosignerPublicKey, VtxoTreeExpiry, VtxoTaprootTree, ConditionWitness, buildOffchainTx, verifyTapscriptSignatures, waitForIncomingFunds, hasBoardingTxExpired, ArkNote, networks, WalletRepositoryImpl, ContractRepositoryImpl, Intent, TxTree, P2A, Unroll, Transaction, ArkError, maybeArkError, };
|
|
37
37
|
export type { Identity, IWallet, WalletConfig, ProviderClass, ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, WalletBalance, SendBitcoinParams, Recipient, SettleParams, Status, VirtualStatus, Outpoint, VirtualCoin, TxKey, TapscriptType, ArkTxInput, OffchainTx, TapLeaves, IncomingFunds, IndexerProvider, PageResponse, Batch, ChainTx, CommitmentTx, TxHistoryRecord, Vtxo, VtxoChain, Tx, OnchainProvider, ArkProvider, SettlementEvent, ArkInfo, SignedIntent, Output, TxNotification, ExplorerTransaction, BatchFinalizationEvent, BatchFinalizedEvent, BatchFailedEvent, TreeSigningStartedEvent, TreeNoncesEvent, BatchStartedEvent, TreeTxEvent, TreeSignatureEvent, ScheduledSession, PaginationOptions, SubscriptionResponse, SubscriptionHeartbeat, SubscriptionEvent, Network, NetworkName, ArkTapscript, RelativeTimelock, EncodedVtxoScript, TapLeafScript, SignerSession, TreeNonces, TreePartialSigs, GetVtxosFilter, Nonces, PartialSig, ArkPsbtFieldCoder, TxTreeNode, AnchorBumper, };
|
|
@@ -49,8 +49,12 @@ export interface OnchainProvider {
|
|
|
49
49
|
*/
|
|
50
50
|
export declare class EsploraProvider implements OnchainProvider {
|
|
51
51
|
private baseUrl;
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
readonly pollingInterval: number;
|
|
53
|
+
readonly forcePolling: boolean;
|
|
54
|
+
constructor(baseUrl: string, opts?: {
|
|
55
|
+
pollingInterval?: number;
|
|
56
|
+
forcePolling?: boolean;
|
|
57
|
+
});
|
|
54
58
|
getCoins(address: string): Promise<Coin[]>;
|
|
55
59
|
getFeeRate(): Promise<number | undefined>;
|
|
56
60
|
broadcastTransaction(...txs: string[]): Promise<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StorageAdapter } from "../storage";
|
|
2
|
-
import { ArkTransaction, ExtendedVirtualCoin } from "../wallet";
|
|
2
|
+
import { ArkTransaction, ExtendedCoin, ExtendedVirtualCoin } from "../wallet";
|
|
3
3
|
export interface WalletState {
|
|
4
4
|
lastSyncTime?: number;
|
|
5
5
|
settings?: Record<string, any>;
|
|
@@ -9,6 +9,10 @@ export interface WalletRepository {
|
|
|
9
9
|
saveVtxos(address: string, vtxos: ExtendedVirtualCoin[]): Promise<void>;
|
|
10
10
|
removeVtxo(address: string, vtxoId: string): Promise<void>;
|
|
11
11
|
clearVtxos(address: string): Promise<void>;
|
|
12
|
+
getUtxos(address: string): Promise<ExtendedCoin[]>;
|
|
13
|
+
saveUtxos(address: string, utxos: ExtendedCoin[]): Promise<void>;
|
|
14
|
+
removeUtxo(address: string, utxoId: string): Promise<void>;
|
|
15
|
+
clearUtxos(address: string): Promise<void>;
|
|
12
16
|
getTransactionHistory(address: string): Promise<ArkTransaction[]>;
|
|
13
17
|
saveTransactions(address: string, txs: ArkTransaction[]): Promise<void>;
|
|
14
18
|
clearTransactions(address: string): Promise<void>;
|
|
@@ -23,6 +27,10 @@ export declare class WalletRepositoryImpl implements WalletRepository {
|
|
|
23
27
|
saveVtxos(address: string, vtxos: ExtendedVirtualCoin[]): Promise<void>;
|
|
24
28
|
removeVtxo(address: string, vtxoId: string): Promise<void>;
|
|
25
29
|
clearVtxos(address: string): Promise<void>;
|
|
30
|
+
getUtxos(address: string): Promise<ExtendedCoin[]>;
|
|
31
|
+
saveUtxos(address: string, utxos: ExtendedCoin[]): Promise<void>;
|
|
32
|
+
removeUtxo(address: string, utxoId: string): Promise<void>;
|
|
33
|
+
clearUtxos(address: string): Promise<void>;
|
|
26
34
|
getTransactionHistory(address: string): Promise<ArkTransaction[]>;
|
|
27
35
|
saveTransactions(address: string, txs: ArkTransaction[]): Promise<void>;
|
|
28
36
|
clearTransactions(address: string): Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NETWORK } from "@scure/btc-signer";
|
|
2
|
+
import { PSBTOutput } from "@scure/btc-signer/psbt.js";
|
|
2
3
|
import { Bytes } from "@scure/btc-signer/utils.js";
|
|
3
4
|
import { ArkAddress } from "./address";
|
|
4
5
|
import { ConditionCSVMultisigTapscript, CSVMultisigTapscript } from "./tapscript";
|
|
@@ -10,6 +11,7 @@ export type TapLeafScript = [
|
|
|
10
11
|
},
|
|
11
12
|
Bytes
|
|
12
13
|
];
|
|
14
|
+
export declare const TapTreeCoder: (typeof PSBTOutput.tapTree)[2];
|
|
13
15
|
export declare function scriptFromTapLeafScript(leaf: TapLeafScript): Bytes;
|
|
14
16
|
/**
|
|
15
17
|
* VtxoScript is a script that contains a list of tapleaf scripts.
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
2
|
-
import { Bytes } from "@scure/btc-signer/utils.js";
|
|
3
1
|
import { TransactionOutput } from "@scure/btc-signer/psbt.js";
|
|
4
2
|
import { ExtendedCoin, VirtualCoin } from "../wallet";
|
|
5
3
|
import { RelativeTimelock } from "../script/tapscript";
|
|
6
4
|
import { EncodedVtxoScript, TapLeafScript } from "../script/base";
|
|
7
5
|
import { CSVMultisigTapscript } from "../script/tapscript";
|
|
6
|
+
import { Transaction } from "./transaction";
|
|
8
7
|
export type ArkTxInput = {
|
|
9
8
|
tapLeafScript: TapLeafScript;
|
|
10
|
-
checkpointTapLeafScript?: Bytes;
|
|
11
9
|
} & EncodedVtxoScript & Pick<VirtualCoin, "txid" | "vout" | "value">;
|
|
12
10
|
export type OffchainTx = {
|
|
13
11
|
arkTx: Transaction;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Transaction as BtcSignerTransaction } from "@scure/btc-signer";
|
|
2
|
+
import { TxOpts } from "@scure/btc-signer/transaction";
|
|
3
|
+
import { Bytes } from "@scure/btc-signer/utils";
|
|
4
|
+
/**
|
|
5
|
+
* Transaction is a wrapper around the @scure/btc-signer Transaction class.
|
|
6
|
+
* It adds the Ark protocol specific options to the transaction.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Transaction extends BtcSignerTransaction {
|
|
9
|
+
static ARK_TX_OPTS: TxOpts;
|
|
10
|
+
constructor(opts?: TxOpts);
|
|
11
|
+
static fromPSBT(psbt_: Bytes, opts?: TxOpts): Transaction;
|
|
12
|
+
static fromRaw(raw: Bytes, opts?: TxOpts): Transaction;
|
|
13
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
2
1
|
import { P2TR } from "@scure/btc-signer/payment.js";
|
|
3
2
|
import { Coin, SendBitcoinParams } from ".";
|
|
4
3
|
import { Identity } from "../identity";
|
|
5
4
|
import { Network, NetworkName } from "../networks";
|
|
6
5
|
import { OnchainProvider } from "../providers/onchain";
|
|
7
6
|
import { AnchorBumper } from "../utils/anchor";
|
|
7
|
+
import { Transaction } from "../utils/transaction";
|
|
8
8
|
/**
|
|
9
9
|
* Onchain Bitcoin wallet implementation for traditional Bitcoin transactions.
|
|
10
10
|
*
|
|
@@ -25,6 +25,10 @@ export declare class Worker {
|
|
|
25
25
|
* Get all vtxos categorized by type
|
|
26
26
|
*/
|
|
27
27
|
private getAllVtxos;
|
|
28
|
+
/**
|
|
29
|
+
* Get all boarding utxos from wallet repository
|
|
30
|
+
*/
|
|
31
|
+
private getAllBoardingUtxos;
|
|
28
32
|
start(withServiceWorkerUpdate?: boolean): Promise<void>;
|
|
29
33
|
clear(): Promise<void>;
|
|
30
34
|
reload(): Promise<void>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Transaction } from "@scure/btc-signer";
|
|
2
1
|
import { ChainTx, IndexerProvider } from "../providers/indexer";
|
|
3
2
|
import { AnchorBumper } from "../utils/anchor";
|
|
4
3
|
import { OnchainProvider } from "../providers/onchain";
|
|
5
4
|
import { Outpoint } from ".";
|
|
6
5
|
import { Wallet } from "./wallet";
|
|
6
|
+
import { Transaction } from "../utils/transaction";
|
|
7
7
|
export declare namespace Unroll {
|
|
8
8
|
enum StepType {
|
|
9
9
|
UNROLL = 0,
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { ExtendedVirtualCoin, VirtualCoin, Wallet } from "..";
|
|
1
|
+
import type { Coin, ExtendedCoin, ExtendedVirtualCoin, VirtualCoin, Wallet } from "..";
|
|
2
2
|
export declare function extendVirtualCoin(wallet: Wallet, vtxo: VirtualCoin): ExtendedVirtualCoin;
|
|
3
|
+
export declare function extendCoin(wallet: Wallet, utxo: Coin): ExtendedCoin;
|
|
@@ -8,7 +8,7 @@ export interface RenewalConfig {
|
|
|
8
8
|
* Enable automatic renewal monitoring
|
|
9
9
|
* @default false
|
|
10
10
|
*/
|
|
11
|
-
enabled
|
|
11
|
+
enabled?: boolean;
|
|
12
12
|
/**
|
|
13
13
|
* Percentage of expiry time to use as threshold (0-100)
|
|
14
14
|
* E.g., 10 means renew when 10% of time until expiry remains
|
|
@@ -27,44 +27,16 @@ export declare const DEFAULT_RENEWAL_CONFIG: Required<Omit<RenewalConfig, "enabl
|
|
|
27
27
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
28
28
|
* @returns true if VTXO expires within threshold, false otherwise
|
|
29
29
|
*/
|
|
30
|
-
export declare function isVtxoExpiringSoon(vtxo: ExtendedVirtualCoin,
|
|
30
|
+
export declare function isVtxoExpiringSoon(vtxo: ExtendedVirtualCoin, percentage: number): boolean;
|
|
31
31
|
/**
|
|
32
|
-
* Filter VTXOs that are expiring soon
|
|
32
|
+
* Filter VTXOs that are expiring soon or are recoverable/subdust
|
|
33
33
|
*
|
|
34
34
|
* @param vtxos - Array of virtual coins to check
|
|
35
35
|
* @param thresholdMs - Threshold in milliseconds from now
|
|
36
|
+
* @param dustAmount - Dust threshold amount in satoshis
|
|
36
37
|
* @returns Array of VTXOs expiring within threshold
|
|
37
38
|
*/
|
|
38
|
-
export declare function
|
|
39
|
-
/**
|
|
40
|
-
* Calculate expiry threshold in milliseconds based on batch expiry and percentage
|
|
41
|
-
*
|
|
42
|
-
* @param batchExpiry - Batch expiry timestamp in milliseconds
|
|
43
|
-
* @param percentage - Percentage of total time (0-100)
|
|
44
|
-
* @returns Threshold timestamp in milliseconds from now
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* // VTXO expires in 10 days, threshold is 10%
|
|
48
|
-
* const expiry = Date.now() + 10 * 24 * 60 * 60 * 1000;
|
|
49
|
-
* const threshold = calculateExpiryThreshold(expiry, 10);
|
|
50
|
-
* // Returns 1 day in milliseconds (10% of 10 days)
|
|
51
|
-
*/
|
|
52
|
-
export declare function calculateExpiryThreshold(batchExpiry: number, percentage: number): number;
|
|
53
|
-
/**
|
|
54
|
-
* Get the minimum expiry time from a list of VTXOs
|
|
55
|
-
*
|
|
56
|
-
* @param vtxos - Array of virtual coins
|
|
57
|
-
* @returns Minimum batch expiry timestamp, or undefined if no VTXOs have expiry
|
|
58
|
-
*/
|
|
59
|
-
export declare function getMinimumExpiry(vtxos: ExtendedVirtualCoin[]): number | undefined;
|
|
60
|
-
/**
|
|
61
|
-
* Calculate dynamic threshold based on the earliest expiring VTXO
|
|
62
|
-
*
|
|
63
|
-
* @param vtxos - Array of virtual coins
|
|
64
|
-
* @param percentage - Percentage of time until expiry (0-100)
|
|
65
|
-
* @returns Threshold in milliseconds, or undefined if no VTXOs have expiry
|
|
66
|
-
*/
|
|
67
|
-
export declare function calculateDynamicThreshold(vtxos: ExtendedVirtualCoin[], percentage: number): number | undefined;
|
|
39
|
+
export declare function getExpiringAndRecoverableVtxos(vtxos: ExtendedVirtualCoin[], percentage: number, dustAmount: bigint): ExtendedVirtualCoin[];
|
|
68
40
|
/**
|
|
69
41
|
* VtxoManager is a unified class for managing VTXO lifecycle operations including
|
|
70
42
|
* recovery of swept/expired VTXOs and renewal to prevent expiration.
|
|
@@ -179,9 +151,9 @@ export declare class VtxoManager {
|
|
|
179
151
|
*/
|
|
180
152
|
getExpiringVtxos(thresholdPercentage?: number): Promise<ExtendedVirtualCoin[]>;
|
|
181
153
|
/**
|
|
182
|
-
* Renew VTXOs by settling them back to the wallet's address
|
|
154
|
+
* Renew expiring VTXOs by settling them back to the wallet's address
|
|
183
155
|
*
|
|
184
|
-
* This method collects all spendable VTXOs (including recoverable ones) and settles
|
|
156
|
+
* This method collects all expiring spendable VTXOs (including recoverable ones) and settles
|
|
185
157
|
* them back to the wallet, effectively refreshing their expiration time. This is the
|
|
186
158
|
* primary way to prevent VTXOs from expiring.
|
|
187
159
|
*
|