@arkade-os/sdk 0.1.3 → 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.
Files changed (114) hide show
  1. package/README.md +156 -174
  2. package/dist/cjs/arknote/index.js +61 -58
  3. package/dist/cjs/bip322/errors.js +13 -0
  4. package/dist/cjs/bip322/index.js +178 -0
  5. package/dist/cjs/forfeit.js +14 -25
  6. package/dist/cjs/identity/singleKey.js +68 -0
  7. package/dist/cjs/index.js +41 -17
  8. package/dist/cjs/providers/ark.js +253 -317
  9. package/dist/cjs/providers/indexer.js +525 -0
  10. package/dist/cjs/providers/onchain.js +193 -15
  11. package/dist/cjs/script/address.js +48 -17
  12. package/dist/cjs/script/base.js +120 -3
  13. package/dist/cjs/script/default.js +18 -4
  14. package/dist/cjs/script/tapscript.js +46 -14
  15. package/dist/cjs/script/vhtlc.js +27 -7
  16. package/dist/cjs/tree/signingSession.js +63 -106
  17. package/dist/cjs/tree/txTree.js +193 -0
  18. package/dist/cjs/tree/validation.js +79 -155
  19. package/dist/cjs/utils/anchor.js +35 -0
  20. package/dist/cjs/utils/arkTransaction.js +108 -0
  21. package/dist/cjs/utils/transactionHistory.js +84 -72
  22. package/dist/cjs/utils/txSizeEstimator.js +12 -0
  23. package/dist/cjs/utils/unknownFields.js +211 -0
  24. package/dist/cjs/wallet/index.js +12 -0
  25. package/dist/cjs/wallet/onchain.js +201 -0
  26. package/dist/cjs/wallet/ramps.js +95 -0
  27. package/dist/cjs/wallet/serviceWorker/db/vtxo/idb.js +32 -0
  28. package/dist/cjs/wallet/serviceWorker/request.js +15 -12
  29. package/dist/cjs/wallet/serviceWorker/response.js +22 -27
  30. package/dist/cjs/wallet/serviceWorker/utils.js +8 -0
  31. package/dist/cjs/wallet/serviceWorker/wallet.js +58 -34
  32. package/dist/cjs/wallet/serviceWorker/worker.js +117 -108
  33. package/dist/cjs/wallet/unroll.js +270 -0
  34. package/dist/cjs/wallet/wallet.js +701 -459
  35. package/dist/esm/arknote/index.js +61 -57
  36. package/dist/esm/bip322/errors.js +9 -0
  37. package/dist/esm/bip322/index.js +174 -0
  38. package/dist/esm/forfeit.js +15 -26
  39. package/dist/esm/identity/singleKey.js +64 -0
  40. package/dist/esm/index.js +30 -12
  41. package/dist/esm/providers/ark.js +252 -317
  42. package/dist/esm/providers/indexer.js +521 -0
  43. package/dist/esm/providers/onchain.js +193 -15
  44. package/dist/esm/script/address.js +48 -17
  45. package/dist/esm/script/base.js +120 -3
  46. package/dist/esm/script/default.js +18 -4
  47. package/dist/esm/script/tapscript.js +46 -14
  48. package/dist/esm/script/vhtlc.js +27 -7
  49. package/dist/esm/tree/signingSession.js +65 -108
  50. package/dist/esm/tree/txTree.js +189 -0
  51. package/dist/esm/tree/validation.js +75 -152
  52. package/dist/esm/utils/anchor.js +31 -0
  53. package/dist/esm/utils/arkTransaction.js +105 -0
  54. package/dist/esm/utils/transactionHistory.js +84 -72
  55. package/dist/esm/utils/txSizeEstimator.js +12 -0
  56. package/dist/esm/utils/unknownFields.js +173 -0
  57. package/dist/esm/wallet/index.js +9 -0
  58. package/dist/esm/wallet/onchain.js +196 -0
  59. package/dist/esm/wallet/ramps.js +91 -0
  60. package/dist/esm/wallet/serviceWorker/db/vtxo/idb.js +32 -0
  61. package/dist/esm/wallet/serviceWorker/request.js +15 -12
  62. package/dist/esm/wallet/serviceWorker/response.js +22 -27
  63. package/dist/esm/wallet/serviceWorker/utils.js +8 -0
  64. package/dist/esm/wallet/serviceWorker/wallet.js +59 -35
  65. package/dist/esm/wallet/serviceWorker/worker.js +117 -108
  66. package/dist/esm/wallet/unroll.js +267 -0
  67. package/dist/esm/wallet/wallet.js +674 -466
  68. package/dist/types/arknote/index.d.ts +40 -13
  69. package/dist/types/bip322/errors.d.ts +6 -0
  70. package/dist/types/bip322/index.d.ts +57 -0
  71. package/dist/types/forfeit.d.ts +2 -14
  72. package/dist/types/identity/singleKey.d.ts +27 -0
  73. package/dist/types/index.d.ts +23 -12
  74. package/dist/types/providers/ark.d.ts +114 -95
  75. package/dist/types/providers/indexer.d.ts +186 -0
  76. package/dist/types/providers/onchain.d.ts +41 -11
  77. package/dist/types/script/address.d.ts +26 -2
  78. package/dist/types/script/base.d.ts +13 -3
  79. package/dist/types/script/default.d.ts +22 -0
  80. package/dist/types/script/tapscript.d.ts +61 -5
  81. package/dist/types/script/vhtlc.d.ts +27 -0
  82. package/dist/types/tree/signingSession.d.ts +5 -5
  83. package/dist/types/tree/txTree.d.ts +28 -0
  84. package/dist/types/tree/validation.d.ts +15 -22
  85. package/dist/types/utils/anchor.d.ts +19 -0
  86. package/dist/types/utils/arkTransaction.d.ts +27 -0
  87. package/dist/types/utils/transactionHistory.d.ts +7 -1
  88. package/dist/types/utils/txSizeEstimator.d.ts +3 -0
  89. package/dist/types/utils/unknownFields.d.ts +83 -0
  90. package/dist/types/wallet/index.d.ts +51 -50
  91. package/dist/types/wallet/onchain.d.ts +49 -0
  92. package/dist/types/wallet/ramps.d.ts +32 -0
  93. package/dist/types/wallet/serviceWorker/db/vtxo/idb.d.ts +2 -0
  94. package/dist/types/wallet/serviceWorker/db/vtxo/index.d.ts +2 -0
  95. package/dist/types/wallet/serviceWorker/request.d.ts +14 -16
  96. package/dist/types/wallet/serviceWorker/response.d.ts +17 -19
  97. package/dist/types/wallet/serviceWorker/utils.d.ts +8 -0
  98. package/dist/types/wallet/serviceWorker/wallet.d.ts +36 -8
  99. package/dist/types/wallet/serviceWorker/worker.d.ts +7 -3
  100. package/dist/types/wallet/unroll.d.ts +102 -0
  101. package/dist/types/wallet/wallet.d.ts +71 -26
  102. package/package.json +14 -15
  103. package/dist/cjs/identity/inMemoryKey.js +0 -40
  104. package/dist/cjs/tree/vtxoTree.js +0 -231
  105. package/dist/cjs/utils/coinselect.js +0 -73
  106. package/dist/cjs/utils/psbt.js +0 -137
  107. package/dist/esm/identity/inMemoryKey.js +0 -36
  108. package/dist/esm/tree/vtxoTree.js +0 -191
  109. package/dist/esm/utils/coinselect.js +0 -69
  110. package/dist/esm/utils/psbt.js +0 -131
  111. package/dist/types/identity/inMemoryKey.d.ts +0 -12
  112. package/dist/types/tree/vtxoTree.d.ts +0 -33
  113. package/dist/types/utils/coinselect.d.ts +0 -21
  114. 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 addresses(id, addresses) {
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
- addresses,
57
+ address,
51
58
  id,
52
59
  };
