@n1xyz/nord-ts 0.1.3 → 0.1.5

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.
@@ -0,0 +1,337 @@
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 = 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
+ /**
43
+ * Administrative client capable of submitting privileged configuration actions.
44
+ */
45
+ class NordAdmin {
46
+ constructor({ nord, signFn, }) {
47
+ this.nord = nord;
48
+ this.signFn = signFn;
49
+ }
50
+ /** Create a new admin client.
51
+ *
52
+ * @param nord - Nord instance
53
+ * @param signFn - Function to sign messages with the admin's wallet.
54
+ *
55
+ * `signFn` must sign the _hex-encoded_ message, not the raw message itself, for
56
+ * the purpose of being compatible with Solana wallets.
57
+ *
58
+ * In practice, you will do something along the lines of:
59
+ *
60
+ * ```typescript
61
+ * (x) => wallet.signMessage(new TextEncoder().encode(x.toHex()));
62
+ * ```
63
+ *
64
+ * For a software signing key, this might look more like:
65
+ *
66
+ * ```typescript
67
+ * (x) => nacl.sign.detached(new TextEncoder().encode(x.toHex()), sk);
68
+ * ``
69
+ *
70
+ * where `nacl` is the tweetnacl library.
71
+ */
72
+ static new({ nord, signFn, }) {
73
+ return new NordAdmin({
74
+ nord,
75
+ signFn,
76
+ });
77
+ }
78
+ /**
79
+ * Submit an action and append the admin signature before sending it to Nord.
80
+ *
81
+ * @param kind - Action payload describing the admin request
82
+ * @throws {NordError} If signing or submission fails
83
+ */
84
+ async submitAction(kind) {
85
+ const timestamp = await this.nord.getTimestamp();
86
+ const action = (0, actions_1.createAction)(timestamp, 0, kind);
87
+ return (0, actions_1.sendAction)(this.nord.webServerUrl, async (xs) => {
88
+ const signature = await this.signFn(xs);
89
+ if (signature.length !== 64) {
90
+ throw new NordError_1.NordError("invalid signature length; must be 64 bytes");
91
+ }
92
+ return Uint8Array.from([...xs, ...signature]);
93
+ }, action);
94
+ }
95
+ /**
96
+ * Register a new token that can be listed on Nord.
97
+ *
98
+ * @param params - Token configuration values
99
+ * @returns Action identifier and resulting token metadata
100
+ * @throws {NordError} If the action submission fails
101
+ */
102
+ async createToken({ tokenDecimals, weightBps, viewSymbol, oracleSymbol, mintAddr, }) {
103
+ const receipt = await this.submitAction({
104
+ case: "createToken",
105
+ value: (0, protobuf_1.create)(proto.Action_CreateTokenSchema, {
106
+ tokenDecimals,
107
+ weightBps,
108
+ viewSymbol,
109
+ oracleSymbol,
110
+ solAddr: mintAddr.toBytes(),
111
+ }),
112
+ });
113
+ (0, actions_1.expectReceiptKind)(receipt, "insertTokenResult", "create token");
114
+ return { actionId: receipt.actionId, ...receipt.kind.value };
115
+ }
116
+ /**
117
+ * Open a new market with the provided trading parameters.
118
+ *
119
+ * @param params - Market configuration to apply
120
+ * @returns Action identifier and resulting market metadata
121
+ * @throws {NordError} If the action submission fails
122
+ */
123
+ async createMarket(params) {
124
+ const receipt = await this.submitAction({
125
+ case: "createMarket",
126
+ value: (0, protobuf_1.create)(proto.Action_CreateMarketSchema, {
127
+ sizeDecimals: params.sizeDecimals,
128
+ priceDecimals: params.priceDecimals,
129
+ imfBps: params.imfBps,
130
+ cmfBps: params.cmfBps,
131
+ mmfBps: params.mmfBps,
132
+ marketType: params.marketType,
133
+ viewSymbol: params.viewSymbol,
134
+ oracleSymbol: params.oracleSymbol,
135
+ baseTokenId: params.baseTokenId,
136
+ }),
137
+ });
138
+ (0, actions_1.expectReceiptKind)(receipt, "insertMarketResult", "create market");
139
+ return { actionId: receipt.actionId, ...receipt.kind.value };
140
+ }
141
+ /**
142
+ * Update the Pyth guardian set used for verifying Wormhole messages.
143
+ *
144
+ * Each address must decode from a 20-byte hex string (with or without a
145
+ * leading `0x` prefix). The engine validates the supplied guardian set index
146
+ * before applying the update.
147
+ *
148
+ * @param params - Guardian set index and guardian addresses
149
+ * @returns Action identifier and guardian update receipt
150
+ * @throws {NordError} If the action submission fails
151
+ */
152
+ async pythSetWormholeGuardians(params) {
153
+ const addresses = params.addresses.map((address) => {
154
+ try {
155
+ const decoded = (0, utils_1.decodeHex)(address);
156
+ if (decoded.length !== 20) {
157
+ throw new Error("guardian address must be 20 bytes");
158
+ }
159
+ return decoded;
160
+ }
161
+ catch (e) {
162
+ throw new NordError_1.NordError("invalid guardian address; must be a 20 byte hex address", { cause: e });
163
+ }
164
+ });
165
+ const receipt = await this.submitAction({
166
+ case: "pythSetWormholeGuardians",
167
+ value: (0, protobuf_1.create)(proto.Action_PythSetWormholeGuardiansSchema, {
168
+ guardianSetIndex: params.guardianSetIndex,
169
+ addresses,
170
+ }),
171
+ });
172
+ (0, actions_1.expectReceiptKind)(receipt, "updateGuardianSetResult", "update wormhole guardians");
173
+ return { actionId: receipt.actionId, ...receipt.kind.value };
174
+ }
175
+ /**
176
+ * Link an oracle symbol to a specific Pyth price feed.
177
+ *
178
+ * The price feed identifier must decode to 32 bytes (with or without a
179
+ * leading `0x` prefix). Use this call to create or update the mapping used
180
+ * by the oracle integration.
181
+ *
182
+ * @param params - Oracle symbol and price feed identifier
183
+ * @returns Action identifier and symbol feed receipt
184
+ * @throws {NordError} If the action submission fails
185
+ */
186
+ async pythSetSymbolFeed(params) {
187
+ let priceFeedId;
188
+ try {
189
+ priceFeedId = (0, utils_1.decodeHex)(params.priceFeedId);
190
+ if (priceFeedId.length !== 32) {
191
+ throw new Error("price feed id must be 32 bytes");
192
+ }
193
+ }
194
+ catch (e) {
195
+ throw new NordError_1.NordError("invalid price feed id; must be a 32 byte hex id", {
196
+ cause: e,
197
+ });
198
+ }
199
+ const receipt = await this.submitAction({
200
+ case: "pythSetSymbolFeed",
201
+ value: (0, protobuf_1.create)(proto.Action_PythSetSymbolFeedSchema, {
202
+ oracleSymbol: params.oracleSymbol,
203
+ priceFeedId,
204
+ }),
205
+ });
206
+ (0, actions_1.expectReceiptKind)(receipt, "oracleSymbolFeedResult", "set symbol feed");
207
+ return { actionId: receipt.actionId, ...receipt.kind.value };
208
+ }
209
+ /**
210
+ * Pause all trading activity on the exchange.
211
+ *
212
+ * @returns Action identifier confirming the pause
213
+ * @throws {NordError} If the action submission fails
214
+ */
215
+ async pause() {
216
+ const receipt = await this.submitAction({
217
+ case: "pause",
218
+ value: (0, protobuf_1.create)(proto.Action_PauseSchema, {}),
219
+ });
220
+ (0, actions_1.expectReceiptKind)(receipt, "paused", "pause");
221
+ return { actionId: receipt.actionId };
222
+ }
223
+ /**
224
+ * Resume trading activity after a pause.
225
+ *
226
+ * @returns Action identifier confirming the unpause
227
+ * @throws {NordError} If the action submission fails
228
+ */
229
+ async unpause() {
230
+ const receipt = await this.submitAction({
231
+ case: "unpause",
232
+ value: (0, protobuf_1.create)(proto.Action_UnpauseSchema, {}),
233
+ });
234
+ (0, actions_1.expectReceiptKind)(receipt, "unpaused", "unpause");
235
+ return { actionId: receipt.actionId };
236
+ }
237
+ /**
238
+ * Freeze an individual market, preventing new trades and orders.
239
+ *
240
+ * @param params - Target market identifier
241
+ * @returns Action identifier and freeze receipt
242
+ * @throws {NordError} If the action submission fails
243
+ */
244
+ async freezeMarket(params) {
245
+ const receipt = await this.submitAction({
246
+ case: "freezeMarket",
247
+ value: (0, protobuf_1.create)(proto.Action_FreezeMarketSchema, {
248
+ marketId: params.marketId,
249
+ }),
250
+ });
251
+ (0, actions_1.expectReceiptKind)(receipt, "marketFreezeUpdated", "freeze market");
252
+ return { actionId: receipt.actionId, ...receipt.kind.value };
253
+ }
254
+ /**
255
+ * Unfreeze a market that was previously halted.
256
+ *
257
+ * @param params - Target market identifier
258
+ * @returns Action identifier and freeze receipt
259
+ * @throws {NordError} If the action submission fails
260
+ */
261
+ async unfreezeMarket(params) {
262
+ const receipt = await this.submitAction({
263
+ case: "unfreezeMarket",
264
+ value: (0, protobuf_1.create)(proto.Action_UnfreezeMarketSchema, {
265
+ marketId: params.marketId,
266
+ }),
267
+ });
268
+ (0, actions_1.expectReceiptKind)(receipt, "marketFreezeUpdated", "unfreeze market");
269
+ return { actionId: receipt.actionId, ...receipt.kind.value };
270
+ }
271
+ /**
272
+ * Append a new fee tier to the account bracket configuration.
273
+ *
274
+ * - The engine supports at most 16 tiers (ids 0–15). Tier 0 is reserved for
275
+ * the default Nord fees; use `updateFeeTier` if you need to change it.
276
+ * - The first appended tier receives id 1, and subsequent tiers increment the id.
277
+ *
278
+ * @param params - Fee tier configuration to insert
279
+ * @returns Action identifier and fee tier addition receipt
280
+ * @throws {NordError} If the action submission fails or the new tier exceeds the maximum range (0-15).
281
+ */
282
+ async addFeeTier(params) {
283
+ const receipt = await this.submitAction({
284
+ case: "addFeeTier",
285
+ value: (0, protobuf_1.create)(proto.Action_AddFeeTierSchema, {
286
+ config: (0, protobuf_1.create)(proto.FeeTierConfigSchema, params.config),
287
+ }),
288
+ });
289
+ (0, actions_1.expectReceiptKind)(receipt, "feeTierAdded", "add fee tier");
290
+ return { actionId: receipt.actionId, ...receipt.kind.value };
291
+ }
292
+ /**
293
+ * Update an existing fee tier with new maker/taker rates.
294
+ *
295
+ * Tier identifiers must already exist; attempting to update a missing tier
296
+ * causes the action to fail.
297
+ *
298
+ * @param params - Fee tier identifier and updated configuration
299
+ * @returns Action identifier and fee tier update receipt
300
+ * @throws {NordError} If the action submission fails or the tier ID exceeds the configured range.
301
+ */
302
+ async updateFeeTier(params) {
303
+ const receipt = await this.submitAction({
304
+ case: "updateFeeTier",
305
+ value: (0, protobuf_1.create)(proto.Action_UpdateFeeTierSchema, {
306
+ id: params.tierId,
307
+ config: (0, protobuf_1.create)(proto.FeeTierConfigSchema, params.config),
308
+ }),
309
+ });
310
+ (0, actions_1.expectReceiptKind)(receipt, "feeTierUpdated", "update fee tier");
311
+ return { actionId: receipt.actionId, ...receipt.kind.value };
312
+ }
313
+ /**
314
+ * Assign a fee tier to one or more accounts.
315
+ *
316
+ * The tier id must be within the configured range (0–15). Every account starts
317
+ * on tier 0; assigning it to another tier requires that tier to exist already.
318
+ * Invalid account ids or tier ids cause the action to fail.
319
+ *
320
+ * @param accounts - Account IDs to update
321
+ * @param tierId - Target fee tier identifier
322
+ * @returns Action identifier and accounts-tier receipt
323
+ * @throws {NordError} If the tier id exceeds the configured range or an account id is invalid.
324
+ */
325
+ async updateAccountsTier(accounts, tierId) {
326
+ const receipt = await this.submitAction({
327
+ case: "updateAccountsTier",
328
+ value: (0, protobuf_1.create)(proto.Action_UpdateAccountsTierSchema, {
329
+ accounts,
330
+ tierId,
331
+ }),
332
+ });
333
+ (0, actions_1.expectReceiptKind)(receipt, "accountsTierUpdated", "update accounts tier");
334
+ return { actionId: receipt.actionId, ...receipt.kind.value };
335
+ }
336
+ }
337
+ exports.NordAdmin = NordAdmin;
@@ -0,0 +1,33 @@
1
+ import { Connection, PublicKey } from "@solana/web3.js";
2
+ import type { Transaction } from "@solana/web3.js";
3
+ import * as proto from "../../gen/nord_pb";
4
+ import { Nord } from "./Nord";
5
+ export interface NordClientParams {
6
+ nord: Nord;
7
+ address: PublicKey;
8
+ walletSignFn: (message: Uint8Array | string) => Promise<Uint8Array>;
9
+ sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
10
+ transactionSignFn: <T extends Transaction>(tx: T) => Promise<T>;
11
+ connection?: Connection;
12
+ sessionId?: bigint;
13
+ sessionPubKey: Uint8Array;
14
+ publicKey: PublicKey;
15
+ }
16
+ export declare abstract class NordClient {
17
+ readonly nord: Nord;
18
+ readonly address: PublicKey;
19
+ readonly walletSignFn: (message: Uint8Array | string) => Promise<Uint8Array>;
20
+ readonly sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
21
+ readonly transactionSignFn: <T extends Transaction>(tx: T) => Promise<T>;
22
+ connection: Connection;
23
+ sessionId?: bigint;
24
+ sessionPubKey: Uint8Array;
25
+ publicKey: PublicKey;
26
+ lastTs: number;
27
+ protected actionNonce: number;
28
+ protected constructor(params: NordClientParams);
29
+ protected submitSignedAction(kind: proto.Action["kind"], makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>): Promise<proto.Receipt>;
30
+ protected nextActionNonce(): number;
31
+ protected cloneClientState(target: NordClient): void;
32
+ getSolanaPublicKey(): PublicKey;
33
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NordClient = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const actions_1 = require("../api/actions");
6
+ class NordClient {
7
+ constructor(params) {
8
+ this.lastTs = 0;
9
+ this.actionNonce = 0;
10
+ this.nord = params.nord;
11
+ this.address = params.address;
12
+ this.walletSignFn = params.walletSignFn;
13
+ this.sessionSignFn = params.sessionSignFn;
14
+ this.transactionSignFn = params.transactionSignFn;
15
+ this.connection =
16
+ params.connection ??
17
+ new web3_js_1.Connection(params.nord.solanaUrl, {
18
+ commitment: "confirmed",
19
+ });
20
+ this.sessionId = params.sessionId;
21
+ this.sessionPubKey = new Uint8Array(params.sessionPubKey);
22
+ this.publicKey = params.publicKey;
23
+ }
24
+ async submitSignedAction(kind, makeSignedMessage) {
25
+ const nonce = this.nextActionNonce();
26
+ const currentTimestamp = await this.nord.getTimestamp();
27
+ const action = (0, actions_1.createAction)(currentTimestamp, nonce, kind);
28
+ return (0, actions_1.sendAction)(this.nord.webServerUrl, makeSignedMessage, action);
29
+ }
30
+ nextActionNonce() {
31
+ return ++this.actionNonce;
32
+ }
33
+ cloneClientState(target) {
34
+ target.connection = this.connection;
35
+ target.sessionId = this.sessionId;
36
+ target.sessionPubKey = new Uint8Array(this.sessionPubKey);
37
+ target.publicKey = this.publicKey;
38
+ target.lastTs = this.lastTs;
39
+ target.actionNonce = this.actionNonce;
40
+ }
41
+ getSolanaPublicKey() {
42
+ return this.address;
43
+ }
44
+ }
45
+ exports.NordClient = NordClient;
@@ -3,8 +3,8 @@ import Decimal from "decimal.js";
3
3
  import { FillMode, Side, SPLTokenInfo, QuoteSize, TriggerKind } from "../../types";
4
4
  import * as proto from "../../gen/nord_pb";
5
5
  import { BigIntValue } from "../../utils";
6
- import type { AccountTriggerInfo, TriggerHistoryPage, HistoryTriggerQuery } from "../api/triggers";
7
6
  import { Nord } from "./Nord";
7
+ import { NordClient } from "./NordClient";
8
8
  /**
9
9
  * Parameters for creating a NordUser instance
10
10
  */
@@ -48,6 +48,7 @@ export interface PlaceOrderParams {
48
48
  quoteSize?: QuoteSize;
49
49
  /** Account ID to place the order from */
50
50
  accountId?: number;
51
+ clientOrderId?: BigIntValue;
51
52
  }
52
53
  export interface AddTriggerParams {
53
54
  marketId: number;
@@ -106,17 +107,7 @@ export interface UserAtomicSubaction {
106
107
  /**
107
108
  * User class for interacting with the Nord protocol
108
109
  */
109
- export declare class NordUser {
110
- /** Nord client instance */
111
- readonly nord: Nord;
112
- /** User's blockchain address */
113
- readonly address: PublicKey;
114
- /** Function to sign messages with the user's wallet */
115
- readonly walletSignFn: (message: Uint8Array | string) => Promise<Uint8Array>;
116
- /** Function to sign messages with the user's session key */
117
- readonly sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
118
- /** Function to sign transactions with the user's wallet */
119
- readonly transactionSignFn: <T extends Transaction>(tx: T) => Promise<T>;
110
+ export declare class NordUser extends NordClient {
120
111
  /** User balances by token symbol */
121
112
  balances: {
122
113
  [key: string]: {
@@ -156,18 +147,6 @@ export declare class NordUser {
156
147
  };
157
148
  /** User's account IDs */
158
149
  accountIds?: number[];
159
- /** Current session ID */
160
- sessionId?: bigint;
161
- /** User's public key */
162
- publicKey: PublicKey;
163
- /** Session public key */
164
- sessionPubKey: Uint8Array;
165
- /** Last timestamp used */
166
- lastTs: number;
167
- /** Last nonce used */
168
- lastNonce: number;
169
- /** Solana connection */
170
- connection: Connection;
171
150
  /** SPL token information */
172
151
  splTokenInfos: SPLTokenInfo[];
173
152
  /**
@@ -202,7 +181,7 @@ export declare class NordUser {
202
181
  */
203
182
  getAssociatedTokenAccount(mint: PublicKey): Promise<PublicKey>;
204
183
  /**
205
- * Deposit SPL tokens to the bridge
184
+ * Deposit SPL tokens to the app
206
185
  *
207
186
  * @param amount - Amount to deposit
208
187
  * @param tokenId - Token ID
@@ -213,7 +192,7 @@ export declare class NordUser {
213
192
  */
214
193
  depositSpl(amount: number, tokenId: number, recipient?: PublicKey): Promise<string>;
215
194
  /**
216
- * Deposit SPL tokens to the bridge
195
+ * Deposit SPL tokens to the app
217
196
  *
218
197
  * @param amount - Amount to deposit
219
198
  * @param tokenId - Token ID
@@ -234,6 +213,7 @@ export declare class NordUser {
234
213
  * @returns Nonce as number
235
214
  */
236
215
  getNonce(): number;
216
+ private submitSessionAction;
237
217
  /**
238
218
  * Update account IDs for this user
239
219
  *
@@ -323,24 +303,6 @@ export declare class NordUser {
323
303
  removeTrigger(params: RemoveTriggerParams): Promise<{
324
304
  actionId: bigint;
325
305
  }>;
326
- /**
327
- * Fetch active triggers for an account.
328
- *
329
- * @param params Optional parameters containing an explicit account id.
330
- * @throws {NordError} If no account can be resolved or the request fails.
331
- */
332
- getAccountTriggers(params?: {
333
- accountId?: number;
334
- }): Promise<AccountTriggerInfo[]>;
335
- /**
336
- * Fetch trigger history for an account.
337
- *
338
- * @param params Optional parameters with account id and history query filters.
339
- * @throws {NordError} If no account can be resolved or the request fails.
340
- */
341
- getAccountTriggerHistory(params: HistoryTriggerQuery & {
342
- accountId?: number;
343
- }): Promise<TriggerHistoryPage>;
344
306
  /**
345
307
  * Transfer tokens to another account
346
308
  *
@@ -397,10 +359,4 @@ export declare class NordUser {
397
359
  [symbol: string]: string;
398
360
  };
399
361
  }>;
400
- /**
401
- * Get the Solana public key derived from the address
402
- *
403
- * @returns The Solana public key
404
- */
405
- getSolanaPublicKey(): PublicKey;
406
362
  }