@arkade-os/sdk 0.3.0-alpha.8 → 0.3.1-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 (77) hide show
  1. package/README.md +64 -14
  2. package/dist/cjs/arknote/index.js +3 -3
  3. package/dist/cjs/forfeit.js +5 -2
  4. package/dist/cjs/identity/singleKey.js +5 -4
  5. package/dist/cjs/index.js +6 -3
  6. package/dist/cjs/{bip322 → intent}/index.js +37 -55
  7. package/dist/cjs/providers/ark.js +62 -23
  8. package/dist/cjs/providers/expoArk.js +15 -170
  9. package/dist/cjs/providers/expoIndexer.js +22 -111
  10. package/dist/cjs/providers/expoUtils.js +124 -0
  11. package/dist/cjs/script/base.js +1 -2
  12. package/dist/cjs/script/tapscript.js +20 -21
  13. package/dist/cjs/script/vhtlc.js +2 -2
  14. package/dist/cjs/tree/signingSession.js +7 -8
  15. package/dist/cjs/tree/txTree.js +3 -4
  16. package/dist/cjs/tree/validation.js +2 -3
  17. package/dist/cjs/utils/arkTransaction.js +104 -12
  18. package/dist/cjs/utils/unknownFields.js +5 -5
  19. package/dist/cjs/wallet/onchain.js +4 -5
  20. package/dist/cjs/wallet/serviceWorker/utils.js +2 -0
  21. package/dist/cjs/wallet/serviceWorker/wallet.js +4 -8
  22. package/dist/cjs/wallet/serviceWorker/worker.js +23 -18
  23. package/dist/cjs/wallet/unroll.js +6 -7
  24. package/dist/cjs/wallet/vtxo-manager.js +381 -0
  25. package/dist/cjs/wallet/wallet.js +63 -94
  26. package/dist/esm/arknote/index.js +2 -2
  27. package/dist/esm/forfeit.js +4 -1
  28. package/dist/esm/identity/singleKey.js +7 -6
  29. package/dist/esm/index.js +7 -6
  30. package/dist/esm/{bip322 → intent}/index.js +31 -48
  31. package/dist/esm/providers/ark.js +62 -23
  32. package/dist/esm/providers/expoArk.js +15 -137
  33. package/dist/esm/providers/expoIndexer.js +22 -78
  34. package/dist/esm/providers/expoUtils.js +87 -0
  35. package/dist/esm/script/base.js +1 -2
  36. package/dist/esm/script/tapscript.js +1 -2
  37. package/dist/esm/script/vhtlc.js +1 -1
  38. package/dist/esm/tree/signingSession.js +8 -9
  39. package/dist/esm/tree/txTree.js +3 -4
  40. package/dist/esm/tree/validation.js +2 -3
  41. package/dist/esm/utils/arkTransaction.js +95 -4
  42. package/dist/esm/utils/unknownFields.js +1 -1
  43. package/dist/esm/wallet/onchain.js +1 -2
  44. package/dist/esm/wallet/serviceWorker/utils.js +1 -0
  45. package/dist/esm/wallet/serviceWorker/wallet.js +5 -9
  46. package/dist/esm/wallet/serviceWorker/worker.js +23 -18
  47. package/dist/esm/wallet/unroll.js +2 -3
  48. package/dist/esm/wallet/vtxo-manager.js +372 -0
  49. package/dist/esm/wallet/wallet.js +56 -87
  50. package/dist/types/arknote/index.d.ts +1 -1
  51. package/dist/types/forfeit.d.ts +2 -2
  52. package/dist/types/identity/index.d.ts +1 -1
  53. package/dist/types/identity/singleKey.d.ts +1 -1
  54. package/dist/types/index.d.ts +6 -5
  55. package/dist/types/intent/index.d.ts +41 -0
  56. package/dist/types/providers/ark.d.ts +55 -21
  57. package/dist/types/providers/expoIndexer.d.ts +2 -10
  58. package/dist/types/providers/expoUtils.d.ts +18 -0
  59. package/dist/types/providers/indexer.d.ts +1 -9
  60. package/dist/types/script/base.d.ts +3 -2
  61. package/dist/types/tree/signingSession.d.ts +10 -10
  62. package/dist/types/utils/anchor.d.ts +2 -2
  63. package/dist/types/utils/arkTransaction.d.ts +13 -3
  64. package/dist/types/utils/unknownFields.d.ts +2 -2
  65. package/dist/types/wallet/index.d.ts +6 -4
  66. package/dist/types/wallet/onchain.d.ts +1 -1
  67. package/dist/types/wallet/serviceWorker/utils.d.ts +1 -0
  68. package/dist/types/wallet/serviceWorker/wallet.d.ts +2 -2
  69. package/dist/types/wallet/serviceWorker/worker.d.ts +3 -1
  70. package/dist/types/wallet/unroll.d.ts +1 -1
  71. package/dist/types/wallet/vtxo-manager.d.ts +207 -0
  72. package/dist/types/wallet/wallet.d.ts +7 -3
  73. package/package.json +1 -2
  74. package/dist/cjs/bip322/errors.js +0 -13
  75. package/dist/esm/bip322/errors.js +0 -9
  76. package/dist/types/bip322/errors.d.ts +0 -6
  77. package/dist/types/bip322/index.d.ts +0 -57
