@n1xyz/nord-ts 0.0.1

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 (141) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc.js +20 -0
  3. package/.prettierignore +1 -0
  4. package/README.md +110 -0
  5. package/dist/abis/ERC20_ABI.d.ts +39 -0
  6. package/dist/abis/ERC20_ABI.js +313 -0
  7. package/dist/abis/NORD_GETTERS_FACET_ABI.d.ts +34 -0
  8. package/dist/abis/NORD_GETTERS_FACET_ABI.js +195 -0
  9. package/dist/abis/NORD_RAMP_FACET_ABI.d.ts +35 -0
  10. package/dist/abis/NORD_RAMP_FACET_ABI.js +144 -0
  11. package/dist/abis/index.d.ts +3 -0
  12. package/dist/abis/index.js +9 -0
  13. package/dist/const.d.ts +11 -0
  14. package/dist/const.js +34 -0
  15. package/dist/gen/common.d.ts +63 -0
  16. package/dist/gen/common.js +205 -0
  17. package/dist/gen/nord.d.ts +705 -0
  18. package/dist/gen/nord.js +4784 -0
  19. package/dist/index.d.ts +5 -0
  20. package/dist/index.js +21 -0
  21. package/dist/nord/Nord.d.ts +76 -0
  22. package/dist/nord/Nord.js +376 -0
  23. package/dist/nord/NordImpl.d.ts +7 -0
  24. package/dist/nord/NordImpl.js +6 -0
  25. package/dist/nord/NordUser.d.ts +77 -0
  26. package/dist/nord/NordUser.js +249 -0
  27. package/dist/nord/actions.d.ts +101 -0
  28. package/dist/nord/actions.js +254 -0
  29. package/dist/nord/index.d.ts +2 -0
  30. package/dist/nord/index.js +9 -0
  31. package/dist/types.d.ts +343 -0
  32. package/dist/types.js +92 -0
  33. package/dist/utils.d.ts +114 -0
  34. package/dist/utils.js +257 -0
  35. package/docs/.nojekyll +1 -0
  36. package/docs/assets/highlight.css +92 -0
  37. package/docs/assets/icons.js +15 -0
  38. package/docs/assets/icons.svg +1 -0
  39. package/docs/assets/main.js +59 -0
  40. package/docs/assets/navigation.js +1 -0
  41. package/docs/assets/search.js +1 -0
  42. package/docs/assets/style.css +1415 -0
  43. package/docs/classes/Nord.html +44 -0
  44. package/docs/classes/NordUser.html +35 -0
  45. package/docs/classes/Subscriber.html +6 -0
  46. package/docs/enums/FillMode.html +5 -0
  47. package/docs/enums/KeyType.html +4 -0
  48. package/docs/enums/PeakTpsPeriodUnit.html +15 -0
  49. package/docs/enums/Side.html +3 -0
  50. package/docs/functions/assert.html +1 -0
  51. package/docs/functions/bigIntToProtoU128.html +4 -0
  52. package/docs/functions/checkPubKeyLength.html +1 -0
  53. package/docs/functions/checkedFetch.html +6 -0
  54. package/docs/functions/createWebSocketSubscription.html +12 -0
  55. package/docs/functions/decodeLengthDelimited.html +10 -0
  56. package/docs/functions/encodeLengthDelimited.html +6 -0
  57. package/docs/functions/fillModeToProtoFillMode.html +5 -0
  58. package/docs/functions/findMarket.html +1 -0
  59. package/docs/functions/findToken.html +1 -0
  60. package/docs/functions/makeWalletSignFn.html +6 -0
  61. package/docs/functions/optExpect.html +5 -0
  62. package/docs/functions/optMap.html +5 -0
  63. package/docs/functions/optUnwrap.html +2 -0
  64. package/docs/functions/panic.html +1 -0
  65. package/docs/functions/signAction.html +6 -0
  66. package/docs/functions/toScaledU128.html +8 -0
  67. package/docs/functions/toScaledU64.html +8 -0
  68. package/docs/index.html +21 -0
  69. package/docs/interfaces/Account.html +8 -0
  70. package/docs/interfaces/ActionInfo.html +8 -0
  71. package/docs/interfaces/ActionQuery.html +4 -0
  72. package/docs/interfaces/ActionResponse.html +8 -0
  73. package/docs/interfaces/ActionsExtendedInfo.html +10 -0
  74. package/docs/interfaces/ActionsQuery.html +5 -0
  75. package/docs/interfaces/ActionsResponse.html +6 -0
  76. package/docs/interfaces/AggregateMetrics.html +12 -0
  77. package/docs/interfaces/BlockQuery.html +6 -0
  78. package/docs/interfaces/BlockResponse.html +6 -0
  79. package/docs/interfaces/BlockSummary.html +8 -0
  80. package/docs/interfaces/BlockSummaryResponse.html +6 -0
  81. package/docs/interfaces/DeltaEvent.html +6 -0
  82. package/docs/interfaces/ERC20TokenInfo.html +5 -0
  83. package/docs/interfaces/Info.html +3 -0
  84. package/docs/interfaces/Market.html +6 -0
  85. package/docs/interfaces/MarketStats.html +7 -0
  86. package/docs/interfaces/MarketsStatsResponse.html +2 -0
  87. package/docs/interfaces/NordConfig.html +5 -0
  88. package/docs/interfaces/Order.html +6 -0
  89. package/docs/interfaces/OrderInfo.html +6 -0
  90. package/docs/interfaces/OrderbookOrder.html +6 -0
  91. package/docs/interfaces/OrderbookResponse.html +10 -0
  92. package/docs/interfaces/PerpMarketStats.html +5 -0
  93. package/docs/interfaces/RollmanActionExtendedInfo.html +4 -0
  94. package/docs/interfaces/RollmanActionInfo.html +4 -0
  95. package/docs/interfaces/RollmanActionResponse.html +4 -0
  96. package/docs/interfaces/RollmanActionsResponse.html +2 -0
  97. package/docs/interfaces/RollmanBlockResponse.html +3 -0
  98. package/docs/interfaces/SubscriberConfig.html +3 -0
  99. package/docs/interfaces/Token.html +5 -0
  100. package/docs/interfaces/Trade.html +5 -0
  101. package/docs/interfaces/TradeInfo.html +20 -0
  102. package/docs/interfaces/Trades.html +5 -0
  103. package/docs/interfaces/TradesQueryParams.html +10 -0
  104. package/docs/interfaces/TradesResponse.html +12 -0
  105. package/docs/modules.html +77 -0
  106. package/docs/types/BigIntValue.html +2 -0
  107. package/docs/variables/DEBUG_KEYS.html +1 -0
  108. package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -0
  109. package/docs/variables/DEV_CONTRACT_ADDRESS.html +1 -0
  110. package/docs/variables/DEV_TOKEN_INFOS.html +1 -0
  111. package/docs/variables/DEV_URL.html +1 -0
  112. package/docs/variables/ERC20_ABI.html +1 -0
  113. package/docs/variables/EVM_DEV_URL.html +1 -0
  114. package/docs/variables/FAUCET_PRIVATE_ADDRESS.html +1 -0
  115. package/docs/variables/MAX_BUFFER_LEN.html +1 -0
  116. package/docs/variables/NORD_GETTERS_FACET_ABI.html +1 -0
  117. package/docs/variables/NORD_RAMP_FACET_ABI.html +1 -0
  118. package/docs/variables/SESSION_TTL.html +1 -0
  119. package/docs/variables/WEBSERVER_DEV_URL.html +1 -0
  120. package/docs/variables/ZERO_DECIMAL.html +1 -0
  121. package/jest.config.ts +9 -0
  122. package/nodemon.json +4 -0
  123. package/package.json +61 -0
  124. package/protoc-generate.sh +23 -0
  125. package/src/abis/ERC20_ABI.ts +310 -0
  126. package/src/abis/NORD_GETTERS_FACET_ABI.ts +192 -0
  127. package/src/abis/NORD_RAMP_FACET_ABI.ts +141 -0
  128. package/src/abis/index.ts +3 -0
  129. package/src/const.ts +39 -0
  130. package/src/gen/common.ts +280 -0
  131. package/src/gen/nord.ts +5666 -0
  132. package/src/index.ts +5 -0
  133. package/src/nord/Nord.ts +504 -0
  134. package/src/nord/NordImpl.ts +8 -0
  135. package/src/nord/NordUser.ts +469 -0
  136. package/src/nord/actions.ts +484 -0
  137. package/src/nord/index.ts +2 -0
  138. package/src/types.ts +393 -0
  139. package/src/utils.ts +300 -0
  140. package/tests/utils.spec.ts +154 -0
  141. package/tsconfig.json +24 -0
