@arkade-os/sdk 0.4.0-next.2 → 0.4.0-next.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.
Files changed (63) hide show
  1. package/dist/cjs/{asset → extension/asset}/index.js +1 -2
  2. package/dist/cjs/extension/asset/packet.js +111 -0
  3. package/dist/cjs/{asset → extension/asset}/types.js +1 -4
  4. package/dist/cjs/extension/index.js +254 -0
  5. package/dist/cjs/extension/packet.js +20 -0
  6. package/dist/cjs/index.js +1 -1
  7. package/dist/cjs/providers/ark.js +52 -37
  8. package/dist/cjs/providers/indexer.js +1 -1
  9. package/dist/cjs/providers/utils.js +39 -29
  10. package/dist/cjs/wallet/asset-manager.js +9 -17
  11. package/dist/cjs/wallet/asset.js +1 -1
  12. package/dist/cjs/wallet/validation.js +6 -2
  13. package/dist/cjs/wallet/wallet.js +5 -4
  14. package/dist/cjs/worker/browser/service-worker-manager.js +111 -10
  15. package/dist/esm/{asset → extension/asset}/index.js +1 -1
  16. package/dist/esm/extension/asset/packet.js +107 -0
  17. package/dist/esm/{asset → extension/asset}/types.js +0 -3
  18. package/dist/esm/extension/index.js +248 -0
  19. package/dist/esm/extension/packet.js +16 -0
  20. package/dist/esm/index.js +1 -1
  21. package/dist/esm/providers/ark.js +52 -37
  22. package/dist/esm/providers/indexer.js +1 -1
  23. package/dist/esm/providers/utils.js +39 -29
  24. package/dist/esm/wallet/asset-manager.js +9 -17
  25. package/dist/esm/wallet/asset.js +1 -1
  26. package/dist/esm/wallet/validation.js +6 -2
  27. package/dist/esm/wallet/wallet.js +5 -4
  28. package/dist/esm/worker/browser/service-worker-manager.js +111 -10
  29. package/dist/types/{asset → extension/asset}/index.d.ts +1 -1
  30. package/dist/types/extension/asset/packet.d.ts +38 -0
  31. package/dist/types/{asset → extension/asset}/types.d.ts +0 -2
  32. package/dist/types/extension/index.d.ts +56 -0
  33. package/dist/types/extension/packet.d.ts +21 -0
  34. package/dist/types/index.d.ts +1 -1
  35. package/dist/types/providers/utils.d.ts +6 -0
  36. package/dist/types/wallet/asset-manager.d.ts +4 -13
  37. package/dist/types/wallet/asset.d.ts +1 -1
  38. package/dist/types/worker/browser/service-worker-manager.d.ts +15 -4
  39. package/package.json +1 -1
  40. package/dist/cjs/asset/packet.js +0 -164
  41. package/dist/esm/asset/packet.js +0 -159
  42. package/dist/types/asset/packet.d.ts +0 -27
  43. /package/dist/cjs/{asset → extension/asset}/assetGroup.js +0 -0
  44. /package/dist/cjs/{asset → extension/asset}/assetId.js +0 -0
  45. /package/dist/cjs/{asset → extension/asset}/assetInput.js +0 -0
  46. /package/dist/cjs/{asset → extension/asset}/assetOutput.js +0 -0
  47. /package/dist/cjs/{asset → extension/asset}/assetRef.js +0 -0
  48. /package/dist/cjs/{asset → extension/asset}/metadata.js +0 -0
  49. /package/dist/cjs/{asset → extension/asset}/utils.js +0 -0
  50. /package/dist/esm/{asset → extension/asset}/assetGroup.js +0 -0
  51. /package/dist/esm/{asset → extension/asset}/assetId.js +0 -0
  52. /package/dist/esm/{asset → extension/asset}/assetInput.js +0 -0
  53. /package/dist/esm/{asset → extension/asset}/assetOutput.js +0 -0
  54. /package/dist/esm/{asset → extension/asset}/assetRef.js +0 -0
  55. /package/dist/esm/{asset → extension/asset}/metadata.js +0 -0
  56. /package/dist/esm/{asset → extension/asset}/utils.js +0 -0
  57. /package/dist/types/{asset → extension/asset}/assetGroup.d.ts +0 -0
  58. /package/dist/types/{asset → extension/asset}/assetId.d.ts +0 -0
  59. /package/dist/types/{asset → extension/asset}/assetInput.d.ts +0 -0
  60. /package/dist/types/{asset → extension/asset}/assetOutput.d.ts +0 -0
  61. /package/dist/types/{asset → extension/asset}/assetRef.d.ts +0 -0
  62. /package/dist/types/{asset → extension/asset}/metadata.d.ts +0 -0
  63. /package/dist/types/{asset → extension/asset}/utils.d.ts +0 -0
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AssetPacketNotFoundError = exports.Packet = exports.AssetGroup = exports.MetadataList = exports.Metadata = exports.AssetOutputs = exports.AssetOutput = exports.AssetInputs = exports.AssetInput = exports.AssetRef = exports.AssetId = exports.AssetRefType = exports.AssetInputType = void 0;
3
+ exports.Packet = exports.AssetGroup = exports.MetadataList = exports.Metadata = exports.AssetOutputs = exports.AssetOutput = exports.AssetInputs = exports.AssetInput = exports.AssetRef = exports.AssetId = exports.AssetRefType = exports.AssetInputType = void 0;
4
4
  var types_1 = require("./types");
