@arkade-os/sdk 0.3.1-alpha.7 → 0.3.2
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/dist/cjs/repositories/walletRepository.js +1 -0
- package/dist/cjs/utils/arkTransaction.js +1 -1
- package/dist/cjs/wallet/serviceWorker/worker.js +34 -24
- package/dist/cjs/wallet/wallet.js +8 -10
- package/dist/esm/repositories/walletRepository.js +1 -0
- package/dist/esm/utils/arkTransaction.js +1 -1
- package/dist/esm/wallet/serviceWorker/worker.js +34 -24
- package/dist/esm/wallet/wallet.js +8 -10
- package/dist/types/wallet/serviceWorker/response.d.ts +3 -3
- package/dist/types/wallet/serviceWorker/worker.d.ts +1 -0
- package/package.json +1 -1
|
@@ -31,6 +31,7 @@ const deserializeTapLeaf = (t) => {
|
|
|
31
31
|
};
|
|
32
32
|
const deserializeVtxo = (o) => ({
|
|
33
33
|
...o,
|
|
34
|
+
createdAt: new Date(o.createdAt),
|
|
34
35
|
tapTree: fromHex(o.tapTree),
|
|
35
36
|
forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
|
|
36
37
|
intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
|
|
@@ -112,7 +112,7 @@ function hasBoardingTxExpired(coin, boardingTimelock) {
|
|
|
112
112
|
return false;
|
|
113
113
|
if (boardingTimelock.value === 0n)
|
|
114
114
|
return true;
|
|
115
|
-
if (boardingTimelock.type
|
|
115
|
+
if (boardingTimelock.type === "blocks")
|
|
116
116
|
return false; // TODO: handle get chain tip
|
|
117
117
|
// validate expiry in terms of seconds
|
|
118
118
|
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
@@ -69,6 +69,33 @@ class Worker {
|
|
|
69
69
|
const address = await this.wallet.getBoardingAddress();
|
|
70
70
|
return await this.walletRepository.getUtxos(address);
|
|
71
71
|
}
|
|
72
|
+
async getTransactionHistory() {
|
|
73
|
+
if (!this.wallet)
|
|
74
|
+
return [];
|
|
75
|
+
let txs = [];
|
|
76
|
+
try {
|
|
77
|
+
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.wallet.getBoardingTxs();
|
|
78
|
+
const { spendable, spent } = await this.getAllVtxos();
|
|
79
|
+
// convert VTXOs to offchain transactions
|
|
80
|
+
console.log("getTransactionHistory - vtxosToTxs:", spendable);
|
|
81
|
+
const offchainTxs = (0, transactionHistory_1.vtxosToTxs)(spendable, spent, roundsToIgnore);
|
|
82
|
+
txs = [...boardingTxs, ...offchainTxs];
|
|
83
|
+
// sort transactions by creation time in descending order (newest first)
|
|
84
|
+
txs.sort(
|
|
85
|
+
// place createdAt = 0 (unconfirmed txs) first, then descending
|
|
86
|
+
(a, b) => {
|
|
87
|
+
if (a.createdAt === 0)
|
|
88
|
+
return -1;
|
|
89
|
+
if (b.createdAt === 0)
|
|
90
|
+
return 1;
|
|
91
|
+
return b.createdAt - a.createdAt;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error("Error getting transaction history:", error);
|
|
96
|
+
}
|
|
97
|
+
return txs;
|
|
98
|
+
}
|
|
72
99
|
async start(withServiceWorkerUpdate = true) {
|
|
73
100
|
self.addEventListener("message", async (event) => {
|
|
74
101
|
await this.handleMessage(event);
|
|
@@ -116,7 +143,7 @@ class Worker {
|
|
|
116
143
|
const address = await this.wallet.getAddress();
|
|
117
144
|
await this.walletRepository.saveVtxos(address, vtxos);
|
|
118
145
|
// Get transaction history to cache boarding txs
|
|
119
|
-
const txs = await this.
|
|
146
|
+
const txs = await this.getTransactionHistory();
|
|
120
147
|
if (txs)
|
|
121
148
|
await this.walletRepository.saveTransactions(address, txs);
|
|
122
149
|
// unsubscribe previous subscription if any
|
|
@@ -139,19 +166,16 @@ class Worker {
|
|
|
139
166
|
...spentVtxos,
|
|
140
167
|
]);
|
|
141
168
|
// notify all clients about the vtxo update
|
|
142
|
-
this.sendMessageToAllClients(response_1.Response.vtxoUpdate(newVtxos, spentVtxos));
|
|
169
|
+
await this.sendMessageToAllClients(response_1.Response.vtxoUpdate(newVtxos, spentVtxos));
|
|
143
170
|
}
|
|
144
171
|
if (funds.type === "utxo") {
|
|
145
|
-
const
|
|
146
|
-
if (newUtxos.length === 0) {
|
|
147
|
-
this.sendMessageToAllClients(response_1.Response.utxoUpdate([]));
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
172
|
+
const utxos = funds.coins.map((utxo) => (0, utils_1.extendCoin)(this.wallet, utxo));
|
|
150
173
|
const boardingAddress = await this.wallet?.getBoardingAddress();
|
|
151
174
|
// save utxos using unified repository
|
|
152
|
-
await this.walletRepository.
|
|
175
|
+
await this.walletRepository.clearUtxos(boardingAddress);
|
|
176
|
+
await this.walletRepository.saveUtxos(boardingAddress, utxos);
|
|
153
177
|
// notify all clients about the utxo update
|
|
154
|
-
this.sendMessageToAllClients(response_1.Response.utxoUpdate(
|
|
178
|
+
await this.sendMessageToAllClients(response_1.Response.utxoUpdate(utxos));
|
|
155
179
|
}
|
|
156
180
|
});
|
|
157
181
|
}
|
|
@@ -437,21 +461,7 @@ class Worker {
|
|
|
437
461
|
return;
|
|
438
462
|
}
|
|
439
463
|
try {
|
|
440
|
-
const
|
|
441
|
-
const { spendable, spent } = await this.getAllVtxos();
|
|
442
|
-
// convert VTXOs to offchain transactions
|
|
443
|
-
const offchainTxs = (0, transactionHistory_1.vtxosToTxs)(spendable, spent, roundsToIgnore);
|
|
444
|
-
const txs = [...boardingTxs, ...offchainTxs];
|
|
445
|
-
// sort transactions by creation time in descending order (newest first)
|
|
446
|
-
txs.sort(
|
|
447
|
-
// place createdAt = 0 (unconfirmed txs) first, then descending
|
|
448
|
-
(a, b) => {
|
|
449
|
-
if (a.createdAt === 0)
|
|
450
|
-
return -1;
|
|
451
|
-
if (b.createdAt === 0)
|
|
452
|
-
return 1;
|
|
453
|
-
return b.createdAt - a.createdAt;
|
|
454
|
-
});
|
|
464
|
+
const txs = await this.getTransactionHistory();
|
|
455
465
|
event.source?.postMessage(response_1.Response.transactionHistory(message.id, txs));
|
|
456
466
|
}
|
|
457
467
|
catch (error) {
|
|
@@ -512,8 +512,8 @@ class Wallet {
|
|
|
512
512
|
...params.inputs.map((input) => `${input.txid}:${input.vout}`),
|
|
513
513
|
];
|
|
514
514
|
const settlementStream = this.arkProvider.getEventStream(abortController.signal, topics);
|
|
515
|
-
//
|
|
516
|
-
let
|
|
515
|
+
// batchId, sweepTapTreeRoot and forfeitOutputScript are set once the BatchStarted event is received
|
|
516
|
+
let batchId;
|
|
517
517
|
let sweepTapTreeRoot;
|
|
518
518
|
const vtxoChunks = [];
|
|
519
519
|
const connectorsChunks = [];
|
|
@@ -526,11 +526,7 @@ class Wallet {
|
|
|
526
526
|
switch (event.type) {
|
|
527
527
|
// the settlement failed
|
|
528
528
|
case ark_1.SettlementEventType.BatchFailed:
|
|
529
|
-
|
|
530
|
-
if (event.id === roundId) {
|
|
531
|
-
throw new Error(event.reason);
|
|
532
|
-
}
|
|
533
|
-
break;
|
|
529
|
+
throw new Error(event.reason);
|
|
534
530
|
case ark_1.SettlementEventType.BatchStarted:
|
|
535
531
|
if (step !== undefined) {
|
|
536
532
|
continue;
|
|
@@ -539,7 +535,7 @@ class Wallet {
|
|
|
539
535
|
if (!res.skip) {
|
|
540
536
|
step = event.type;
|
|
541
537
|
sweepTapTreeRoot = res.sweepTapTreeRoot;
|
|
542
|
-
|
|
538
|
+
batchId = res.roundId;
|
|
543
539
|
if (!hasOffchainOutputs) {
|
|
544
540
|
// if there are no offchain outputs, we don't have to handle musig2 tree signatures
|
|
545
541
|
// we can directly advance to the finalization step
|
|
@@ -644,8 +640,10 @@ class Wallet {
|
|
|
644
640
|
if (step !== ark_1.SettlementEventType.BatchFinalization) {
|
|
645
641
|
continue;
|
|
646
642
|
}
|
|
647
|
-
|
|
648
|
-
|
|
643
|
+
if (event.id === batchId) {
|
|
644
|
+
abortController.abort();
|
|
645
|
+
return event.commitmentTxid;
|
|
646
|
+
}
|
|
649
647
|
}
|
|
650
648
|
}
|
|
651
649
|
}
|
|
@@ -28,6 +28,7 @@ const deserializeTapLeaf = (t) => {
|
|
|
28
28
|
};
|
|
29
29
|
const deserializeVtxo = (o) => ({
|
|
30
30
|
...o,
|
|
31
|
+
createdAt: new Date(o.createdAt),
|
|
31
32
|
tapTree: fromHex(o.tapTree),
|
|
32
33
|
forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
|
|
33
34
|
intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
|
|
@@ -107,7 +107,7 @@ export function hasBoardingTxExpired(coin, boardingTimelock) {
|
|
|
107
107
|
return false;
|
|
108
108
|
if (boardingTimelock.value === 0n)
|
|
109
109
|
return true;
|
|
110
|
-
if (boardingTimelock.type
|
|
110
|
+
if (boardingTimelock.type === "blocks")
|
|
111
111
|
return false; // TODO: handle get chain tip
|
|
112
112
|
// validate expiry in terms of seconds
|
|
113
113
|
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
@@ -66,6 +66,33 @@ export class Worker {
|
|
|
66
66
|
const address = await this.wallet.getBoardingAddress();
|
|
67
67
|
return await this.walletRepository.getUtxos(address);
|
|
68
68
|
}
|
|
69
|
+
async getTransactionHistory() {
|
|
70
|
+
if (!this.wallet)
|
|
71
|
+
return [];
|
|
72
|
+
let txs = [];
|
|
73
|
+
try {
|
|
74
|
+
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.wallet.getBoardingTxs();
|
|
75
|
+
const { spendable, spent } = await this.getAllVtxos();
|
|
76
|
+
// convert VTXOs to offchain transactions
|
|
77
|
+
console.log("getTransactionHistory - vtxosToTxs:", spendable);
|
|
78
|
+
const offchainTxs = vtxosToTxs(spendable, spent, roundsToIgnore);
|
|
79
|
+
txs = [...boardingTxs, ...offchainTxs];
|
|
80
|
+
// sort transactions by creation time in descending order (newest first)
|
|
81
|
+
txs.sort(
|
|
82
|
+
// place createdAt = 0 (unconfirmed txs) first, then descending
|
|
83
|
+
(a, b) => {
|
|
84
|
+
if (a.createdAt === 0)
|
|
85
|
+
return -1;
|
|
86
|
+
if (b.createdAt === 0)
|
|
87
|
+
return 1;
|
|
88
|
+
return b.createdAt - a.createdAt;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error("Error getting transaction history:", error);
|
|
93
|
+
}
|
|
94
|
+
return txs;
|
|
95
|
+
}
|
|
69
96
|
async start(withServiceWorkerUpdate = true) {
|
|
70
97
|
self.addEventListener("message", async (event) => {
|
|
71
98
|
await this.handleMessage(event);
|
|
@@ -113,7 +140,7 @@ export class Worker {
|
|
|
113
140
|
const address = await this.wallet.getAddress();
|
|
114
141
|
await this.walletRepository.saveVtxos(address, vtxos);
|
|
115
142
|
// Get transaction history to cache boarding txs
|
|
116
|
-
const txs = await this.
|
|
143
|
+
const txs = await this.getTransactionHistory();
|
|
117
144
|
if (txs)
|
|
118
145
|
await this.walletRepository.saveTransactions(address, txs);
|
|
119
146
|
// unsubscribe previous subscription if any
|
|
@@ -136,19 +163,16 @@ export class Worker {
|
|
|
136
163
|
...spentVtxos,
|
|
137
164
|
]);
|
|
138
165
|
// notify all clients about the vtxo update
|
|
139
|
-
this.sendMessageToAllClients(Response.vtxoUpdate(newVtxos, spentVtxos));
|
|
166
|
+
await this.sendMessageToAllClients(Response.vtxoUpdate(newVtxos, spentVtxos));
|
|
140
167
|
}
|
|
141
168
|
if (funds.type === "utxo") {
|
|
142
|
-
const
|
|
143
|
-
if (newUtxos.length === 0) {
|
|
144
|
-
this.sendMessageToAllClients(Response.utxoUpdate([]));
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
169
|
+
const utxos = funds.coins.map((utxo) => extendCoin(this.wallet, utxo));
|
|
147
170
|
const boardingAddress = await this.wallet?.getBoardingAddress();
|
|
148
171
|
// save utxos using unified repository
|
|
149
|
-
await this.walletRepository.
|
|
172
|
+
await this.walletRepository.clearUtxos(boardingAddress);
|
|
173
|
+
await this.walletRepository.saveUtxos(boardingAddress, utxos);
|
|
150
174
|
// notify all clients about the utxo update
|
|
151
|
-
this.sendMessageToAllClients(Response.utxoUpdate(
|
|
175
|
+
await this.sendMessageToAllClients(Response.utxoUpdate(utxos));
|
|
152
176
|
}
|
|
153
177
|
});
|
|
154
178
|
}
|
|
@@ -434,21 +458,7 @@ export class Worker {
|
|
|
434
458
|
return;
|
|
435
459
|
}
|
|
436
460
|
try {
|
|
437
|
-
const
|
|
438
|
-
const { spendable, spent } = await this.getAllVtxos();
|
|
439
|
-
// convert VTXOs to offchain transactions
|
|
440
|
-
const offchainTxs = vtxosToTxs(spendable, spent, roundsToIgnore);
|
|
441
|
-
const txs = [...boardingTxs, ...offchainTxs];
|
|
442
|
-
// sort transactions by creation time in descending order (newest first)
|
|
443
|
-
txs.sort(
|
|
444
|
-
// place createdAt = 0 (unconfirmed txs) first, then descending
|
|
445
|
-
(a, b) => {
|
|
446
|
-
if (a.createdAt === 0)
|
|
447
|
-
return -1;
|
|
448
|
-
if (b.createdAt === 0)
|
|
449
|
-
return 1;
|
|
450
|
-
return b.createdAt - a.createdAt;
|
|
451
|
-
});
|
|
461
|
+
const txs = await this.getTransactionHistory();
|
|
452
462
|
event.source?.postMessage(Response.transactionHistory(message.id, txs));
|
|
453
463
|
}
|
|
454
464
|
catch (error) {
|
|
@@ -475,8 +475,8 @@ export class Wallet {
|
|
|
475
475
|
...params.inputs.map((input) => `${input.txid}:${input.vout}`),
|
|
476
476
|
];
|
|
477
477
|
const settlementStream = this.arkProvider.getEventStream(abortController.signal, topics);
|
|
478
|
-
//
|
|
479
|
-
let
|
|
478
|
+
// batchId, sweepTapTreeRoot and forfeitOutputScript are set once the BatchStarted event is received
|
|
479
|
+
let batchId;
|
|
480
480
|
let sweepTapTreeRoot;
|
|
481
481
|
const vtxoChunks = [];
|
|
482
482
|
const connectorsChunks = [];
|
|
@@ -489,11 +489,7 @@ export class Wallet {
|
|
|
489
489
|
switch (event.type) {
|
|
490
490
|
// the settlement failed
|
|
491
491
|
case SettlementEventType.BatchFailed:
|
|
492
|
-
|
|
493
|
-
if (event.id === roundId) {
|
|
494
|
-
throw new Error(event.reason);
|
|
495
|
-
}
|
|
496
|
-
break;
|
|
492
|
+
throw new Error(event.reason);
|
|
497
493
|
case SettlementEventType.BatchStarted:
|
|
498
494
|
if (step !== undefined) {
|
|
499
495
|
continue;
|
|
@@ -502,7 +498,7 @@ export class Wallet {
|
|
|
502
498
|
if (!res.skip) {
|
|
503
499
|
step = event.type;
|
|
504
500
|
sweepTapTreeRoot = res.sweepTapTreeRoot;
|
|
505
|
-
|
|
501
|
+
batchId = res.roundId;
|
|
506
502
|
if (!hasOffchainOutputs) {
|
|
507
503
|
// if there are no offchain outputs, we don't have to handle musig2 tree signatures
|
|
508
504
|
// we can directly advance to the finalization step
|
|
@@ -607,8 +603,10 @@ export class Wallet {
|
|
|
607
603
|
if (step !== SettlementEventType.BatchFinalization) {
|
|
608
604
|
continue;
|
|
609
605
|
}
|
|
610
|
-
|
|
611
|
-
|
|
606
|
+
if (event.id === batchId) {
|
|
607
|
+
abortController.abort();
|
|
608
|
+
return event.commitmentTxid;
|
|
609
|
+
}
|
|
612
610
|
}
|
|
613
611
|
}
|
|
614
612
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WalletBalance, VirtualCoin, ArkTransaction, IWallet,
|
|
1
|
+
import { WalletBalance, VirtualCoin, ArkTransaction, IWallet, ExtendedCoin } from "..";
|
|
2
2
|
import { ExtendedVirtualCoin } from "../..";
|
|
3
3
|
import { SettlementEvent } from "../../providers/ark";
|
|
4
4
|
/**
|
|
@@ -116,8 +116,8 @@ export declare namespace Response {
|
|
|
116
116
|
function vtxoUpdate(newVtxos: ExtendedVirtualCoin[], spentVtxos: ExtendedVirtualCoin[]): VtxoUpdate;
|
|
117
117
|
interface UtxoUpdate extends Base {
|
|
118
118
|
type: "UTXO_UPDATE";
|
|
119
|
-
coins:
|
|
119
|
+
coins: ExtendedCoin[];
|
|
120
120
|
}
|
|
121
121
|
function isUtxoUpdate(response: Base): response is UtxoUpdate;
|
|
122
|
-
function utxoUpdate(coins:
|
|
122
|
+
function utxoUpdate(coins: ExtendedCoin[]): UtxoUpdate;
|
|
123
123
|
}
|
|
@@ -29,6 +29,7 @@ export declare class Worker {
|
|
|
29
29
|
* Get all boarding utxos from wallet repository
|
|
30
30
|
*/
|
|
31
31
|
private getAllBoardingUtxos;
|
|
32
|
+
private getTransactionHistory;
|
|
32
33
|
start(withServiceWorkerUpdate?: boolean): Promise<void>;
|
|
33
34
|
clear(): Promise<void>;
|
|
34
35
|
reload(): Promise<void>;
|