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

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.
@@ -73,6 +73,9 @@ class SingleKey {
73
73
  }
74
74
  return txCpy;
75
75
  }
76
+ compressedPublicKey() {
77
+ return Promise.resolve((0, utils_js_1.pubECDSA)(this.key, true));
78
+ }
76
79
  xOnlyPublicKey() {
77
80
  return Promise.resolve((0, utils_js_1.pubSchnorr)(this.key));
78
81
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RestArkProvider = exports.SettlementEventType = void 0;
4
4
  exports.isFetchTimeoutError = isFetchTimeoutError;
5
5
  const base_1 = require("@scure/base");
6
+ const utils_1 = require("./utils");
6
7
  var SettlementEventType;
7
8
  (function (SettlementEventType) {
8
9
  SettlementEventType["BatchStarted"] = "batch_started";
@@ -45,6 +46,7 @@ class RestArkProvider {
45
46
  vtxoMinAmount: BigInt(fromServer.vtxoMinAmount ?? 0),
46
47
  vtxoMaxAmount: BigInt(fromServer.vtxoMaxAmount ?? -1),
47
48
  boardingExitDelay: BigInt(fromServer.boardingExitDelay ?? 0),
49
+ checkpointExitClosure: fromServer.checkpointTapscript ?? "",
48
50
  marketHour: "marketHour" in fromServer && fromServer.marketHour != null
49
51
  ? {
50
52
  nextStartTime: BigInt(fromServer.marketHour.nextStartTime ?? 0),
@@ -219,39 +221,21 @@ class RestArkProvider {
219
221
  : "";
220
222
  while (!signal?.aborted) {
221
223
  try {
222
- const response = await fetch(url + queryParams, {
223
- headers: {
224
- Accept: "application/json",
225
- },
226
- signal,
227
- });
228
- if (!response.ok) {
229
- throw new Error(`Unexpected status ${response.status} when fetching event stream`);
230
- }
231
- if (!response.body) {
232
- throw new Error("Response body is null");
233
- }
234
- const reader = response.body.getReader();
235
- const decoder = new TextDecoder();
236
- let buffer = "";
237
- while (!signal?.aborted) {
238
- const { done, value } = await reader.read();
239
- if (done) {
240
- break;
241
- }
242
- // Append new data to buffer and split by newlines
243
- buffer += decoder.decode(value, { stream: true });
244
- const lines = buffer.split("\n");
245
- // Process all complete lines
246
- for (let i = 0; i < lines.length - 1; i++) {
247
- const line = lines[i].trim();
248
- if (!line)
249
- continue;
224
+ const eventSource = new EventSource(url + queryParams);
225
+ // Set up abort handling
226
+ const abortHandler = () => {
227
+ eventSource.close();
228
+ };
229
+ signal?.addEventListener("abort", abortHandler);
230
+ try {
231
+ for await (const event of (0, utils_1.eventSourceIterator)(eventSource)) {
232
+ if (signal?.aborted)
233
+ break;
250
234
  try {
251
- const data = JSON.parse(line);
252
- const event = this.parseSettlementEvent(data.result);
253
- if (event) {
254
- yield event;
235
+ const data = JSON.parse(event.data);
236
+ const settlementEvent = this.parseSettlementEvent(data);
237
+ if (settlementEvent) {
238
+ yield settlementEvent;
255
239
  }
256
240
  }
257
241
  catch (err) {
@@ -259,8 +243,10 @@ class RestArkProvider {
259
243
  throw err;
260
244
  }
261
245
  }
262
- // Keep the last partial line in the buffer
263
- buffer = lines[lines.length - 1];
246
+ }
247
+ finally {
248
+ signal?.removeEventListener("abort", abortHandler);
249
+ eventSource.close();
264
250
  }
265
251
  }
266
252
  catch (error) {
@@ -268,7 +254,6 @@ class RestArkProvider {
268
254
  break;
269
255
  }
270
256
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
271
- // these timeouts are set by builtin fetch function
272
257
  if (isFetchTimeoutError(error)) {
273
258
  console.debug("Timeout error ignored");
274
259
  continue;
@@ -282,42 +267,32 @@ class RestArkProvider {
282
267
  const url = `${this.serverUrl}/v1/txs`;
283
268
  while (!signal?.aborted) {
284
269
  try {
285
- const response = await fetch(url, {
286
- headers: {
287
- Accept: "application/json",
288
- },
289
- signal,
290
- });
291
- if (!response.ok) {
292
- throw new Error(`Unexpected status ${response.status} when fetching transaction stream`);
293
- }
294
- if (!response.body) {
295
- throw new Error("Response body is null");
296
- }
297
- const reader = response.body.getReader();
298
- const decoder = new TextDecoder();
299
- let buffer = "";
300
- while (!signal?.aborted) {
301
- const { done, value } = await reader.read();
302
- if (done) {
303
- break;
304
- }
305
- // Append new data to buffer and split by newlines
306
- buffer += decoder.decode(value, { stream: true });
307
- const lines = buffer.split("\n");
308
- // Process all complete lines
309
- for (let i = 0; i < lines.length - 1; i++) {
310
- const line = lines[i].trim();
311
- if (!line)
312
- continue;
313
- const data = JSON.parse(line);
314
- const txNotification = this.parseTransactionNotification(data.result);
315
- if (txNotification) {
316
- yield txNotification;
270
+ const eventSource = new EventSource(url);
271
+ // Set up abort handling
272
+ const abortHandler = () => {
273
+ eventSource.close();
274
+ };
275
+ signal?.addEventListener("abort", abortHandler);
276
+ try {
277
+ for await (const event of (0, utils_1.eventSourceIterator)(eventSource)) {
278
+ if (signal?.aborted)
279
+ break;
280
+ try {
281
+ const data = JSON.parse(event.data);
282
+ const txNotification = this.parseTransactionNotification(data);
283
+ if (txNotification) {
284
+ yield txNotification;
285
+ }
286
+ }
287
+ catch (err) {
288
+ console.error("Failed to parse transaction notification:", err);
289
+ throw err;
317
290
  }
318
291
  }
319
- // Keep the last partial line in the buffer
320
- buffer = lines[lines.length - 1];
292
+ }
293
+ finally {
294
+ signal?.removeEventListener("abort", abortHandler);
295
+ eventSource.close();
321
296
  }
322
297
  }
323
298
  catch (error) {
@@ -325,12 +300,11 @@ class RestArkProvider {
325
300
  break;
326
301
  }
327
302
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
328
- // these timeouts are set by builtin fetch function
329
303
  if (isFetchTimeoutError(error)) {
330
304
  console.debug("Timeout error ignored");
331
305
  continue;
332
306
  }
333
- console.error("Address subscription error:", error);
307
+ console.error("Transaction stream error:", error);
334
308
  throw error;
335
309
  }
336
310
  }
@@ -413,6 +387,10 @@ class RestArkProvider {
413
387
  signature: data.treeSignature.signature,
414
388
  };
415
389
  }
390
+ // Skip heartbeat events
391
+ if (data.heartbeat) {
392
+ return null;
393
+ }
416
394
  console.warn("Unknown event type:", data);
417
395
  return null;
418
396
  }
@@ -439,6 +417,10 @@ class RestArkProvider {
439
417
  },
440
418
  };
441
419
  }
420
+ // Skip heartbeat events
421
+ if (data.heartbeat) {
422
+ return null;
423
+ }
442
424
  console.warn("Unknown transaction notification type:", data);
443
425
  return null;
444
426
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RestIndexerProvider = exports.ChainTxType = exports.IndexerTxType = void 0;
4
4
  const ark_1 = require("./ark");
5
+ const utils_1 = require("./utils");
5
6
  var IndexerTxType;
6
7
  (function (IndexerTxType) {
7
8
  IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
@@ -30,7 +31,7 @@ class RestIndexerProvider {
30
31
  this.serverUrl = serverUrl;
31
32
  }
32
33
  async getVtxoTree(batchOutpoint, opts) {
33
- let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
34
+ let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
34
35
  const params = new URLSearchParams();
35
36
  if (opts) {
36
37
  if (opts.pageIndex !== undefined)
@@ -58,7 +59,7 @@ class RestIndexerProvider {
58
59
  return data;
59
60
  }
60
61
  async getVtxoTreeLeaves(batchOutpoint, opts) {
61
- let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
62
+ let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
62
63
  const params = new URLSearchParams();
63
64
  if (opts) {
64
65
  if (opts.pageIndex !== undefined)
@@ -80,7 +81,7 @@ class RestIndexerProvider {
80
81
  return data;
81
82
  }
82
83
  async getBatchSweepTransactions(batchOutpoint) {
83
- const url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
84
+ const url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
84
85
  const res = await fetch(url);
85
86
  if (!res.ok) {
86
87
  throw new Error(`Failed to fetch batch sweep transactions: ${res.statusText}`);
@@ -92,7 +93,7 @@ class RestIndexerProvider {
92
93
  return data;
93
94
  }
94
95
  async getCommitmentTx(txid) {
95
- const url = `${this.serverUrl}/v1/commitmentTx/${txid}`;
96
+ const url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}`;
96
97
  const res = await fetch(url);
97
98
  if (!res.ok) {
98
99
  throw new Error(`Failed to fetch commitment tx: ${res.statusText}`);
@@ -104,7 +105,7 @@ class RestIndexerProvider {
104
105
  return data;
105
106
  }
106
107
  async getCommitmentTxConnectors(txid, opts) {
107
- let url = `${this.serverUrl}/v1/commitmentTx/${txid}/connectors`;
108
+ let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/connectors`;
108
109
  const params = new URLSearchParams();
109
110
  if (opts) {
110
111
  if (opts.pageIndex !== undefined)
@@ -132,7 +133,7 @@ class RestIndexerProvider {
132
133
  return data;
133
134
  }
134
135
  async getCommitmentTxForfeitTxs(txid, opts) {
135
- let url = `${this.serverUrl}/v1/commitmentTx/${txid}/forfeitTxs`;
136
+ let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/forfeitTxs`;
136
137
  const params = new URLSearchParams();
137
138
  if (opts) {
138
139
  if (opts.pageIndex !== undefined)
@@ -154,47 +155,41 @@ class RestIndexerProvider {
154
155
  return data;
155
156
  }
156
157
  async *getSubscription(subscriptionId, abortSignal) {
157
- const url = `${this.serverUrl}/v1/script/subscription/${subscriptionId}`;
158
- while (!abortSignal.aborted) {
158
+ const url = `${this.serverUrl}/v1/indexer/script/subscription/${subscriptionId}`;
159
+ while (!abortSignal?.aborted) {
159
160
  try {
160
- const res = await fetch(url, {
161
- headers: {
162
- Accept: "application/json",
163
- },
164
- });
165
- if (!res.ok) {
166
- throw new Error(`Unexpected status ${res.status} when subscribing to address updates`);
167
- }
168
- if (!res.body) {
169
- throw new Error("Response body is null");
170
- }
171
- const reader = res.body.getReader();
172
- const decoder = new TextDecoder();
173
- let buffer = "";
174
- while (!abortSignal.aborted) {
175
- const { done, value } = await reader.read();
176
- if (done) {
177
- break;
178
- }
179
- buffer += decoder.decode(value, { stream: true });
180
- const lines = buffer.split("\n");
181
- for (let i = 0; i < lines.length - 1; i++) {
182
- const line = lines[i].trim();
183
- if (!line)
184
- continue;
185
- const data = JSON.parse(line);
186
- if ("result" in data) {
187
- yield {
188
- txid: data.result.txid,
189
- scripts: data.result.scripts || [],
190
- newVtxos: (data.result.newVtxos || []).map(convertVtxo),
191
- spentVtxos: (data.result.spentVtxos || []).map(convertVtxo),
192
- tx: data.result.tx,
193
- checkpointTxs: data.result.checkpointTxs,
194
- };
161
+ const eventSource = new EventSource(url);
162
+ // Set up abort handling
163
+ const abortHandler = () => {
164
+ eventSource.close();
165
+ };
166
+ abortSignal?.addEventListener("abort", abortHandler);
167
+ try {
168
+ for await (const event of (0, utils_1.eventSourceIterator)(eventSource)) {
169
+ if (abortSignal?.aborted)
170
+ break;
171
+ try {
172
+ const data = JSON.parse(event.data);
173
+ if (data.event) {
174
+ yield {
175
+ txid: data.event.txid,
176
+ scripts: data.event.scripts || [],
177
+ newVtxos: (data.event.newVtxos || []).map(convertVtxo),
178
+ spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
179
+ tx: data.event.tx,
180
+ checkpointTxs: data.event.checkpointTxs,
181
+ };
182
+ }
183
+ }
184
+ catch (err) {
185
+ console.error("Failed to parse subscription event:", err);
186
+ throw err;
195
187
  }
196
188
  }
197
- buffer = lines[lines.length - 1];
189
+ }
190
+ finally {
191
+ abortSignal?.removeEventListener("abort", abortHandler);
192
+ eventSource.close();
198
193
  }
199
194
  }
200
195
  catch (error) {
@@ -202,7 +197,6 @@ class RestIndexerProvider {
202
197
  break;
203
198
  }
204
199
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
205
- // these timeouts are set by builtin fetch function
206
200
  if ((0, ark_1.isFetchTimeoutError)(error)) {
207
201
  console.debug("Timeout error ignored");
208
202
  continue;
@@ -213,7 +207,7 @@ class RestIndexerProvider {
213
207
  }
214
208
  }
215
209
  async getVirtualTxs(txids, opts) {
216
- let url = `${this.serverUrl}/v1/virtualTx/${txids.join(",")}`;
210
+ let url = `${this.serverUrl}/v1/indexer/virtualTx/${txids.join(",")}`;
217
211
  const params = new URLSearchParams();
218
212
  if (opts) {
219
213
  if (opts.pageIndex !== undefined)
@@ -235,7 +229,7 @@ class RestIndexerProvider {
235
229
  return data;
236
230
  }
237
231
  async getVtxoChain(vtxoOutpoint, opts) {
238
- let url = `${this.serverUrl}/v1/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
232
+ let url = `${this.serverUrl}/v1/indexer/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
239
233
  const params = new URLSearchParams();
240
234
  if (opts) {
241
235
  if (opts.pageIndex !== undefined)
@@ -264,7 +258,7 @@ class RestIndexerProvider {
264
258
  if (!opts?.scripts && !opts?.outpoints) {
265
259
  throw new Error("Either scripts or outpoints must be provided");
266
260
  }
267
- let url = `${this.serverUrl}/v1/vtxos`;
261
+ let url = `${this.serverUrl}/v1/indexer/vtxos`;
268
262
  const params = new URLSearchParams();
269
263
  // Handle scripts with multi collection format
270
264
  if (opts?.scripts && opts.scripts.length > 0) {
@@ -307,7 +301,7 @@ class RestIndexerProvider {
307
301
  };
308
302
  }
309
303
  async subscribeForScripts(scripts, subscriptionId) {
310
- const url = `${this.serverUrl}/v1/script/subscribe`;
304
+ const url = `${this.serverUrl}/v1/indexer/script/subscribe`;
311
305
  const res = await fetch(url, {
312
306
  headers: {
313
307
  "Content-Type": "application/json",
@@ -325,7 +319,7 @@ class RestIndexerProvider {
325
319
  return data.subscriptionId;
326
320
  }
327
321
  async unsubscribeForScripts(subscriptionId, scripts) {
328
- const url = `${this.serverUrl}/v1/script/unsubscribe`;
322
+ const url = `${this.serverUrl}/v1/indexer/script/unsubscribe`;
329
323
  const res = await fetch(url, {
330
324
  headers: {
331
325
  "Content-Type": "application/json",
@@ -442,7 +436,7 @@ var Response;
442
436
  return (typeof data === "object" &&
443
437
  isOutpoint(data.outpoint) &&
444
438
  typeof data.createdAt === "string" &&
445
- typeof data.expiresAt === "string" &&
439
+ (data.expiresAt === null || typeof data.expiresAt === "string") &&
446
440
  typeof data.amount === "string" &&
447
441
  typeof data.script === "string" &&
448
442
  typeof data.isPreconfirmed === "boolean" &&
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eventSourceIterator = eventSourceIterator;
4
+ async function* eventSourceIterator(eventSource) {
5
+ const messageQueue = [];
6
+ const errorQueue = [];
7
+ let messageResolve = null;
8
+ let errorResolve = null;
9
+ const messageHandler = (event) => {
10
+ if (messageResolve) {
11
+ messageResolve(event);
12
+ messageResolve = null;
13
+ }
14
+ else {
15
+ messageQueue.push(event);
16
+ }
17
+ };
18
+ const errorHandler = () => {
19
+ const error = new Error("EventSource error");
20
+ if (errorResolve) {
21
+ errorResolve(error);
22
+ errorResolve = null;
23
+ }
24
+ else {
25
+ errorQueue.push(error);
26
+ }
27
+ };
28
+ eventSource.addEventListener("message", messageHandler);
29
+ eventSource.addEventListener("error", errorHandler);
30
+ try {
31
+ while (true) {
32
+ // if we have queued messages, yield the first one, remove it from the queue
33
+ if (messageQueue.length > 0) {
34
+ yield messageQueue.shift();
35
+ continue;
36
+ }
37
+ // if we have queued errors, throw the first one, remove it from the queue
38
+ if (errorQueue.length > 0) {
39
+ const error = errorQueue.shift();
40
+ throw error;
41
+ }
42
+ // wait for the next message or error
43
+ const result = await new Promise((resolve, reject) => {
44
+ messageResolve = resolve;
45
+ errorResolve = reject;
46
+ }).finally(() => {
47
+ messageResolve = null;
48
+ errorResolve = null;
49
+ });
50
+ if (result) {
51
+ yield result;
52
+ }
53
+ }
54
+ }
55
+ finally {
56
+ // clean up
57
+ eventSource.removeEventListener("message", messageHandler);
58
+ eventSource.removeEventListener("error", errorHandler);
59
+ }
60
+ }
@@ -1,6 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WalletRepositoryImpl = void 0;
4
+ const base_1 = require("@scure/base");
5
+ const btc_signer_1 = require("@scure/btc-signer");
6
+ // Utility functions for (de)serializing complex structures
7
+ const toHex = (b) => (b ? base_1.hex.encode(b) : undefined);
8
+ const fromHex = (h) => h ? base_1.hex.decode(h) : undefined;
9
+ const serializeTapLeaf = ([cb, s]) => ({
10
+ cb: btc_signer_1.TaprootControlBlock.encode(cb) &&
11
+ base_1.hex.encode(btc_signer_1.TaprootControlBlock.encode(cb)),
12
+ s: base_1.hex.encode(s),
13
+ });
14
+ const serializeVtxo = (v) => ({
15
+ ...v,
16
+ tapTree: toHex(v.tapTree),
17
+ forfeitTapLeafScript: serializeTapLeaf(v.forfeitTapLeafScript),
18
+ intentTapLeafScript: serializeTapLeaf(v.intentTapLeafScript),
19
+ extraWitness: v.extraWitness?.map((w) => toHex(w)),
20
+ });
21
+ const deserializeTapLeaf = (t) => {
22
+ const cb = btc_signer_1.TaprootControlBlock.decode(fromHex(t.cb));
23
+ const s = fromHex(t.s);
24
+ return [cb, s];
25
+ };
26
+ const deserializeVtxo = (o) => ({
27
+ ...o,
28
+ tapTree: fromHex(o.tapTree),
29
+ forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
30
+ intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
31
+ extraWitness: o.extraWitness?.map((w) => fromHex(w)),
32
+ });
4
33
  class WalletRepositoryImpl {
5
34
  constructor(storage) {
6
35
  this.storage = storage;
@@ -22,7 +51,8 @@ class WalletRepositoryImpl {
22
51
  return [];
23
52
  }
24
53
  try {
25
- const vtxos = JSON.parse(stored);
54
+ const parsed = JSON.parse(stored);
55
+ const vtxos = parsed.map(deserializeVtxo);
26
56
  this.cache.vtxos.set(address, vtxos);
27
57
  return vtxos.slice();
28
58
  }
@@ -42,7 +72,7 @@ class WalletRepositoryImpl {
42
72
  vtxos.push(vtxo);
43
73
  }
44
74
  this.cache.vtxos.set(address, vtxos);
45
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos));
75
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos.map(serializeVtxo)));
46
76
  }
47
77
  async saveVtxos(address, vtxos) {
48
78
  const storedVtxos = await this.getVtxos(address);
@@ -56,14 +86,14 @@ class WalletRepositoryImpl {
56
86
  }
57
87
  }
58
88
  this.cache.vtxos.set(address, storedVtxos);
59
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos));
89
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos.map(serializeVtxo)));
60
90
  }
61
91
  async removeVtxo(address, vtxoId) {
62
92
  const vtxos = await this.getVtxos(address);
63
93
  const [txid, vout] = vtxoId.split(":");
64
94
  const filtered = vtxos.filter((v) => !(v.txid === txid && v.vout === parseInt(vout)));
65
95
  this.cache.vtxos.set(address, filtered);
66
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered));
96
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered.map(serializeVtxo)));
67
97
  }
68
98
  async clearVtxos(address) {
69
99
  this.cache.vtxos.set(address, []);
@@ -297,7 +297,7 @@ var CSVMultisigTapscript;
297
297
  throw new Error(`Invalid script: too short (expected at least 3)`);
298
298
  }
299
299
  const sequence = asm[0];
300
- if (typeof sequence === "string" || typeof sequence === "number") {
300
+ if (typeof sequence === "string") {
301
301
  throw new Error("Invalid script: expected sequence number");
302
302
  }
303
303
  if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
@@ -311,7 +311,13 @@ var CSVMultisigTapscript;
311
311
  catch (error) {
312
312
  throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
313
313
  }
314
- const sequenceNum = Number(MinimalScriptNum.decode(sequence));
314
+ let sequenceNum;
315
+ if (typeof sequence === "number") {
316
+ sequenceNum = sequence;
317
+ }
318
+ else {
319
+ sequenceNum = Number(MinimalScriptNum.decode(sequence));
320
+ }
315
321
  const decodedTimelock = bip68.decode(sequenceNum);
316
322
  const timelock = decodedTimelock.blocks !== undefined
317
323
  ? { type: "blocks", value: BigInt(decodedTimelock.blocks) }
@@ -90,7 +90,7 @@ class TreeSignerSession {
90
90
  if (!this.myNonces)
91
91
  throw new Error("nonces not generated");
92
92
  const sigs = new Map();
93
- for (const g of this.graph) {
93
+ for (const g of this.graph.iterator()) {
94
94
  const sig = this.signPartial(g);
95
95
  sigs.set(g.txid, sig);
96
96
  }
@@ -101,7 +101,7 @@ class TreeSignerSession {
101
101
  throw exports.ErrMissingVtxoGraph;
102
102
  const myNonces = new Map();
103
103
  const publicKey = secp256k1_js_1.secp256k1.getPublicKey(this.secretKey);
104
- for (const g of this.graph) {
104
+ for (const g of this.graph.iterator()) {
105
105
  const nonces = musig2.generateNonces(publicKey);
106
106
  myNonces.set(g.txid, nonces);
107
107
  }
@@ -144,7 +144,7 @@ TreeSignerSession.NOT_INITIALIZED = new Error("session not initialized, call ini
144
144
  // Helper function to validate tree signatures
145
145
  async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree) {
146
146
  // Iterate through each level of the tree
147
- for (const g of vtxoTree) {
147
+ for (const g of vtxoTree.iterator()) {
148
148
  // Parse the transaction
149
149
  const input = g.root.getInput(0);
150
150
  // Check if input has signature
@@ -157,11 +157,11 @@ class TxTree {
157
157
  }
158
158
  throw new Error(`tx not found: ${txid}`);
159
159
  }
160
- *[Symbol.iterator]() {
161
- yield this;
160
+ *iterator() {
162
161
  for (const child of this.children.values()) {
163
- yield* child;
162
+ yield* child.iterator();
164
163
  }
164
+ yield this;
165
165
  }
166
166
  }
167
167
  exports.TxTree = TxTree;
@@ -81,7 +81,7 @@ function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
81
81
  // validate the graph structure
82
82
  graph.validate();
83
83
  // iterates over all the nodes of the graph to verify that cosigners public keys are corresponding to the parent output
84
- for (const g of graph) {
84
+ for (const g of graph.iterator()) {
85
85
  for (const [childIndex, child] of g.children) {
86
86
  const parentOutput = g.root.getOutput(childIndex);
87
87
  if (!parentOutput?.script) {
@@ -17,7 +17,7 @@ async function setupServiceWorker(path) {
17
17
  // register service worker
18
18
  const registration = await navigator.serviceWorker.register(path);
19
19
  // force update to ensure the service worker is active
20
- registration.update();
20
+ await registration.update();
21
21
  const serviceWorker = registration.active || registration.waiting || registration.installing;
22
22
  if (!serviceWorker) {
23
23
  throw new Error("Failed to get service worker instance");
@@ -39,11 +39,11 @@ async function setupServiceWorker(path) {
39
39
  reject(new Error("Service worker activation timed out"));
40
40
  }, 10000);
41
41
  const cleanup = () => {
42
- serviceWorker.removeEventListener("activate", onActivate);
43
- serviceWorker.removeEventListener("error", onError);
42
+ navigator.serviceWorker.removeEventListener("activate", onActivate);
43
+ navigator.serviceWorker.removeEventListener("error", onError);
44
44
  clearTimeout(timeout);
45
45
  };
46
- serviceWorker.addEventListener("activate", onActivate);
47
- serviceWorker.addEventListener("error", onError);
46
+ navigator.serviceWorker.addEventListener("activate", onActivate);
47
+ navigator.serviceWorker.addEventListener("error", onError);
48
48
  });
49
49
  }