@n1xyz/nord-ts 0.0.12 → 0.0.15
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/.prettierignore +1 -0
- package/README.md +9 -6
- package/dist/bridge/client.d.ts +8 -7
- package/dist/bridge/client.js +38 -37
- package/dist/bridge/index.d.ts +1 -2
- package/dist/bridge/index.js +2 -2
- package/dist/bridge/types.d.ts +5 -3
- package/dist/bridge/types.js +3 -1
- package/dist/gen/nord.d.ts +66 -5
- package/dist/gen/nord.js +449 -22
- package/dist/idl/bridge.json +1493 -0
- package/dist/idl/index.d.ts +585 -0
- package/dist/idl/index.js +8 -0
- package/dist/nord/api/core.d.ts +8 -8
- package/dist/nord/api/core.js +58 -15
- package/dist/nord/api/metrics.js +7 -4
- package/dist/nord/client/Nord.d.ts +57 -72
- package/dist/nord/client/Nord.js +134 -125
- package/dist/nord/client/NordUser.d.ts +0 -17
- package/dist/nord/client/NordUser.js +4 -35
- package/dist/types.d.ts +38 -15
- 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/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Nord.html +99 -100
- package/docs/classes/NordError.html +6 -6
- package/docs/classes/NordUser.html +48 -53
- package/docs/classes/NordWebSocketClient.html +6 -11
- package/docs/classes/SolanaBridgeClient.html +23 -23
- package/docs/classes/Subscriber.html +3 -3
- package/docs/enums/FillMode.html +2 -2
- package/docs/enums/KeyType.html +2 -2
- package/docs/enums/MetricPeriod.html +2 -2
- package/docs/enums/PdaSeedType.html +2 -2
- package/docs/enums/PeakTpsPeriodUnit.html +2 -2
- package/docs/enums/Side.html +2 -2
- package/docs/enums/WebSocketMessageType.html +3 -3
- package/docs/functions/actionQueryRollman.html +1 -1
- package/docs/functions/actionsQueryRollman.html +1 -1
- package/docs/functions/aggregateMetrics-1.html +1 -1
- package/docs/functions/assert.html +1 -1
- package/docs/functions/bigIntToProtoU128.html +1 -1
- package/docs/functions/bridgeToBN.html +1 -1
- package/docs/functions/bufferToHex.html +1 -1
- package/docs/functions/cancelOrder.html +1 -1
- package/docs/functions/checkPubKeyLength.html +1 -1
- package/docs/functions/checkedFetch.html +1 -1
- package/docs/functions/createSession.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/findPda.html +1 -1
- package/docs/functions/findToken.html +1 -1
- package/docs/functions/fromBN.html +1 -1
- package/docs/functions/getAccount.html +1 -1
- package/docs/functions/getActionNonce.html +1 -1
- package/docs/functions/getCurrentTps.html +1 -1
- package/docs/functions/getInfo.html +1 -1
- package/docs/functions/{queryLastNBlocks.html → getLastActionId.html} +3 -3
- package/docs/functions/getMedianLatency.html +1 -1
- package/docs/functions/getOrderbook.html +1 -1
- package/docs/functions/getPeakTps.html +1 -1
- package/docs/functions/getTimestamp.html +1 -1
- package/docs/functions/getTotalTransactions.html +1 -1
- package/docs/functions/getTrades.html +1 -1
- package/docs/functions/getUserAccountIds.html +1 -1
- package/docs/functions/hexToBuffer.html +1 -1
- package/docs/functions/initWebSocketClient.html +9 -9
- package/docs/functions/keypairFromPrivateKey.html +1 -1
- package/docs/functions/makeSigningFunction.html +1 -1
- package/docs/functions/makeWalletSignFn.html +1 -1
- package/docs/functions/marketsStats.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/placeOrder.html +1 -1
- package/docs/functions/queryAction.html +1 -1
- package/docs/functions/queryPrometheus.html +1 -1
- package/docs/functions/queryRecentActions.html +4 -3
- package/docs/functions/revokeSession.html +1 -1
- package/docs/functions/shortenPublicKey.html +1 -1
- package/docs/functions/signAction.html +1 -1
- package/docs/functions/toBN.html +1 -1
- package/docs/functions/toScaledU128.html +1 -1
- package/docs/functions/toScaledU64.html +1 -1
- package/docs/functions/transfer.html +1 -1
- package/docs/functions/withdraw.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +2 -2
- package/docs/interfaces/Account.html +2 -2
- package/docs/interfaces/ActionInfo.html +2 -2
- package/docs/interfaces/ActionNonceResponse.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/BlockFacts.html +5 -5
- 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/DepositSplParams.html +5 -5
- 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 +19 -9
- package/docs/interfaces/NordWebSocketClientEvents.html +2 -2
- package/docs/interfaces/NordWebSocketEvents.html +3 -3
- package/docs/interfaces/Order.html +2 -2
- package/docs/interfaces/OrderInfo.html +2 -2
- package/docs/interfaces/OrderbookEntry.html +2 -2
- package/docs/interfaces/OrderbookQuery.html +2 -2
- package/docs/interfaces/OrderbookResponse.html +2 -2
- package/docs/interfaces/OrderbookSubscription.html +5 -5
- 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/SPLTokenInfo.html +5 -5
- package/docs/interfaces/SolanaBridgeConfig.html +5 -5
- package/docs/interfaces/StateFacts.html +5 -5
- package/docs/interfaces/SubscriberConfig.html +2 -2
- package/docs/interfaces/TimestampResponse.html +2 -2
- package/docs/interfaces/Token.html +2 -2
- package/docs/interfaces/TokenInfo.html +3 -2
- package/docs/interfaces/Trade.html +2 -2
- package/docs/interfaces/TradeSubscription.html +5 -5
- package/docs/interfaces/Trades.html +2 -2
- package/docs/interfaces/TradesQuery.html +2 -2
- package/docs/interfaces/TradesResponse.html +2 -2
- package/docs/interfaces/TransferParams.html +4 -4
- package/docs/interfaces/UserAccountIdsQuery.html +2 -2
- package/docs/interfaces/UserAccountIdsResponse.html +2 -2
- package/docs/interfaces/WebSocketAccountUpdate.html +6 -0
- package/docs/interfaces/WebSocketDeltaUpdate.html +3 -3
- package/docs/interfaces/WebSocketSubscription.html +3 -3
- package/docs/interfaces/WebSocketTradeUpdate.html +3 -3
- package/docs/interfaces/WithdrawalClaim.html +7 -7
- package/docs/interfaces/WithdrawalParams.html +4 -4
- package/docs/modules.html +1 -1
- package/docs/types/BigIntValue.html +1 -1
- package/docs/types/SubscriptionPattern.html +4 -0
- package/docs/types/SubscriptionType.html +2 -0
- package/docs/types/WebSocketMessage.html +1 -1
- package/docs/variables/DEBUG_KEYS.html +1 -1
- package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -1
- package/docs/variables/DEV_TOKEN_INFOS.html +1 -1
- package/docs/variables/DEV_URL.html +1 -1
- package/docs/variables/MAX_BUFFER_LEN.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/docs/variables/_private.html +1 -1
- package/idl-generate.sh +4 -0
- package/package.json +4 -3
- package/src/bridge/client.ts +54 -43
- package/src/bridge/index.ts +1 -2
- package/src/bridge/types.ts +5 -3
- package/src/gen/nord.ts +518 -19
- package/src/idl/bridge.json +1493 -0
- package/src/idl/index.ts +2 -0
- package/src/nord/api/core.ts +70 -20
- package/src/nord/api/metrics.ts +28 -20
- package/src/nord/api/queries.ts +7 -11
- package/src/nord/client/Nord.ts +174 -168
- package/src/nord/client/NordUser.ts +32 -98
- package/src/types.ts +40 -15
- package/src/websocket/NordWebSocketClient.ts +11 -14
- package/src/websocket/events.ts +2 -2
- package/docs/functions/blockQueryRollman.html +0 -6
- package/docs/functions/blockSummaryQueryRollman.html +0 -6
- package/docs/functions/queryBlock.html +0 -6
- package/docs/functions/queryRecentBlocks.html +0 -6
- package/docs/interfaces/WebSocketUserUpdate.html +0 -6
- package/src/idl/bridge.ts +0 -930
- package/test.ts +0 -107
package/dist/nord/client/Nord.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.Nord = void 0;
|
|
37
37
|
const events_1 = require("events");
|
|
38
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
38
39
|
const types_1 = require("../../types");
|
|
39
40
|
const core = __importStar(require("../api/core"));
|
|
40
41
|
const market = __importStar(require("../api/market"));
|
|
@@ -50,74 +51,80 @@ class Nord {
|
|
|
50
51
|
*
|
|
51
52
|
* @param config - Configuration options for the Nord client
|
|
52
53
|
* @param config.webServerUrl - Base URL for the Nord web server
|
|
53
|
-
* @param config.
|
|
54
|
+
* @param config.bridgeVk - Bridge verification key
|
|
54
55
|
* @param config.solanaUrl - Solana cluster URL
|
|
55
|
-
* @param config.initWebSockets - Whether to initialize WebSockets on creation, defaults to true
|
|
56
|
-
* @param config.tradesSubscriptions - Optional array of trades subscriptions to initialize with (e.g., ["trades@BTCUSDC"])
|
|
57
|
-
* @param config.deltasSubscriptions - Optional array of deltas subscriptions to initialize with (e.g., ["deltas@BTCUSDC"])
|
|
58
56
|
* @throws {Error} If required configuration is missing
|
|
59
57
|
*/
|
|
60
|
-
constructor(
|
|
58
|
+
constructor(config) {
|
|
61
59
|
/** Available markets */
|
|
62
60
|
this.markets = [];
|
|
63
61
|
/** Available tokens */
|
|
64
62
|
this.tokens = [];
|
|
65
63
|
/** Map of symbol to market_id */
|
|
66
64
|
this.symbolToMarketId = new Map();
|
|
67
|
-
|
|
68
|
-
* WebSocket client for trades
|
|
69
|
-
* @private
|
|
70
|
-
*/
|
|
71
|
-
this.tradesWs = null;
|
|
72
|
-
/**
|
|
73
|
-
* WebSocket client for orderbook deltas
|
|
74
|
-
* @private
|
|
75
|
-
*/
|
|
76
|
-
this.deltasWs = null;
|
|
77
|
-
/**
|
|
78
|
-
* WebSocket client for user updates
|
|
79
|
-
* @private
|
|
80
|
-
*/
|
|
81
|
-
this.userWs = null;
|
|
82
|
-
if (!webServerUrl) {
|
|
65
|
+
if (!config.webServerUrl) {
|
|
83
66
|
throw new NordError_1.NordError("webServerUrl is required");
|
|
84
67
|
}
|
|
85
|
-
if (!
|
|
86
|
-
throw new NordError_1.NordError("
|
|
68
|
+
if (!config.bridgeVk) {
|
|
69
|
+
throw new NordError_1.NordError("bridgeVk is required");
|
|
87
70
|
}
|
|
88
|
-
if (!solanaUrl) {
|
|
71
|
+
if (!config.solanaUrl) {
|
|
89
72
|
throw new NordError_1.NordError("solanaUrl is required");
|
|
90
73
|
}
|
|
91
|
-
this.webServerUrl = webServerUrl;
|
|
92
|
-
this.
|
|
93
|
-
this.solanaUrl = solanaUrl;
|
|
94
|
-
// Store subscription parameters
|
|
95
|
-
this.tradesSubscriptions = tradesSubscriptions;
|
|
96
|
-
this.deltasSubscriptions = deltasSubscriptions;
|
|
97
|
-
// Initialize WebSocket clients only if initWebSockets is true
|
|
98
|
-
if (initWebSockets) {
|
|
99
|
-
this.initializeWebSockets();
|
|
100
|
-
}
|
|
74
|
+
this.webServerUrl = config.webServerUrl;
|
|
75
|
+
this.bridgeVk = config.bridgeVk;
|
|
76
|
+
this.solanaUrl = config.solanaUrl;
|
|
101
77
|
}
|
|
102
78
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
79
|
+
* Create a WebSocket client with specific subscriptions
|
|
80
|
+
*
|
|
81
|
+
* @param options - Subscription options that specify which data streams to subscribe to
|
|
82
|
+
* @returns A new WebSocket client with the requested subscriptions
|
|
83
|
+
* @throws {NordError} If invalid subscription options are provided
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Create a client for trades and deltas from one market and an account
|
|
87
|
+
* const wsClient = nord.createWebSocketClient({
|
|
88
|
+
* trades: ["BTCUSDC"],
|
|
89
|
+
* deltas: ["BTCUSDC"],
|
|
90
|
+
* accounts: [123]
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Create a client for trades from multiple markets
|
|
95
|
+
* const tradesClient = nord.createWebSocketClient({
|
|
96
|
+
* trades: ["BTCUSDC", "ETHUSDC"]
|
|
97
|
+
* });
|
|
113
98
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
99
|
+
createWebSocketClient(options) {
|
|
100
|
+
const subscriptions = [];
|
|
101
|
+
// Add trade subscriptions
|
|
102
|
+
if (options.trades && options.trades.length > 0) {
|
|
103
|
+
options.trades.forEach((symbol) => {
|
|
104
|
+
subscriptions.push(`trades@${symbol}`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Add delta subscriptions
|
|
108
|
+
if (options.deltas && options.deltas.length > 0) {
|
|
109
|
+
options.deltas.forEach((symbol) => {
|
|
110
|
+
subscriptions.push(`deltas@${symbol}`);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Add account subscriptions
|
|
114
|
+
if (options.accounts && options.accounts.length > 0) {
|
|
115
|
+
options.accounts.forEach((accountId) => {
|
|
116
|
+
if (isNaN(accountId) || accountId <= 0) {
|
|
117
|
+
throw new NordError_1.NordError(`Invalid account ID: ${accountId}. Must be a positive number.`);
|
|
118
|
+
}
|
|
119
|
+
subscriptions.push(`account@${accountId}`);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Validate that at least one subscription was provided
|
|
123
|
+
if (subscriptions.length === 0) {
|
|
124
|
+
throw new NordError_1.NordError("At least one subscription must be provided");
|
|
125
|
+
}
|
|
126
|
+
// Create and return a new WebSocket client
|
|
127
|
+
return core.initWebSocketClient(this.webServerUrl, subscriptions);
|
|
121
128
|
}
|
|
122
129
|
/**
|
|
123
130
|
* Get the current timestamp from the Nord server
|
|
@@ -162,19 +169,42 @@ class Nord {
|
|
|
162
169
|
*
|
|
163
170
|
* @param nordConfig - Configuration options for the Nord client
|
|
164
171
|
* @param nordConfig.webServerUrl - Base URL for the Nord web server
|
|
165
|
-
* @param nordConfig.
|
|
172
|
+
* @param nordConfig.bridgeVk - Bridge verification key
|
|
166
173
|
* @param nordConfig.solanaUrl - Solana cluster URL
|
|
167
|
-
* @param nordConfig.initWebSockets - Whether to initialize WebSockets on creation, defaults to true
|
|
168
|
-
* @param nordConfig.tradesSubscriptions - Optional array of trades subscriptions (e.g., ["trades@BTCUSDC"])
|
|
169
|
-
* @param nordConfig.deltasSubscriptions - Optional array of deltas subscriptions (e.g., ["deltas@BTCUSDC"])
|
|
170
174
|
* @returns Initialized Nord client
|
|
171
175
|
* @throws {NordError} If initialization fails
|
|
172
176
|
*/
|
|
173
177
|
static async initNord(nordConfig) {
|
|
174
178
|
const nord = new Nord(nordConfig);
|
|
175
|
-
await nord.
|
|
179
|
+
await nord.init();
|
|
176
180
|
return nord;
|
|
177
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Initialize the Nord client by deriving program ID and fetching info
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
async init() {
|
|
187
|
+
const connection = new web3_js_1.Connection(this.solanaUrl);
|
|
188
|
+
const bridgeVkPubkey = new web3_js_1.PublicKey(this.bridgeVk);
|
|
189
|
+
const bridgeAccount = await connection.getAccountInfo(bridgeVkPubkey);
|
|
190
|
+
if (!bridgeAccount) {
|
|
191
|
+
throw new NordError_1.NordError(`Bridge account ${this.bridgeVk} not found`);
|
|
192
|
+
}
|
|
193
|
+
this._solanaProgramId = bridgeAccount.owner.toString();
|
|
194
|
+
await this.fetchNordInfo();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get the Solana program ID derived from bridge VK
|
|
198
|
+
*
|
|
199
|
+
* @returns Program ID string
|
|
200
|
+
* @throws {NordError} If program ID hasn't been initialized
|
|
201
|
+
*/
|
|
202
|
+
getSolanaProgramId() {
|
|
203
|
+
if (!this._solanaProgramId) {
|
|
204
|
+
throw new NordError_1.NordError("Solana program ID not initialized. Have you called Nord.initNord()?");
|
|
205
|
+
}
|
|
206
|
+
return this._solanaProgramId;
|
|
207
|
+
}
|
|
178
208
|
/**
|
|
179
209
|
* Get market statistics
|
|
180
210
|
*
|
|
@@ -294,79 +324,31 @@ class Nord {
|
|
|
294
324
|
async queryPrometheus(params) {
|
|
295
325
|
return metrics.queryPrometheus(this.webServerUrl, params);
|
|
296
326
|
}
|
|
297
|
-
/**
|
|
298
|
-
* Get the trades WebSocket client (default)
|
|
299
|
-
* If not already initialized, it will be created
|
|
300
|
-
*
|
|
301
|
-
* @returns WebSocket client for trades
|
|
302
|
-
*/
|
|
303
|
-
getWebSocketClient() {
|
|
304
|
-
if (!this.tradesWs) {
|
|
305
|
-
this.initializeWebSockets();
|
|
306
|
-
}
|
|
307
|
-
return this.tradesWs;
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Get the trades WebSocket client
|
|
311
|
-
* If not already initialized, it will be created
|
|
312
|
-
*
|
|
313
|
-
* @returns WebSocket client for trades
|
|
314
|
-
*/
|
|
315
|
-
getTradesWebSocketClient() {
|
|
316
|
-
if (!this.tradesWs) {
|
|
317
|
-
this.initializeWebSockets();
|
|
318
|
-
}
|
|
319
|
-
return this.tradesWs;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Get the deltas WebSocket client
|
|
323
|
-
* If not already initialized, it will be created
|
|
324
|
-
*
|
|
325
|
-
* @returns WebSocket client for orderbook deltas
|
|
326
|
-
*/
|
|
327
|
-
getDeltasWebSocketClient() {
|
|
328
|
-
if (!this.deltasWs) {
|
|
329
|
-
this.initializeWebSockets();
|
|
330
|
-
}
|
|
331
|
-
return this.deltasWs;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Get the user WebSocket client
|
|
335
|
-
* If not already initialized, it will be created
|
|
336
|
-
*
|
|
337
|
-
* @returns WebSocket client for user updates
|
|
338
|
-
*/
|
|
339
|
-
getUserWebSocketClient() {
|
|
340
|
-
if (!this.userWs) {
|
|
341
|
-
// Initialize user WebSocket client on demand
|
|
342
|
-
this.userWs = core.initWebSocketClient(this.webServerUrl, "user");
|
|
343
|
-
return this.userWs;
|
|
344
|
-
}
|
|
345
|
-
return this.userWs;
|
|
346
|
-
}
|
|
347
327
|
/**
|
|
348
328
|
* Subscribe to orderbook updates for a market
|
|
349
329
|
*
|
|
350
330
|
* @param symbol - Market symbol
|
|
351
331
|
* @returns Orderbook subscription
|
|
332
|
+
* @throws {NordError} If symbol is invalid
|
|
352
333
|
*/
|
|
353
334
|
subscribeOrderbook(symbol) {
|
|
335
|
+
if (!symbol || typeof symbol !== "string") {
|
|
336
|
+
throw new NordError_1.NordError("Invalid market symbol");
|
|
337
|
+
}
|
|
354
338
|
const subscription = new events_1.EventEmitter();
|
|
339
|
+
const wsClient = this.createWebSocketClient({
|
|
340
|
+
deltas: [symbol],
|
|
341
|
+
});
|
|
355
342
|
const handleDelta = (update) => {
|
|
356
343
|
if (update.symbol !== symbol) {
|
|
357
344
|
return;
|
|
358
345
|
}
|
|
359
346
|
subscription.emit("message", update);
|
|
360
347
|
};
|
|
361
|
-
|
|
362
|
-
if (!this.deltasWs) {
|
|
363
|
-
this.initializeWebSockets();
|
|
364
|
-
}
|
|
365
|
-
this.deltasWs.on("delta", handleDelta);
|
|
366
|
-
this.deltasWs.subscribe([`deltas@${symbol}`]);
|
|
348
|
+
wsClient.on("delta", handleDelta);
|
|
367
349
|
subscription.close = () => {
|
|
368
|
-
|
|
369
|
-
|
|
350
|
+
wsClient.unsubscribe([`deltas@${symbol}`]);
|
|
351
|
+
wsClient.removeListener("delta", handleDelta);
|
|
370
352
|
subscription.removeAllListeners();
|
|
371
353
|
};
|
|
372
354
|
return subscription;
|
|
@@ -376,24 +358,55 @@ class Nord {
|
|
|
376
358
|
*
|
|
377
359
|
* @param symbol - Market symbol
|
|
378
360
|
* @returns Trade subscription
|
|
361
|
+
* @throws {NordError} If symbol is invalid
|
|
379
362
|
*/
|
|
380
363
|
subscribeTrades(symbol) {
|
|
364
|
+
if (!symbol || typeof symbol !== "string") {
|
|
365
|
+
throw new NordError_1.NordError("Invalid market symbol");
|
|
366
|
+
}
|
|
381
367
|
const subscription = new events_1.EventEmitter();
|
|
368
|
+
const wsClient = this.createWebSocketClient({
|
|
369
|
+
trades: [symbol],
|
|
370
|
+
});
|
|
382
371
|
const handleTrade = (update) => {
|
|
383
372
|
if (update.symbol !== symbol) {
|
|
384
373
|
return;
|
|
385
374
|
}
|
|
386
375
|
subscription.emit("message", update);
|
|
387
376
|
};
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
377
|
+
wsClient.on("trades", handleTrade);
|
|
378
|
+
subscription.close = () => {
|
|
379
|
+
wsClient.unsubscribe([`trades@${symbol}`]);
|
|
380
|
+
wsClient.removeListener("trades", handleTrade);
|
|
381
|
+
subscription.removeAllListeners();
|
|
382
|
+
};
|
|
383
|
+
return subscription;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Subscribe to account updates
|
|
387
|
+
*
|
|
388
|
+
* @param accountId - Account ID to subscribe to
|
|
389
|
+
* @returns User subscription
|
|
390
|
+
* @throws {NordError} If accountId is invalid
|
|
391
|
+
*/
|
|
392
|
+
subscribeAccount(accountId) {
|
|
393
|
+
if (isNaN(accountId) || accountId <= 0) {
|
|
394
|
+
throw new NordError_1.NordError("Invalid account ID");
|
|
391
395
|
}
|
|
392
|
-
|
|
393
|
-
this.
|
|
396
|
+
const subscription = new events_1.EventEmitter();
|
|
397
|
+
const wsClient = this.createWebSocketClient({
|
|
398
|
+
accounts: [accountId],
|
|
399
|
+
});
|
|
400
|
+
const handleAccountUpdate = (update) => {
|
|
401
|
+
if (update.account_id !== accountId) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
subscription.emit("message", update);
|
|
405
|
+
};
|
|
406
|
+
wsClient.on("account", handleAccountUpdate);
|
|
394
407
|
subscription.close = () => {
|
|
395
|
-
|
|
396
|
-
|
|
408
|
+
wsClient.unsubscribe([`account@${accountId}`]);
|
|
409
|
+
wsClient.removeListener("account", handleAccountUpdate);
|
|
397
410
|
subscription.removeAllListeners();
|
|
398
411
|
};
|
|
399
412
|
return subscription;
|
|
@@ -440,10 +453,6 @@ class Nord {
|
|
|
440
453
|
}
|
|
441
454
|
query = { market_id: marketId };
|
|
442
455
|
}
|
|
443
|
-
// Ensure market_id is provided
|
|
444
|
-
if (query.market_id === undefined) {
|
|
445
|
-
throw new NordError_1.NordError("market_id is required for orderbook query");
|
|
446
|
-
}
|
|
447
456
|
return market.getOrderbook(this.webServerUrl, query);
|
|
448
457
|
}
|
|
449
458
|
/**
|
|
@@ -64,15 +64,6 @@ export interface TransferParams {
|
|
|
64
64
|
/** Destination account ID */
|
|
65
65
|
toAccountId: number;
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Parameters for creating a new account
|
|
69
|
-
*/
|
|
70
|
-
export interface CreateAccountParams {
|
|
71
|
-
/** Token ID for initial funding */
|
|
72
|
-
tokenId: number;
|
|
73
|
-
/** Initial funding amount */
|
|
74
|
-
amount: Decimal.Value;
|
|
75
|
-
}
|
|
76
67
|
/**
|
|
77
68
|
* User class for interacting with the Nord protocol
|
|
78
69
|
*/
|
|
@@ -270,14 +261,6 @@ export declare class NordUser {
|
|
|
270
261
|
* @throws {NordError} If the operation fails
|
|
271
262
|
*/
|
|
272
263
|
transferToAccount(params: TransferParams): Promise<void>;
|
|
273
|
-
/**
|
|
274
|
-
* Create a new account
|
|
275
|
-
*
|
|
276
|
-
* @param params - Account creation parameters
|
|
277
|
-
* @returns New NordUser instance
|
|
278
|
-
* @throws {NordError} If the operation fails
|
|
279
|
-
*/
|
|
280
|
-
createAccount(params: CreateAccountParams): Promise<NordUser>;
|
|
281
264
|
/**
|
|
282
265
|
* Helper function to retry a promise with exponential backoff
|
|
283
266
|
*
|
|
@@ -153,7 +153,7 @@ class NordUser {
|
|
|
153
153
|
initBridgeClient() {
|
|
154
154
|
if (!this.getSolanaPublicKey() ||
|
|
155
155
|
!this.connection ||
|
|
156
|
-
!this.nord.
|
|
156
|
+
!this.nord.getSolanaProgramId()) {
|
|
157
157
|
throw new NordError_1.NordError("Solana public key, connection, and program ID are required to initialize bridge client");
|
|
158
158
|
}
|
|
159
159
|
// Create an Anchor wallet that uses walletSignFn for signing
|
|
@@ -176,9 +176,10 @@ class NordUser {
|
|
|
176
176
|
// Initialize the bridge client
|
|
177
177
|
this.bridgeClient = new client_1.SolanaBridgeClient({
|
|
178
178
|
rpcUrl: this.connection.rpcEndpoint,
|
|
179
|
-
programId: this.nord.
|
|
179
|
+
programId: this.nord.getSolanaProgramId(),
|
|
180
180
|
commitment: "confirmed",
|
|
181
181
|
tokenInfos: this.splTokenInfos,
|
|
182
|
+
bridgeVk: this.nord.bridgeVk,
|
|
182
183
|
}, wallet);
|
|
183
184
|
}
|
|
184
185
|
/**
|
|
@@ -276,9 +277,6 @@ class NordUser {
|
|
|
276
277
|
const mint = new web3_js_1.PublicKey(tokenInfo.mint);
|
|
277
278
|
// Get the user's token account
|
|
278
279
|
const fromAccount = await this.getAssociatedTokenAccount(mint);
|
|
279
|
-
// Get the bridge's token account
|
|
280
|
-
const [authority] = await this.bridgeClient.findAuthorityPda();
|
|
281
|
-
const toAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
282
280
|
// Convert amount to BN with proper decimals
|
|
283
281
|
const amountBN = (0, utils_2.toBN)(amount, tokenInfo.precision);
|
|
284
282
|
// Deposit tokens
|
|
@@ -286,7 +284,6 @@ class NordUser {
|
|
|
286
284
|
amount: amountBN,
|
|
287
285
|
mint,
|
|
288
286
|
fromAccount,
|
|
289
|
-
toAccount,
|
|
290
287
|
});
|
|
291
288
|
}
|
|
292
289
|
catch (error) {
|
|
@@ -372,7 +369,7 @@ class NordUser {
|
|
|
372
369
|
async fetchInfo() {
|
|
373
370
|
if (this.accountIds !== undefined) {
|
|
374
371
|
const accountsData = await Promise.all(this.accountIds.map(async (accountId) => {
|
|
375
|
-
const response = await (0, utils_2.checkedFetch)(`${this.nord.webServerUrl}/account
|
|
372
|
+
const response = await (0, utils_2.checkedFetch)(`${this.nord.webServerUrl}/account/${accountId}`);
|
|
376
373
|
const accountData = (await response.json());
|
|
377
374
|
// Ensure we have the correct accountId
|
|
378
375
|
return {
|
|
@@ -547,34 +544,6 @@ class NordUser {
|
|
|
547
544
|
throw new NordError_1.NordError("Failed to transfer tokens", { cause: error });
|
|
548
545
|
}
|
|
549
546
|
}
|
|
550
|
-
/**
|
|
551
|
-
* Create a new account
|
|
552
|
-
*
|
|
553
|
-
* @param params - Account creation parameters
|
|
554
|
-
* @returns New NordUser instance
|
|
555
|
-
* @throws {NordError} If the operation fails
|
|
556
|
-
*/
|
|
557
|
-
async createAccount(params) {
|
|
558
|
-
try {
|
|
559
|
-
this.checkSessionValidity();
|
|
560
|
-
// Create a new keypair for the account
|
|
561
|
-
const keypair = web3_js_1.Keypair.generate();
|
|
562
|
-
// Create a new NordUser
|
|
563
|
-
const newUser = NordUser.fromPrivateKey(this.nord, keypair.secretKey, this.connection);
|
|
564
|
-
// Transfer initial funds
|
|
565
|
-
await this.transferToAccount({
|
|
566
|
-
to: newUser,
|
|
567
|
-
tokenId: params.tokenId,
|
|
568
|
-
amount: params.amount,
|
|
569
|
-
fromAccountId: (0, utils_2.optExpect)(this.accountIds?.[0], "No account ID"),
|
|
570
|
-
toAccountId: (0, utils_2.optExpect)(newUser.accountIds?.[0], "No account ID for new user"),
|
|
571
|
-
});
|
|
572
|
-
return newUser;
|
|
573
|
-
}
|
|
574
|
-
catch (error) {
|
|
575
|
-
throw new NordError_1.NordError("Failed to create account", { cause: error });
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
547
|
/**
|
|
579
548
|
* Helper function to retry a promise with exponential backoff
|
|
580
549
|
*
|
package/dist/types.d.ts
CHANGED
|
@@ -15,23 +15,46 @@ export declare enum PeakTpsPeriodUnit {
|
|
|
15
15
|
Month = "m",
|
|
16
16
|
Year = "y"
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Nord subscription type for trades or deltas
|
|
20
|
+
*/
|
|
21
|
+
export type SubscriptionType = "trades" | "deltas" | "account";
|
|
22
|
+
/**
|
|
23
|
+
* Pattern for a valid Nord subscription
|
|
24
|
+
* Format should be: "<type>@<parameter>"
|
|
25
|
+
* Examples: "trades@BTCUSDC", "deltas@ETHUSDC", "account@42"
|
|
26
|
+
*/
|
|
27
|
+
export type SubscriptionPattern = `${SubscriptionType}@${string}` | string;
|
|
18
28
|
/**
|
|
19
29
|
* Configuration options for the Nord client
|
|
20
30
|
*/
|
|
21
31
|
export interface NordConfig {
|
|
22
32
|
/** Base URL for the Nord web server */
|
|
23
33
|
webServerUrl: string;
|
|
24
|
-
/**
|
|
25
|
-
|
|
34
|
+
/** Bridge verification key */
|
|
35
|
+
bridgeVk: string;
|
|
26
36
|
/** Solana cluster URL */
|
|
27
37
|
solanaUrl: string;
|
|
28
38
|
/** Whether to initialize WebSockets on creation, defaults to true */
|
|
29
39
|
initWebSockets?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Initial subscriptions for the trades WebSocket
|
|
42
|
+
* Supports both formats:
|
|
43
|
+
* - Legacy format: ["BTCUSDC", "ETHUSDC"]
|
|
44
|
+
* - New format: ["trades@BTCUSDC", "trades@ETHUSDC"]
|
|
45
|
+
*/
|
|
46
|
+
tradesSubscriptions?: SubscriptionPattern[];
|
|
47
|
+
/**
|
|
48
|
+
* Initial subscriptions for the deltas WebSocket
|
|
49
|
+
* Supports both formats:
|
|
50
|
+
* - Legacy format: ["BTCUSDC", "ETHUSDC"]
|
|
51
|
+
* - New format: ["deltas@BTCUSDC", "deltas@ETHUSDC"]
|
|
52
|
+
*/
|
|
53
|
+
deltasSubscriptions?: SubscriptionPattern[];
|
|
34
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Configuration options for the Nord client
|
|
57
|
+
*/
|
|
35
58
|
export interface TokenInfo {
|
|
36
59
|
address: string;
|
|
37
60
|
precision: number;
|
|
@@ -355,22 +378,22 @@ export interface ActionNonceResponse {
|
|
|
355
378
|
export declare enum WebSocketMessageType {
|
|
356
379
|
Subscribe = "subscribe",
|
|
357
380
|
Unsubscribe = "unsubscribe",
|
|
358
|
-
TradeUpdate = "
|
|
381
|
+
TradeUpdate = "trades",
|
|
359
382
|
DeltaUpdate = "delta",
|
|
360
|
-
|
|
383
|
+
AccountUpdate = "account"
|
|
361
384
|
}
|
|
362
385
|
/**
|
|
363
386
|
* WebSocket subscription request
|
|
364
387
|
*/
|
|
365
388
|
export interface WebSocketSubscription {
|
|
366
|
-
|
|
389
|
+
e: WebSocketMessageType;
|
|
367
390
|
streams: string[];
|
|
368
391
|
}
|
|
369
392
|
/**
|
|
370
393
|
* WebSocket trade update message
|
|
371
394
|
*/
|
|
372
395
|
export interface WebSocketTradeUpdate {
|
|
373
|
-
|
|
396
|
+
e: WebSocketMessageType.TradeUpdate;
|
|
374
397
|
symbol: string;
|
|
375
398
|
trades: Trade[];
|
|
376
399
|
timestamp: number;
|
|
@@ -379,7 +402,7 @@ export interface WebSocketTradeUpdate {
|
|
|
379
402
|
* WebSocket delta update message
|
|
380
403
|
*/
|
|
381
404
|
export interface WebSocketDeltaUpdate {
|
|
382
|
-
|
|
405
|
+
e: WebSocketMessageType.DeltaUpdate;
|
|
383
406
|
last_update_id: number;
|
|
384
407
|
update_id: number;
|
|
385
408
|
market_symbol: string;
|
|
@@ -390,11 +413,11 @@ export interface WebSocketDeltaUpdate {
|
|
|
390
413
|
/**
|
|
391
414
|
* WebSocket user update message
|
|
392
415
|
*/
|
|
393
|
-
export interface
|
|
394
|
-
|
|
395
|
-
|
|
416
|
+
export interface WebSocketAccountUpdate {
|
|
417
|
+
e: WebSocketMessageType.AccountUpdate;
|
|
418
|
+
accountId: number;
|
|
396
419
|
account: Account;
|
|
397
420
|
timestamp: number;
|
|
398
421
|
}
|
|
399
|
-
export type WebSocketMessage = WebSocketSubscription | WebSocketTradeUpdate | WebSocketDeltaUpdate |
|
|
422
|
+
export type WebSocketMessage = WebSocketSubscription | WebSocketTradeUpdate | WebSocketDeltaUpdate | WebSocketAccountUpdate;
|
|
400
423
|
export {};
|
package/dist/types.js
CHANGED
|
@@ -97,7 +97,7 @@ var WebSocketMessageType;
|
|
|
97
97
|
(function (WebSocketMessageType) {
|
|
98
98
|
WebSocketMessageType["Subscribe"] = "subscribe";
|
|
99
99
|
WebSocketMessageType["Unsubscribe"] = "unsubscribe";
|
|
100
|
-
WebSocketMessageType["TradeUpdate"] = "
|
|
100
|
+
WebSocketMessageType["TradeUpdate"] = "trades";
|
|
101
101
|
WebSocketMessageType["DeltaUpdate"] = "delta";
|
|
102
|
-
WebSocketMessageType["
|
|
102
|
+
WebSocketMessageType["AccountUpdate"] = "account";
|
|
103
103
|
})(WebSocketMessageType || (exports.WebSocketMessageType = WebSocketMessageType = {}));
|
|
@@ -4,9 +4,6 @@ import { NordWebSocketClientEvents } from "./events";
|
|
|
4
4
|
* WebSocket client for Nord exchange
|
|
5
5
|
*
|
|
6
6
|
* This client connects to one of the specific Nord WebSocket endpoints:
|
|
7
|
-
* - /ws/trades - For trade updates
|
|
8
|
-
* - /ws/deltas - For orderbook delta updates
|
|
9
|
-
* - /ws/user - For user-specific updates
|
|
10
7
|
*
|
|
11
8
|
* Each endpoint handles a specific type of data and subscriptions must match
|
|
12
9
|
* the endpoint type (e.g., only 'trades@BTCUSDC' subscriptions are valid on
|
|
@@ -7,16 +7,13 @@ exports.NordWebSocketClient = void 0;
|
|
|
7
7
|
const ws_1 = __importDefault(require("ws"));
|
|
8
8
|
const events_1 = require("events");
|
|
9
9
|
const types_1 = require("../types");
|
|
10
|
-
const VALID_STREAM_TYPES = ["trades", "
|
|
10
|
+
const VALID_STREAM_TYPES = ["trades", "delta", "account"];
|
|
11
11
|
// Constants for WebSocket readyState
|
|
12
12
|
const WS_OPEN = 1;
|
|
13
13
|
/**
|
|
14
14
|
* WebSocket client for Nord exchange
|
|
15
15
|
*
|
|
16
16
|
* This client connects to one of the specific Nord WebSocket endpoints:
|
|
17
|
-
* - /ws/trades - For trade updates
|
|
18
|
-
* - /ws/deltas - For orderbook delta updates
|
|
19
|
-
* - /ws/user - For user-specific updates
|
|
20
17
|
*
|
|
21
18
|
* Each endpoint handles a specific type of data and subscriptions must match
|
|
22
19
|
* the endpoint type (e.g., only 'trades@BTCUSDC' subscriptions are valid on
|
|
@@ -64,8 +61,8 @@ class NordWebSocketClient extends events_1.EventEmitter {
|
|
|
64
61
|
if (!VALID_STREAM_TYPES.includes(type)) {
|
|
65
62
|
throw new Error(`Invalid stream type: ${type}. Valid types are: ${VALID_STREAM_TYPES.join(", ")}`);
|
|
66
63
|
}
|
|
67
|
-
if (type === "
|
|
68
|
-
throw new Error(`Invalid
|
|
64
|
+
if (type === "account" && !/^\d+$/.test(params)) {
|
|
65
|
+
throw new Error(`Invalid account ID in stream: ${params}. Expected numeric ID`);
|
|
69
66
|
}
|
|
70
67
|
}
|
|
71
68
|
/**
|
|
@@ -228,7 +225,7 @@ class NordWebSocketClient extends events_1.EventEmitter {
|
|
|
228
225
|
return;
|
|
229
226
|
}
|
|
230
227
|
const message = {
|
|
231
|
-
|
|
228
|
+
e: types_1.WebSocketMessageType.Subscribe,
|
|
232
229
|
streams,
|
|
233
230
|
};
|
|
234
231
|
try {
|
|
@@ -266,7 +263,7 @@ class NordWebSocketClient extends events_1.EventEmitter {
|
|
|
266
263
|
return;
|
|
267
264
|
}
|
|
268
265
|
const message = {
|
|
269
|
-
|
|
266
|
+
e: types_1.WebSocketMessageType.Unsubscribe,
|
|
270
267
|
streams,
|
|
271
268
|
};
|
|
272
269
|
try {
|
|
@@ -311,18 +308,18 @@ class NordWebSocketClient extends events_1.EventEmitter {
|
|
|
311
308
|
* @param message WebSocket message
|
|
312
309
|
*/
|
|
313
310
|
handleMessage(message) {
|
|
314
|
-
switch (message.
|
|
311
|
+
switch (message.e) {
|
|
315
312
|
case types_1.WebSocketMessageType.TradeUpdate:
|
|
316
|
-
this.emit("
|
|
313
|
+
this.emit("trades", message);
|
|
317
314
|
break;
|
|
318
315
|
case types_1.WebSocketMessageType.DeltaUpdate:
|
|
319
316
|
this.emit("delta", message);
|
|
320
317
|
break;
|
|
321
|
-
case types_1.WebSocketMessageType.
|
|
322
|
-
this.emit("
|
|
318
|
+
case types_1.WebSocketMessageType.AccountUpdate:
|
|
319
|
+
this.emit("account", message);
|
|
323
320
|
break;
|
|
324
321
|
default:
|
|
325
|
-
this.emit("error", new Error(`Unknown message type: ${message.
|
|
322
|
+
this.emit("error", new Error(`Unknown message type: ${message.e}`));
|
|
326
323
|
}
|
|
327
324
|
}
|
|
328
325
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WebSocketTradeUpdate, WebSocketDeltaUpdate,
|
|
1
|
+
import { WebSocketTradeUpdate, WebSocketDeltaUpdate, WebSocketAccountUpdate } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Event type definitions for the NordWebSocketClient
|
|
4
4
|
*/
|
|
@@ -8,7 +8,7 @@ export interface NordWebSocketEvents {
|
|
|
8
8
|
error: (error: Error) => void;
|
|
9
9
|
trade: (update: WebSocketTradeUpdate) => void;
|
|
10
10
|
delta: (update: WebSocketDeltaUpdate) => void;
|
|
11
|
-
|
|
11
|
+
account: (update: WebSocketAccountUpdate) => void;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Type declaration for NordWebSocketClient event methods
|