@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.
- package/README.md +2 -2
- package/dist/gen/nord_pb.d.ts +399 -3
- package/dist/gen/nord_pb.js +119 -61
- package/dist/gen/openapi.d.ts +216 -3
- package/dist/nord/api/actions.d.ts +11 -0
- package/dist/nord/api/actions.js +18 -0
- package/dist/nord/client/Nord.d.ts +113 -8
- package/dist/nord/client/Nord.js +206 -8
- package/dist/nord/client/NordAdmin.d.ts +236 -0
- package/dist/nord/client/NordAdmin.js +337 -0
- package/dist/nord/client/NordClient.d.ts +33 -0
- package/dist/nord/client/NordClient.js +45 -0
- package/dist/nord/client/NordUser.d.ts +6 -50
- package/dist/nord/client/NordUser.js +162 -133
- package/dist/nord/index.d.ts +4 -0
- package/dist/nord/index.js +5 -1
- package/dist/types.d.ts +13 -5
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +5 -0
- package/package.json +2 -2
- package/src/gen/nord_pb.ts +499 -60
- package/src/gen/openapi.ts +216 -3
- package/src/nord/api/actions.ts +28 -4
- package/src/nord/client/Nord.ts +258 -15
- package/src/nord/client/NordAdmin.ts +441 -0
- package/src/nord/client/NordClient.ts +79 -0
- package/src/nord/client/NordUser.ts +176 -229
- package/src/nord/index.ts +11 -0
- package/src/types.ts +15 -5
- package/src/utils.ts +5 -0
- package/src/nord/api/triggers.ts +0 -57
|
@@ -21,39 +21,30 @@ import {
|
|
|
21
21
|
SPLTokenInfo,
|
|
22
22
|
QuoteSize,
|
|
23
23
|
TriggerKind,
|
|
24
|
+
fillModeToProtoFillMode,
|
|
24
25
|
} from "../../types";
|
|
25
26
|
import * as proto from "../../gen/nord_pb";
|
|
26
27
|
import {
|
|
27
28
|
BigIntValue,
|
|
28
29
|
checkedFetch,
|
|
30
|
+
assert,
|
|
29
31
|
findMarket,
|
|
30
32
|
findToken,
|
|
31
33
|
optExpect,
|
|
32
34
|
keypairFromPrivateKey,
|
|
35
|
+
toScaledU64,
|
|
33
36
|
} from "../../utils";
|
|
37
|
+
import { create } from "@bufbuild/protobuf";
|
|
34
38
|
import {
|
|
35
|
-
cancelOrder,
|
|
36
39
|
createSession,
|
|
37
|
-
placeOrder,
|
|
38
40
|
revokeSession,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
AtomicSubaction as ApiAtomicSubaction,
|
|
43
|
-
addTrigger as addTriggerAction,
|
|
44
|
-
removeTrigger as removeTriggerAction,
|
|
41
|
+
atomic,
|
|
42
|
+
expectReceiptKind,
|
|
43
|
+
AtomicSubaction,
|
|
45
44
|
} from "../api/actions";
|
|
46
|
-
import type {
|
|
47
|
-
AccountTriggerInfo,
|
|
48
|
-
TriggerHistoryPage,
|
|
49
|
-
HistoryTriggerQuery,
|
|
50
|
-
} from "../api/triggers";
|
|
51
|
-
import {
|
|
52
|
-
getAccountTriggers as fetchAccountTriggers,
|
|
53
|
-
getAccountTriggerHistory as fetchAccountTriggerHistory,
|
|
54
|
-
} from "../api/triggers";
|
|
55
45
|
import { NordError } from "../utils/NordError";
|
|
56
46
|
import { Nord } from "./Nord";
|
|
47
|
+
import { NordClient } from "./NordClient";
|
|
57
48
|
|
|
58
49
|
/**
|
|
59
50
|
* Parameters for creating a NordUser instance
|
|
@@ -114,6 +105,8 @@ export interface PlaceOrderParams {
|
|
|
114
105
|
|
|
115
106
|
/** Account ID to place the order from */
|
|
116
107
|
accountId?: number;
|
|
108
|
+
|
|
109
|
+
clientOrderId?: BigIntValue;
|
|
117
110
|
}
|
|
118
111
|
|
|
119
112
|
export interface AddTriggerParams {
|
|
@@ -190,26 +183,7 @@ export interface UserAtomicSubaction {
|
|
|
190
183
|
/**
|
|
191
184
|
* User class for interacting with the Nord protocol
|
|
192
185
|
*/
|
|
193
|
-
export class NordUser {
|
|
194
|
-
/** Nord client instance */
|
|
195
|
-
public readonly nord: Nord;
|
|
196
|
-
|
|
197
|
-
/** User's blockchain address */
|
|
198
|
-
public readonly address: PublicKey;
|
|
199
|
-
|
|
200
|
-
/** Function to sign messages with the user's wallet */
|
|
201
|
-
public readonly walletSignFn: (
|
|
202
|
-
message: Uint8Array | string,
|
|
203
|
-
) => Promise<Uint8Array>;
|
|
204
|
-
|
|
205
|
-
/** Function to sign messages with the user's session key */
|
|
206
|
-
public readonly sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
|
|
207
|
-
|
|
208
|
-
/** Function to sign transactions with the user's wallet */
|
|
209
|
-
public readonly transactionSignFn: <T extends Transaction>(
|
|
210
|
-
tx: T,
|
|
211
|
-
) => Promise<T>;
|
|
212
|
-
|
|
186
|
+
export class NordUser extends NordClient {
|
|
213
187
|
/** User balances by token symbol */
|
|
214
188
|
public balances: {
|
|
215
189
|
[key: string]: { accountId: number; balance: number; symbol: string }[];
|
|
@@ -249,24 +223,6 @@ export class NordUser {
|
|
|
249
223
|
/** User's account IDs */
|
|
250
224
|
public accountIds?: number[];
|
|
251
225
|
|
|
252
|
-
/** Current session ID */
|
|
253
|
-
public sessionId?: bigint;
|
|
254
|
-
|
|
255
|
-
/** User's public key */
|
|
256
|
-
public publicKey: PublicKey;
|
|
257
|
-
|
|
258
|
-
/** Session public key */
|
|
259
|
-
public sessionPubKey: Uint8Array;
|
|
260
|
-
|
|
261
|
-
/** Last timestamp used */
|
|
262
|
-
public lastTs = 0;
|
|
263
|
-
|
|
264
|
-
/** Last nonce used */
|
|
265
|
-
public lastNonce = 0;
|
|
266
|
-
|
|
267
|
-
/** Solana connection */
|
|
268
|
-
public connection: Connection;
|
|
269
|
-
|
|
270
226
|
/** SPL token information */
|
|
271
227
|
public splTokenInfos: SPLTokenInfo[] = [];
|
|
272
228
|
|
|
@@ -297,28 +253,24 @@ export class NordUser {
|
|
|
297
253
|
throw new NordError("Session public key is required");
|
|
298
254
|
}
|
|
299
255
|
|
|
256
|
+
let parsedAddress: PublicKey;
|
|
300
257
|
try {
|
|
301
|
-
|
|
258
|
+
parsedAddress = new PublicKey(address);
|
|
302
259
|
} catch (error) {
|
|
303
260
|
throw new NordError("Invalid Solana address", { cause: error });
|
|
304
261
|
}
|
|
305
262
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// Set sessionId if provided
|
|
319
|
-
if (sessionId !== undefined) {
|
|
320
|
-
this.sessionId = sessionId;
|
|
321
|
-
}
|
|
263
|
+
super({
|
|
264
|
+
nord,
|
|
265
|
+
address: parsedAddress,
|
|
266
|
+
walletSignFn,
|
|
267
|
+
sessionSignFn,
|
|
268
|
+
transactionSignFn,
|
|
269
|
+
connection,
|
|
270
|
+
sessionId,
|
|
271
|
+
sessionPubKey,
|
|
272
|
+
publicKey,
|
|
273
|
+
});
|
|
322
274
|
|
|
323
275
|
// Convert tokens from info endpoint to SPLTokenInfo
|
|
324
276
|
if (this.nord.tokens && this.nord.tokens.length > 0) {
|
|
@@ -344,8 +296,9 @@ export class NordUser {
|
|
|
344
296
|
sessionSignFn: this.sessionSignFn,
|
|
345
297
|
transactionSignFn: this.transactionSignFn,
|
|
346
298
|
connection: this.connection,
|
|
347
|
-
sessionPubKey: this.sessionPubKey,
|
|
299
|
+
sessionPubKey: new Uint8Array(this.sessionPubKey),
|
|
348
300
|
publicKey: this.publicKey,
|
|
301
|
+
sessionId: this.sessionId,
|
|
349
302
|
});
|
|
350
303
|
|
|
351
304
|
// Copy other properties
|
|
@@ -353,11 +306,8 @@ export class NordUser {
|
|
|
353
306
|
cloned.positions = { ...this.positions };
|
|
354
307
|
cloned.margins = { ...this.margins };
|
|
355
308
|
cloned.accountIds = this.accountIds ? [...this.accountIds] : undefined;
|
|
356
|
-
cloned.sessionId = this.sessionId;
|
|
357
|
-
cloned.publicKey = this.publicKey;
|
|
358
|
-
cloned.lastTs = this.lastTs;
|
|
359
|
-
cloned.lastNonce = this.lastNonce;
|
|
360
309
|
cloned.splTokenInfos = [...this.splTokenInfos];
|
|
310
|
+
this.cloneClientState(cloned);
|
|
361
311
|
|
|
362
312
|
return cloned;
|
|
363
313
|
}
|
|
@@ -486,7 +436,7 @@ export class NordUser {
|
|
|
486
436
|
}
|
|
487
437
|
|
|
488
438
|
/**
|
|
489
|
-
* Deposit SPL tokens to the
|
|
439
|
+
* Deposit SPL tokens to the app
|
|
490
440
|
*
|
|
491
441
|
* @param amount - Amount to deposit
|
|
492
442
|
* @param tokenId - Token ID
|
|
@@ -504,7 +454,7 @@ export class NordUser {
|
|
|
504
454
|
}
|
|
505
455
|
|
|
506
456
|
/**
|
|
507
|
-
* Deposit SPL tokens to the
|
|
457
|
+
* Deposit SPL tokens to the app
|
|
508
458
|
*
|
|
509
459
|
* @param amount - Amount to deposit
|
|
510
460
|
* @param tokenId - Token ID
|
|
@@ -573,7 +523,19 @@ export class NordUser {
|
|
|
573
523
|
* @returns Nonce as number
|
|
574
524
|
*/
|
|
575
525
|
getNonce(): number {
|
|
576
|
-
return
|
|
526
|
+
return this.nextActionNonce();
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private async submitSessionAction(
|
|
530
|
+
kind: proto.Action["kind"],
|
|
531
|
+
): Promise<proto.Receipt> {
|
|
532
|
+
return this.submitSignedAction(kind, async (message) => {
|
|
533
|
+
const signature = await this.sessionSignFn(message);
|
|
534
|
+
const signed = new Uint8Array(message.length + signature.length);
|
|
535
|
+
signed.set(message);
|
|
536
|
+
signed.set(signature, message.length);
|
|
537
|
+
return signed;
|
|
538
|
+
});
|
|
577
539
|
}
|
|
578
540
|
|
|
579
541
|
/**
|
|
@@ -763,19 +725,21 @@ export class NordUser {
|
|
|
763
725
|
}>): Promise<{ actionId: bigint }> {
|
|
764
726
|
try {
|
|
765
727
|
this.checkSessionValidity();
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
728
|
+
const token = findToken(this.nord.tokens, tokenId);
|
|
729
|
+
const scaledAmount = toScaledU64(amount, token.decimals);
|
|
730
|
+
if (scaledAmount <= 0n) {
|
|
731
|
+
throw new NordError("Withdraw amount must be positive");
|
|
732
|
+
}
|
|
733
|
+
const receipt = await this.submitSessionAction({
|
|
734
|
+
case: "withdraw",
|
|
735
|
+
value: create(proto.Action_WithdrawSchema, {
|
|
736
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
737
|
+
tokenId,
|
|
738
|
+
amount: scaledAmount,
|
|
739
|
+
}),
|
|
740
|
+
});
|
|
741
|
+
expectReceiptKind(receipt, "withdrawResult", "withdraw");
|
|
742
|
+
return { actionId: receipt.actionId };
|
|
779
743
|
} catch (error) {
|
|
780
744
|
throw new NordError(
|
|
781
745
|
`Failed to withdraw ${amount} of token ID ${tokenId}`,
|
|
@@ -802,27 +766,48 @@ export class NordUser {
|
|
|
802
766
|
if (!market) {
|
|
803
767
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
804
768
|
}
|
|
769
|
+
const sessionId = optExpect(this.sessionId, "No session");
|
|
770
|
+
const price = toScaledU64(params.price ?? 0, market.priceDecimals);
|
|
771
|
+
const size = toScaledU64(params.size ?? 0, market.sizeDecimals);
|
|
772
|
+
const scaledQuote = params.quoteSize
|
|
773
|
+
? params.quoteSize.toWire(market.priceDecimals, market.sizeDecimals)
|
|
774
|
+
: undefined;
|
|
775
|
+
assert(
|
|
776
|
+
price > 0n || size > 0n || scaledQuote !== undefined,
|
|
777
|
+
"OrderLimit must include at least one of: size, price, or quoteSize",
|
|
778
|
+
);
|
|
805
779
|
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
{
|
|
812
|
-
sessionId: optExpect(this.sessionId, "No session"),
|
|
813
|
-
senderId: params.accountId,
|
|
814
|
-
sizeDecimals: market.sizeDecimals,
|
|
815
|
-
priceDecimals: market.priceDecimals,
|
|
780
|
+
const receipt = await this.submitSessionAction({
|
|
781
|
+
case: "placeOrder",
|
|
782
|
+
value: create(proto.Action_PlaceOrderSchema, {
|
|
783
|
+
sessionId: BigInt(sessionId),
|
|
784
|
+
senderAccountId: params.accountId,
|
|
816
785
|
marketId: params.marketId,
|
|
817
|
-
side: params.side,
|
|
818
|
-
fillMode: params.fillMode,
|
|
786
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
787
|
+
fillMode: fillModeToProtoFillMode(params.fillMode),
|
|
819
788
|
isReduceOnly: params.isReduceOnly,
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
quoteSize:
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
789
|
+
price,
|
|
790
|
+
size,
|
|
791
|
+
quoteSize:
|
|
792
|
+
scaledQuote === undefined
|
|
793
|
+
? undefined
|
|
794
|
+
: create(proto.QuoteSizeSchema, {
|
|
795
|
+
size: scaledQuote.size,
|
|
796
|
+
price: scaledQuote.price,
|
|
797
|
+
}),
|
|
798
|
+
clientOrderId:
|
|
799
|
+
params.clientOrderId === undefined
|
|
800
|
+
? undefined
|
|
801
|
+
: BigInt(params.clientOrderId),
|
|
802
|
+
}),
|
|
803
|
+
});
|
|
804
|
+
expectReceiptKind(receipt, "placeOrderResult", "place order");
|
|
805
|
+
const result = receipt.kind.value;
|
|
806
|
+
return {
|
|
807
|
+
actionId: receipt.actionId,
|
|
808
|
+
orderId: result.posted?.orderId,
|
|
809
|
+
fills: result.fills,
|
|
810
|
+
};
|
|
826
811
|
} catch (error) {
|
|
827
812
|
throw new NordError("Failed to place order", { cause: error });
|
|
828
813
|
}
|
|
@@ -848,18 +833,20 @@ export class NordUser {
|
|
|
848
833
|
providedAccountId != null ? providedAccountId : this.accountIds?.[0];
|
|
849
834
|
try {
|
|
850
835
|
this.checkSessionValidity();
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
836
|
+
const receipt = await this.submitSessionAction({
|
|
837
|
+
case: "cancelOrderById",
|
|
838
|
+
value: create(proto.Action_CancelOrderByIdSchema, {
|
|
839
|
+
orderId: BigInt(orderId),
|
|
840
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
841
|
+
senderAccountId: accountId,
|
|
842
|
+
}),
|
|
843
|
+
});
|
|
844
|
+
expectReceiptKind(receipt, "cancelOrderResult", "cancel order");
|
|
845
|
+
return {
|
|
846
|
+
actionId: receipt.actionId,
|
|
847
|
+
orderId: receipt.kind.value.orderId,
|
|
848
|
+
accountId: receipt.kind.value.accountId,
|
|
849
|
+
};
|
|
863
850
|
} catch (error) {
|
|
864
851
|
throw new NordError(`Failed to cancel order ${orderId}`, {
|
|
865
852
|
cause: error,
|
|
@@ -881,23 +868,41 @@ export class NordUser {
|
|
|
881
868
|
if (!market) {
|
|
882
869
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
883
870
|
}
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
871
|
+
const triggerPrice = toScaledU64(
|
|
872
|
+
params.triggerPrice,
|
|
873
|
+
market.priceDecimals,
|
|
874
|
+
);
|
|
875
|
+
assert(triggerPrice > 0n, "Trigger price must be positive");
|
|
876
|
+
const limitPrice =
|
|
877
|
+
params.limitPrice === undefined
|
|
878
|
+
? undefined
|
|
879
|
+
: toScaledU64(params.limitPrice, market.priceDecimals);
|
|
880
|
+
if (limitPrice !== undefined) {
|
|
881
|
+
assert(limitPrice > 0n, "Limit price must be positive");
|
|
882
|
+
}
|
|
883
|
+
const key = create(proto.TriggerKeySchema, {
|
|
884
|
+
kind:
|
|
885
|
+
params.kind === TriggerKind.StopLoss
|
|
886
|
+
? proto.TriggerKind.STOP_LOSS
|
|
887
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
888
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
889
|
+
});
|
|
890
|
+
const prices = create(proto.Action_TriggerPricesSchema, {
|
|
891
|
+
triggerPrice,
|
|
892
|
+
limitPrice,
|
|
893
|
+
});
|
|
894
|
+
const receipt = await this.submitSessionAction({
|
|
895
|
+
case: "addTrigger",
|
|
896
|
+
value: create(proto.Action_AddTriggerSchema, {
|
|
897
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
891
898
|
marketId: params.marketId,
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
priceDecimals: market.priceDecimals,
|
|
895
|
-
triggerPrice: params.triggerPrice,
|
|
896
|
-
limitPrice: params.limitPrice,
|
|
899
|
+
key,
|
|
900
|
+
prices,
|
|
897
901
|
accountId: params.accountId,
|
|
898
|
-
},
|
|
899
|
-
);
|
|
900
|
-
|
|
902
|
+
}),
|
|
903
|
+
});
|
|
904
|
+
expectReceiptKind(receipt, "triggerAdded", "add trigger");
|
|
905
|
+
return { actionId: receipt.actionId };
|
|
901
906
|
} catch (error) {
|
|
902
907
|
throw new NordError("Failed to add trigger", { cause: error });
|
|
903
908
|
}
|
|
@@ -919,80 +924,29 @@ export class NordUser {
|
|
|
919
924
|
if (!market) {
|
|
920
925
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
921
926
|
}
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
927
|
+
const key = create(proto.TriggerKeySchema, {
|
|
928
|
+
kind:
|
|
929
|
+
params.kind === TriggerKind.StopLoss
|
|
930
|
+
? proto.TriggerKind.STOP_LOSS
|
|
931
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
932
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
933
|
+
});
|
|
934
|
+
const receipt = await this.submitSessionAction({
|
|
935
|
+
case: "removeTrigger",
|
|
936
|
+
value: create(proto.Action_RemoveTriggerSchema, {
|
|
937
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
929
938
|
marketId: params.marketId,
|
|
930
|
-
|
|
931
|
-
kind: params.kind,
|
|
939
|
+
key,
|
|
932
940
|
accountId: params.accountId,
|
|
933
|
-
},
|
|
934
|
-
);
|
|
935
|
-
|
|
941
|
+
}),
|
|
942
|
+
});
|
|
943
|
+
expectReceiptKind(receipt, "triggerRemoved", "remove trigger");
|
|
944
|
+
return { actionId: receipt.actionId };
|
|
936
945
|
} catch (error) {
|
|
937
946
|
throw new NordError("Failed to remove trigger", { cause: error });
|
|
938
947
|
}
|
|
939
948
|
}
|
|
940
949
|
|
|
941
|
-
/**
|
|
942
|
-
* Fetch active triggers for an account.
|
|
943
|
-
*
|
|
944
|
-
* @param params Optional parameters containing an explicit account id.
|
|
945
|
-
* @throws {NordError} If no account can be resolved or the request fails.
|
|
946
|
-
*/
|
|
947
|
-
async getAccountTriggers(params?: {
|
|
948
|
-
accountId?: number;
|
|
949
|
-
}): Promise<AccountTriggerInfo[]> {
|
|
950
|
-
const accountId = params?.accountId ?? this.accountIds?.[0];
|
|
951
|
-
|
|
952
|
-
if (accountId == null) {
|
|
953
|
-
throw new NordError(
|
|
954
|
-
"Account ID is undefined. Make sure to call updateAccountId() before requesting triggers.",
|
|
955
|
-
);
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
try {
|
|
959
|
-
return await fetchAccountTriggers(this.nord.webServerUrl, accountId);
|
|
960
|
-
} catch (error) {
|
|
961
|
-
throw new NordError("Failed to fetch account triggers", { cause: error });
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
/**
|
|
966
|
-
* Fetch trigger history for an account.
|
|
967
|
-
*
|
|
968
|
-
* @param params Optional parameters with account id and history query filters.
|
|
969
|
-
* @throws {NordError} If no account can be resolved or the request fails.
|
|
970
|
-
*/
|
|
971
|
-
async getAccountTriggerHistory(
|
|
972
|
-
params: HistoryTriggerQuery & { accountId?: number },
|
|
973
|
-
): Promise<TriggerHistoryPage> {
|
|
974
|
-
const { accountId: providedAccountId, ...query } = params;
|
|
975
|
-
const accountId = providedAccountId ?? this.accountIds?.[0];
|
|
976
|
-
|
|
977
|
-
if (accountId == null) {
|
|
978
|
-
throw new NordError(
|
|
979
|
-
"Account ID is undefined. Make sure to call updateAccountId() before requesting trigger history.",
|
|
980
|
-
);
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
try {
|
|
984
|
-
return await fetchAccountTriggerHistory(
|
|
985
|
-
this.nord.webServerUrl,
|
|
986
|
-
accountId,
|
|
987
|
-
query,
|
|
988
|
-
);
|
|
989
|
-
} catch (error) {
|
|
990
|
-
throw new NordError("Failed to fetch account trigger history", {
|
|
991
|
-
cause: error,
|
|
992
|
-
});
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
|
|
996
950
|
/**
|
|
997
951
|
* Transfer tokens to another account
|
|
998
952
|
*
|
|
@@ -1004,20 +958,22 @@ export class NordUser {
|
|
|
1004
958
|
this.checkSessionValidity();
|
|
1005
959
|
const token = findToken(this.nord.tokens, params.tokenId);
|
|
1006
960
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
961
|
+
const amount = toScaledU64(params.amount, token.decimals);
|
|
962
|
+
if (amount <= 0n) {
|
|
963
|
+
throw new NordError("Transfer amount must be positive");
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
const receipt = await this.submitSessionAction({
|
|
967
|
+
case: "transfer",
|
|
968
|
+
value: create(proto.Action_TransferSchema, {
|
|
969
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
1014
970
|
fromAccountId: optExpect(params.fromAccountId, "No source account"),
|
|
1015
971
|
toAccountId: optExpect(params.toAccountId, "No target account"),
|
|
1016
972
|
tokenId: params.tokenId,
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
);
|
|
973
|
+
amount,
|
|
974
|
+
}),
|
|
975
|
+
});
|
|
976
|
+
expectReceiptKind(receipt, "transferred", "transfer tokens");
|
|
1021
977
|
} catch (error) {
|
|
1022
978
|
throw new NordError("Failed to transfer tokens", { cause: error });
|
|
1023
979
|
}
|
|
@@ -1054,7 +1010,7 @@ export class NordUser {
|
|
|
1054
1010
|
);
|
|
1055
1011
|
}
|
|
1056
1012
|
|
|
1057
|
-
const apiActions:
|
|
1013
|
+
const apiActions: AtomicSubaction[] = userActions.map((act) => {
|
|
1058
1014
|
if (act.kind === "place") {
|
|
1059
1015
|
const market = findMarket(this.nord.markets, act.marketId!);
|
|
1060
1016
|
if (!market) {
|
|
@@ -1072,15 +1028,15 @@ export class NordUser {
|
|
|
1072
1028
|
price: act.price,
|
|
1073
1029
|
quoteSize: act.quoteSize,
|
|
1074
1030
|
clientOrderId: act.clientOrderId,
|
|
1075
|
-
} as
|
|
1031
|
+
} as AtomicSubaction;
|
|
1076
1032
|
}
|
|
1077
1033
|
return {
|
|
1078
1034
|
kind: "cancel",
|
|
1079
1035
|
orderId: act.orderId,
|
|
1080
|
-
} as
|
|
1036
|
+
} as AtomicSubaction;
|
|
1081
1037
|
});
|
|
1082
1038
|
|
|
1083
|
-
const result = await
|
|
1039
|
+
const result = await atomic(
|
|
1084
1040
|
this.nord.webServerUrl,
|
|
1085
1041
|
this.sessionSignFn,
|
|
1086
1042
|
await this.nord.getTimestamp(),
|
|
@@ -1252,13 +1208,4 @@ export class NordUser {
|
|
|
1252
1208
|
});
|
|
1253
1209
|
}
|
|
1254
1210
|
}
|
|
1255
|
-
|
|
1256
|
-
/**
|
|
1257
|
-
* Get the Solana public key derived from the address
|
|
1258
|
-
*
|
|
1259
|
-
* @returns The Solana public key
|
|
1260
|
-
*/
|
|
1261
|
-
getSolanaPublicKey(): PublicKey {
|
|
1262
|
-
return this.address;
|
|
1263
|
-
}
|
|
1264
1211
|
}
|
package/src/nord/index.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
// Export main client classes
|
|
2
2
|
export { Nord } from "./client/Nord";
|
|
3
3
|
export { NordUser } from "./client/NordUser";
|
|
4
|
+
export { NordAdmin } from "./client/NordAdmin";
|
|
5
|
+
export { NordClient } from "./client/NordClient";
|
|
6
|
+
export type { NordClientParams } from "./client/NordClient";
|
|
7
|
+
export type {
|
|
8
|
+
CreateTokenParams,
|
|
9
|
+
CreateMarketParams,
|
|
10
|
+
PythSetWormholeGuardiansParams,
|
|
11
|
+
PythSetSymbolFeedParams,
|
|
12
|
+
FreezeMarketParams,
|
|
13
|
+
UnfreezeMarketParams,
|
|
14
|
+
} from "./client/NordAdmin";
|
|
4
15
|
|
|
5
16
|
// Export utility classes
|
|
6
17
|
export { NordError } from "./utils/NordError";
|
package/src/types.ts
CHANGED
|
@@ -38,8 +38,8 @@ export type SubscriptionPattern = `${SubscriptionType}@${string}` | string;
|
|
|
38
38
|
export interface NordConfig {
|
|
39
39
|
/** Base URL for the Nord web server */
|
|
40
40
|
webServerUrl: string;
|
|
41
|
-
/**
|
|
42
|
-
|
|
41
|
+
/** App address */
|
|
42
|
+
app: string;
|
|
43
43
|
/** Solana cluster URL */
|
|
44
44
|
solanaUrl: string;
|
|
45
45
|
/**
|
|
@@ -49,9 +49,9 @@ export interface NordConfig {
|
|
|
49
49
|
initWebSockets?: boolean;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export type
|
|
53
|
-
export type Market =
|
|
54
|
-
export type Token =
|
|
52
|
+
export type MarketsInfo = components["schemas"]["MarketsInfo"];
|
|
53
|
+
export type Market = MarketsInfo["markets"][number];
|
|
54
|
+
export type Token = MarketsInfo["tokens"][number];
|
|
55
55
|
export type Account = components["schemas"]["Account"];
|
|
56
56
|
export type TradesResponse =
|
|
57
57
|
components["schemas"]["PageResult_for_String_and_Trade"];
|
|
@@ -92,6 +92,16 @@ export type AccountPnlQuery = components["schemas"]["AccountPnlQuery"];
|
|
|
92
92
|
export type AccountPnl = components["schemas"]["AccountPnl"];
|
|
93
93
|
export type AccountPnlPage =
|
|
94
94
|
components["schemas"]["PageResult_for_uint64_and_AccountPnl"];
|
|
95
|
+
export type AccountTriggerInfo = components["schemas"]["AccountTriggerInfo"];
|
|
96
|
+
export type TriggerHistoryPage =
|
|
97
|
+
components["schemas"]["PageResult_for_uint64_and_HistoryTriggerInfo"];
|
|
98
|
+
export type HistoryTriggerQuery = components["schemas"]["AccountTriggersQuery"];
|
|
99
|
+
export type FeeTierConfig = components["schemas"]["FeeTierConfig"];
|
|
100
|
+
export type FeeTierId = components["schemas"]["FeeTierId"];
|
|
101
|
+
export type TokenStats = components["schemas"]["TokenStats"];
|
|
102
|
+
export type AccountFeeTier = components["schemas"]["AccountFeeTier"];
|
|
103
|
+
export type AccountFeeTierPage =
|
|
104
|
+
components["schemas"]["PageResult_for_uint32_and_AccountFeeTier"];
|
|
95
105
|
|
|
96
106
|
/**
|
|
97
107
|
* Configuration options for the Nord client
|
package/src/utils.ts
CHANGED
|
@@ -233,6 +233,11 @@ export function checkPubKeyLength(keyType: KeyType, len: number): void {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
export function decodeHex(value: string): Uint8Array {
|
|
237
|
+
const hex = value.startsWith("0x") ? value.slice(2) : value;
|
|
238
|
+
return Uint8Array.from(Buffer.from(hex, "hex"));
|
|
239
|
+
}
|
|
240
|
+
|
|
236
241
|
export function findMarket(markets: Market[], marketId: number): Market {
|
|
237
242
|
if (marketId < 0 || markets.length - 1 < marketId) {
|
|
238
243
|
throw new Error(`The market with marketId=${marketId} not found`);
|