@arkade-os/sdk 0.3.0-alpha.0 → 0.3.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/cjs/arknote/index.js +4 -4
  2. package/dist/cjs/bip322/index.js +9 -7
  3. package/dist/cjs/forfeit.js +2 -2
  4. package/dist/cjs/identity/singleKey.js +10 -7
  5. package/dist/cjs/index.js +2 -2
  6. package/dist/cjs/musig2/keys.js +1 -1
  7. package/dist/cjs/musig2/nonces.js +1 -1
  8. package/dist/cjs/musig2/sign.js +1 -1
  9. package/dist/cjs/networks.js +6 -6
  10. package/dist/cjs/providers/ark.js +53 -71
  11. package/dist/cjs/providers/indexer.js +45 -51
  12. package/dist/cjs/providers/utils.js +60 -0
  13. package/dist/cjs/repositories/walletRepository.js +34 -4
  14. package/dist/cjs/script/address.js +3 -3
  15. package/dist/cjs/script/base.js +7 -7
  16. package/dist/cjs/script/tapscript.js +29 -23
  17. package/dist/cjs/script/vhtlc.js +2 -2
  18. package/dist/cjs/tree/signingSession.js +11 -10
  19. package/dist/cjs/tree/txTree.js +9 -9
  20. package/dist/cjs/tree/validation.js +6 -6
  21. package/dist/cjs/utils/arkTransaction.js +5 -5
  22. package/dist/cjs/utils/unknownFields.js +5 -5
  23. package/dist/cjs/wallet/onchain.js +5 -5
  24. package/dist/cjs/wallet/unroll.js +6 -6
  25. package/dist/cjs/wallet/wallet.js +21 -22
  26. package/dist/esm/arknote/index.js +2 -2
  27. package/dist/esm/bip322/index.js +3 -1
  28. package/dist/esm/forfeit.js +1 -1
  29. package/dist/esm/identity/singleKey.js +5 -2
  30. package/dist/esm/index.js +1 -1
  31. package/dist/esm/musig2/keys.js +1 -1
  32. package/dist/esm/musig2/nonces.js +1 -1
  33. package/dist/esm/musig2/sign.js +1 -1
  34. package/dist/esm/networks.js +1 -1
  35. package/dist/esm/providers/ark.js +53 -71
  36. package/dist/esm/providers/indexer.js +45 -51
  37. package/dist/esm/providers/utils.js +57 -0
  38. package/dist/esm/repositories/walletRepository.js +34 -4
  39. package/dist/esm/script/address.js +1 -1
  40. package/dist/esm/script/base.js +3 -3
  41. package/dist/esm/script/tapscript.js +10 -4
  42. package/dist/esm/script/vhtlc.js +1 -1
  43. package/dist/esm/tree/signingSession.js +6 -5
  44. package/dist/esm/tree/txTree.js +5 -5
  45. package/dist/esm/tree/validation.js +3 -3
  46. package/dist/esm/utils/arkTransaction.js +2 -2
  47. package/dist/esm/utils/unknownFields.js +1 -1
  48. package/dist/esm/wallet/onchain.js +2 -2
  49. package/dist/esm/wallet/unroll.js +2 -2
  50. package/dist/esm/wallet/wallet.js +9 -10
  51. package/dist/types/arknote/index.d.ts +1 -1
  52. package/dist/types/bip322/index.d.ts +2 -2
  53. package/dist/types/forfeit.d.ts +1 -1
  54. package/dist/types/identity/index.d.ts +4 -3
  55. package/dist/types/identity/singleKey.d.ts +2 -1
  56. package/dist/types/index.d.ts +1 -1
  57. package/dist/types/providers/ark.d.ts +1 -0
  58. package/dist/types/providers/utils.d.ts +1 -0
  59. package/dist/types/script/address.d.ts +1 -1
  60. package/dist/types/script/base.d.ts +1 -1
  61. package/dist/types/script/default.d.ts +1 -1
  62. package/dist/types/script/tapscript.d.ts +1 -1
  63. package/dist/types/script/vhtlc.d.ts +1 -1
  64. package/dist/types/tree/txTree.d.ts +3 -3
  65. package/dist/types/tree/validation.d.ts +1 -1
  66. package/dist/types/utils/anchor.d.ts +1 -1
  67. package/dist/types/utils/arkTransaction.d.ts +3 -3
  68. package/dist/types/utils/unknownFields.d.ts +1 -1
  69. package/dist/types/wallet/index.d.ts +1 -1
  70. package/dist/types/wallet/onchain.d.ts +2 -2
  71. package/dist/types/wallet/unroll.d.ts +1 -1
  72. package/dist/types/wallet/wallet.d.ts +1 -1
  73. package/package.json +3 -2
