@arkade-os/sdk 0.3.8 → 0.3.10
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 +78 -1
- package/dist/cjs/identity/singleKey.js +33 -1
- package/dist/cjs/index.js +17 -2
- package/dist/cjs/intent/index.js +31 -2
- package/dist/cjs/providers/ark.js +15 -5
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/wallet/batch.js +183 -0
- package/dist/cjs/wallet/index.js +15 -0
- package/dist/cjs/wallet/serviceWorker/request.js +0 -2
- package/dist/cjs/wallet/serviceWorker/wallet.js +98 -34
- package/dist/cjs/wallet/serviceWorker/worker.js +163 -72
- package/dist/cjs/wallet/utils.js +2 -2
- package/dist/cjs/wallet/vtxo-manager.js +5 -0
- package/dist/cjs/wallet/wallet.js +358 -360
- package/dist/esm/identity/singleKey.js +31 -0
- package/dist/esm/index.js +12 -7
- package/dist/esm/intent/index.js +31 -2
- package/dist/esm/providers/ark.js +15 -5
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/wallet/batch.js +180 -0
- package/dist/esm/wallet/index.js +14 -0
- package/dist/esm/wallet/serviceWorker/request.js +0 -2
- package/dist/esm/wallet/serviceWorker/wallet.js +96 -33
- package/dist/esm/wallet/serviceWorker/worker.js +165 -74
- package/dist/esm/wallet/utils.js +2 -2
- package/dist/esm/wallet/vtxo-manager.js +6 -1
- package/dist/esm/wallet/wallet.js +359 -363
- package/dist/types/identity/index.d.ts +5 -3
- package/dist/types/identity/singleKey.d.ts +20 -1
- package/dist/types/index.d.ts +11 -8
- package/dist/types/intent/index.d.ts +19 -2
- package/dist/types/providers/ark.d.ts +9 -8
- package/dist/types/providers/indexer.d.ts +2 -2
- package/dist/types/wallet/batch.d.ts +87 -0
- package/dist/types/wallet/index.d.ts +76 -16
- package/dist/types/wallet/serviceWorker/request.d.ts +5 -1
- package/dist/types/wallet/serviceWorker/wallet.d.ts +46 -15
- package/dist/types/wallet/serviceWorker/worker.d.ts +6 -3
- package/dist/types/wallet/utils.d.ts +8 -3
- package/dist/types/wallet/wallet.d.ts +87 -36
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference lib="webworker" />
|
|
2
|
-
import { SingleKey } from '../../identity/singleKey.js';
|
|
3
|
-
import { isRecoverable, isSpendable, isSubdust, } from '../index.js';
|
|
4
|
-
import { Wallet } from '../wallet.js';
|
|
2
|
+
import { ReadonlySingleKey, SingleKey } from '../../identity/singleKey.js';
|
|
3
|
+
import { isExpired, isRecoverable, isSpendable, isSubdust, } from '../index.js';
|
|
4
|
+
import { ReadonlyWallet, Wallet } from '../wallet.js';
|
|
5
5
|
import { Request } from './request.js';
|
|
6
6
|
import { Response } from './response.js';
|
|
7
7
|
import { RestArkProvider } from '../../providers/ark.js';
|
|
@@ -12,9 +12,70 @@ import { IndexedDBStorageAdapter } from '../../storage/indexedDB.js';
|
|
|
12
12
|
import { WalletRepositoryImpl, } from '../../repositories/walletRepository.js';
|
|
13
13
|
import { extendCoin, extendVirtualCoin } from '../utils.js';
|
|
14
14
|
import { DEFAULT_DB_NAME } from './utils.js';
|
|
15
|
+
class ReadonlyHandler {
|
|
16
|
+
constructor(wallet) {
|
|
17
|
+
this.wallet = wallet;
|
|
18
|
+
}
|
|
19
|
+
get offchainTapscript() {
|
|
20
|
+
return this.wallet.offchainTapscript;
|
|
21
|
+
}
|
|
22
|
+
get boardingTapscript() {
|
|
23
|
+
return this.wallet.boardingTapscript;
|
|
24
|
+
}
|
|
25
|
+
get onchainProvider() {
|
|
26
|
+
return this.wallet.onchainProvider;
|
|
27
|
+
}
|
|
28
|
+
get dustAmount() {
|
|
29
|
+
return this.wallet.dustAmount;
|
|
30
|
+
}
|
|
31
|
+
get identity() {
|
|
32
|
+
return this.wallet.identity;
|
|
33
|
+
}
|
|
34
|
+
notifyIncomingFunds(...args) {
|
|
35
|
+
return this.wallet.notifyIncomingFunds(...args);
|
|
36
|
+
}
|
|
37
|
+
getAddress() {
|
|
38
|
+
return this.wallet.getAddress();
|
|
39
|
+
}
|
|
40
|
+
getBoardingAddress() {
|
|
41
|
+
return this.wallet.getBoardingAddress();
|
|
42
|
+
}
|
|
43
|
+
getBoardingTxs() {
|
|
44
|
+
return this.wallet.getBoardingTxs();
|
|
45
|
+
}
|
|
46
|
+
async handleReload(_) {
|
|
47
|
+
const pending = await this.wallet.fetchPendingTxs();
|
|
48
|
+
return { pending, finalized: [] };
|
|
49
|
+
}
|
|
50
|
+
async handleSettle(..._) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
async handleSendBitcoin(..._) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
class Handler extends ReadonlyHandler {
|
|
58
|
+
constructor(wallet) {
|
|
59
|
+
super(wallet);
|
|
60
|
+
this.wallet = wallet;
|
|
61
|
+
}
|
|
62
|
+
async handleReload(vtxos) {
|
|
63
|
+
return this.wallet.finalizePendingTxs(vtxos.filter((vtxo) => vtxo.virtualStatus.state !== "swept" &&
|
|
64
|
+
vtxo.virtualStatus.state !== "settled"));
|
|
65
|
+
}
|
|
66
|
+
async handleSettle(...args) {
|
|
67
|
+
return this.wallet.settle(...args);
|
|
68
|
+
}
|
|
69
|
+
async handleSendBitcoin(...args) {
|
|
70
|
+
return this.wallet.sendBitcoin(...args);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
15
73
|
/**
|
|
16
|
-
* Worker is a class letting to interact with ServiceWorkerWallet
|
|
17
|
-
* it aims to be run in a service worker context
|
|
74
|
+
* Worker is a class letting to interact with ServiceWorkerWallet and ServiceWorkerReadonlyWallet from
|
|
75
|
+
* the client; it aims to be run in a service worker context.
|
|
76
|
+
*
|
|
77
|
+
* The messages requiring a Wallet rather than a ReadonlyWallet result in no-op
|
|
78
|
+
* without errors.
|
|
18
79
|
*/
|
|
19
80
|
export class Worker {
|
|
20
81
|
constructor(dbName = DEFAULT_DB_NAME, dbVersion = 1, messageCallback = () => { }) {
|
|
@@ -28,9 +89,9 @@ export class Worker {
|
|
|
28
89
|
* Get spendable vtxos for the current wallet address
|
|
29
90
|
*/
|
|
30
91
|
async getSpendableVtxos() {
|
|
31
|
-
if (!this.
|
|
92
|
+
if (!this.handler)
|
|
32
93
|
return [];
|
|
33
|
-
const address = await this.
|
|
94
|
+
const address = await this.handler.getAddress();
|
|
34
95
|
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
35
96
|
return allVtxos.filter(isSpendable);
|
|
36
97
|
}
|
|
@@ -38,9 +99,9 @@ export class Worker {
|
|
|
38
99
|
* Get swept vtxos for the current wallet address
|
|
39
100
|
*/
|
|
40
101
|
async getSweptVtxos() {
|
|
41
|
-
if (!this.
|
|
102
|
+
if (!this.handler)
|
|
42
103
|
return [];
|
|
43
|
-
const address = await this.
|
|
104
|
+
const address = await this.handler.getAddress();
|
|
44
105
|
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
45
106
|
return allVtxos.filter((vtxo) => vtxo.virtualStatus.state === "swept");
|
|
46
107
|
}
|
|
@@ -48,9 +109,9 @@ export class Worker {
|
|
|
48
109
|
* Get all vtxos categorized by type
|
|
49
110
|
*/
|
|
50
111
|
async getAllVtxos() {
|
|
51
|
-
if (!this.
|
|
112
|
+
if (!this.handler)
|
|
52
113
|
return { spendable: [], spent: [] };
|
|
53
|
-
const address = await this.
|
|
114
|
+
const address = await this.handler.getAddress();
|
|
54
115
|
const allVtxos = await this.walletRepository.getVtxos(address);
|
|
55
116
|
return {
|
|
56
117
|
spendable: allVtxos.filter(isSpendable),
|
|
@@ -61,17 +122,17 @@ export class Worker {
|
|
|
61
122
|
* Get all boarding utxos from wallet repository
|
|
62
123
|
*/
|
|
63
124
|
async getAllBoardingUtxos() {
|
|
64
|
-
if (!this.
|
|
125
|
+
if (!this.handler)
|
|
65
126
|
return [];
|
|
66
|
-
const address = await this.
|
|
127
|
+
const address = await this.handler.getBoardingAddress();
|
|
67
128
|
return await this.walletRepository.getUtxos(address);
|
|
68
129
|
}
|
|
69
130
|
async getTransactionHistory() {
|
|
70
|
-
if (!this.
|
|
131
|
+
if (!this.handler)
|
|
71
132
|
return [];
|
|
72
133
|
let txs = [];
|
|
73
134
|
try {
|
|
74
|
-
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.
|
|
135
|
+
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.handler.getBoardingTxs();
|
|
75
136
|
const { spendable, spent } = await this.getAllVtxos();
|
|
76
137
|
// convert VTXOs to offchain transactions
|
|
77
138
|
const offchainTxs = vtxosToTxs(spendable, spent, roundsToIgnore);
|
|
@@ -114,7 +175,7 @@ export class Worker {
|
|
|
114
175
|
await this.storage.clear();
|
|
115
176
|
// Reset in-memory caches by recreating the repository
|
|
116
177
|
this.walletRepository = new WalletRepositoryImpl(this.storage);
|
|
117
|
-
this.
|
|
178
|
+
this.handler = undefined;
|
|
118
179
|
this.arkProvider = undefined;
|
|
119
180
|
this.indexerProvider = undefined;
|
|
120
181
|
}
|
|
@@ -122,35 +183,34 @@ export class Worker {
|
|
|
122
183
|
await this.onWalletInitialized();
|
|
123
184
|
}
|
|
124
185
|
async onWalletInitialized() {
|
|
125
|
-
if (!this.
|
|
186
|
+
if (!this.handler ||
|
|
126
187
|
!this.arkProvider ||
|
|
127
188
|
!this.indexerProvider ||
|
|
128
|
-
!this.
|
|
129
|
-
!this.
|
|
189
|
+
!this.handler.offchainTapscript ||
|
|
190
|
+
!this.handler.boardingTapscript) {
|
|
130
191
|
return;
|
|
131
192
|
}
|
|
132
193
|
// Get public key script and set the initial vtxos state
|
|
133
|
-
const script = hex.encode(this.
|
|
194
|
+
const script = hex.encode(this.handler.offchainTapscript.pkScript);
|
|
134
195
|
const response = await this.indexerProvider.getVtxos({
|
|
135
196
|
scripts: [script],
|
|
136
197
|
});
|
|
137
|
-
const vtxos = response.vtxos.map((vtxo) => extendVirtualCoin(this.
|
|
198
|
+
const vtxos = response.vtxos.map((vtxo) => extendVirtualCoin(this.handler, vtxo));
|
|
138
199
|
try {
|
|
139
|
-
// recover pending transactions
|
|
140
|
-
const {
|
|
141
|
-
vtxo.virtualStatus.state !== "settled"));
|
|
200
|
+
// recover pending transactions if possible
|
|
201
|
+
const { pending, finalized } = await this.handler.handleReload(vtxos);
|
|
142
202
|
console.info(`Recovered ${finalized.length}/${pending.length} pending transactions: ${finalized.join(", ")}`);
|
|
143
203
|
}
|
|
144
204
|
catch (error) {
|
|
145
205
|
console.error("Error recovering pending transactions:", error);
|
|
146
206
|
}
|
|
147
207
|
// Get wallet address and save vtxos using unified repository
|
|
148
|
-
const address = await this.
|
|
208
|
+
const address = await this.handler.getAddress();
|
|
149
209
|
await this.walletRepository.saveVtxos(address, vtxos);
|
|
150
210
|
// Fetch boarding utxos and save using unified repository
|
|
151
|
-
const boardingAddress = await this.
|
|
152
|
-
const coins = await this.
|
|
153
|
-
await this.walletRepository.saveUtxos(boardingAddress, coins.map((utxo) => extendCoin(this.
|
|
211
|
+
const boardingAddress = await this.handler.getBoardingAddress();
|
|
212
|
+
const coins = await this.handler.onchainProvider.getCoins(boardingAddress);
|
|
213
|
+
await this.walletRepository.saveUtxos(boardingAddress, coins.map((utxo) => extendCoin(this.handler, utxo)));
|
|
154
214
|
// Get transaction history to cache boarding txs
|
|
155
215
|
const txs = await this.getTransactionHistory();
|
|
156
216
|
if (txs)
|
|
@@ -159,13 +219,13 @@ export class Worker {
|
|
|
159
219
|
if (this.incomingFundsSubscription)
|
|
160
220
|
this.incomingFundsSubscription();
|
|
161
221
|
// subscribe for incoming funds and notify all clients when new funds arrive
|
|
162
|
-
this.incomingFundsSubscription = await this.
|
|
222
|
+
this.incomingFundsSubscription = await this.handler.notifyIncomingFunds(async (funds) => {
|
|
163
223
|
if (funds.type === "vtxo") {
|
|
164
224
|
const newVtxos = funds.newVtxos.length > 0
|
|
165
|
-
? funds.newVtxos.map((vtxo) => extendVirtualCoin(this.
|
|
225
|
+
? funds.newVtxos.map((vtxo) => extendVirtualCoin(this.handler, vtxo))
|
|
166
226
|
: [];
|
|
167
227
|
const spentVtxos = funds.spentVtxos.length > 0
|
|
168
|
-
? funds.spentVtxos.map((vtxo) => extendVirtualCoin(this.
|
|
228
|
+
? funds.spentVtxos.map((vtxo) => extendVirtualCoin(this.handler, vtxo))
|
|
169
229
|
: [];
|
|
170
230
|
if ([...newVtxos, ...spentVtxos].length === 0)
|
|
171
231
|
return;
|
|
@@ -178,8 +238,8 @@ export class Worker {
|
|
|
178
238
|
await this.sendMessageToAllClients(Response.vtxoUpdate(newVtxos, spentVtxos));
|
|
179
239
|
}
|
|
180
240
|
if (funds.type === "utxo") {
|
|
181
|
-
const utxos = funds.coins.map((utxo) => extendCoin(this.
|
|
182
|
-
const boardingAddress = await this.
|
|
241
|
+
const utxos = funds.coins.map((utxo) => extendCoin(this.handler, utxo));
|
|
242
|
+
const boardingAddress = await this.handler?.getBoardingAddress();
|
|
183
243
|
// save utxos using unified repository
|
|
184
244
|
await this.walletRepository.clearUtxos(boardingAddress);
|
|
185
245
|
await this.walletRepository.saveUtxos(boardingAddress, utxos);
|
|
@@ -195,31 +255,46 @@ export class Worker {
|
|
|
195
255
|
}
|
|
196
256
|
}
|
|
197
257
|
async handleInitWallet(event) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
event.source?.postMessage(Response.error(message.id, "Invalid INIT_WALLET message format"));
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
if (!message.privateKey) {
|
|
205
|
-
const err = "Missing privateKey";
|
|
206
|
-
event.source?.postMessage(Response.error(message.id, err));
|
|
207
|
-
console.error(err);
|
|
258
|
+
if (!Request.isInitWallet(event.data)) {
|
|
259
|
+
console.error("Invalid INIT_WALLET message format", event.data);
|
|
260
|
+
event.source?.postMessage(Response.error(event.data.id, "Invalid INIT_WALLET message format"));
|
|
208
261
|
return;
|
|
209
262
|
}
|
|
263
|
+
const message = event.data;
|
|
264
|
+
const { arkServerPublicKey, arkServerUrl } = message;
|
|
265
|
+
this.arkProvider = new RestArkProvider(arkServerUrl);
|
|
266
|
+
this.indexerProvider = new RestIndexerProvider(arkServerUrl);
|
|
210
267
|
try {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
268
|
+
if ("privateKey" in message.key &&
|
|
269
|
+
typeof message.key.privateKey === "string") {
|
|
270
|
+
const { key: { privateKey }, } = message;
|
|
271
|
+
const identity = SingleKey.fromHex(privateKey);
|
|
272
|
+
const wallet = await Wallet.create({
|
|
273
|
+
identity,
|
|
274
|
+
arkServerUrl,
|
|
275
|
+
arkServerPublicKey,
|
|
276
|
+
storage: this.storage, // Use unified storage for wallet too
|
|
277
|
+
});
|
|
278
|
+
this.handler = new Handler(wallet);
|
|
279
|
+
}
|
|
280
|
+
else if ("publicKey" in message.key &&
|
|
281
|
+
typeof message.key.publicKey === "string") {
|
|
282
|
+
const { key: { publicKey }, } = message;
|
|
283
|
+
const identity = ReadonlySingleKey.fromPublicKey(hex.decode(publicKey));
|
|
284
|
+
const wallet = await ReadonlyWallet.create({
|
|
285
|
+
identity,
|
|
286
|
+
arkServerUrl,
|
|
287
|
+
arkServerPublicKey,
|
|
288
|
+
storage: this.storage, // Use unified storage for wallet too
|
|
289
|
+
});
|
|
290
|
+
this.handler = new ReadonlyHandler(wallet);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
const err = "Missing privateKey or publicKey in key object";
|
|
294
|
+
event.source?.postMessage(Response.error(message.id, err));
|
|
295
|
+
console.error(err);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
223
298
|
}
|
|
224
299
|
catch (error) {
|
|
225
300
|
console.error("Error initializing wallet:", error);
|
|
@@ -227,7 +302,10 @@ export class Worker {
|
|
|
227
302
|
? error.message
|
|
228
303
|
: "Unknown error occurred";
|
|
229
304
|
event.source?.postMessage(Response.error(message.id, errorMessage));
|
|
305
|
+
return;
|
|
230
306
|
}
|
|
307
|
+
event.source?.postMessage(Response.walletInitialized(message.id));
|
|
308
|
+
await this.onWalletInitialized();
|
|
231
309
|
}
|
|
232
310
|
async handleSettle(event) {
|
|
233
311
|
const message = event.data;
|
|
@@ -237,15 +315,20 @@ export class Worker {
|
|
|
237
315
|
return;
|
|
238
316
|
}
|
|
239
317
|
try {
|
|
240
|
-
if (!this.
|
|
318
|
+
if (!this.handler) {
|
|
241
319
|
console.error("Wallet not initialized");
|
|
242
320
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
243
321
|
return;
|
|
244
322
|
}
|
|
245
|
-
const txid = await this.
|
|
323
|
+
const txid = await this.handler.handleSettle(message.params, (e) => {
|
|
246
324
|
event.source?.postMessage(Response.settleEvent(message.id, e));
|
|
247
325
|
});
|
|
248
|
-
|
|
326
|
+
if (txid) {
|
|
327
|
+
event.source?.postMessage(Response.settleSuccess(message.id, txid));
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
event.source?.postMessage(Response.error(message.id, "Operation not supported in readonly mode"));
|
|
331
|
+
}
|
|
249
332
|
}
|
|
250
333
|
catch (error) {
|
|
251
334
|
console.error("Error settling:", error);
|
|
@@ -262,14 +345,19 @@ export class Worker {
|
|
|
262
345
|
event.source?.postMessage(Response.error(message.id, "Invalid SEND_BITCOIN message format"));
|
|
263
346
|
return;
|
|
264
347
|
}
|
|
265
|
-
if (!this.
|
|
348
|
+
if (!this.handler) {
|
|
266
349
|
console.error("Wallet not initialized");
|
|
267
350
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
268
351
|
return;
|
|
269
352
|
}
|
|
270
353
|
try {
|
|
271
|
-
const txid = await this.
|
|
272
|
-
|
|
354
|
+
const txid = await this.handler.handleSendBitcoin(message.params);
|
|
355
|
+
if (txid) {
|
|
356
|
+
event.source?.postMessage(Response.sendBitcoinSuccess(message.id, txid));
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
event.source?.postMessage(Response.error(message.id, "Operation not supported in readonly mode"));
|
|
360
|
+
}
|
|
273
361
|
}
|
|
274
362
|
catch (error) {
|
|
275
363
|
console.error("Error sending bitcoin:", error);
|
|
@@ -286,13 +374,13 @@ export class Worker {
|
|
|
286
374
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_ADDRESS message format"));
|
|
287
375
|
return;
|
|
288
376
|
}
|
|
289
|
-
if (!this.
|
|
377
|
+
if (!this.handler) {
|
|
290
378
|
console.error("Wallet not initialized");
|
|
291
379
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
292
380
|
return;
|
|
293
381
|
}
|
|
294
382
|
try {
|
|
295
|
-
const address = await this.
|
|
383
|
+
const address = await this.handler.getAddress();
|
|
296
384
|
event.source?.postMessage(Response.address(message.id, address));
|
|
297
385
|
}
|
|
298
386
|
catch (error) {
|
|
@@ -310,13 +398,13 @@ export class Worker {
|
|
|
310
398
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_BOARDING_ADDRESS message format"));
|
|
311
399
|
return;
|
|
312
400
|
}
|
|
313
|
-
if (!this.
|
|
401
|
+
if (!this.handler) {
|
|
314
402
|
console.error("Wallet not initialized");
|
|
315
403
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
316
404
|
return;
|
|
317
405
|
}
|
|
318
406
|
try {
|
|
319
|
-
const address = await this.
|
|
407
|
+
const address = await this.handler.getBoardingAddress();
|
|
320
408
|
event.source?.postMessage(Response.boardingAddress(message.id, address));
|
|
321
409
|
}
|
|
322
410
|
catch (error) {
|
|
@@ -334,7 +422,7 @@ export class Worker {
|
|
|
334
422
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_BALANCE message format"));
|
|
335
423
|
return;
|
|
336
424
|
}
|
|
337
|
-
if (!this.
|
|
425
|
+
if (!this.handler) {
|
|
338
426
|
console.error("Wallet not initialized");
|
|
339
427
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
340
428
|
return;
|
|
@@ -403,14 +491,14 @@ export class Worker {
|
|
|
403
491
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_VTXOS message format"));
|
|
404
492
|
return;
|
|
405
493
|
}
|
|
406
|
-
if (!this.
|
|
494
|
+
if (!this.handler) {
|
|
407
495
|
console.error("Wallet not initialized");
|
|
408
496
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
409
497
|
return;
|
|
410
498
|
}
|
|
411
499
|
try {
|
|
412
500
|
const vtxos = await this.getSpendableVtxos();
|
|
413
|
-
const dustAmount = this.
|
|
501
|
+
const dustAmount = this.handler.dustAmount;
|
|
414
502
|
const includeRecoverable = message.filter?.withRecoverable ?? false;
|
|
415
503
|
const filteredVtxos = includeRecoverable
|
|
416
504
|
? vtxos
|
|
@@ -421,6 +509,9 @@ export class Worker {
|
|
|
421
509
|
if (isRecoverable(v)) {
|
|
422
510
|
return false;
|
|
423
511
|
}
|
|
512
|
+
if (isExpired(v)) {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
424
515
|
return true;
|
|
425
516
|
});
|
|
426
517
|
event.source?.postMessage(Response.vtxos(message.id, filteredVtxos));
|
|
@@ -440,7 +531,7 @@ export class Worker {
|
|
|
440
531
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_BOARDING_UTXOS message format"));
|
|
441
532
|
return;
|
|
442
533
|
}
|
|
443
|
-
if (!this.
|
|
534
|
+
if (!this.handler) {
|
|
444
535
|
console.error("Wallet not initialized");
|
|
445
536
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
446
537
|
return;
|
|
@@ -464,7 +555,7 @@ export class Worker {
|
|
|
464
555
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_TRANSACTION_HISTORY message format"));
|
|
465
556
|
return;
|
|
466
557
|
}
|
|
467
|
-
if (!this.
|
|
558
|
+
if (!this.handler) {
|
|
468
559
|
console.error("Wallet not initialized");
|
|
469
560
|
event.source?.postMessage(Response.error(message.id, "Wallet not initialized"));
|
|
470
561
|
return;
|
|
@@ -488,10 +579,10 @@ export class Worker {
|
|
|
488
579
|
event.source?.postMessage(Response.error(message.id, "Invalid GET_STATUS message format"));
|
|
489
580
|
return;
|
|
490
581
|
}
|
|
491
|
-
const pubKey = this.
|
|
492
|
-
? await this.
|
|
582
|
+
const pubKey = this.handler
|
|
583
|
+
? await this.handler.identity.xOnlyPublicKey()
|
|
493
584
|
: undefined;
|
|
494
|
-
event.source?.postMessage(Response.walletStatus(message.id, this.
|
|
585
|
+
event.source?.postMessage(Response.walletStatus(message.id, this.handler !== undefined, pubKey));
|
|
495
586
|
}
|
|
496
587
|
async handleMessage(event) {
|
|
497
588
|
this.messageCallback(event);
|
|
@@ -570,7 +661,7 @@ export class Worker {
|
|
|
570
661
|
event.source?.postMessage(Response.error(message.id, "Invalid RELOAD_WALLET message format"));
|
|
571
662
|
return;
|
|
572
663
|
}
|
|
573
|
-
if (!this.
|
|
664
|
+
if (!this.handler) {
|
|
574
665
|
console.error("Wallet not initialized");
|
|
575
666
|
event.source?.postMessage(Response.walletReloaded(message.id, false));
|
|
576
667
|
return;
|
package/dist/esm/wallet/utils.js
CHANGED
|
@@ -2,7 +2,7 @@ export function extendVirtualCoin(wallet, vtxo) {
|
|
|
2
2
|
return {
|
|
3
3
|
...vtxo,
|
|
4
4
|
forfeitTapLeafScript: wallet.offchainTapscript.forfeit(),
|
|
5
|
-
intentTapLeafScript: wallet.offchainTapscript.
|
|
5
|
+
intentTapLeafScript: wallet.offchainTapscript.forfeit(),
|
|
6
6
|
tapTree: wallet.offchainTapscript.encode(),
|
|
7
7
|
};
|
|
8
8
|
}
|
|
@@ -10,7 +10,7 @@ export function extendCoin(wallet, utxo) {
|
|
|
10
10
|
return {
|
|
11
11
|
...utxo,
|
|
12
12
|
forfeitTapLeafScript: wallet.boardingTapscript.forfeit(),
|
|
13
|
-
intentTapLeafScript: wallet.boardingTapscript.
|
|
13
|
+
intentTapLeafScript: wallet.boardingTapscript.forfeit(),
|
|
14
14
|
tapTree: wallet.boardingTapscript.encode(),
|
|
15
15
|
};
|
|
16
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRecoverable, isSubdust } from './index.js';
|
|
1
|
+
import { isExpired, isRecoverable, isSpendable, isSubdust, } from './index.js';
|
|
2
2
|
export const DEFAULT_THRESHOLD_MS = 3 * 24 * 60 * 60 * 1000; // 3 days
|
|
3
3
|
/**
|
|
4
4
|
* Default renewal configuration values
|
|
@@ -26,6 +26,10 @@ function getRecoverableVtxos(vtxos, dustAmount) {
|
|
|
26
26
|
if (isRecoverable(vtxo)) {
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
|
+
// also include vtxos that are not swept but expired
|
|
30
|
+
if (isSpendable(vtxo) && isExpired(vtxo)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
29
33
|
// Recover preconfirmed subdust to consolidate small amounts
|
|
30
34
|
if (vtxo.virtualStatus.state === "preconfirmed" &&
|
|
31
35
|
isSubdust(vtxo, dustAmount)) {
|
|
@@ -100,6 +104,7 @@ export function isVtxoExpiringSoon(vtxo, thresholdMs // in milliseconds
|
|
|
100
104
|
export function getExpiringAndRecoverableVtxos(vtxos, thresholdMs, dustAmount) {
|
|
101
105
|
return vtxos.filter((vtxo) => isVtxoExpiringSoon(vtxo, thresholdMs) ||
|
|
102
106
|
isRecoverable(vtxo) ||
|
|
107
|
+
(isSpendable(vtxo) && isExpired(vtxo)) ||
|
|
103
108
|
isSubdust(vtxo, dustAmount));
|
|
104
109
|
}
|
|
105
110
|
/**
|