@@ -1,40 +1,8 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.ExpoArkProvider = void 0;
37
4
  const ark_1 = require("./ark");
5
+ const expoUtils_1 = require("./expoUtils");
38
6
  /**
39
7
  * Expo-compatible Ark provider implementation using expo/fetch for SSE support.
40
8
  * This provider works specifically in React Native/Expo environments where
@@ -53,87 +21,23 @@ class ExpoArkProvider extends ark_1.RestArkProvider {
53
21
  super(serverUrl);
54
22
  }
55
23
  async *getEventStream(signal, topics) {
56
- // Dynamic import to avoid bundling expo/fetch in non-Expo environments
57
- let expoFetch = fetch; // Default to standard fetch
58
- try {
59
- const expoFetchModule = await Promise.resolve().then(() => __importStar(require("expo/fetch")));
60
- // expo/fetch returns a compatible fetch function but with different types
61
- expoFetch = expoFetchModule.fetch;
62
- console.debug("Using expo/fetch for SSE");
63
- }
64
- catch (error) {
65
- // Fall back to standard fetch if expo/fetch is not available
66
- console.warn("Using standard fetch instead of expo/fetch. " +
67
- "Streaming may not be fully supported in some environments.", error);
68
- }
24
+ const expoFetch = await (0, expoUtils_1.getExpoFetch)();
69
25
  const url = `${this.serverUrl}/v1/batch/events`;
70
26
  const queryParams = topics.length > 0
71
27
  ? `?${topics.map((topic) => `topics=${encodeURIComponent(topic)}`).join("&")}`
72
28
  : "";
73
29
  while (!signal?.aborted) {
74
- // Create a new AbortController for this specific fetch attempt
75
- // to prevent accumulating listeners on the parent signal
76
- const fetchController = new AbortController();
77
- const cleanup = () => fetchController.abort();
78
- signal?.addEventListener("abort", cleanup, { once: true });
79
30
  try {
80
- const response = await expoFetch(url + queryParams, {
81
- headers: {
82
- Accept: "text/event-stream",
83
- },
84
- signal: fetchController.signal,
85
- });
86
- if (!response.ok) {
87
- throw new Error(`Unexpected status ${response.status} when fetching event stream`);
88
- }
89
- if (!response.body) {
90
- throw new Error("Response body is null");
91
- }
92
- const reader = response.body.getReader();
93
- const decoder = new TextDecoder();
94
- let buffer = "";
95
- while (!signal?.aborted) {
96
- const { done, value } = await reader.read();
97
- if (done) {
98
- break;
99
- }
100
- // Append new data to buffer and split by newlines
101
- buffer += decoder.decode(value, { stream: true });
102
- const lines = buffer.split("\n");
103
- // Process all complete lines
104
- for (let i = 0; i < lines.length - 1; i++) {
105
- const line = lines[i].trim();
106
- if (!line)
107
- continue;
108
- try {
109
- // Parse SSE format: "data: {json}"
110
- if (line.startsWith("data:")) {
111
- const jsonStr = line.substring(5).trim();
112
- if (!jsonStr)
113
- continue;
114
- const data = JSON.parse(jsonStr);
115
- // Handle different response structures
116
- // v8 mesh API might wrap in {result: ...} or send directly
117
- const eventData = data.result || data;
118
- // Skip heartbeat messages
119
- if (eventData.heartbeat !== undefined) {
120
- continue;
121
- }
122
- const event = this.parseSettlementEvent(eventData);
123
- if (event) {
124
- yield event;
125
- }
126
- }
127
- }
128
- catch (err) {
129
- console.error("Failed to parse event:", line);
130
- console.error("Parse error:", err);
131
- throw err;
132
- }
31
+ yield* (0, expoUtils_1.sseStreamIterator)(url + queryParams, signal, expoFetch, {}, (data) => {
32
+ // Handle different response structures
33
+ // v8 mesh API might wrap in {result: ...} or send directly
34
+ const eventData = data.result || data;
35
+ // Skip heartbeat messages
36
+ if (eventData.heartbeat !== undefined) {
37
+ return null;
133
38
  }
134
- // Keep the last partial line in the buffer
135
- buffer = lines[lines.length - 1];
136
- }
39
+ return this.parseSettlementEvent(eventData);
40
+ });
137
41
  }
138
42
  catch (error) {
139
43
  if (error instanceof Error && error.name === "AbortError") {
@@ -148,71 +52,16 @@ class ExpoArkProvider extends ark_1.RestArkProvider {
148
52
  console.error("Event stream error:", error);
149
53
  throw error;
150
54
  }
151
- finally {
152
- // Clean up the abort listener
153
- signal?.removeEventListener("abort", cleanup);
154
- }
155
55
  }
156
56
  }
157
57
  async *getTransactionsStream(signal) {
158
- // Dynamic import to avoid bundling expo/fetch in non-Expo environments
159
- let expoFetch = fetch; // Default to standard fetch
160
- try {
161
- const expoFetchModule = await Promise.resolve().then(() => __importStar(require("expo/fetch")));
162
- // expo/fetch returns a compatible fetch function but with different types
163
- expoFetch = expoFetchModule.fetch;
164
- console.debug("Using expo/fetch for transaction stream");
165
- }
166
- catch (error) {
167
- // Fall back to standard fetch if expo/fetch is not available
168
- console.warn("Using standard fetch instead of expo/fetch. " +
169
- "Streaming may not be fully supported in some environments.", error);
170
- }
58
+ const expoFetch = await (0, expoUtils_1.getExpoFetch)();
171
59
  const url = `${this.serverUrl}/v1/txs`;
172
60
  while (!signal?.aborted) {
173
- // Create a new AbortController for this specific fetch attempt
174
- // to prevent accumulating listeners on the parent signal
175
- const fetchController = new AbortController();
176
- const cleanup = () => fetchController.abort();
177
- signal?.addEventListener("abort", cleanup, { once: true });
178
61
  try {
179
- const response = await expoFetch(url, {
180
- headers: {
181
- Accept: "text/event-stream",
182
- },
183
- signal: fetchController.signal,
62
+ yield* (0, expoUtils_1.sseStreamIterator)(url, signal, expoFetch, {}, (data) => {
63
+ return this.parseTransactionNotification(data.result);
184
64
  });
185
- if (!response.ok) {
186
- throw new Error(`Unexpected status ${response.status} when fetching transaction stream`);
187
- }
188
- if (!response.body) {
189
- throw new Error("Response body is null");
190
- }
191
- const reader = response.body.getReader();
192
- const decoder = new TextDecoder();
193
- let buffer = "";
194
- while (!signal?.aborted) {
195
- const { done, value } = await reader.read();
196
- if (done) {
197
- break;
198
- }
199
- // Append new data to buffer and split by newlines
200
- buffer += decoder.decode(value, { stream: true });
201
- const lines = buffer.split("\n");
202
- // Process all complete lines
203
- for (let i = 0; i < lines.length - 1; i++) {
204
- const line = lines[i].trim();
205
- if (!line)
206
- continue;
207
- const data = JSON.parse(line);
208
- const txNotification = this.parseTransactionNotification(data.result);
209
- if (txNotification) {
210
- yield txNotification;
211
- }
212
- }
213
- // Keep the last partial line in the buffer
214
- buffer = lines[lines.length - 1];
215
- }
216
65
  }
217
66
  catch (error) {
218
67
  if (error instanceof Error && error.name === "AbortError") {
@@ -224,13 +73,9 @@ class ExpoArkProvider extends ark_1.RestArkProvider {
224
73
  console.debug("Timeout error ignored");
225
74
  continue;
226
75
  }
227
- console.error("Address subscription error:", error);
76
+ console.error("Transaction stream error:", error);
228
77
  throw error;
229
78
  }
230
- finally {
231
- // Clean up the abort listener
232
- signal?.removeEventListener("abort", cleanup);
233
- }
234
79
  }
235
80
  }
236
81
  }
@@ -1,41 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.ExpoIndexerProvider = void 0;
37
4
  const indexer_1 = require("./indexer");
38
5
  const ark_1 = require("./ark");
6
+ const expoUtils_1 = require("./expoUtils");
39
7
  // Helper function to convert Vtxo to VirtualCoin (same as in indexer.ts)
40
8
  function convertVtxo(vtxo) {
41
9
  return {
@@ -85,95 +53,38 @@ class ExpoIndexerProvider extends indexer_1.RestIndexerProvider {
85
53
  // Detect if we're running in React Native/Expo environment
86
54
  const isReactNative = typeof navigator !== "undefined" &&
87
55
  navigator.product === "ReactNative";
88
- // Dynamic import to avoid bundling expo/fetch in non-Expo environments
89
- let expoFetch = fetch; // Default to standard fetch
90
- try {
91
- const expoFetchModule = await Promise.resolve().then(() => __importStar(require("expo/fetch")));
92
- // expo/fetch returns a compatible fetch function but with different types
93
- expoFetch = expoFetchModule.fetch;
94
- console.debug("Using expo/fetch for indexer subscription");
95
- }
96
- catch (error) {
56
+ const expoFetch = await (0, expoUtils_1.getExpoFetch)().catch((error) => {
97
57
  // In React Native/Expo, expo/fetch is required for proper streaming support
98
58
  if (isReactNative) {
99
59
  throw new Error("expo/fetch is unavailable in React Native environment. " +
100
60
  "Please ensure expo/fetch is installed and properly configured. " +
101
61
  "Streaming support may not work with standard fetch in React Native.");
102
62
  }
103
- // In non-RN environments, fall back to standard fetch but warn about potential streaming issues
104
- console.warn("Using standard fetch instead of expo/fetch. " +
105
- "Streaming may not be fully supported in some environments.", error);
106
- }
63
+ throw error;
64
+ });
107
65
  const url = `${this.serverUrl}/v1/indexer/script/subscription/${subscriptionId}`;
108
66
  while (!abortSignal.aborted) {
109
67
  try {
110
- const res = await expoFetch(url, {
111
- headers: {
112
- Accept: "text/event-stream",
113
- "Content-Type": "application/json",
114
- },
115
- signal: abortSignal,
116
- });
117
- if (!res.ok) {
118
- throw new Error(`Unexpected status ${res.status} when subscribing to address updates`);
119
- }
120
- // Check if response is the expected content type
121
- const contentType = res.headers.get("content-type");
122
- if (contentType &&
123
- !contentType.includes("text/event-stream") &&
124
- !contentType.includes("application/json")) {
125
- throw new Error(`Unexpected content-type: ${contentType}. Expected text/event-stream or application/json`);
126
- }
127
- if (!res.body) {
128
- throw new Error("Response body is null");
129
- }
130
- const reader = res.body.getReader();
131
- const decoder = new TextDecoder();
132
- let buffer = "";
133
- while (!abortSignal.aborted) {
134
- const { done, value } = await reader.read();
135
- if (done) {
136
- break;
68
+ yield* (0, expoUtils_1.sseStreamIterator)(url, abortSignal, expoFetch, { "Content-Type": "application/json" }, (data) => {
69
+ // Handle new v8 proto format with heartbeat or event
70
+ if (data.heartbeat !== undefined) {
71
+ // Skip heartbeat messages
72
+ return null;
137
73
  }
138
- buffer += decoder.decode(value, { stream: true });
139
- const lines = buffer.split("\n");
140
- for (let i = 0; i < lines.length - 1; i++) {
141
- const line = lines[i].trim();
142
- if (!line)
143
- continue;
144
- try {
145
- // Parse SSE format: "data: {json}"
146
- if (line.startsWith("data:")) {
147
- const jsonStr = line.substring(5).trim();
148
- if (!jsonStr)
149
- continue;
150
- const data = JSON.parse(jsonStr);
151
- // Handle new v8 proto format with heartbeat or event
152
- if (data.heartbeat !== undefined) {
153
- // Skip heartbeat messages
154
- continue;
155
- }
156
- // Process event messages
157
- if (data.event) {
158
- yield {
159
- txid: data.event.txid,
160
- scripts: data.event.scripts || [],
161
- newVtxos: (data.event.newVtxos || []).map(convertVtxo),
162
- spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
163
- sweptVtxos: (data.event.sweptVtxos || []).map(convertVtxo),
164
- tx: data.event.tx,
165
- checkpointTxs: data.event.checkpointTxs,
166
- };
167
- }
168
- }
169
- }
170
- catch (parseError) {
171
- console.error("Failed to parse subscription response:", parseError);
172
- throw parseError;
173
- }
74
+ // Process event messages
75
+ if (data.event) {
76
+ return {
77
+ txid: data.event.txid,
78
+ scripts: data.event.scripts || [],
79
+ newVtxos: (data.event.newVtxos || []).map(convertVtxo),
80
+ spentVtxos: (data.event.spentVtxos || []).map(convertVtxo),
81
+ sweptVtxos: (data.event.sweptVtxos || []).map(convertVtxo),
82
+ tx: data.event.tx,
83
+ checkpointTxs: data.event.checkpointTxs,
84
+ };
174
85
  }
175
- buffer = lines[lines.length - 1];
176
- }
86
+ return null;
87
+ });
177
88
  }
178
89
  catch (error) {
179
90
  if (error instanceof Error && error.name === "AbortError") {
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getExpoFetch = getExpoFetch;
37
+ exports.sseStreamIterator = sseStreamIterator;
38
+ /**
39
+ * Dynamically imports expo/fetch with fallback to standard fetch.
40
+ * @returns A fetch function suitable for SSE streaming
41
+ */
42
+ async function getExpoFetch(options) {
43
+ const requireExpo = options?.requireExpo ?? false;
44
+ try {
45
+ const expoFetchModule = await Promise.resolve().then(() => __importStar(require("expo/fetch")));
46
+ console.debug("Using expo/fetch for streaming");
47
+ return expoFetchModule.fetch;
48
+ }
49
+ catch (error) {
50
+ if (requireExpo) {
51
+ throw new Error("expo/fetch is unavailable in this environment. " +
52
+ "Please ensure expo/fetch is installed and properly configured.");
53
+ }
54
+ console.warn("Using standard fetch instead of expo/fetch. " +
55
+ "Streaming may not be fully supported in some environments.", error);
56
+ return fetch;
57
+ }
58
+ }
59
+ /**
60
+ * Generic SSE stream processor using fetch API with ReadableStream.
61
+ * Handles SSE format parsing, buffer management, and abort signals.
62
+ *
63
+ * @param url - The SSE endpoint URL
64
+ * @param abortSignal - Signal to abort the stream
65
+ * @param fetchFn - Fetch function to use (defaults to standard fetch)
66
+ * @param headers - Additional headers to send
67
+ * @param parseData - Function to parse and yield data from SSE events
68
+ */
69
+ async function* sseStreamIterator(url, abortSignal, fetchFn, headers, parseData) {
70
+ const fetchController = new AbortController();
71
+ const cleanup = () => fetchController.abort();
72
+ abortSignal?.addEventListener("abort", cleanup, { once: true });
73
+ try {
74
+ const response = await fetchFn(url, {
75
+ headers: {
76
+ Accept: "text/event-stream",
77
+ ...headers,
78
+ },
79
+ signal: fetchController.signal,
80
+ });
81
+ if (!response.ok) {
82
+ throw new Error(`Unexpected status ${response.status} when fetching SSE stream`);
83
+ }
84
+ if (!response.body) {
85
+ throw new Error("Response body is null");
86
+ }
87
+ const reader = response.body.getReader();
88
+ const decoder = new TextDecoder();
89
+ let buffer = "";
90
+ while (!abortSignal?.aborted) {
91
+ const { done, value } = await reader.read();
92
+ if (done) {
93
+ break;
94
+ }
95
+ buffer += decoder.decode(value, { stream: true });
96
+ const lines = buffer.split("\n");
97
+ for (let i = 0; i < lines.length - 1; i++) {
98
+ const line = lines[i].trim();
99
+ if (!line)
100
+ continue;
101
+ if (line.startsWith("data:")) {
102
+ const jsonStr = line.substring(5).trim();
103
+ if (!jsonStr)
104
+ continue;
105
+ try {
106
+ const data = JSON.parse(jsonStr);
107
+ const parsed = parseData(data);
108
+ if (parsed !== null) {
109
+ yield parsed;
110
+ }
111
+ }
112
+ catch (parseError) {
113
+ console.error("Failed to parse SSE data:", parseError);
114
+ throw parseError;
115
+ }
116
+ }
117
+ }
118
+ buffer = lines[lines.length - 1];
119
+ }
120
+ }
121
+ finally {
122
+ abortSignal?.removeEventListener("abort", cleanup);
123
+ }
124
+ }
@@ -5,7 +5,6 @@ exports.scriptFromTapLeafScript = scriptFromTapLeafScript;
5
5
  const btc_signer_1 = require("@scure/btc-signer");
6
6
  const payment_js_1 = require("@scure/btc-signer/payment.js");
7
7
  const psbt_js_1 = require("@scure/btc-signer/psbt.js");
8
- const utils_js_1 = require("@scure/btc-signer/utils.js");
9
8
  const base_1 = require("@scure/base");
10
9
  const address_1 = require("./address");
11
10
  const tapscript_1 = require("./tapscript");
@@ -30,7 +29,7 @@ class VtxoScript {
30
29
  constructor(scripts) {
31
30
  this.scripts = scripts;
32
31
  const tapTree = (0, btc_signer_1.taprootListToTree)(scripts.map((script) => ({ script, leafVersion: payment_js_1.TAP_LEAF_VERSION })));
33
- const payment = (0, btc_signer_1.p2tr)(utils_js_1.TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true);
32
+ const payment = (0, btc_signer_1.p2tr)(btc_signer_1.TAPROOT_UNSPENDABLE_KEY, tapTree, undefined, true);
34
33
  if (!payment.tapLeafScript ||
35
34
  payment.tapLeafScript.length !== scripts.length) {
36
35
  throw new Error("invalid scripts");