@n1xyz/nord-ts 0.0.18-8121ed05.0 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.claude/settings.local.json +11 -0
  2. package/.local/qa.ts +77 -0
  3. package/.local/test-atomic.ts +112 -0
  4. package/check.sh +4 -0
  5. package/default.nix +47 -0
  6. package/package.json +20 -27
  7. package/src/index.ts +0 -16
  8. package/src/nord/api/actions.ts +131 -9
  9. package/src/nord/api/core.ts +0 -71
  10. package/src/nord/client/Nord.ts +142 -76
  11. package/src/nord/client/NordUser.ts +171 -50
  12. package/src/nord/index.ts +0 -2
  13. package/src/nord/models/Subscriber.ts +2 -2
  14. package/src/types.ts +55 -216
  15. package/src/utils.ts +6 -42
  16. package/src/websocket/NordWebSocketClient.ts +23 -15
  17. package/src/websocket/index.ts +1 -1
  18. package/tests/utils.spec.ts +1 -34
  19. package/dist/bridge/client.d.ts +0 -151
  20. package/dist/bridge/client.js +0 -434
  21. package/dist/bridge/const.d.ts +0 -23
  22. package/dist/bridge/const.js +0 -47
  23. package/dist/bridge/index.d.ts +0 -4
  24. package/dist/bridge/index.js +0 -23
  25. package/dist/bridge/types.d.ts +0 -120
  26. package/dist/bridge/types.js +0 -18
  27. package/dist/bridge/utils.d.ts +0 -64
  28. package/dist/bridge/utils.js +0 -131
  29. package/dist/const.d.ts +0 -8
  30. package/dist/const.js +0 -30
  31. package/dist/gen/common.d.ts +0 -68
  32. package/dist/gen/common.js +0 -215
  33. package/dist/gen/nord.d.ts +0 -853
  34. package/dist/gen/nord.js +0 -6368
  35. package/dist/idl/bridge.d.ts +0 -569
  36. package/dist/idl/bridge.js +0 -8
  37. package/dist/idl/bridge.json +0 -1506
  38. package/dist/idl/index.d.ts +0 -607
  39. package/dist/idl/index.js +0 -8
  40. package/dist/index.d.ts +0 -6
  41. package/dist/index.js +0 -30
  42. package/dist/nord/api/actions.d.ts +0 -106
  43. package/dist/nord/api/actions.js +0 -256
  44. package/dist/nord/api/core.d.ts +0 -49
  45. package/dist/nord/api/core.js +0 -164
  46. package/dist/nord/api/market.d.ts +0 -36
  47. package/dist/nord/api/market.js +0 -96
  48. package/dist/nord/api/metrics.d.ts +0 -67
  49. package/dist/nord/api/metrics.js +0 -229
  50. package/dist/nord/api/queries.d.ts +0 -46
  51. package/dist/nord/api/queries.js +0 -109
  52. package/dist/nord/client/Nord.d.ts +0 -284
  53. package/dist/nord/client/Nord.js +0 -491
  54. package/dist/nord/client/NordUser.d.ts +0 -287
  55. package/dist/nord/client/NordUser.js +0 -595
  56. package/dist/nord/index.d.ts +0 -9
  57. package/dist/nord/index.js +0 -33
  58. package/dist/nord/models/Subscriber.d.ts +0 -37
  59. package/dist/nord/models/Subscriber.js +0 -25
  60. package/dist/nord/utils/NordError.d.ts +0 -35
  61. package/dist/nord/utils/NordError.js +0 -49
  62. package/dist/types.d.ts +0 -407
  63. package/dist/types.js +0 -103
  64. package/dist/utils.d.ts +0 -116
  65. package/dist/utils.js +0 -271
  66. package/dist/websocket/NordWebSocketClient.d.ts +0 -68
  67. package/dist/websocket/NordWebSocketClient.js +0 -338
  68. package/dist/websocket/events.d.ts +0 -19
  69. package/dist/websocket/events.js +0 -2
  70. package/dist/websocket/index.d.ts +0 -2
  71. package/dist/websocket/index.js +0 -5
  72. package/jest.config.ts +0 -9
  73. package/nodemon.json +0 -4
  74. package/protoc-generate.sh +0 -23
  75. package/src/idl/bridge.json +0 -1506
  76. package/src/nord/api/market.ts +0 -122
  77. package/src/nord/api/queries.ts +0 -135
