@pythnetwork/pyth-lazer-sdk 5.0.0 → 5.2.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.
Files changed (33) hide show
  1. package/dist/cjs/{client.js → client.cjs} +93 -98
  2. package/dist/cjs/constants.cjs +36 -0
  3. package/dist/cjs/index.cjs +20 -0
  4. package/dist/cjs/package.json +1 -1
  5. package/dist/cjs/protocol.cjs +33 -0
  6. package/dist/cjs/protocol.d.ts +1 -1
  7. package/dist/cjs/socket/{resilient-websocket.js → resilient-websocket.cjs} +47 -48
  8. package/dist/cjs/socket/{websocket-pool.js → websocket-pool.cjs} +68 -65
  9. package/dist/cjs/util/{buffer-util.js → buffer-util.cjs} +14 -14
  10. package/dist/cjs/util/env-util.cjs +33 -0
  11. package/dist/cjs/util/index.cjs +20 -0
  12. package/dist/cjs/util/url-util.cjs +17 -0
  13. package/dist/esm/{client.js → client.mjs} +76 -88
  14. package/dist/esm/index.mjs +3 -0
  15. package/dist/esm/package.json +1 -1
  16. package/dist/esm/protocol.d.ts +1 -1
  17. package/dist/esm/{protocol.js → protocol.mjs} +4 -4
  18. package/dist/esm/socket/{resilient-websocket.js → resilient-websocket.mjs} +27 -36
  19. package/dist/esm/socket/{websocket-pool.js → websocket-pool.mjs} +47 -53
  20. package/dist/esm/util/{buffer-util.js → buffer-util.mjs} +3 -6
  21. package/dist/esm/util/{env-util.js → env-util.mjs} +4 -8
  22. package/dist/esm/util/index.mjs +3 -0
  23. package/dist/esm/util/{url-util.js → url-util.mjs} +2 -4
  24. package/package.json +108 -15
  25. package/dist/cjs/constants.js +0 -9
  26. package/dist/cjs/index.js +0 -19
  27. package/dist/cjs/protocol.js +0 -15
  28. package/dist/cjs/util/env-util.js +0 -32
  29. package/dist/cjs/util/index.js +0 -19
  30. package/dist/cjs/util/url-util.js +0 -18
  31. package/dist/esm/index.js +0 -3
  32. package/dist/esm/util/index.js +0 -3
  33. /package/dist/esm/{constants.js → constants.mjs} +0 -0
@@ -1,82 +1,91 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.WebSocketPool = void 0;
7
- const ttlcache_1 = __importDefault(require("@isaacs/ttlcache"));
8
- const ts_log_1 = require("ts-log");
9
- const resilient_websocket_js_1 = require("./resilient-websocket.js");
10
- const constants_js_1 = require("../constants.js");
11
- const index_js_1 = require("../util/index.js");
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "WebSocketPool", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return WebSocketPool;
9
+ }
10
+ });
11
+ const _ttlcache = /*#__PURE__*/ _interop_require_default(require("@isaacs/ttlcache"));
12
+ const _tslog = require("ts-log");
13
+ const _resilientwebsocket = require("./resilient-websocket.cjs");
14
+ const _constants = require("../constants.cjs");
15
+ const _index = require("../util/index.cjs");
16
+ function _interop_require_default(obj) {
17
+ return obj && obj.__esModule ? obj : {
18
+ default: obj
19
+ };
20
+ }
12
21
  const DEFAULT_NUM_CONNECTIONS = 4;
