@n1xyz/nord-ts 0.1.7 → 0.1.8
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/dist/actions.js +39 -82
- package/dist/bundle.js +79181 -0
- package/dist/client/Nord.d.ts +2 -2
- package/dist/client/Nord.js +46 -78
- package/dist/client/NordAdmin.d.ts +2 -2
- package/dist/client/NordAdmin.js +57 -89
- package/dist/client/NordUser.js +118 -147
- package/dist/const.js +5 -8
- package/dist/error.js +7 -5
- package/dist/gen/nord_pb.js +88 -92
- package/dist/gen/openapi.d.ts +5 -6
- package/dist/gen/openapi.js +1 -2
- package/dist/index.js +10 -49
- package/dist/types.d.ts +1 -0
- package/dist/types.js +21 -60
- package/dist/utils.js +38 -86
- package/dist/websocket/NordWebSocketClient.js +12 -17
- package/dist/websocket/Subscriber.js +6 -7
- package/dist/websocket/events.js +1 -2
- package/dist/websocket/index.js +10 -15
- package/package.json +2 -3
- package/dist/api/client.d.ts +0 -14
- package/dist/api/client.js +0 -45
- package/dist/bridge/client.d.ts +0 -151
- package/dist/bridge/client.js +0 -434
- package/dist/bridge/const.d.ts +0 -23
- package/dist/bridge/const.js +0 -47
- package/dist/bridge/index.d.ts +0 -4
- package/dist/bridge/index.js +0 -23
- package/dist/bridge/types.d.ts +0 -120
- package/dist/bridge/types.js +0 -18
- package/dist/bridge/utils.d.ts +0 -64
- package/dist/bridge/utils.js +0 -131
- package/dist/gen/common.d.ts +0 -68
- package/dist/gen/common.js +0 -215
- package/dist/gen/nord.d.ts +0 -882
- package/dist/gen/nord.js +0 -6520
- package/dist/idl/bridge.d.ts +0 -569
- package/dist/idl/bridge.js +0 -8
- package/dist/idl/bridge.json +0 -1506
- package/dist/idl/index.d.ts +0 -607
- package/dist/idl/index.js +0 -8
- package/dist/nord/api/actions.d.ts +0 -126
- package/dist/nord/api/actions.js +0 -397
- package/dist/nord/api/core.d.ts +0 -16
- package/dist/nord/api/core.js +0 -81
- package/dist/nord/api/market.d.ts +0 -36
- package/dist/nord/api/market.js +0 -96
- package/dist/nord/api/metrics.d.ts +0 -67
- package/dist/nord/api/metrics.js +0 -229
- package/dist/nord/api/queries.d.ts +0 -46
- package/dist/nord/api/queries.js +0 -109
- package/dist/nord/api/triggers.d.ts +0 -7
- package/dist/nord/api/triggers.js +0 -38
- package/dist/nord/client/Nord.d.ts +0 -396
- package/dist/nord/client/Nord.js +0 -747
- package/dist/nord/client/NordAdmin.d.ts +0 -259
- package/dist/nord/client/NordAdmin.js +0 -395
- package/dist/nord/client/NordClient.d.ts +0 -33
- package/dist/nord/client/NordClient.js +0 -45
- package/dist/nord/client/NordUser.d.ts +0 -362
- package/dist/nord/client/NordUser.js +0 -781
- package/dist/nord/index.d.ts +0 -11
- package/dist/nord/index.js +0 -36
- package/dist/nord/models/Subscriber.d.ts +0 -37
- package/dist/nord/models/Subscriber.js +0 -25
- package/dist/nord/utils/NordError.d.ts +0 -35
- package/dist/nord/utils/NordError.js +0 -49
- package/src/actions.ts +0 -333
- package/src/client/Nord.ts +0 -934
- package/src/client/NordAdmin.ts +0 -484
- package/src/client/NordUser.ts +0 -1122
- package/src/const.ts +0 -34
- package/src/error.ts +0 -76
- package/src/gen/.gitkeep +0 -0
- package/src/gen/nord_pb.ts +0 -5053
- package/src/gen/openapi.ts +0 -2904
- package/src/index.ts +0 -11
- package/src/types.ts +0 -327
- package/src/utils.ts +0 -266
- package/src/websocket/NordWebSocketClient.ts +0 -316
- package/src/websocket/Subscriber.ts +0 -56
- package/src/websocket/events.ts +0 -31
- package/src/websocket/index.ts +0 -105
package/dist/client/NordUser.js
CHANGED
|
@@ -1,53 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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.NordUser = void 0;
|
|
37
|
-
const spl_token_1 = require("@solana/spl-token");
|
|
38
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
39
|
-
const ed = __importStar(require("@noble/ed25519"));
|
|
40
|
-
const proton_1 = require("@n1xyz/proton");
|
|
41
|
-
const types_1 = require("../types");
|
|
42
|
-
const proto = __importStar(require("../gen/nord_pb"));
|
|
43
|
-
const utils_1 = require("../utils");
|
|
44
|
-
const protobuf_1 = require("@bufbuild/protobuf");
|
|
45
|
-
const actions_1 = require("../actions");
|
|
46
|
-
const error_1 = require("../error");
|
|
1
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddress, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, } from "@solana/spl-token";
|
|
2
|
+
import { PublicKey, Transaction } from "@solana/web3.js";
|
|
3
|
+
import * as ed from "@noble/ed25519";
|
|
4
|
+
import { floatToScaledBigIntLossy } from "@n1xyz/proton";
|
|
5
|
+
import { Side, TriggerKind, fillModeToProtoFillMode, } from "../types";
|
|
6
|
+
import * as proto from "../gen/nord_pb";
|
|
7
|
+
import { checkedFetch, assert, findMarket, findToken, optExpect, keypairFromPrivateKey, toScaledU64, } from "../utils";
|
|
8
|
+
import { create } from "@bufbuild/protobuf";
|
|
9
|
+
import { createSession, revokeSession, atomic, expectReceiptKind, createAction, sendAction, } from "../actions";
|
|
10
|
+
import { NordError } from "../error";
|
|
47
11
|
/**
|
|
48
12
|
* User class for interacting with the Nord protocol
|
|
49
13
|
*/
|
|
50
|
-
class NordUser {
|
|
14
|
+
export class NordUser {
|
|
15
|
+
nord;
|
|
16
|
+
sessionSignFn;
|
|
17
|
+
transactionSignFn;
|
|
18
|
+
sessionId;
|
|
19
|
+
sessionPubKey;
|
|
20
|
+
publicKey;
|
|
21
|
+
lastTs = 0;
|
|
22
|
+
nonce = 0;
|
|
23
|
+
/** User balances by token symbol */
|
|
24
|
+
balances = {};
|
|
25
|
+
/** User positions by account ID */
|
|
26
|
+
positions = {};
|
|
27
|
+
/** User margins by account ID */
|
|
28
|
+
margins = {};
|
|
29
|
+
/** User's account IDs */
|
|
30
|
+
accountIds;
|
|
31
|
+
/** SPL token information */
|
|
32
|
+
splTokenInfos = [];
|
|
51
33
|
/**
|
|
52
34
|
* Create a new NordUser instance
|
|
53
35
|
*
|
|
@@ -60,21 +42,11 @@ class NordUser {
|
|
|
60
42
|
* @throws {NordError} If required parameters are missing
|
|
61
43
|
*/
|
|
62
44
|
constructor({ nord, sessionSignFn, transactionSignFn, sessionId, sessionPubKey, publicKey, }) {
|
|
63
|
-
this.lastTs = 0;
|
|
64
|
-
this.nonce = 0;
|
|
65
|
-
/** User balances by token symbol */
|
|
66
|
-
this.balances = {};
|
|
67
|
-
/** User positions by account ID */
|
|
68
|
-
this.positions = {};
|
|
69
|
-
/** User margins by account ID */
|
|
70
|
-
this.margins = {};
|
|
71
|
-
/** SPL token information */
|
|
72
|
-
this.splTokenInfos = [];
|
|
73
45
|
this.nord = nord;
|
|
74
46
|
this.sessionSignFn = sessionSignFn;
|
|
75
47
|
this.transactionSignFn = transactionSignFn;
|
|
76
48
|
this.sessionId = sessionId;
|
|
77
|
-
this.sessionPubKey = new
|
|
49
|
+
this.sessionPubKey = new PublicKey(sessionPubKey);
|
|
78
50
|
this.publicKey = publicKey;
|
|
79
51
|
// Convert tokens from info endpoint to SPLTokenInfo
|
|
80
52
|
if (this.nord.tokens && this.nord.tokens.length > 0) {
|
|
@@ -96,7 +68,7 @@ class NordUser {
|
|
|
96
68
|
*/
|
|
97
69
|
static fromPrivateKey(nord, privateKey) {
|
|
98
70
|
try {
|
|
99
|
-
const keypair =
|
|
71
|
+
const keypair = keypairFromPrivateKey(privateKey);
|
|
100
72
|
const publicKey = keypair.publicKey;
|
|
101
73
|
const sessionSignFn = async (message) => {
|
|
102
74
|
// Use ed25519 to sign the message
|
|
@@ -115,7 +87,7 @@ class NordUser {
|
|
|
115
87
|
});
|
|
116
88
|
}
|
|
117
89
|
catch (error) {
|
|
118
|
-
throw new
|
|
90
|
+
throw new NordError("Failed to create NordUser from private key", {
|
|
119
91
|
cause: error,
|
|
120
92
|
});
|
|
121
93
|
}
|
|
@@ -132,19 +104,19 @@ class NordUser {
|
|
|
132
104
|
// Get the token program ID from the mint account
|
|
133
105
|
const mintAccount = await this.nord.solanaConnection.getAccountInfo(mint);
|
|
134
106
|
if (!mintAccount) {
|
|
135
|
-
throw new
|
|
107
|
+
throw new NordError("Mint account not found");
|
|
136
108
|
}
|
|
137
109
|
const tokenProgramId = mintAccount.owner;
|
|
138
110
|
// Validate that the mint is owned by a supported SPL token program
|
|
139
|
-
if (!tokenProgramId.equals(
|
|
140
|
-
!tokenProgramId.equals(
|
|
141
|
-
throw new
|
|
111
|
+
if (!tokenProgramId.equals(TOKEN_PROGRAM_ID) &&
|
|
112
|
+
!tokenProgramId.equals(TOKEN_2022_PROGRAM_ID)) {
|
|
113
|
+
throw new NordError("Mint Account is not owned by a supported SPL token program");
|
|
142
114
|
}
|
|
143
|
-
const associatedTokenAddress = await
|
|
115
|
+
const associatedTokenAddress = await getAssociatedTokenAddress(mint, this.publicKey, false, tokenProgramId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
144
116
|
return associatedTokenAddress;
|
|
145
117
|
}
|
|
146
118
|
catch (error) {
|
|
147
|
-
throw new
|
|
119
|
+
throw new NordError("Failed to get associated token account", {
|
|
148
120
|
cause: error,
|
|
149
121
|
});
|
|
150
122
|
}
|
|
@@ -177,20 +149,20 @@ class NordUser {
|
|
|
177
149
|
// Find the token info
|
|
178
150
|
const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
|
|
179
151
|
if (!tokenInfo) {
|
|
180
|
-
throw new
|
|
152
|
+
throw new NordError(`Token with ID ${tokenId} not found`);
|
|
181
153
|
}
|
|
182
|
-
const mint = new
|
|
154
|
+
const mint = new PublicKey(tokenInfo.mint);
|
|
183
155
|
const fromAccount = await this.getAssociatedTokenAccount(mint);
|
|
184
156
|
const payer = this.publicKey;
|
|
185
157
|
const { ix, extraSigner } = await this.nord.protonClient.buildDepositIx({
|
|
186
158
|
payer,
|
|
187
159
|
recipient: recipient ?? payer,
|
|
188
|
-
quantAmount:
|
|
160
|
+
quantAmount: floatToScaledBigIntLossy(amount, tokenInfo.precision),
|
|
189
161
|
mint,
|
|
190
162
|
sourceTokenAccount: fromAccount,
|
|
191
163
|
});
|
|
192
164
|
const { blockhash } = await this.nord.solanaConnection.getLatestBlockhash();
|
|
193
|
-
const tx = new
|
|
165
|
+
const tx = new Transaction();
|
|
194
166
|
tx.add(ix);
|
|
195
167
|
tx.recentBlockhash = blockhash;
|
|
196
168
|
tx.feePayer = payer;
|
|
@@ -200,7 +172,7 @@ class NordUser {
|
|
|
200
172
|
return signature;
|
|
201
173
|
}
|
|
202
174
|
catch (error) {
|
|
203
|
-
throw new
|
|
175
|
+
throw new NordError(`Failed to deposit ${amount} of token ID ${tokenId}`, { cause: error });
|
|
204
176
|
}
|
|
205
177
|
}
|
|
206
178
|
/**
|
|
@@ -228,18 +200,18 @@ class NordUser {
|
|
|
228
200
|
async updateAccountId() {
|
|
229
201
|
try {
|
|
230
202
|
if (!this.publicKey) {
|
|
231
|
-
throw new
|
|
203
|
+
throw new NordError("Public key is required to update account ID");
|
|
232
204
|
}
|
|
233
205
|
const resp = await this.nord.getUser({
|
|
234
206
|
pubkey: this.publicKey.toBase58(),
|
|
235
207
|
});
|
|
236
208
|
if (!resp) {
|
|
237
|
-
throw new
|
|
209
|
+
throw new NordError(`User ${this.publicKey.toBase58()} not found`);
|
|
238
210
|
}
|
|
239
211
|
this.accountIds = resp.accountIds;
|
|
240
212
|
}
|
|
241
213
|
catch (error) {
|
|
242
|
-
throw new
|
|
214
|
+
throw new NordError("Failed to update account ID", { cause: error });
|
|
243
215
|
}
|
|
244
216
|
}
|
|
245
217
|
/**
|
|
@@ -250,7 +222,7 @@ class NordUser {
|
|
|
250
222
|
async fetchInfo() {
|
|
251
223
|
if (this.accountIds !== undefined) {
|
|
252
224
|
const accountsData = await Promise.all(this.accountIds.map(async (accountId) => {
|
|
253
|
-
const response = await
|
|
225
|
+
const response = await checkedFetch(`${this.nord.webServerUrl}/account/${accountId}`);
|
|
254
226
|
const accountData = (await response.json());
|
|
255
227
|
// Ensure we have the correct accountId
|
|
256
228
|
return {
|
|
@@ -281,7 +253,7 @@ class NordUser {
|
|
|
281
253
|
* @throws {NordError} If the operation fails
|
|
282
254
|
*/
|
|
283
255
|
async refreshSession() {
|
|
284
|
-
const result = await
|
|
256
|
+
const result = await createSession(this.nord.httpClient, this.transactionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
285
257
|
userPubkey: this.publicKey,
|
|
286
258
|
sessionPubkey: this.sessionPubKey,
|
|
287
259
|
});
|
|
@@ -295,13 +267,13 @@ class NordUser {
|
|
|
295
267
|
*/
|
|
296
268
|
async revokeSession(sessionId) {
|
|
297
269
|
try {
|
|
298
|
-
await
|
|
270
|
+
await revokeSession(this.nord.httpClient, this.transactionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
299
271
|
userPubkey: this.publicKey,
|
|
300
272
|
sessionId,
|
|
301
273
|
});
|
|
302
274
|
}
|
|
303
275
|
catch (error) {
|
|
304
|
-
throw new
|
|
276
|
+
throw new NordError(`Failed to revoke session ${sessionId}`, {
|
|
305
277
|
cause: error,
|
|
306
278
|
});
|
|
307
279
|
}
|
|
@@ -313,7 +285,7 @@ class NordUser {
|
|
|
313
285
|
*/
|
|
314
286
|
checkSessionValidity() {
|
|
315
287
|
if (this.sessionId === undefined || this.sessionId === BigInt(0)) {
|
|
316
|
-
throw new
|
|
288
|
+
throw new NordError("Invalid or empty session ID. Please create or refresh your session.");
|
|
317
289
|
}
|
|
318
290
|
}
|
|
319
291
|
/**
|
|
@@ -326,24 +298,24 @@ class NordUser {
|
|
|
326
298
|
async withdraw({ amount, tokenId, }) {
|
|
327
299
|
try {
|
|
328
300
|
this.checkSessionValidity();
|
|
329
|
-
const token =
|
|
330
|
-
const scaledAmount =
|
|
301
|
+
const token = findToken(this.nord.tokens, tokenId);
|
|
302
|
+
const scaledAmount = toScaledU64(amount, token.decimals);
|
|
331
303
|
if (scaledAmount <= 0n) {
|
|
332
|
-
throw new
|
|
304
|
+
throw new NordError("Withdraw amount must be positive");
|
|
333
305
|
}
|
|
334
306
|
const receipt = await this.submitSessionAction({
|
|
335
307
|
case: "withdraw",
|
|
336
|
-
value:
|
|
337
|
-
sessionId: BigInt(
|
|
308
|
+
value: create(proto.Action_WithdrawSchema, {
|
|
309
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
338
310
|
tokenId,
|
|
339
311
|
amount: scaledAmount,
|
|
340
312
|
}),
|
|
341
313
|
});
|
|
342
|
-
|
|
314
|
+
expectReceiptKind(receipt, "withdrawResult", "withdraw");
|
|
343
315
|
return { actionId: receipt.actionId };
|
|
344
316
|
}
|
|
345
317
|
catch (error) {
|
|
346
|
-
throw new
|
|
318
|
+
throw new NordError(`Failed to withdraw ${amount} of token ID ${tokenId}`, { cause: error });
|
|
347
319
|
}
|
|
348
320
|
}
|
|
349
321
|
/**
|
|
@@ -364,38 +336,38 @@ class NordUser {
|
|
|
364
336
|
async placeOrder({ marketId, side, fillMode, isReduceOnly, size, price, quoteSize, accountId, clientOrderId, }) {
|
|
365
337
|
try {
|
|
366
338
|
this.checkSessionValidity();
|
|
367
|
-
const market =
|
|
339
|
+
const market = findMarket(this.nord.markets, marketId);
|
|
368
340
|
if (!market) {
|
|
369
|
-
throw new
|
|
341
|
+
throw new NordError(`Market with ID ${marketId} not found`);
|
|
370
342
|
}
|
|
371
|
-
const sessionId =
|
|
372
|
-
const scaledPrice =
|
|
373
|
-
const scaledSize =
|
|
343
|
+
const sessionId = optExpect(this.sessionId, "No session");
|
|
344
|
+
const scaledPrice = toScaledU64(price ?? 0, market.priceDecimals);
|
|
345
|
+
const scaledSize = toScaledU64(size ?? 0, market.sizeDecimals);
|
|
374
346
|
const scaledQuote = quoteSize
|
|
375
347
|
? quoteSize.toWire(market.priceDecimals, market.sizeDecimals)
|
|
376
348
|
: undefined;
|
|
377
|
-
|
|
349
|
+
assert(scaledPrice > 0n || scaledSize > 0n || scaledQuote !== undefined, "OrderLimit must include at least one of: size, price, or quoteSize");
|
|
378
350
|
const receipt = await this.submitSessionAction({
|
|
379
351
|
case: "placeOrder",
|
|
380
|
-
value:
|
|
352
|
+
value: create(proto.Action_PlaceOrderSchema, {
|
|
381
353
|
sessionId: BigInt(sessionId),
|
|
382
354
|
senderAccountId: accountId,
|
|
383
355
|
marketId,
|
|
384
|
-
side: side ===
|
|
385
|
-
fillMode:
|
|
356
|
+
side: side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
357
|
+
fillMode: fillModeToProtoFillMode(fillMode),
|
|
386
358
|
isReduceOnly,
|
|
387
359
|
price: scaledPrice,
|
|
388
360
|
size: scaledSize,
|
|
389
361
|
quoteSize: scaledQuote === undefined
|
|
390
362
|
? undefined
|
|
391
|
-
:
|
|
363
|
+
: create(proto.QuoteSizeSchema, {
|
|
392
364
|
size: scaledQuote.size,
|
|
393
365
|
price: scaledQuote.price,
|
|
394
366
|
}),
|
|
395
367
|
clientOrderId: clientOrderId === undefined ? undefined : BigInt(clientOrderId),
|
|
396
368
|
}),
|
|
397
369
|
});
|
|
398
|
-
|
|
370
|
+
expectReceiptKind(receipt, "placeOrderResult", "place order");
|
|
399
371
|
const result = receipt.kind.value;
|
|
400
372
|
return {
|
|
401
373
|
actionId: receipt.actionId,
|
|
@@ -404,7 +376,7 @@ class NordUser {
|
|
|
404
376
|
};
|
|
405
377
|
}
|
|
406
378
|
catch (error) {
|
|
407
|
-
throw new
|
|
379
|
+
throw new NordError("Failed to place order", { cause: error });
|
|
408
380
|
}
|
|
409
381
|
}
|
|
410
382
|
/**
|
|
@@ -421,13 +393,13 @@ class NordUser {
|
|
|
421
393
|
this.checkSessionValidity();
|
|
422
394
|
const receipt = await this.submitSessionAction({
|
|
423
395
|
case: "cancelOrderById",
|
|
424
|
-
value:
|
|
396
|
+
value: create(proto.Action_CancelOrderByIdSchema, {
|
|
425
397
|
orderId: BigInt(orderId),
|
|
426
|
-
sessionId: BigInt(
|
|
398
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
427
399
|
senderAccountId: accountId,
|
|
428
400
|
}),
|
|
429
401
|
});
|
|
430
|
-
|
|
402
|
+
expectReceiptKind(receipt, "cancelOrderResult", "cancel order");
|
|
431
403
|
return {
|
|
432
404
|
actionId: receipt.actionId,
|
|
433
405
|
orderId: receipt.kind.value.orderId,
|
|
@@ -435,7 +407,7 @@ class NordUser {
|
|
|
435
407
|
};
|
|
436
408
|
}
|
|
437
409
|
catch (error) {
|
|
438
|
-
throw new
|
|
410
|
+
throw new NordError(`Failed to cancel order ${orderId}`, {
|
|
439
411
|
cause: error,
|
|
440
412
|
});
|
|
441
413
|
}
|
|
@@ -455,43 +427,43 @@ class NordUser {
|
|
|
455
427
|
async addTrigger({ marketId, side, kind, triggerPrice, limitPrice, accountId, }) {
|
|
456
428
|
try {
|
|
457
429
|
this.checkSessionValidity();
|
|
458
|
-
const market =
|
|
430
|
+
const market = findMarket(this.nord.markets, marketId);
|
|
459
431
|
if (!market) {
|
|
460
|
-
throw new
|
|
432
|
+
throw new NordError(`Market with ID ${marketId} not found`);
|
|
461
433
|
}
|
|
462
|
-
const scaledTriggerPrice =
|
|
463
|
-
|
|
434
|
+
const scaledTriggerPrice = toScaledU64(triggerPrice, market.priceDecimals);
|
|
435
|
+
assert(scaledTriggerPrice > 0n, "Trigger price must be positive");
|
|
464
436
|
const scaledLimitPrice = limitPrice === undefined
|
|
465
437
|
? undefined
|
|
466
|
-
:
|
|
438
|
+
: toScaledU64(limitPrice, market.priceDecimals);
|
|
467
439
|
if (scaledLimitPrice !== undefined) {
|
|
468
|
-
|
|
440
|
+
assert(scaledLimitPrice > 0n, "Limit price must be positive");
|
|
469
441
|
}
|
|
470
|
-
const key =
|
|
471
|
-
kind: kind ===
|
|
442
|
+
const key = create(proto.TriggerKeySchema, {
|
|
443
|
+
kind: kind === TriggerKind.StopLoss
|
|
472
444
|
? proto.TriggerKind.STOP_LOSS
|
|
473
445
|
: proto.TriggerKind.TAKE_PROFIT,
|
|
474
|
-
side: side ===
|
|
446
|
+
side: side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
475
447
|
});
|
|
476
|
-
const prices =
|
|
448
|
+
const prices = create(proto.Action_TriggerPricesSchema, {
|
|
477
449
|
triggerPrice: scaledTriggerPrice,
|
|
478
450
|
limitPrice: scaledLimitPrice,
|
|
479
451
|
});
|
|
480
452
|
const receipt = await this.submitSessionAction({
|
|
481
453
|
case: "addTrigger",
|
|
482
|
-
value:
|
|
483
|
-
sessionId: BigInt(
|
|
454
|
+
value: create(proto.Action_AddTriggerSchema, {
|
|
455
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
484
456
|
marketId,
|
|
485
457
|
key,
|
|
486
458
|
prices,
|
|
487
459
|
accountId,
|
|
488
460
|
}),
|
|
489
461
|
});
|
|
490
|
-
|
|
462
|
+
expectReceiptKind(receipt, "triggerAdded", "add trigger");
|
|
491
463
|
return { actionId: receipt.actionId };
|
|
492
464
|
}
|
|
493
465
|
catch (error) {
|
|
494
|
-
throw new
|
|
466
|
+
throw new NordError("Failed to add trigger", { cause: error });
|
|
495
467
|
}
|
|
496
468
|
}
|
|
497
469
|
/**
|
|
@@ -507,30 +479,30 @@ class NordUser {
|
|
|
507
479
|
async removeTrigger({ marketId, side, kind, accountId, }) {
|
|
508
480
|
try {
|
|
509
481
|
this.checkSessionValidity();
|
|
510
|
-
const market =
|
|
482
|
+
const market = findMarket(this.nord.markets, marketId);
|
|
511
483
|
if (!market) {
|
|
512
|
-
throw new
|
|
484
|
+
throw new NordError(`Market with ID ${marketId} not found`);
|
|
513
485
|
}
|
|
514
|
-
const key =
|
|
515
|
-
kind: kind ===
|
|
486
|
+
const key = create(proto.TriggerKeySchema, {
|
|
487
|
+
kind: kind === TriggerKind.StopLoss
|
|
516
488
|
? proto.TriggerKind.STOP_LOSS
|
|
517
489
|
: proto.TriggerKind.TAKE_PROFIT,
|
|
518
|
-
side: side ===
|
|
490
|
+
side: side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
519
491
|
});
|
|
520
492
|
const receipt = await this.submitSessionAction({
|
|
521
493
|
case: "removeTrigger",
|
|
522
|
-
value:
|
|
523
|
-
sessionId: BigInt(
|
|
494
|
+
value: create(proto.Action_RemoveTriggerSchema, {
|
|
495
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
524
496
|
marketId,
|
|
525
497
|
key,
|
|
526
498
|
accountId,
|
|
527
499
|
}),
|
|
528
500
|
});
|
|
529
|
-
|
|
501
|
+
expectReceiptKind(receipt, "triggerRemoved", "remove trigger");
|
|
530
502
|
return { actionId: receipt.actionId };
|
|
531
503
|
}
|
|
532
504
|
catch (error) {
|
|
533
|
-
throw new
|
|
505
|
+
throw new NordError("Failed to remove trigger", { cause: error });
|
|
534
506
|
}
|
|
535
507
|
}
|
|
536
508
|
/**
|
|
@@ -545,24 +517,24 @@ class NordUser {
|
|
|
545
517
|
async transferToAccount({ tokenId, amount, fromAccountId, toAccountId, }) {
|
|
546
518
|
try {
|
|
547
519
|
this.checkSessionValidity();
|
|
548
|
-
const token =
|
|
549
|
-
const scaledAmount =
|
|
520
|
+
const token = findToken(this.nord.tokens, tokenId);
|
|
521
|
+
const scaledAmount = toScaledU64(amount, token.decimals);
|
|
550
522
|
if (scaledAmount <= 0n) {
|
|
551
|
-
throw new
|
|
523
|
+
throw new NordError("Transfer amount must be positive");
|
|
552
524
|
}
|
|
553
525
|
const receipt = await this.submitSessionAction({
|
|
554
526
|
case: "transfer",
|
|
555
|
-
value:
|
|
556
|
-
sessionId: BigInt(
|
|
557
|
-
fromAccountId:
|
|
558
|
-
toAccountId:
|
|
527
|
+
value: create(proto.Action_TransferSchema, {
|
|
528
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
529
|
+
fromAccountId: optExpect(fromAccountId, "No source account"),
|
|
530
|
+
toAccountId: optExpect(toAccountId, "No target account"),
|
|
559
531
|
tokenId,
|
|
560
532
|
amount: scaledAmount,
|
|
561
533
|
}),
|
|
562
534
|
});
|
|
563
|
-
|
|
535
|
+
expectReceiptKind(receipt, "transferred", "transfer tokens");
|
|
564
536
|
if (receipt.kind.value.accountCreated) {
|
|
565
|
-
|
|
537
|
+
assert(receipt.kind.value.toUserAccount !== undefined, `toAccount must be defined on new account on ${receipt.kind.value}`);
|
|
566
538
|
return {
|
|
567
539
|
actionId: receipt.actionId,
|
|
568
540
|
newAccountId: receipt.kind.value.toUserAccount,
|
|
@@ -573,7 +545,7 @@ class NordUser {
|
|
|
573
545
|
}
|
|
574
546
|
}
|
|
575
547
|
catch (error) {
|
|
576
|
-
throw new
|
|
548
|
+
throw new NordError("Failed to transfer tokens", { cause: error });
|
|
577
549
|
}
|
|
578
550
|
}
|
|
579
551
|
/**
|
|
@@ -593,13 +565,13 @@ class NordUser {
|
|
|
593
565
|
this.checkSessionValidity();
|
|
594
566
|
const accountId = providedAccountId != null ? providedAccountId : this.accountIds?.[0];
|
|
595
567
|
if (accountId == null) {
|
|
596
|
-
throw new
|
|
568
|
+
throw new NordError("Account ID is undefined. Make sure to call updateAccountId() before atomic operations.");
|
|
597
569
|
}
|
|
598
570
|
const apiActions = userActions.map((act) => {
|
|
599
571
|
if (act.kind === "place") {
|
|
600
|
-
const market =
|
|
572
|
+
const market = findMarket(this.nord.markets, act.marketId);
|
|
601
573
|
if (!market) {
|
|
602
|
-
throw new
|
|
574
|
+
throw new NordError(`Market ${act.marketId} not found`);
|
|
603
575
|
}
|
|
604
576
|
return {
|
|
605
577
|
kind: "place",
|
|
@@ -620,15 +592,15 @@ class NordUser {
|
|
|
620
592
|
orderId: act.orderId,
|
|
621
593
|
};
|
|
622
594
|
});
|
|
623
|
-
const result = await
|
|
624
|
-
sessionId:
|
|
595
|
+
const result = await atomic(this.nord.httpClient, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
|
|
596
|
+
sessionId: optExpect(this.sessionId, "No session"),
|
|
625
597
|
accountId: accountId,
|
|
626
598
|
actions: apiActions,
|
|
627
599
|
});
|
|
628
600
|
return result;
|
|
629
601
|
}
|
|
630
602
|
catch (error) {
|
|
631
|
-
throw new
|
|
603
|
+
throw new NordError("Atomic operation failed", { cause: error });
|
|
632
604
|
}
|
|
633
605
|
}
|
|
634
606
|
/**
|
|
@@ -695,8 +667,8 @@ class NordUser {
|
|
|
695
667
|
// Process batch in parallel
|
|
696
668
|
const batchPromises = batch.map(async (token) => {
|
|
697
669
|
try {
|
|
698
|
-
const mint = new
|
|
699
|
-
const associatedTokenAddress = await this.retryWithBackoff(() =>
|
|
670
|
+
const mint = new PublicKey(token.mintAddr);
|
|
671
|
+
const associatedTokenAddress = await this.retryWithBackoff(() => getAssociatedTokenAddress(mint, this.publicKey), maxRetries);
|
|
700
672
|
if (includeTokenAccounts) {
|
|
701
673
|
tokenAccounts[token.symbol] = associatedTokenAddress.toString();
|
|
702
674
|
}
|
|
@@ -728,7 +700,7 @@ class NordUser {
|
|
|
728
700
|
return includeTokenAccounts ? { balances, tokenAccounts } : { balances };
|
|
729
701
|
}
|
|
730
702
|
catch (error) {
|
|
731
|
-
throw new
|
|
703
|
+
throw new NordError("Failed to get Solana token balances", {
|
|
732
704
|
cause: error,
|
|
733
705
|
});
|
|
734
706
|
}
|
|
@@ -736,8 +708,7 @@ class NordUser {
|
|
|
736
708
|
async submitSignedAction(kind, makeSignedMessage) {
|
|
737
709
|
const nonce = this.getNonce();
|
|
738
710
|
const currentTimestamp = await this.nord.getTimestamp();
|
|
739
|
-
const action =
|
|
740
|
-
return
|
|
711
|
+
const action = createAction(currentTimestamp, nonce, kind);
|
|
712
|
+
return sendAction(this.nord.httpClient, makeSignedMessage, action);
|
|
741
713
|
}
|
|
742
714
|
}
|
|
743
|
-
exports.NordUser = NordUser;
|
package/dist/const.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_FUNDING_AMOUNTS = exports.DEV_TOKEN_INFOS = exports.WEBSERVER_DEV_URL = exports.DEV_URL = exports.DEBUG_KEYS = void 0;
|
|
4
1
|
const WEBSERVER_PORT = "80";
|
|
5
|
-
|
|
2
|
+
export const DEBUG_KEYS = [
|
|
6
3
|
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
|
|
7
4
|
"0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
|
|
8
5
|
"0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a",
|
|
@@ -14,9 +11,9 @@ exports.DEBUG_KEYS = [
|
|
|
14
11
|
"0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97",
|
|
15
12
|
"0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6",
|
|
16
13
|
];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
export const DEV_URL = "http://localhost";
|
|
15
|
+
export const WEBSERVER_DEV_URL = DEV_URL + ":" + WEBSERVER_PORT;
|
|
16
|
+
export const DEV_TOKEN_INFOS = [
|
|
20
17
|
{
|
|
21
18
|
address: "0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae",
|
|
22
19
|
precision: 6,
|
|
@@ -24,7 +21,7 @@ exports.DEV_TOKEN_INFOS = [
|
|
|
24
21
|
name: "usdc",
|
|
25
22
|
},
|
|
26
23
|
];
|
|
27
|
-
|
|
24
|
+
export const DEFAULT_FUNDING_AMOUNTS = {
|
|
28
25
|
SOL: ["0.2", 0],
|
|
29
26
|
"0x9a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae": ["10000", 6],
|
|
30
27
|
};
|
package/dist/error.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NordError = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* Custom error class for Nord-related errors
|
|
6
3
|
*/
|
|
7
|
-
class NordError extends Error {
|
|
4
|
+
export class NordError extends Error {
|
|
5
|
+
/** The original error that caused this error */
|
|
6
|
+
cause;
|
|
7
|
+
/** HTTP status code (if applicable) */
|
|
8
|
+
statusCode;
|
|
9
|
+
/** Additional error details */
|
|
10
|
+
details;
|
|
8
11
|
/**
|
|
9
12
|
* Create a new NordError
|
|
10
13
|
*
|
|
@@ -46,4 +49,3 @@ class NordError extends Error {
|
|
|
46
49
|
return result;
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
|
-
exports.NordError = NordError;
|