@arkade-os/sdk 0.1.4 → 0.2.0
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 +156 -174
- package/dist/cjs/arknote/index.js +61 -58
- package/dist/cjs/bip322/errors.js +13 -0
- package/dist/cjs/bip322/index.js +178 -0
- package/dist/cjs/forfeit.js +14 -25
- package/dist/cjs/identity/singleKey.js +68 -0
- package/dist/cjs/index.js +41 -17
- package/dist/cjs/providers/ark.js +253 -317
- package/dist/cjs/providers/indexer.js +525 -0
- package/dist/cjs/providers/onchain.js +193 -15
- package/dist/cjs/script/address.js +48 -17
- package/dist/cjs/script/base.js +120 -3
- package/dist/cjs/script/default.js +18 -4
- package/dist/cjs/script/tapscript.js +46 -14
- package/dist/cjs/script/vhtlc.js +27 -7
- package/dist/cjs/tree/signingSession.js +63 -106
- package/dist/cjs/tree/txTree.js +193 -0
- package/dist/cjs/tree/validation.js +79 -155
- package/dist/cjs/utils/anchor.js +35 -0
- package/dist/cjs/utils/arkTransaction.js +108 -0
- package/dist/cjs/utils/transactionHistory.js +84 -72
- package/dist/cjs/utils/txSizeEstimator.js +12 -0
- package/dist/cjs/utils/unknownFields.js +211 -0
- package/dist/cjs/wallet/index.js +12 -0
- package/dist/cjs/wallet/onchain.js +201 -0
- package/dist/cjs/wallet/ramps.js +95 -0
- package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +32 -0
- package/dist/cjs/wallet/serviceWorker/request.js +15 -12
- package/dist/cjs/wallet/serviceWorker/response.js +22 -27
- package/dist/cjs/wallet/serviceWorker/utils.js +8 -0
- package/dist/cjs/wallet/serviceWorker/wallet.js +58 -34
- package/dist/cjs/wallet/serviceWorker/worker.js +117 -108
- package/dist/cjs/wallet/unroll.js +270 -0
- package/dist/cjs/wallet/wallet.js +701 -454
- package/dist/esm/arknote/index.js +61 -57
- package/dist/esm/bip322/errors.js +9 -0
- package/dist/esm/bip322/index.js +174 -0
- package/dist/esm/forfeit.js +15 -26
- package/dist/esm/identity/singleKey.js +64 -0
- package/dist/esm/index.js +30 -12
- package/dist/esm/providers/ark.js +252 -317
- package/dist/esm/providers/indexer.js +521 -0
- package/dist/esm/providers/onchain.js +193 -15
- package/dist/esm/script/address.js +48 -17
- package/dist/esm/script/base.js +120 -3
- package/dist/esm/script/default.js +18 -4
- package/dist/esm/script/tapscript.js +46 -14
- package/dist/esm/script/vhtlc.js +27 -7
- package/dist/esm/tree/signingSession.js +65 -108
- package/dist/esm/tree/txTree.js +189 -0
- package/dist/esm/tree/validation.js +75 -152
- package/dist/esm/utils/anchor.js +31 -0
- package/dist/esm/utils/arkTransaction.js +105 -0
- package/dist/esm/utils/transactionHistory.js +84 -72
- package/dist/esm/utils/txSizeEstimator.js +12 -0
- package/dist/esm/utils/unknownFields.js +173 -0
- package/dist/esm/wallet/index.js +9 -0
- package/dist/esm/wallet/onchain.js +196 -0
- package/dist/esm/wallet/ramps.js +91 -0
- package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +32 -0
- package/dist/esm/wallet/serviceWorker/request.js +15 -12
- package/dist/esm/wallet/serviceWorker/response.js +22 -27
- package/dist/esm/wallet/serviceWorker/utils.js +8 -0
- package/dist/esm/wallet/serviceWorker/wallet.js +59 -35
- package/dist/esm/wallet/serviceWorker/worker.js +117 -108
- package/dist/esm/wallet/unroll.js +267 -0
- package/dist/esm/wallet/wallet.js +674 -461
- package/dist/types/arknote/index.d.ts +40 -13
- package/dist/types/bip322/errors.d.ts +6 -0
- package/dist/types/bip322/index.d.ts +57 -0
- package/dist/types/forfeit.d.ts +2 -14
- package/dist/types/identity/singleKey.d.ts +27 -0
- package/dist/types/index.d.ts +23 -12
- package/dist/types/providers/ark.d.ts +114 -95
- package/dist/types/providers/indexer.d.ts +186 -0
- package/dist/types/providers/onchain.d.ts +41 -11
- package/dist/types/script/address.d.ts +26 -2
- package/dist/types/script/base.d.ts +13 -3
- package/dist/types/script/default.d.ts +22 -0
- package/dist/types/script/tapscript.d.ts +61 -5
- package/dist/types/script/vhtlc.d.ts +27 -0
- package/dist/types/tree/signingSession.d.ts +5 -5
- package/dist/types/tree/txTree.d.ts +28 -0
- package/dist/types/tree/validation.d.ts +15 -22
- package/dist/types/utils/anchor.d.ts +19 -0
- package/dist/types/utils/arkTransaction.d.ts +27 -0
- package/dist/types/utils/transactionHistory.d.ts +7 -1
- package/dist/types/utils/txSizeEstimator.d.ts +3 -0
- package/dist/types/utils/unknownFields.d.ts +83 -0
- package/dist/types/wallet/index.d.ts +51 -50
- package/dist/types/wallet/onchain.d.ts +49 -0
- package/dist/types/wallet/ramps.d.ts +32 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +2 -0
- package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +2 -0
- package/dist/types/wallet/serviceWorker/request.d.ts +14 -16
- package/dist/types/wallet/serviceWorker/response.d.ts +17 -19
- package/dist/types/wallet/serviceWorker/utils.d.ts +8 -0
- package/dist/types/wallet/serviceWorker/wallet.d.ts +36 -8
- package/dist/types/wallet/serviceWorker/worker.d.ts +7 -3
- package/dist/types/wallet/unroll.d.ts +102 -0
- package/dist/types/wallet/wallet.d.ts +71 -25
- package/package.json +14 -15
- package/dist/cjs/identity/inMemoryKey.js +0 -40
- package/dist/cjs/tree/vtxoTree.js +0 -231
- package/dist/cjs/utils/coinselect.js +0 -73
- package/dist/cjs/utils/psbt.js +0 -137
- package/dist/esm/identity/inMemoryKey.js +0 -36
- package/dist/esm/tree/vtxoTree.js +0 -191
- package/dist/esm/utils/coinselect.js +0 -69
- package/dist/esm/utils/psbt.js +0 -131
- package/dist/types/identity/inMemoryKey.d.ts +0 -12
- package/dist/types/tree/vtxoTree.d.ts +0 -33
- package/dist/types/utils/coinselect.d.ts +0 -21
- package/dist/types/utils/psbt.d.ts +0 -11
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Response = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Response is the namespace that contains the response types for the service worker.
|
|
6
|
+
*/
|
|
4
7
|
var Response;
|
|
5
8
|
(function (Response) {
|
|
6
9
|
Response.walletInitialized = (id) => ({
|
|
@@ -43,28 +46,28 @@ var Response;
|
|
|
43
46
|
return response.type === "ADDRESS" && response.success === true;
|
|
44
47
|
}
|
|
45
48
|
Response.isAddress = isAddress;
|
|
46
|
-
function
|
|
49
|
+
function isBoardingAddress(response) {
|
|
50
|
+
return (response.type === "BOARDING_ADDRESS" && response.success === true);
|
|
51
|
+
}
|
|
52
|
+
Response.isBoardingAddress = isBoardingAddress;
|
|
53
|
+
function address(id, address) {
|
|
47
54
|
return {
|
|
48
55
|
type: "ADDRESS",
|
|
49
56
|
success: true,
|
|
50
|
-
|
|
57
|
+
address,
|
|
51
58
|
id,
|
|
52
59
|
};
|
|
53
60
|
}
|
|
54
|
-
Response.
|
|
55
|
-
function
|
|
56
|
-
return response.type === "ADDRESS_INFO" && response.success === true;
|
|
57
|
-
}
|
|
58
|
-
Response.isAddressInfo = isAddressInfo;
|
|
59
|
-
function addressInfo(id, addressInfo) {
|
|
61
|
+
Response.address = address;
|
|
62
|
+
function boardingAddress(id, address) {
|
|
60
63
|
return {
|
|
61
|
-
type: "
|
|
64
|
+
type: "BOARDING_ADDRESS",
|
|
62
65
|
success: true,
|
|
63
|
-
|
|
66
|
+
address,
|
|
64
67
|
id,
|
|
65
68
|
};
|
|
66
69
|
}
|
|
67
|
-
Response.
|
|
70
|
+
Response.boardingAddress = boardingAddress;
|
|
68
71
|
function isBalance(response) {
|
|
69
72
|
return response.type === "BALANCE" && response.success === true;
|
|
70
73
|
}
|
|
@@ -78,19 +81,6 @@ var Response;
|
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
Response.balance = balance;
|
|
81
|
-
function isCoins(response) {
|
|
82
|
-
return response.type === "COINS" && response.success === true;
|
|
83
|
-
}
|
|
84
|
-
Response.isCoins = isCoins;
|
|
85
|
-
function coins(id, coins) {
|
|
86
|
-
return {
|
|
87
|
-
type: "COINS",
|
|
88
|
-
success: true,
|
|
89
|
-
coins,
|
|
90
|
-
id,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
Response.coins = coins;
|
|
94
84
|
function isVtxos(response) {
|
|
95
85
|
return response.type === "VTXOS" && response.success === true;
|
|
96
86
|
}
|
|
@@ -184,12 +174,17 @@ var Response;
|
|
|
184
174
|
};
|
|
185
175
|
}
|
|
186
176
|
Response.clearResponse = clearResponse;
|
|
187
|
-
function
|
|
177
|
+
function signSuccess(id, tx) {
|
|
188
178
|
return {
|
|
189
|
-
type: "
|
|
179
|
+
type: "SIGN_SUCCESS",
|
|
190
180
|
success: true,
|
|
181
|
+
tx,
|
|
191
182
|
id,
|
|
192
183
|
};
|
|
193
184
|
}
|
|
194
|
-
Response.
|
|
185
|
+
Response.signSuccess = signSuccess;
|
|
186
|
+
function isSignSuccess(response) {
|
|
187
|
+
return response.type === "SIGN_SUCCESS" && response.success === true;
|
|
188
|
+
}
|
|
189
|
+
Response.isSignSuccess = isSignSuccess;
|
|
195
190
|
})(Response || (exports.Response = Response = {}));
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setupServiceWorker = setupServiceWorker;
|
|
4
|
+
/**
|
|
5
|
+
* setupServiceWorker sets up the service worker.
|
|
6
|
+
* @param path - the path to the service worker script
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const serviceWorker = await setupServiceWorker("/service-worker.js");
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
4
12
|
async function setupServiceWorker(path) {
|
|
5
13
|
// check if service workers are supported
|
|
6
14
|
if (!("serviceWorker" in navigator)) {
|
|
@@ -3,13 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ServiceWorkerWallet = void 0;
|
|
4
4
|
const response_1 = require("./response");
|
|
5
5
|
const base_1 = require("@scure/base");
|
|
6
|
+
const singleKey_1 = require("../../identity/singleKey");
|
|
7
|
+
const signingSession_1 = require("../../tree/signingSession");
|
|
8
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
6
9
|
class UnexpectedResponseError extends Error {
|
|
7
10
|
constructor(response) {
|
|
8
11
|
super(`Unexpected response type. Got: ${JSON.stringify(response, null, 2)}`);
|
|
9
12
|
this.name = "UnexpectedResponseError";
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Service Worker-based wallet implementation for browser environments.
|
|
17
|
+
*
|
|
18
|
+
* This wallet uses a service worker as a backend to handle wallet logic,
|
|
19
|
+
* providing secure key storage and transaction signing in web applications.
|
|
20
|
+
* The service worker runs in a separate thread and can persist data between
|
|
21
|
+
* browser sessions.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Create and initialize the service worker wallet
|
|
26
|
+
* const serviceWorker = await setupServiceWorker("/service-worker.js");
|
|
27
|
+
* const wallet = new ServiceWorkerWallet(serviceWorker);
|
|
28
|
+
* await wallet.init({
|
|
29
|
+
* privateKey: 'your_private_key_hex',
|
|
30
|
+
* arkServerUrl: 'https://ark.example.com'
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use like any other wallet
|
|
34
|
+
* const address = await wallet.getAddress();
|
|
35
|
+
* const balance = await wallet.getBalance();
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
13
38
|
class ServiceWorkerWallet {
|
|
14
39
|
constructor(serviceWorker) {
|
|
15
40
|
this.serviceWorker = serviceWorker;
|
|
@@ -44,11 +69,14 @@ class ServiceWorkerWallet {
|
|
|
44
69
|
type: "INIT_WALLET",
|
|
45
70
|
id: getRandomId(),
|
|
46
71
|
privateKey: config.privateKey,
|
|
47
|
-
|
|
48
|
-
arkServerUrl: config.arkServerUrl || "",
|
|
72
|
+
arkServerUrl: config.arkServerUrl,
|
|
49
73
|
arkServerPublicKey: config.arkServerPublicKey,
|
|
50
74
|
};
|
|
51
75
|
await this.sendMessage(message);
|
|
76
|
+
const privKeyBytes = base_1.hex.decode(config.privateKey);
|
|
77
|
+
// cache the identity xOnlyPublicKey
|
|
78
|
+
this.cachedXOnlyPublicKey =
|
|
79
|
+
singleKey_1.SingleKey.fromPrivateKey(privKeyBytes).xOnlyPublicKey();
|
|
52
80
|
}
|
|
53
81
|
async clear() {
|
|
54
82
|
const message = {
|
|
@@ -56,6 +84,8 @@ class ServiceWorkerWallet {
|
|
|
56
84
|
id: getRandomId(),
|
|
57
85
|
};
|
|
58
86
|
await this.sendMessage(message);
|
|
87
|
+
// clear the cached xOnlyPublicKey
|
|
88
|
+
this.cachedXOnlyPublicKey = undefined;
|
|
59
89
|
}
|
|
60
90
|
// send a message and wait for a response
|
|
61
91
|
async sendMessage(message) {
|
|
@@ -89,7 +119,7 @@ class ServiceWorkerWallet {
|
|
|
89
119
|
try {
|
|
90
120
|
const response = await this.sendMessage(message);
|
|
91
121
|
if (response_1.Response.isAddress(response)) {
|
|
92
|
-
return response.
|
|
122
|
+
return response.address;
|
|
93
123
|
}
|
|
94
124
|
throw new UnexpectedResponseError(response);
|
|
95
125
|
}
|
|
@@ -97,20 +127,20 @@ class ServiceWorkerWallet {
|
|
|
97
127
|
throw new Error(`Failed to get address: ${error}`);
|
|
98
128
|
}
|
|
99
129
|
}
|
|
100
|
-
async
|
|
130
|
+
async getBoardingAddress() {
|
|
101
131
|
const message = {
|
|
102
|
-
type: "
|
|
132
|
+
type: "GET_BOARDING_ADDRESS",
|
|
103
133
|
id: getRandomId(),
|
|
104
134
|
};
|
|
105
135
|
try {
|
|
106
136
|
const response = await this.sendMessage(message);
|
|
107
|
-
if (response_1.Response.
|
|
108
|
-
return response.
|
|
137
|
+
if (response_1.Response.isBoardingAddress(response)) {
|
|
138
|
+
return response.address;
|
|
109
139
|
}
|
|
110
140
|
throw new UnexpectedResponseError(response);
|
|
111
141
|
}
|
|
112
142
|
catch (error) {
|
|
113
|
-
throw new Error(`Failed to get address
|
|
143
|
+
throw new Error(`Failed to get boarding address: ${error}`);
|
|
114
144
|
}
|
|
115
145
|
}
|
|
116
146
|
async getBalance() {
|
|
@@ -129,26 +159,11 @@ class ServiceWorkerWallet {
|
|
|
129
159
|
throw new Error(`Failed to get balance: ${error}`);
|
|
130
160
|
}
|
|
131
161
|
}
|
|
132
|
-
async
|
|
133
|
-
const message = {
|
|
134
|
-
type: "GET_COINS",
|
|
135
|
-
id: getRandomId(),
|
|
136
|
-
};
|
|
137
|
-
try {
|
|
138
|
-
const response = await this.sendMessage(message);
|
|
139
|
-
if (response_1.Response.isCoins(response)) {
|
|
140
|
-
return response.coins;
|
|
141
|
-
}
|
|
142
|
-
throw new UnexpectedResponseError(response);
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
throw new Error(`Failed to get coins: ${error}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
async getVtxos() {
|
|
162
|
+
async getVtxos(filter) {
|
|
149
163
|
const message = {
|
|
150
164
|
type: "GET_VTXOS",
|
|
151
165
|
id: getRandomId(),
|
|
166
|
+
filter,
|
|
152
167
|
};
|
|
153
168
|
try {
|
|
154
169
|
const response = await this.sendMessage(message);
|
|
@@ -177,11 +192,10 @@ class ServiceWorkerWallet {
|
|
|
177
192
|
throw new Error(`Failed to get boarding UTXOs: ${error}`);
|
|
178
193
|
}
|
|
179
194
|
}
|
|
180
|
-
async sendBitcoin(params
|
|
195
|
+
async sendBitcoin(params) {
|
|
181
196
|
const message = {
|
|
182
197
|
type: "SEND_BITCOIN",
|
|
183
198
|
params,
|
|
184
|
-
zeroFee,
|
|
185
199
|
id: getRandomId(),
|
|
186
200
|
};
|
|
187
201
|
try {
|
|
@@ -248,21 +262,31 @@ class ServiceWorkerWallet {
|
|
|
248
262
|
throw new Error(`Failed to get transaction history: ${error}`);
|
|
249
263
|
}
|
|
250
264
|
}
|
|
251
|
-
|
|
265
|
+
xOnlyPublicKey() {
|
|
266
|
+
if (!this.cachedXOnlyPublicKey) {
|
|
267
|
+
throw new Error("Wallet not initialized");
|
|
268
|
+
}
|
|
269
|
+
return this.cachedXOnlyPublicKey;
|
|
270
|
+
}
|
|
271
|
+
signerSession() {
|
|
272
|
+
return signingSession_1.TreeSignerSession.random();
|
|
273
|
+
}
|
|
274
|
+
async sign(tx, inputIndexes) {
|
|
252
275
|
const message = {
|
|
253
|
-
type: "
|
|
254
|
-
|
|
276
|
+
type: "SIGN",
|
|
277
|
+
tx: base_1.base64.encode(tx.toPSBT()),
|
|
278
|
+
inputIndexes,
|
|
255
279
|
id: getRandomId(),
|
|
256
280
|
};
|
|
257
281
|
try {
|
|
258
282
|
const response = await this.sendMessage(message);
|
|
259
|
-
if (response
|
|
260
|
-
return;
|
|
283
|
+
if (response_1.Response.isSignSuccess(response)) {
|
|
284
|
+
return btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(response.tx));
|
|
261
285
|
}
|
|
262
286
|
throw new UnexpectedResponseError(response);
|
|
263
287
|
}
|
|
264
288
|
catch (error) {
|
|
265
|
-
throw new Error(`Failed to
|
|
289
|
+
throw new Error(`Failed to sign: ${error}`);
|
|
266
290
|
}
|
|
267
291
|
}
|
|
268
292
|
}
|
|
@@ -2,16 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Worker = void 0;
|
|
4
4
|
/// <reference lib="webworker" />
|
|
5
|
-
const
|
|
5
|
+
const singleKey_1 = require("../../identity/singleKey");
|
|
6
|
+
const __1 = require("..");
|
|
6
7
|
const wallet_1 = require("../wallet");
|
|
7
8
|
const request_1 = require("./request");
|
|
8
9
|
const response_1 = require("./response");
|
|
9
10
|
const ark_1 = require("../../providers/ark");
|
|
10
|
-
const default_1 = require("../../script/default");
|
|
11
11
|
const idb_1 = require("./db/vtxo/idb");
|
|
12
12
|
const transactionHistory_1 = require("../../utils/transactionHistory");
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const indexer_1 = require("../../providers/indexer");
|
|
14
|
+
const base_1 = require("@scure/base");
|
|
15
|
+
const btc_signer_1 = require("@scure/btc-signer");
|
|
16
|
+
/**
|
|
17
|
+
* Worker is a class letting to interact with ServiceWorkerWallet from the client
|
|
18
|
+
* it aims to be run in a service worker context
|
|
19
|
+
*/
|
|
15
20
|
class Worker {
|
|
16
21
|
constructor(vtxoRepository = new idb_1.IndexedDBVtxoRepository(), messageCallback = () => { }) {
|
|
17
22
|
this.vtxoRepository = vtxoRepository;
|
|
@@ -39,41 +44,48 @@ class Worker {
|
|
|
39
44
|
await this.vtxoRepository.close();
|
|
40
45
|
this.wallet = undefined;
|
|
41
46
|
this.arkProvider = undefined;
|
|
47
|
+
this.indexerProvider = undefined;
|
|
42
48
|
this.vtxoSubscription = undefined;
|
|
43
49
|
}
|
|
44
50
|
async onWalletInitialized() {
|
|
45
51
|
if (!this.wallet ||
|
|
46
52
|
!this.arkProvider ||
|
|
53
|
+
!this.indexerProvider ||
|
|
47
54
|
!this.wallet.offchainTapscript ||
|
|
48
55
|
!this.wallet.boardingTapscript) {
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
51
58
|
// subscribe to address updates
|
|
52
|
-
const addressInfo = await this.wallet.getAddressInfo();
|
|
53
|
-
if (!addressInfo.offchain) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
59
|
await this.vtxoRepository.open();
|
|
57
|
-
// set the initial vtxos state
|
|
58
|
-
const { spendableVtxos, spentVtxos } = await this.arkProvider.getVirtualCoins(addressInfo.offchain.address);
|
|
59
60
|
const encodedOffchainTapscript = this.wallet.offchainTapscript.encode();
|
|
60
61
|
const forfeit = this.wallet.offchainTapscript.forfeit();
|
|
61
|
-
const
|
|
62
|
+
const exit = this.wallet.offchainTapscript.exit();
|
|
63
|
+
const script = base_1.hex.encode(this.wallet.offchainTapscript.pkScript);
|
|
64
|
+
// set the initial vtxos state
|
|
65
|
+
const response = await this.indexerProvider.getVtxos({
|
|
66
|
+
scripts: [script],
|
|
67
|
+
});
|
|
68
|
+
const vtxos = response.vtxos.map((vtxo) => ({
|
|
62
69
|
...vtxo,
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
forfeitTapLeafScript: forfeit,
|
|
71
|
+
intentTapLeafScript: exit,
|
|
72
|
+
tapTree: encodedOffchainTapscript,
|
|
65
73
|
}));
|
|
66
74
|
await this.vtxoRepository.addOrUpdate(vtxos);
|
|
67
|
-
this.processVtxoSubscription(
|
|
75
|
+
this.processVtxoSubscription({
|
|
76
|
+
script,
|
|
77
|
+
vtxoScript: this.wallet.offchainTapscript,
|
|
78
|
+
});
|
|
68
79
|
}
|
|
69
|
-
async processVtxoSubscription({
|
|
80
|
+
async processVtxoSubscription({ script, vtxoScript, }) {
|
|
70
81
|
try {
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const tapLeafScript = vtxoScript.findLeaf(scripts.forfeit[0]);
|
|
82
|
+
const forfeitTapLeafScript = vtxoScript.forfeit();
|
|
83
|
+
const intentTapLeafScript = vtxoScript.exit();
|
|
74
84
|
const abortController = new AbortController();
|
|
75
|
-
const
|
|
85
|
+
const subscriptionId = await this.indexerProvider.subscribeForScripts([script]);
|
|
86
|
+
const subscription = this.indexerProvider.getSubscription(subscriptionId, abortController.signal);
|
|
76
87
|
this.vtxoSubscription = abortController;
|
|
88
|
+
const tapTree = vtxoScript.encode();
|
|
77
89
|
for await (const update of subscription) {
|
|
78
90
|
const vtxos = [...update.newVtxos, ...update.spentVtxos];
|
|
79
91
|
if (vtxos.length === 0) {
|
|
@@ -81,8 +93,9 @@ class Worker {
|
|
|
81
93
|
}
|
|
82
94
|
const extendedVtxos = vtxos.map((vtxo) => ({
|
|
83
95
|
...vtxo,
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
forfeitTapLeafScript,
|
|
97
|
+
intentTapLeafScript,
|
|
98
|
+
tapTree,
|
|
86
99
|
}));
|
|
87
100
|
await this.vtxoRepository.addOrUpdate(extendedVtxos);
|
|
88
101
|
}
|
|
@@ -106,9 +119,9 @@ class Worker {
|
|
|
106
119
|
}
|
|
107
120
|
try {
|
|
108
121
|
this.arkProvider = new ark_1.RestArkProvider(message.arkServerUrl);
|
|
122
|
+
this.indexerProvider = new indexer_1.RestIndexerProvider(message.arkServerUrl);
|
|
109
123
|
this.wallet = await wallet_1.Wallet.create({
|
|
110
|
-
|
|
111
|
-
identity: inMemoryKey_1.InMemoryKey.fromHex(message.privateKey),
|
|
124
|
+
identity: singleKey_1.SingleKey.fromHex(message.privateKey),
|
|
112
125
|
arkServerUrl: message.arkServerUrl,
|
|
113
126
|
arkServerPublicKey: message.arkServerPublicKey,
|
|
114
127
|
});
|
|
@@ -162,7 +175,7 @@ class Worker {
|
|
|
162
175
|
return;
|
|
163
176
|
}
|
|
164
177
|
try {
|
|
165
|
-
const txid = await this.wallet.sendBitcoin(message.params
|
|
178
|
+
const txid = await this.wallet.sendBitcoin(message.params);
|
|
166
179
|
event.source?.postMessage(response_1.Response.sendBitcoinSuccess(message.id, txid));
|
|
167
180
|
}
|
|
168
181
|
catch (error) {
|
|
@@ -186,8 +199,8 @@ class Worker {
|
|
|
186
199
|
return;
|
|
187
200
|
}
|
|
188
201
|
try {
|
|
189
|
-
const
|
|
190
|
-
event.source?.postMessage(response_1.Response.
|
|
202
|
+
const address = await this.wallet.getAddress();
|
|
203
|
+
event.source?.postMessage(response_1.Response.address(message.id, address));
|
|
191
204
|
}
|
|
192
205
|
catch (error) {
|
|
193
206
|
console.error("Error getting address:", error);
|
|
@@ -197,11 +210,11 @@ class Worker {
|
|
|
197
210
|
event.source?.postMessage(response_1.Response.error(message.id, errorMessage));
|
|
198
211
|
}
|
|
199
212
|
}
|
|
200
|
-
async
|
|
213
|
+
async handleGetBoardingAddress(event) {
|
|
201
214
|
const message = event.data;
|
|
202
|
-
if (!request_1.Request.
|
|
203
|
-
console.error("Invalid
|
|
204
|
-
event.source?.postMessage(response_1.Response.error(message.id, "Invalid
|
|
215
|
+
if (!request_1.Request.isGetBoardingAddress(message)) {
|
|
216
|
+
console.error("Invalid GET_BOARDING_ADDRESS message format", message);
|
|
217
|
+
event.source?.postMessage(response_1.Response.error(message.id, "Invalid GET_BOARDING_ADDRESS message format"));
|
|
205
218
|
return;
|
|
206
219
|
}
|
|
207
220
|
if (!this.wallet) {
|
|
@@ -210,11 +223,11 @@ class Worker {
|
|
|
210
223
|
return;
|
|
211
224
|
}
|
|
212
225
|
try {
|
|
213
|
-
const
|
|
214
|
-
event.source?.postMessage(response_1.Response.
|
|
226
|
+
const address = await this.wallet.getBoardingAddress();
|
|
227
|
+
event.source?.postMessage(response_1.Response.boardingAddress(message.id, address));
|
|
215
228
|
}
|
|
216
229
|
catch (error) {
|
|
217
|
-
console.error("Error getting address
|
|
230
|
+
console.error("Error getting boarding address:", error);
|
|
218
231
|
const errorMessage = error instanceof Error
|
|
219
232
|
? error.message
|
|
220
233
|
: "Unknown error occurred";
|
|
@@ -234,40 +247,52 @@ class Worker {
|
|
|
234
247
|
return;
|
|
235
248
|
}
|
|
236
249
|
try {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
.
|
|
240
|
-
.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
250
|
+
const [boardingUtxos, spendableVtxos, sweptVtxos] = await Promise.all([
|
|
251
|
+
this.wallet.getBoardingUtxos(),
|
|
252
|
+
this.vtxoRepository.getSpendableVtxos(),
|
|
253
|
+
this.vtxoRepository.getSweptVtxos(),
|
|
254
|
+
]);
|
|
255
|
+
// boarding
|
|
256
|
+
let confirmed = 0;
|
|
257
|
+
let unconfirmed = 0;
|
|
258
|
+
for (const utxo of boardingUtxos) {
|
|
259
|
+
if (utxo.status.confirmed) {
|
|
260
|
+
confirmed += utxo.value;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
unconfirmed += utxo.value;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// offchain
|
|
267
|
+
let settled = 0;
|
|
268
|
+
let preconfirmed = 0;
|
|
269
|
+
let recoverable = 0;
|
|
270
|
+
for (const vtxo of spendableVtxos) {
|
|
271
|
+
if (vtxo.virtualStatus.state === "settled") {
|
|
272
|
+
settled += vtxo.value;
|
|
273
|
+
}
|
|
274
|
+
else if (vtxo.virtualStatus.state === "preconfirmed") {
|
|
275
|
+
preconfirmed += vtxo.value;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
for (const vtxo of sweptVtxos) {
|
|
279
|
+
if ((0, __1.isSpendable)(vtxo)) {
|
|
280
|
+
recoverable += vtxo.value;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const totalBoarding = confirmed + unconfirmed;
|
|
284
|
+
const totalOffchain = settled + preconfirmed + recoverable;
|
|
258
285
|
event.source?.postMessage(response_1.Response.balance(message.id, {
|
|
259
|
-
|
|
260
|
-
confirmed
|
|
261
|
-
unconfirmed
|
|
262
|
-
total:
|
|
263
|
-
},
|
|
264
|
-
offchain: {
|
|
265
|
-
swept: offchainSweptBalance,
|
|
266
|
-
settled: offchainSettledBalance,
|
|
267
|
-
pending: offchainPendingBalance,
|
|
268
|
-
total: offchainTotal,
|
|
286
|
+
boarding: {
|
|
287
|
+
confirmed,
|
|
288
|
+
unconfirmed,
|
|
289
|
+
total: totalBoarding,
|
|
269
290
|
},
|
|
270
|
-
|
|
291
|
+
settled,
|
|
292
|
+
preconfirmed,
|
|
293
|
+
available: settled + preconfirmed,
|
|
294
|
+
recoverable,
|
|
295
|
+
total: totalBoarding + totalOffchain,
|
|
271
296
|
}));
|
|
272
297
|
}
|
|
273
298
|
catch (error) {
|
|
@@ -278,30 +303,6 @@ class Worker {
|
|
|
278
303
|
event.source?.postMessage(response_1.Response.error(message.id, errorMessage));
|
|
279
304
|
}
|
|
280
305
|
}
|
|
281
|
-
async handleGetCoins(event) {
|
|
282
|
-
const message = event.data;
|
|
283
|
-
if (!request_1.Request.isGetCoins(message)) {
|
|
284
|
-
console.error("Invalid GET_COINS message format", message);
|
|
285
|
-
event.source?.postMessage(response_1.Response.error(message.id, "Invalid GET_COINS message format"));
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
if (!this.wallet) {
|
|
289
|
-
console.error("Wallet not initialized");
|
|
290
|
-
event.source?.postMessage(response_1.Response.error(message.id, "Wallet not initialized"));
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
try {
|
|
294
|
-
const coins = await this.wallet.getCoins();
|
|
295
|
-
event.source?.postMessage(response_1.Response.coins(message.id, coins));
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
console.error("Error getting coins:", error);
|
|
299
|
-
const errorMessage = error instanceof Error
|
|
300
|
-
? error.message
|
|
301
|
-
: "Unknown error occurred";
|
|
302
|
-
event.source?.postMessage(response_1.Response.error(message.id, errorMessage));
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
306
|
async handleGetVtxos(event) {
|
|
306
307
|
const message = event.data;
|
|
307
308
|
if (!request_1.Request.isGetVtxos(message)) {
|
|
@@ -315,7 +316,18 @@ class Worker {
|
|
|
315
316
|
return;
|
|
316
317
|
}
|
|
317
318
|
try {
|
|
318
|
-
|
|
319
|
+
let vtxos = await this.vtxoRepository.getSpendableVtxos();
|
|
320
|
+
if (!message.filter?.withRecoverable) {
|
|
321
|
+
if (!this.wallet)
|
|
322
|
+
throw new Error("Wallet not initialized");
|
|
323
|
+
// exclude subdust is we don't want recoverable
|
|
324
|
+
vtxos = vtxos.filter((v) => !(0, __1.isSubdust)(v, this.wallet.dustAmount));
|
|
325
|
+
}
|
|
326
|
+
if (message.filter?.withRecoverable) {
|
|
327
|
+
// get also swept and spendable vtxos
|
|
328
|
+
const sweptVtxos = await this.vtxoRepository.getSweptVtxos();
|
|
329
|
+
vtxos.push(...sweptVtxos.filter(__1.isSpendable));
|
|
330
|
+
}
|
|
319
331
|
event.source?.postMessage(response_1.Response.vtxos(message.id, vtxos));
|
|
320
332
|
}
|
|
321
333
|
catch (error) {
|
|
@@ -363,7 +375,7 @@ class Worker {
|
|
|
363
375
|
return;
|
|
364
376
|
}
|
|
365
377
|
try {
|
|
366
|
-
const { boardingTxs, roundsToIgnore } = await this.wallet.getBoardingTxs();
|
|
378
|
+
const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.wallet.getBoardingTxs();
|
|
367
379
|
const { spendable, spent } = await this.vtxoRepository.getAllVtxos();
|
|
368
380
|
// convert VTXOs to offchain transactions
|
|
369
381
|
const offchainTxs = (0, transactionHistory_1.vtxosToTxs)(spendable, spent, roundsToIgnore);
|
|
@@ -397,11 +409,11 @@ class Worker {
|
|
|
397
409
|
}
|
|
398
410
|
event.source?.postMessage(response_1.Response.walletStatus(message.id, this.wallet !== undefined));
|
|
399
411
|
}
|
|
400
|
-
async
|
|
412
|
+
async handleSign(event) {
|
|
401
413
|
const message = event.data;
|
|
402
|
-
if (!request_1.Request.
|
|
403
|
-
console.error("Invalid
|
|
404
|
-
event.source?.postMessage(response_1.Response.error(message.id, "Invalid
|
|
414
|
+
if (!request_1.Request.isSign(message)) {
|
|
415
|
+
console.error("Invalid SIGN message format", message);
|
|
416
|
+
event.source?.postMessage(response_1.Response.error(message.id, "Invalid SIGN message format"));
|
|
405
417
|
return;
|
|
406
418
|
}
|
|
407
419
|
if (!this.wallet) {
|
|
@@ -410,11 +422,12 @@ class Worker {
|
|
|
410
422
|
return;
|
|
411
423
|
}
|
|
412
424
|
try {
|
|
413
|
-
|
|
414
|
-
|
|
425
|
+
const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(message.tx));
|
|
426
|
+
const signedTx = await this.wallet.identity.sign(tx, message.inputIndexes);
|
|
427
|
+
event.source?.postMessage(response_1.Response.signSuccess(message.id, base_1.base64.encode(signedTx.toPSBT())));
|
|
415
428
|
}
|
|
416
429
|
catch (error) {
|
|
417
|
-
console.error("Error
|
|
430
|
+
console.error("Error signing:", error);
|
|
418
431
|
const errorMessage = error instanceof Error
|
|
419
432
|
? error.message
|
|
420
433
|
: "Unknown error occurred";
|
|
@@ -446,18 +459,14 @@ class Worker {
|
|
|
446
459
|
await this.handleGetAddress(event);
|
|
447
460
|
break;
|
|
448
461
|
}
|
|
449
|
-
case "
|
|
450
|
-
await this.
|
|
462
|
+
case "GET_BOARDING_ADDRESS": {
|
|
463
|
+
await this.handleGetBoardingAddress(event);
|
|
451
464
|
break;
|
|
452
465
|
}
|
|
453
466
|
case "GET_BALANCE": {
|
|
454
467
|
await this.handleGetBalance(event);
|
|
455
468
|
break;
|
|
456
469
|
}
|
|
457
|
-
case "GET_COINS": {
|
|
458
|
-
await this.handleGetCoins(event);
|
|
459
|
-
break;
|
|
460
|
-
}
|
|
461
470
|
case "GET_VTXOS": {
|
|
462
471
|
await this.handleGetVtxos(event);
|
|
463
472
|
break;
|
|
@@ -474,14 +483,14 @@ class Worker {
|
|
|
474
483
|
await this.handleGetStatus(event);
|
|
475
484
|
break;
|
|
476
485
|
}
|
|
477
|
-
case "EXIT": {
|
|
478
|
-
await this.handleExit(event);
|
|
479
|
-
break;
|
|
480
|
-
}
|
|
481
486
|
case "CLEAR": {
|
|
482
487
|
await this.handleClear(event);
|
|
483
488
|
break;
|
|
484
489
|
}
|
|
490
|
+
case "SIGN": {
|
|
491
|
+
await this.handleSign(event);
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
485
494
|
default:
|
|
486
495
|
event.source?.postMessage(response_1.Response.error(message.id, "Unknown message type"));
|
|
487
496
|
}
|