@arkade-os/sdk 0.2.3 → 0.3.0-alpha.1

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.
Files changed (121) hide show
  1. package/README.md +114 -43
  2. package/dist/cjs/adapters/asyncStorage.js +5 -0
  3. package/dist/cjs/adapters/fileSystem.js +5 -0
  4. package/dist/cjs/adapters/indexedDB.js +5 -0
  5. package/dist/cjs/adapters/localStorage.js +5 -0
  6. package/dist/cjs/arknote/index.js +4 -4
  7. package/dist/cjs/bip322/index.js +11 -9
  8. package/dist/cjs/forfeit.js +2 -2
  9. package/dist/cjs/identity/index.js +15 -0
  10. package/dist/cjs/identity/singleKey.js +24 -5
  11. package/dist/cjs/index.js +7 -5
  12. package/dist/cjs/musig2/keys.js +7 -7
  13. package/dist/cjs/musig2/nonces.js +1 -1
  14. package/dist/cjs/musig2/sign.js +6 -6
  15. package/dist/cjs/networks.js +6 -6
  16. package/dist/cjs/repositories/contractRepository.js +130 -0
  17. package/dist/cjs/repositories/index.js +18 -0
  18. package/dist/cjs/repositories/walletRepository.js +136 -0
  19. package/dist/cjs/script/address.js +3 -3
  20. package/dist/cjs/script/base.js +7 -7
  21. package/dist/cjs/script/tapscript.js +21 -21
  22. package/dist/cjs/script/vhtlc.js +2 -2
  23. package/dist/cjs/storage/asyncStorage.js +47 -0
  24. package/dist/cjs/storage/fileSystem.js +138 -0
  25. package/dist/cjs/storage/inMemory.js +21 -0
  26. package/dist/cjs/storage/indexedDB.js +97 -0
  27. package/dist/cjs/storage/localStorage.js +48 -0
  28. package/dist/cjs/tree/signingSession.js +12 -11
  29. package/dist/cjs/tree/txTree.js +6 -6
  30. package/dist/cjs/tree/validation.js +5 -5
  31. package/dist/cjs/utils/arkTransaction.js +5 -5
  32. package/dist/cjs/utils/unknownFields.js +5 -5
  33. package/dist/cjs/wallet/onchain.js +16 -10
  34. package/dist/cjs/wallet/serviceWorker/request.js +4 -14
  35. package/dist/cjs/wallet/serviceWorker/response.js +0 -13
  36. package/dist/cjs/wallet/serviceWorker/wallet.js +124 -130
  37. package/dist/cjs/wallet/serviceWorker/worker.js +84 -53
  38. package/dist/cjs/wallet/unroll.js +6 -6
  39. package/dist/cjs/wallet/wallet.js +37 -20
  40. package/dist/esm/adapters/asyncStorage.js +1 -0
  41. package/dist/esm/adapters/fileSystem.js +1 -0
  42. package/dist/esm/adapters/indexedDB.js +1 -0
  43. package/dist/esm/adapters/localStorage.js +1 -0
  44. package/dist/esm/arknote/index.js +2 -2
  45. package/dist/esm/bip322/index.js +4 -2
  46. package/dist/esm/forfeit.js +1 -1
  47. package/dist/esm/identity/index.js +1 -1
  48. package/dist/esm/identity/singleKey.js +22 -3
  49. package/dist/esm/index.js +5 -4
  50. package/dist/esm/musig2/keys.js +7 -7
  51. package/dist/esm/musig2/nonces.js +1 -1
  52. package/dist/esm/musig2/sign.js +5 -5
  53. package/dist/esm/networks.js +1 -1
  54. package/dist/esm/repositories/contractRepository.js +126 -0
  55. package/dist/esm/repositories/index.js +2 -0
  56. package/dist/esm/repositories/walletRepository.js +132 -0
  57. package/dist/esm/script/address.js +1 -1
  58. package/dist/esm/script/base.js +3 -3
  59. package/dist/esm/script/tapscript.js +2 -2
  60. package/dist/esm/script/vhtlc.js +1 -1
  61. package/dist/esm/storage/asyncStorage.js +43 -0
  62. package/dist/esm/storage/fileSystem.js +101 -0
  63. package/dist/esm/storage/inMemory.js +17 -0
  64. package/dist/esm/storage/indexedDB.js +93 -0
  65. package/dist/esm/storage/localStorage.js +44 -0
  66. package/dist/esm/tree/signingSession.js +4 -3
  67. package/dist/esm/tree/txTree.js +2 -2
  68. package/dist/esm/tree/validation.js +2 -2
  69. package/dist/esm/utils/arkTransaction.js +2 -2
  70. package/dist/esm/utils/unknownFields.js +1 -1
  71. package/dist/esm/wallet/onchain.js +14 -8
  72. package/dist/esm/wallet/serviceWorker/request.js +4 -14
  73. package/dist/esm/wallet/serviceWorker/response.js +0 -13
  74. package/dist/esm/wallet/serviceWorker/wallet.js +125 -131
  75. package/dist/esm/wallet/serviceWorker/worker.js +85 -54
  76. package/dist/esm/wallet/unroll.js +2 -2
  77. package/dist/esm/wallet/wallet.js +25 -8
  78. package/dist/types/adapters/asyncStorage.d.ts +2 -0
  79. package/dist/types/adapters/fileSystem.d.ts +2 -0
  80. package/dist/types/adapters/indexedDB.d.ts +2 -0
  81. package/dist/types/adapters/localStorage.d.ts +2 -0
  82. package/dist/types/arknote/index.d.ts +1 -1
  83. package/dist/types/bip322/index.d.ts +2 -2
  84. package/dist/types/forfeit.d.ts +1 -1
  85. package/dist/types/identity/index.d.ts +4 -2
  86. package/dist/types/identity/singleKey.d.ts +13 -2
  87. package/dist/types/index.d.ts +5 -5
  88. package/dist/types/repositories/contractRepository.d.ts +20 -0
  89. package/dist/types/repositories/index.d.ts +2 -0
  90. package/dist/types/repositories/walletRepository.d.ts +38 -0
  91. package/dist/types/script/address.d.ts +1 -1
  92. package/dist/types/script/base.d.ts +1 -1
  93. package/dist/types/script/default.d.ts +1 -1
  94. package/dist/types/script/tapscript.d.ts +1 -1
  95. package/dist/types/script/vhtlc.d.ts +1 -1
  96. package/dist/types/storage/asyncStorage.d.ts +9 -0
  97. package/dist/types/storage/fileSystem.d.ts +11 -0
  98. package/dist/types/storage/inMemory.d.ts +8 -0
  99. package/dist/types/storage/index.d.ts +6 -0
  100. package/dist/types/storage/indexedDB.d.ts +12 -0
  101. package/dist/types/storage/localStorage.d.ts +8 -0
  102. package/dist/types/tree/txTree.d.ts +1 -1
  103. package/dist/types/tree/validation.d.ts +1 -1
  104. package/dist/types/utils/anchor.d.ts +1 -1
  105. package/dist/types/utils/arkTransaction.d.ts +3 -3
  106. package/dist/types/utils/unknownFields.d.ts +1 -1
  107. package/dist/types/wallet/index.d.ts +4 -1
  108. package/dist/types/wallet/onchain.d.ts +5 -4
  109. package/dist/types/wallet/serviceWorker/request.d.ts +1 -7
  110. package/dist/types/wallet/serviceWorker/response.d.ts +1 -8
  111. package/dist/types/wallet/serviceWorker/wallet.d.ts +67 -21
  112. package/dist/types/wallet/serviceWorker/worker.d.ts +16 -4
  113. package/dist/types/wallet/unroll.d.ts +1 -1
  114. package/dist/types/wallet/wallet.d.ts +5 -1
  115. package/package.json +39 -15
  116. package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +0 -185
  117. package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +0 -181
  118. package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +0 -20
  119. package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +0 -14
  120. /package/dist/cjs/{wallet/serviceWorker/db/vtxo → storage}/index.js +0 -0
  121. /package/dist/esm/{wallet/serviceWorker/db/vtxo → storage}/index.js +0 -0