53
60
  }
54
- Response.addresses = addresses;
55
- function isAddressInfo(response) {
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: "ADDRESS_INFO",
64
+ type: "BOARDING_ADDRESS",
62
65
  success: true,
63
- addressInfo,
66
+ address,
64
67
  id,
65
68
  };
66
69
  }
67
- Response.addressInfo = addressInfo;
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 exitSuccess(id) {
177
+ function signSuccess(id, tx) {
188
178
  return {
189
- type: "EXIT_SUCCESS",
179
+ type: "SIGN_SUCCESS",
190
180
  success: true,
181
+ tx,
191
182
  id,
192
183
  };
193
184
  }
194
- Response.exitSuccess = exitSuccess;
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
- // ServiceWorkerWallet is a wallet that uses a service worker as "backend" to handle the wallet logic
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
- network: config.network,
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.addresses;
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 getAddressInfo() {
130
+ async getBoardingAddress() {
101
131
  const message = {
102
- type: "GET_ADDRESS_INFO",
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.isAddressInfo(response)) {
108
- return response.addressInfo;
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 info: ${error}`);
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 getCoins() {
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, zeroFee) {
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
- async exit(outpoints) {
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: "EXIT",
254
- outpoints,
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.type === "EXIT_SUCCESS") {
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 exit: ${error}`);
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 inMemoryKey_1 = require("../../identity/inMemoryKey");
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
- // Worker is a class letting to interact with ServiceWorkerWallet from the client
14
- // it aims to be run in a service worker context
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 vtxos = [...spendableVtxos, ...spentVtxos].map((vtxo) => ({
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
- tapLeafScript: forfeit,
64
- scripts: encodedOffchainTapscript,
70
+ forfeitTapLeafScript: forfeit,
71
+ intentTapLeafScript: exit,
72
+ tapTree: encodedOffchainTapscript,
65
73
  }));
66
74
  await this.vtxoRepository.addOrUpdate(vtxos);
67
- this.processVtxoSubscription(addressInfo.offchain);
75
+ this.processVtxoSubscription({
76
+ script,
77
+ vtxoScript: this.wallet.offchainTapscript,
78
+ });
68
79
  }
69
- async processVtxoSubscription({ address, scripts, }) {
80
+ async processVtxoSubscription({ script, vtxoScript, }) {
70
81
  try {
71
- const addressScripts = [...scripts.exit, ...scripts.forfeit];
72
- const vtxoScript = default_1.DefaultVtxo.Script.decode(addressScripts);
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 subscription = this.arkProvider.subscribeForAddress(address, abortController.signal);
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
- tapLeafScript,
85
- scripts: addressScripts,
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
- network: message.network,
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, message.zeroFee);
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 addresses = await this.wallet.getAddress();
190
- event.source?.postMessage(response_1.Response.addresses(message.id, addresses));
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 handleGetAddressInfo(event) {
213
+ async handleGetBoardingAddress(event) {
201
214
  const message = event.data;
202
- if (!request_1.Request.isGetAddressInfo(message)) {
203
- console.error("Invalid GET_ADDRESS_INFO message format", message);
204
- event.source?.postMessage(response_1.Response.error(message.id, "Invalid GET_ADDRESS_INFO message format"));
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 addressInfo = await this.wallet.getAddressInfo();
214
- event.source?.postMessage(response_1.Response.addressInfo(message.id, addressInfo));
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 info:", error);
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 coins = await this.wallet.getCoins();
238
- const onchainConfirmed = coins
239
- .filter((coin) => coin.status.confirmed)
240
- .reduce((sum, coin) => sum + coin.value, 0);
241
- const onchainUnconfirmed = coins
242
- .filter((coin) => !coin.status.confirmed)
243
- .reduce((sum, coin) => sum + coin.value, 0);
244
- const onchainTotal = onchainConfirmed + onchainUnconfirmed;
245
- const spendableVtxos = await this.vtxoRepository.getSpendableVtxos();
246
- const offchainSettledBalance = spendableVtxos.reduce((sum, vtxo) => vtxo.virtualStatus.state === "settled"
247
- ? sum + vtxo.value
248
- : sum, 0);
249
- const offchainPendingBalance = spendableVtxos.reduce((sum, vtxo) => vtxo.virtualStatus.state === "pending"
250
- ? sum + vtxo.value
251
- : sum, 0);
252
- const offchainSweptBalance = spendableVtxos.reduce((sum, vtxo) => vtxo.virtualStatus.state === "swept"
253
- ? sum + vtxo.value
254
- : sum, 0);
255
- const offchainTotal = offchainSettledBalance +
256
- offchainPendingBalance +
257
- offchainSweptBalance;
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
- onchain: {
260
- confirmed: onchainConfirmed,
261
- unconfirmed: onchainUnconfirmed,
262
- total: onchainTotal,
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
- total: onchainTotal + offchainTotal,
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
- const vtxos = await this.vtxoRepository.getSpendableVtxos();
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 handleExit(event) {
412
+ async handleSign(event) {
401
413
  const message = event.data;
402
- if (!request_1.Request.isExit(message)) {
403
- console.error("Invalid EXIT message format", message);
404
- event.source?.postMessage(response_1.Response.error(message.id, "Invalid EXIT message format"));
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
- await this.wallet.exit(message.outpoints);
414
- event.source?.postMessage(response_1.Response.exitSuccess(message.id));
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 exiting:", 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 "GET_ADDRESS_INFO": {
450
- await this.handleGetAddressInfo(event);
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
  }