@@ -0,0 +1,5 @@
1
+ export * from "./types";
2
+ export * from "./utils";
3
+ export * from "./abis";
4
+ export * from "./nord";
5
+ export * from "./const";
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./utils"), exports);
19
+ __exportStar(require("./abis"), exports);
20
+ __exportStar(require("./nord"), exports);
21
+ __exportStar(require("./const"), exports);
@@ -0,0 +1,76 @@
1
+ import { ActionQuery, ActionResponse, ActionsResponse, AggregateMetrics, BlockQuery, BlockResponse, BlockSummaryResponse, type DeltaEvent, ERC20TokenInfo, type Market, NordConfig, PeakTpsPeriodUnit, RollmanActionResponse, RollmanActionsResponse, RollmanBlockResponse, MarketsStatsResponse, type SubscriberConfig, type Token, type Trades, type Account, type OrderbookResponse, type TradesResponse, type TradesQueryParams } from "../types";
2
+ import { NordImpl } from "./NordImpl";
3
+ export declare function depositOnlyTx(privateAddress: string, publicKey: Uint8Array, amount: number, precision: number, contractAddress: string): Promise<string>;
4
+ export declare function depositOnlyTxRaw(privateAddress: string, publicKey: Uint8Array, amount: number, precision: number, contractAddress: string): Promise<string>;
5
+ export declare class Nord {
6
+ impl: NordImpl;
7
+ evmUrl: string;
8
+ webServerUrl: string;
9
+ contractAddress: string;
10
+ tokenInfos: ERC20TokenInfo[];
11
+ markets: Market[];
12
+ tokens: Token[];
13
+ constructor({ evmUrl, webServerUrl, tokenInfos, contractAddress, }: NordConfig);
14
+ getTimestamp(): Promise<bigint>;
15
+ getActionNonce(): Promise<number>;
16
+ fetchNordInfo(): Promise<void>;
17
+ static initNord(nordConfig: NordConfig): Promise<Nord>;
18
+ static initDevNord(): Promise<Nord>;
19
+ marketsStats(): Promise<MarketsStatsResponse>;
20
+ queryBlock(query: BlockQuery): Promise<BlockResponse>;
21
+ queryLastNBlocks(): Promise<BlockResponse>;
22
+ queryRecentBlocks(last_n: number): Promise<BlockSummaryResponse>;
23
+ queryAction(query: ActionQuery): Promise<ActionResponse>;
24
+ queryRecentActions(last_n: number): Promise<ActionsResponse>;
25
+ aggregateMetrics(txPeakTpsPeriod?: number, txPeakTpsPeriodUnit?: PeakTpsPeriodUnit): Promise<AggregateMetrics>;
26
+ getCurrentTps(period?: string): Promise<number>;
27
+ getPeakTps(period?: string): Promise<number>;
28
+ getMedianLatency(period?: string): Promise<number>;
29
+ getTotalTransactions(): Promise<string>;
30
+ blockQueryRollman(query: BlockQuery): Promise<RollmanBlockResponse>;
31
+ blockSummaryQueryRollman(last_n: number): Promise<BlockSummaryResponse>;
32
+ actionQueryRollman(query: ActionQuery): Promise<RollmanActionResponse>;
33
+ actionsQueryRollman(last_n: number): Promise<RollmanActionsResponse>;
34
+ queryPrometheus(params: string): Promise<number>;
35
+ static approveTx(privateAddress: string, erc20address: string, contractAddress: string): Promise<void>;
36
+ /**
37
+ * Fetches a sequence of actions between specified action IDs
38
+ * @param fromActionId - Starting action ID
39
+ * @param toActionId - Ending action ID
40
+ * @returns A promise that resolves to an ActionsResponse
41
+ */
42
+ getActions(fromActionId: number, toActionId: number): Promise<ActionsResponse>;
43
+ /**
44
+ * Fetches trades for a specified account
45
+ * @param params - Query parameters for fetching trades
46
+ * @returns A promise that resolves to a TradesResponse
47
+ */
48
+ getTrades(params: TradesQueryParams): Promise<TradesResponse>;
49
+ /**
50
+ * Fetches the orderbook for a specified market
51
+ * @param symbol - Market symbol
52
+ * @returns A promise that resolves to an OrderbookResponse
53
+ */
54
+ getOrderbook(symbol: string): Promise<OrderbookResponse>;
55
+ }
56
+ export declare class Subscriber {
57
+ streamURL: string;
58
+ buffer: (DeltaEvent | Trades | Account)[];
59
+ maxBufferLen: number;
60
+ constructor(config: SubscriberConfig);
61
+ subscribe(): void;
62
+ }
63
+ /**
64
+ * Creates a WebSocket subscription to specified streams
65
+ * @param baseUrl - Base URL of the API
66
+ * @param streams - Array of streams to subscribe to
67
+ * @returns A Subscriber instance
68
+ *
69
+ * Syntax for streams:
70
+ * - trades@<symbol>: Subscribe to trades for a market
71
+ * - deltas@<symbol>: Subscribe to orderbook deltas for a market
72
+ * - user@<user id>: Subscribe to user account updates
73
+ *
74
+ * Example: createWebSocketSubscription('https://alpha-api.layern.network', ['trades@BTCUSDC', 'deltas@BTCUSDC', 'user@0'])
75
+ */
76
+ export declare function createWebSocketSubscription(baseUrl: string, streams: string[]): Subscriber;
@@ -0,0 +1,376 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Subscriber = exports.Nord = void 0;
40
+ exports.depositOnlyTx = depositOnlyTx;
41
+ exports.depositOnlyTxRaw = depositOnlyTxRaw;
42
+ exports.createWebSocketSubscription = createWebSocketSubscription;
43
+ const ethers_1 = require("ethers");
44
+ const ws_1 = __importDefault(require("ws"));
45
+ const types_1 = require("../types");
46
+ const utils_1 = require("../utils");
47
+ const const_1 = require("../const");
48
+ const abis_1 = require("../abis");
49
+ const proto = __importStar(require("../gen/nord"));
50
+ async function depositOnlyTx(privateAddress, publicKey, amount, precision, contractAddress) {
51
+ const provider = new ethers_1.ethers.JsonRpcProvider(process.env.SECRET_FAUCET_RPC);
52
+ const wallet = new ethers_1.ethers.Wallet(privateAddress, provider);
53
+ const nordContract = new ethers_1.ethers.Contract(contractAddress, abis_1.NORD_RAMP_FACET_ABI, wallet);
54
+ const depositTx = await nordContract.depositUnchecked(publicKey, BigInt(0), ethers_1.ethers.parseUnits(amount.toString(), precision), {
55
+ gasLimit: 1000000,
56
+ maxFeePerGas: ethers_1.ethers.parseUnits("100", "gwei"),
57
+ maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.01", "gwei"),
58
+ });
59
+ return depositTx.hash;
60
+ }
61
+ async function depositOnlyTxRaw(privateAddress, publicKey, amount, precision, contractAddress) {
62
+ const provider = new ethers_1.ethers.JsonRpcProvider(process.env.SECRET_FAUCET_RPC);
63
+ const wallet = new ethers_1.ethers.Wallet(privateAddress, provider);
64
+ const nordContract = new ethers_1.ethers.Contract(contractAddress, abis_1.NORD_RAMP_FACET_ABI, wallet);
65
+ const depositTx = await nordContract.depositUnchecked.populateTransaction(publicKey, BigInt(0), ethers_1.ethers.parseUnits(amount.toString(), precision), {
66
+ maxFeePerGas: ethers_1.ethers.parseUnits("0.0003", "gwei"),
67
+ maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.0003", "gwei"),
68
+ });
69
+ return JSON.stringify(depositTx);
70
+ }
71
+ function makeNordImpl(nord) {
72
+ return {
73
+ getTimestamp: () => nord.getTimestamp().then((x) => x + 1n),
74
+ };
75
+ }
76
+ class Nord {
77
+ constructor({ evmUrl, webServerUrl, tokenInfos, contractAddress, }) {
78
+ this.impl = makeNordImpl(this);
79
+ this.evmUrl = evmUrl;
80
+ this.webServerUrl = webServerUrl;
81
+ this.tokenInfos = tokenInfos;
82
+ this.contractAddress = contractAddress;
83
+ this.markets = [];
84
+ this.tokens = [];
85
+ }
86
+ async getTimestamp() {
87
+ const resp = await (await (0, utils_1.checkedFetch)(`${this.webServerUrl}/timestamp`, { method: "GET" })).json();
88
+ return BigInt(resp);
89
+ }
90
+ async getActionNonce() {
91
+ const resp = await (await (0, utils_1.checkedFetch)(`${this.webServerUrl}/action_nonce`, { method: "GET" })).json();
92
+ return resp;
93
+ }
94
+ async fetchNordInfo() {
95
+ const response = await (0, utils_1.checkedFetch)(`${this.webServerUrl}/info`, {
96
+ method: "GET",
97
+ });
98
+ const info = await response.json();
99
+ this.markets = info.markets;
100
+ this.tokens = info.tokens;
101
+ }
102
+ static async initNord(nordConfig) {
103
+ const nord = new Nord(nordConfig);
104
+ await nord.fetchNordInfo();
105
+ return nord;
106
+ }
107
+ static async initDevNord() {
108
+ const nord = new Nord({
109
+ evmUrl: const_1.EVM_DEV_URL,
110
+ webServerUrl: const_1.WEBSERVER_DEV_URL,
111
+ tokenInfos: const_1.DEV_TOKEN_INFOS,
112
+ contractAddress: const_1.DEV_CONTRACT_ADDRESS,
113
+ });
114
+ await nord.fetchNordInfo();
115
+ return nord;
116
+ }
117
+ async marketsStats() {
118
+ const response = await (0, utils_1.checkedFetch)(`${this.webServerUrl}/stats`, {
119
+ method: "GET",
120
+ });
121
+ const stats = await response.json();
122
+ return stats;
123
+ }
124
+ // Query the block info from rollman.
125
+ async queryBlock(query) {
126
+ const rollmanResponse = await this.blockQueryRollman(query);
127
+ const queryResponse = {
128
+ block_number: rollmanResponse.block_number,
129
+ actions: [],
130
+ };
131
+ for (const rollmanAction of rollmanResponse.actions) {
132
+ const blockAction = {
133
+ action_id: rollmanAction.action_id,
134
+ action: (0, utils_1.decodeLengthDelimited)(new Uint8Array(rollmanAction.action_pb), proto.Action),
135
+ exec_timestamp: rollmanAction.exec_timestamp,
136
+ };
137
+ queryResponse.actions.push(blockAction);
138
+ }
139
+ return queryResponse;
140
+ }
141
+ // Query the block info from rollman.
142
+ async queryLastNBlocks() {
143
+ const rollmanResponse = await this.blockQueryRollman({});
144
+ const queryResponse = {
145
+ block_number: rollmanResponse.block_number,
146
+ actions: [],
147
+ };
148
+ for (const rollmanAction of rollmanResponse.actions) {
149
+ const blockAction = {
150
+ action_id: rollmanAction.action_id,
151
+ action: (0, utils_1.decodeLengthDelimited)(rollmanAction.action_pb, proto.Action),
152
+ exec_timestamp: rollmanAction.exec_timestamp,
153
+ };
154
+ queryResponse.actions.push(blockAction);
155
+ }
156
+ return queryResponse;
157
+ }
158
+ // Query the block summary of recent blocks from rollman.
159
+ async queryRecentBlocks(last_n) {
160
+ const response = await this.blockSummaryQueryRollman(last_n);
161
+ return response;
162
+ }
163
+ // Query the action info from rollman.
164
+ async queryAction(query) {
165
+ const rollmanResponse = await this.actionQueryRollman(query);
166
+ return {
167
+ block_number: rollmanResponse.block_number,
168
+ action: (0, utils_1.decodeLengthDelimited)(rollmanResponse.action_pb, proto.Action),
169
+ };
170
+ }
171
+ // Query the recent transactions from rollman.
172
+ async queryRecentActions(last_n) {
173
+ const rollmanResponse = await this.actionsQueryRollman(last_n);
174
+ const queryResponse = {
175
+ actions: [],
176
+ };
177
+ for (const rollmanExtendedAction of rollmanResponse.actions) {
178
+ const extendedActionInfo = {
179
+ block_number: rollmanExtendedAction.block_number,
180
+ action_id: rollmanExtendedAction.action_id,
181
+ action: (0, utils_1.decodeLengthDelimited)(rollmanExtendedAction.action_pb, proto.Action),
182
+ };
183
+ queryResponse.actions.push(extendedActionInfo);
184
+ }
185
+ return queryResponse;
186
+ }
187
+ // Query the aggregate metrics across nord and rollman.
188
+ async aggregateMetrics(txPeakTpsPeriod = 1, txPeakTpsPeriodUnit = types_1.PeakTpsPeriodUnit.Day) {
189
+ // Get the latest block number for L2 blocks.
190
+ const blockQuery = {};
191
+ const rollmanResponse = await this.blockQueryRollman(blockQuery);
192
+ const period = txPeakTpsPeriod.toString() + txPeakTpsPeriodUnit;
193
+ const query = `max_over_time(rate(nord_requests_ok_count[1m])[${period}:1m])`;
194
+ return {
195
+ blocks_total: rollmanResponse.block_number,
196
+ tx_total: await this.queryPrometheus("nord_requests_ok_count"),
197
+ tx_tps: await this.getCurrentTps(),
198
+ tx_tps_peak: await this.queryPrometheus(query),
199
+ request_latency_average: await this.queryPrometheus('nord_requests_ok_latency{quantile="0.5"}'),
200
+ };
201
+ }
202
+ async getCurrentTps(period = "1m") {
203
+ return await this.queryPrometheus("rate(nord_requests_ok_count[" + period + "])");
204
+ }
205
+ async getPeakTps(period = "24h") {
206
+ return await this.queryPrometheus("max_over_time(rate(nord_requests_ok_count[30s])[" + period + ":])");
207
+ }
208
+ async getMedianLatency(period = "1m") {
209
+ return await this.queryPrometheus(`avg_over_time(nord_requests_ok_latency{quantile="0.5"}[${period}])`);
210
+ }
211
+ async getTotalTransactions() {
212
+ return await (await (0, utils_1.checkedFetch)(this.webServerUrl + "/last_actionid")).text();
213
+ }
214
+ // Helper to query rollman for block info.
215
+ async blockQueryRollman(query) {
216
+ let url = this.webServerUrl + "/block_query";
217
+ if (query.block_number != null) {
218
+ url = url + "?block_number=" + query.block_number;
219
+ }
220
+ const response = await (0, utils_1.checkedFetch)(url);
221
+ if (!response.ok) {
222
+ throw new Error("Rollman query failed " + url);
223
+ }
224
+ return await response.json();
225
+ }
226
+ // Helper to query rollman for recent block summary.
227
+ async blockSummaryQueryRollman(last_n) {
228
+ const url = this.webServerUrl + "/last_n_blocks?last_n=" + last_n;
229
+ const response = await (0, utils_1.checkedFetch)(url);
230
+ if (!response.ok) {
231
+ throw new Error("Rollman query failed " + url);
232
+ }
233
+ return await response.json();
234
+ }
235
+ // Helper to query rollman for action info.
236
+ async actionQueryRollman(query) {
237
+ const url = this.webServerUrl + "/tx_query?action_id=" + query.action_id;
238
+ const response = await (0, utils_1.checkedFetch)(url);
239
+ if (!response.ok) {
240
+ throw new Error("Rollman query failed " + url);
241
+ }
242
+ return await response.json();
243
+ }
244
+ // Helper to query rollman for recent actions.
245
+ async actionsQueryRollman(last_n) {
246
+ const url = this.webServerUrl + "/last_n_actions?last_n=" + last_n;
247
+ const response = await (0, utils_1.checkedFetch)(url);
248
+ if (!response.ok) {
249
+ throw new Error("Rollman query failed " + url);
250
+ }
251
+ return await response.json();
252
+ }
253
+ // Helper to query prometheus.
254
+ async queryPrometheus(params) {
255
+ const url = this.webServerUrl + "/prometheus_query?query=" + params;
256
+ const response = await (0, utils_1.checkedFetch)(url);
257
+ if (!response.ok) {
258
+ throw new Error("Prometheus query failed " + url);
259
+ }
260
+ const json = await response.json();
261
+ // Prometheus HTTP API: https://prometheus.io/docs/prometheus/latest/querying/api/
262
+ return Number(json.data.result[0].value[1]);
263
+ }
264
+ static async approveTx(privateAddress, erc20address, contractAddress) {
265
+ const provider = new ethers_1.ethers.JsonRpcProvider(process.env.SECRET_FAUCET_RPC);
266
+ const wallet = new ethers_1.ethers.Wallet(privateAddress, provider);
267
+ const erc20Contract = new ethers_1.ethers.Contract(erc20address, abis_1.ERC20_ABI, wallet);
268
+ const maxUint256 = ethers_1.ethers.MaxUint256;
269
+ const approveTx = await erc20Contract.approve(contractAddress, maxUint256.toString(), {
270
+ maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
271
+ maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
272
+ });
273
+ return approveTx.hash;
274
+ }
275
+ /**
276
+ * Fetches a sequence of actions between specified action IDs
277
+ * @param fromActionId - Starting action ID
278
+ * @param toActionId - Ending action ID
279
+ * @returns A promise that resolves to an ActionsResponse
280
+ */
281
+ async getActions(fromActionId, toActionId) {
282
+ const response = await (0, utils_1.checkedFetch)(`${this.webServerUrl}/actions?from=${fromActionId}&to=${toActionId}`, { method: "GET" });
283
+ const rawResponse = await response.json();
284
+ const queryResponse = {
285
+ actions: [],
286
+ };
287
+ if (Array.isArray(rawResponse.actions)) {
288
+ for (const action of rawResponse.actions) {
289
+ const extendedActionInfo = {
290
+ block_number: action.block_number,
291
+ action_id: action.action_id,
292
+ action: (0, utils_1.decodeLengthDelimited)(action.action_pb, proto.Action),
293
+ };
294
+ queryResponse.actions.push(extendedActionInfo);
295
+ }
296
+ }
297
+ return queryResponse;
298
+ }
299
+ /**
300
+ * Fetches trades for a specified account
301
+ * @param params - Query parameters for fetching trades
302
+ * @returns A promise that resolves to a TradesResponse
303
+ */
304
+ async getTrades(params) {
305
+ const { accountId, since, until, pageId } = params;
306
+ let url = `${this.webServerUrl}/trades?accountId=${accountId}`;
307
+ if (since) {
308
+ url += `&since=${encodeURIComponent(since)}`;
309
+ }
310
+ if (until) {
311
+ url += `&until=${encodeURIComponent(until)}`;
312
+ }
313
+ if (pageId) {
314
+ url += `&pageId=${encodeURIComponent(pageId)}`;
315
+ }
316
+ const response = await (0, utils_1.checkedFetch)(url, { method: "GET" });
317
+ const tradesResponse = await response.json();
318
+ return tradesResponse;
319
+ }
320
+ /**
321
+ * Fetches the orderbook for a specified market
322
+ * @param symbol - Market symbol
323
+ * @returns A promise that resolves to an OrderbookResponse
324
+ */
325
+ async getOrderbook(symbol) {
326
+ const response = await (0, utils_1.checkedFetch)(`${this.webServerUrl}/orderbook?symbol=${encodeURIComponent(symbol)}`, { method: "GET" });
327
+ const orderbook = await response.json();
328
+ return orderbook;
329
+ }
330
+ }
331
+ exports.Nord = Nord;
332
+ class Subscriber {
333
+ constructor(config) {
334
+ this.streamURL = config.streamURL;
335
+ this.buffer = [];
336
+ this.maxBufferLen = config.maxBufferLen || utils_1.MAX_BUFFER_LEN;
337
+ }
338
+ subscribe() {
339
+ const ws = new ws_1.default(this.streamURL);
340
+ ws.on("message", (data) => {
341
+ try {
342
+ const parsed = JSON.parse(data.toString());
343
+ this.buffer.push(parsed);
344
+ if (this.buffer.length > this.maxBufferLen) {
345
+ this.buffer.shift();
346
+ }
347
+ }
348
+ catch (e) {
349
+ console.error("Failed to parse websocket message", e);
350
+ }
351
+ });
352
+ }
353
+ }
354
+ exports.Subscriber = Subscriber;
355
+ /**
356
+ * Creates a WebSocket subscription to specified streams
357
+ * @param baseUrl - Base URL of the API
358
+ * @param streams - Array of streams to subscribe to
359
+ * @returns A Subscriber instance
360
+ *
361
+ * Syntax for streams:
362
+ * - trades@<symbol>: Subscribe to trades for a market
363
+ * - deltas@<symbol>: Subscribe to orderbook deltas for a market
364
+ * - user@<user id>: Subscribe to user account updates
365
+ *
366
+ * Example: createWebSocketSubscription('https://alpha-api.layern.network', ['trades@BTCUSDC', 'deltas@BTCUSDC', 'user@0'])
367
+ */
368
+ function createWebSocketSubscription(baseUrl, streams) {
369
+ const streamPath = streams.join('&');
370
+ const wsUrl = baseUrl.replace(/^http/, 'ws') + `/ws/${streamPath}`;
371
+ const subscriber = new Subscriber({
372
+ streamURL: wsUrl,
373
+ });
374
+ subscriber.subscribe();
375
+ return subscriber;
376
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Implementation of some functions backing Nord and NordUser as interface,
3
+ * for mocking reasons
4
+ */
5
+ export interface NordImpl {
6
+ getTimestamp: () => Promise<bigint>;
7
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Implementation of some functions backing Nord and NordUser as interface,
4
+ * for mocking reasons
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,77 @@
1
+ import { BrowserProvider } from "ethers";
2
+ import { BigIntValue } from "../utils";
3
+ import { FillMode, Order, Side } from "../types";
4
+ import { Nord } from "./Nord";
5
+ import Decimal from "decimal.js";
6
+ export declare class NordUser {
7
+ nord: Nord;
8
+ address: string;
9
+ walletSignFn: (message: Uint8Array | string) => Promise<string>;
10
+ sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
11
+ balances: {
12
+ [key: string]: {
13
+ accountId: number;
14
+ balance: number;
15
+ symbol: string;
16
+ }[];
17
+ };
18
+ orders: {
19
+ [key: string]: Order[];
20
+ };
21
+ accountIds?: number[];
22
+ sessionId?: bigint;
23
+ publicKey: Uint8Array | undefined;
24
+ lastTs: number;
25
+ lastNonce: number;
26
+ constructor(params: {
27
+ nord: Nord;
28
+ address: string;
29
+ walletSignFn: (message: Uint8Array | string) => Promise<string>;
30
+ sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
31
+ });
32
+ clone(): NordUser;
33
+ /**
34
+ * Generates a nonce based on the current timestamp.
35
+ * @returns Generated nonce as a number.
36
+ */
37
+ getNonce(): number;
38
+ updateAccountId(): Promise<void>;
39
+ fetchInfo(): Promise<void>;
40
+ setPublicKey(): Promise<void>;
41
+ fundEthWallet(): Promise<void>;
42
+ fundErc20Wallet(): Promise<void>;
43
+ refreshSession(sessionPk: Uint8Array): Promise<void>;
44
+ /**
45
+ * Revokes session previously created by user
46
+ *
47
+ * @param sessionId - session identifier
48
+ */
49
+ revokeSession(sessionId: BigIntValue): Promise<void>;
50
+ deposit(provider: BrowserProvider, amount: number, tokenId: number): Promise<void>;
51
+ depositApproveTx(provider: BrowserProvider, amount: number, tokenId: number): Promise<void>;
52
+ depositOnlyTx(provider: BrowserProvider, amount: number, tokenId: number): Promise<void>;
53
+ depositEth(provider: BrowserProvider, amount: number, tokenId: number): Promise<void>;
54
+ withdraw(tokenId: number, amount: number): Promise<void>;
55
+ placeOrder(params: {
56
+ marketId: number;
57
+ side: Side;
58
+ fillMode: FillMode;
59
+ isReduceOnly: boolean;
60
+ size?: Decimal.Value;
61
+ price?: Decimal.Value;
62
+ quoteSize?: Decimal.Value;
63
+ accountId?: number;
64
+ }): Promise<bigint | undefined>;
65
+ cancelOrder(orderId: BigIntValue, accountId: number): Promise<bigint>;
66
+ transferToAccount(params: {
67
+ to: NordUser;
68
+ tokenId: number;
69
+ amount: Decimal.Value;
70
+ fromAccountId: number;
71
+ toAccountId: number;
72
+ }): Promise<void>;
73
+ createAccount(params: {
74
+ tokenId: number;
75
+ amount: Decimal.Value;
76
+ }): Promise<NordUser>;
77
+ }