@chainstream-io/sdk 0.1.20 → 0.1.22

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/dist/index.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- export { q as DexAggregatorOptions, r as DexClient, p as DexRequestContext, L as LIB_VERSION, P as PostOptions, o as TokenProvider } from './index-Rg3zipzv.cjs';
1
+ export { q as DexAggregatorOptions, r as DexClient, p as DexRequestContext, L as LIB_VERSION, P as PostOptions, o as TokenProvider } from './index-CuPWnFsI.cjs';
2
2
  import './WatchlistApi-18jD3YH5.cjs';
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { q as DexAggregatorOptions, r as DexClient, p as DexRequestContext, L as LIB_VERSION, P as PostOptions, o as TokenProvider } from './index-8REU_oTW.js';
1
+ export { q as DexAggregatorOptions, r as DexClient, p as DexRequestContext, L as LIB_VERSION, P as PostOptions, o as TokenProvider } from './index-DWL6morC.js';
2
2
  import './WatchlistApi-18jD3YH5.js';
package/dist/index.mjs CHANGED
@@ -4,7 +4,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
4
4
 
5
5
  // src/stream/stream.ts
6
6
  import { Centrifuge } from "@chainstream-io/centrifuge";
7
- import { createRequire } from "module";
8
7
 
9
8
  // src/stream/stream.fields.ts
