@n1xyz/nord-ts 0.0.19 ā 0.0.21
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/const.d.ts +8 -0
- package/dist/const.js +30 -0
- package/dist/gen/nord.d.ts +882 -0
- package/dist/gen/nord.js +6520 -0
- package/dist/gen/openapi.d.ts +2244 -0
- package/dist/gen/openapi.js +6 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/nord/api/actions.d.ts +135 -0
- package/dist/nord/api/actions.js +313 -0
- package/dist/nord/api/core.d.ts +16 -0
- package/dist/nord/api/core.js +81 -0
- package/dist/nord/api/metrics.d.ts +67 -0
- package/dist/nord/api/metrics.js +229 -0
- package/dist/nord/client/Nord.d.ts +282 -0
- package/dist/nord/client/Nord.js +528 -0
- package/dist/nord/client/NordUser.d.ts +340 -0
- package/dist/nord/client/NordUser.js +652 -0
- package/dist/nord/index.d.ts +7 -0
- package/dist/nord/index.js +31 -0
- package/dist/nord/models/Subscriber.d.ts +37 -0
- package/dist/nord/models/Subscriber.js +25 -0
- package/dist/nord/utils/NordError.d.ts +35 -0
- package/dist/nord/utils/NordError.js +49 -0
- package/dist/types.d.ts +251 -0
- package/dist/types.js +101 -0
- package/dist/utils.d.ts +98 -0
- package/dist/utils.js +237 -0
- package/dist/websocket/NordWebSocketClient.d.ts +57 -0
- package/dist/websocket/NordWebSocketClient.js +251 -0
- package/dist/websocket/events.d.ts +19 -0
- package/dist/websocket/events.js +2 -0
- package/dist/websocket/index.d.ts +2 -0
- package/dist/websocket/index.js +5 -0
- package/package.json +8 -2
- package/src/gen/.gitkeep +0 -0
- package/src/gen/nord.ts +7593 -0
- package/src/gen/openapi.ts +2245 -0
- package/src/nord/api/core.ts +1 -16
- package/src/nord/client/Nord.ts +7 -11
- package/src/types.ts +0 -11
- package/src/websocket/NordWebSocketClient.ts +0 -113
- package/.claude/settings.local.json +0 -11
- package/.local/qa.ts +0 -77
- package/.local/test-atomic.ts +0 -112
- package/.prettierignore +0 -2
- package/check.sh +0 -4
- package/default.nix +0 -47
- package/eslint.config.mjs +0 -66
- package/tests/utils.spec.ts +0 -121
- package/tsconfig.eslint.json +0 -12
- package/tsconfig.json +0 -24
package/src/nord/api/core.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { checkedFetch } from "../../utils";
|
|
1
|
+
import { SubscriptionPattern } from "../../types";
|
|
3
2
|
import { NordWebSocketClient } from "../../websocket/index";
|
|
4
3
|
import { NordError } from "../utils/NordError";
|
|
5
4
|
|
|
@@ -19,12 +18,10 @@ import { NordError } from "../utils/NordError";
|
|
|
19
18
|
export function initWebSocketClient(
|
|
20
19
|
webServerUrl: string,
|
|
21
20
|
subscriptions?: SubscriptionPattern[] | "trades" | "delta" | "account",
|
|
22
|
-
initialSubscriptions?: SubscriptionPattern[],
|
|
23
21
|
): NordWebSocketClient {
|
|
24
22
|
try {
|
|
25
23
|
// Determine URL and subscriptions based on parameters
|
|
26
24
|
let wsUrl = webServerUrl.replace(/^http/, "ws") + `/ws`;
|
|
27
|
-
let wsSubscriptions: SubscriptionPattern[] = [];
|
|
28
25
|
|
|
29
26
|
// Validate subscriptions parameter
|
|
30
27
|
if (typeof subscriptions === "string") {
|
|
@@ -35,12 +32,6 @@ export function initWebSocketClient(
|
|
|
35
32
|
subscriptions === "account"
|
|
36
33
|
) {
|
|
37
34
|
wsUrl += `/${subscriptions}`;
|
|
38
|
-
// If initialSubscriptions provided, use them
|
|
39
|
-
if (initialSubscriptions && initialSubscriptions.length > 0) {
|
|
40
|
-
// Validate initialSubscriptions
|
|
41
|
-
initialSubscriptions.forEach(validateSubscription);
|
|
42
|
-
wsSubscriptions = initialSubscriptions;
|
|
43
|
-
}
|
|
44
35
|
} else {
|
|
45
36
|
throw new NordError(
|
|
46
37
|
`Invalid endpoint: ${subscriptions}. Must be "trades", "deltas", or "account".`,
|
|
@@ -68,12 +59,6 @@ export function initWebSocketClient(
|
|
|
68
59
|
// Add connected handler for debugging
|
|
69
60
|
ws.on("connected", () => {
|
|
70
61
|
console.log("Nord WebSocket connected successfully");
|
|
71
|
-
|
|
72
|
-
// Subscribe to additional subscriptions if provided
|
|
73
|
-
// For new format, these are already part of the URL
|
|
74
|
-
if (wsSubscriptions.length > 0) {
|
|
75
|
-
ws.subscribe(wsSubscriptions);
|
|
76
|
-
}
|
|
77
62
|
});
|
|
78
63
|
|
|
79
64
|
// Connect the WebSocket
|
package/src/nord/client/Nord.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
import { ProtonClient } from "@n1xyz/proton";
|
|
2
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
1
3
|
import { EventEmitter } from "events";
|
|
2
|
-
import { PublicKey, Connection } from "@solana/web3.js";
|
|
3
4
|
import createClient, { Client, FetchOptions } from "openapi-fetch";
|
|
5
|
+
import * as proto from "../../gen/nord";
|
|
6
|
+
import type { paths } from "../../gen/openapi.ts";
|
|
4
7
|
import {
|
|
5
|
-
Info,
|
|
6
8
|
Account,
|
|
7
9
|
ActionResponse,
|
|
8
10
|
AggregateMetrics,
|
|
11
|
+
Info,
|
|
9
12
|
Market,
|
|
13
|
+
MarketStats,
|
|
10
14
|
NordConfig,
|
|
11
15
|
OrderbookQuery,
|
|
12
16
|
OrderbookResponse,
|
|
@@ -15,18 +19,13 @@ import {
|
|
|
15
19
|
Token,
|
|
16
20
|
TradesResponse,
|
|
17
21
|
User,
|
|
18
|
-
MarketStats,
|
|
19
22
|
} from "../../types";
|
|
20
|
-
import
|
|
21
|
-
import * as proto from "../../gen/nord";
|
|
22
|
-
// import { base64 } from "@scure/base";
|
|
23
|
+
import * as utils from "../../utils";
|
|
23
24
|
import { NordWebSocketClient } from "../../websocket/index";
|
|
24
25
|
import * as core from "../api/core";
|
|
25
26
|
import * as metrics from "../api/metrics";
|
|
26
|
-
import * as utils from "../../utils";
|
|
27
27
|
import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
|
|
28
28
|
import { NordError } from "../utils/NordError";
|
|
29
|
-
import type { paths } from "../../gen/openapi.ts";
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* User subscription interface
|
|
@@ -427,7 +426,6 @@ export class Nord {
|
|
|
427
426
|
wsClient.on("delta", handleDelta);
|
|
428
427
|
|
|
429
428
|
subscription.close = () => {
|
|
430
|
-
wsClient.unsubscribe([`deltas@${symbol}`]);
|
|
431
429
|
wsClient.removeListener("delta", handleDelta);
|
|
432
430
|
subscription.removeAllListeners();
|
|
433
431
|
};
|
|
@@ -471,7 +469,6 @@ export class Nord {
|
|
|
471
469
|
wsClient.on("trades", handleTrade);
|
|
472
470
|
|
|
473
471
|
subscription.close = () => {
|
|
474
|
-
wsClient.unsubscribe([`trades@${symbol}`]);
|
|
475
472
|
wsClient.removeListener("trades", handleTrade);
|
|
476
473
|
subscription.removeAllListeners();
|
|
477
474
|
};
|
|
@@ -507,7 +504,6 @@ export class Nord {
|
|
|
507
504
|
wsClient.on("account", handleAccountUpdate);
|
|
508
505
|
|
|
509
506
|
subscription.close = () => {
|
|
510
|
-
wsClient.unsubscribe([`account@${accountId}`]);
|
|
511
507
|
wsClient.removeListener("account", handleAccountUpdate);
|
|
512
508
|
subscription.removeAllListeners();
|
|
513
509
|
};
|
package/src/types.ts
CHANGED
|
@@ -251,21 +251,11 @@ export interface ActionNonceResponse {
|
|
|
251
251
|
* WebSocket message types
|
|
252
252
|
*/
|
|
253
253
|
export enum WebSocketMessageType {
|
|
254
|
-
Subscribe = "subscribe",
|
|
255
|
-
Unsubscribe = "unsubscribe",
|
|
256
254
|
TradeUpdate = "trades",
|
|
257
255
|
DeltaUpdate = "delta",
|
|
258
256
|
AccountUpdate = "account",
|
|
259
257
|
}
|
|
260
258
|
|
|
261
|
-
/**
|
|
262
|
-
* WebSocket subscription request
|
|
263
|
-
*/
|
|
264
|
-
export interface WebSocketSubscription {
|
|
265
|
-
e: WebSocketMessageType;
|
|
266
|
-
streams: string[]; // Array of streams to subscribe/unsubscribe (e.g. ["trades@BTCUSDC", "deltas@BTCUSDC"])
|
|
267
|
-
}
|
|
268
|
-
|
|
269
259
|
/**
|
|
270
260
|
* WebSocket trade update message
|
|
271
261
|
*/
|
|
@@ -300,7 +290,6 @@ export interface WebSocketAccountUpdate {
|
|
|
300
290
|
}
|
|
301
291
|
|
|
302
292
|
export type WebSocketMessage =
|
|
303
|
-
| WebSocketSubscription
|
|
304
293
|
| WebSocketTradeUpdate
|
|
305
294
|
| WebSocketDeltaUpdate
|
|
306
295
|
| WebSocketAccountUpdate;
|
|
@@ -4,8 +4,6 @@ import {
|
|
|
4
4
|
WebSocketAccountUpdate,
|
|
5
5
|
WebSocketDeltaUpdate,
|
|
6
6
|
WebSocketMessage,
|
|
7
|
-
WebSocketMessageType,
|
|
8
|
-
WebSocketSubscription,
|
|
9
7
|
WebSocketTradeUpdate,
|
|
10
8
|
} from "../types";
|
|
11
9
|
import { NordWebSocketClientEvents } from "./events";
|
|
@@ -47,7 +45,6 @@ export class NordWebSocketClient
|
|
|
47
45
|
{
|
|
48
46
|
private ws: WebSocketInstance | null = null;
|
|
49
47
|
private url: string;
|
|
50
|
-
private subscriptions: Set<string> = new Set();
|
|
51
48
|
private reconnectAttempts: number = 0;
|
|
52
49
|
private maxReconnectAttempts: number = 5;
|
|
53
50
|
private reconnectDelay: number = 1000;
|
|
@@ -174,11 +171,6 @@ export class NordWebSocketClient
|
|
|
174
171
|
this.emit("connected");
|
|
175
172
|
this.reconnectAttempts = 0;
|
|
176
173
|
this.reconnectDelay = 1000;
|
|
177
|
-
|
|
178
|
-
// Resubscribe to previous subscriptions
|
|
179
|
-
if (this.subscriptions.size > 0) {
|
|
180
|
-
this.subscribe([...this.subscriptions]);
|
|
181
|
-
}
|
|
182
174
|
};
|
|
183
175
|
|
|
184
176
|
(this.ws as BrowserWebSocket).onmessage = (event: { data: any }) => {
|
|
@@ -202,13 +194,11 @@ export class NordWebSocketClient
|
|
|
202
194
|
event && event.reason ? ` Reason: ${event.reason}` : "";
|
|
203
195
|
const code = event && event.code ? ` Code: ${event.code}` : "";
|
|
204
196
|
this.emit("disconnected");
|
|
205
|
-
console.log(`WebSocket closed.${code}${reason}`);
|
|
206
197
|
this.reconnect();
|
|
207
198
|
};
|
|
208
199
|
|
|
209
200
|
(this.ws as BrowserWebSocket).onerror = (event: any) => {
|
|
210
201
|
const errorMsg = `WebSocket error: ${event && event.type ? event.type : "unknown"}`;
|
|
211
|
-
console.error(errorMsg, event);
|
|
212
202
|
this.emit("error", new Error(errorMsg));
|
|
213
203
|
};
|
|
214
204
|
} else {
|
|
@@ -221,11 +211,6 @@ export class NordWebSocketClient
|
|
|
221
211
|
this.reconnectAttempts = 0;
|
|
222
212
|
this.reconnectDelay = 1000;
|
|
223
213
|
this.setupHeartbeat();
|
|
224
|
-
|
|
225
|
-
// Resubscribe to previous subscriptions
|
|
226
|
-
if (this.subscriptions.size > 0) {
|
|
227
|
-
this.subscribe([...this.subscriptions]);
|
|
228
|
-
}
|
|
229
214
|
});
|
|
230
215
|
|
|
231
216
|
nodeWs.on("message", (data: WebSocket.Data) => {
|
|
@@ -244,7 +229,6 @@ export class NordWebSocketClient
|
|
|
244
229
|
|
|
245
230
|
nodeWs.on("close", (code: number, reason: string) => {
|
|
246
231
|
this.emit("disconnected");
|
|
247
|
-
console.log(`WebSocket closed. Code: ${code} Reason: ${reason}`);
|
|
248
232
|
if (this.pingInterval) {
|
|
249
233
|
clearInterval(this.pingInterval);
|
|
250
234
|
}
|
|
@@ -255,7 +239,6 @@ export class NordWebSocketClient
|
|
|
255
239
|
});
|
|
256
240
|
|
|
257
241
|
nodeWs.on("error", (error: Error) => {
|
|
258
|
-
console.error("WebSocket error:", error);
|
|
259
242
|
this.emit("error", error);
|
|
260
243
|
});
|
|
261
244
|
|
|
@@ -267,105 +250,10 @@ export class NordWebSocketClient
|
|
|
267
250
|
}
|
|
268
251
|
} catch (error) {
|
|
269
252
|
const errorMsg = `Failed to initialize WebSocket: ${error instanceof Error ? error.message : String(error)}`;
|
|
270
|
-
console.error(errorMsg);
|
|
271
253
|
this.emit("error", new Error(errorMsg));
|
|
272
254
|
}
|
|
273
255
|
}
|
|
274
256
|
|
|
275
|
-
/**
|
|
276
|
-
* Subscribe to one or more streams
|
|
277
|
-
* @param streams Array of streams to subscribe to (e.g. ["trades@BTCUSDC", "deltas@BTCUSDC"])
|
|
278
|
-
*/
|
|
279
|
-
public subscribe(streams: string[]): void {
|
|
280
|
-
// Validate all streams first
|
|
281
|
-
try {
|
|
282
|
-
streams.forEach((stream) => this.validateStream(stream));
|
|
283
|
-
} catch (error) {
|
|
284
|
-
this.emit(
|
|
285
|
-
"error",
|
|
286
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
287
|
-
);
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (
|
|
292
|
-
!this.ws ||
|
|
293
|
-
(this.isBrowser
|
|
294
|
-
? (this.ws as BrowserWebSocket).readyState !== WS_OPEN
|
|
295
|
-
: (this.ws as WebSocket).readyState !== WebSocket.OPEN)
|
|
296
|
-
) {
|
|
297
|
-
streams.forEach((stream) => this.subscriptions.add(stream));
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const message: WebSocketSubscription = {
|
|
302
|
-
e: WebSocketMessageType.Subscribe,
|
|
303
|
-
streams,
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
const messageStr = JSON.stringify(message);
|
|
308
|
-
if (this.isBrowser) {
|
|
309
|
-
(this.ws as BrowserWebSocket).send(messageStr);
|
|
310
|
-
} else {
|
|
311
|
-
(this.ws as WebSocket).send(messageStr);
|
|
312
|
-
}
|
|
313
|
-
streams.forEach((stream) => this.subscriptions.add(stream));
|
|
314
|
-
} catch (error) {
|
|
315
|
-
this.emit(
|
|
316
|
-
"error",
|
|
317
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Unsubscribe from one or more streams
|
|
324
|
-
* @param streams Array of streams to unsubscribe from
|
|
325
|
-
*/
|
|
326
|
-
public unsubscribe(streams: string[]): void {
|
|
327
|
-
// Validate all streams first
|
|
328
|
-
try {
|
|
329
|
-
streams.forEach((stream) => this.validateStream(stream));
|
|
330
|
-
} catch (error) {
|
|
331
|
-
this.emit(
|
|
332
|
-
"error",
|
|
333
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
334
|
-
);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (
|
|
339
|
-
!this.ws ||
|
|
340
|
-
(this.isBrowser
|
|
341
|
-
? (this.ws as BrowserWebSocket).readyState !== WS_OPEN
|
|
342
|
-
: (this.ws as WebSocket).readyState !== WebSocket.OPEN)
|
|
343
|
-
) {
|
|
344
|
-
streams.forEach((stream) => this.subscriptions.delete(stream));
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const message: WebSocketSubscription = {
|
|
349
|
-
e: WebSocketMessageType.Unsubscribe,
|
|
350
|
-
streams,
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
try {
|
|
354
|
-
const messageStr = JSON.stringify(message);
|
|
355
|
-
if (this.isBrowser) {
|
|
356
|
-
(this.ws as BrowserWebSocket).send(messageStr);
|
|
357
|
-
} else {
|
|
358
|
-
(this.ws as WebSocket).send(messageStr);
|
|
359
|
-
}
|
|
360
|
-
streams.forEach((stream) => this.subscriptions.delete(stream));
|
|
361
|
-
} catch (error) {
|
|
362
|
-
this.emit(
|
|
363
|
-
"error",
|
|
364
|
-
error instanceof Error ? error : new Error(String(error)),
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
257
|
/**
|
|
370
258
|
* Close the WebSocket connection
|
|
371
259
|
*/
|
|
@@ -386,7 +274,6 @@ export class NordWebSocketClient
|
|
|
386
274
|
clearTimeout(this.pingTimeout);
|
|
387
275
|
this.pingTimeout = null;
|
|
388
276
|
}
|
|
389
|
-
this.subscriptions.clear();
|
|
390
277
|
}
|
|
391
278
|
|
|
392
279
|
/**
|
package/.local/qa.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// quick script i use to qa sdk against deployed instance. this
|
|
2
|
-
// will no longer be needed once we have proper integration tests.
|
|
3
|
-
|
|
4
|
-
import { Nord, NordUser } from "../src";
|
|
5
|
-
|
|
6
|
-
const nord = await Nord.initNord({
|
|
7
|
-
bridgeVk: "rbrpQMMPaVLSG3hTPZj2GLKxGLbPM2q7gDxc7BTync6",
|
|
8
|
-
initWebSockets: false,
|
|
9
|
-
solanaUrl: "https://api.devnet.solana.com",
|
|
10
|
-
webServerUrl: "https://zo-devnet-rc.n1.xyz",
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const poky = await nord.getUser({
|
|
14
|
-
pubkey: "GSPX6qX4bs8oTU3n5A1Xx8q9MPiGFyxWhMtuVvpZNK52",
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
console.log("user", poky);
|
|
18
|
-
|
|
19
|
-
if (!poky) {
|
|
20
|
-
throw new Error("No user found");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
console.log("account", await nord.getAccount(poky.accountIds[0]));
|
|
24
|
-
console.log("timestamp", await nord.getTimestamp());
|
|
25
|
-
console.log("actionNonce", await nord.getActionNonce());
|
|
26
|
-
console.log("lastActionId", await nord.getLastActionId());
|
|
27
|
-
console.log("info", await nord.getInfo());
|
|
28
|
-
|
|
29
|
-
console.log(
|
|
30
|
-
"marketStats",
|
|
31
|
-
await nord.getMarketStats({
|
|
32
|
-
marketId: 1,
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
console.log(
|
|
37
|
-
"orderbook",
|
|
38
|
-
await nord.getOrderbook({
|
|
39
|
-
market_id: 1,
|
|
40
|
-
}),
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const since = new Date();
|
|
44
|
-
since.setMinutes(0);
|
|
45
|
-
|
|
46
|
-
console.log(
|
|
47
|
-
"trades",
|
|
48
|
-
await nord.getTrades({
|
|
49
|
-
takerId: poky.accountIds[0],
|
|
50
|
-
sinceRcf3339: since.toISOString(),
|
|
51
|
-
untilRfc3339: new Date().toISOString(),
|
|
52
|
-
pageId: "0",
|
|
53
|
-
}),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
console.log(
|
|
57
|
-
"recentActions",
|
|
58
|
-
await nord.queryRecentActions({
|
|
59
|
-
from: 6,
|
|
60
|
-
to: 6,
|
|
61
|
-
}),
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
console.log("action", await nord.queryAction({ action_id: 0 }));
|
|
65
|
-
console.log("action", await nord.queryAction({ action_id: 1 }));
|
|
66
|
-
console.log("action", await nord.queryAction({ action_id: 2 }));
|
|
67
|
-
console.log("action", await nord.queryAction({ action_id: 5 }));
|
|
68
|
-
console.log("action", await nord.queryAction({ action_id: 100 }));
|
|
69
|
-
|
|
70
|
-
const user = NordUser.fromPrivateKey(
|
|
71
|
-
nord,
|
|
72
|
-
new Uint8Array(JSON.parse(process.env.PRIVATE_KEY!)),
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
console.log("deposit", await user.deposit({ amount: 2.0, tokenId: 0 }));
|
|
76
|
-
await user.refreshSession();
|
|
77
|
-
console.log("withdraw", await user.withdraw({ amount: 2.0, tokenId: 0 }));
|
package/.local/test-atomic.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { NordWebSocketClient } from "../src/websocket/NordWebSocketClient";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* All event types that we track in the counters object. Keeping this
|
|
5
|
-
* union type explicit lets TypeScript validate that we use the same
|
|
6
|
-
* keys everywhere and prevents typos.
|
|
7
|
-
*/
|
|
8
|
-
export type CounterKeys =
|
|
9
|
-
| "trade"
|
|
10
|
-
| "delta"
|
|
11
|
-
| "account"
|
|
12
|
-
| "error"
|
|
13
|
-
| "disconnected";
|
|
14
|
-
|
|
15
|
-
interface Endpoint {
|
|
16
|
-
/** WebSocket endpoint URL */
|
|
17
|
-
url: string;
|
|
18
|
-
/** Streams we want to subscribe to once connected (can be empty) */
|
|
19
|
-
streams: string[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Webāsocket endpoints to test. Keep this list short & focused so the smoke
|
|
24
|
-
* test finishes quickly inside CI.
|
|
25
|
-
*/
|
|
26
|
-
const endpoints: Endpoint[] = [
|
|
27
|
-
// {
|
|
28
|
-
// url: "wss://staging.n1.xyz/ws/",
|
|
29
|
-
// streams: [], // no runtime subscribe call needed
|
|
30
|
-
// },
|
|
31
|
-
|
|
32
|
-
// {
|
|
33
|
-
// url: `wss://staging.n1.xyz/ws/account@${process.env.NORD_ACCOUNT_ID ?? "3"}`,
|
|
34
|
-
// streams: [],
|
|
35
|
-
// },
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
url: `wss://zo-devnet-rc.n1.xyz/ws/trades@ETHPERP`,
|
|
39
|
-
streams: ["trades@ETHPERP"],
|
|
40
|
-
},
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
/** How long each endpoint should be observed for (default: 15āÆs) */
|
|
44
|
-
// const TEST_DURATION_MS = Number(process.env.TEST_DURATION_MS ?? 15_000);
|
|
45
|
-
const TEST_DURATION_MS = 15_000;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Simple message counters for every event type the client can emit.
|
|
49
|
-
* This is mutated by the event handlers during the test run.
|
|
50
|
-
*/
|
|
51
|
-
const counters: Record<CounterKeys, number> = {
|
|
52
|
-
trade: 0,
|
|
53
|
-
delta: 0,
|
|
54
|
-
account: 0,
|
|
55
|
-
error: 0,
|
|
56
|
-
disconnected: 0,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Connect to a single endpoint, wait for activity, then verify we received the
|
|
61
|
-
* expected events.
|
|
62
|
-
*/
|
|
63
|
-
async function smokeTest(endpoint: Endpoint): Promise<void> {
|
|
64
|
-
console.log(`š°ļø Connecting to ${endpoint.url} ā¦`);
|
|
65
|
-
const client = new NordWebSocketClient(endpoint.url);
|
|
66
|
-
client.connect();
|
|
67
|
-
|
|
68
|
-
client.on("connected", () => {
|
|
69
|
-
console.log("ā
connected");
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
client.on("disconnected", () => {
|
|
73
|
-
console.log("ā ļø disconnected");
|
|
74
|
-
counters.disconnected++;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
client.on("error", (err: unknown) => {
|
|
78
|
-
console.error("ā error:", err);
|
|
79
|
-
counters.error++;
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
client.on("trades", (m) => {
|
|
83
|
-
console.log({ m });
|
|
84
|
-
counters.trade++;
|
|
85
|
-
});
|
|
86
|
-
client.on("deltas", (m) => {
|
|
87
|
-
console.log({ m });
|
|
88
|
-
counters.delta++;
|
|
89
|
-
});
|
|
90
|
-
client.on("accounts", (m) => {
|
|
91
|
-
console.log({ m });
|
|
92
|
-
counters.account++;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Wait a bit, then close and report
|
|
96
|
-
await new Promise((resolve) => setTimeout(resolve, TEST_DURATION_MS));
|
|
97
|
-
client.close();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
(async () => {
|
|
101
|
-
try {
|
|
102
|
-
for (const ep of endpoints) {
|
|
103
|
-
await smokeTest(ep);
|
|
104
|
-
}
|
|
105
|
-
console.log("\nš All websocket endpoints responded as expected:");
|
|
106
|
-
console.table(counters);
|
|
107
|
-
} catch (e) {
|
|
108
|
-
console.error("\nš“ Smoke test failed:", (e as Error).message);
|
|
109
|
-
console.table(counters);
|
|
110
|
-
process.exitCode = 1;
|
|
111
|
-
}
|
|
112
|
-
})();
|
package/.prettierignore
DELETED
package/check.sh
DELETED
package/default.nix
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
{ inputs, ... }:
|
|
2
|
-
{
|
|
3
|
-
perSystem =
|
|
4
|
-
{
|
|
5
|
-
pkgs,
|
|
6
|
-
self',
|
|
7
|
-
system,
|
|
8
|
-
...
|
|
9
|
-
}:
|
|
10
|
-
{
|
|
11
|
-
packages = {
|
|
12
|
-
nord-ts-proto =
|
|
13
|
-
let
|
|
14
|
-
ts-proto = inputs.n1.packages.${system}.ts-proto;
|
|
15
|
-
in
|
|
16
|
-
pkgs.writeShellApplication {
|
|
17
|
-
name = "nord-ts-proto";
|
|
18
|
-
runtimeInputs = [ pkgs.protobuf ];
|
|
19
|
-
text = ''
|
|
20
|
-
if [ $# -ne 2 ]; then
|
|
21
|
-
echo >&2 "usage: $(basename "$0") <proto-file> <out-dir>"
|
|
22
|
-
exit 1
|
|
23
|
-
fi
|
|
24
|
-
readonly PROTO_FILE="$1"
|
|
25
|
-
readonly OUT_DIR="$2"
|
|
26
|
-
protoc \
|
|
27
|
-
--plugin="${ts-proto}/bin/protoc-gen-ts_proto" \
|
|
28
|
-
--ts_proto_opt=forceLong=bigint \
|
|
29
|
-
--ts_proto_opt=esModuleInterop=true \
|
|
30
|
-
--ts_proto_opt=oneof=unions-value \
|
|
31
|
-
--ts_proto_opt=unrecognizedEnum=false \
|
|
32
|
-
--ts_proto_out="$OUT_DIR" \
|
|
33
|
-
--proto_path="$(dirname "$PROTO_FILE")" \
|
|
34
|
-
"$PROTO_FILE"
|
|
35
|
-
'';
|
|
36
|
-
};
|
|
37
|
-
nord-ts-check = pkgs.writeShellApplication {
|
|
38
|
-
name = "ts-check";
|
|
39
|
-
runtimeInputs = [
|
|
40
|
-
pkgs.protobuf
|
|
41
|
-
pkgs.pnpm
|
|
42
|
-
];
|
|
43
|
-
text = builtins.readFile ./check.sh;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
}
|
package/eslint.config.mjs
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
|
2
|
-
import globals from "globals";
|
|
3
|
-
import tsParser from "@typescript-eslint/parser";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import js from "@eslint/js";
|
|
7
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = path.dirname(__filename);
|
|
11
|
-
const compat = new FlatCompat({
|
|
12
|
-
baseDirectory: __dirname,
|
|
13
|
-
recommendedConfig: js.configs.recommended,
|
|
14
|
-
allConfig: js.configs.all,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export default [
|
|
18
|
-
{
|
|
19
|
-
ignores: [
|
|
20
|
-
"**/dist",
|
|
21
|
-
"**/node_modules",
|
|
22
|
-
"**/.git",
|
|
23
|
-
"**/docs",
|
|
24
|
-
"src/gen/*",
|
|
25
|
-
"*.mjs",
|
|
26
|
-
"*.js",
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
...compat.extends(
|
|
30
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
31
|
-
"plugin:@typescript-eslint/recommended",
|
|
32
|
-
),
|
|
33
|
-
{
|
|
34
|
-
plugins: {
|
|
35
|
-
"@typescript-eslint": typescriptEslint,
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
languageOptions: {
|
|
39
|
-
globals: {
|
|
40
|
-
...globals.browser,
|
|
41
|
-
...globals.node,
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
parser: tsParser,
|
|
45
|
-
ecmaVersion: "latest",
|
|
46
|
-
sourceType: "module",
|
|
47
|
-
|
|
48
|
-
parserOptions: {
|
|
49
|
-
project: ["./tsconfig.json", "./tsconfig.eslint.json"],
|
|
50
|
-
tsconfigRootDir: ".",
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
rules: {
|
|
55
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
56
|
-
|
|
57
|
-
"@typescript-eslint/no-unused-vars": [
|
|
58
|
-
"warn",
|
|
59
|
-
{
|
|
60
|
-
argsIgnorePattern: "^_",
|
|
61
|
-
varsIgnorePattern: "^_",
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
];
|