13
22
  class WebSocketPool {
14
23
  logger;
15
24
  rwsPool;
16
25
  cache;
17
- subscriptions; // id -> subscription Request
26
+ subscriptions;
18
27
  messageListeners;
19
28
  allConnectionsDownListeners;
20
29
  wasAllDown = true;
21
30
  checkConnectionStatesInterval;
22
- constructor(logger) {
31
+ constructor(logger){
23
32
  this.logger = logger;
24
33
  this.rwsPool = [];
25
- this.cache = new ttlcache_1.default({ ttl: 1000 * 10 }); // TTL of 10 seconds
34
+ this.cache = new _ttlcache.default({
35
+ ttl: 1000 * 10
36
+ }); // TTL of 10 seconds
26
37
  this.subscriptions = new Map();
27
38
  this.messageListeners = [];
28
39
  this.allConnectionsDownListeners = [];
29
40
  // Start monitoring connection states
30
- this.checkConnectionStatesInterval = setInterval(() => {
41
+ this.checkConnectionStatesInterval = setInterval(()=>{
31
42
  this.checkConnectionStates();
32
43
  }, 100);
33
44
  }
34
45
  /**
35
- * Creates a new WebSocketPool instance that uses multiple redundant WebSocket connections for reliability.
36
- * Usage semantics are similar to using a regular WebSocket client.
37
- * @param urls - List of WebSocket URLs to connect to
38
- * @param token - Authentication token to use for the connections
39
- * @param numConnections - Number of parallel WebSocket connections to maintain (default: 3)
40
- * @param logger - Optional logger to get socket level logs. Compatible with most loggers such as the built-in console and `bunyan`.
41
- */
42
- static async create(config, token, logger) {
46
+ * Creates a new WebSocketPool instance that uses multiple redundant WebSocket connections for reliability.
47
+ * Usage semantics are similar to using a regular WebSocket client.
48
+ * @param urls - List of WebSocket URLs to connect to
49
+ * @param token - Authentication token to use for the connections
50
+ * @param numConnections - Number of parallel WebSocket connections to maintain (default: 3)
51
+ * @param logger - Optional logger to get socket level logs. Compatible with most loggers such as the built-in console and `bunyan`.
52
+ */ static async create(config, token, logger) {
43
53
  const urls = config.urls ?? [
44
- constants_js_1.DEFAULT_STREAM_SERVICE_0_URL,
45
- constants_js_1.DEFAULT_STREAM_SERVICE_1_URL,
54
+ _constants.DEFAULT_STREAM_SERVICE_0_URL,
55
+ _constants.DEFAULT_STREAM_SERVICE_1_URL
46
56
  ];
47
- const log = logger ?? ts_log_1.dummyLogger;
57
+ const log = logger ?? _tslog.dummyLogger;
48
58
  const pool = new WebSocketPool(log);
49
59
  const numConnections = config.numConnections ?? DEFAULT_NUM_CONNECTIONS;
50
- for (let i = 0; i < numConnections; i++) {
60
+ for(let i = 0; i < numConnections; i++){
51
61
  const baseUrl = urls[i % urls.length];
52
- const isBrowser = (0, index_js_1.envIsBrowserOrWorker)();
53
- const url = isBrowser
54
- ? (0, index_js_1.addAuthTokenToWebSocketUrl)(baseUrl, token)
55
- : baseUrl;
62
+ const isBrowser = (0, _index.envIsBrowserOrWorker)();
63
+ const url = isBrowser ? (0, _index.addAuthTokenToWebSocketUrl)(baseUrl, token) : baseUrl;
56
64
  if (!url) {
57
65
  throw new Error(`URLs must not be null or empty`);
58
66
  }
59
67
  const wsOptions = {
60
68
  ...config.rwsConfig?.wsOptions,
61
- headers: isBrowser ? undefined : { Authorization: `Bearer ${token}` },
69
+ headers: isBrowser ? undefined : {
70
+ Authorization: `Bearer ${token}`
71
+ }
62
72
  };
63
- const rws = new resilient_websocket_js_1.ResilientWebSocket({
73
+ const rws = new _resilientwebsocket.ResilientWebSocket({
64
74
  ...config.rwsConfig,
65
75
  endpoint: url,
66
76
  wsOptions,
67
- logger: log,
77
+ logger: log
68
78
  });
69
79
  // If a websocket client unexpectedly disconnects, ResilientWebSocket will reestablish
70
80
  // the connection and call the onReconnect callback.
71
- rws.onReconnect = () => {
81
+ rws.onReconnect = ()=>{
72
82
  if (rws.wsUserClosed) {
73
83
  return;
74
84
  }
75
- for (const [, request] of pool.subscriptions) {
85
+ for (const [, request] of pool.subscriptions){
76
86
  try {
77
87
  rws.send(JSON.stringify(request));
78
- }
79
- catch (error) {
88
+ } catch (error) {
80
89
  pool.logger.error("Failed to resend subscription on reconnect:", error);
81
90
  }
82
91
  }
@@ -85,8 +94,8 @@ class WebSocketPool {
85
94
  rws.onError = config.onError;
86
95
  }
87
96
  // Handle all client messages ourselves. Dedupe before sending to registered message handlers.
88
- rws.onMessage = (data) => {
89
- pool.dedupeHandler(data).catch((error) => {
97
+ rws.onMessage = (data)=>{
98
+ pool.dedupeHandler(data).catch((error)=>{
90
99
  const errMsg = `An error occurred in the WebSocket pool's dedupeHandler: ${error instanceof Error ? error.message : String(error)}`;
91
100
  throw new Error(errMsg);
92
101
  });
@@ -95,35 +104,31 @@ class WebSocketPool {
95
104
  rws.startWebSocket();
96
105
  }
97
106
  pool.logger.info(`Started WebSocketPool with ${numConnections.toString()} connections. Waiting for at least one to connect...`);
98
- while (!pool.isAnyConnectionEstablished()) {
99
- await new Promise((resolve) => setTimeout(resolve, 100));
107
+ while(!pool.isAnyConnectionEstablished()){
108
+ await new Promise((resolve)=>setTimeout(resolve, 100));
100
109
  }
101
110
  pool.logger.info(`At least one WebSocket connection is established. WebSocketPool is ready.`);
102
111
  return pool;
103
112
  }
104
113
  /**
105
- * Checks for error responses in JSON messages and throws appropriate errors
106
- */
107
- handleErrorMessages(data) {
114
+ * Checks for error responses in JSON messages and throws appropriate errors
115
+ */ handleErrorMessages(data) {
108
116
  const message = JSON.parse(data);
109
117
  if (message.type === "subscriptionError") {
110
118
  throw new Error(`Error occurred for subscription ID ${String(message.subscriptionId)}: ${message.error}`);
111
- }
112
- else if (message.type === "error") {
119
+ } else if (message.type === "error") {
113
120
  throw new Error(`Error: ${message.error}`);
114
121
  }
115
122
  }
116
123
  async constructCacheKeyFromWebsocketData(data) {
117
- if (typeof data === "string")
118
- return data;
119
- const buff = await (0, index_js_1.bufferFromWebsocketData)(data);
124
+ if (typeof data === "string") return data;
125
+ const buff = await (0, _index.bufferFromWebsocketData)(data);
120
126
  return buff.toString("hex");
121
127
  }
122
128
  /**
123
- * Handles incoming websocket messages by deduplicating identical messages received across
124
- * multiple connections before forwarding to registered handlers
125
- */
126
- dedupeHandler = async (data) => {
129
+ * Handles incoming websocket messages by deduplicating identical messages received across
130
+ * multiple connections before forwarding to registered handlers
131
+ */ dedupeHandler = async (data)=>{
127
132
  const cacheKey = await this.constructCacheKeyFromWebsocketData(data);
128
133
  if (this.cache.has(cacheKey)) {
129
134
  this.logger.debug("Dropping duplicate message");
@@ -133,10 +138,10 @@ class WebSocketPool {
133
138
  if (typeof data === "string") {
134
139
  this.handleErrorMessages(data);
135
140
  }
136
- await Promise.all(this.messageListeners.map((handler) => handler(data)));
141
+ await Promise.all(this.messageListeners.map((handler)=>handler(data)));
137
142
  };
138
143
  sendRequest(request) {
139
- for (const rws of this.rwsPool) {
144
+ for (const rws of this.rwsPool){
140
145
  rws.send(JSON.stringify(request));
141
146
  }
142
147
  }
@@ -151,7 +156,7 @@ class WebSocketPool {
151
156
  this.subscriptions.delete(subscriptionId);
152
157
  const request = {
153
158
  type: "unsubscribe",
154
- subscriptionId,
159
+ subscriptionId
155
160
  };
156
161
  this.sendRequest(request);
157
162
  }
@@ -159,17 +164,16 @@ class WebSocketPool {
159
164
  this.messageListeners.push(handler);
160
165
  }
161
166
  /**
162
- * Calls the handler if all websocket connections are currently down or in reconnecting state.
163
- * The connections may still try to reconnect in the background.
164
- */
165
- addAllConnectionsDownListener(handler) {
167
+ * Calls the handler if all websocket connections are currently down or in reconnecting state.
168
+ * The connections may still try to reconnect in the background.
169
+ */ addAllConnectionsDownListener(handler) {
166
170
  this.allConnectionsDownListeners.push(handler);
167
171
  }
168
172
  areAllConnectionsDown() {
169
- return this.rwsPool.every((ws) => !ws.isConnected() || ws.isReconnecting());
173
+ return this.rwsPool.every((ws)=>!ws.isConnected() || ws.isReconnecting());
170
174
  }
171
175
  isAnyConnectionEstablished() {
172
- return this.rwsPool.some((ws) => ws.isConnected());
176
+ return this.rwsPool.some((ws)=>ws.isConnected());
173
177
  }
174
178
  checkConnectionStates() {
175
179
  const allDown = this.areAllConnectionsDown();
@@ -178,7 +182,7 @@ class WebSocketPool {
178
182
  this.wasAllDown = true;
179
183
  this.logger.error("All WebSocket connections are down or reconnecting");
180
184
  // Notify all listeners
181
- for (const listener of this.allConnectionsDownListeners) {
185
+ for (const listener of this.allConnectionsDownListeners){
182
186
  listener();
183
187
  }
184
188
  }
@@ -188,7 +192,7 @@ class WebSocketPool {
188
192
  }
189
193
  }
190
194
  shutdown() {
191
- for (const rws of this.rwsPool) {
195
+ for (const rws of this.rwsPool){
192
196
  rws.closeWebSocket();
193
197
  }
194
198
  this.rwsPool = [];
@@ -198,4 +202,3 @@ class WebSocketPool {
198
202
  clearInterval(this.checkConnectionStatesInterval);
199
203
  }
200
204
  }
201
- exports.WebSocketPool = WebSocketPool;
@@ -1,29 +1,29 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bufferFromWebsocketData = bufferFromWebsocketData;
4
1
  // the linting rules don't allow importing anything that might clash with
5
2
  // a global, top-level import. we disable this rule because we need this
6
3
  // imported from our installed dependency
7
4
  // eslint-disable-next-line unicorn/prefer-node-protocol
8
- const buffer_1 = require("buffer");
9
- const BufferClassToUse = "Buffer" in globalThis ? globalThis.Buffer : buffer_1.Buffer;
10
- /**
11
- * given a relatively unknown websocket frame data object,
12
- * returns a valid Buffer instance that is safe to use
13
- * isomorphically in any JS runtime environment
14
- */
5
+ "use strict";
6
+ Object.defineProperty(exports, "__esModule", {
7
+ value: true
8
+ });
9
+ Object.defineProperty(exports, "bufferFromWebsocketData", {
10
+ enumerable: true,
11
+ get: function() {
12
+ return bufferFromWebsocketData;
13
+ }
14
+ });
15
+ const _buffer = require("buffer");
16
+ const BufferClassToUse = "Buffer" in globalThis ? globalThis.Buffer : _buffer.Buffer;
15
17
  async function bufferFromWebsocketData(data) {
16
18
  if (typeof data === "string") {
17
19
  return BufferClassToUse.from(new TextEncoder().encode(data).buffer);
18
20
  }
19
- if (data instanceof BufferClassToUse)
20
- return data;
21
+ if (data instanceof BufferClassToUse) return data;
21
22
  if (data instanceof Blob) {
22
23
  // let the uncaught promise exception bubble up if there's an issue
23
24
  return BufferClassToUse.from(await data.arrayBuffer());
24
25
  }
25
- if (data instanceof ArrayBuffer)
26
- return BufferClassToUse.from(data);
26
+ if (data instanceof ArrayBuffer) return BufferClassToUse.from(data);
27
27
  if (Array.isArray(data)) {
28
28
  // an array of buffers is highly unlikely, but it is a possibility
29
29
  // indicated by the WebSocket Data interface
@@ -0,0 +1,33 @@
1
+ // we create this local-only type, which has assertions made to indicate
2
+ // that we do not know and cannot guarantee which JS environment we are in
3
+ "use strict";
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ function _export(target, all) {
8
+ for(var name in all)Object.defineProperty(target, name, {
9
+ enumerable: true,
10
+ get: Object.getOwnPropertyDescriptor(all, name).get
11
+ });
12
+ }
13
+ _export(exports, {
14
+ get envIsBrowser () {
15
+ return envIsBrowser;
16
+ },
17
+ get envIsBrowserOrWorker () {
18
+ return envIsBrowserOrWorker;
19
+ },
20
+ get envIsServiceOrWebWorker () {
21
+ return envIsServiceOrWebWorker;
22
+ }
23
+ });
24
+ const g = globalThis;
25
+ function envIsServiceOrWebWorker() {
26
+ return typeof WorkerGlobalScope !== "undefined" && g.self instanceof WorkerGlobalScope;
27
+ }
28
+ function envIsBrowser() {
29
+ return g.window !== undefined;
30
+ }
31
+ function envIsBrowserOrWorker() {
32
+ return envIsServiceOrWebWorker() || envIsBrowser();
33
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./buffer-util.cjs"), exports);
6
+ _export_star(require("./env-util.cjs"), exports);
7
+ _export_star(require("./url-util.cjs"), exports);
8
+ function _export_star(from, to) {
9
+ Object.keys(from).forEach(function(k) {
10
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
11
+ Object.defineProperty(to, k, {
12
+ enumerable: true,
13
+ get: function() {
14
+ return from[k];
15
+ }
16
+ });
17
+ }
18
+ });
19
+ return from;
20
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "addAuthTokenToWebSocketUrl", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return addAuthTokenToWebSocketUrl;
9
+ }
10
+ });
11
+ const ACCESS_TOKEN_QUERY_PARAM_KEY = "ACCESS_TOKEN";
12
+ function addAuthTokenToWebSocketUrl(baseUrl, authToken) {
13
+ if (!baseUrl || !authToken) return baseUrl;
14
+ const parsedUrl = new URL(baseUrl);
15
+ parsedUrl.searchParams.set(ACCESS_TOKEN_QUERY_PARAM_KEY, authToken);
16
+ return parsedUrl.toString();
17
+ }
@@ -1,9 +1,8 @@
1
- import WebSocket from "isomorphic-ws";
2
1
  import { dummyLogger } from "ts-log";
3
- import { DEFAULT_METADATA_SERVICE_URL, DEFAULT_PRICE_SERVICE_URL, } from "./constants.js";
4
- import { BINARY_UPDATE_FORMAT_MAGIC_LE, FORMAT_MAGICS_LE } from "./protocol.js";
5
- import { WebSocketPool } from "./socket/websocket-pool.js";
6
- import { bufferFromWebsocketData } from "./util/buffer-util.js";
2
+ import { DEFAULT_METADATA_SERVICE_URL, DEFAULT_PRICE_SERVICE_URL } from "./constants.mjs";
3
+ import { BINARY_UPDATE_FORMAT_MAGIC_LE, FORMAT_MAGICS_LE } from "./protocol.mjs";
4
+ import { WebSocketPool } from "./socket/websocket-pool.mjs";
5
+ import { bufferFromWebsocketData } from "./util/buffer-util.mjs";
7
6
  const UINT16_NUM_BYTES = 2;
8
7
  const UINT32_NUM_BYTES = 4;
9
8
  const UINT64_NUM_BYTES = 8;
@@ -13,7 +12,7 @@ export class PythLazerClient {
13
12
  priceServiceUrl;
14
13
  logger;
15
14
  wsp;
16
- constructor(token, metadataServiceUrl, priceServiceUrl, logger, wsp) {
15
+ constructor(token, metadataServiceUrl, priceServiceUrl, logger, wsp){
17
16
  this.token = token;
18
17
  this.metadataServiceUrl = metadataServiceUrl;
19
18
  this.priceServiceUrl = priceServiceUrl;
@@ -21,21 +20,19 @@ export class PythLazerClient {
21
20
  this.wsp = wsp;
22
21
  }
23
22
  /**
24
- * Gets the WebSocket pool. If the WebSocket pool is not configured, an error is thrown.
25
- * @throws Error if WebSocket pool is not configured
26
- * @returns The WebSocket pool
27
- */
28
- getWebSocketPool() {
23
+ * Gets the WebSocket pool. If the WebSocket pool is not configured, an error is thrown.
24
+ * @throws Error if WebSocket pool is not configured
25
+ * @returns The WebSocket pool
26
+ */ getWebSocketPool() {
29
27
  if (!this.wsp) {
30
28
  throw new Error("WebSocket pool is not available. Make sure to provide webSocketPoolConfig when creating the client.");
31
29
  }
32
30
  return this.wsp;
33
31
  }
34
32
  /**
35
- * Creates a new PythLazerClient instance.
36
- * @param config - Configuration including token, metadata service URL, and price service URL, and WebSocket pool configuration
37
- */
38
- static async create(config) {
33
+ * Creates a new PythLazerClient instance.
34
+ * @param config - Configuration including token, metadata service URL, and price service URL, and WebSocket pool configuration
35
+ */ static async create(config) {
39
36
  const token = config.token;
40
37
  // Collect and remove trailing slash from URLs
41
38
  const metadataServiceUrl = (config.metadataServiceUrl ?? DEFAULT_METADATA_SERVICE_URL).replace(/\/+$/, "");
@@ -49,26 +46,23 @@ export class PythLazerClient {
49
46
  return new PythLazerClient(token, metadataServiceUrl, priceServiceUrl, logger, wsp);
50
47
  }
51
48
  /**
52
- * Adds a message listener that receives either JSON or binary responses from the WebSocket connections.
53
- * The listener will be called for each message received, with deduplication across redundant connections.
54
- * @param handler - Callback function that receives the parsed message. The message can be either a JSON response
55
- * or a binary response containing EVM, Solana, or parsed payload data.
56
- */
57
- addMessageListener(handler) {
49
+ * Adds a message listener that receives either JSON or binary responses from the WebSocket connections.
50
+ * The listener will be called for each message received, with deduplication across redundant connections.
51
+ * @param handler - Callback function that receives the parsed message. The message can be either a JSON response
52
+ * or a binary response containing EVM, Solana, or parsed payload data.
53
+ */ addMessageListener(handler) {
58
54
  const wsp = this.getWebSocketPool();
59
- wsp.addMessageListener(async (data) => {
55
+ wsp.addMessageListener(async (data)=>{
60
56
  if (typeof data == "string") {
61
57
  handler({
62
58
  type: "json",
63
- value: JSON.parse(data),
59
+ value: JSON.parse(data)
64
60
  });
65
61
  return;
66
62
  }
67
63
  const buffData = await bufferFromWebsocketData(data);
68
64
  let pos = 0;
69
- const magic = buffData
70
- .subarray(pos, pos + UINT32_NUM_BYTES)
71
- .readUint32LE();
65
+ const magic = buffData.subarray(pos, pos + UINT32_NUM_BYTES).readUint32LE();
72
66
  pos += UINT32_NUM_BYTES;
73
67
  if (magic != BINARY_UPDATE_FORMAT_MAGIC_LE) {
74
68
  throw new Error("binary update format magic mismatch");
@@ -76,36 +70,32 @@ export class PythLazerClient {
76
70
  // TODO: some uint64 values may not be representable as Number.
77
71
  const subscriptionId = Number(buffData.subarray(pos, pos + UINT64_NUM_BYTES).readBigInt64BE());
78
72
  pos += UINT64_NUM_BYTES;
79
- const value = { subscriptionId };
80
- while (pos < buffData.length) {
81
- const len = buffData
82
- .subarray(pos, pos + UINT16_NUM_BYTES)
83
- .readUint16BE();
73
+ const value = {
74
+ subscriptionId
75
+ };
76
+ while(pos < buffData.length){
77
+ const len = buffData.subarray(pos, pos + UINT16_NUM_BYTES).readUint16BE();
84
78
  pos += UINT16_NUM_BYTES;
85
- const magic = buffData
86
- .subarray(pos, pos + UINT32_NUM_BYTES)
87
- .readUint32LE();
79
+ const magic = buffData.subarray(pos, pos + UINT32_NUM_BYTES).readUint32LE();
88
80
  if (magic == FORMAT_MAGICS_LE.EVM) {
89
81
  value.evm = buffData.subarray(pos, pos + len);
90
- }
91
- else if (magic == FORMAT_MAGICS_LE.SOLANA) {
82
+ } else if (magic == FORMAT_MAGICS_LE.SOLANA) {
92
83
  value.solana = buffData.subarray(pos, pos + len);
93
- }
94
- else if (magic == FORMAT_MAGICS_LE.LE_ECDSA) {
84
+ } else if (magic == FORMAT_MAGICS_LE.LE_ECDSA) {
95
85
  value.leEcdsa = buffData.subarray(pos, pos + len);
96
- }
97
- else if (magic == FORMAT_MAGICS_LE.LE_UNSIGNED) {
86
+ } else if (magic == FORMAT_MAGICS_LE.LE_UNSIGNED) {
98
87
  value.leUnsigned = buffData.subarray(pos, pos + len);
99
- }
100
- else if (magic == FORMAT_MAGICS_LE.JSON) {
88
+ } else if (magic == FORMAT_MAGICS_LE.JSON) {
101
89
  value.parsed = JSON.parse(buffData.subarray(pos + UINT32_NUM_BYTES, pos + len).toString());
102
- }
103
- else {
90
+ } else {
104
91
  throw new Error(`unknown magic: ${magic.toString()}`);
105
92
  }
106
93
  pos += len;
107
94
  }
108
- handler({ type: "binary", value });
95
+ handler({
96
+ type: "binary",
97
+ value
98
+ });
109
99
  });
110
100
  }
111
101
  subscribe(request) {
@@ -124,11 +114,10 @@ export class PythLazerClient {
124
114
  wsp.sendRequest(request);
125
115
  }
126
116
  /**
127
- * Registers a handler function that will be called whenever all WebSocket connections are down or attempting to reconnect.
128
- * The connections may still try to reconnect in the background. To shut down the pool, call `shutdown()`.
129
- * @param handler - Function to be called when all connections are down
130
- */
131
- addAllConnectionsDownListener(handler) {
117
+ * Registers a handler function that will be called whenever all WebSocket connections are down or attempting to reconnect.
118
+ * The connections may still try to reconnect in the background. To shut down the pool, call `shutdown()`.
119
+ * @param handler - Function to be called when all connections are down
120
+ */ addAllConnectionsDownListener(handler) {
132
121
  const wsp = this.getWebSocketPool();
133
122
  wsp.addAllConnectionsDownListener(handler);
134
123
  }
@@ -137,27 +126,25 @@ export class PythLazerClient {
137
126
  wsp.shutdown();
138
127
  }
139
128
  /**
140
- * Private helper method to make authenticated HTTP requests with Bearer token
141
- * @param url - The URL to fetch
142
- * @param options - Additional fetch options
143
- * @returns Promise resolving to the fetch Response
144
- */
145
- async authenticatedFetch(url, options = {}) {
129
+ * Private helper method to make authenticated HTTP requests with Bearer token
130
+ * @param url - The URL to fetch
131
+ * @param options - Additional fetch options
132
+ * @returns Promise resolving to the fetch Response
133
+ */ async authenticatedFetch(url, options = {}) {
146
134
  const headers = {
147
135
  Authorization: `Bearer ${this.token}`,
148
- ...options.headers,
136
+ ...options.headers
149
137
  };
150
138
  return fetch(url, {
151
139
  ...options,
152
- headers,
140
+ headers
153
141
  });
154
142
  }
155
143
  /**
156
- * Queries the symbols endpoint to get available price feed symbols.
157
- * @param params - Optional query parameters to filter symbols
158
- * @returns Promise resolving to array of symbol information
159
- */
160
- async getSymbols(params) {
144
+ * Queries the symbols endpoint to get available price feed symbols.
145
+ * @param params - Optional query parameters to filter symbols
146
+ * @returns Promise resolving to array of symbol information
147
+ */ async getSymbols(params) {
161
148
  const url = new URL(`${this.metadataServiceUrl}/v1/symbols`);
162
149
  if (params?.query) {
163
150
  url.searchParams.set("query", params.query);
@@ -170,61 +157,62 @@ export class PythLazerClient {
170
157
  if (!response.ok) {
171
158
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
172
159
  }
173
- return (await response.json());
174
- }
175
- catch (error) {
160
+ return await response.json();
161
+ } catch (error) {
176
162
  throw new Error(`Failed to fetch symbols: ${error instanceof Error ? error.message : String(error)}`);
177
163
  }
178
164
  }
179
165
  /**
180
- * Queries the latest price endpoint to get current price data.
181
- * @param params - Parameters for the latest price request
182
- * @returns Promise resolving to JsonUpdate with current price data
183
- */
184
- async getLatestPrice(params) {
166
+ * Queries the latest price endpoint to get current price data.
167
+ * @param params - Parameters for the latest price request
168
+ * @returns Promise resolving to JsonUpdate with current price data
169
+ */ async getLatestPrice(params) {
185
170
  const url = `${this.priceServiceUrl}/v1/latest_price`;
186
171
  try {
187
172
  const body = JSON.stringify(params);
188
- this.logger.debug("getLatestPrice", { url, body });
173
+ this.logger.debug("getLatestPrice", {
174
+ url,
175
+ body
176
+ });
189
177
  const response = await this.authenticatedFetch(url, {
190
178
  method: "POST",
191
179
  headers: {
192
- "Content-Type": "application/json",
180
+ "Content-Type": "application/json"
193
181
  },
194
- body: body,
182
+ body: body
195
183
  });
196
184
  if (!response.ok) {
197
185
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
198
186
  }
199
- return (await response.json());
200
- }
201
- catch (error) {
187
+ return await response.json();
188
+ } catch (error) {
202
189
  throw new Error(`Failed to fetch latest price: ${error instanceof Error ? error.message : String(error)}`);
203
190
  }
204
191
  }
205
192
  /**
206
- * Queries the price endpoint to get historical price data at a specific timestamp.
207
- * @param params - Parameters for the price request including timestamp
208
- * @returns Promise resolving to JsonUpdate with price data at the specified time
209
- */
210
- async getPrice(params) {
193
+ * Queries the price endpoint to get historical price data at a specific timestamp.
194
+ * @param params - Parameters for the price request including timestamp
195
+ * @returns Promise resolving to JsonUpdate with price data at the specified time
196
+ */ async getPrice(params) {
211
197
  const url = `${this.priceServiceUrl}/v1/price`;
212
198
  try {
213
199
  const body = JSON.stringify(params);
214
- this.logger.debug("getPrice", { url, body });
200
+ this.logger.debug("getPrice", {
201
+ url,
202
+ body
203
+ });
215
204
  const response = await this.authenticatedFetch(url, {
216
205
  method: "POST",
217
206
  headers: {
218
- "Content-Type": "application/json",
207
+ "Content-Type": "application/json"
219
208
  },
220
- body: body,
209
+ body: body
221
210
  });
222
211
  if (!response.ok) {
223
212
  throw new Error(`HTTP error! status: ${String(response.status)} - ${await response.text()}`);
224
213
  }
225
- return (await response.json());
226
- }
227
- catch (error) {
214
+ return await response.json();
215
+ } catch (error) {
228
216
  throw new Error(`Failed to fetch price: ${error instanceof Error ? error.message : String(error)}`);
229
217
  }
230
218
  }
@@ -0,0 +1,3 @@
1
+ export * from "./client.mjs";
2
+ export * from "./protocol.mjs";
3
+ export * from "./constants.mjs";
@@ -1 +1 @@
1
- {"type":"module"}
1
+ { "type": "module" }