@n1xyz/nord-ts 0.0.12 → 0.0.14
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/nord/api/core.d.ts +8 -8
- package/dist/nord/api/core.js +55 -14
- package/dist/nord/api/metrics.js +1 -1
- package/dist/nord/client/Nord.d.ts +39 -68
- package/dist/nord/client/Nord.js +97 -115
- package/dist/nord/client/NordUser.d.ts +0 -17
- package/dist/nord/client/NordUser.js +0 -28
- package/dist/types.d.ts +36 -13
- package/dist/types.js +2 -2
- package/dist/websocket/NordWebSocketClient.d.ts +0 -3
- package/dist/websocket/NordWebSocketClient.js +10 -13
- package/dist/websocket/events.d.ts +2 -2
- package/package.json +1 -1
- package/src/idl/bridge.ts +0 -1
- package/src/nord/api/core.ts +69 -17
- package/src/nord/api/metrics.ts +26 -20
- package/src/nord/api/queries.ts +7 -11
- package/src/nord/client/Nord.ts +126 -156
- package/src/nord/client/NordUser.ts +0 -49
- package/src/types.ts +38 -13
- package/src/websocket/NordWebSocketClient.ts +11 -14
- package/src/websocket/events.ts +2 -2
- package/test.ts +0 -107
package/src/nord/client/Nord.ts
CHANGED
|
@@ -14,11 +14,12 @@ import {
|
|
|
14
14
|
PeakTpsPeriodUnit,
|
|
15
15
|
RollmanActionResponse,
|
|
16
16
|
RollmanActionsResponse,
|
|
17
|
+
SubscriptionPattern,
|
|
17
18
|
Token,
|
|
18
19
|
TradesQuery,
|
|
19
20
|
TradesResponse,
|
|
20
21
|
UserAccountIdsQuery,
|
|
21
|
-
UserAccountIdsResponse
|
|
22
|
+
UserAccountIdsResponse,
|
|
22
23
|
} from "../../types";
|
|
23
24
|
import { NordWebSocketClient } from "../../websocket/index";
|
|
24
25
|
import * as core from "../api/core";
|
|
@@ -35,6 +36,18 @@ export interface UserSubscription extends EventEmitter {
|
|
|
35
36
|
close: () => void;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* WebSocket subscription options interface
|
|
41
|
+
*/
|
|
42
|
+
export interface WebSocketSubscriptionOptions {
|
|
43
|
+
/** Market symbols to subscribe to for trade updates */
|
|
44
|
+
trades?: string[];
|
|
45
|
+
/** Market symbols to subscribe to for orderbook delta updates */
|
|
46
|
+
deltas?: string[];
|
|
47
|
+
/** Account IDs to subscribe to for account updates */
|
|
48
|
+
accounts?: number[];
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
/**
|
|
39
52
|
* Main Nord client class for interacting with the Nord API
|
|
40
53
|
*/
|
|
@@ -57,36 +70,6 @@ export class Nord {
|
|
|
57
70
|
/** Map of symbol to market_id */
|
|
58
71
|
private symbolToMarketId: Map<string, number> = new Map();
|
|
59
72
|
|
|
60
|
-
/**
|
|
61
|
-
* WebSocket client for trades
|
|
62
|
-
* @private
|
|
63
|
-
*/
|
|
64
|
-
private tradesWs: NordWebSocketClient | null = null;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* WebSocket client for orderbook deltas
|
|
68
|
-
* @private
|
|
69
|
-
*/
|
|
70
|
-
private deltasWs: NordWebSocketClient | null = null;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* WebSocket client for user updates
|
|
74
|
-
* @private
|
|
75
|
-
*/
|
|
76
|
-
private userWs: NordWebSocketClient | null = null;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Initial subscriptions for the trades WebSocket
|
|
80
|
-
* @private
|
|
81
|
-
*/
|
|
82
|
-
private tradesSubscriptions?: string[];
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Initial subscriptions for the deltas WebSocket
|
|
86
|
-
* @private
|
|
87
|
-
*/
|
|
88
|
-
private deltasSubscriptions?: string[];
|
|
89
|
-
|
|
90
73
|
/**
|
|
91
74
|
* Create a new Nord client
|
|
92
75
|
*
|
|
@@ -94,19 +77,9 @@ export class Nord {
|
|
|
94
77
|
* @param config.webServerUrl - Base URL for the Nord web server
|
|
95
78
|
* @param config.solanaProgramId - Solana program ID
|
|
96
79
|
* @param config.solanaUrl - Solana cluster URL
|
|
97
|
-
* @param config.initWebSockets - Whether to initialize WebSockets on creation, defaults to true
|
|
98
|
-
* @param config.tradesSubscriptions - Optional array of trades subscriptions to initialize with (e.g., ["trades@BTCUSDC"])
|
|
99
|
-
* @param config.deltasSubscriptions - Optional array of deltas subscriptions to initialize with (e.g., ["deltas@BTCUSDC"])
|
|
100
80
|
* @throws {Error} If required configuration is missing
|
|
101
81
|
*/
|
|
102
|
-
constructor({
|
|
103
|
-
webServerUrl,
|
|
104
|
-
solanaProgramId,
|
|
105
|
-
solanaUrl,
|
|
106
|
-
initWebSockets = true,
|
|
107
|
-
tradesSubscriptions,
|
|
108
|
-
deltasSubscriptions,
|
|
109
|
-
}: NordConfig) {
|
|
82
|
+
constructor({ webServerUrl, solanaProgramId, solanaUrl }: NordConfig) {
|
|
110
83
|
if (!webServerUrl) {
|
|
111
84
|
throw new NordError("webServerUrl is required");
|
|
112
85
|
}
|
|
@@ -122,48 +95,67 @@ export class Nord {
|
|
|
122
95
|
this.webServerUrl = webServerUrl;
|
|
123
96
|
this.solanaProgramId = solanaProgramId;
|
|
124
97
|
this.solanaUrl = solanaUrl;
|
|
125
|
-
|
|
126
|
-
// Store subscription parameters
|
|
127
|
-
this.tradesSubscriptions = tradesSubscriptions;
|
|
128
|
-
this.deltasSubscriptions = deltasSubscriptions;
|
|
129
|
-
|
|
130
|
-
// Initialize WebSocket clients only if initWebSockets is true
|
|
131
|
-
if (initWebSockets) {
|
|
132
|
-
this.initializeWebSockets();
|
|
133
|
-
}
|
|
134
98
|
}
|
|
135
99
|
|
|
136
100
|
/**
|
|
137
|
-
*
|
|
101
|
+
* Create a WebSocket client with specific subscriptions
|
|
138
102
|
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
103
|
+
* @param options - Subscription options that specify which data streams to subscribe to
|
|
104
|
+
* @returns A new WebSocket client with the requested subscriptions
|
|
105
|
+
* @throws {NordError} If invalid subscription options are provided
|
|
141
106
|
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
107
|
+
* @example
|
|
108
|
+
* // Create a client for trades and deltas from one market and an account
|
|
109
|
+
* const wsClient = nord.createWebSocketClient({
|
|
110
|
+
* trades: ["BTCUSDC"],
|
|
111
|
+
* deltas: ["BTCUSDC"],
|
|
112
|
+
* accounts: [123]
|
|
113
|
+
* });
|
|
144
114
|
*
|
|
145
|
-
* @
|
|
146
|
-
*
|
|
115
|
+
* @example
|
|
116
|
+
* // Create a client for trades from multiple markets
|
|
117
|
+
* const tradesClient = nord.createWebSocketClient({
|
|
118
|
+
* trades: ["BTCUSDC", "ETHUSDC"]
|
|
119
|
+
* });
|
|
147
120
|
*/
|
|
148
|
-
public
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
121
|
+
public createWebSocketClient(
|
|
122
|
+
options: WebSocketSubscriptionOptions,
|
|
123
|
+
): NordWebSocketClient {
|
|
124
|
+
const subscriptions: SubscriptionPattern[] = [];
|
|
125
|
+
|
|
126
|
+
// Add trade subscriptions
|
|
127
|
+
if (options.trades && options.trades.length > 0) {
|
|
128
|
+
options.trades.forEach((symbol) => {
|
|
129
|
+
subscriptions.push(`trades@${symbol}` as SubscriptionPattern);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Add delta subscriptions
|
|
134
|
+
if (options.deltas && options.deltas.length > 0) {
|
|
135
|
+
options.deltas.forEach((symbol) => {
|
|
136
|
+
subscriptions.push(`deltas@${symbol}` as SubscriptionPattern);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Add account subscriptions
|
|
141
|
+
if (options.accounts && options.accounts.length > 0) {
|
|
142
|
+
options.accounts.forEach((accountId) => {
|
|
143
|
+
if (isNaN(accountId) || accountId <= 0) {
|
|
144
|
+
throw new NordError(
|
|
145
|
+
`Invalid account ID: ${accountId}. Must be a positive number.`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
subscriptions.push(`account@${accountId}` as SubscriptionPattern);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Validate that at least one subscription was provided
|
|
153
|
+
if (subscriptions.length === 0) {
|
|
154
|
+
throw new NordError("At least one subscription must be provided");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Create and return a new WebSocket client
|
|
158
|
+
return core.initWebSocketClient(this.webServerUrl, subscriptions);
|
|
167
159
|
}
|
|
168
160
|
|
|
169
161
|
/**
|
|
@@ -214,9 +206,6 @@ export class Nord {
|
|
|
214
206
|
* @param nordConfig.webServerUrl - Base URL for the Nord web server
|
|
215
207
|
* @param nordConfig.solanaProgramId - Solana program ID
|
|
216
208
|
* @param nordConfig.solanaUrl - Solana cluster URL
|
|
217
|
-
* @param nordConfig.initWebSockets - Whether to initialize WebSockets on creation, defaults to true
|
|
218
|
-
* @param nordConfig.tradesSubscriptions - Optional array of trades subscriptions (e.g., ["trades@BTCUSDC"])
|
|
219
|
-
* @param nordConfig.deltasSubscriptions - Optional array of deltas subscriptions (e.g., ["deltas@BTCUSDC"])
|
|
220
209
|
* @returns Initialized Nord client
|
|
221
210
|
* @throws {NordError} If initialization fails
|
|
222
211
|
*/
|
|
@@ -268,7 +257,7 @@ export class Nord {
|
|
|
268
257
|
async getLastActionId(): Promise<number> {
|
|
269
258
|
return queries.getLastActionId(this.webServerUrl);
|
|
270
259
|
}
|
|
271
|
-
|
|
260
|
+
|
|
272
261
|
/**
|
|
273
262
|
* Fetch aggregate metrics from the Nord API
|
|
274
263
|
*
|
|
@@ -364,68 +353,22 @@ export class Nord {
|
|
|
364
353
|
return metrics.queryPrometheus(this.webServerUrl, params);
|
|
365
354
|
}
|
|
366
355
|
|
|
367
|
-
/**
|
|
368
|
-
* Get the trades WebSocket client (default)
|
|
369
|
-
* If not already initialized, it will be created
|
|
370
|
-
*
|
|
371
|
-
* @returns WebSocket client for trades
|
|
372
|
-
*/
|
|
373
|
-
public getWebSocketClient(): NordWebSocketClient {
|
|
374
|
-
if (!this.tradesWs) {
|
|
375
|
-
this.initializeWebSockets();
|
|
376
|
-
}
|
|
377
|
-
return this.tradesWs!;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Get the trades WebSocket client
|
|
382
|
-
* If not already initialized, it will be created
|
|
383
|
-
*
|
|
384
|
-
* @returns WebSocket client for trades
|
|
385
|
-
*/
|
|
386
|
-
public getTradesWebSocketClient(): NordWebSocketClient {
|
|
387
|
-
if (!this.tradesWs) {
|
|
388
|
-
this.initializeWebSockets();
|
|
389
|
-
}
|
|
390
|
-
return this.tradesWs!;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/**
|
|
394
|
-
* Get the deltas WebSocket client
|
|
395
|
-
* If not already initialized, it will be created
|
|
396
|
-
*
|
|
397
|
-
* @returns WebSocket client for orderbook deltas
|
|
398
|
-
*/
|
|
399
|
-
public getDeltasWebSocketClient(): NordWebSocketClient {
|
|
400
|
-
if (!this.deltasWs) {
|
|
401
|
-
this.initializeWebSockets();
|
|
402
|
-
}
|
|
403
|
-
return this.deltasWs!;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* Get the user WebSocket client
|
|
408
|
-
* If not already initialized, it will be created
|
|
409
|
-
*
|
|
410
|
-
* @returns WebSocket client for user updates
|
|
411
|
-
*/
|
|
412
|
-
public getUserWebSocketClient(): NordWebSocketClient {
|
|
413
|
-
if (!this.userWs) {
|
|
414
|
-
// Initialize user WebSocket client on demand
|
|
415
|
-
this.userWs = core.initWebSocketClient(this.webServerUrl, "user");
|
|
416
|
-
return this.userWs;
|
|
417
|
-
}
|
|
418
|
-
return this.userWs;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
356
|
/**
|
|
422
357
|
* Subscribe to orderbook updates for a market
|
|
423
358
|
*
|
|
424
359
|
* @param symbol - Market symbol
|
|
425
360
|
* @returns Orderbook subscription
|
|
361
|
+
* @throws {NordError} If symbol is invalid
|
|
426
362
|
*/
|
|
427
363
|
public subscribeOrderbook(symbol: string): OrderbookSubscription {
|
|
364
|
+
if (!symbol || typeof symbol !== "string") {
|
|
365
|
+
throw new NordError("Invalid market symbol");
|
|
366
|
+
}
|
|
367
|
+
|
|
428
368
|
const subscription = new EventEmitter() as OrderbookSubscription;
|
|
369
|
+
const wsClient = this.createWebSocketClient({
|
|
370
|
+
deltas: [symbol],
|
|
371
|
+
});
|
|
429
372
|
|
|
430
373
|
const handleDelta = (update: {
|
|
431
374
|
symbol: string;
|
|
@@ -439,17 +382,11 @@ export class Nord {
|
|
|
439
382
|
subscription.emit("message", update);
|
|
440
383
|
};
|
|
441
384
|
|
|
442
|
-
|
|
443
|
-
if (!this.deltasWs) {
|
|
444
|
-
this.initializeWebSockets();
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
this.deltasWs!.on("delta", handleDelta);
|
|
448
|
-
this.deltasWs!.subscribe([`deltas@${symbol}`]);
|
|
385
|
+
wsClient.on("delta", handleDelta);
|
|
449
386
|
|
|
450
387
|
subscription.close = () => {
|
|
451
|
-
|
|
452
|
-
|
|
388
|
+
wsClient.unsubscribe([`deltas@${symbol}`]);
|
|
389
|
+
wsClient.removeListener("delta", handleDelta);
|
|
453
390
|
subscription.removeAllListeners();
|
|
454
391
|
};
|
|
455
392
|
|
|
@@ -461,9 +398,17 @@ export class Nord {
|
|
|
461
398
|
*
|
|
462
399
|
* @param symbol - Market symbol
|
|
463
400
|
* @returns Trade subscription
|
|
401
|
+
* @throws {NordError} If symbol is invalid
|
|
464
402
|
*/
|
|
465
403
|
public subscribeTrades(symbol: string): TradeSubscription {
|
|
404
|
+
if (!symbol || typeof symbol !== "string") {
|
|
405
|
+
throw new NordError("Invalid market symbol");
|
|
406
|
+
}
|
|
407
|
+
|
|
466
408
|
const subscription = new EventEmitter() as TradeSubscription;
|
|
409
|
+
const wsClient = this.createWebSocketClient({
|
|
410
|
+
trades: [symbol],
|
|
411
|
+
});
|
|
467
412
|
|
|
468
413
|
const handleTrade = (update: {
|
|
469
414
|
symbol: string;
|
|
@@ -481,17 +426,47 @@ export class Nord {
|
|
|
481
426
|
subscription.emit("message", update);
|
|
482
427
|
};
|
|
483
428
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
429
|
+
wsClient.on("trades", handleTrade);
|
|
430
|
+
|
|
431
|
+
subscription.close = () => {
|
|
432
|
+
wsClient.unsubscribe([`trades@${symbol}`]);
|
|
433
|
+
wsClient.removeListener("trades", handleTrade);
|
|
434
|
+
subscription.removeAllListeners();
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
return subscription;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Subscribe to account updates
|
|
442
|
+
*
|
|
443
|
+
* @param accountId - Account ID to subscribe to
|
|
444
|
+
* @returns User subscription
|
|
445
|
+
* @throws {NordError} If accountId is invalid
|
|
446
|
+
*/
|
|
447
|
+
public subscribeAccount(accountId: number): UserSubscription {
|
|
448
|
+
if (isNaN(accountId) || accountId <= 0) {
|
|
449
|
+
throw new NordError("Invalid account ID");
|
|
487
450
|
}
|
|
488
451
|
|
|
489
|
-
|
|
490
|
-
this.
|
|
452
|
+
const subscription = new EventEmitter() as UserSubscription;
|
|
453
|
+
const wsClient = this.createWebSocketClient({
|
|
454
|
+
accounts: [accountId],
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
const handleAccountUpdate = (update: any) => {
|
|
458
|
+
if (update.account_id !== accountId) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
subscription.emit("message", update);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
wsClient.on("account", handleAccountUpdate);
|
|
491
466
|
|
|
492
467
|
subscription.close = () => {
|
|
493
|
-
|
|
494
|
-
|
|
468
|
+
wsClient.unsubscribe([`account@${accountId}`]);
|
|
469
|
+
wsClient.removeListener("account", handleAccountUpdate);
|
|
495
470
|
subscription.removeAllListeners();
|
|
496
471
|
};
|
|
497
472
|
|
|
@@ -547,11 +522,6 @@ export class Nord {
|
|
|
547
522
|
query = { market_id: marketId };
|
|
548
523
|
}
|
|
549
524
|
|
|
550
|
-
// Ensure market_id is provided
|
|
551
|
-
if (query.market_id === undefined) {
|
|
552
|
-
throw new NordError("market_id is required for orderbook query");
|
|
553
|
-
}
|
|
554
|
-
|
|
555
525
|
return market.getOrderbook(this.webServerUrl, query);
|
|
556
526
|
}
|
|
557
527
|
|
|
@@ -111,17 +111,6 @@ export interface TransferParams {
|
|
|
111
111
|
toAccountId: number;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
/**
|
|
115
|
-
* Parameters for creating a new account
|
|
116
|
-
*/
|
|
117
|
-
export interface CreateAccountParams {
|
|
118
|
-
/** Token ID for initial funding */
|
|
119
|
-
tokenId: number;
|
|
120
|
-
|
|
121
|
-
/** Initial funding amount */
|
|
122
|
-
amount: Decimal.Value;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
114
|
/**
|
|
126
115
|
* User class for interacting with the Nord protocol
|
|
127
116
|
*/
|
|
@@ -892,44 +881,6 @@ export class NordUser {
|
|
|
892
881
|
}
|
|
893
882
|
}
|
|
894
883
|
|
|
895
|
-
/**
|
|
896
|
-
* Create a new account
|
|
897
|
-
*
|
|
898
|
-
* @param params - Account creation parameters
|
|
899
|
-
* @returns New NordUser instance
|
|
900
|
-
* @throws {NordError} If the operation fails
|
|
901
|
-
*/
|
|
902
|
-
async createAccount(params: CreateAccountParams): Promise<NordUser> {
|
|
903
|
-
try {
|
|
904
|
-
this.checkSessionValidity();
|
|
905
|
-
// Create a new keypair for the account
|
|
906
|
-
const keypair = Keypair.generate();
|
|
907
|
-
|
|
908
|
-
// Create a new NordUser
|
|
909
|
-
const newUser = NordUser.fromPrivateKey(
|
|
910
|
-
this.nord,
|
|
911
|
-
keypair.secretKey,
|
|
912
|
-
this.connection,
|
|
913
|
-
);
|
|
914
|
-
|
|
915
|
-
// Transfer initial funds
|
|
916
|
-
await this.transferToAccount({
|
|
917
|
-
to: newUser,
|
|
918
|
-
tokenId: params.tokenId,
|
|
919
|
-
amount: params.amount,
|
|
920
|
-
fromAccountId: optExpect(this.accountIds?.[0], "No account ID"),
|
|
921
|
-
toAccountId: optExpect(
|
|
922
|
-
newUser.accountIds?.[0],
|
|
923
|
-
"No account ID for new user",
|
|
924
|
-
),
|
|
925
|
-
});
|
|
926
|
-
|
|
927
|
-
return newUser;
|
|
928
|
-
} catch (error) {
|
|
929
|
-
throw new NordError("Failed to create account", { cause: error });
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
884
|
/**
|
|
934
885
|
* Helper function to retry a promise with exponential backoff
|
|
935
886
|
*
|
package/src/types.ts
CHANGED
|
@@ -17,6 +17,18 @@ export enum PeakTpsPeriodUnit {
|
|
|
17
17
|
Year = "y",
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Nord subscription type for trades or deltas
|
|
22
|
+
*/
|
|
23
|
+
export type SubscriptionType = "trades" | "deltas" | "account";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Pattern for a valid Nord subscription
|
|
27
|
+
* Format should be: "<type>@<parameter>"
|
|
28
|
+
* Examples: "trades@BTCUSDC", "deltas@ETHUSDC", "account@42"
|
|
29
|
+
*/
|
|
30
|
+
export type SubscriptionPattern = `${SubscriptionType}@${string}` | string;
|
|
31
|
+
|
|
20
32
|
/**
|
|
21
33
|
* Configuration options for the Nord client
|
|
22
34
|
*/
|
|
@@ -29,12 +41,25 @@ export interface NordConfig {
|
|
|
29
41
|
solanaUrl: string;
|
|
30
42
|
/** Whether to initialize WebSockets on creation, defaults to true */
|
|
31
43
|
initWebSockets?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Initial subscriptions for the trades WebSocket
|
|
46
|
+
* Supports both formats:
|
|
47
|
+
* - Legacy format: ["BTCUSDC", "ETHUSDC"]
|
|
48
|
+
* - New format: ["trades@BTCUSDC", "trades@ETHUSDC"]
|
|
49
|
+
*/
|
|
50
|
+
tradesSubscriptions?: SubscriptionPattern[];
|
|
51
|
+
/**
|
|
52
|
+
* Initial subscriptions for the deltas WebSocket
|
|
53
|
+
* Supports both formats:
|
|
54
|
+
* - Legacy format: ["BTCUSDC", "ETHUSDC"]
|
|
55
|
+
* - New format: ["deltas@BTCUSDC", "deltas@ETHUSDC"]
|
|
56
|
+
*/
|
|
57
|
+
deltasSubscriptions?: SubscriptionPattern[];
|
|
36
58
|
}
|
|
37
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Configuration options for the Nord client
|
|
62
|
+
*/
|
|
38
63
|
export interface TokenInfo {
|
|
39
64
|
address: string;
|
|
40
65
|
precision: number;
|
|
@@ -411,16 +436,16 @@ export interface ActionNonceResponse {
|
|
|
411
436
|
export enum WebSocketMessageType {
|
|
412
437
|
Subscribe = "subscribe",
|
|
413
438
|
Unsubscribe = "unsubscribe",
|
|
414
|
-
TradeUpdate = "
|
|
439
|
+
TradeUpdate = "trades",
|
|
415
440
|
DeltaUpdate = "delta",
|
|
416
|
-
|
|
441
|
+
AccountUpdate = "account",
|
|
417
442
|
}
|
|
418
443
|
|
|
419
444
|
/**
|
|
420
445
|
* WebSocket subscription request
|
|
421
446
|
*/
|
|
422
447
|
export interface WebSocketSubscription {
|
|
423
|
-
|
|
448
|
+
e: WebSocketMessageType;
|
|
424
449
|
streams: string[]; // Array of streams to subscribe/unsubscribe (e.g. ["trades@BTCUSDC", "deltas@BTCUSDC"])
|
|
425
450
|
}
|
|
426
451
|
|
|
@@ -428,7 +453,7 @@ export interface WebSocketSubscription {
|
|
|
428
453
|
* WebSocket trade update message
|
|
429
454
|
*/
|
|
430
455
|
export interface WebSocketTradeUpdate {
|
|
431
|
-
|
|
456
|
+
e: WebSocketMessageType.TradeUpdate;
|
|
432
457
|
symbol: string;
|
|
433
458
|
trades: Trade[];
|
|
434
459
|
timestamp: number;
|
|
@@ -438,7 +463,7 @@ export interface WebSocketTradeUpdate {
|
|
|
438
463
|
* WebSocket delta update message
|
|
439
464
|
*/
|
|
440
465
|
export interface WebSocketDeltaUpdate {
|
|
441
|
-
|
|
466
|
+
e: WebSocketMessageType.DeltaUpdate;
|
|
442
467
|
last_update_id: number;
|
|
443
468
|
update_id: number;
|
|
444
469
|
market_symbol: string;
|
|
@@ -450,9 +475,9 @@ export interface WebSocketDeltaUpdate {
|
|
|
450
475
|
/**
|
|
451
476
|
* WebSocket user update message
|
|
452
477
|
*/
|
|
453
|
-
export interface
|
|
454
|
-
|
|
455
|
-
|
|
478
|
+
export interface WebSocketAccountUpdate {
|
|
479
|
+
e: WebSocketMessageType.AccountUpdate;
|
|
480
|
+
accountId: number;
|
|
456
481
|
account: Account;
|
|
457
482
|
timestamp: number;
|
|
458
483
|
}
|
|
@@ -461,4 +486,4 @@ export type WebSocketMessage =
|
|
|
461
486
|
| WebSocketSubscription
|
|
462
487
|
| WebSocketTradeUpdate
|
|
463
488
|
| WebSocketDeltaUpdate
|
|
464
|
-
|
|
|
489
|
+
| WebSocketAccountUpdate;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
WebSocketSubscription,
|
|
7
7
|
WebSocketTradeUpdate,
|
|
8
8
|
WebSocketDeltaUpdate,
|
|
9
|
-
|
|
9
|
+
WebSocketAccountUpdate,
|
|
10
10
|
} from "../types";
|
|
11
11
|
import { NordWebSocketClientEvents } from "./events";
|
|
12
12
|
|
|
@@ -27,7 +27,7 @@ type BrowserWebSocket = {
|
|
|
27
27
|
|
|
28
28
|
type WebSocketInstance = WebSocket | BrowserWebSocket;
|
|
29
29
|
|
|
30
|
-
const VALID_STREAM_TYPES = ["trades", "
|
|
30
|
+
const VALID_STREAM_TYPES = ["trades", "delta", "account"];
|
|
31
31
|
|
|
32
32
|
// Constants for WebSocket readyState
|
|
33
33
|
const WS_OPEN = 1;
|
|
@@ -36,9 +36,6 @@ const WS_OPEN = 1;
|
|
|
36
36
|
* WebSocket client for Nord exchange
|
|
37
37
|
*
|
|
38
38
|
* This client connects to one of the specific Nord WebSocket endpoints:
|
|
39
|
-
* - /ws/trades - For trade updates
|
|
40
|
-
* - /ws/deltas - For orderbook delta updates
|
|
41
|
-
* - /ws/user - For user-specific updates
|
|
42
39
|
*
|
|
43
40
|
* Each endpoint handles a specific type of data and subscriptions must match
|
|
44
41
|
* the endpoint type (e.g., only 'trades@BTCUSDC' subscriptions are valid on
|
|
@@ -104,9 +101,9 @@ export class NordWebSocketClient
|
|
|
104
101
|
);
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
if (type === "
|
|
104
|
+
if (type === "account" && !/^\d+$/.test(params)) {
|
|
108
105
|
throw new Error(
|
|
109
|
-
`Invalid
|
|
106
|
+
`Invalid account ID in stream: ${params}. Expected numeric ID`,
|
|
110
107
|
);
|
|
111
108
|
}
|
|
112
109
|
}
|
|
@@ -304,7 +301,7 @@ export class NordWebSocketClient
|
|
|
304
301
|
}
|
|
305
302
|
|
|
306
303
|
const message: WebSocketSubscription = {
|
|
307
|
-
|
|
304
|
+
e: WebSocketMessageType.Subscribe,
|
|
308
305
|
streams,
|
|
309
306
|
};
|
|
310
307
|
|
|
@@ -351,7 +348,7 @@ export class NordWebSocketClient
|
|
|
351
348
|
}
|
|
352
349
|
|
|
353
350
|
const message: WebSocketSubscription = {
|
|
354
|
-
|
|
351
|
+
e: WebSocketMessageType.Unsubscribe,
|
|
355
352
|
streams,
|
|
356
353
|
};
|
|
357
354
|
|
|
@@ -399,18 +396,18 @@ export class NordWebSocketClient
|
|
|
399
396
|
* @param message WebSocket message
|
|
400
397
|
*/
|
|
401
398
|
private handleMessage(message: WebSocketMessage): void {
|
|
402
|
-
switch (message.
|
|
399
|
+
switch (message.e) {
|
|
403
400
|
case WebSocketMessageType.TradeUpdate:
|
|
404
|
-
this.emit("
|
|
401
|
+
this.emit("trades", message as WebSocketTradeUpdate);
|
|
405
402
|
break;
|
|
406
403
|
case WebSocketMessageType.DeltaUpdate:
|
|
407
404
|
this.emit("delta", message as WebSocketDeltaUpdate);
|
|
408
405
|
break;
|
|
409
|
-
case WebSocketMessageType.
|
|
410
|
-
this.emit("
|
|
406
|
+
case WebSocketMessageType.AccountUpdate:
|
|
407
|
+
this.emit("account", message as WebSocketAccountUpdate);
|
|
411
408
|
break;
|
|
412
409
|
default:
|
|
413
|
-
this.emit("error", new Error(`Unknown message type: ${message.
|
|
410
|
+
this.emit("error", new Error(`Unknown message type: ${message.e}`));
|
|
414
411
|
}
|
|
415
412
|
}
|
|
416
413
|
|
package/src/websocket/events.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WebSocketTradeUpdate,
|
|
3
3
|
WebSocketDeltaUpdate,
|
|
4
|
-
|
|
4
|
+
WebSocketAccountUpdate,
|
|
5
5
|
} from "../types";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -13,7 +13,7 @@ export interface NordWebSocketEvents {
|
|
|
13
13
|
error: (error: Error) => void;
|
|
14
14
|
trade: (update: WebSocketTradeUpdate) => void;
|
|
15
15
|
delta: (update: WebSocketDeltaUpdate) => void;
|
|
16
|
-
|
|
16
|
+
account: (update: WebSocketAccountUpdate) => void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|