5
5
  Object.defineProperty(exports, "AssetInputType", { enumerable: true, get: function () { return types_1.AssetInputType; } });
6
6
  Object.defineProperty(exports, "AssetRefType", { enumerable: true, get: function () { return types_1.AssetRefType; } });
@@ -21,4 +21,3 @@ var assetGroup_1 = require("./assetGroup");
21
21
  Object.defineProperty(exports, "AssetGroup", { enumerable: true, get: function () { return assetGroup_1.AssetGroup; } });
22
22
  var packet_1 = require("./packet");
23
23
  Object.defineProperty(exports, "Packet", { enumerable: true, get: function () { return packet_1.Packet; } });
24
- Object.defineProperty(exports, "AssetPacketNotFoundError", { enumerable: true, get: function () { return packet_1.AssetPacketNotFoundError; } });
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Packet = void 0;
4
+ const base_1 = require("@scure/base");
5
+ const types_1 = require("./types");
6
+ const assetGroup_1 = require("./assetGroup");
7
+ const utils_1 = require("./utils");
8
+ /**
9
+ * Packet represents a collection of asset groups.
10
+ * It encodes/decodes as raw bytes only — OP_RETURN framing is handled by the Extension module.
11
+ */
12
+ class Packet {
13
+ constructor(groups) {
14
+ this.groups = groups;
15
+ }
16
+ static create(groups) {
17
+ const p = new Packet(groups);
18
+ p.validate();
19
+ return p;
20
+ }
21
+ /**
22
+ * fromBytes parses a Packet from raw bytes.
23
+ */
24
+ static fromBytes(buf) {
25
+ return Packet.fromReader(new utils_1.BufferReader(buf));
26
+ }
27
+ /**
28
+ * fromString parses a Packet from a raw hex string (not an OP_RETURN script).
29
+ */
30
+ static fromString(s) {
31
+ if (!s) {
32
+ throw new Error("missing packet data");
33
+ }
34
+ let buf;
35
+ try {
36
+ buf = base_1.hex.decode(s);
37
+ }
38
+ catch {
39
+ throw new Error("invalid packet format, must be hex");
40
+ }
41
+ return Packet.fromBytes(buf);
42
+ }
43
+ /**
44
+ * type returns the TLV packet type tag. Implements ExtensionPacket interface.
45
+ */
46
+ type() {
47
+ return Packet.PACKET_TYPE;
48
+ }
49
+ leafTxPacket(intentTxid) {
50
+ const leafGroups = this.groups.map((group) => group.toBatchLeafAssetGroup(intentTxid));
51
+ return new Packet(leafGroups);
52
+ }
53
+ /**
54
+ * serialize encodes the packet as raw bytes (varint group count + group data).
55
+ * Does NOT include OP_RETURN, ARK magic, or TLV type/length — those are
56
+ * added by the Extension module.
57
+ */
58
+ serialize() {
59
+ if (this.groups.length === 0) {
60
+ return new Uint8Array(0);
61
+ }
62
+ const writer = new utils_1.BufferWriter();
63
+ writer.writeVarUint(this.groups.length);
64
+ for (const group of this.groups) {
65
+ group.serializeTo(writer);
66
+ }
67
+ return writer.toBytes();
68
+ }
69
+ /**
70
+ * toString returns the hex-encoded raw packet bytes.
71
+ */
72
+ toString() {
73
+ return base_1.hex.encode(this.serialize());
74
+ }
75
+ validate() {
76
+ if (this.groups.length === 0) {
77
+ throw new Error("missing assets");
78
+ }
79
+ const seenAssetIds = new Set();
80
+ for (const group of this.groups) {
81
+ if (group.assetId !== null) {
82
+ const key = group.assetId.toString();
83
+ if (seenAssetIds.has(key)) {
84
+ throw new Error(`duplicate asset group for asset ${key}`);
85
+ }
86
+ seenAssetIds.add(key);
87
+ }
88
+ if (group.controlAsset !== null &&
89
+ group.controlAsset.ref.type === types_1.AssetRefType.ByGroup &&
90
+ group.controlAsset.ref.groupIndex >= this.groups.length) {
91
+ throw new Error(`invalid control asset group index, ${group.controlAsset.ref.groupIndex} out of range [0, ${this.groups.length - 1}]`);
92
+ }
93
+ }
94
+ }
95
+ static fromReader(reader) {
96
+ const count = Number(reader.readVarUint());
97
+ const groups = [];
98
+ for (let i = 0; i < count; i++) {
99
+ groups.push(assetGroup_1.AssetGroup.fromReader(reader));
100
+ }
101
+ if (reader.remaining() > 0) {
102
+ throw new Error(`invalid packet length, left ${reader.remaining()} unknown bytes to read`);
103
+ }
104
+ const packet = new Packet(groups);
105
+ packet.validate();
106
+ return packet;
107
+ }
108
+ }
109
+ exports.Packet = Packet;
110
+ /** PACKET_TYPE is the 1-byte TLV type tag used in the Extension envelope. */
111
+ Packet.PACKET_TYPE = 0;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MARKER_ASSET_PAYLOAD = exports.ARKADE_MAGIC = exports.MASK_METADATA = exports.MASK_CONTROL_ASSET = exports.MASK_ASSET_ID = exports.AssetRefType = exports.AssetInputType = exports.ASSET_VERSION = exports.ASSET_ID_SIZE = exports.TX_HASH_SIZE = void 0;
3
+ exports.MASK_METADATA = exports.MASK_CONTROL_ASSET = exports.MASK_ASSET_ID = exports.AssetRefType = exports.AssetInputType = exports.ASSET_VERSION = exports.ASSET_ID_SIZE = exports.TX_HASH_SIZE = void 0;
4
4
  exports.TX_HASH_SIZE = 32;