@@ -1,4 +1,5 @@
1
1
  import { isFetchTimeoutError } from './ark.js';
2
+ import { eventSourceIterator } from './utils.js';
2
3
  export var IndexerTxType;
3
4
  (function (IndexerTxType) {
4
5
  IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
@@ -27,7 +28,7 @@ export class RestIndexerProvider {
27
28
  this.serverUrl = serverUrl;
28
29
  }
29
30
  async getVtxoTree(batchOutpoint, opts) {
30
- let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
31
+ let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree`;
31
32
  const params = new URLSearchParams();
32
33
  if (opts) {
33
34
  if (opts.pageIndex !== undefined)
@@ -55,7 +56,7 @@ export class RestIndexerProvider {
55
56
  return data;
56
57
  }
57
58
  async getVtxoTreeLeaves(batchOutpoint, opts) {
58
- let url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
59
+ let url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/tree/leaves`;
59
60
  const params = new URLSearchParams();
60
61
  if (opts) {
61
62
  if (opts.pageIndex !== undefined)
@@ -77,7 +78,7 @@ export class RestIndexerProvider {
77
78
  return data;
78
79
  }
79
80
  async getBatchSweepTransactions(batchOutpoint) {
80
- const url = `${this.serverUrl}/v1/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
81
+ const url = `${this.serverUrl}/v1/indexer/batch/${batchOutpoint.txid}/${batchOutpoint.vout}/sweepTxs`;
81
82
  const res = await fetch(url);
82
83
  if (!res.ok) {
83
84
  throw new Error(`Failed to fetch batch sweep transactions: ${res.statusText}`);
@@ -89,7 +90,7 @@ export class RestIndexerProvider {
89
90
  return data;
90
91
  }
91
92
  async getCommitmentTx(txid) {
92
- const url = `${this.serverUrl}/v1/commitmentTx/${txid}`;
93
+ const url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}`;
93
94
  const res = await fetch(url);
94
95
  if (!res.ok) {
95
96
  throw new Error(`Failed to fetch commitment tx: ${res.statusText}`);
@@ -101,7 +102,7 @@ export class RestIndexerProvider {
101
102
  return data;
102
103
  }
103
104
  async getCommitmentTxConnectors(txid, opts) {
104
- let url = `${this.serverUrl}/v1/commitmentTx/${txid}/connectors`;
105
+ let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/connectors`;
105
106
  const params = new URLSearchParams();
106
107
  if (opts) {
107
108
  if (opts.pageIndex !== undefined)
@@ -129,7 +130,7 @@ export class RestIndexerProvider {
129
130
  return data;
130
131
  }
131
132
  async getCommitmentTxForfeitTxs(txid, opts) {
132
- let url = `${this.serverUrl}/v1/commitmentTx/${txid}/forfeitTxs`;
133
+ let url = `${this.serverUrl}/v1/indexer/commitmentTx/${txid}/forfeitTxs`;
133
134
  const params = new URLSearchParams();
134
135
  if (opts) {
135
136
  if (opts.pageIndex !== undefined)
@@ -151,47 +152,41 @@ export class RestIndexerProvider {
151
152
  return data;
152
153
  }
153
154
  async *getSubscription(subscriptionId, abortSignal) {
154
- const url = `${this.serverUrl}/v1/script/subscription/${subscriptionId}`;
155
- while (!abortSignal.aborted) {
155
+ const url = `${this.serverUrl}/v1/indexer/script/subscription/${subscriptionId}`;
156
+ while (!abortSignal?.aborted) {
156
157
  try {
157
- const res = await fetch(url, {
158
- headers: {
159
- Accept: "application/json",
160
- },
161
- });
162
- if (!res.ok) {
163
- throw new Error(`Unexpected status ${res.status} when subscribing to address updates`);
164
- }
165
- if (!res.body) {
166
- throw new Error("Response body is null");
167
- }
168
- const reader = res.body.getReader();
169
- const decoder = new TextDecoder();
170
- let buffer = "";
171
- while (!abortSignal.aborted) {
172
- const { done, value } = await reader.read();
173
- if (done) {
174
- break;
175
- }
176
- buffer += decoder.decode(value, { stream: true });
177
- const lines = buffer.split("\n");
178
- for (let i = 0; i < lines.length - 1; i++) {
179
- const line = lines[i].trim();
180
- if (!line)
181
- continue;
182
- const data = JSON.parse(line);
183
- if ("result" in data) {
184
- yield {
185
- txid: data.result.txid,
186
- scripts: data.result.scripts || [],
187
- newVtxos: (data.result.newVtxos || []).map(convertVtxo),
188
- spentVtxos: (data.result.spentVtxos || []).map(convertVtxo),
189
- tx: data.result.tx,
190
- checkpointTxs: data.result.checkpointTxs,
191
- };
158
+ const eventSource = new EventSource(url);
159
+ // Set up abort handling
160
+ const abortHandler = () => {
161
+ eventSource.close();
162
+ };
163
+ abortSignal?.addEventListener("abort", abortHandler);
164
+ try {
165
+ for await (const event of eventSourceIterator(eventSource)) {
166
+ if (abortSignal?.aborted)
167
+ break;
168
+ try {
169
+ const data = JSON.parse(event.data);
170
+ if (data.event) {
171
+ yield {
172
+ txid: data.event.txid,
173
+ scripts: data.event.scripts || [],
174
+ newVtxos: (data.event.newVtxos || []).map(convertVtxo),
175
+ spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
176
+ tx: data.event.tx,
177
+ checkpointTxs: data.event.checkpointTxs,
178
+ };
179
+ }
180
+ }
181
+ catch (err) {
182
+ console.error("Failed to parse subscription event:", err);
183
+ throw err;
192
184
  }
193
185
  }
194
- buffer = lines[lines.length - 1];
186
+ }
187
+ finally {
188
+ abortSignal?.removeEventListener("abort", abortHandler);
189
+ eventSource.close();
195
190
  }
196
191
  }
197
192
  catch (error) {
@@ -199,7 +194,6 @@ export class RestIndexerProvider {
199
194
  break;
200
195
  }
201
196
  // ignore timeout errors, they're expected when the server is not sending anything for 5 min
202
- // these timeouts are set by builtin fetch function
203
197
  if (isFetchTimeoutError(error)) {
204
198
  console.debug("Timeout error ignored");
205
199
  continue;
@@ -210,7 +204,7 @@ export class RestIndexerProvider {
210
204
  }
211
205
  }
212
206
  async getVirtualTxs(txids, opts) {
213
- let url = `${this.serverUrl}/v1/virtualTx/${txids.join(",")}`;
207
+ let url = `${this.serverUrl}/v1/indexer/virtualTx/${txids.join(",")}`;
214
208
  const params = new URLSearchParams();
215
209
  if (opts) {
216
210
  if (opts.pageIndex !== undefined)
@@ -232,7 +226,7 @@ export class RestIndexerProvider {
232
226
  return data;
233
227
  }
234
228
  async getVtxoChain(vtxoOutpoint, opts) {
235
- let url = `${this.serverUrl}/v1/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
229
+ let url = `${this.serverUrl}/v1/indexer/vtxo/${vtxoOutpoint.txid}/${vtxoOutpoint.vout}/chain`;
236
230
  const params = new URLSearchParams();
237
231
  if (opts) {
238
232
  if (opts.pageIndex !== undefined)
@@ -261,7 +255,7 @@ export class RestIndexerProvider {
261
255
  if (!opts?.scripts && !opts?.outpoints) {
262
256
  throw new Error("Either scripts or outpoints must be provided");
263
257
  }
264
- let url = `${this.serverUrl}/v1/vtxos`;
258
+ let url = `${this.serverUrl}/v1/indexer/vtxos`;
265
259
  const params = new URLSearchParams();
266
260
  // Handle scripts with multi collection format
267
261
  if (opts?.scripts && opts.scripts.length > 0) {
@@ -304,7 +298,7 @@ export class RestIndexerProvider {
304
298
  };
305
299
  }
306
300
  async subscribeForScripts(scripts, subscriptionId) {
307
- const url = `${this.serverUrl}/v1/script/subscribe`;
301
+ const url = `${this.serverUrl}/v1/indexer/script/subscribe`;
308
302
  const res = await fetch(url, {
309
303
  headers: {
310
304
  "Content-Type": "application/json",
@@ -322,7 +316,7 @@ export class RestIndexerProvider {
322
316
  return data.subscriptionId;
323
317
  }
324
318
  async unsubscribeForScripts(subscriptionId, scripts) {
325
- const url = `${this.serverUrl}/v1/script/unsubscribe`;
319
+ const url = `${this.serverUrl}/v1/indexer/script/unsubscribe`;
326
320
  const res = await fetch(url, {
327
321
  headers: {
328
322
  "Content-Type": "application/json",
@@ -438,7 +432,7 @@ var Response;
438
432
  return (typeof data === "object" &&
439
433
  isOutpoint(data.outpoint) &&
440
434
  typeof data.createdAt === "string" &&
441
- typeof data.expiresAt === "string" &&
435
+ (data.expiresAt === null || typeof data.expiresAt === "string") &&
442
436
  typeof data.amount === "string" &&
443
437
  typeof data.script === "string" &&
444
438
  typeof data.isPreconfirmed === "boolean" &&
@@ -0,0 +1,57 @@
1
+ export async function* eventSourceIterator(eventSource) {
2
+ const messageQueue = [];
3
+ const errorQueue = [];
4
+ let messageResolve = null;
5
+ let errorResolve = null;
6
+ const messageHandler = (event) => {
7
+ if (messageResolve) {
8
+ messageResolve(event);
9
+ messageResolve = null;
10
+ }
11
+ else {
12
+ messageQueue.push(event);
13
+ }
14
+ };
15
+ const errorHandler = () => {
16
+ const error = new Error("EventSource error");
17
+ if (errorResolve) {
18
+ errorResolve(error);
19
+ errorResolve = null;
20
+ }
21
+ else {
22
+ errorQueue.push(error);
23
+ }
24
+ };
25
+ eventSource.addEventListener("message", messageHandler);
26
+ eventSource.addEventListener("error", errorHandler);
27
+ try {
28
+ while (true) {
29
+ // if we have queued messages, yield the first one, remove it from the queue
30
+ if (messageQueue.length > 0) {
31
+ yield messageQueue.shift();
32
+ continue;
33
+ }
34
+ // if we have queued errors, throw the first one, remove it from the queue
35
+ if (errorQueue.length > 0) {
36
+ const error = errorQueue.shift();
37
+ throw error;
38
+ }
39
+ // wait for the next message or error
40
+ const result = await new Promise((resolve, reject) => {
41
+ messageResolve = resolve;
42
+ errorResolve = reject;
43
+ }).finally(() => {
44
+ messageResolve = null;
45
+ errorResolve = null;
46
+ });
47
+ if (result) {
48
+ yield result;
49
+ }
50
+ }
51
+ }
52
+ finally {
53
+ // clean up
54
+ eventSource.removeEventListener("message", messageHandler);
55
+ eventSource.removeEventListener("error", errorHandler);
56
+ }
57
+ }
@@ -1,3 +1,32 @@
1
+ import { hex } from "@scure/base";
2
+ import { TaprootControlBlock } from "@scure/btc-signer";
3
+ // Utility functions for (de)serializing complex structures
4
+ const toHex = (b) => (b ? hex.encode(b) : undefined);
5
+ const fromHex = (h) => h ? hex.decode(h) : undefined;
6
+ const serializeTapLeaf = ([cb, s]) => ({
7
+ cb: TaprootControlBlock.encode(cb) &&
8
+ hex.encode(TaprootControlBlock.encode(cb)),
9
+ s: hex.encode(s),
10
+ });
11
+ const serializeVtxo = (v) => ({
12
+ ...v,
13
+ tapTree: toHex(v.tapTree),
14
+ forfeitTapLeafScript: serializeTapLeaf(v.forfeitTapLeafScript),
15
+ intentTapLeafScript: serializeTapLeaf(v.intentTapLeafScript),
16
+ extraWitness: v.extraWitness?.map((w) => toHex(w)),
17
+ });
18
+ const deserializeTapLeaf = (t) => {
19
+ const cb = TaprootControlBlock.decode(fromHex(t.cb));
20
+ const s = fromHex(t.s);
21
+ return [cb, s];
22
+ };
23
+ const deserializeVtxo = (o) => ({
24
+ ...o,
25
+ tapTree: fromHex(o.tapTree),
26
+ forfeitTapLeafScript: deserializeTapLeaf(o.forfeitTapLeafScript),
27
+ intentTapLeafScript: deserializeTapLeaf(o.intentTapLeafScript),
28
+ extraWitness: o.extraWitness?.map((w) => fromHex(w)),
29
+ });
1
30
  export class WalletRepositoryImpl {
2
31
  constructor(storage) {
3
32
  this.storage = storage;
@@ -19,7 +48,8 @@ export class WalletRepositoryImpl {
19
48
  return [];
20
49
  }
21
50
  try {
22
- const vtxos = JSON.parse(stored);
51
+ const parsed = JSON.parse(stored);
52
+ const vtxos = parsed.map(deserializeVtxo);
23
53
  this.cache.vtxos.set(address, vtxos);
24
54
  return vtxos.slice();
25
55
  }
@@ -39,7 +69,7 @@ export class WalletRepositoryImpl {
39
69
  vtxos.push(vtxo);
40
70
  }
41
71
  this.cache.vtxos.set(address, vtxos);
42
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos));
72
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(vtxos.map(serializeVtxo)));
43
73
  }
44
74
  async saveVtxos(address, vtxos) {
45
75
  const storedVtxos = await this.getVtxos(address);
@@ -53,14 +83,14 @@ export class WalletRepositoryImpl {
53
83
  }
54
84
  }
55
85
  this.cache.vtxos.set(address, storedVtxos);
56
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos));
86
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(storedVtxos.map(serializeVtxo)));
57
87
  }
58
88
  async removeVtxo(address, vtxoId) {
59
89
  const vtxos = await this.getVtxos(address);
60
90
  const [txid, vout] = vtxoId.split(":");
61
91
  const filtered = vtxos.filter((v) => !(v.txid === txid && v.vout === parseInt(vout)));
62
92
  this.cache.vtxos.set(address, filtered);
63
- await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered));
93
+ await this.storage.setItem(`vtxos:${address}`, JSON.stringify(filtered.map(serializeVtxo)));
64
94
  }
65
95
  async clearVtxos(address) {
66
96
  this.cache.vtxos.set(address, []);
@@ -1,5 +1,5 @@
1
1
  import { bech32m } from "@scure/base";
2
- import { Script } from "@scure/btc-signer";
2
+ import { Script } from "@scure/btc-signer/script.js";
3
3
  /**
4
4
  * ArkAddress allows to create and decode bech32m encoded ark address.
5
5
  * An ark address is composed of:
@@ -1,7 +1,7 @@
1
- import { Address, p2tr, TAP_LEAF_VERSION, taprootListToTree, } from "@scure/btc-signer/payment";
2
- import { TAPROOT_UNSPENDABLE_KEY, } from "@scure/btc-signer/utils";
1
+ import { Address, p2tr, TAP_LEAF_VERSION, taprootListToTree, } from "@scure/btc-signer/payment.js";
2
+ import { TAPROOT_UNSPENDABLE_KEY, } from "@scure/btc-signer/utils.js";
3
3
  import { ArkAddress } from './address.js';
4
- import { Script } from "@scure/btc-signer";
4
+ import { Script } from "@scure/btc-signer/script.js";
5
5
  import { hex } from "@scure/base";
6
6
  import { ConditionCSVMultisigTapscript, CSVMultisigTapscript, } from './tapscript.js';
7
7
  export function scriptFromTapLeafScript(leaf) {
@@ -1,6 +1,6 @@
1
1
  import * as bip68 from "bip68";
2
- import { Script, ScriptNum } from "@scure/btc-signer/script";
3
- import { p2tr_ms } from "@scure/btc-signer/payment";
2
+ import { Script, ScriptNum } from "@scure/btc-signer/script.js";
3
+ import { p2tr_ms } from "@scure/btc-signer/payment.js";
4
4
  import { hex } from "@scure/base";
5
5
  const MinimalScriptNum = ScriptNum(undefined, true);
6
6
  export var TapscriptType;
@@ -260,7 +260,7 @@ export var CSVMultisigTapscript;
260
260
  throw new Error(`Invalid script: too short (expected at least 3)`);
261
261
  }
262
262
  const sequence = asm[0];
263
- if (typeof sequence === "string" || typeof sequence === "number") {
263
+ if (typeof sequence === "string") {
264
264
  throw new Error("Invalid script: expected sequence number");
265
265
  }
266
266
  if (asm[1] !== "CHECKSEQUENCEVERIFY" || asm[2] !== "DROP") {
@@ -274,7 +274,13 @@ export var CSVMultisigTapscript;
274
274
  catch (error) {
275
275
  throw new Error(`Invalid multisig script: ${error instanceof Error ? error.message : String(error)}`);
276
276
  }
277
- const sequenceNum = Number(MinimalScriptNum.decode(sequence));
277
+ let sequenceNum;
278
+ if (typeof sequence === "number") {
279
+ sequenceNum = sequence;
280
+ }
281
+ else {
282
+ sequenceNum = Number(MinimalScriptNum.decode(sequence));
283
+ }
278
284
  const decodedTimelock = bip68.decode(sequenceNum);
279
285
  const timelock = decodedTimelock.blocks !== undefined
280
286
  ? { type: "blocks", value: BigInt(decodedTimelock.blocks) }
@@ -1,4 +1,4 @@
1
- import { Script } from "@scure/btc-signer";
1
+ import { Script } from "@scure/btc-signer/script.js";
2
2
  import { CLTVMultisigTapscript, ConditionCSVMultisigTapscript, ConditionMultisigTapscript, CSVMultisigTapscript, MultisigTapscript, } from './tapscript.js';
3
3
  import { hex } from "@scure/base";
4
4
  import { VtxoScript } from './base.js';
@@ -1,8 +1,9 @@
1
1
  import * as musig2 from '../musig2/index.js';
2
- import { Script, SigHash } from "@scure/btc-signer";
2
+ import { Script } from "@scure/btc-signer/script.js";
3
+ import { SigHash } from "@scure/btc-signer/transaction.js";
3
4
  import { hex } from "@scure/base";
4
5
  import { schnorr, secp256k1 } from "@noble/curves/secp256k1.js";
5
- import { randomPrivateKeyBytes, sha256x2 } from "@scure/btc-signer/utils";
6
+ import { randomPrivateKeyBytes, sha256x2 } from "@scure/btc-signer/utils.js";
6
7
  import { CosignerPublicKey, getArkPsbtFields } from '../utils/unknownFields.js';
7
8
  export const ErrMissingVtxoGraph = new Error("missing vtxo graph");
8
9
  export const ErrMissingAggregateKey = new Error("missing aggregate key");
@@ -52,7 +53,7 @@ export class TreeSignerSession {
52
53
  if (!this.myNonces)
53
54
  throw new Error("nonces not generated");
54
55
  const sigs = new Map();
55
- for (const g of this.graph) {
56
+ for (const g of this.graph.iterator()) {
56
57
  const sig = this.signPartial(g);
57
58
  sigs.set(g.txid, sig);
58
59
  }
@@ -63,7 +64,7 @@ export class TreeSignerSession {
63
64
  throw ErrMissingVtxoGraph;
64
65
  const myNonces = new Map();
65
66
  const publicKey = secp256k1.getPublicKey(this.secretKey);
66
- for (const g of this.graph) {
67
+ for (const g of this.graph.iterator()) {
67
68
  const nonces = musig2.generateNonces(publicKey);
68
69
  myNonces.set(g.txid, nonces);
69
70
  }
@@ -105,7 +106,7 @@ TreeSignerSession.NOT_INITIALIZED = new Error("session not initialized, call ini
105
106
  // Helper function to validate tree signatures
106
107
  export async function validateTreeSigs(finalAggregatedKey, sharedOutputAmount, vtxoTree) {
107
108
  // Iterate through each level of the tree
108
- for (const g of vtxoTree) {
109
+ for (const g of vtxoTree.iterator()) {
109
110
  // Parse the transaction
110
111
  const input = g.root.getInput(0);
111
112
  // Check if input has signature
@@ -1,7 +1,7 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { base64 } from "@scure/base";
3
3
  import { hex } from "@scure/base";
4
- import { sha256x2 } from "@scure/btc-signer/utils";
4
+ import { sha256x2 } from "@scure/btc-signer/utils.js";
5
5
  /**
6
6
  * TxTree is a graph of bitcoin transactions.
7
7
  * It is used to represent batch tree created during settlement session
@@ -154,11 +154,11 @@ export class TxTree {
154
154
  }
155
155
  throw new Error(`tx not found: ${txid}`);
156
156
  }
157
- *[Symbol.iterator]() {
158
- yield this;
157
+ *iterator() {
159
158
  for (const child of this.children.values()) {
160
- yield* child;
159
+ yield* child.iterator();
161
160
  }
161
+ yield this;
162
162
  }
163
163
  }
164
164
  // Helper function to check if a chunk has a specific child
@@ -1,7 +1,7 @@
1
1
  import { hex } from "@scure/base";
2
- import { Transaction } from "@scure/btc-signer";
2
+ import { Transaction } from "@scure/btc-signer/transaction.js";
3
3
  import { base64 } from "@scure/base";
4
- import { sha256x2 } from "@scure/btc-signer/utils";
4
+ import { sha256x2 } from "@scure/btc-signer/utils.js";
5
5
  import { aggregateKeys } from '../musig2/index.js';
6
6
  import { CosignerPublicKey, getArkPsbtFields } from '../utils/unknownFields.js';
7
7
  export const ErrInvalidSettlementTx = (tx) => new Error(`invalid settlement transaction: ${tx}`);
@@ -75,7 +75,7 @@ export function validateVtxoTxGraph(graph, roundTransaction, sweepTapTreeRoot) {
75
75
  // validate the graph structure
76
76
  graph.validate();
77
77
  // iterates over all the nodes of the graph to verify that cosigners public keys are corresponding to the parent output
78
- for (const g of graph) {
78
+ for (const g of graph.iterator()) {
79
79
  for (const [childIndex, child] of g.children) {
80
80
  const parentOutput = g.root.getOutput(childIndex);
81
81
  if (!parentOutput?.script) {
@@ -1,9 +1,9 @@
1
- import { DEFAULT_SEQUENCE, Transaction } from "@scure/btc-signer";
1
+ import { DEFAULT_SEQUENCE, Transaction, } from "@scure/btc-signer/transaction.js";
2
2
  import { CLTVMultisigTapscript, decodeTapscript } from '../script/tapscript.js';
3
3
  import { scriptFromTapLeafScript, VtxoScript, } from '../script/base.js';
4
4
  import { P2A } from './anchor.js';
5
5
  import { hex } from "@scure/base";
6
- import { sha256x2 } from "@scure/btc-signer/utils";
6
+ import { sha256x2 } from "@scure/btc-signer/utils.js";
7
7
  import { setArkPsbtField, VtxoTaprootTree } from './unknownFields.js';
8
8
  /**
9
9
  * Builds an offchain transaction with checkpoint transactions.
@@ -1,5 +1,5 @@
1
1
  import * as bip68 from "bip68";
2
- import { RawWitness, ScriptNum } from "@scure/btc-signer";
2
+ import { RawWitness, ScriptNum } from "@scure/btc-signer/script.js";
3
3
  import { hex } from "@scure/base";
4
4
  /**
5
5
  * ArkPsbtFieldKey is the key values for ark psbt fields.
@@ -1,7 +1,7 @@
1
- import { p2tr } from "@scure/btc-signer/payment";
1
+ import { p2tr } from "@scure/btc-signer/payment.js";
2
2
  import { getNetwork } from '../networks.js';
3
3
  import { ESPLORA_URL, EsploraProvider, } from '../providers/onchain.js';
4
- import { Transaction } from "@scure/btc-signer";
4
+ import { Transaction } from "@scure/btc-signer/transaction.js";
5
5
  import { findP2AOutput, P2A } from '../utils/anchor.js';
6
6
  import { TxWeightEstimator } from '../utils/txSizeEstimator.js';
7
7
  /**
@@ -1,8 +1,8 @@
1
- import { SigHash, Transaction } from "@scure/btc-signer";
1
+ import { SigHash, Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { ChainTxType } from '../providers/indexer.js';
3
3
  import { base64, hex } from "@scure/base";
4
4
  import { VtxoScript } from '../script/base.js';
5
- import { TaprootControlBlock, } from "@scure/btc-signer/psbt";
5
+ import { TaprootControlBlock, } from "@scure/btc-signer/psbt.js";
6
6
  import { TxWeightEstimator } from '../utils/txSizeEstimator.js';
7
7
  import { Wallet } from './wallet.js';
8
8
  export var Unroll;
@@ -1,8 +1,8 @@
1
1
  import { base64, hex } from "@scure/base";
2
2
  import * as bip68 from "bip68";
3
- import { Address, OutScript, tapLeafHash } from "@scure/btc-signer/payment";
4
- import { SigHash, Transaction } from "@scure/btc-signer";
5
- import { TaprootControlBlock, } from "@scure/btc-signer/psbt";
3
+ import { Address, OutScript, tapLeafHash } from "@scure/btc-signer/payment.js";
4
+ import { SigHash, Transaction } from "@scure/btc-signer/transaction.js";
5
+ import { TaprootControlBlock, } from "@scure/btc-signer/psbt.js";
6
6
  import { vtxosToTxs } from '../utils/transactionHistory.js';
7
7
  import { ArkAddress } from '../script/address.js';
8
8
  import { DefaultVtxo } from '../script/default.js';
@@ -12,7 +12,7 @@ import { SettlementEventType, RestArkProvider, } from '../providers/ark.js';
12
12
  import { buildForfeitTx } from '../forfeit.js';
13
13
  import { validateConnectorsTxGraph, validateVtxoTxGraph, } from '../tree/validation.js';
14
14
  import { isRecoverable, isSpendable, isSubdust, TxType, } from './index.js';
15
- import { sha256, sha256x2 } from "@scure/btc-signer/utils";
15
+ import { sha256, sha256x2 } from "@scure/btc-signer/utils.js";
16
16
  import { VtxoScript } from '../script/base.js';
17
17
  import { CSVMultisigTapscript } from '../script/tapscript.js';
18
18
  import { buildOffchainTx } from '../utils/arkTransaction.js';
@@ -98,10 +98,8 @@ export class Wallet {
98
98
  // Save tapscripts
99
99
  const offchainTapscript = bareVtxoTapscript;
100
100
  // the serverUnrollScript is the one used to create output scripts of the checkpoint transactions
101
- const serverUnrollScript = CSVMultisigTapscript.encode({
102
- timelock: exitTimelock,
103
- pubkeys: [serverPubKey],
104
- });
101
+ const rawCheckpointExitClosure = hex.decode(info.checkpointExitClosure);
102
+ const serverUnrollScript = CSVMultisigTapscript.decode(rawCheckpointExitClosure);
105
103
  // parse the server forfeit address
106
104
  // server is expecting funds to be sent to this address
107
105
  const forfeitAddress = Address(network).decode(info.forfeitAddress);
@@ -167,8 +165,9 @@ export class Wallet {
167
165
  }
168
166
  async getVtxos(filter) {
169
167
  const address = await this.getAddress();
170
- // Try to get from cache first
171
- const cachedVtxos = await this.walletRepository.getVtxos(address);
168
+ // Try to get from cache first first (optional fast path)
169
+ // const cachedVtxos = await this.walletRepository.getVtxos(address);
170
+ // if (cachedVtxos.length) return cachedVtxos;
172
171
  // For now, always fetch fresh data from provider and update cache
173
172
  // In future, we can add cache invalidation logic based on timestamps
174
173
  const spendableVtxos = await this.getVirtualCoins(filter);
@@ -1,5 +1,5 @@
1
1
  import { TapLeafScript, VtxoScript } from "../script/base";
2
- import { Bytes } from "@scure/btc-signer/utils";
2
+ import { Bytes } from "@scure/btc-signer/utils.js";
3
3
  import { ExtendedCoin, Status } from "../wallet";
4
4
  /**
5
5
  * ArkNotes are special virtual coins in the Ark protocol that can be created
@@ -1,5 +1,5 @@
1
- import { Transaction } from "@scure/btc-signer";
2
- import { TransactionInput, TransactionOutput } from "@scure/btc-signer/psbt";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
+ import { TransactionInput, TransactionOutput } from "@scure/btc-signer/psbt.js";
3
3
  /**
4
4
  * BIP-322 signature implementation for Bitcoin message signing.
5
5
  *
@@ -1,3 +1,3 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { TransactionInputUpdate } from "@scure/btc-signer/psbt";
3
3
  export declare function buildForfeitTx(inputs: TransactionInputUpdate[], forfeitPkScript: Uint8Array, txLocktime?: number): Transaction;
@@ -1,9 +1,10 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { SignerSession } from "../tree/signingSession";
3
3
  export interface Identity {
4
- sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
5
- xOnlyPublicKey(): Promise<Uint8Array>;
6
4
  signerSession(): SignerSession;
5
+ xOnlyPublicKey(): Promise<Uint8Array>;
6
+ compressedPublicKey(): Promise<Uint8Array>;
7
7
  signMessage(message: string): Promise<Uint8Array>;
8
+ sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
8
9
  }
9
10
  export * from "./singleKey";
@@ -1,4 +1,4 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { Identity } from ".";
3
3
  import { SignerSession } from "../tree/signingSession";
4
4
  /**
@@ -32,6 +32,7 @@ export declare class SingleKey implements Identity {
32
32
  */
33
33
  toHex(): string;
34
34
  sign(tx: Transaction, inputIndexes?: number[]): Promise<Transaction>;
35
+ compressedPublicKey(): Promise<Uint8Array>;
35
36
  xOnlyPublicKey(): Promise<Uint8Array>;
36
37
  signerSession(): SignerSession;
37
38
  signMessage(message: string): Promise<Uint8Array>;
@@ -1,4 +1,4 @@
1
- import { Transaction } from "@scure/btc-signer";
1
+ import { Transaction } from "@scure/btc-signer/transaction.js";
2
2
  import { SingleKey } from "./identity/singleKey";
3
3
  import { Identity } from "./identity";
4
4
  import { ArkAddress } from "./script/address";
@@ -84,6 +84,7 @@ export interface ArkInfo {
84
84
  vtxoMinAmount: bigint;
85
85
  vtxoMaxAmount: bigint;
86
86
  boardingExitDelay: bigint;
87
+ checkpointExitClosure: string;
87
88
  }
88
89
  export interface Intent {
89
90
  signature: string;
@@ -0,0 +1 @@
1
+ export declare function eventSourceIterator(eventSource: EventSource): AsyncGenerator<MessageEvent, void, unknown>;
@@ -1,4 +1,4 @@
1
- import { Bytes } from "@scure/btc-signer/utils";
1
+ import { Bytes } from "@scure/btc-signer/utils.js";
2
2
  /**
3
3
  * ArkAddress allows to create and decode bech32m encoded ark address.
4
4
  * An ark address is composed of:
@@ -1,4 +1,4 @@
1
- import { BTC_NETWORK, Bytes } from "@scure/btc-signer/utils";
1
+ import { BTC_NETWORK, Bytes } from "@scure/btc-signer/utils.js";
2
2
  import { ArkAddress } from "./address";
3
3
  import { ConditionCSVMultisigTapscript, CSVMultisigTapscript } from "./tapscript";
4
4
  export type TapLeafScript = [