@@ -1,338 +0,0 @@
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.NordWebSocketClient = void 0;
7
- const ws_1 = __importDefault(require("ws"));
8
- const events_1 = require("events");
9
- const types_1 = require("../types");
10
- const VALID_STREAM_TYPES = ["trades", "delta", "account"];
11
- // Constants for WebSocket readyState
12
- const WS_OPEN = 1;
13
- /**
14
- * WebSocket client for Nord exchange
15
- *
16
- * This client connects to one of the specific Nord WebSocket endpoints:
17
- *
18
- * Each endpoint handles a specific type of data and subscriptions must match
19
- * the endpoint type (e.g., only 'trades@BTCUSDC' subscriptions are valid on
20
- * the /ws/trades endpoint).
21
- */
22
- class NordWebSocketClient extends events_1.EventEmitter {
23
- /**
24
- * Create a new NordWebSocketClient
25
- * @param url WebSocket server URL
26
- */
27
- constructor(url) {
28
- super();
29
- this.ws = null;
30
- this.subscriptions = new Set();
31
- this.reconnectAttempts = 0;
32
- this.maxReconnectAttempts = 5;
33
- this.reconnectDelay = 1000;
34
- this.pingInterval = null;
35
- this.pingTimeout = null;
36
- this.url = url;
37
- // Check if we're in a browser environment
38
- // The most reliable way is to check for Node.js process
39
- this.isBrowser =
40
- typeof process === "undefined" ||
41
- !process.versions ||
42
- !process.versions.node;
43
- }
44
- /**
45
- * Validate stream format
46
- * @param stream Stream identifier to validate
47
- * @throws Error if stream format is invalid
48
- */
49
- validateStream(stream) {
50
- const [type, params] = stream.split("@");
51
- if (!type || !params) {
52
- throw new Error(`Invalid stream format: ${stream}. Expected format: <type>@<params>`);
53
- }
54
- // Extract the endpoint from the URL
55
- const urlPath = new URL(this.url).pathname;
56
- const endpoint = urlPath.split("/").pop();
57
- // Ensure the stream type matches the endpoint we're connected to
58
- if (endpoint && type !== endpoint) {
59
- throw new Error(`Stream type '${type}' doesn't match the connected endpoint '${endpoint}'`);
60
- }
61
- if (!VALID_STREAM_TYPES.includes(type)) {
62
- throw new Error(`Invalid stream type: ${type}. Valid types are: ${VALID_STREAM_TYPES.join(", ")}`);
63
- }
64
- if (type === "account" && !/^\d+$/.test(params)) {
65
- throw new Error(`Invalid account ID in stream: ${params}. Expected numeric ID`);
66
- }
67
- }
68
- /**
69
- * Setup WebSocket ping/pong heartbeat
70
- */
71
- setupHeartbeat() {
72
- if (this.pingInterval) {
73
- clearInterval(this.pingInterval);
74
- }
75
- if (this.pingTimeout) {
76
- clearTimeout(this.pingTimeout);
77
- }
78
- // In browser, we rely on the browser's WebSocket implementation to handle ping/pong
79
- if (this.isBrowser) {
80
- return;
81
- }
82
- this.pingInterval = setInterval(() => {
83
- if (this.ws && !this.isBrowser) {
84
- // Only use ping() method in Node.js environment
85
- this.ws.ping();
86
- // Set timeout for pong response
87
- this.pingTimeout = setTimeout(() => {
88
- this.emit("error", new Error("WebSocket ping timeout"));
89
- this.close();
90
- this.reconnect();
91
- }, 5000); // 5 second timeout
92
- }
93
- }, 30000); // Send ping every 30 seconds
94
- }
95
- /**
96
- * Get the appropriate WebSocket class based on environment
97
- */
98
- getWebSocketClass() {
99
- if (this.isBrowser) {
100
- // In browser environments
101
- if (typeof globalThis !== "undefined" && globalThis.WebSocket) {
102
- return globalThis.WebSocket;
103
- }
104
- throw new Error("WebSocket is not available in this environment");
105
- }
106
- else {
107
- // In Node.js
108
- return ws_1.default;
109
- }
110
- }
111
- /**
112
- * Connect to the Nord WebSocket server
113
- */
114
- connect() {
115
- if (this.ws) {
116
- return;
117
- }
118
- try {
119
- const WebSocketClass = this.getWebSocketClass();
120
- if (this.isBrowser) {
121
- // Browser WebSocket setup
122
- this.ws = new WebSocketClass(this.url);
123
- this.ws.onopen = () => {
124
- this.emit("connected");
125
- this.reconnectAttempts = 0;
126
- this.reconnectDelay = 1000;
127
- // Resubscribe to previous subscriptions
128
- if (this.subscriptions.size > 0) {
129
- this.subscribe([...this.subscriptions]);
130
- }
131
- };
132
- this.ws.onmessage = (event) => {
133
- try {
134
- const message = JSON.parse(event.data);
135
- this.handleMessage(message);
136
- }
137
- catch (error) {
138
- this.emit("error", new Error(`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`));
139
- }
140
- };
141
- this.ws.onclose = (event) => {
142
- const reason = event && event.reason ? ` Reason: ${event.reason}` : "";
143
- const code = event && event.code ? ` Code: ${event.code}` : "";
144
- this.emit("disconnected");
145
- console.log(`WebSocket closed.${code}${reason}`);
146
- this.reconnect();
147
- };
148
- this.ws.onerror = (event) => {
149
- const errorMsg = `WebSocket error: ${event && event.type ? event.type : "unknown"}`;
150
- console.error(errorMsg, event);
151
- this.emit("error", new Error(errorMsg));
152
- };
153
- }
154
- else {
155
- // Node.js WebSocket setup
156
- const nodeWs = new WebSocketClass(this.url);
157
- this.ws = nodeWs;
158
- nodeWs.on("open", () => {
159
- this.emit("connected");
160
- this.reconnectAttempts = 0;
161
- this.reconnectDelay = 1000;
162
- this.setupHeartbeat();
163
- // Resubscribe to previous subscriptions
164
- if (this.subscriptions.size > 0) {
165
- this.subscribe([...this.subscriptions]);
166
- }
167
- });
168
- nodeWs.on("message", (data) => {
169
- try {
170
- const message = JSON.parse(data.toString());
171
- this.handleMessage(message);
172
- }
173
- catch (error) {
174
- this.emit("error", new Error(`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`));
175
- }
176
- });
177
- nodeWs.on("close", (code, reason) => {
178
- this.emit("disconnected");
179
- console.log(`WebSocket closed. Code: ${code} Reason: ${reason}`);
180
- if (this.pingInterval) {
181
- clearInterval(this.pingInterval);
182
- }
183
- if (this.pingTimeout) {
184
- clearTimeout(this.pingTimeout);
185
- }
186
- this.reconnect();
187
- });
188
- nodeWs.on("error", (error) => {
189
- console.error("WebSocket error:", error);
190
- this.emit("error", error);
191
- });
192
- nodeWs.on("pong", () => {
193
- if (this.pingTimeout) {
194
- clearTimeout(this.pingTimeout);
195
- }
196
- });
197
- }
198
- }
199
- catch (error) {
200
- const errorMsg = `Failed to initialize WebSocket: ${error instanceof Error ? error.message : String(error)}`;
201
- console.error(errorMsg);
202
- this.emit("error", new Error(errorMsg));
203
- }
204
- }
205
- /**
206
- * Subscribe to one or more streams
207
- * @param streams Array of streams to subscribe to (e.g. ["trades@BTCUSDC", "deltas@BTCUSDC"])
208
- */
209
- subscribe(streams) {
210
- // Validate all streams first
211
- try {
212
- streams.forEach((stream) => this.validateStream(stream));
213
- }
214
- catch (error) {
215
- this.emit("error", error instanceof Error ? error : new Error(String(error)));
216
- return;
217
- }
218
- if (!this.ws ||
219
- (this.isBrowser
220
- ? this.ws.readyState !== WS_OPEN
221
- : this.ws.readyState !== ws_1.default.OPEN)) {
222
- streams.forEach((stream) => this.subscriptions.add(stream));
223
- return;
224
- }
225
- const message = {
226
- e: types_1.WebSocketMessageType.Subscribe,
227
- streams,
228
- };
229
- try {
230
- const messageStr = JSON.stringify(message);
231
- if (this.isBrowser) {
232
- this.ws.send(messageStr);
233
- }
234
- else {
235
- this.ws.send(messageStr);
236
- }
237
- streams.forEach((stream) => this.subscriptions.add(stream));
238
- }
239
- catch (error) {
240
- this.emit("error", error instanceof Error ? error : new Error(String(error)));
241
- }
242
- }
243
- /**
244
- * Unsubscribe from one or more streams
245
- * @param streams Array of streams to unsubscribe from
246
- */
247
- unsubscribe(streams) {
248
- // Validate all streams first
249
- try {
250
- streams.forEach((stream) => this.validateStream(stream));
251
- }
252
- catch (error) {
253
- this.emit("error", error instanceof Error ? error : new Error(String(error)));
254
- return;
255
- }
256
- if (!this.ws ||
257
- (this.isBrowser
258
- ? this.ws.readyState !== WS_OPEN
259
- : this.ws.readyState !== ws_1.default.OPEN)) {
260
- streams.forEach((stream) => this.subscriptions.delete(stream));
261
- return;
262
- }
263
- const message = {
264
- e: types_1.WebSocketMessageType.Unsubscribe,
265
- streams,
266
- };
267
- try {
268
- const messageStr = JSON.stringify(message);
269
- if (this.isBrowser) {
270
- this.ws.send(messageStr);
271
- }
272
- else {
273
- this.ws.send(messageStr);
274
- }
275
- streams.forEach((stream) => this.subscriptions.delete(stream));
276
- }
277
- catch (error) {
278
- this.emit("error", error instanceof Error ? error : new Error(String(error)));
279
- }
280
- }
281
- /**
282
- * Close the WebSocket connection
283
- */
284
- close() {
285
- if (this.ws) {
286
- if (this.isBrowser) {
287
- this.ws.close();
288
- }
289
- else {
290
- this.ws.close();
291
- }
292
- this.ws = null;
293
- }
294
- if (this.pingInterval) {
295
- clearInterval(this.pingInterval);
296
- this.pingInterval = null;
297
- }
298
- if (this.pingTimeout) {
299
- clearTimeout(this.pingTimeout);
300
- this.pingTimeout = null;
301
- }
302
- this.subscriptions.clear();
303
- }
304
- /**
305
- * Handle incoming WebSocket messages
306
- * @param message WebSocket message
307
- */
308
- handleMessage(message) {
309
- switch (message.e) {
310
- case types_1.WebSocketMessageType.TradeUpdate:
311
- this.emit("trades", message);
312
- break;
313
- case types_1.WebSocketMessageType.DeltaUpdate:
314
- this.emit("delta", message);
315
- break;
316
- case types_1.WebSocketMessageType.AccountUpdate:
317
- this.emit("account", message);
318
- break;
319
- default:
320
- this.emit("error", new Error(`Unknown message type: ${message.e}`));
321
- }
322
- }
323
- /**
324
- * Attempt to reconnect to the WebSocket server
325
- */
326
- reconnect() {
327
- if (this.reconnectAttempts >= this.maxReconnectAttempts) {
328
- this.emit("error", new Error("Max reconnection attempts reached"));
329
- return;
330
- }
331
- setTimeout(() => {
332
- this.reconnectAttempts++;
333
- this.reconnectDelay *= 2; // Exponential backoff
334
- this.connect();
335
- }, this.reconnectDelay);
336
- }
337
- }
338
- exports.NordWebSocketClient = NordWebSocketClient;
@@ -1,19 +0,0 @@
1
- import { WebSocketTradeUpdate, WebSocketDeltaUpdate, WebSocketAccountUpdate } from "../types";
2
- /**
3
- * Event type definitions for the NordWebSocketClient
4
- */
5
- export interface NordWebSocketEvents {
6
- connected: () => void;
7
- disconnected: () => void;
8
- error: (error: Error) => void;
9
- trade: (update: WebSocketTradeUpdate) => void;
10
- delta: (update: WebSocketDeltaUpdate) => void;
11
- account: (update: WebSocketAccountUpdate) => void;
12
- }
13
- /**
14
- * Type declaration for NordWebSocketClient event methods
15
- */
16
- export declare interface NordWebSocketClientEvents {
17
- on<E extends keyof NordWebSocketEvents>(event: E, listener: NordWebSocketEvents[E]): this;
18
- emit<E extends keyof NordWebSocketEvents>(event: E, ...args: Parameters<NordWebSocketEvents[E]>): boolean;
19
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- export { NordWebSocketClient } from "./NordWebSocketClient";
2
- export { NordWebSocketEvents, NordWebSocketClientEvents } from "./events";
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NordWebSocketClient = void 0;
4
- var NordWebSocketClient_1 = require("./NordWebSocketClient");
5
- Object.defineProperty(exports, "NordWebSocketClient", { enumerable: true, get: function () { return NordWebSocketClient_1.NordWebSocketClient; } });
package/jest.config.ts DELETED
@@ -1,9 +0,0 @@
1
- import type {Config} from '@jest/types';
2
- // Sync object
3
- const config: Config.InitialOptions = {
4
- verbose: true,
5
- transform: {
6
- "^.+\\.tsx?$": "ts-jest",
7
- },
8
- };
9
- export default config;
package/nodemon.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "watch": ["src", "tests"],
3
- "ext": "js, ts"
4
- }
@@ -1,23 +0,0 @@
1
- #!/bin/sh
2
-
3
- SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
- PROTO_PATH="${SCRIPT_DIR}/../engine/nord.proto"
5
- PROTO_INCLUE_PATH="${SCRIPT_DIR}/.."
6
- PLUGIN_PATH="${SCRIPT_DIR}/node_modules/.bin/protoc-gen-ts_proto"
7
- OUT_DIR="${SCRIPT_DIR}/src/gen"
8
-
9
- # Clean all existing generated files
10
- rm -rf "${OUT_DIR}"
11
- mkdir "${OUT_DIR}"
12
-
13
- # Generate all messages
14
- protoc \
15
- --plugin="${PLUGIN_PATH}" \
16
- --ts_proto_opt=forceLong=bigint \
17
- --ts_proto_opt=esModuleInterop=true \
18
- --ts_proto_opt=oneof=unions-value \
19
- --ts_proto_opt=unrecognizedEnum=false \
20
- --ts_proto_out="${OUT_DIR}" \
21
- --proto_path="$(dirname "${PROTO_PATH}")" \
22
- --proto_path="${PROTO_INCLUE_PATH}" \
23
- "${PROTO_PATH}"