@n1xyz/nord-ts 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/actions.js +184 -0
  2. package/dist/client/Nord.d.ts +9 -15
  3. package/dist/client/Nord.js +759 -0
  4. package/dist/client/NordAdmin.js +362 -0
  5. package/dist/client/NordUser.d.ts +3 -1
  6. package/dist/client/NordUser.js +752 -0
  7. package/dist/const.js +27 -0
  8. package/dist/error.js +51 -0
  9. package/dist/gen/nord_pb.d.ts +132 -114
  10. package/dist/gen/nord_pb.js +1068 -0
  11. package/dist/gen/openapi.d.ts +345 -72
  12. package/dist/gen/openapi.js +5 -0
  13. package/dist/index.browser.js +61342 -80207
  14. package/dist/index.common.js +59722 -87597
  15. package/dist/index.js +10 -0
  16. package/dist/nord/api/actions.d.ts +128 -0
  17. package/dist/nord/api/actions.js +396 -0
  18. package/dist/nord/api/core.d.ts +16 -0
  19. package/dist/nord/api/core.js +81 -0
  20. package/dist/nord/api/metrics.d.ts +67 -0
  21. package/dist/nord/api/metrics.js +229 -0
  22. package/dist/nord/api/triggers.d.ts +7 -0
  23. package/dist/nord/api/triggers.js +38 -0
  24. package/dist/nord/client/Nord.d.ts +387 -0
  25. package/dist/nord/client/Nord.js +747 -0
  26. package/dist/nord/client/NordAdmin.d.ts +226 -0
  27. package/dist/nord/client/NordAdmin.js +410 -0
  28. package/dist/nord/client/NordClient.d.ts +16 -0
  29. package/dist/nord/client/NordClient.js +28 -0
  30. package/dist/nord/client/NordUser.d.ts +379 -0
  31. package/dist/nord/client/NordUser.js +787 -0
  32. package/dist/nord/index.d.ts +8 -0
  33. package/dist/nord/index.js +34 -0
  34. package/dist/nord/models/Subscriber.d.ts +37 -0
  35. package/dist/nord/models/Subscriber.js +25 -0
  36. package/dist/nord/utils/NordError.d.ts +35 -0
  37. package/dist/nord/utils/NordError.js +49 -0
  38. package/dist/types.d.ts +15 -6
  39. package/dist/types.js +92 -0
  40. package/dist/utils.js +193 -0
  41. package/dist/websocket/NordWebSocketClient.d.ts +1 -0
  42. package/dist/websocket/NordWebSocketClient.js +242 -0
  43. package/dist/websocket/Subscriber.d.ts +7 -1
  44. package/dist/websocket/Subscriber.js +24 -0
  45. package/dist/websocket/events.d.ts +2 -1
  46. package/dist/websocket/events.js +1 -0
  47. package/dist/websocket/index.d.ts +1 -1
  48. package/dist/websocket/index.js +80 -0
  49. package/package.json +2 -2
