@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.
- package/.eslintignore +1 -0
- package/.eslintrc.js +20 -0
- package/.prettierignore +1 -0
- package/README.md +110 -0
- package/dist/abis/ERC20_ABI.d.ts +39 -0
- package/dist/abis/ERC20_ABI.js +313 -0
- package/dist/abis/NORD_GETTERS_FACET_ABI.d.ts +34 -0
- package/dist/abis/NORD_GETTERS_FACET_ABI.js +195 -0
- package/dist/abis/NORD_RAMP_FACET_ABI.d.ts +35 -0
- package/dist/abis/NORD_RAMP_FACET_ABI.js +144 -0
- package/dist/abis/index.d.ts +3 -0
- package/dist/abis/index.js +9 -0
- package/dist/const.d.ts +11 -0
- package/dist/const.js +34 -0
- package/dist/gen/common.d.ts +63 -0
- package/dist/gen/common.js +205 -0
- package/dist/gen/nord.d.ts +705 -0
- package/dist/gen/nord.js +4784 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/nord/Nord.d.ts +76 -0
- package/dist/nord/Nord.js +376 -0
- package/dist/nord/NordImpl.d.ts +7 -0
- package/dist/nord/NordImpl.js +6 -0
- package/dist/nord/NordUser.d.ts +77 -0
- package/dist/nord/NordUser.js +249 -0
- package/dist/nord/actions.d.ts +101 -0
- package/dist/nord/actions.js +254 -0
- package/dist/nord/index.d.ts +2 -0
- package/dist/nord/index.js +9 -0
- package/dist/types.d.ts +343 -0
- package/dist/types.js +92 -0
- package/dist/utils.d.ts +114 -0
- package/dist/utils.js +257 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +92 -0
- package/docs/assets/icons.js +15 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +59 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1415 -0
- package/docs/classes/Nord.html +44 -0
- package/docs/classes/NordUser.html +35 -0
- package/docs/classes/Subscriber.html +6 -0
- package/docs/enums/FillMode.html +5 -0
- package/docs/enums/KeyType.html +4 -0
- package/docs/enums/PeakTpsPeriodUnit.html +15 -0
- package/docs/enums/Side.html +3 -0
- package/docs/functions/assert.html +1 -0
- package/docs/functions/bigIntToProtoU128.html +4 -0
- package/docs/functions/checkPubKeyLength.html +1 -0
- package/docs/functions/checkedFetch.html +6 -0
- package/docs/functions/createWebSocketSubscription.html +12 -0
- package/docs/functions/decodeLengthDelimited.html +10 -0
- package/docs/functions/encodeLengthDelimited.html +6 -0
- package/docs/functions/fillModeToProtoFillMode.html +5 -0
- package/docs/functions/findMarket.html +1 -0
- package/docs/functions/findToken.html +1 -0
- package/docs/functions/makeWalletSignFn.html +6 -0
- package/docs/functions/optExpect.html +5 -0
- package/docs/functions/optMap.html +5 -0
- package/docs/functions/optUnwrap.html +2 -0
- package/docs/functions/panic.html +1 -0
- package/docs/functions/signAction.html +6 -0
- package/docs/functions/toScaledU128.html +8 -0
- package/docs/functions/toScaledU64.html +8 -0
- package/docs/index.html +21 -0
- package/docs/interfaces/Account.html +8 -0
- package/docs/interfaces/ActionInfo.html +8 -0
- package/docs/interfaces/ActionQuery.html +4 -0
- package/docs/interfaces/ActionResponse.html +8 -0
- package/docs/interfaces/ActionsExtendedInfo.html +10 -0
- package/docs/interfaces/ActionsQuery.html +5 -0
- package/docs/interfaces/ActionsResponse.html +6 -0
- package/docs/interfaces/AggregateMetrics.html +12 -0
- package/docs/interfaces/BlockQuery.html +6 -0
- package/docs/interfaces/BlockResponse.html +6 -0
- package/docs/interfaces/BlockSummary.html +8 -0
- package/docs/interfaces/BlockSummaryResponse.html +6 -0
- package/docs/interfaces/DeltaEvent.html +6 -0
- package/docs/interfaces/ERC20TokenInfo.html +5 -0
- package/docs/interfaces/Info.html +3 -0
- package/docs/interfaces/Market.html +6 -0
- package/docs/interfaces/MarketStats.html +7 -0
- package/docs/interfaces/MarketsStatsResponse.html +2 -0
- package/docs/interfaces/NordConfig.html +5 -0
- package/docs/interfaces/Order.html +6 -0
- package/docs/interfaces/OrderInfo.html +6 -0
- package/docs/interfaces/OrderbookOrder.html +6 -0
- package/docs/interfaces/OrderbookResponse.html +10 -0
- package/docs/interfaces/PerpMarketStats.html +5 -0
- package/docs/interfaces/RollmanActionExtendedInfo.html +4 -0
- package/docs/interfaces/RollmanActionInfo.html +4 -0
- package/docs/interfaces/RollmanActionResponse.html +4 -0
- package/docs/interfaces/RollmanActionsResponse.html +2 -0
- package/docs/interfaces/RollmanBlockResponse.html +3 -0
- package/docs/interfaces/SubscriberConfig.html +3 -0
- package/docs/interfaces/Token.html +5 -0
- package/docs/interfaces/Trade.html +5 -0
- package/docs/interfaces/TradeInfo.html +20 -0
- package/docs/interfaces/Trades.html +5 -0
- package/docs/interfaces/TradesQueryParams.html +10 -0
- package/docs/interfaces/TradesResponse.html +12 -0
- package/docs/modules.html +77 -0
- package/docs/types/BigIntValue.html +2 -0
- package/docs/variables/DEBUG_KEYS.html +1 -0
- package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -0
- package/docs/variables/DEV_CONTRACT_ADDRESS.html +1 -0
- package/docs/variables/DEV_TOKEN_INFOS.html +1 -0
- package/docs/variables/DEV_URL.html +1 -0
- package/docs/variables/ERC20_ABI.html +1 -0
- package/docs/variables/EVM_DEV_URL.html +1 -0
- package/docs/variables/FAUCET_PRIVATE_ADDRESS.html +1 -0
- package/docs/variables/MAX_BUFFER_LEN.html +1 -0
- package/docs/variables/NORD_GETTERS_FACET_ABI.html +1 -0
- package/docs/variables/NORD_RAMP_FACET_ABI.html +1 -0
- package/docs/variables/SESSION_TTL.html +1 -0
- package/docs/variables/WEBSERVER_DEV_URL.html +1 -0
- package/docs/variables/ZERO_DECIMAL.html +1 -0
- package/jest.config.ts +9 -0
- package/nodemon.json +4 -0
- package/package.json +61 -0
- package/protoc-generate.sh +23 -0
- package/src/abis/ERC20_ABI.ts +310 -0
- package/src/abis/NORD_GETTERS_FACET_ABI.ts +192 -0
- package/src/abis/NORD_RAMP_FACET_ABI.ts +141 -0
- package/src/abis/index.ts +3 -0
- package/src/const.ts +39 -0
- package/src/gen/common.ts +280 -0
- package/src/gen/nord.ts +5666 -0
- package/src/index.ts +5 -0
- package/src/nord/Nord.ts +504 -0
- package/src/nord/NordImpl.ts +8 -0
- package/src/nord/NordUser.ts +469 -0
- package/src/nord/actions.ts +484 -0
- package/src/nord/index.ts +2 -0
- package/src/types.ts +393 -0
- package/src/utils.ts +300 -0
- package/tests/utils.spec.ts +154 -0
- package/tsconfig.json +24 -0
package/dist/index.d.ts
ADDED
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,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
|
+
}
|