@n1xyz/nord-ts 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/const.d.ts +8 -0
  2. package/dist/const.js +30 -0
  3. package/dist/gen/nord.d.ts +882 -0
  4. package/dist/gen/nord.js +6520 -0
  5. package/dist/gen/openapi.d.ts +2244 -0
  6. package/dist/gen/openapi.js +6 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.js +21 -0
  9. package/dist/nord/api/actions.d.ts +135 -0
  10. package/dist/nord/api/actions.js +313 -0
  11. package/dist/nord/api/core.d.ts +16 -0
  12. package/dist/nord/api/core.js +81 -0
  13. package/dist/nord/api/metrics.d.ts +67 -0
  14. package/dist/nord/api/metrics.js +229 -0
  15. package/dist/nord/client/Nord.d.ts +282 -0
  16. package/dist/nord/client/Nord.js +528 -0
  17. package/dist/nord/client/NordUser.d.ts +340 -0
  18. package/dist/nord/client/NordUser.js +652 -0
  19. package/dist/nord/index.d.ts +7 -0
  20. package/dist/nord/index.js +31 -0
  21. package/dist/nord/models/Subscriber.d.ts +37 -0
  22. package/dist/nord/models/Subscriber.js +25 -0
  23. package/dist/nord/utils/NordError.d.ts +35 -0
  24. package/dist/nord/utils/NordError.js +49 -0
  25. package/dist/types.d.ts +251 -0
  26. package/dist/types.js +101 -0
  27. package/dist/utils.d.ts +98 -0
  28. package/dist/utils.js +237 -0
  29. package/dist/websocket/NordWebSocketClient.d.ts +57 -0
  30. package/dist/websocket/NordWebSocketClient.js +251 -0
  31. package/dist/websocket/events.d.ts +19 -0
  32. package/dist/websocket/events.js +2 -0
  33. package/dist/websocket/index.d.ts +2 -0
  34. package/dist/websocket/index.js +5 -0
  35. package/package.json +8 -2
  36. package/src/gen/.gitkeep +0 -0
  37. package/src/gen/nord.ts +7593 -0
  38. package/src/gen/openapi.ts +2245 -0
  39. package/src/nord/api/core.ts +1 -16
  40. package/src/nord/client/Nord.ts +7 -11
  41. package/src/types.ts +0 -11
  42. package/src/websocket/NordWebSocketClient.ts +0 -113
  43. package/.claude/settings.local.json +0 -11
  44. package/.local/qa.ts +0 -77
  45. package/.local/test-atomic.ts +0 -112
  46. package/.prettierignore +0 -2
  47. package/check.sh +0 -4
  48. package/default.nix +0 -47
  49. package/eslint.config.mjs +0 -66
  50. package/tests/utils.spec.ts +0 -121
  51. package/tsconfig.eslint.json +0 -12
  52. package/tsconfig.json +0 -24
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MetricPeriod = void 0;
4
+ exports.aggregateMetrics = aggregateMetrics;
5
+ exports.getCurrentTps = getCurrentTps;
6
+ exports.getPeakTps = getPeakTps;
7
+ exports.getMedianLatency = getMedianLatency;
8
+ exports.getTotalTransactions = getTotalTransactions;
9
+ exports.queryPrometheus = queryPrometheus;
10
+ const types_1 = require("../../types");
11
+ const utils_1 = require("../../utils");
12
+ const NordError_1 = require("../utils/NordError");
13
+ /**
14
+ * Time periods for metrics queries
15
+ */
16
+ var MetricPeriod;
17
+ (function (MetricPeriod) {
18
+ MetricPeriod["ONE_MINUTE"] = "1m";
19
+ MetricPeriod["FIVE_MINUTES"] = "5m";
20
+ MetricPeriod["FIFTEEN_MINUTES"] = "15m";
21
+ MetricPeriod["ONE_HOUR"] = "1h";
22
+ MetricPeriod["FOUR_HOURS"] = "4h";
23
+ MetricPeriod["ONE_DAY"] = "24h";
24
+ MetricPeriod["ONE_WEEK"] = "7d";
25
+ })(MetricPeriod || (exports.MetricPeriod = MetricPeriod = {}));
26
+ /**
27
+ * Fetch aggregate metrics from the Nord API
28
+ *
29
+ * @param webServerUrl - Base URL for the Nord web server
30
+ * @param txPeakTpsPeriod - Period for peak TPS calculation
31
+ * @param txPeakTpsPeriodUnit - Unit for peak TPS period
32
+ * @returns Aggregate metrics
33
+ * @throws {NordError} If the request fails
34
+ */
35
+ async function aggregateMetrics(webServerUrl, txPeakTpsPeriod = 1, txPeakTpsPeriodUnit = types_1.PeakTpsPeriodUnit.Day) {
36
+ try {
37
+ const response = await (0, utils_1.checkedFetch)(`${webServerUrl}/metrics?tx_peak_tps_period=${txPeakTpsPeriod}&tx_peak_tps_period_unit=${txPeakTpsPeriodUnit}`);
38
+ // Get the raw text response (Prometheus format)
39
+ const text = await response.text();
40
+ // Parse the Prometheus-formatted metrics text into an AggregateMetrics object
41
+ const metrics = {
42
+ blocks_total: 0,
43
+ tx_total: extractMetricValue(text, "nord_requests_ok_count"),
44
+ tx_tps: calculateTps(text),
45
+ tx_tps_peak: calculatePeakTps(text),
46
+ request_latency_average: extractLatency(text),
47
+ };
48
+ return metrics;
49
+ }
50
+ catch (error) {
51
+ throw new NordError_1.NordError("Failed to fetch aggregate metrics", { cause: error });
52
+ }
53
+ }
54
+ /**
55
+ * Extract a metric value from Prometheus-formatted text
56
+ *
57
+ * @param text - Prometheus-formatted metrics text
58
+ * @param metricName - Name of the metric to extract
59
+ * @returns The metric value as a number, or 0 if not found
60
+ */
61
+ function extractMetricValue(text, metricName) {
62
+ const regex = new RegExp(`^${metricName}\\s+([\\d.]+)`, "m");
63
+ const match = text.match(regex);
64
+ return match ? parseFloat(match[1]) : 0;
65
+ }
66
+ /**
67
+ * Calculate TPS from Prometheus metrics
68
+ *
69
+ * @param text - Prometheus-formatted metrics text
70
+ * @returns Calculated TPS value
71
+ */
72
+ function calculateTps(text) {
73
+ // Use the request count and latency to estimate TPS
74
+ const requestCount = extractMetricValue(text, "nord_requests_ok_count");
75
+ const latencySum = extractSummaryValue(text, "nord_requests_ok_latency_sum");
76
+ const latencyCount = extractSummaryValue(text, "nord_requests_ok_latency_count");
77
+ if (latencySum > 0 && latencyCount > 0) {
78
+ // Average latency in seconds
79
+ const avgLatency = latencySum / latencyCount;
80
+ // If we have valid latency data, estimate TPS as requests per second
81
+ return avgLatency > 0 ? requestCount / (latencyCount * avgLatency) : 0;
82
+ }
83
+ // Fallback: just return a small fraction of the total request count
84
+ return requestCount > 0 ? requestCount / 100 : 0;
85
+ }
86
+ /**
87
+ * Calculate peak TPS from Prometheus metrics
88
+ *
89
+ * @param text - Prometheus-formatted metrics text
90
+ * @returns Calculated peak TPS value
91
+ */
92
+ function calculatePeakTps(text) {
93
+ // For peak TPS, we'll use a simple heuristic: 2x the current TPS estimate
94
+ // TODO: fix this
95
+ return calculateTps(text) * 2;
96
+ }
97
+ /**
98
+ * Extract latency from Prometheus metrics
99
+ *
100
+ * @param text - Prometheus-formatted metrics text
101
+ * @returns Average latency in seconds
102
+ */
103
+ function extractLatency(text) {
104
+ // TODO: fix - using average for latency is kinda wack. ok to merge for now but should change.
105
+ const latencySum = extractSummaryValue(text, "nord_requests_ok_latency_sum");
106
+ const latencyCount = extractSummaryValue(text, "nord_requests_ok_latency_count");
107
+ return latencyCount > 0 ? latencySum / latencyCount : 0;
108
+ }
109
+ /**
110
+ * Extract a summary value from Prometheus-formatted text
111
+ *
112
+ * @param text - Prometheus-formatted metrics text
113
+ * @param metricName - Name of the metric to extract
114
+ * @returns The metric value as a number, or 0 if not found
115
+ */
116
+ function extractSummaryValue(text, metricName) {
117
+ const regex = new RegExp(`^${metricName}\\s+([\\d.]+)`, "m");
118
+ const match = text.match(regex);
119
+ return match ? parseFloat(match[1]) : 0;
120
+ }
121
+ /**
122
+ * Get current transactions per second
123
+ *
124
+ * @param webServerUrl - Base URL for the Nord web server
125
+ * @param period - Time period for the query
126
+ * @returns Current TPS value
127
+ * @throws {NordError} If the request fails
128
+ */
129
+ async function getCurrentTps(webServerUrl, period = "1m") {
130
+ try {
131
+ // nord_tx_count doesn't exist in the metrics, use nord_requests_ok_count instead
132
+ return await queryPrometheus(webServerUrl, `sum(rate(nord_requests_ok_count[${period}]))`);
133
+ }
134
+ catch (error) {
135
+ throw new NordError_1.NordError(`Failed to get current TPS for period ${period}`, {
136
+ cause: error,
137
+ });
138
+ }
139
+ }
140
+ /**
141
+ * Get peak transactions per second
142
+ *
143
+ * @param webServerUrl - Base URL for the Nord web server
144
+ * @param period - Time period for the query
145
+ * @returns Peak TPS value
146
+ * @throws {NordError} If the request fails
147
+ */
148
+ async function getPeakTps(webServerUrl, period = "24h") {
149
+ try {
150
+ // nord_tx_count doesn't exist in the metrics, use nord_requests_ok_count instead
151
+ return await queryPrometheus(webServerUrl, `max_over_time(sum(rate(nord_requests_ok_count[1m]))[${period}:])`);
152
+ }
153
+ catch (error) {
154
+ throw new NordError_1.NordError(`Failed to get peak TPS for period ${period}`, {
155
+ cause: error,
156
+ });
157
+ }
158
+ }
159
+ /**
160
+ * Get median transaction latency
161
+ *
162
+ * @param webServerUrl - Base URL for the Nord web server
163
+ * @param period - Time period for the query
164
+ * @returns Median latency in milliseconds
165
+ * @throws {NordError} If the request fails
166
+ */
167
+ async function getMedianLatency(webServerUrl, period = "1m") {
168
+ try {
169
+ // nord_tx_latency_ms doesn't exist, use nord_requests_ok_latency instead
170
+ // which contains the latency data in the summary metric
171
+ return await queryPrometheus(webServerUrl, `quantile_over_time(0.5, nord_requests_ok_latency[${period}]) * 1000`);
172
+ }
173
+ catch (error) {
174
+ throw new NordError_1.NordError(`Failed to get median latency for period ${period}`, {
175
+ cause: error,
176
+ });
177
+ }
178
+ }
179
+ /**
180
+ * Get total transaction count
181
+ *
182
+ * @param webServerUrl - Base URL for the Nord web server
183
+ * @returns Total transaction count
184
+ * @throws {NordError} If the request fails
185
+ */
186
+ async function getTotalTransactions(webServerUrl) {
187
+ try {
188
+ // nord_tx_count doesn't exist, use nord_requests_ok_count instead
189
+ return await queryPrometheus(webServerUrl, "sum(nord_requests_ok_count)");
190
+ }
191
+ catch (error) {
192
+ throw new NordError_1.NordError("Failed to get total transactions", { cause: error });
193
+ }
194
+ }
195
+ /**
196
+ * Query Prometheus metrics
197
+ *
198
+ * @param webServerUrl - Base URL for the Nord web server
199
+ * @param params - Prometheus query parameters
200
+ * @returns Query result as a number
201
+ * @throws {NordError} If the request fails
202
+ */
203
+ async function queryPrometheus(webServerUrl, params) {
204
+ try {
205
+ const response = await (0, utils_1.checkedFetch)(`${webServerUrl}/prometheus?query=${encodeURIComponent(params)}`);
206
+ // Handle raw text response
207
+ const text = await response.text();
208
+ try {
209
+ // Try to parse as JSON first
210
+ const data = JSON.parse(text);
211
+ return data.data.result[0]?.value[1] || 0;
212
+ }
213
+ catch (error) {
214
+ console.log("Prometheus query failed:", error);
215
+ // Try to find a number in the response
216
+ const numberMatch = text.match(/[\d.]+/);
217
+ if (numberMatch) {
218
+ return parseFloat(numberMatch[0]);
219
+ }
220
+ // Return 0 if no number is found
221
+ return 0;
222
+ }
223
+ }
224
+ catch (error) {
225
+ throw new NordError_1.NordError(`Failed to query Prometheus: ${params}`, {
226
+ cause: error,
227
+ });
228
+ }
229
+ }
@@ -0,0 +1,282 @@
1
+ import { ProtonClient } from "@n1xyz/proton";
2
+ import { PublicKey } from "@solana/web3.js";
3
+ import { EventEmitter } from "events";
4
+ import { Account, ActionResponse, AggregateMetrics, Info, Market, MarketStats, NordConfig, OrderbookQuery, OrderbookResponse, PeakTpsPeriodUnit, Token, TradesResponse, User } from "../../types";
5
+ import { NordWebSocketClient } from "../../websocket/index";
6
+ import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
7
+ /**
8
+ * User subscription interface
9
+ */
10
+ export interface UserSubscription extends EventEmitter {
11
+ close: () => void;
12
+ }
13
+ /**
14
+ * WebSocket subscription options interface
15
+ */
16
+ export interface WebSocketSubscriptionOptions {
17
+ /** Market symbols to subscribe to for trade updates */
18
+ trades?: string[];
19
+ /** Market symbols to subscribe to for orderbook delta updates */
20
+ deltas?: string[];
21
+ /** Account IDs to subscribe to for account updates */
22
+ accounts?: number[];
23
+ }
24
+ /**
25
+ * Main Nord client class for interacting with the Nord API
26
+ */
27
+ export declare class Nord {
28
+ /** Base URL for the Nord web server */
29
+ readonly webServerUrl: string;
30
+ /** Bridge verification key */
31
+ readonly bridgeVk: PublicKey;
32
+ /** Solana RPC URL */
33
+ readonly solanaUrl: string;
34
+ /** Available markets */
35
+ markets: Market[];
36
+ /** Available tokens */
37
+ tokens: Token[];
38
+ /** Map of symbol to market_id */
39
+ private symbolToMarketId;
40
+ /** Proton client for bridge and hansel operations */
41
+ protonClient: ProtonClient;
42
+ /** HTTP client for Nord operations */
43
+ private httpClient;
44
+ /**
45
+ * Create a new Nord client
46
+ *
47
+ * @param config - Configuration options for the Nord client
48
+ * @param config.webServerUrl - Base URL for the Nord web server
49
+ * @param config.bridgeVk - Bridge verification key
50
+ * @param config.solanaUrl - Solana cluster URL
51
+ * @throws {Error} If required configuration is missing
52
+ */
53
+ private constructor();
54
+ /**
55
+ * Create a WebSocket client with specific subscriptions
56
+ *
57
+ * @param options - Subscription options that specify which data streams to subscribe to
58
+ * @returns A new WebSocket client with the requested subscriptions
59
+ * @throws {NordError} If invalid subscription options are provided
60
+ *
61
+ * @example
62
+ * // Create a client for trades and deltas from one market and an account
63
+ * const wsClient = nord.createWebSocketClient({
64
+ * trades: ["BTCUSDC"],
65
+ * deltas: ["BTCUSDC"],
66
+ * accounts: [123]
67
+ * });
68
+ *
69
+ * @example
70
+ * // Create a client for trades from multiple markets
71
+ * const tradesClient = nord.createWebSocketClient({
72
+ * trades: ["BTCUSDC", "ETHUSDC"]
73
+ * });
74
+ */
75
+ createWebSocketClient(options: WebSocketSubscriptionOptions): NordWebSocketClient;
76
+ private GET;
77
+ /**
78
+ * Get the current timestamp from the Nord server
79
+ *
80
+ * @returns Current timestamp as a bigint
81
+ * @throws {NordError} If the request fails
82
+ */
83
+ getTimestamp(): Promise<bigint>;
84
+ /**
85
+ * Get the last event nonce from the Nord server
86
+ *
87
+ * @returns Next action nonce
88
+ * @throws {NordError} If the request fails
89
+ */
90
+ getActionNonce(): Promise<number>;
91
+ /**
92
+ * Fetch information about Nord markets and tokens
93
+ *
94
+ * @throws {NordError} If the request fails
95
+ */
96
+ fetchNordInfo(): Promise<void>;
97
+ /**
98
+ * Initialize a new Nord client
99
+ *
100
+ * @param nordConfig - Configuration options for the Nord client
101
+ * @param nordConfig.webServerUrl - Base URL for the Nord web server
102
+ * @param nordConfig.bridgeVk - Bridge verification key
103
+ * @param nordConfig.solanaUrl - Solana cluster URL
104
+ * @returns Initialized Nord client
105
+ * @throws {NordError} If initialization fails
106
+ */
107
+ static initNord({ bridgeVk: bridgeVk_, solanaUrl, webServerUrl, }: Readonly<NordConfig>): Promise<Nord>;
108
+ /**
109
+ * Initialize the Nord client
110
+ * @private
111
+ */
112
+ private init;
113
+ /**
114
+ * Query a specific action
115
+ *
116
+ * @param query - Action query parameters
117
+ * @returns Action response
118
+ * @throws {NordError} If the request fails
119
+ */
120
+ queryAction({ action_id, }: {
121
+ action_id: number;
122
+ }): Promise<ActionResponse | null>;
123
+ /**
124
+ * Query recent actions
125
+ *
126
+ * @param from - Starting action index
127
+ * @param to - Ending action index
128
+ * @returns Actions response
129
+ * @throws {NordError} If the request fails
130
+ */
131
+ queryRecentActions(query: {
132
+ from: number;
133
+ to: number;
134
+ }): Promise<ActionResponse[]>;
135
+ /**
136
+ * Get the last action ID
137
+ *
138
+ * @returns Last action ID
139
+ * @throws {NordError} If the request fails
140
+ */
141
+ getLastActionId(): Promise<number>;
142
+ /**
143
+ * Fetch aggregate metrics from the Nord API
144
+ *
145
+ * @param txPeakTpsPeriod - Period for peak TPS calculation
146
+ * @param txPeakTpsPeriodUnit - Unit for peak TPS period
147
+ * @returns Aggregate metrics
148
+ * @throws {NordError} If the request fails
149
+ */
150
+ aggregateMetrics(txPeakTpsPeriod?: number, txPeakTpsPeriodUnit?: PeakTpsPeriodUnit): Promise<AggregateMetrics>;
151
+ /**
152
+ * Get current transactions per second
153
+ *
154
+ * @param period - Time period for the query
155
+ * @returns Current TPS value
156
+ * @throws {NordError} If the request fails
157
+ */
158
+ getCurrentTps(period?: string): Promise<number>;
159
+ /**
160
+ * Get peak transactions per second
161
+ *
162
+ * @param period - Time period for the query
163
+ * @returns Peak TPS value
164
+ * @throws {NordError} If the request fails
165
+ */
166
+ getPeakTps(period?: string): Promise<number>;
167
+ /**
168
+ * Get median transaction latency
169
+ *
170
+ * @param period - Time period for the query
171
+ * @returns Median latency in milliseconds
172
+ * @throws {NordError} If the request fails
173
+ */
174
+ getMedianLatency(period?: string): Promise<number>;
175
+ /**
176
+ * Get total transaction count
177
+ *
178
+ * @returns Total transaction count
179
+ * @throws {NordError} If the request fails
180
+ */
181
+ getTotalTransactions(): Promise<number>;
182
+ /**
183
+ * Query Prometheus metrics
184
+ *
185
+ * @param params - Prometheus query parameters
186
+ * @returns Query result as a number
187
+ * @throws {NordError} If the request fails
188
+ */
189
+ queryPrometheus(params: string): Promise<number>;
190
+ /**
191
+ * Subscribe to orderbook updates for a market
192
+ *
193
+ * @param symbol - Market symbol
194
+ * @returns Orderbook subscription
195
+ * @throws {NordError} If symbol is invalid
196
+ */
197
+ subscribeOrderbook(symbol: string): OrderbookSubscription;
198
+ /**
199
+ * Subscribe to trade updates for a market
200
+ *
201
+ * @param symbol - Market symbol
202
+ * @returns Trade subscription
203
+ * @throws {NordError} If symbol is invalid
204
+ */
205
+ subscribeTrades(symbol: string): TradeSubscription;
206
+ /**
207
+ * Subscribe to account updates
208
+ *
209
+ * @param accountId - Account ID to subscribe to
210
+ * @returns User subscription
211
+ * @throws {NordError} If accountId is invalid
212
+ */
213
+ subscribeAccount(accountId: number): UserSubscription;
214
+ /**
215
+ * Get trades for a market
216
+ *
217
+ * @param query - Trades query parameters
218
+ * @returns Trades response
219
+ * @throws {NordError} If the request fails
220
+ */
221
+ getTrades(query: Readonly<{
222
+ marketId?: number;
223
+ takerId?: number;
224
+ makerId?: number;
225
+ takerSide?: "bid" | "ask";
226
+ pageSize?: number;
227
+ sinceRcf3339?: string;
228
+ untilRfc3339?: string;
229
+ pageId?: string;
230
+ }>): Promise<TradesResponse>;
231
+ /**
232
+ * Get user account IDs
233
+ *
234
+ * @param query - User account IDs query parameters
235
+ * @returns User account IDs response
236
+ * @throws {NordError} If the request fails
237
+ */
238
+ getUser(query: {
239
+ pubkey: string | PublicKey;
240
+ }): Promise<User | null>;
241
+ /**
242
+ * Get orderbook for a market
243
+ *
244
+ * @param query - Orderbook query parameters (either market_id or symbol must be provided)
245
+ * @returns Orderbook response
246
+ * @throws {NordError} If the request fails or if the market symbol is unknown
247
+ * @remarks It's recommended to initialize the Nord client using the static `initNord` method
248
+ * to ensure market information is properly loaded before calling this method.
249
+ */
250
+ getOrderbook(query: OrderbookQuery): Promise<OrderbookResponse>;
251
+ /**
252
+ * Get information about the Nord server
253
+ *
254
+ * @returns Information about markets and tokens
255
+ * @throws {NordError} If the request fails
256
+ */
257
+ getInfo(): Promise<Info>;
258
+ /**
259
+ * Get account information
260
+ *
261
+ * @param accountId - Account ID to get information for
262
+ * @returns Account information
263
+ * @throws {NordError} If the request fails
264
+ */
265
+ getAccount(accountId: number): Promise<Account>;
266
+ /**
267
+ * Get market statistics (alias for marketsStats for backward compatibility)
268
+ *
269
+ * @returns Market statistics response
270
+ */
271
+ getMarketStats({ marketId, }: {
272
+ marketId: number;
273
+ }): Promise<MarketStats>;
274
+ /**
275
+ * Check if an account exists for the given address
276
+ *
277
+ * @param address - The public key address to check
278
+ * @returns True if the account exists, false otherwise
279
+ * @deprecated use getUser instead
280
+ */
281
+ accountExists(pubkey: string | PublicKey): Promise<boolean>;
282
+ }