@@ -0,0 +1,226 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import * as proto from "../../gen/nord_pb";
3
+ import { Nord } from "./Nord";
4
+ import { FeeTierConfig } from "../../gen/nord_pb";
5
+ export declare enum AclRole {
6
+ FEE_MANAGER = 1,
7
+ MARKET_MANAGER = 2,
8
+ ADMIN = -2147483648
9
+ }
10
+ /**
11
+ * Administrative client capable of submitting privileged configuration actions.
12
+ */
13
+ export declare class NordAdmin {
14
+ private readonly nord;
15
+ private readonly admin;
16
+ private readonly signFn;
17
+ private constructor();
18
+ /** Create a new admin client.
19
+ *
20
+ * @param nord - Nord instance
21
+ * @param admin - The user that will be signing actions.
22
+ * @param signFn - Function to sign messages with the admin's wallet.
23
+ *
24
+ * `signFn` must sign the _hex-encoded_ message, not the raw message itself, for
25
+ * the purpose of being compatible with Solana wallets.
26
+ *
27
+ * In practice, you will do something along the lines of:
28
+ *
29
+ * ```typescript
30
+ * (x) => wallet.signMessage(new TextEncoder().encode(x.toHex()));
31
+ * ```
32
+ *
33
+ * For a software signing key, this might look more like:
34
+ *
35
+ * ```typescript
36
+ * (x) => nacl.sign.detached(new TextEncoder().encode(x.toHex()), sk);
37
+ * ``
38
+ *
39
+ * where `nacl` is the tweetnacl library.
40
+ */
41
+ static new({ nord, admin, signFn, }: Readonly<{
42
+ nord: Nord;
43
+ admin: PublicKey;
44
+ signFn: (m: Uint8Array) => Promise<Uint8Array>;
45
+ }>): NordAdmin;
46
+ /**
47
+ * Submit an action and append the admin signature before sending it to Nord.
48
+ *
49
+ * @param kind - Action payload describing the admin request
50
+ * @throws {NordError} If signing or submission fails
51
+ */
52
+ private submitAction;
53
+ /** Set acl permissions for a given user.
54
+ *
55
+ * If all roles are removed, the user is removed from the acl.
56
+ *
57
+ * @param target - User to update.
58
+ * @param addRoles - Roles to add to the user.
59
+ * @param removeRoles - Reles to remove from the user.
60
+ */
61
+ updateAcl({ target, addRoles, removeRoles, }: Readonly<{
62
+ target: PublicKey;
63
+ addRoles: AclRole[];
64
+ removeRoles: AclRole[];
65
+ }>): Promise<{
66
+ actionId: bigint;
67
+ } & proto.Receipt_AclUpdated>;
68
+ /**
69
+ * Register a new token that can be listed on Nord.
70
+ *
71
+ * @param mintAddr - SPL mint to register
72
+ * @param tokenDecimals - On-chain decimal precision
73
+ * @param weightBps - Risk weight in basis points
74
+ * @param viewSymbol - Symbol shown to users
75
+ * @param oracleSymbol - Symbol used by the oracle
76
+ * @returns Action identifier and resulting token metadata
77
+ * @throws {NordError} If the action submission fails
78
+ */
79
+ createToken({ mintAddr, tokenDecimals, weightBps, viewSymbol, oracleSymbol, }: Readonly<Omit<proto.Action_CreateToken, "aclPubkey" | "solAddr">> & {
80
+ mintAddr: PublicKey;
81
+ }): Promise<{
82
+ actionId: bigint;
83
+ } & proto.Receipt_InsertTokenResult>;
84
+ /**
85
+ * Open a new market with explicit trading parameters.
86
+ *
87
+ * @param sizeDecimals - Base asset decimal precision
88
+ * @param priceDecimals - Quote price decimal precision
89
+ * @param imfBps - Initial margin fraction in basis points
90
+ * @param cmfBps - Cancel margin fraction in basis points
91
+ * @param mmfBps - Maintenance margin fraction in basis points
92
+ * @param marketType - Market kind to open
93
+ * @param viewSymbol - Symbol shown to users
94
+ * @param oracleSymbol - Symbol used by the oracle
95
+ * @param baseTokenId - Token id used as the base asset
96
+ * @returns Action identifier and resulting market metadata
97
+ * @throws {NordError} If the action submission fails
98
+ */
99
+ createMarket({ sizeDecimals, priceDecimals, imfBps, cmfBps, mmfBps, marketType, viewSymbol, oracleSymbol, baseTokenId, }: Readonly<Omit<proto.Action_CreateMarket, "aclPubkey">>): Promise<{
100
+ actionId: bigint;
101
+ } & proto.Receipt_InsertMarketResult>;
102
+ /**
103
+ * Update the Pyth guardian set used for verifying Wormhole messages.
104
+ *
105
+ * Each address must decode from a 20-byte hex string (with or without a
106
+ * leading `0x` prefix). The engine validates the supplied guardian set index
107
+ * before applying the update.
108
+ *
109
+ * @param guardianSetIndex - Wormhole guardian set identifier
110
+ * @param guardianAddresses - Guardian addresses as 20-byte hex strings
111
+ * @returns Action identifier and guardian update receipt
112
+ * @throws {NordError} If the action submission fails
113
+ */
114
+ pythSetWormholeGuardians({ guardianSetIndex, addresses: guardianAddresses, }: Readonly<{
115
+ guardianSetIndex: number;
116
+ addresses: string[];
117
+ }>): Promise<{
118
+ actionId: bigint;
119
+ } & proto.Receipt_UpdateGuardianSetResult>;
120
+ /**
121
+ * Link an oracle symbol to a specific Pyth price feed.
122
+ *
123
+ * The price feed identifier must decode to 32 bytes (with or without a
124
+ * leading `0x` prefix). Use this call to create or update the mapping used
125
+ * by the oracle integration.
126
+ *
127
+ * @param oracleSymbol - Symbol to update
128
+ * @param priceFeedHex - 32-byte hex price feed id
129
+ * @returns Action identifier and symbol feed receipt
130
+ * @throws {NordError} If the action submission fails
131
+ */
132
+ pythSetSymbolFeed({ oracleSymbol, priceFeedId: priceFeedHex, }: Readonly<{
133
+ oracleSymbol: string;
134
+ priceFeedId: string;
135
+ }>): Promise<{
136
+ actionId: bigint;
137
+ } & proto.Receipt_OracleSymbolFeedResult>;
138
+ /**
139
+ * Pause all trading activity on the exchange.
140
+ *
141
+ * @returns Action identifier confirming the pause
142
+ * @throws {NordError} If the action submission fails
143
+ */
144
+ pause(): Promise<{
145
+ actionId: bigint;
146
+ }>;
147
+ /**
148
+ * Resume trading activity after a pause.
149
+ *
150
+ * @returns Action identifier confirming the unpause
151
+ * @throws {NordError} If the action submission fails
152
+ */
153
+ unpause(): Promise<{
154
+ actionId: bigint;
155
+ }>;
156
+ /**
157
+ * Freeze an individual market, preventing new trades and orders.
158
+ *
159
+ * @param marketId - Target market identifier
160
+ * @returns Action identifier and freeze receipt
161
+ * @throws {NordError} If the action submission fails
162
+ */
163
+ freezeMarket({ marketId, }: Readonly<{
164
+ marketId: number;
165
+ }>): Promise<{
166
+ actionId: bigint;
167
+ } & proto.Receipt_MarketFreezeUpdated>;
168
+ /**
169
+ * Unfreeze a market that was previously halted.
170
+ *
171
+ * @param marketId - Target market identifier
172
+ * @returns Action identifier and freeze receipt
173
+ * @throws {NordError} If the action submission fails
174
+ */
175
+ unfreezeMarket({ marketId, }: Readonly<{
176
+ marketId: number;
177
+ }>): Promise<{
178
+ actionId: bigint;
179
+ } & proto.Receipt_MarketFreezeUpdated>;
180
+ /**
181
+ * Append a new fee tier to the account bracket configuration.
182
+ *
183
+ * - The engine supports at most 16 tiers (ids 0–15). Tier 0 is reserved for
184
+ * the default Nord fees; use `updateFeeTier` if you need to change it.
185
+ * - The first appended tier receives id 1, and subsequent tiers increment the id.
186
+ *
187
+ * @param config - Maker/taker configuration to insert
188
+ * @returns Action identifier and fee tier addition receipt
189
+ * @throws {NordError} If the action submission fails or the new tier exceeds the maximum range (0-15).
190
+ */
191
+ addFeeTier(config: Readonly<FeeTierConfig>): Promise<{
192
+ actionId: bigint;
193
+ } & proto.Receipt_FeeTierAdded>;
194
+ /**
195
+ * Update an existing fee tier with new maker/taker rates.
196
+ *
197
+ * Tier identifiers must already exist; attempting to update a missing tier
198
+ * causes the action to fail.
199
+ *
200
+ * @param tierId - Fee tier identifier
201
+ * @param config - Updated maker/taker configuration
202
+ * @returns Action identifier and fee tier update receipt
203
+ * @throws {NordError} If the action submission fails or the tier ID exceeds the configured range.
204
+ */
205
+ updateFeeTier({ tierId, config, }: Readonly<{
206
+ tierId: number;
207
+ config: FeeTierConfig;
208
+ }>): Promise<{
209
+ actionId: bigint;
210
+ } & proto.Receipt_FeeTierUpdated>;
211
+ /**
212
+ * Assign a fee tier to one or more accounts.
213
+ *
214
+ * The tier id must be within the configured range (0–15). Every account starts
215
+ * on tier 0; assigning it to another tier requires that tier to exist already.
216
+ * Invalid account ids or tier ids cause the action to fail.
217
+ *
218
+ * @param accounts - Account IDs to update
219
+ * @param tierId - Target fee tier identifier
220
+ * @returns Action identifier and accounts-tier receipt
221
+ * @throws {NordError} If the tier id exceeds the configured range or an account id is invalid.
222
+ */
223
+ updateAccountsTier(accounts: number[], tierId: number): Promise<{
224
+ actionId: bigint;
225
+ } & proto.Receipt_AccountsTierUpdated>;
226
+ }
@@ -0,0 +1,410 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.NordAdmin = exports.AclRole = void 0;
37
+ const protobuf_1 = require("@bufbuild/protobuf");
38
+ const proto = __importStar(require("../../gen/nord_pb"));
39
+ const utils_1 = require("../../utils");
40
+ const actions_1 = require("../api/actions");
41
+ const NordError_1 = require("../utils/NordError");
42
+ // NOTE: keep in sync with `acl.rs`.
43
+ // NOTE: don't forget `number` as int is internally a u32.
44
+ var AclRole;
45
+ (function (AclRole) {
46
+ AclRole[AclRole["FEE_MANAGER"] = 1] = "FEE_MANAGER";
47
+ AclRole[AclRole["MARKET_MANAGER"] = 2] = "MARKET_MANAGER";
48
+ // TODO: unsure about this?
49
+ AclRole[AclRole["ADMIN"] = -2147483648] = "ADMIN";
50
+ })(AclRole || (exports.AclRole = AclRole = {}));
51
+ /**
52
+ * Administrative client capable of submitting privileged configuration actions.
53
+ */
54
+ class NordAdmin {
55
+ constructor({ nord, admin, signFn, }) {
56
+ this.nord = nord;
57
+ this.admin = admin;
58
+ this.signFn = signFn;
59
+ }
60
+ /** Create a new admin client.
61
+ *
62
+ * @param nord - Nord instance
63
+ * @param admin - The user that will be signing actions.
64
+ * @param signFn - Function to sign messages with the admin's wallet.
65
+ *
66
+ * `signFn` must sign the _hex-encoded_ message, not the raw message itself, for
67
+ * the purpose of being compatible with Solana wallets.
68
+ *
69
+ * In practice, you will do something along the lines of:
70
+ *
71
+ * ```typescript
72
+ * (x) => wallet.signMessage(new TextEncoder().encode(x.toHex()));
73
+ * ```
74
+ *
75
+ * For a software signing key, this might look more like:
76
+ *
77
+ * ```typescript
78
+ * (x) => nacl.sign.detached(new TextEncoder().encode(x.toHex()), sk);
79
+ * ``
80
+ *
81
+ * where `nacl` is the tweetnacl library.
82
+ */
83
+ static new({ nord, admin, signFn, }) {
84
+ return new NordAdmin({
85
+ nord,
86
+ admin,
87
+ signFn,
88
+ });
89
+ }
90
+ /**
91
+ * Submit an action and append the admin signature before sending it to Nord.
92
+ *
93
+ * @param kind - Action payload describing the admin request
94
+ * @throws {NordError} If signing or submission fails
95
+ */
96
+ async submitAction(kind) {
97
+ const timestamp = await this.nord.getTimestamp();
98
+ const action = (0, actions_1.createAction)(timestamp, 0, kind);
99
+ return (0, actions_1.sendAction)(this.nord.webServerUrl, async (xs) => {
100
+ const signature = await this.signFn(xs);
101
+ if (signature.length !== 64) {
102
+ throw new NordError_1.NordError("invalid signature length; must be 64 bytes");
103
+ }
104
+ return Uint8Array.from([...xs, ...signature]);
105
+ }, action, this.nord.client);
106
+ }
107
+ /** Set acl permissions for a given user.
108
+ *
109
+ * If all roles are removed, the user is removed from the acl.
110
+ *
111
+ * @param target - User to update.
112
+ * @param addRoles - Roles to add to the user.
113
+ * @param removeRoles - Reles to remove from the user.
114
+ */
115
+ async updateAcl({ target, addRoles, removeRoles, }) {
116
+ const allRoles = addRoles.concat(removeRoles);
117
+ if (allRoles.length !== new Set(allRoles).size) {
118
+ throw new NordError_1.NordError("duplicate roles in acl update; must be unique");
119
+ }
120
+ let mask = 0;
121
+ let values = 0;
122
+ for (const role of allRoles) {
123
+ mask |= role;
124
+ }
125
+ for (const role of addRoles) {
126
+ values |= role;
127
+ }
128
+ const receipt = await this.submitAction({
129
+ case: "updateAcl",
130
+ value: (0, protobuf_1.create)(proto.Action_UpdateAclSchema, {
131
+ aclPubkey: this.admin.toBytes(),
132
+ targetPubkey: target.toBytes(),
133
+ rolesValue: values,
134
+ rolesMask: mask,
135
+ }),
136
+ });
137
+ (0, actions_1.expectReceiptKind)(receipt, "aclUpdated", "update acl");
138
+ return { ...receipt.kind.value, actionId: receipt.actionId };
139
+ }
140
+ /**
141
+ * Register a new token that can be listed on Nord.
142
+ *
143
+ * @param mintAddr - SPL mint to register
144
+ * @param tokenDecimals - On-chain decimal precision
145
+ * @param weightBps - Risk weight in basis points
146
+ * @param viewSymbol - Symbol shown to users
147
+ * @param oracleSymbol - Symbol used by the oracle
148
+ * @returns Action identifier and resulting token metadata
149
+ * @throws {NordError} If the action submission fails
150
+ */
151
+ async createToken({ mintAddr, tokenDecimals, weightBps, viewSymbol, oracleSymbol, }) {
152
+ const receipt = await this.submitAction({
153
+ case: "createToken",
154
+ value: (0, protobuf_1.create)(proto.Action_CreateTokenSchema, {
155
+ aclPubkey: this.admin.toBytes(),
156
+ tokenDecimals,
157
+ weightBps,
158
+ viewSymbol,
159
+ oracleSymbol,
160
+ solAddr: mintAddr.toBytes(),
161
+ }),
162
+ });
163
+ (0, actions_1.expectReceiptKind)(receipt, "insertTokenResult", "create token");
164
+ return { actionId: receipt.actionId, ...receipt.kind.value };
165
+ }
166
+ /**
167
+ * Open a new market with explicit trading parameters.
168
+ *
169
+ * @param sizeDecimals - Base asset decimal precision
170
+ * @param priceDecimals - Quote price decimal precision
171
+ * @param imfBps - Initial margin fraction in basis points
172
+ * @param cmfBps - Cancel margin fraction in basis points
173
+ * @param mmfBps - Maintenance margin fraction in basis points
174
+ * @param marketType - Market kind to open
175
+ * @param viewSymbol - Symbol shown to users
176
+ * @param oracleSymbol - Symbol used by the oracle
177
+ * @param baseTokenId - Token id used as the base asset
178
+ * @returns Action identifier and resulting market metadata
179
+ * @throws {NordError} If the action submission fails
180
+ */
181
+ async createMarket({ sizeDecimals, priceDecimals, imfBps, cmfBps, mmfBps, marketType, viewSymbol, oracleSymbol, baseTokenId, }) {
182
+ const receipt = await this.submitAction({
183
+ case: "createMarket",
184
+ value: (0, protobuf_1.create)(proto.Action_CreateMarketSchema, {
185
+ aclPubkey: this.admin.toBytes(),
186
+ sizeDecimals,
187
+ priceDecimals,
188
+ imfBps,
189
+ cmfBps,
190
+ mmfBps,
191
+ marketType,
192
+ viewSymbol,
193
+ oracleSymbol,
194
+ baseTokenId,
195
+ }),
196
+ });
197
+ (0, actions_1.expectReceiptKind)(receipt, "insertMarketResult", "create market");
198
+ return { actionId: receipt.actionId, ...receipt.kind.value };
199
+ }
200
+ /**
201
+ * Update the Pyth guardian set used for verifying Wormhole messages.
202
+ *
203
+ * Each address must decode from a 20-byte hex string (with or without a
204
+ * leading `0x` prefix). The engine validates the supplied guardian set index
205
+ * before applying the update.
206
+ *
207
+ * @param guardianSetIndex - Wormhole guardian set identifier
208
+ * @param guardianAddresses - Guardian addresses as 20-byte hex strings
209
+ * @returns Action identifier and guardian update receipt
210
+ * @throws {NordError} If the action submission fails
211
+ */
212
+ async pythSetWormholeGuardians({ guardianSetIndex, addresses: guardianAddresses, }) {
213
+ const addresses = guardianAddresses.map((address) => {
214
+ try {
215
+ const decoded = (0, utils_1.decodeHex)(address);
216
+ if (decoded.length !== 20) {
217
+ throw new Error("guardian address must be 20 bytes");
218
+ }
219
+ return decoded;
220
+ }
221
+ catch (e) {
222
+ throw new NordError_1.NordError("invalid guardian address; must be a 20 byte hex address", { cause: e });
223
+ }
224
+ });
225
+ const receipt = await this.submitAction({
226
+ case: "pythSetWormholeGuardians",
227
+ value: (0, protobuf_1.create)(proto.Action_PythSetWormholeGuardiansSchema, {
228
+ aclPubkey: this.admin.toBytes(),
229
+ guardianSetIndex,
230
+ addresses,
231
+ }),
232
+ });
233
+ (0, actions_1.expectReceiptKind)(receipt, "updateGuardianSetResult", "update wormhole guardians");
234
+ return { actionId: receipt.actionId, ...receipt.kind.value };
235
+ }
236
+ /**
237
+ * Link an oracle symbol to a specific Pyth price feed.
238
+ *
239
+ * The price feed identifier must decode to 32 bytes (with or without a
240
+ * leading `0x` prefix). Use this call to create or update the mapping used
241
+ * by the oracle integration.
242
+ *
243
+ * @param oracleSymbol - Symbol to update
244
+ * @param priceFeedHex - 32-byte hex price feed id
245
+ * @returns Action identifier and symbol feed receipt
246
+ * @throws {NordError} If the action submission fails
247
+ */
248
+ async pythSetSymbolFeed({ oracleSymbol, priceFeedId: priceFeedHex, }) {
249
+ let priceFeedId;
250
+ try {
251
+ priceFeedId = (0, utils_1.decodeHex)(priceFeedHex);
252
+ if (priceFeedId.length !== 32) {
253
+ throw new Error("price feed id must be 32 bytes");
254
+ }
255
+ }
256
+ catch (e) {
257
+ throw new NordError_1.NordError("invalid price feed id; must be a 32 byte hex id", {
258
+ cause: e,
259
+ });
260
+ }
261
+ const receipt = await this.submitAction({
262
+ case: "pythSetSymbolFeed",
263
+ value: (0, protobuf_1.create)(proto.Action_PythSetSymbolFeedSchema, {
264
+ aclPubkey: this.admin.toBytes(),
265
+ oracleSymbol,
266
+ priceFeedId,
267
+ }),
268
+ });
269
+ (0, actions_1.expectReceiptKind)(receipt, "oracleSymbolFeedResult", "set symbol feed");
270
+ return { actionId: receipt.actionId, ...receipt.kind.value };
271
+ }
272
+ /**
273
+ * Pause all trading activity on the exchange.
274
+ *
275
+ * @returns Action identifier confirming the pause
276
+ * @throws {NordError} If the action submission fails
277
+ */
278
+ async pause() {
279
+ const receipt = await this.submitAction({
280
+ case: "pause",
281
+ value: (0, protobuf_1.create)(proto.Action_PauseSchema, {
282
+ aclPubkey: this.admin.toBytes(),
283
+ }),
284
+ });
285
+ (0, actions_1.expectReceiptKind)(receipt, "paused", "pause");
286
+ return { actionId: receipt.actionId };
287
+ }
288
+ /**
289
+ * Resume trading activity after a pause.
290
+ *
291
+ * @returns Action identifier confirming the unpause
292
+ * @throws {NordError} If the action submission fails
293
+ */
294
+ async unpause() {
295
+ const receipt = await this.submitAction({
296
+ case: "unpause",
297
+ value: (0, protobuf_1.create)(proto.Action_UnpauseSchema, {
298
+ aclPubkey: this.admin.toBytes(),
299
+ }),
300
+ });
301
+ (0, actions_1.expectReceiptKind)(receipt, "unpaused", "unpause");
302
+ return { actionId: receipt.actionId };
303
+ }
304
+ /**
305
+ * Freeze an individual market, preventing new trades and orders.
306
+ *
307
+ * @param marketId - Target market identifier
308
+ * @returns Action identifier and freeze receipt
309
+ * @throws {NordError} If the action submission fails
310
+ */
311
+ async freezeMarket({ marketId, }) {
312
+ const receipt = await this.submitAction({
313
+ case: "freezeMarket",
314
+ value: (0, protobuf_1.create)(proto.Action_FreezeMarketSchema, {
315
+ marketId,
316
+ aclPubkey: this.admin.toBytes(),
317
+ }),
318
+ });
319
+ (0, actions_1.expectReceiptKind)(receipt, "marketFreezeUpdated", "freeze market");
320
+ return { actionId: receipt.actionId, ...receipt.kind.value };
321
+ }
322
+ /**
323
+ * Unfreeze a market that was previously halted.
324
+ *
325
+ * @param marketId - Target market identifier
326
+ * @returns Action identifier and freeze receipt
327
+ * @throws {NordError} If the action submission fails
328
+ */
329
+ async unfreezeMarket({ marketId, }) {
330
+ const receipt = await this.submitAction({
331
+ case: "unfreezeMarket",
332
+ value: (0, protobuf_1.create)(proto.Action_UnfreezeMarketSchema, {
333
+ marketId,
334
+ aclPubkey: this.admin.toBytes(),
335
+ }),
336
+ });
337
+ (0, actions_1.expectReceiptKind)(receipt, "marketFreezeUpdated", "unfreeze market");
338
+ return { actionId: receipt.actionId, ...receipt.kind.value };
339
+ }
340
+ /**
341
+ * Append a new fee tier to the account bracket configuration.
342
+ *
343
+ * - The engine supports at most 16 tiers (ids 0–15). Tier 0 is reserved for
344
+ * the default Nord fees; use `updateFeeTier` if you need to change it.
345
+ * - The first appended tier receives id 1, and subsequent tiers increment the id.
346
+ *
347
+ * @param config - Maker/taker configuration to insert
348
+ * @returns Action identifier and fee tier addition receipt
349
+ * @throws {NordError} If the action submission fails or the new tier exceeds the maximum range (0-15).
350
+ */
351
+ async addFeeTier(config) {
352
+ const receipt = await this.submitAction({
353
+ case: "addFeeTier",
354
+ value: (0, protobuf_1.create)(proto.Action_AddFeeTierSchema, {
355
+ aclPubkey: this.admin.toBytes(),
356
+ config: (0, protobuf_1.create)(proto.FeeTierConfigSchema, config),
357
+ }),
358
+ });
359
+ (0, actions_1.expectReceiptKind)(receipt, "feeTierAdded", "add fee tier");
360
+ return { actionId: receipt.actionId, ...receipt.kind.value };
361
+ }
362
+ /**
363
+ * Update an existing fee tier with new maker/taker rates.
364
+ *
365
+ * Tier identifiers must already exist; attempting to update a missing tier
366
+ * causes the action to fail.
367
+ *
368
+ * @param tierId - Fee tier identifier
369
+ * @param config - Updated maker/taker configuration
370
+ * @returns Action identifier and fee tier update receipt
371
+ * @throws {NordError} If the action submission fails or the tier ID exceeds the configured range.
372
+ */
373
+ async updateFeeTier({ tierId, config, }) {
374
+ const receipt = await this.submitAction({
375
+ case: "updateFeeTier",
376
+ value: (0, protobuf_1.create)(proto.Action_UpdateFeeTierSchema, {
377
+ aclPubkey: this.admin.toBytes(),
378
+ id: tierId,
379
+ config: (0, protobuf_1.create)(proto.FeeTierConfigSchema, config),
380
+ }),
381
+ });
382
+ (0, actions_1.expectReceiptKind)(receipt, "feeTierUpdated", "update fee tier");
383
+ return { actionId: receipt.actionId, ...receipt.kind.value };
384
+ }
385
+ /**
386
+ * Assign a fee tier to one or more accounts.
387
+ *
388
+ * The tier id must be within the configured range (0–15). Every account starts
389
+ * on tier 0; assigning it to another tier requires that tier to exist already.
390
+ * Invalid account ids or tier ids cause the action to fail.
391
+ *
392
+ * @param accounts - Account IDs to update
393
+ * @param tierId - Target fee tier identifier
394
+ * @returns Action identifier and accounts-tier receipt
395
+ * @throws {NordError} If the tier id exceeds the configured range or an account id is invalid.
396
+ */
397
+ async updateAccountsTier(accounts, tierId) {
398
+ const receipt = await this.submitAction({
399
+ case: "updateAccountsTier",
400
+ value: (0, protobuf_1.create)(proto.Action_UpdateAccountsTierSchema, {
401
+ aclPubkey: this.admin.toBytes(),
402
+ accounts,
403
+ tierId,
404
+ }),
405
+ });
406
+ (0, actions_1.expectReceiptKind)(receipt, "accountsTierUpdated", "update accounts tier");
407
+ return { actionId: receipt.actionId, ...receipt.kind.value };
408
+ }
409
+ }
410
+ exports.NordAdmin = NordAdmin;
@@ -0,0 +1,16 @@
1
+ import { Client, FetchOptions } from "openapi-fetch";
2
+ import type { paths } from "../../gen/openapi.ts";
3
+ export declare class NordTransport {
4
+ readonly baseUrl: string;
5
+ private readonly client;
6
+ constructor(baseUrl: string);
7
+ get<P extends keyof paths & string>(path: P, options: FetchOptions<paths[P]["get"]>): Promise<import("openapi-fetch").ParseAsResponse<import("openapi-typescript-helpers").SuccessResponse<import("openapi-typescript-helpers").ResponseObjectMap<paths[P]["get"]>, `${string}/${string}`>, import("openapi-fetch").ParamsOption<paths[P]["get"]> & import("openapi-fetch").RequestBodyOption<paths[P]["get"]> & {
8
+ baseUrl?: string;
9
+ querySerializer?: import("openapi-fetch").QuerySerializerOptions | import("openapi-fetch").QuerySerializer<paths[P]["get"]> | undefined;
10
+ bodySerializer?: import("openapi-fetch").BodySerializer<paths[P]["get"]> | undefined;
11
+ parseAs?: import("openapi-fetch").ParseAs;
12
+ fetch?: import("openapi-fetch").ClientOptions["fetch"];
13
+ headers?: import("openapi-fetch").HeadersOptions;
14
+ } & Omit<RequestInit, "headers" | "body">> & ({} | null)>;
15
+ get clientInstance(): Client<paths>;
16
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NordTransport = void 0;
7
+ const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
8
+ const NordError_1 = require("../utils/NordError");
9
+ class NordTransport {
10
+ constructor(baseUrl) {
11
+ this.baseUrl = baseUrl;
12
+ this.client = (0, openapi_fetch_1.default)({ baseUrl });
13
+ }
14
+ async get(path, options) {
15
+ const response = await this.client.GET(path, options);
16
+ if (response.error) {
17
+ throw new NordError_1.NordError(`failed to GET ${path}`, { cause: response.error });
18
+ }
19
+ if (response.data === undefined) {
20
+ throw new NordError_1.NordError("internal assertion violation", { cause: response });
21
+ }
22
+ return response.data;
23
+ }
24
+ get clientInstance() {
25
+ return this.client;
26
+ }
27
+ }
28
+ exports.NordTransport = NordTransport;