@@ -3,93 +3,91 @@ 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
+ const indexedDB_1 = require("../../storage/indexedDB");
7
+ const walletRepository_1 = require("../../repositories/walletRepository");
8
+ const contractRepository_1 = require("../../repositories/contractRepository");
9
+ const utils_1 = require("./utils");
10
+ const isPrivateKeyIdentity = (identity) => {
11
+ return (identity.toHex !== undefined &&
12
+ typeof identity.toHex === "function" &&
13
+ typeof identity.toHex() === "string" &&
14
+ identity.toHex().length > 0);
15
+ };
9
16
  class UnexpectedResponseError extends Error {
10
17
  constructor(response) {
11
18
  super(`Unexpected response type. Got: ${JSON.stringify(response, null, 2)}`);
12
19
  this.name = "UnexpectedResponseError";
13
20
  }
14
21
  }
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
- */
38
22
  class ServiceWorkerWallet {
39
- constructor(serviceWorker) {
23
+ constructor(serviceWorker, identity, walletRepository, contractRepository) {
40
24
  this.serviceWorker = serviceWorker;
25
+ this.identity = identity;
26
+ this.walletRepository = walletRepository;
27
+ this.contractRepository = contractRepository;
41
28
  }
42
- async getStatus() {
43
- const message = {
44
- type: "GET_STATUS",
45
- id: getRandomId(),
46
- };
47
- const response = await this.sendMessage(message);
48
- if (response_1.Response.isWalletStatus(response)) {
49
- const { walletInitialized, xOnlyPublicKey } = response.status;
50
- if (walletInitialized)
51
- this.cachedXOnlyPublicKey = xOnlyPublicKey;
52
- return response.status;
53
- }
54
- throw new UnexpectedResponseError(response);
55
- }
56
- async init(config, failIfInitialized = false) {
57
- // Check if wallet is already initialized
58
- const statusMessage = {
59
- type: "GET_STATUS",
60
- id: getRandomId(),
61
- };
62
- const response = await this.sendMessage(statusMessage);
63
- if (response_1.Response.isWalletStatus(response) &&
64
- response.status.walletInitialized) {
65
- if (failIfInitialized) {
66
- throw new Error("Wallet already initialized");
67
- }
68
- this.cachedXOnlyPublicKey = response.status.xOnlyPublicKey;
69
- return;
29
+ static async create(options) {
30
+ // Default to IndexedDB for service worker context
31
+ const storage = options.storage || new indexedDB_1.IndexedDBStorageAdapter("wallet-db");
32
+ // Create repositories
33
+ const walletRepo = new walletRepository_1.WalletRepositoryImpl(storage);
34
+ const contractRepo = new contractRepository_1.ContractRepositoryImpl(storage);
35
+ // Extract identity and check if it can expose private key
36
+ const identity = isPrivateKeyIdentity(options.identity)
37
+ ? options.identity
38
+ : null;
39
+ if (!identity) {
40
+ throw new Error("ServiceWorkerWallet.create() requires a Identity that can expose its private key");
70
41
  }
71
- // If not initialized, proceed with initialization
72
- const message = {
42
+ // Extract private key for service worker initialization
43
+ const privateKey = identity.toHex();
44
+ // Create the wallet instance
45
+ const wallet = new ServiceWorkerWallet(options.serviceWorker, identity, walletRepo, contractRepo);
46
+ // Initialize the service worker with the config
47
+ const initMessage = {
73
48
  type: "INIT_WALLET",
74
49
  id: getRandomId(),
75
- privateKey: config.privateKey,
76
- arkServerUrl: config.arkServerUrl,
77
- arkServerPublicKey: config.arkServerPublicKey,
50
+ privateKey,
51
+ arkServerUrl: options.arkServerUrl,
52
+ arkServerPublicKey: options.arkServerPublicKey,
78
53
  };
79
- await this.sendMessage(message);
80
- const privKeyBytes = base_1.hex.decode(config.privateKey);
81
- // cache the identity xOnlyPublicKey
82
- this.cachedXOnlyPublicKey =
83
- singleKey_1.SingleKey.fromPrivateKey(privKeyBytes).xOnlyPublicKey();
54
+ // Initialize the service worker
55
+ await wallet.sendMessage(initMessage);
56
+ return wallet;
84
57
  }
85
- async clear() {
86
- const message = {
87
- type: "CLEAR",
88
- id: getRandomId(),
89
- };
90
- await this.sendMessage(message);
91
- // clear the cached xOnlyPublicKey
92
- this.cachedXOnlyPublicKey = undefined;
58
+ /**
59
+ * Simplified setup method that handles service worker registration,
60
+ * identity creation, and wallet initialization automatically.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * // One-liner setup - handles everything automatically!
65
+ * const wallet = await ServiceWorkerWallet.setup({
66
+ * serviceWorkerPath: '/service-worker.js',
67
+ * arkServerUrl: 'https://mutinynet.arkade.sh'
68
+ * });
69
+ *
70
+ * // With custom identity
71
+ * const identity = SingleKey.fromHex('your_private_key_hex');
72
+ * const wallet = await ServiceWorkerWallet.setup({
73
+ * serviceWorkerPath: '/service-worker.js',
74
+ * arkServerUrl: 'https://mutinynet.arkade.sh',
75
+ * identity
76
+ * });
77
+ * ```
78
+ */
79
+ static async setup(options) {
80
+ // Register and setup the service worker
81
+ const serviceWorker = await (0, utils_1.setupServiceWorker)(options.serviceWorkerPath);
82
+ // Use the existing create method
83
+ return await ServiceWorkerWallet.create({
84
+ arkServerPublicKey: options.arkServerPublicKey,
85
+ arkServerUrl: options.arkServerUrl,
86
+ esploraUrl: options.esploraUrl,
87
+ identity: options.identity,
88
+ serviceWorker,
89
+ storage: options.storage,
90
+ });
93
91
  }
94
92
  // send a message and wait for a response
95
93
  async sendMessage(message) {
@@ -115,6 +113,21 @@ class ServiceWorkerWallet {
115
113
  this.serviceWorker.postMessage(message);
116
114
  });
117
115
  }
116
+ async clear() {
117
+ const message = {
118
+ type: "CLEAR",
119
+ id: getRandomId(),
120
+ };
121
+ // Clear page-side storage to maintain parity with SW
122
+ try {
123
+ const address = await this.getAddress();
124
+ await this.walletRepository.clearVtxos(address);
125
+ }
126
+ catch (_) {
127
+ console.warn("Failed to clear vtxos from wallet repository");
128
+ }
129
+ await this.sendMessage(message);
130
+ }
118
131
  async getAddress() {
119
132
  const message = {
120
133
  type: "GET_ADDRESS",
@@ -163,37 +176,64 @@ class ServiceWorkerWallet {
163
176
  throw new Error(`Failed to get balance: ${error}`);
164
177
  }
165
178
  }
166
- async getVtxos(filter) {
179
+ async getBoardingUtxos() {
167
180
  const message = {
168
- type: "GET_VTXOS",
181
+ type: "GET_BOARDING_UTXOS",
169
182
  id: getRandomId(),
170
- filter,
171
183
  };
172
184
  try {
173
185
  const response = await this.sendMessage(message);
174
- if (response_1.Response.isVtxos(response)) {
175
- return response.vtxos;
186
+ if (response_1.Response.isBoardingUtxos(response)) {
187
+ return response.boardingUtxos;
176
188
  }
177
189
  throw new UnexpectedResponseError(response);
178
190
  }
179
191
  catch (error) {
180
- throw new Error(`Failed to get vtxos: ${error}`);
192
+ throw new Error(`Failed to get boarding UTXOs: ${error}`);
181
193
  }
182
194
  }
183
- async getBoardingUtxos() {
195
+ async getStatus() {
184
196
  const message = {
185
- type: "GET_BOARDING_UTXOS",
197
+ type: "GET_STATUS",
198
+ id: getRandomId(),
199
+ };
200
+ const response = await this.sendMessage(message);
201
+ if (response_1.Response.isWalletStatus(response)) {
202
+ return response.status;
203
+ }
204
+ throw new UnexpectedResponseError(response);
205
+ }
206
+ async getTransactionHistory() {
207
+ const message = {
208
+ type: "GET_TRANSACTION_HISTORY",
186
209
  id: getRandomId(),
187
210
  };
188
211
  try {
189
212
  const response = await this.sendMessage(message);
190
- if (response_1.Response.isBoardingUtxos(response)) {
191
- return response.boardingUtxos;
213
+ if (response_1.Response.isTransactionHistory(response)) {
214
+ return response.transactions;
192
215
  }
193
216
  throw new UnexpectedResponseError(response);
194
217
  }
195
218
  catch (error) {
196
- throw new Error(`Failed to get boarding UTXOs: ${error}`);
219
+ throw new Error(`Failed to get transaction history: ${error}`);
220
+ }
221
+ }
222
+ async getVtxos(filter) {
223
+ const message = {
224
+ type: "GET_VTXOS",
225
+ id: getRandomId(),
226
+ filter,
227
+ };
228
+ try {
229
+ const response = await this.sendMessage(message);
230
+ if (response_1.Response.isVtxos(response)) {
231
+ return response.vtxos;
232
+ }
233
+ throw new UnexpectedResponseError(response);
234
+ }
235
+ catch (error) {
236
+ throw new Error(`Failed to get vtxos: ${error}`);
197
237
  }
198
238
  }
199
239
  async sendBitcoin(params) {
@@ -250,52 +290,6 @@ class ServiceWorkerWallet {
250
290
  throw new Error(`Settlement failed: ${error}`);
251
291
  }
252
292
  }
253
- async getTransactionHistory() {
254
- const message = {
255
- type: "GET_TRANSACTION_HISTORY",
256
- id: getRandomId(),
257
- };
258
- try {
259
- const response = await this.sendMessage(message);
260
- if (response_1.Response.isTransactionHistory(response)) {
261
- return response.transactions;
262
- }
263
- throw new UnexpectedResponseError(response);
264
- }
265
- catch (error) {
266
- throw new Error(`Failed to get transaction history: ${error}`);
267
- }
268
- }
269
- xOnlyPublicKey() {
270
- if (!this.cachedXOnlyPublicKey) {
271
- throw new Error("Wallet not initialized");
272
- }
273
- return this.cachedXOnlyPublicKey;
274
- }
275
- signerSession() {
276
- return signingSession_1.TreeSignerSession.random();
277
- }
278
- async sign(tx, inputIndexes) {
279
- const message = {
280
- type: "SIGN",
281
- tx: base_1.base64.encode(tx.toPSBT()),
282
- inputIndexes,
283
- id: getRandomId(),
284
- };
285
- try {
286
- const response = await this.sendMessage(message);
287
- if (response_1.Response.isSignSuccess(response)) {
288
- return btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(response.tx), {
289
- allowUnknown: true,
290
- allowUnknownInputs: true,
291
- });
292
- }
293
- throw new UnexpectedResponseError(response);
294
- }
295
- catch (error) {
296
- throw new Error(`Failed to sign: ${error}`);
297
- }
298
- }
299
293
  }
300
294
  exports.ServiceWorkerWallet = ServiceWorkerWallet;
301
295
  function getRandomId() {
@@ -8,19 +8,53 @@ const wallet_1 = require("../wallet");
8
8
  const request_1 = require("./request");
9
9
  const response_1 = require("./response");
10
10
  const ark_1 = require("../../providers/ark");
11
- const idb_1 = require("./db/vtxo/idb");
12
11
  const transactionHistory_1 = require("../../utils/transactionHistory");
13
12
  const indexer_1 = require("../../providers/indexer");
14
13
  const base_1 = require("@scure/base");
15
- const btc_signer_1 = require("@scure/btc-signer");
14
+ const indexedDB_1 = require("../../storage/indexedDB");
15
+ const walletRepository_1 = require("../../repositories/walletRepository");
16
16
  /**
17
17
  * Worker is a class letting to interact with ServiceWorkerWallet from the client
18
18
  * it aims to be run in a service worker context
19
19
  */
20
20
  class Worker {
21
- constructor(vtxoRepository = new idb_1.IndexedDBVtxoRepository(), messageCallback = () => { }) {
22
- this.vtxoRepository = vtxoRepository;
21
+ constructor(messageCallback = () => { }) {
23
22
  this.messageCallback = messageCallback;
23
+ this.storage = new indexedDB_1.IndexedDBStorageAdapter("arkade-service-worker", 1);
24
+ this.walletRepository = new walletRepository_1.WalletRepositoryImpl(this.storage);
25
+ }
26
+ /**
27
+ * Get spendable vtxos for the current wallet address
28
+ */
29
+ async getSpendableVtxos() {
30
+ if (!this.wallet)
31
+ return [];
32
+ const address = await this.wallet.getAddress();
33
+ const allVtxos = await this.walletRepository.getVtxos(address);
34
+ return allVtxos.filter(__1.isSpendable);
35
+ }
36
+ /**
37
+ * Get swept vtxos for the current wallet address
38
+ */
39
+ async getSweptVtxos() {
40
+ if (!this.wallet)
41
+ return [];
42
+ const address = await this.wallet.getAddress();
43
+ const allVtxos = await this.walletRepository.getVtxos(address);
44
+ return allVtxos.filter((vtxo) => vtxo.virtualStatus.state === "swept" && (0, __1.isSpendable)(vtxo));
45
+ }
46
+ /**
47
+ * Get all vtxos categorized by type
48
+ */
49
+ async getAllVtxos() {
50
+ if (!this.wallet)
51
+ return { spendable: [], spent: [] };
52
+ const address = await this.wallet.getAddress();
53
+ const allVtxos = await this.walletRepository.getVtxos(address);
54
+ return {
55
+ spendable: allVtxos.filter(__1.isSpendable),
56
+ spent: allVtxos.filter((vtxo) => !(0, __1.isSpendable)(vtxo)),
57
+ };
24
58
  }
25
59
  async start(withServiceWorkerUpdate = true) {
26
60
  self.addEventListener("message", async (event) => {
@@ -41,7 +75,8 @@ class Worker {
41
75
  if (this.vtxoSubscription) {
42
76
  this.vtxoSubscription.abort();
43
77
  }
44
- await this.vtxoRepository.close();
78
+ // Clear storage - this replaces vtxoRepository.close()
79
+ await this.storage.clear();
45
80
  this.wallet = undefined;
46
81
  this.arkProvider = undefined;
47
82
  this.indexerProvider = undefined;
@@ -60,8 +95,6 @@ class Worker {
60
95
  !this.wallet.boardingTapscript) {
61
96
  return;
62
97
  }
63
- // subscribe to address updates
64
- await this.vtxoRepository.open();
65
98
  const encodedOffchainTapscript = this.wallet.offchainTapscript.encode();
66
99
  const forfeit = this.wallet.offchainTapscript.forfeit();
67
100
  const exit = this.wallet.offchainTapscript.exit();
@@ -76,7 +109,9 @@ class Worker {
76
109
  intentTapLeafScript: exit,
77
110
  tapTree: encodedOffchainTapscript,
78
111
  }));
79
- await this.vtxoRepository.addOrUpdate(vtxos);
112
+ // Get wallet address and save vtxos using unified repository
113
+ const address = await this.wallet.getAddress();
114
+ await this.walletRepository.saveVtxos(address, vtxos);
80
115
  this.processVtxoSubscription({
81
116
  script,
82
117
  vtxoScript: this.wallet.offchainTapscript,
@@ -102,7 +137,11 @@ class Worker {
102
137
  intentTapLeafScript,
103
138
  tapTree,
104
139
  }));
105
- await this.vtxoRepository.addOrUpdate(extendedVtxos);
140
+ // Get wallet address and save vtxos using unified repository
141
+ const address = await this.wallet.getAddress();
142
+ await this.walletRepository.saveVtxos(address, extendedVtxos);
143
+ // Notify all clients about the vtxo update
144
+ this.sendMessageToAllClients("VTXO_UPDATE", "");
106
145
  }
107
146
  }
108
147
  catch (error) {
@@ -110,7 +149,7 @@ class Worker {
110
149
  }
111
150
  }
112
151
  async handleClear(event) {
113
- this.clear();
152
+ await this.clear();
114
153
  if (request_1.Request.isBase(event.data)) {
115
154
  event.source?.postMessage(response_1.Response.clearResponse(event.data.id, true));
116
155
  }
@@ -122,13 +161,22 @@ class Worker {
122
161
  event.source?.postMessage(response_1.Response.error(message.id, "Invalid INIT_WALLET message format"));
123
162
  return;
124
163
  }
164
+ if (!message.privateKey) {
165
+ const err = "Missing privateKey";
166
+ event.source?.postMessage(response_1.Response.error(message.id, err));
167
+ console.error(err);
168
+ return;
169
+ }
125
170
  try {
126
- this.arkProvider = new ark_1.RestArkProvider(message.arkServerUrl);
127
- this.indexerProvider = new indexer_1.RestIndexerProvider(message.arkServerUrl);
171
+ const { arkServerPublicKey, arkServerUrl, privateKey } = message;
172
+ const identity = singleKey_1.SingleKey.fromHex(privateKey);
173
+ this.arkProvider = new ark_1.RestArkProvider(arkServerUrl);
174
+ this.indexerProvider = new indexer_1.RestIndexerProvider(arkServerUrl);
128
175
  this.wallet = await wallet_1.Wallet.create({
129
- identity: singleKey_1.SingleKey.fromHex(message.privateKey),
130
- arkServerUrl: message.arkServerUrl,
131
- arkServerPublicKey: message.arkServerPublicKey,
176
+ identity,
177
+ arkServerUrl,
178
+ arkServerPublicKey,
179
+ storage: this.storage, // Use unified storage for wallet too
132
180
  });
133
181
  event.source?.postMessage(response_1.Response.walletInitialized(message.id));
134
182
  await this.onWalletInitialized();
@@ -254,8 +302,8 @@ class Worker {
254
302
  try {
255
303
  const [boardingUtxos, spendableVtxos, sweptVtxos] = await Promise.all([
256
304
  this.wallet.getBoardingUtxos(),
257
- this.vtxoRepository.getSpendableVtxos(),
258
- this.vtxoRepository.getSweptVtxos(),
305
+ this.getSpendableVtxos(),
306
+ this.getSweptVtxos(),
259
307
  ]);
260
308
  // boarding
261
309
  let confirmed = 0;
@@ -321,7 +369,7 @@ class Worker {
321
369
  return;
322
370
  }
323
371
  try {
324
- let vtxos = await this.vtxoRepository.getSpendableVtxos();
372
+ let vtxos = await this.getSpendableVtxos();
325
373
  if (!message.filter?.withRecoverable) {
326
374
  if (!this.wallet)
327
375
  throw new Error("Wallet not initialized");
@@ -330,7 +378,7 @@ class Worker {
330
378
  }
331
379
  if (message.filter?.withRecoverable) {
332
380
  // get also swept and spendable vtxos
333
- const sweptVtxos = await this.vtxoRepository.getSweptVtxos();
381
+ const sweptVtxos = await this.getSweptVtxos();
334
382
  vtxos.push(...sweptVtxos.filter(__1.isSpendable));
335
383
  }
336
384
  event.source?.postMessage(response_1.Response.vtxos(message.id, vtxos));
@@ -381,7 +429,7 @@ class Worker {
381
429
  }
382
430
  try {
383
431
  const { boardingTxs, commitmentsToIgnore: roundsToIgnore } = await this.wallet.getBoardingTxs();
384
- const { spendable, spent } = await this.vtxoRepository.getAllVtxos();
432
+ const { spendable, spent } = await this.getAllVtxos();
385
433
  // convert VTXOs to offchain transactions
386
434
  const offchainTxs = (0, transactionHistory_1.vtxosToTxs)(spendable, spent, roundsToIgnore);
387
435
  const txs = [...boardingTxs, ...offchainTxs];
@@ -412,35 +460,10 @@ class Worker {
412
460
  event.source?.postMessage(response_1.Response.error(message.id, "Invalid GET_STATUS message format"));
413
461
  return;
414
462
  }
415
- event.source?.postMessage(response_1.Response.walletStatus(message.id, this.wallet !== undefined, this.wallet?.identity.xOnlyPublicKey()));
416
- }
417
- async handleSign(event) {
418
- const message = event.data;
419
- if (!request_1.Request.isSign(message)) {
420
- console.error("Invalid SIGN message format", message);
421
- event.source?.postMessage(response_1.Response.error(message.id, "Invalid SIGN message format"));
422
- return;
423
- }
424
- if (!this.wallet) {
425
- console.error("Wallet not initialized");
426
- event.source?.postMessage(response_1.Response.error(message.id, "Wallet not initialized"));
427
- return;
428
- }
429
- try {
430
- const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(message.tx), {
431
- allowUnknown: true,
432
- allowUnknownInputs: true,
433
- });
434
- const signedTx = await this.wallet.identity.sign(tx, message.inputIndexes);
435
- event.source?.postMessage(response_1.Response.signSuccess(message.id, base_1.base64.encode(signedTx.toPSBT())));
436
- }
437
- catch (error) {
438
- console.error("Error signing:", error);
439
- const errorMessage = error instanceof Error
440
- ? error.message
441
- : "Unknown error occurred";
442
- event.source?.postMessage(response_1.Response.error(message.id, errorMessage));
443
- }
463
+ const pubKey = this.wallet
464
+ ? await this.wallet.identity.xOnlyPublicKey()
465
+ : undefined;
466
+ event.source?.postMessage(response_1.Response.walletStatus(message.id, this.wallet !== undefined, pubKey));
444
467
  }
445
468
  async handleMessage(event) {
446
469
  this.messageCallback(event);
@@ -495,13 +518,21 @@ class Worker {
495
518
  await this.handleClear(event);
496
519
  break;
497
520
  }
498
- case "SIGN": {
499
- await this.handleSign(event);
500
- break;
501
- }
502
521
  default:
503
522
  event.source?.postMessage(response_1.Response.error(message.id, "Unknown message type"));
504
523
  }
505
524
  }
525
+ async sendMessageToAllClients(type, message) {
526
+ self.clients
527
+ .matchAll({ includeUncontrolled: true, type: "window" })
528
+ .then((clients) => {
529
+ clients.forEach((client) => {
530
+ client.postMessage({
531
+ type,
532
+ message,
533
+ });
534
+ });
535
+ });
536
+ }
506
537
  }
507
538
  exports.Worker = Worker;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Unroll = void 0;
4
- const btc_signer_1 = require("@scure/btc-signer");
4
+ const transaction_js_1 = require("@scure/btc-signer/transaction.js");
5
5
  const indexer_1 = require("../providers/indexer");
6
6
  const base_1 = require("@scure/base");
7
7
  const base_2 = require("../script/base");
8
- const psbt_1 = require("@scure/btc-signer/psbt");
8
+ const psbt_js_1 = require("@scure/btc-signer/psbt.js");
9
9
  const txSizeEstimator_1 = require("../utils/txSizeEstimator");
10
10
  const wallet_1 = require("./wallet");
11
11
  var Unroll;
@@ -106,7 +106,7 @@ var Unroll;
106
106
  if (virtualTxs.txs.length === 0) {
107
107
  throw new Error(`Tx ${nextTxToBroadcast.txid} not found`);
108
108
  }
109
- const tx = btc_signer_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
109
+ const tx = transaction_js_1.Transaction.fromPSBT(base_1.base64.decode(virtualTxs.txs[0]), {
110
110
  allowUnknownInputs: true,
111
111
  });
112
112
  // finalize the tree transaction
@@ -197,11 +197,11 @@ var Unroll;
197
197
  amount: BigInt(vtxo.value),
198
198
  script: base_2.VtxoScript.decode(vtxo.tapTree).pkScript,
199
199
  },
200
- sighashType: btc_signer_1.SigHash.DEFAULT,
200
+ sighashType: transaction_js_1.SigHash.DEFAULT,
201
201
  });
202
- txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, psbt_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
202
+ txWeightEstimator.addTapscriptInput(64, spendingLeaf[1].length, psbt_js_1.TaprootControlBlock.encode(spendingLeaf[0]).length);
203
203
  }
204
- const tx = new btc_signer_1.Transaction({ allowUnknownInputs: true, version: 2 });
204
+ const tx = new transaction_js_1.Transaction({ allowUnknownInputs: true, version: 2 });
205
205
  for (const input of inputs) {
206
206
  tx.addInput(input);
207
207
  }