10
9
  var CEL_FIELD_MAPPINGS = {
@@ -265,62 +264,100 @@ var StreamApi = class {
265
264
  constructor(context) {
266
265
  __publicField(this, "realtimeClient");
267
266
  __publicField(this, "listenersMap");
268
- __publicField(this, "getTokenValue");
269
- const realtimeEndpoint = context.streamUrl;
270
- this.getTokenValue = async () => {
271
- return typeof context.accessToken === "string" ? context.accessToken : await context.accessToken.getToken();
272
- };
273
- let wsImpl = void 0;
274
- if (typeof process !== "undefined" && process.versions?.node) {
275
- try {
276
- const require2 = createRequire(import.meta.url);
277
- wsImpl = require2("ws");
278
- } catch {
279
- }
280
- }
281
- if (!wsImpl && typeof WebSocket !== "undefined") {
282
- wsImpl = WebSocket;
267
+ __publicField(this, "context");
268
+ __publicField(this, "initPromise", null);
269
+ this.context = context;
270
+ this.listenersMap = /* @__PURE__ */ new Map();
271
+ }
272
+ /**
273
+ * Initialize Centrifuge client with current token
274
+ * This is called lazily when connect() is called
275
+ */
276
+ async initClient() {
277
+ if (this.realtimeClient) {
278
+ return;
283
279
  }
280
+ const token = await this.getTokenValue();
281
+ const realtimeEndpoint = this.buildWsUrl(this.context.streamUrl, token);
284
282
  this.realtimeClient = new Centrifuge(realtimeEndpoint, {
285
- ...wsImpl && { websocket: wsImpl },
286
283
  getToken: async (_ctx) => {
287
- const token = await this.getTokenValue();
288
- this.realtimeClient.setHttpHeaders({
289
- Authorization: `Bearer ${token}`,
290
- "User-Agent": `chainstream-io/sdk/javascript`
291
- });
292
- return token;
284
+ return this.getTokenValue();
293
285
  }
294
286
  });
295
287
  this.realtimeClient.on("connected", () => {
296
288
  console.log("[streaming] connected");
297
- }).on("disconnected", (err) => {
298
- console.warn("[streaming] disconnected", err);
289
+ }).on("disconnected", (ctx) => {
290
+ console.warn("[streaming] disconnected", ctx);
299
291
  }).on("error", (err) => {
300
292
  console.error("[streaming] error: ", err);
301
293
  });
302
- this.listenersMap = /* @__PURE__ */ new Map();
303
294
  }
304
- async connect() {
305
- const token = await this.getTokenValue();
306
- this.realtimeClient.setHttpHeaders({
307
- Authorization: `Bearer ${token}`
295
+ /**
296
+ * Wait for initialization to complete
297
+ * If not initialized, auto-connect first
298
+ */
299
+ async ensureInitialized() {
300
+ if (!this.initPromise) {
301
+ this.connect();
302
+ }
303
+ await this.initPromise;
304
+ }
305
+ /**
306
+ * Get token value from string or TokenProvider
307
+ */
308
+ async getTokenValue() {
309
+ return typeof this.context.accessToken === "string" ? this.context.accessToken : await this.context.accessToken.getToken();
310
+ }
311
+ /**
312
+ * Build WebSocket URL with token as query parameter
313
+ */
314
+ buildWsUrl(endpoint, token) {
315
+ const url = new URL(endpoint);
316
+ url.searchParams.set("token", token);
317
+ return url.toString();
318
+ }
319
+ /**
320
+ * Connect to the WebSocket server.
321
+ * This is automatically called when you use subscribe methods if not already connected.
322
+ * You can also call this method manually for explicit control.
323
+ */
324
+ connect() {
325
+ this.initPromise = this.initClient().then(() => {
326
+ this.realtimeClient.connect();
308
327
  });
309
- this.realtimeClient.connect();
328
+ }
329
+ /**
330
+ * Disconnect from the WebSocket server.
331
+ * All subscriptions will be automatically removed.
332
+ */
333
+ disconnect() {
334
+ if (this.realtimeClient) {
335
+ this.realtimeClient.disconnect();
336
+ }
337
+ }
338
+ /**
339
+ * Check if the WebSocket is currently connected.
340
+ */
341
+ isConnected() {
342
+ return this.realtimeClient?.state === "connected";
310
343
  }
311
344
  /**
312
345
  * Start batching commands for efficient bulk operations
313
346
  * All subscription commands after this call will be batched until stopBatching is called
314
347
  */
315
348
  startBatching() {
316
- this.realtimeClient.startBatching();
349
+ if (this.realtimeClient) {
350
+ this.realtimeClient.startBatching();
351
+ }
317
352
  }
318
353
  /**
319
354
  * Stop batching and flush all collected commands to the server
320
355
  * This will send all batched subscription commands in a single network request
321
356
  */
322
357
  stopBatching() {
323
- this.realtimeClient.stopBatching();
358
+ if (this.realtimeClient) {
359
+ this.realtimeClient.stopBatching();
360
+ }
324
361
  }
325
362
  /**
326
363
  * Batch subscribe method that accepts a function containing subscription calls
@@ -350,26 +387,31 @@ var StreamApi = class {
350
387
  });
351
388
  }
352
389
  subscribe(channel, fn, filter, methodName) {
353
- let sub = this.realtimeClient.getSubscription(channel);
354
390
  let listeners = this.listenersMap.get(channel);
355
- if (!sub) {
391
+ if (!listeners) {
356
392
  listeners = /* @__PURE__ */ new Set();
357
393
  this.listenersMap.set(channel, listeners);
358
- console.log("[xrealtime] create new sub: ", channel);
359
- const processedFilter = filter && methodName ? replaceFilterFields(filter, methodName) : filter;
360
- sub = this.realtimeClient.newSubscription(channel, {
361
- delta: "fossil",
362
- ...processedFilter && { filter: processedFilter }
363
- });
364
- sub.on("subscribed", () => {
365
- console.log("[xrealtime] subscribed", channel);
366
- }).on("unsubscribed", () => {
367
- console.log("[xrealtime] unsubscribed", channel);
368
- }).on("publication", (ctx) => {
369
- listeners?.forEach((it) => it(ctx.data));
370
- }).subscribe();
371
- }
372
- listeners?.add(fn);
394
+ }
395
+ listeners.add(fn);
396
+ this.ensureInitialized().then(() => {
397
+ let sub = this.realtimeClient.getSubscription(channel);
398
+ if (!sub) {
399
+ console.log("[xrealtime] create new sub: ", channel);
400
+ const processedFilter = filter && methodName ? replaceFilterFields(filter, methodName) : filter;
401
+ sub = this.realtimeClient.newSubscription(channel, {
402
+ delta: "fossil",
403
+ ...processedFilter && { filter: processedFilter }
404
+ });
405
+ sub.on("subscribed", () => {
406
+ console.log("[xrealtime] subscribed", channel);
407
+ }).on("unsubscribed", () => {
408
+ console.log("[xrealtime] unsubscribed", channel);
409
+ }).on("publication", (ctx) => {
410
+ const currentListeners = this.listenersMap.get(channel);
411
+ currentListeners?.forEach((it) => it(ctx.data));
412
+ }).subscribe();
413
+ }
414
+ });
373
415
  return new StreamUnsubscrible(this, channel, fn);
374
416
  }
375
417
  unsubscribe(channel, fn) {
@@ -381,12 +423,14 @@ var StreamApi = class {
381
423
  console.log("unsubscribe, remain listeners: ", listeners.size);
382
424
  if (listeners.size === 0) {
383
425
  console.log("unsubscribe channel: ", channel);
384
- const sub = this.realtimeClient.getSubscription(channel);
385
- if (sub) {
386
- sub.unsubscribe();
387
- this.realtimeClient.removeSubscription(sub);
388
- }
389
426
  this.listenersMap.delete(channel);
427
+ this.ensureInitialized().then(() => {
428
+ const sub = this.realtimeClient.getSubscription(channel);
429
+ if (sub) {
430
+ sub.unsubscribe();
431
+ this.realtimeClient.removeSubscription(sub);
432
+ }
433
+ });
390
434
  }
391
435
  }
392
436
  formatScientificNotation(value) {
@@ -8163,7 +8207,7 @@ var WatchlistApi = class extends BaseAPI {
8163
8207
 
8164
8208
  // src/index.ts
8165
8209
  import { EventSourcePolyfill } from "event-source-polyfill";
8166
- var LIB_VERSION = "0.1.20";
8210
+ var LIB_VERSION = "0.1.22";
8167
8211
  var UserAgentMiddleware = class {
8168
8212
  async pre(context) {
8169
8213
  if (!context.init.headers) {
@@ -8201,9 +8245,6 @@ var DexClient = class {
8201
8245
  __publicField(this, "endpoint");
8202
8246
  const baseUrl = options.serverUrl ?? "https://api-dex.chainstream.io";
8203
8247
  const streamUrl = options.streamUrl ?? "wss://realtime-dex.chainstream.io/connection/websocket";
8204
- const tokenProvider = typeof accessToken === "string" ? {
8205
- getToken: () => accessToken
8206
- } : accessToken;
8207
8248
  this.requestCtx = { baseUrl, streamUrl, accessToken };
8208
8249
  const config = new Configuration({
8209
8250
  basePath: baseUrl,
@@ -8233,7 +8274,9 @@ var DexClient = class {
8233
8274
  this.jobs = new JobsApi(config);
8234
8275
  this.kyt = new KYTApi(config);
8235
8276
  this.endpoint = new EndpointApi(config);
8236
- this.stream.connect();
8277
+ if (options.autoConnectWebSocket === true) {
8278
+ this.stream.connect();
8279
+ }
8237
8280
  }
8238
8281
  async waitForJob(jobId, timeout = 6e4) {
8239
8282
  const accessToken = typeof this.requestCtx.accessToken === "string" ? this.requestCtx.accessToken : await this.requestCtx.accessToken.getToken();