5
5
  exports.ASSET_ID_SIZE = 34;
6
6
  exports.ASSET_VERSION = 0x01;
@@ -20,6 +20,3 @@ var AssetRefType;
20
20
  exports.MASK_ASSET_ID = 0x01;
21
21
  exports.MASK_CONTROL_ASSET = 0x02;
22
22
  exports.MASK_METADATA = 0x04;
23
- // ARK magic bytes and marker
24
- exports.ARKADE_MAGIC = new Uint8Array([0x41, 0x52, 0x4b]); // "ARK"
25
- exports.MARKER_ASSET_PAYLOAD = 0x00;
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Extension = exports.ExtensionNotFoundError = exports.ARKADE_MAGIC = exports.UnknownPacket = void 0;
4
+ const base_1 = require("@scure/base");
5
+ const btc_signer_1 = require("@scure/btc-signer");
6
+ const utils_js_1 = require("@scure/btc-signer/utils.js");
7
+ const packet_1 = require("./asset/packet");
8
+ const utils_1 = require("./asset/utils");
9
+ const packet_2 = require("./packet");
10
+ var packet_3 = require("./packet");
11
+ Object.defineProperty(exports, "UnknownPacket", { enumerable: true, get: function () { return packet_3.UnknownPacket; } });
12
+ /**
13
+ * ArkadeMagic is the 3-byte magic prefix ("ARK") that identifies an OP_RETURN
14
+ * output as an ark extension blob.
15
+ */
16
+ exports.ARKADE_MAGIC = new Uint8Array([0x41, 0x52, 0x4b]); // "ARK"
17
+ /**
18
+ * ErrExtensionNotFound is thrown when no extension output is found in a transaction.
19
+ */
20
+ class ExtensionNotFoundError extends Error {
21
+ constructor() {
22
+ super("no extension output found in transaction");
23
+ this.name = "ExtensionNotFoundError";
24
+ }
25
+ }
26
+ exports.ExtensionNotFoundError = ExtensionNotFoundError;
27
+ /**
28
+ * Extension is a set of typed packets encoded in an OP_RETURN output.
29
+ *
30
+ * Wire format:
31
+ * OP_RETURN | <push> | ARK(3B) | [type(1B) | varint_len | data]...
32
+ */
33
+ class Extension {
34
+ constructor(packets) {
35
+ this.packets = packets;
36
+ }
37
+ static create(packets) {
38
+ if (packets.length === 0) {
39
+ throw new Error("missing packets");
40
+ }
41
+ const seen = new Set();
42
+ for (const p of packets) {
43
+ if (seen.has(p.type())) {
44
+ throw new Error(`duplicate packet type ${p.type()}`);
45
+ }
46
+ seen.add(p.type());
47
+ }
48
+ return new Extension(packets);
49
+ }
50
+ /**
51
+ * isExtension returns true if the script is an OP_RETURN whose push data
52
+ * begins with the ARK magic bytes.
53
+ */
54
+ static isExtension(script) {
55
+ try {
56
+ const decoded = btc_signer_1.Script.decode(script);
57
+ if (decoded.length < 2 || decoded[0] !== "RETURN")
58
+ return false;
59
+ const data = decoded[1];
60
+ if (!(data instanceof Uint8Array))
61
+ return false;
62
+ return (data.length >= exports.ARKADE_MAGIC.length &&
63
+ (0, utils_js_1.equalBytes)(data.slice(0, exports.ARKADE_MAGIC.length), exports.ARKADE_MAGIC));
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /**
70
+ * fromBytes parses an Extension from a raw OP_RETURN script.
71
+ */
72
+ static fromBytes(script) {
73
+ if (!script || script.length === 0) {
74
+ throw new Error("missing OP_RETURN");
75
+ }
76
+ let decoded;
77
+ try {
78
+ decoded = btc_signer_1.Script.decode(script);
79
+ }
80
+ catch {
81
+ throw new Error("expected OP_RETURN");
82
+ }
83
+ if (decoded.length === 0 || decoded[0] !== "RETURN") {
84
+ throw new Error("expected OP_RETURN");
85
+ }
86
+ const dataPushes = decoded
87
+ .slice(1)
88
+ .filter((x) => x instanceof Uint8Array);
89
+ if (dataPushes.length === 0) {
90
+ throw new Error("missing magic prefix: EOF");
91
+ }
92
+ // Concatenate all data pushes (handles OP_PUSHDATA1/2/4)
93
+ const payload = new Uint8Array(dataPushes.reduce((acc, d) => acc + d.length, 0));
94
+ let offset = 0;
95
+ for (const d of dataPushes) {
96
+ payload.set(d, offset);
97
+ offset += d.length;
98
+ }
99
+ // Check ARK magic
100
+ if (payload.length < exports.ARKADE_MAGIC.length ||
101
+ !(0, utils_js_1.equalBytes)(payload.slice(0, exports.ARKADE_MAGIC.length), exports.ARKADE_MAGIC)) {
102
+ throw new Error(`expected magic prefix ${base_1.hex.encode(exports.ARKADE_MAGIC)}, got ${base_1.hex.encode(payload.slice(0, Math.min(payload.length, exports.ARKADE_MAGIC.length)))}`);
103
+ }
104
+ // Parse TLV records
105
+ const reader = new utils_1.BufferReader(payload.slice(exports.ARKADE_MAGIC.length));
106
+ const packets = [];
107
+ while (reader.remaining() > 0) {
108
+ const packetType = reader.readByte();
109
+ let data;
110
+ try {
111
+ data = reader.readVarSlice();
112
+ }
113
+ catch {
114
+ throw new Error("missing packet data");
115
+ }
116
+ packets.push(parsePacket(packetType, data));
117
+ }
118
+ if (packets.length === 0) {
119
+ throw new Error("missing packets");
120
+ }
121
+ // Reject duplicate packet types
122
+ const seen = new Set();
123
+ for (const p of packets) {
124
+ if (seen.has(p.type())) {
125
+ throw new Error(`duplicate packet type ${p.type()}`);
126
+ }
127
+ seen.add(p.type());
128
+ }
129
+ return new Extension(packets);
130
+ }
131
+ /**
132
+ * fromTx searches the transaction outputs for an extension blob and parses it.
133
+ * Throws ExtensionNotFoundError if none is found.
134
+ */
135
+ static fromTx(tx) {
136
+ for (let i = 0; i < tx.outputsLength; i++) {
137
+ const output = tx.getOutput(i);
138
+ if (!output?.script)
139
+ continue;
140
+ if (Extension.isExtension(output.script)) {
141
+ return Extension.fromBytes(output.script);
142
+ }
143
+ }
144
+ throw new ExtensionNotFoundError();
145
+ }
146
+ /**
147
+ * serialize encodes the extension as an OP_RETURN script.
148
+ *
149
+ * Layout: OP_RETURN | <push> | ARK | [type | varint_len | data]...
150
+ */
151
+ serialize() {
152
+ // Build payload: ARK magic + TLV records
153
+ const parts = [exports.ARKADE_MAGIC];
154
+ for (const p of this.packets) {
155
+ const data = p.serialize();
156
+ // type (1 byte)
157
+ const typeByte = new Uint8Array([p.type()]);
158
+ // varint length prefix + data
159
+ const lengthBuf = encodeVarUint(data.length);
160
+ parts.push(typeByte, lengthBuf, data);
161
+ }
162
+ const totalLen = parts.reduce((acc, p) => acc + p.length, 0);
163
+ const payload = new Uint8Array(totalLen);
164
+ let off = 0;
165
+ for (const p of parts) {
166
+ payload.set(p, off);
167
+ off += p.length;
168
+ }
169
+ return buildOpReturnScript(payload);
170
+ }
171
+ /**
172
+ * txOut returns the extension as a zero-value OP_RETURN transaction output.
173
+ */
174
+ txOut() {
175
+ return {
176
+ script: this.serialize(),
177
+ amount: 0n,
178
+ };
179
+ }
180
+ /**
181
+ * getAssetPacket returns the embedded Packet, or null if not present.
182
+ */
183
+ getAssetPacket() {
184
+ for (const p of this.packets) {
185
+ if (p instanceof packet_1.Packet) {
186
+ return p;
187
+ }
188
+ }
189
+ return null;
190
+ }
191
+ }
192
+ exports.Extension = Extension;
193
+ /**
194
+ * parsePacket dispatches to a known packet type or falls back to UnknownPacket.
195
+ */
196
+ function parsePacket(packetType, data) {
197
+ if (packetType === packet_1.Packet.PACKET_TYPE) {
198
+ return packet_1.Packet.fromBytes(data);
199
+ }
200
+ return new packet_2.UnknownPacket(packetType, data);
201
+ }
202
+ /**
203
+ * encodeVarUint encodes a non-negative integer as a LEB128 unsigned varint.
204
+ */
205
+ function encodeVarUint(value) {
206
+ const bytes = [];
207
+ let remaining = value;
208
+ do {
209
+ let byte = remaining & 0x7f;
210
+ remaining >>>= 7;
211
+ if (remaining > 0)
212
+ byte |= 0x80;
213
+ bytes.push(byte);
214
+ } while (remaining > 0);
215
+ return new Uint8Array(bytes);
216
+ }
217
+ /**
218
+ * buildOpReturnScript builds an OP_RETURN script with an arbitrary-length data push.
219
+ * Manually constructed to avoid the 520-byte cap in some script builders.
220
+ *
221
+ * Opcodes: 0x6a=OP_RETURN, 0x4c=OP_PUSHDATA1, 0x4d=OP_PUSHDATA2, 0x4e=OP_PUSHDATA4
222
+ */
223
+ function buildOpReturnScript(data) {
224
+ const n = data.length;
225
+ let script;
226
+ if (n <= 75) {
227
+ script = new Uint8Array(2 + n);
228
+ script[0] = 0x6a; // OP_RETURN
229
+ script[1] = n;
230
+ script.set(data, 2);
231
+ }
232
+ else if (n <= 255) {
233
+ script = new Uint8Array(3 + n);
234
+ script[0] = 0x6a;
235
+ script[1] = 0x4c; // OP_PUSHDATA1
236
+ script[2] = n;
237
+ script.set(data, 3);
238
+ }
239
+ else if (n <= 65535) {
240
+ script = new Uint8Array(4 + n);
241
+ script[0] = 0x6a;
242
+ script[1] = 0x4d; // OP_PUSHDATA2
243
+ new DataView(script.buffer).setUint16(2, n, true);
244
+ script.set(data, 4);
245
+ }
246
+ else {
247
+ script = new Uint8Array(6 + n);
248
+ script[0] = 0x6a;
249
+ script[1] = 0x4e; // OP_PUSHDATA4
250
+ new DataView(script.buffer).setUint32(2, n, true);
251
+ script.set(data, 6);
252
+ }
253
+ return script;
254
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnknownPacket = void 0;
4
+ /**
5
+ * UnknownPacket holds a packet whose type is not recognized by this implementation.
6
+ * It round-trips opaquely: the raw bytes are preserved as-is.
7
+ */
8
+ class UnknownPacket {
9
+ constructor(packetType, data) {
10
+ this.packetType = packetType;
11
+ this.data = data;
12
+ }
13
+ type() {
14
+ return this.packetType;
15
+ }
16
+ serialize() {
17
+ return this.data;
18
+ }
19
+ }
20
+ exports.UnknownPacket = UnknownPacket;
package/dist/cjs/index.js CHANGED
@@ -156,7 +156,7 @@ Object.defineProperty(exports, "ContractRepositoryImpl", { enumerable: true, get
156
156
  const delegator_2 = require("./wallet/delegator");
157
157
  Object.defineProperty(exports, "DelegatorManagerImpl", { enumerable: true, get: function () { return delegator_2.DelegatorManagerImpl; } });
158
158
  __exportStar(require("./arkfee"), exports);
159
- exports.asset = __importStar(require("./asset"));
159
+ exports.asset = __importStar(require("./extension/asset"));
160
160
  // Contracts
161
161
  const contracts_1 = require("./contracts");
162
162
  Object.defineProperty(exports, "ContractManager", { enumerable: true, get: function () { return contracts_1.ContractManager; } });
@@ -225,54 +225,69 @@ class RestArkProvider {
225
225
  handleError(errorText, `Failed to submit forfeit transactions: ${response.statusText}`);
226
226
  }
227
227
  }
228
- async *getEventStream(signal, topics) {
228
+ getEventStream(signal, topics) {
229
229
  const url = `${this.serverUrl}/v1/batch/events`;
230
230
  const queryParams = topics.length > 0
231
231
  ? `?${topics.map((topic) => `topics=${encodeURIComponent(topic)}`).join("&")}`
232
232
  : "";
233
- while (!signal?.aborted) {
234
- try {
235
- const eventSource = new EventSource(url + queryParams);
236
- // Set up abort handling
237
- const abortHandler = () => {
238
- eventSource.close();
239
- };
240
- signal?.addEventListener("abort", abortHandler);
233
+ // Create first EventSource eagerly so events are buffered
234
+ // before the caller starts iterating, preventing race conditions
235
+ // where the server emits events before iteration begins.
236
+ const eagerEventSource = new EventSource(url + queryParams);
237
+ const eagerIterator = (0, utils_1.eventSourceIterator)(eagerEventSource);
238
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
239
+ const self = this;
240
+ return (async function* () {
241
+ let firstIteration = true;
242
+ while (!signal?.aborted) {
243
+ const eventSource = firstIteration
244
+ ? eagerEventSource
245
+ : new EventSource(url + queryParams);
246
+ const iterator = firstIteration
247
+ ? eagerIterator
248
+ : (0, utils_1.eventSourceIterator)(eventSource);
249
+ firstIteration = false;
241
250
  try {
242
- for await (const event of (0, utils_1.eventSourceIterator)(eventSource)) {
243
- if (signal?.aborted)
244
- break;
245
- try {
246
- const data = JSON.parse(event.data);
247
- const settlementEvent = this.parseSettlementEvent(data);
248
- if (settlementEvent) {
249
- yield settlementEvent;
251
+ const abortHandler = () => {
252
+ eventSource.close();
253
+ };
254
+ signal?.addEventListener("abort", abortHandler);
255
+ try {
256
+ for await (const event of iterator) {
257
+ if (signal?.aborted)
258
+ break;
259
+ try {
260
+ const data = JSON.parse(event.data);
261
+ const settlementEvent = self.parseSettlementEvent(data);
262
+ if (settlementEvent) {
263
+ yield settlementEvent;
264
+ }
265
+ }
266
+ catch (err) {
267
+ console.error("Failed to parse event:", err);
268
+ throw err;
250
269
  }
251
- }
252
- catch (err) {
253
- console.error("Failed to parse event:", err);
254
- throw err;
255
270
  }
256
271
  }
272
+ finally {
273
+ signal?.removeEventListener("abort", abortHandler);
274
+ eventSource.close();
275
+ }
257
276
  }
258
- finally {
259
- signal?.removeEventListener("abort", abortHandler);
260
- eventSource.close();
261
- }
262
- }
263
- catch (error) {
264
- if (error instanceof Error && error.name === "AbortError") {
265
- break;
266
- }
267
- // ignore timeout errors, they're expected when the server is not sending anything for 5 min
268
- if (isFetchTimeoutError(error)) {
269
- console.debug("Timeout error ignored");
270
- continue;
277
+ catch (error) {
278
+ if (error instanceof Error && error.name === "AbortError") {
279
+ break;
280
+ }
281
+ // ignore timeout errors, they're expected when the server is not sending anything for 5 min
282
+ if (isFetchTimeoutError(error)) {
283
+ console.debug("Timeout error ignored");
284
+ continue;
285
+ }
286
+ console.error("Event stream error:", error);
287
+ throw error;
271
288
  }
272
- console.error("Event stream error:", error);
273
- throw error;
274
289
  }
275
- }
290
+ })();
276
291
  }
277
292
  async *getTransactionsStream(signal) {
278
293
  const url = `${this.serverUrl}/v1/txs`;
@@ -4,7 +4,7 @@ exports.RestIndexerProvider = exports.ChainTxType = exports.IndexerTxType = void
4
4
  const base_1 = require("@scure/base");
5
5
  const ark_1 = require("./ark");
6
6
  const utils_1 = require("./utils");
7
- const asset_1 = require("../asset");
7
+ const asset_1 = require("../extension/asset");
8
8
  var IndexerTxType;
9
9
  (function (IndexerTxType) {
10
10
  IndexerTxType[IndexerTxType["INDEXER_TX_TYPE_UNSPECIFIED"] = 0] = "INDEXER_TX_TYPE_UNSPECIFIED";
@@ -1,7 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.eventSourceIterator = eventSourceIterator;
4
- async function* eventSourceIterator(eventSource) {
4
+ /**
5
+ * Creates an async iterator over EventSource messages that attaches listeners
6
+ * eagerly (at call time) rather than lazily (at first .next() call).
7
+ * This ensures events are buffered immediately, preventing race conditions
8
+ * where events arrive before iteration begins.
9
+ */
10
+ function eventSourceIterator(eventSource) {
5
11
  const messageQueue = [];
6
12
  const errorQueue = [];
7
13
  let messageResolve = null;
@@ -26,36 +32,40 @@ async function* eventSourceIterator(eventSource) {
26
32
  errorQueue.push(error);
27
33
  }
28
34
  };
35
+ // Attach listeners immediately so events are buffered
36
+ // even before the caller starts iterating
29
37
  eventSource.addEventListener("message", messageHandler);
30
38
  eventSource.addEventListener("error", errorHandler);
31
- try {
32
- while (true) {
33
- // if we have queued messages, yield the first one, remove it from the queue
34
- if (messageQueue.length > 0) {
35
- yield messageQueue.shift();
36
- continue;
37
- }
38
- // if we have queued errors, throw the first one, remove it from the queue
39
- if (errorQueue.length > 0) {
40
- const error = errorQueue.shift();
41
- throw error;
42
- }
43
- // wait for the next message or error
44
- const result = await new Promise((resolve, reject) => {
45
- messageResolve = resolve;
46
- errorResolve = reject;
47
- }).finally(() => {
48
- messageResolve = null;
49
- errorResolve = null;
50
- });
51
- if (result) {
52
- yield result;
39
+ return (async function* () {
40
+ try {
41
+ while (true) {
42
+ // if we have queued messages, yield the first one, remove it from the queue
43
+ if (messageQueue.length > 0) {
44
+ yield messageQueue.shift();
45
+ continue;
46
+ }
47
+ // if we have queued errors, throw the first one, remove it from the queue
48
+ if (errorQueue.length > 0) {
49
+ const error = errorQueue.shift();
50
+ throw error;
51
+ }
52
+ // wait for the next message or error
53
+ const result = await new Promise((resolve, reject) => {
54
+ messageResolve = resolve;
55
+ errorResolve = reject;
56
+ }).finally(() => {
57
+ messageResolve = null;
58
+ errorResolve = null;
59
+ });
60
+ if (result) {
61
+ yield result;
62
+ }
53
63
  }
54
64
  }
55
- }
56
- finally {
57
- // clean up
58
- eventSource.removeEventListener("message", messageHandler);
59
- eventSource.removeEventListener("error", errorHandler);
60
- }
65
+ finally {
66
+ // clean up
67
+ eventSource.removeEventListener("message", messageHandler);
68
+ eventSource.removeEventListener("error", errorHandler);
69
+ }
70
+ })();
61
71
  }