@inodra/sui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +237 -0
- package/bin/inodra-sui.mjs +2 -0
- package/dist/chunk-3CBLVI6J.js +426 -0
- package/dist/chunk-3CBLVI6J.js.map +1 -0
- package/dist/chunk-4HKKW5QN.js +80 -0
- package/dist/chunk-4HKKW5QN.js.map +1 -0
- package/dist/chunk-74XGJJJI.js +33 -0
- package/dist/chunk-74XGJJJI.js.map +1 -0
- package/dist/chunk-D6FZYWG7.js +99 -0
- package/dist/chunk-D6FZYWG7.js.map +1 -0
- package/dist/chunk-LZZMTSLH.js +31 -0
- package/dist/chunk-LZZMTSLH.js.map +1 -0
- package/dist/chunk-M3M2L6BW.js +29 -0
- package/dist/chunk-M3M2L6BW.js.map +1 -0
- package/dist/chunk-NSXRC5XW.js +298 -0
- package/dist/chunk-NSXRC5XW.js.map +1 -0
- package/dist/chunk-OGMBYWTG.js +537 -0
- package/dist/chunk-OGMBYWTG.js.map +1 -0
- package/dist/chunk-U6D5LGNF.js +111 -0
- package/dist/chunk-U6D5LGNF.js.map +1 -0
- package/dist/chunk-ZSW3EWGF.js +539 -0
- package/dist/chunk-ZSW3EWGF.js.map +1 -0
- package/dist/cli.js +665 -0
- package/dist/cli.js.map +1 -0
- package/dist/events.cjs +3273 -0
- package/dist/events.cjs.map +1 -0
- package/dist/events.d.cts +47 -0
- package/dist/events.d.ts +47 -0
- package/dist/events.js +2578 -0
- package/dist/events.js.map +1 -0
- package/dist/graphql.cjs +129 -0
- package/dist/graphql.cjs.map +1 -0
- package/dist/graphql.d.cts +36 -0
- package/dist/graphql.d.ts +36 -0
- package/dist/graphql.js +10 -0
- package/dist/graphql.js.map +1 -0
- package/dist/grpc-web.cjs +129 -0
- package/dist/grpc-web.cjs.map +1 -0
- package/dist/grpc-web.d.cts +31 -0
- package/dist/grpc-web.d.ts +31 -0
- package/dist/grpc-web.js +10 -0
- package/dist/grpc-web.js.map +1 -0
- package/dist/grpc.cjs +131 -0
- package/dist/grpc.cjs.map +1 -0
- package/dist/grpc.d.cts +34 -0
- package/dist/grpc.d.ts +34 -0
- package/dist/grpc.js +10 -0
- package/dist/grpc.js.map +1 -0
- package/dist/index-CGBN_EI5.d.ts +4800 -0
- package/dist/index-CVO2Kj8a.d.cts +4800 -0
- package/dist/index.cjs +4723 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +504 -0
- package/dist/index.d.ts +504 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/manage.cjs +376 -0
- package/dist/manage.cjs.map +1 -0
- package/dist/manage.d.cts +2 -0
- package/dist/manage.d.ts +2 -0
- package/dist/manage.js +8 -0
- package/dist/manage.js.map +1 -0
- package/dist/network-CEg2MJY3.d.cts +60 -0
- package/dist/network-CEg2MJY3.d.ts +60 -0
- package/dist/node.cjs +4759 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +28 -0
- package/dist/node.d.ts +28 -0
- package/dist/node.js +73 -0
- package/dist/node.js.map +1 -0
- package/dist/reflection-Bx44-Fs1.d.ts +4639 -0
- package/dist/reflection-Cf7WFH6H.d.cts +4639 -0
- package/dist/reflection-FEGYA7DU.js +9 -0
- package/dist/reflection-FEGYA7DU.js.map +1 -0
- package/dist/runtime-OWKF3LZ7.js +37 -0
- package/dist/runtime-OWKF3LZ7.js.map +1 -0
- package/dist/warp.cjs +633 -0
- package/dist/warp.cjs.map +1 -0
- package/dist/warp.d.cts +195 -0
- package/dist/warp.d.ts +195 -0
- package/dist/warp.js +12 -0
- package/dist/warp.js.map +1 -0
- package/dist/webhooks.cjs +104 -0
- package/dist/webhooks.cjs.map +1 -0
- package/dist/webhooks.d.cts +35 -0
- package/dist/webhooks.d.ts +35 -0
- package/dist/webhooks.js +7 -0
- package/dist/webhooks.js.map +1 -0
- package/llms.txt +189 -0
- package/package.json +119 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
baseEventType,
|
|
3
|
+
eventTypeMatches,
|
|
4
|
+
innerEventType,
|
|
5
|
+
moveAddress,
|
|
6
|
+
moveBalance,
|
|
7
|
+
moveBool,
|
|
8
|
+
moveBytes,
|
|
9
|
+
moveSmallUint,
|
|
10
|
+
moveString,
|
|
11
|
+
moveTypeName,
|
|
12
|
+
moveUint,
|
|
13
|
+
warpAddressPayloadSchema,
|
|
14
|
+
warpCoinPayloadSchema,
|
|
15
|
+
warpEventPayloadSchema,
|
|
16
|
+
warpObjectPayloadSchema,
|
|
17
|
+
webhookEventBodySchema
|
|
18
|
+
} from "./chunk-D6FZYWG7.js";
|
|
19
|
+
export {
|
|
20
|
+
baseEventType,
|
|
21
|
+
eventTypeMatches,
|
|
22
|
+
innerEventType,
|
|
23
|
+
moveAddress,
|
|
24
|
+
moveBalance,
|
|
25
|
+
moveBool,
|
|
26
|
+
moveBytes,
|
|
27
|
+
moveSmallUint,
|
|
28
|
+
moveString,
|
|
29
|
+
moveTypeName,
|
|
30
|
+
moveUint,
|
|
31
|
+
warpAddressPayloadSchema,
|
|
32
|
+
warpCoinPayloadSchema,
|
|
33
|
+
warpEventPayloadSchema,
|
|
34
|
+
warpObjectPayloadSchema,
|
|
35
|
+
webhookEventBodySchema
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=runtime-OWKF3LZ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/warp.cjs
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/warp/index.ts
|
|
21
|
+
var warp_exports = {};
|
|
22
|
+
__export(warp_exports, {
|
|
23
|
+
WarpSseStream: () => WarpSseStream,
|
|
24
|
+
WarpWebSocketStream: () => WarpWebSocketStream,
|
|
25
|
+
iterateStream: () => iterateStream
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(warp_exports);
|
|
28
|
+
|
|
29
|
+
// src/warp/iterate.ts
|
|
30
|
+
async function* iterateStream(stream, options = {}) {
|
|
31
|
+
const queue = [];
|
|
32
|
+
let notify;
|
|
33
|
+
let closed = false;
|
|
34
|
+
let failure;
|
|
35
|
+
const unsubscribes = [
|
|
36
|
+
stream.on("message", (event) => {
|
|
37
|
+
queue.push(event);
|
|
38
|
+
notify?.();
|
|
39
|
+
}),
|
|
40
|
+
stream.on("close", ({ reason }) => {
|
|
41
|
+
closed = true;
|
|
42
|
+
if (reason !== "client closed") {
|
|
43
|
+
failure = new Error(`Warp stream closed: ${reason}`);
|
|
44
|
+
}
|
|
45
|
+
notify?.();
|
|
46
|
+
})
|
|
47
|
+
];
|
|
48
|
+
try {
|
|
49
|
+
for (; ; ) {
|
|
50
|
+
while (queue.length > 0) {
|
|
51
|
+
yield queue.shift();
|
|
52
|
+
}
|
|
53
|
+
if (closed) {
|
|
54
|
+
if (failure) {
|
|
55
|
+
throw failure;
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await new Promise((resolve) => {
|
|
60
|
+
notify = resolve;
|
|
61
|
+
});
|
|
62
|
+
notify = void 0;
|
|
63
|
+
}
|
|
64
|
+
} finally {
|
|
65
|
+
for (const unsubscribe of unsubscribes) {
|
|
66
|
+
unsubscribe();
|
|
67
|
+
}
|
|
68
|
+
if (options.closeOnReturn ?? true) {
|
|
69
|
+
stream.close();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/core/auth.ts
|
|
75
|
+
function resolveAuth(auth) {
|
|
76
|
+
if (typeof auth === "string") {
|
|
77
|
+
return staticAuth(apiKeyCredentials(auth));
|
|
78
|
+
}
|
|
79
|
+
if ("apiKey" in auth) {
|
|
80
|
+
return staticAuth(apiKeyCredentials(auth.apiKey));
|
|
81
|
+
}
|
|
82
|
+
if ("sessionToken" in auth) {
|
|
83
|
+
return staticAuth({
|
|
84
|
+
headers: { authorization: `Bearer ${auth.sessionToken}` }
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
credentials: async () => auth.getCredentials(),
|
|
89
|
+
staticCredentials: () => void 0
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function authFromOptions(options, context) {
|
|
93
|
+
if (options.auth !== void 0) {
|
|
94
|
+
return resolveAuth(options.auth);
|
|
95
|
+
}
|
|
96
|
+
if (options.apiKey) {
|
|
97
|
+
return resolveAuth(options.apiKey);
|
|
98
|
+
}
|
|
99
|
+
throw new Error(`${context} requires auth (or the apiKey shorthand)`);
|
|
100
|
+
}
|
|
101
|
+
function apiKeyCredentials(apiKey) {
|
|
102
|
+
if (!apiKey) {
|
|
103
|
+
throw new Error("Inodra auth: apiKey must be a non-empty string");
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
headers: { "x-api-key": apiKey },
|
|
107
|
+
queryParams: { api_key: apiKey }
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function staticAuth(credentials) {
|
|
111
|
+
return {
|
|
112
|
+
credentials: async () => credentials,
|
|
113
|
+
staticCredentials: () => credentials
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/core/version.ts
|
|
118
|
+
var SDK_VERSION = "0.1.0";
|
|
119
|
+
var SDK_HEADER_NAME = "x-inodra-sdk";
|
|
120
|
+
var SDK_HEADER_VALUE = `inodra-sdk-ts/${SDK_VERSION}`;
|
|
121
|
+
|
|
122
|
+
// src/core/network.ts
|
|
123
|
+
var INODRA_ENDPOINTS = {
|
|
124
|
+
mainnet: {
|
|
125
|
+
rest: "https://mainnet-api.inodra.com/v1",
|
|
126
|
+
graphql: "https://mainnet-api.inodra.com/v1/graphql",
|
|
127
|
+
/** host:port for native gRPC transports */
|
|
128
|
+
grpc: "mainnet-grpc.inodra.com:443",
|
|
129
|
+
/** base URL for gRPC-Web transports */
|
|
130
|
+
grpcWeb: "https://mainnet-grpc.inodra.com",
|
|
131
|
+
warpWs: "wss://mainnet-api.inodra.com/v1"
|
|
132
|
+
},
|
|
133
|
+
testnet: {
|
|
134
|
+
rest: "https://testnet-api.inodra.com/v1",
|
|
135
|
+
graphql: "https://testnet-api.inodra.com/v1/graphql",
|
|
136
|
+
grpc: "testnet-grpc.inodra.com:443",
|
|
137
|
+
grpcWeb: "https://testnet-grpc.inodra.com",
|
|
138
|
+
warpWs: "wss://testnet-api.inodra.com/v1"
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
function warpStreamUrl(network, subscriptionId) {
|
|
142
|
+
return `${INODRA_ENDPOINTS[network].rest}/warp/${subscriptionId}/stream`;
|
|
143
|
+
}
|
|
144
|
+
function warpWebSocketUrl(network, subscriptionId) {
|
|
145
|
+
return `${INODRA_ENDPOINTS[network].warpWs}/warp/${subscriptionId}/ws`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/warp/emitter.ts
|
|
149
|
+
var Emitter = class {
|
|
150
|
+
handlers = /* @__PURE__ */ new Map();
|
|
151
|
+
on(event, handler) {
|
|
152
|
+
let set = this.handlers.get(event);
|
|
153
|
+
if (!set) {
|
|
154
|
+
set = /* @__PURE__ */ new Set();
|
|
155
|
+
this.handlers.set(event, set);
|
|
156
|
+
}
|
|
157
|
+
set.add(handler);
|
|
158
|
+
return () => set?.delete(handler);
|
|
159
|
+
}
|
|
160
|
+
off(event, handler) {
|
|
161
|
+
this.handlers.get(event)?.delete(handler);
|
|
162
|
+
}
|
|
163
|
+
/** Returns false if any handler threw. */
|
|
164
|
+
emit(event, payload) {
|
|
165
|
+
let ok = true;
|
|
166
|
+
for (const handler of this.handlers.get(event) ?? []) {
|
|
167
|
+
try {
|
|
168
|
+
handler(payload);
|
|
169
|
+
} catch {
|
|
170
|
+
ok = false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return ok;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/warp/sse-parser.ts
|
|
178
|
+
var SseParser = class {
|
|
179
|
+
buffer = "";
|
|
180
|
+
eventName = "";
|
|
181
|
+
dataLines = [];
|
|
182
|
+
id;
|
|
183
|
+
retryMs;
|
|
184
|
+
feed(chunk) {
|
|
185
|
+
this.buffer += chunk;
|
|
186
|
+
const messages = [];
|
|
187
|
+
for (; ; ) {
|
|
188
|
+
const newline = this.buffer.search(/\r\n|\r|\n/);
|
|
189
|
+
if (newline === -1) {
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
const line = this.buffer.slice(0, newline);
|
|
193
|
+
const sep = this.buffer.slice(newline, newline + 2);
|
|
194
|
+
this.buffer = this.buffer.slice(newline + (sep === "\r\n" ? 2 : 1));
|
|
195
|
+
if (line === "") {
|
|
196
|
+
const message = this.flush();
|
|
197
|
+
if (message) {
|
|
198
|
+
messages.push(message);
|
|
199
|
+
}
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
this.parseLine(line);
|
|
203
|
+
}
|
|
204
|
+
return messages;
|
|
205
|
+
}
|
|
206
|
+
parseLine(line) {
|
|
207
|
+
if (line.startsWith(":")) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const colon = line.indexOf(":");
|
|
211
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
212
|
+
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
213
|
+
if (value.startsWith(" ")) {
|
|
214
|
+
value = value.slice(1);
|
|
215
|
+
}
|
|
216
|
+
switch (field) {
|
|
217
|
+
case "event":
|
|
218
|
+
this.eventName = value;
|
|
219
|
+
break;
|
|
220
|
+
case "data":
|
|
221
|
+
this.dataLines.push(value);
|
|
222
|
+
break;
|
|
223
|
+
case "id":
|
|
224
|
+
if (!value.includes("\0")) {
|
|
225
|
+
this.id = value;
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
case "retry": {
|
|
229
|
+
const ms = Number(value);
|
|
230
|
+
if (Number.isInteger(ms) && ms >= 0) {
|
|
231
|
+
this.retryMs = ms;
|
|
232
|
+
}
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
default:
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
flush() {
|
|
240
|
+
if (this.dataLines.length === 0 && this.eventName === "") {
|
|
241
|
+
const retryOnly = this.retryMs;
|
|
242
|
+
this.retryMs = void 0;
|
|
243
|
+
return retryOnly === void 0 ? void 0 : { event: "", data: "", retryMs: retryOnly };
|
|
244
|
+
}
|
|
245
|
+
const message = {
|
|
246
|
+
event: this.eventName || "message",
|
|
247
|
+
data: this.dataLines.join("\n"),
|
|
248
|
+
id: this.id,
|
|
249
|
+
retryMs: this.retryMs
|
|
250
|
+
};
|
|
251
|
+
this.eventName = "";
|
|
252
|
+
this.dataLines = [];
|
|
253
|
+
this.retryMs = void 0;
|
|
254
|
+
return message;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// src/warp/types.ts
|
|
259
|
+
var CONTROL_EVENTS = /* @__PURE__ */ new Set(["connected", "error", "quota_exceeded"]);
|
|
260
|
+
function backoffDelayMs(attempt) {
|
|
261
|
+
return Math.min(1e3 * 2 ** (attempt - 1), 3e4) + Math.random() * 250;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/warp/sse.ts
|
|
265
|
+
var WarpSseStream = class extends Emitter {
|
|
266
|
+
lastEventId;
|
|
267
|
+
options;
|
|
268
|
+
auth;
|
|
269
|
+
url;
|
|
270
|
+
fetchImpl;
|
|
271
|
+
abort;
|
|
272
|
+
reconnectAttempt = 0;
|
|
273
|
+
serverRetryMs;
|
|
274
|
+
closed = false;
|
|
275
|
+
closeEmitted = false;
|
|
276
|
+
constructor(options) {
|
|
277
|
+
super();
|
|
278
|
+
this.options = options;
|
|
279
|
+
this.auth = authFromOptions(options, "WarpSseStream");
|
|
280
|
+
const base = options.url ?? warpStreamUrl(options.network ?? "mainnet", options.subscriptionId);
|
|
281
|
+
if (options.mode !== void 0) {
|
|
282
|
+
const url = new URL(base);
|
|
283
|
+
url.searchParams.set("mode", options.mode);
|
|
284
|
+
this.url = url.toString();
|
|
285
|
+
} else {
|
|
286
|
+
this.url = base;
|
|
287
|
+
}
|
|
288
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
289
|
+
this.lastEventId = options.lastEventId;
|
|
290
|
+
}
|
|
291
|
+
connect() {
|
|
292
|
+
if (this.abort) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
this.closed = false;
|
|
296
|
+
this.closeEmitted = false;
|
|
297
|
+
this.abort = new AbortController();
|
|
298
|
+
void this.run(this.abort.signal);
|
|
299
|
+
}
|
|
300
|
+
close() {
|
|
301
|
+
const wasActive = this.abort !== void 0;
|
|
302
|
+
this.closed = true;
|
|
303
|
+
this.abort?.abort();
|
|
304
|
+
this.abort = void 0;
|
|
305
|
+
if (wasActive) {
|
|
306
|
+
this.emitClose("client closed");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Emit "close" exactly once per connection lifecycle. */
|
|
310
|
+
emitClose(reason) {
|
|
311
|
+
if (this.closeEmitted) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
this.closeEmitted = true;
|
|
315
|
+
this.emit("close", { reason });
|
|
316
|
+
}
|
|
317
|
+
/** Iterate data events; ends when the stream closes (throws unless client-initiated). */
|
|
318
|
+
[Symbol.asyncIterator]() {
|
|
319
|
+
return iterateStream(this);
|
|
320
|
+
}
|
|
321
|
+
async run(signal) {
|
|
322
|
+
for (; ; ) {
|
|
323
|
+
try {
|
|
324
|
+
await this.consume(signal);
|
|
325
|
+
if (this.closed || signal.aborted) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
} catch (error) {
|
|
329
|
+
if (this.closed || signal.aborted) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (error instanceof TerminalStreamError) {
|
|
333
|
+
this.emit("error", error);
|
|
334
|
+
this.emitClose(error.message);
|
|
335
|
+
this.close();
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
this.emit(
|
|
339
|
+
"error",
|
|
340
|
+
error instanceof Error ? error : new Error(String(error))
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
if (!(this.options.reconnect ?? true)) {
|
|
344
|
+
this.emitClose("disconnected");
|
|
345
|
+
this.close();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
this.reconnectAttempt += 1;
|
|
349
|
+
if (this.reconnectAttempt > (this.options.maxReconnectAttempts ?? 10)) {
|
|
350
|
+
this.emitClose("max reconnect attempts exceeded");
|
|
351
|
+
this.close();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const delayMs = this.serverRetryMs ?? backoffDelayMs(this.reconnectAttempt);
|
|
355
|
+
this.emit("reconnecting", { attempt: this.reconnectAttempt, delayMs });
|
|
356
|
+
await sleep(delayMs);
|
|
357
|
+
if (this.closed || signal.aborted) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async consume(signal) {
|
|
363
|
+
const { headers: authHeaders } = await this.auth.credentials();
|
|
364
|
+
const headers = {
|
|
365
|
+
accept: "text/event-stream",
|
|
366
|
+
...authHeaders,
|
|
367
|
+
[SDK_HEADER_NAME]: SDK_HEADER_VALUE
|
|
368
|
+
};
|
|
369
|
+
if (this.lastEventId !== void 0) {
|
|
370
|
+
headers["Last-Event-ID"] = this.lastEventId;
|
|
371
|
+
}
|
|
372
|
+
const response = await this.fetchImpl(this.url, { headers, signal });
|
|
373
|
+
if (!response.ok || !response.body) {
|
|
374
|
+
const retryable = response.status >= 500;
|
|
375
|
+
const message = `SSE connection failed with status ${response.status}`;
|
|
376
|
+
if (retryable) {
|
|
377
|
+
throw new Error(message);
|
|
378
|
+
}
|
|
379
|
+
throw new TerminalStreamError(message);
|
|
380
|
+
}
|
|
381
|
+
const parser = new SseParser();
|
|
382
|
+
const decoder = new TextDecoder();
|
|
383
|
+
const reader = response.body.getReader();
|
|
384
|
+
for (; ; ) {
|
|
385
|
+
const { done, value } = await reader.read();
|
|
386
|
+
if (done) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
for (const message of parser.feed(decoder.decode(value, { stream: true }))) {
|
|
390
|
+
if (message.retryMs !== void 0) {
|
|
391
|
+
this.serverRetryMs = message.retryMs;
|
|
392
|
+
}
|
|
393
|
+
if (message.event === "" && message.data === "") {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
this.dispatch(message.event, message.id, message.data);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
dispatch(event, id, raw) {
|
|
401
|
+
let data = raw;
|
|
402
|
+
try {
|
|
403
|
+
data = JSON.parse(raw);
|
|
404
|
+
} catch {
|
|
405
|
+
}
|
|
406
|
+
if (id !== void 0) {
|
|
407
|
+
this.lastEventId = id;
|
|
408
|
+
}
|
|
409
|
+
switch (event) {
|
|
410
|
+
case "connected":
|
|
411
|
+
this.reconnectAttempt = 0;
|
|
412
|
+
this.emit("connected", data);
|
|
413
|
+
return;
|
|
414
|
+
case "quota_exceeded":
|
|
415
|
+
this.emit("quota_exceeded", data);
|
|
416
|
+
this.emitClose("quota_exceeded");
|
|
417
|
+
this.close();
|
|
418
|
+
return;
|
|
419
|
+
case "error": {
|
|
420
|
+
const message = typeof data === "object" && data !== null && "error" in data ? String(data.error) : raw;
|
|
421
|
+
this.emit("error", new Error(message));
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
default:
|
|
425
|
+
if (!CONTROL_EVENTS.has(event)) {
|
|
426
|
+
this.emit("message", { type: event, id, data });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
var TerminalStreamError = class extends Error {
|
|
432
|
+
};
|
|
433
|
+
function sleep(ms) {
|
|
434
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/warp/ws.ts
|
|
438
|
+
var WarpWebSocketStream = class extends Emitter {
|
|
439
|
+
lastEventId;
|
|
440
|
+
options;
|
|
441
|
+
auth;
|
|
442
|
+
wsCtor;
|
|
443
|
+
ws;
|
|
444
|
+
reconnectAttempt = 0;
|
|
445
|
+
closed = false;
|
|
446
|
+
constructor(options) {
|
|
447
|
+
super();
|
|
448
|
+
this.options = options;
|
|
449
|
+
this.auth = authFromOptions(options, "WarpWebSocketStream");
|
|
450
|
+
const ctor = options.webSocket ?? globalThis.WebSocket;
|
|
451
|
+
if (!ctor) {
|
|
452
|
+
throw new Error(
|
|
453
|
+
"No WebSocket implementation available \u2014 pass one via the webSocket option"
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
this.wsCtor = ctor;
|
|
457
|
+
this.lastEventId = options.lastEventId;
|
|
458
|
+
}
|
|
459
|
+
connect() {
|
|
460
|
+
if (this.ws) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
this.closed = false;
|
|
464
|
+
this.open();
|
|
465
|
+
}
|
|
466
|
+
close() {
|
|
467
|
+
this.closed = true;
|
|
468
|
+
this.ws?.close(1e3, "client closed");
|
|
469
|
+
this.ws = void 0;
|
|
470
|
+
}
|
|
471
|
+
/** Acknowledge an event by ID (only needed with autoAck: false). */
|
|
472
|
+
ack(id) {
|
|
473
|
+
this.ws?.send(JSON.stringify({ type: "ack", id }));
|
|
474
|
+
}
|
|
475
|
+
/** Iterate data events; ends when the stream closes (throws unless client-initiated). */
|
|
476
|
+
[Symbol.asyncIterator]() {
|
|
477
|
+
return iterateStream(this);
|
|
478
|
+
}
|
|
479
|
+
buildUrl(authParams) {
|
|
480
|
+
const base = this.options.url ?? warpWebSocketUrl(
|
|
481
|
+
this.options.network ?? "mainnet",
|
|
482
|
+
this.options.subscriptionId
|
|
483
|
+
);
|
|
484
|
+
const url = new URL(base);
|
|
485
|
+
for (const [key, value] of Object.entries(authParams)) {
|
|
486
|
+
url.searchParams.set(key, value);
|
|
487
|
+
}
|
|
488
|
+
if (this.options.mode !== void 0) {
|
|
489
|
+
url.searchParams.set("mode", this.options.mode);
|
|
490
|
+
}
|
|
491
|
+
if (this.lastEventId !== void 0) {
|
|
492
|
+
url.searchParams.set("lastEventId", this.lastEventId);
|
|
493
|
+
}
|
|
494
|
+
return url.toString();
|
|
495
|
+
}
|
|
496
|
+
open() {
|
|
497
|
+
const credentials = this.auth.staticCredentials();
|
|
498
|
+
if (credentials) {
|
|
499
|
+
this.openWith(credentials.queryParams);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
void this.auth.credentials().then(
|
|
503
|
+
(resolved) => {
|
|
504
|
+
if (!this.closed && !this.ws) {
|
|
505
|
+
this.openWith(resolved.queryParams);
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
(error) => {
|
|
509
|
+
this.failTerminally(
|
|
510
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
511
|
+
"credential resolution failed"
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
failTerminally(error, reason) {
|
|
517
|
+
this.closed = true;
|
|
518
|
+
this.emit("error", error);
|
|
519
|
+
this.emit("close", { reason });
|
|
520
|
+
}
|
|
521
|
+
openWith(authParams) {
|
|
522
|
+
if (!authParams) {
|
|
523
|
+
this.failTerminally(
|
|
524
|
+
new Error(
|
|
525
|
+
"These credentials cannot authenticate a WebSocket (no header support on upgrades) \u2014 use an API key or the SSE stream"
|
|
526
|
+
),
|
|
527
|
+
"unsupported credentials"
|
|
528
|
+
);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const ws = new this.wsCtor(this.buildUrl(authParams));
|
|
532
|
+
this.ws = ws;
|
|
533
|
+
ws.addEventListener("message", (event) => {
|
|
534
|
+
this.handleMessage(event);
|
|
535
|
+
});
|
|
536
|
+
ws.addEventListener("error", () => {
|
|
537
|
+
this.emit("error", new Error("WebSocket transport error"));
|
|
538
|
+
});
|
|
539
|
+
ws.addEventListener("close", (event) => {
|
|
540
|
+
if (this.ws !== ws) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
this.ws = void 0;
|
|
544
|
+
this.handleClose(event.code, event.reason);
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
handleMessage(event) {
|
|
548
|
+
let parsed;
|
|
549
|
+
try {
|
|
550
|
+
parsed = JSON.parse(
|
|
551
|
+
typeof event.data === "string" ? event.data : String(event.data)
|
|
552
|
+
);
|
|
553
|
+
} catch {
|
|
554
|
+
this.emit("error", new Error("Received malformed WebSocket message"));
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const type = typeof parsed.event === "string" ? parsed.event : "message";
|
|
558
|
+
const id = typeof parsed.id === "string" ? parsed.id : void 0;
|
|
559
|
+
switch (type) {
|
|
560
|
+
case "connected":
|
|
561
|
+
this.reconnectAttempt = 0;
|
|
562
|
+
this.emit("connected", parsed.data);
|
|
563
|
+
return;
|
|
564
|
+
case "quota_exceeded":
|
|
565
|
+
this.emit("quota_exceeded", parsed.data);
|
|
566
|
+
return;
|
|
567
|
+
// server closes with 1008; handleClose makes it terminal
|
|
568
|
+
case "error": {
|
|
569
|
+
const message = typeof parsed.data === "object" && parsed.data !== null && "error" in parsed.data ? String(parsed.data.error) : "Server error";
|
|
570
|
+
this.emit("error", new Error(message));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
default: {
|
|
574
|
+
if (id !== void 0) {
|
|
575
|
+
this.lastEventId = id;
|
|
576
|
+
}
|
|
577
|
+
const handlersSucceeded = this.emit("message", {
|
|
578
|
+
type,
|
|
579
|
+
id,
|
|
580
|
+
data: parsed.data
|
|
581
|
+
});
|
|
582
|
+
if ((this.options.autoAck ?? true) && id !== void 0) {
|
|
583
|
+
if (handlersSucceeded) {
|
|
584
|
+
this.ack(id);
|
|
585
|
+
} else {
|
|
586
|
+
this.emit(
|
|
587
|
+
"error",
|
|
588
|
+
new Error(
|
|
589
|
+
`Message handler threw; event ${id} not acked and will be redelivered`
|
|
590
|
+
)
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
handleClose(code, reason) {
|
|
598
|
+
if (this.closed) {
|
|
599
|
+
this.emit("close", { reason: "client closed" });
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (code === 1008) {
|
|
603
|
+
this.emit("close", { reason: reason || "policy violation" });
|
|
604
|
+
this.closed = true;
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (!(this.options.reconnect ?? true)) {
|
|
608
|
+
this.emit("close", { reason: reason || "disconnected" });
|
|
609
|
+
this.closed = true;
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
this.reconnectAttempt += 1;
|
|
613
|
+
if (this.reconnectAttempt > (this.options.maxReconnectAttempts ?? 10)) {
|
|
614
|
+
this.emit("close", { reason: "max reconnect attempts exceeded" });
|
|
615
|
+
this.closed = true;
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const delayMs = backoffDelayMs(this.reconnectAttempt);
|
|
619
|
+
this.emit("reconnecting", { attempt: this.reconnectAttempt, delayMs });
|
|
620
|
+
setTimeout(() => {
|
|
621
|
+
if (!this.closed && !this.ws) {
|
|
622
|
+
this.open();
|
|
623
|
+
}
|
|
624
|
+
}, delayMs);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
628
|
+
0 && (module.exports = {
|
|
629
|
+
WarpSseStream,
|
|
630
|
+
WarpWebSocketStream,
|
|
631
|
+
iterateStream
|
|
632
|
+
});
|
|
633
|
+
//# sourceMappingURL=warp.cjs.map
|