@n1xyz/nord-ts 0.0.1 → 0.0.4
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/.eslintrc.js +11 -0
- package/README.md +148 -65
- package/dist/bridge/NordUser.d.ts +78 -0
- package/dist/bridge/NordUser.js +196 -0
- package/dist/bridge/client.d.ts +150 -0
- package/dist/bridge/client.js +394 -0
- package/dist/bridge/const.d.ts +23 -0
- package/dist/bridge/const.js +47 -0
- package/dist/bridge/index.d.ts +5 -0
- package/dist/bridge/index.js +23 -0
- package/dist/bridge/types.d.ts +118 -0
- package/dist/bridge/types.js +16 -0
- package/dist/bridge/utils.d.ts +64 -0
- package/dist/bridge/utils.js +131 -0
- package/dist/client.d.ts +70 -0
- package/dist/client.js +129 -0
- package/dist/const.d.ts +2 -5
- package/dist/const.js +18 -22
- package/dist/constants/endpoints.d.ts +65 -0
- package/dist/constants/endpoints.js +68 -0
- package/dist/gen/common.d.ts +6 -1
- package/dist/gen/common.js +19 -9
- package/dist/gen/nord.d.ts +75 -17
- package/dist/gen/nord.js +987 -423
- package/dist/idl/bridge.d.ts +2 -0
- package/dist/idl/bridge.js +703 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +18 -2
- package/dist/models/account.d.ts +58 -0
- package/dist/models/account.js +6 -0
- package/dist/models/index.d.ts +8 -0
- package/dist/models/index.js +28 -0
- package/dist/models/market.d.ts +137 -0
- package/dist/models/market.js +6 -0
- package/dist/models/order.d.ts +211 -0
- package/dist/models/order.js +6 -0
- package/dist/models/token.d.ts +50 -0
- package/dist/models/token.js +6 -0
- package/dist/nord/Nord.d.ts +222 -49
- package/dist/nord/Nord.js +290 -278
- package/dist/nord/NordError.d.ts +23 -0
- package/dist/nord/NordError.js +48 -0
- package/dist/nord/NordImpl.d.ts +6 -2
- package/dist/nord/NordImpl.js +21 -1
- package/dist/nord/NordUser.d.ts +208 -42
- package/dist/nord/NordUser.js +389 -157
- package/dist/nord/Subscriber.d.ts +37 -0
- package/dist/nord/Subscriber.js +29 -0
- package/dist/nord/api/actions.d.ts +101 -0
- package/dist/nord/api/actions.js +250 -0
- package/dist/nord/api/core.d.ts +49 -0
- package/dist/nord/api/core.js +121 -0
- package/dist/nord/api/index.d.ts +1 -0
- package/dist/nord/api/index.js +17 -0
- package/dist/nord/api/market.d.ts +36 -0
- package/dist/nord/api/market.js +98 -0
- package/dist/nord/api/metrics.d.ts +67 -0
- package/dist/nord/api/metrics.js +132 -0
- package/dist/nord/api/orderFunctions.d.ts +168 -0
- package/dist/nord/api/orderFunctions.js +133 -0
- package/dist/nord/api/queries.d.ts +81 -0
- package/dist/nord/api/queries.js +187 -0
- package/dist/nord/client/Nord.d.ts +335 -0
- package/dist/nord/client/Nord.js +532 -0
- package/dist/nord/client/NordUser.d.ts +320 -0
- package/dist/nord/client/NordUser.js +701 -0
- package/dist/nord/core.d.ts +48 -0
- package/dist/nord/core.js +97 -0
- package/dist/nord/index.d.ts +9 -2
- package/dist/nord/index.js +30 -6
- package/dist/nord/market.d.ts +36 -0
- package/dist/nord/market.js +90 -0
- package/dist/nord/metrics.d.ts +67 -0
- package/dist/nord/metrics.js +124 -0
- package/dist/nord/models/Subscriber.d.ts +37 -0
- package/dist/nord/models/Subscriber.js +29 -0
- package/dist/nord/queries.d.ts +81 -0
- package/dist/nord/queries.js +181 -0
- package/dist/nord/types.d.ts +88 -0
- package/dist/nord/types.js +2 -0
- package/dist/nord/utils/NordError.d.ts +35 -0
- package/dist/nord/utils/NordError.js +46 -0
- package/dist/nord/websocket.d.ts +49 -0
- package/dist/nord/websocket.js +107 -0
- package/dist/operations/account.d.ts +58 -0
- package/dist/operations/account.js +112 -0
- package/dist/operations/market.d.ts +65 -0
- package/dist/operations/market.js +131 -0
- package/dist/operations/orders.d.ts +57 -0
- package/dist/operations/orders.js +129 -0
- package/dist/solana/NordUser.d.ts +78 -0
- package/dist/solana/NordUser.js +196 -0
- package/dist/solana/client.d.ts +139 -0
- package/dist/solana/client.js +360 -0
- package/dist/solana/const.d.ts +23 -0
- package/dist/solana/const.js +47 -0
- package/dist/solana/index.d.ts +5 -0
- package/dist/solana/index.js +23 -0
- package/dist/solana/types.d.ts +118 -0
- package/dist/solana/types.js +16 -0
- package/dist/solana/utils.d.ts +64 -0
- package/dist/solana/utils.js +131 -0
- package/dist/types/api.d.ts +152 -0
- package/dist/types/api.js +6 -0
- package/dist/types/config.d.ts +34 -0
- package/dist/types/config.js +6 -0
- package/dist/types.d.ts +144 -87
- package/dist/types.js +13 -2
- package/dist/utils/errors.d.ts +96 -0
- package/dist/utils/errors.js +132 -0
- package/dist/utils/http.d.ts +35 -0
- package/dist/utils/http.js +105 -0
- package/dist/utils.d.ts +14 -5
- package/dist/utils.js +26 -7
- package/dist/websocket/NordWebSocketClient.d.ts +71 -0
- package/dist/websocket/NordWebSocketClient.js +343 -0
- package/dist/websocket/client.d.ts +93 -0
- package/dist/websocket/client.js +222 -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/dist/websocket.d.ts +55 -0
- package/dist/websocket.js +211 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Nord.html +2 -15
- package/docs/classes/NordUser.html +4 -4
- package/docs/enums/FillMode.html +2 -2
- package/docs/enums/KeyType.html +2 -2
- package/docs/enums/PeakTpsPeriodUnit.html +2 -2
- package/docs/enums/Side.html +2 -2
- package/docs/functions/assert.html +1 -1
- package/docs/functions/bigIntToProtoU128.html +1 -1
- package/docs/functions/checkPubKeyLength.html +1 -1
- package/docs/functions/checkedFetch.html +1 -1
- package/docs/functions/decodeLengthDelimited.html +1 -1
- package/docs/functions/encodeLengthDelimited.html +1 -1
- package/docs/functions/fillModeToProtoFillMode.html +1 -1
- package/docs/functions/findMarket.html +1 -1
- package/docs/functions/findToken.html +1 -1
- package/docs/functions/makeWalletSignFn.html +1 -1
- package/docs/functions/optExpect.html +1 -1
- package/docs/functions/optMap.html +1 -1
- package/docs/functions/optUnwrap.html +1 -1
- package/docs/functions/panic.html +1 -1
- package/docs/functions/signAction.html +1 -1
- package/docs/functions/toScaledU128.html +1 -1
- package/docs/functions/toScaledU64.html +1 -1
- package/docs/interfaces/Account.html +2 -2
- package/docs/interfaces/ActionInfo.html +2 -2
- package/docs/interfaces/ActionQuery.html +2 -2
- package/docs/interfaces/ActionResponse.html +2 -2
- package/docs/interfaces/ActionsExtendedInfo.html +2 -2
- package/docs/interfaces/ActionsQuery.html +2 -2
- package/docs/interfaces/ActionsResponse.html +2 -2
- package/docs/interfaces/AggregateMetrics.html +2 -2
- package/docs/interfaces/BlockQuery.html +2 -2
- package/docs/interfaces/BlockResponse.html +2 -2
- package/docs/interfaces/BlockSummary.html +2 -2
- package/docs/interfaces/BlockSummaryResponse.html +2 -2
- package/docs/interfaces/DeltaEvent.html +2 -2
- package/docs/interfaces/ERC20TokenInfo.html +2 -2
- package/docs/interfaces/Info.html +2 -2
- package/docs/interfaces/Market.html +2 -2
- package/docs/interfaces/MarketStats.html +2 -2
- package/docs/interfaces/MarketsStatsResponse.html +2 -2
- package/docs/interfaces/NordConfig.html +2 -2
- package/docs/interfaces/Order.html +2 -2
- package/docs/interfaces/OrderInfo.html +2 -2
- package/docs/interfaces/PerpMarketStats.html +2 -2
- package/docs/interfaces/RollmanActionExtendedInfo.html +2 -2
- package/docs/interfaces/RollmanActionInfo.html +2 -2
- package/docs/interfaces/RollmanActionResponse.html +2 -2
- package/docs/interfaces/RollmanActionsResponse.html +2 -2
- package/docs/interfaces/RollmanBlockResponse.html +2 -2
- package/docs/interfaces/SubscriberConfig.html +2 -2
- package/docs/interfaces/Token.html +2 -2
- package/docs/interfaces/Trade.html +2 -2
- package/docs/interfaces/Trades.html +2 -2
- package/docs/modules.html +0 -7
- package/docs/types/BigIntValue.html +1 -1
- package/docs/variables/DEBUG_KEYS.html +1 -1
- package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -1
- package/docs/variables/DEV_CONTRACT_ADDRESS.html +1 -1
- package/docs/variables/DEV_TOKEN_INFOS.html +1 -1
- package/docs/variables/DEV_URL.html +1 -1
- package/docs/variables/ERC20_ABI.html +1 -1
- package/docs/variables/EVM_DEV_URL.html +1 -1
- package/docs/variables/FAUCET_PRIVATE_ADDRESS.html +1 -1
- package/docs/variables/MAX_BUFFER_LEN.html +1 -1
- package/docs/variables/NORD_GETTERS_FACET_ABI.html +1 -1
- package/docs/variables/NORD_RAMP_FACET_ABI.html +1 -1
- package/docs/variables/SESSION_TTL.html +1 -1
- package/docs/variables/WEBSERVER_DEV_URL.html +1 -1
- package/docs/variables/ZERO_DECIMAL.html +1 -1
- package/package.json +10 -12
- package/src/bridge/client.ts +487 -0
- package/src/bridge/const.ts +53 -0
- package/src/bridge/index.ts +7 -0
- package/src/bridge/types.ts +127 -0
- package/src/bridge/utils.ts +140 -0
- package/src/const.ts +20 -25
- package/src/gen/common.ts +27 -10
- package/src/gen/nord.ts +1044 -483
- package/src/idl/bridge.ts +702 -0
- package/src/index.ts +24 -5
- package/src/nord/{actions.ts → api/actions.ts} +33 -37
- package/src/nord/api/core.ts +130 -0
- package/src/nord/api/market.ts +125 -0
- package/src/nord/api/metrics.ts +154 -0
- package/src/nord/api/queries.ts +236 -0
- package/src/nord/client/Nord.ts +652 -0
- package/src/nord/client/NordUser.ts +1105 -0
- package/src/nord/index.ts +16 -2
- package/src/nord/models/Subscriber.ts +57 -0
- package/src/nord/utils/NordError.ts +72 -0
- package/src/types.ts +170 -99
- package/src/utils.ts +40 -19
- package/src/websocket/NordWebSocketClient.ts +432 -0
- package/src/websocket/events.ts +31 -0
- package/src/websocket/index.ts +2 -0
- package/tests/utils.spec.ts +24 -24
- package/docs/classes/Subscriber.html +0 -6
- package/docs/functions/createWebSocketSubscription.html +0 -12
- package/docs/interfaces/OrderbookOrder.html +0 -6
- package/docs/interfaces/OrderbookResponse.html +0 -10
- package/docs/interfaces/TradeInfo.html +0 -20
- package/docs/interfaces/TradesQueryParams.html +0 -10
- package/docs/interfaces/TradesResponse.html +0 -12
- package/src/abis/ERC20_ABI.ts +0 -310
- package/src/abis/NORD_GETTERS_FACET_ABI.ts +0 -192
- package/src/abis/NORD_RAMP_FACET_ABI.ts +0 -141
- package/src/abis/index.ts +0 -3
- package/src/nord/Nord.ts +0 -504
- package/src/nord/NordImpl.ts +0 -8
- package/src/nord/NordUser.ts +0 -469
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import {
|
|
4
|
+
WebSocketMessage,
|
|
5
|
+
WebSocketMessageType,
|
|
6
|
+
WebSocketSubscription,
|
|
7
|
+
WebSocketTradeUpdate,
|
|
8
|
+
WebSocketDeltaUpdate,
|
|
9
|
+
WebSocketUserUpdate,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import { NordWebSocketClientEvents } from './events';
|
|
12
|
+
|
|
13
|
+
// Define a type that works for both Node.js ws and browser WebSocket
|
|
14
|
+
type BrowserWebSocket = {
|
|
15
|
+
OPEN: number;
|
|
16
|
+
CONNECTING: number;
|
|
17
|
+
CLOSING: number;
|
|
18
|
+
CLOSED: number;
|
|
19
|
+
readyState: number;
|
|
20
|
+
send: (data: string) => void;
|
|
21
|
+
close: () => void;
|
|
22
|
+
onopen: ((this: any, ev: any) => any) | null;
|
|
23
|
+
onmessage: ((this: any, ev: { data: any }) => any) | null;
|
|
24
|
+
onclose: ((this: any, ev: any) => any) | null;
|
|
25
|
+
onerror: ((this: any, ev: any) => any) | null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type WebSocketInstance = WebSocket | BrowserWebSocket;
|
|
29
|
+
|
|
30
|
+
const VALID_STREAM_TYPES = ['trades', 'deltas', 'user'];
|
|
31
|
+
|
|
32
|
+
// Constants for WebSocket readyState
|
|
33
|
+
const WS_OPEN = 1;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* WebSocket client for Nord exchange
|
|
37
|
+
*
|
|
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
|
+
*
|
|
43
|
+
* Each endpoint handles a specific type of data and subscriptions must match
|
|
44
|
+
* the endpoint type (e.g., only 'trades@BTCUSDC' subscriptions are valid on
|
|
45
|
+
* the /ws/trades endpoint).
|
|
46
|
+
*/
|
|
47
|
+
export class NordWebSocketClient
|
|
48
|
+
extends EventEmitter
|
|
49
|
+
implements NordWebSocketClientEvents
|
|
50
|
+
{
|
|
51
|
+
private ws: WebSocketInstance | null = null;
|
|
52
|
+
private url: string;
|
|
53
|
+
private subscriptions: Set<string> = new Set();
|
|
54
|
+
private reconnectAttempts: number = 0;
|
|
55
|
+
private maxReconnectAttempts: number = 5;
|
|
56
|
+
private reconnectDelay: number = 1000;
|
|
57
|
+
private pingInterval: NodeJS.Timeout | null = null;
|
|
58
|
+
private pingTimeout: NodeJS.Timeout | null = null;
|
|
59
|
+
private isBrowser: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a new NordWebSocketClient
|
|
63
|
+
* @param url WebSocket server URL
|
|
64
|
+
*/
|
|
65
|
+
constructor(url: string) {
|
|
66
|
+
super();
|
|
67
|
+
this.url = url;
|
|
68
|
+
// Check if we're in a browser environment
|
|
69
|
+
// The most reliable way is to check for Node.js process
|
|
70
|
+
this.isBrowser =
|
|
71
|
+
typeof process === 'undefined' ||
|
|
72
|
+
!process.versions ||
|
|
73
|
+
!process.versions.node;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Validate stream format
|
|
78
|
+
* @param stream Stream identifier to validate
|
|
79
|
+
* @throws Error if stream format is invalid
|
|
80
|
+
*/
|
|
81
|
+
private validateStream(stream: string): void {
|
|
82
|
+
const [type, params] = stream.split('@');
|
|
83
|
+
|
|
84
|
+
if (!type || !params) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Invalid stream format: ${stream}. Expected format: <type>@<params>`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Extract the endpoint from the URL
|
|
91
|
+
const urlPath = new URL(this.url).pathname;
|
|
92
|
+
const endpoint = urlPath.split('/').pop();
|
|
93
|
+
|
|
94
|
+
// Ensure the stream type matches the endpoint we're connected to
|
|
95
|
+
if (endpoint && type !== endpoint) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Stream type '${type}' doesn't match the connected endpoint '${endpoint}'`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!VALID_STREAM_TYPES.includes(type)) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Invalid stream type: ${type}. Valid types are: ${VALID_STREAM_TYPES.join(', ')}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (type === 'user' && !/^\d+$/.test(params)) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Invalid user ID in stream: ${params}. Expected numeric ID`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Setup WebSocket ping/pong heartbeat
|
|
116
|
+
*/
|
|
117
|
+
private setupHeartbeat(): void {
|
|
118
|
+
if (this.pingInterval) {
|
|
119
|
+
clearInterval(this.pingInterval);
|
|
120
|
+
}
|
|
121
|
+
if (this.pingTimeout) {
|
|
122
|
+
clearTimeout(this.pingTimeout);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// In browser, we rely on the browser's WebSocket implementation to handle ping/pong
|
|
126
|
+
if (this.isBrowser) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.pingInterval = setInterval(() => {
|
|
131
|
+
if (this.ws && !this.isBrowser) {
|
|
132
|
+
// Only use ping() method in Node.js environment
|
|
133
|
+
(this.ws as WebSocket).ping();
|
|
134
|
+
|
|
135
|
+
// Set timeout for pong response
|
|
136
|
+
this.pingTimeout = setTimeout(() => {
|
|
137
|
+
this.emit('error', new Error('WebSocket ping timeout'));
|
|
138
|
+
this.close();
|
|
139
|
+
this.reconnect();
|
|
140
|
+
}, 5000); // 5 second timeout
|
|
141
|
+
}
|
|
142
|
+
}, 30000); // Send ping every 30 seconds
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get the appropriate WebSocket class based on environment
|
|
147
|
+
*/
|
|
148
|
+
private getWebSocketClass(): any {
|
|
149
|
+
if (this.isBrowser) {
|
|
150
|
+
// In browser environments
|
|
151
|
+
// @ts-ignore - Check for WebSocket in globalThis
|
|
152
|
+
if (typeof globalThis !== 'undefined' && globalThis.WebSocket) {
|
|
153
|
+
// @ts-ignore - Return WebSocket from globalThis
|
|
154
|
+
return globalThis.WebSocket;
|
|
155
|
+
}
|
|
156
|
+
throw new Error('WebSocket is not available in this environment');
|
|
157
|
+
} else {
|
|
158
|
+
// In Node.js
|
|
159
|
+
return WebSocket;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Connect to the Nord WebSocket server
|
|
165
|
+
*/
|
|
166
|
+
public connect(): void {
|
|
167
|
+
if (this.ws) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const WebSocketClass = this.getWebSocketClass();
|
|
173
|
+
|
|
174
|
+
if (this.isBrowser) {
|
|
175
|
+
// Browser WebSocket setup
|
|
176
|
+
this.ws = new WebSocketClass(this.url) as BrowserWebSocket;
|
|
177
|
+
|
|
178
|
+
(this.ws as BrowserWebSocket).onopen = () => {
|
|
179
|
+
this.emit('connected');
|
|
180
|
+
this.reconnectAttempts = 0;
|
|
181
|
+
this.reconnectDelay = 1000;
|
|
182
|
+
|
|
183
|
+
// Resubscribe to previous subscriptions
|
|
184
|
+
if (this.subscriptions.size > 0) {
|
|
185
|
+
this.subscribe([...this.subscriptions]);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
(this.ws as BrowserWebSocket).onmessage = (event: { data: any }) => {
|
|
190
|
+
try {
|
|
191
|
+
const message = JSON.parse(
|
|
192
|
+
event.data as string,
|
|
193
|
+
) as WebSocketMessage;
|
|
194
|
+
this.handleMessage(message);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
this.emit(
|
|
197
|
+
'error',
|
|
198
|
+
new Error(
|
|
199
|
+
`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`,
|
|
200
|
+
),
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
(this.ws as BrowserWebSocket).onclose = (event: any) => {
|
|
206
|
+
const reason =
|
|
207
|
+
event && event.reason ? ` Reason: ${event.reason}` : '';
|
|
208
|
+
const code = event && event.code ? ` Code: ${event.code}` : '';
|
|
209
|
+
this.emit('disconnected');
|
|
210
|
+
console.log(`WebSocket closed.${code}${reason}`);
|
|
211
|
+
this.reconnect();
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
(this.ws as BrowserWebSocket).onerror = (event: any) => {
|
|
215
|
+
const errorMsg = `WebSocket error: ${event && event.type ? event.type : 'unknown'}`;
|
|
216
|
+
console.error(errorMsg, event);
|
|
217
|
+
this.emit('error', new Error(errorMsg));
|
|
218
|
+
};
|
|
219
|
+
} else {
|
|
220
|
+
// Node.js WebSocket setup
|
|
221
|
+
const nodeWs = new WebSocketClass(this.url) as WebSocket;
|
|
222
|
+
this.ws = nodeWs;
|
|
223
|
+
|
|
224
|
+
nodeWs.on('open', () => {
|
|
225
|
+
this.emit('connected');
|
|
226
|
+
this.reconnectAttempts = 0;
|
|
227
|
+
this.reconnectDelay = 1000;
|
|
228
|
+
this.setupHeartbeat();
|
|
229
|
+
|
|
230
|
+
// Resubscribe to previous subscriptions
|
|
231
|
+
if (this.subscriptions.size > 0) {
|
|
232
|
+
this.subscribe([...this.subscriptions]);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
nodeWs.on('message', (data: WebSocket.Data) => {
|
|
237
|
+
try {
|
|
238
|
+
const message = JSON.parse(data.toString()) as WebSocketMessage;
|
|
239
|
+
this.handleMessage(message);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
this.emit(
|
|
242
|
+
'error',
|
|
243
|
+
new Error(
|
|
244
|
+
`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`,
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
nodeWs.on('close', (code: number, reason: string) => {
|
|
251
|
+
this.emit('disconnected');
|
|
252
|
+
console.log(`WebSocket closed. Code: ${code} Reason: ${reason}`);
|
|
253
|
+
if (this.pingInterval) {
|
|
254
|
+
clearInterval(this.pingInterval);
|
|
255
|
+
}
|
|
256
|
+
if (this.pingTimeout) {
|
|
257
|
+
clearTimeout(this.pingTimeout);
|
|
258
|
+
}
|
|
259
|
+
this.reconnect();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
nodeWs.on('error', (error: Error) => {
|
|
263
|
+
console.error('WebSocket error:', error);
|
|
264
|
+
this.emit('error', error);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
nodeWs.on('pong', () => {
|
|
268
|
+
if (this.pingTimeout) {
|
|
269
|
+
clearTimeout(this.pingTimeout);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
} catch (error) {
|
|
274
|
+
const errorMsg = `Failed to initialize WebSocket: ${error instanceof Error ? error.message : String(error)}`;
|
|
275
|
+
console.error(errorMsg);
|
|
276
|
+
this.emit('error', new Error(errorMsg));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Subscribe to one or more streams
|
|
282
|
+
* @param streams Array of streams to subscribe to (e.g. ["trades@BTCUSDC", "deltas@BTCUSDC"])
|
|
283
|
+
*/
|
|
284
|
+
public subscribe(streams: string[]): void {
|
|
285
|
+
// Validate all streams first
|
|
286
|
+
try {
|
|
287
|
+
streams.forEach((stream) => this.validateStream(stream));
|
|
288
|
+
} catch (error) {
|
|
289
|
+
this.emit(
|
|
290
|
+
'error',
|
|
291
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
292
|
+
);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (
|
|
297
|
+
!this.ws ||
|
|
298
|
+
(this.isBrowser
|
|
299
|
+
? (this.ws as BrowserWebSocket).readyState !== WS_OPEN
|
|
300
|
+
: (this.ws as WebSocket).readyState !== WebSocket.OPEN)
|
|
301
|
+
) {
|
|
302
|
+
streams.forEach((stream) => this.subscriptions.add(stream));
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const message: WebSocketSubscription = {
|
|
307
|
+
type: WebSocketMessageType.Subscribe,
|
|
308
|
+
streams,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
const messageStr = JSON.stringify(message);
|
|
313
|
+
if (this.isBrowser) {
|
|
314
|
+
(this.ws as BrowserWebSocket).send(messageStr);
|
|
315
|
+
} else {
|
|
316
|
+
(this.ws as WebSocket).send(messageStr);
|
|
317
|
+
}
|
|
318
|
+
streams.forEach((stream) => this.subscriptions.add(stream));
|
|
319
|
+
} catch (error) {
|
|
320
|
+
this.emit(
|
|
321
|
+
'error',
|
|
322
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Unsubscribe from one or more streams
|
|
329
|
+
* @param streams Array of streams to unsubscribe from
|
|
330
|
+
*/
|
|
331
|
+
public unsubscribe(streams: string[]): void {
|
|
332
|
+
// Validate all streams first
|
|
333
|
+
try {
|
|
334
|
+
streams.forEach((stream) => this.validateStream(stream));
|
|
335
|
+
} catch (error) {
|
|
336
|
+
this.emit(
|
|
337
|
+
'error',
|
|
338
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
339
|
+
);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (
|
|
344
|
+
!this.ws ||
|
|
345
|
+
(this.isBrowser
|
|
346
|
+
? (this.ws as BrowserWebSocket).readyState !== WS_OPEN
|
|
347
|
+
: (this.ws as WebSocket).readyState !== WebSocket.OPEN)
|
|
348
|
+
) {
|
|
349
|
+
streams.forEach((stream) => this.subscriptions.delete(stream));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const message: WebSocketSubscription = {
|
|
354
|
+
type: WebSocketMessageType.Unsubscribe,
|
|
355
|
+
streams,
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
try {
|
|
359
|
+
const messageStr = JSON.stringify(message);
|
|
360
|
+
if (this.isBrowser) {
|
|
361
|
+
(this.ws as BrowserWebSocket).send(messageStr);
|
|
362
|
+
} else {
|
|
363
|
+
(this.ws as WebSocket).send(messageStr);
|
|
364
|
+
}
|
|
365
|
+
streams.forEach((stream) => this.subscriptions.delete(stream));
|
|
366
|
+
} catch (error) {
|
|
367
|
+
this.emit(
|
|
368
|
+
'error',
|
|
369
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Close the WebSocket connection
|
|
376
|
+
*/
|
|
377
|
+
public close(): void {
|
|
378
|
+
if (this.ws) {
|
|
379
|
+
if (this.isBrowser) {
|
|
380
|
+
(this.ws as BrowserWebSocket).close();
|
|
381
|
+
} else {
|
|
382
|
+
(this.ws as WebSocket).close();
|
|
383
|
+
}
|
|
384
|
+
this.ws = null;
|
|
385
|
+
}
|
|
386
|
+
if (this.pingInterval) {
|
|
387
|
+
clearInterval(this.pingInterval);
|
|
388
|
+
this.pingInterval = null;
|
|
389
|
+
}
|
|
390
|
+
if (this.pingTimeout) {
|
|
391
|
+
clearTimeout(this.pingTimeout);
|
|
392
|
+
this.pingTimeout = null;
|
|
393
|
+
}
|
|
394
|
+
this.subscriptions.clear();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Handle incoming WebSocket messages
|
|
399
|
+
* @param message WebSocket message
|
|
400
|
+
*/
|
|
401
|
+
private handleMessage(message: WebSocketMessage): void {
|
|
402
|
+
switch (message.type) {
|
|
403
|
+
case WebSocketMessageType.TradeUpdate:
|
|
404
|
+
this.emit('trade', message as WebSocketTradeUpdate);
|
|
405
|
+
break;
|
|
406
|
+
case WebSocketMessageType.DeltaUpdate:
|
|
407
|
+
this.emit('delta', message as WebSocketDeltaUpdate);
|
|
408
|
+
break;
|
|
409
|
+
case WebSocketMessageType.UserUpdate:
|
|
410
|
+
this.emit('user', message as WebSocketUserUpdate);
|
|
411
|
+
break;
|
|
412
|
+
default:
|
|
413
|
+
this.emit('error', new Error(`Unknown message type: ${message.type}`));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Attempt to reconnect to the WebSocket server
|
|
419
|
+
*/
|
|
420
|
+
private reconnect(): void {
|
|
421
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
422
|
+
this.emit('error', new Error('Max reconnection attempts reached'));
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
setTimeout(() => {
|
|
427
|
+
this.reconnectAttempts++;
|
|
428
|
+
this.reconnectDelay *= 2; // Exponential backoff
|
|
429
|
+
this.connect();
|
|
430
|
+
}, this.reconnectDelay);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WebSocketTradeUpdate,
|
|
3
|
+
WebSocketDeltaUpdate,
|
|
4
|
+
WebSocketUserUpdate,
|
|
5
|
+
} from '../types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Event type definitions for the NordWebSocketClient
|
|
9
|
+
*/
|
|
10
|
+
export interface NordWebSocketEvents {
|
|
11
|
+
connected: () => void;
|
|
12
|
+
disconnected: () => void;
|
|
13
|
+
error: (error: Error) => void;
|
|
14
|
+
trade: (update: WebSocketTradeUpdate) => void;
|
|
15
|
+
delta: (update: WebSocketDeltaUpdate) => void;
|
|
16
|
+
user: (update: WebSocketUserUpdate) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Type declaration for NordWebSocketClient event methods
|
|
21
|
+
*/
|
|
22
|
+
export declare interface NordWebSocketClientEvents {
|
|
23
|
+
on<E extends keyof NordWebSocketEvents>(
|
|
24
|
+
event: E,
|
|
25
|
+
listener: NordWebSocketEvents[E],
|
|
26
|
+
): this;
|
|
27
|
+
emit<E extends keyof NordWebSocketEvents>(
|
|
28
|
+
event: E,
|
|
29
|
+
...args: Parameters<NordWebSocketEvents[E]>
|
|
30
|
+
): boolean;
|
|
31
|
+
}
|
package/tests/utils.spec.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { describe, it, expect } from
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
2
2
|
import {
|
|
3
3
|
bigIntToProtoU128,
|
|
4
4
|
toScaledU64,
|
|
5
5
|
toScaledU128,
|
|
6
6
|
encodeLengthDelimited,
|
|
7
7
|
decodeLengthDelimited,
|
|
8
|
-
} from
|
|
9
|
-
import Decimal from
|
|
10
|
-
import * as proto from
|
|
8
|
+
} from '../src/utils';
|
|
9
|
+
import Decimal from 'decimal.js';
|
|
10
|
+
import * as proto from '../src/gen/nord';
|
|
11
11
|
|
|
12
|
-
describe(
|
|
12
|
+
describe('toScaledU64', () => {
|
|
13
13
|
// Used as scaling medium
|
|
14
14
|
const D64 = Decimal.clone({
|
|
15
15
|
precision: 20,
|
|
@@ -35,12 +35,12 @@ describe("toScaledU64", () => {
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
const failure: Array<[Decimal.Value, number, string]> = [
|
|
38
|
-
[-1, 0,
|
|
39
|
-
[-1000, 2,
|
|
40
|
-
[0.1, 0,
|
|
41
|
-
[0.0001, 3,
|
|
42
|
-
[MaxDec.add(1), 0,
|
|
43
|
-
[MaxDec.add(1).div(1000), 3,
|
|
38
|
+
[-1, 0, 'Number is negative'],
|
|
39
|
+
[-1000, 2, 'Number is negative'],
|
|
40
|
+
[0.1, 0, 'Precision loss'],
|
|
41
|
+
[0.0001, 3, 'Precision loss'],
|
|
42
|
+
[MaxDec.add(1), 0, 'Integer is out of range'],
|
|
43
|
+
[MaxDec.add(1).div(1000), 3, 'Integer is out of range'],
|
|
44
44
|
];
|
|
45
45
|
|
|
46
46
|
failure.forEach((sample) => {
|
|
@@ -50,7 +50,7 @@ describe("toScaledU64", () => {
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
describe(
|
|
53
|
+
describe('toScaledU128', () => {
|
|
54
54
|
// Used as scaling medium
|
|
55
55
|
const D128 = Decimal.clone({
|
|
56
56
|
precision: 40,
|
|
@@ -76,12 +76,12 @@ describe("toScaledU128", () => {
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
const failure: Array<[Decimal.Value, number, string]> = [
|
|
79
|
-
[-1, 0,
|
|
80
|
-
[-1000, 2,
|
|
81
|
-
[0.1, 0,
|
|
82
|
-
[0.0001, 3,
|
|
83
|
-
[MaxDec.add(1), 0,
|
|
84
|
-
[MaxDec.add(1).div(1000), 3,
|
|
79
|
+
[-1, 0, 'Number is negative'],
|
|
80
|
+
[-1000, 2, 'Number is negative'],
|
|
81
|
+
[0.1, 0, 'Precision loss'],
|
|
82
|
+
[0.0001, 3, 'Precision loss'],
|
|
83
|
+
[MaxDec.add(1), 0, 'Integer is out of range'],
|
|
84
|
+
[MaxDec.add(1).div(1000), 3, 'Integer is out of range'],
|
|
85
85
|
];
|
|
86
86
|
|
|
87
87
|
failure.forEach((sample) => {
|
|
@@ -94,7 +94,7 @@ describe("toScaledU128", () => {
|
|
|
94
94
|
const U64_MAX = (1n << 64n) - 1n;
|
|
95
95
|
const U128_MAX = (1n << 128n) - 1n;
|
|
96
96
|
|
|
97
|
-
describe(
|
|
97
|
+
describe('bigIntToProtoU128', () => {
|
|
98
98
|
const success: Array<[bigint, { lo: bigint; hi: bigint }]> = [
|
|
99
99
|
[0n, { lo: 0n, hi: 0n }],
|
|
100
100
|
[1n, { lo: 1n, hi: 0n }],
|
|
@@ -112,8 +112,8 @@ describe("bigIntToProtoU128", () => {
|
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
const failure: Array<[bigint, string]> = [
|
|
115
|
-
[-1n,
|
|
116
|
-
[U128_MAX + 1n,
|
|
115
|
+
[-1n, 'Negative number'],
|
|
116
|
+
[U128_MAX + 1n, 'U128 overflow'],
|
|
117
117
|
];
|
|
118
118
|
|
|
119
119
|
failure.forEach((sample, index) => {
|
|
@@ -123,12 +123,12 @@ describe("bigIntToProtoU128", () => {
|
|
|
123
123
|
});
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
describe(
|
|
126
|
+
describe('proto.Action encode-decode loop', () => {
|
|
127
127
|
const action: proto.Action = {
|
|
128
128
|
currentTimestamp: 0n,
|
|
129
129
|
nonce: 0,
|
|
130
130
|
kind: {
|
|
131
|
-
$case:
|
|
131
|
+
$case: 'placeOrder',
|
|
132
132
|
value: {
|
|
133
133
|
sessionId: 42n,
|
|
134
134
|
marketId: 9,
|
|
@@ -145,7 +145,7 @@ describe("proto.Action encode-decode loop", () => {
|
|
|
145
145
|
},
|
|
146
146
|
};
|
|
147
147
|
|
|
148
|
-
it(
|
|
148
|
+
it('action encode-decode roundabout should succeed', () => {
|
|
149
149
|
const encoded = encodeLengthDelimited(action, proto.Action);
|
|
150
150
|
const decoded: proto.Action = decodeLengthDelimited(encoded, proto.Action);
|
|
151
151
|
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>Subscriber | @layer-n/nord-ts</title><meta name="description" content="Documentation for @layer-n/nord-ts"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@layer-n/nord-ts</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">@layer-n/nord-ts</a></li><li><a href="Subscriber.html">Subscriber</a></li></ul><h1>Class Subscriber</h1></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L454">nord/Nord.ts:454</a></li></ul></aside><section class="tsd-panel-group tsd-index-group"><section class="tsd-panel tsd-index-panel"><details class="tsd-index-content tsd-index-accordion" open><summary class="tsd-accordion-summary tsd-index-summary"><h5 class="tsd-index-heading uppercase" role="button" aria-expanded="false" tabIndex="0"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-chevronSmall"></use></svg> Index</h5></summary><div class="tsd-accordion-details"><section class="tsd-index-section"><h3 class="tsd-index-heading">Constructors</h3><div class="tsd-index-list"><a href="Subscriber.html#constructor" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-512"></use></svg><span>constructor</span></a>
|
|
2
|
-
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Properties</h3><div class="tsd-index-list"><a href="Subscriber.html#buffer" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>buffer</span></a>
|
|
3
|
-
<a href="Subscriber.html#maxBufferLen" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>max<wbr/>Buffer<wbr/>Len</span></a>
|
|
4
|
-
<a href="Subscriber.html#streamURL" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>streamURL</span></a>
|
|
5
|
-
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Methods</h3><div class="tsd-index-list"><a href="Subscriber.html#subscribe" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-2048"></use></svg><span>subscribe</span></a>
|
|
6
|
-
</div></section></div></details></section></section><section class="tsd-panel-group tsd-member-group"><h2>Constructors</h2><section class="tsd-panel tsd-member"><a id="constructor" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>constructor</span><a href="#constructor" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="constructor.new_Subscriber" class="tsd-anchor"></a><span class="tsd-kind-constructor-signature">new <wbr/>Subscriber</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">config</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="Subscriber.html" class="tsd-signature-type tsd-kind-class">Subscriber</a><a href="#constructor.new_Subscriber" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">config</span>: <a href="../interfaces/SubscriberConfig.html" class="tsd-signature-type tsd-kind-interface">SubscriberConfig</a></span></li></ul></div><h4 class="tsd-returns-title">Returns <a href="Subscriber.html" class="tsd-signature-type tsd-kind-class">Subscriber</a></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L459">nord/Nord.ts:459</a></li></ul></aside></li></ul></section></section><section class="tsd-panel-group tsd-member-group"><h2>Properties</h2><section class="tsd-panel tsd-member"><a id="buffer" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>buffer</span><a href="#buffer" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">buffer</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><a href="../interfaces/DeltaEvent.html" class="tsd-signature-type tsd-kind-interface">DeltaEvent</a><span class="tsd-signature-symbol"> | </span><a href="../interfaces/Trades.html" class="tsd-signature-type tsd-kind-interface">Trades</a><span class="tsd-signature-symbol"> | </span><a href="../interfaces/Account.html" class="tsd-signature-type tsd-kind-interface">Account</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">[]</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L456">nord/Nord.ts:456</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="maxBufferLen" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>max<wbr/>Buffer<wbr/>Len</span><a href="#maxBufferLen" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">max<wbr/>Buffer<wbr/>Len</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L457">nord/Nord.ts:457</a></li></ul></aside></section><section class="tsd-panel tsd-member"><a id="streamURL" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>streamURL</span><a href="#streamURL" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">streamURL</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L455">nord/Nord.ts:455</a></li></ul></aside></section></section><section class="tsd-panel-group tsd-member-group"><h2>Methods</h2><section class="tsd-panel tsd-member"><a id="subscribe" class="tsd-anchor"></a><h3 class="tsd-anchor-link"><span>subscribe</span><a href="#subscribe" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="subscribe.subscribe-1" class="tsd-anchor"></a><span class="tsd-kind-call-signature">subscribe</span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span><a href="#subscribe.subscribe-1" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L465">nord/Nord.ts:465</a></li></ul></aside></li></ul></section></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-index-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><h4 class="uppercase">Member Visibility</h4><form><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-private" name="private"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Private</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></form></div><div class="tsd-theme-toggle"><h4 class="uppercase">Theme</h4><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-index-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#constructor" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-512"></use></svg><span>constructor</span></a><a href="#buffer" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>buffer</span></a><a href="#maxBufferLen" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>max<wbr/>Buffer<wbr/>Len</span></a><a href="#streamURL" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1024"></use></svg><span>streamURL</span></a><a href="#subscribe" class=""><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-2048"></use></svg><span>subscribe</span></a></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1"></use></svg><span>@layer-n/nord-ts</span></a><ul class="tsd-small-nested-navigation" id="tsd-nav-container" data-base=".."><li>Loading...</li></ul></nav></div></div></div><div class="tsd-generator"><p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></div><div class="overlay"></div></body></html>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>createWebSocketSubscription | @layer-n/nord-ts</title><meta name="description" content="Documentation for @layer-n/nord-ts"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search" data-base=".."><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@layer-n/nord-ts</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../modules.html">@layer-n/nord-ts</a></li><li><a href="createWebSocketSubscription.html">createWebSocketSubscription</a></li></ul><h1>Function createWebSocketSubscription</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="createWebSocketSubscription" class="tsd-anchor"></a><span class="tsd-kind-call-signature">create<wbr/>Web<wbr/>Socket<wbr/>Subscription</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">baseUrl</span>, <span class="tsd-kind-parameter">streams</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><a href="../classes/Subscriber.html" class="tsd-signature-type tsd-kind-class">Subscriber</a><a href="#createWebSocketSubscription" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li class="tsd-description"><div class="tsd-comment tsd-typography"><p>Creates a WebSocket subscription to specified streams</p>
|
|
2
|
-
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">baseUrl</span>: <span class="tsd-signature-type">string</span></span><div class="tsd-comment tsd-typography"><p>Base URL of the API</p>
|
|
3
|
-
</div><div class="tsd-comment tsd-typography"></div></li><li><span><span class="tsd-kind-parameter">streams</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">[]</span></span><div class="tsd-comment tsd-typography"><p>Array of streams to subscribe to</p>
|
|
4
|
-
</div><div class="tsd-comment tsd-typography"></div></li></ul></div><h4 class="tsd-returns-title">Returns <a href="../classes/Subscriber.html" class="tsd-signature-type tsd-kind-class">Subscriber</a></h4><p>A Subscriber instance</p>
|
|
5
|
-
<p>Syntax for streams:</p>
|
|
6
|
-
<ul>
|
|
7
|
-
<li>trades@<symbol>: Subscribe to trades for a market</li>
|
|
8
|
-
<li>deltas@<symbol>: Subscribe to orderbook deltas for a market</li>
|
|
9
|
-
<li>user@<user id>: Subscribe to user account updates</li>
|
|
10
|
-
</ul>
|
|
11
|
-
<p>Example: createWebSocketSubscription('<a href="https://alpha-api.layern.network">https://alpha-api.layern.network</a>', ['trades@BTCUSDC', 'deltas@BTCUSDC', 'user@0'])</p>
|
|
12
|
-
<div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/n1xyz/nord-ts/blob/381766a/src/nord/Nord.ts#L494">nord/Nord.ts:494</a></li></ul></aside></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-index-accordion"><summary class="tsd-accordion-summary"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><h4 class="uppercase">Member Visibility</h4><form><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-private" name="private"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Private</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></form></div><div class="tsd-theme-toggle"><h4 class="uppercase">Theme</h4><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="../assets/icons.svg#icon-1"></use></svg><span>@layer-n/nord-ts</span></a><ul class="tsd-small-nested-navigation" id="tsd-nav-container" data-base=".."><li>Loading...</li></ul></nav></div></div></div><div class="tsd-generator"><p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></div><div class="overlay"></div></body></html>
|