@n1xyz/nord-ts 0.1.3 → 0.1.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.
- package/README.md +2 -2
- package/dist/gen/nord_pb.d.ts +113 -0
- package/dist/gen/nord_pb.js +21 -6
- package/dist/gen/openapi.d.ts +51 -2
- package/dist/nord/api/actions.d.ts +2 -0
- package/dist/nord/api/actions.js +2 -0
- package/dist/nord/client/Nord.d.ts +23 -8
- package/dist/nord/client/Nord.js +58 -8
- package/dist/nord/client/NordAdmin.d.ts +70 -0
- package/dist/nord/client/NordAdmin.js +187 -0
- package/dist/nord/client/NordClient.d.ts +42 -0
- package/dist/nord/client/NordClient.js +93 -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 +8 -5
- package/package.json +2 -2
- package/src/gen/nord_pb.ts +128 -4
- package/src/gen/openapi.ts +51 -2
- package/src/nord/api/actions.ts +2 -3
- package/src/nord/client/Nord.ts +75 -15
- package/src/nord/client/NordAdmin.ts +232 -0
- package/src/nord/client/NordClient.ts +105 -0
- package/src/nord/client/NordUser.ts +175 -229
- package/src/nord/index.ts +12 -0
- package/src/types.ts +9 -5
- package/src/nord/api/triggers.ts +0 -57
|
@@ -21,39 +21,29 @@ 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
|
-
atomic as atomicAction,
|
|
42
|
-
AtomicSubaction as ApiAtomicSubaction,
|
|
43
|
-
addTrigger as addTriggerAction,
|
|
44
|
-
removeTrigger as removeTriggerAction,
|
|
41
|
+
atomic,
|
|
42
|
+
AtomicSubaction,
|
|
45
43
|
} 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
44
|
import { NordError } from "../utils/NordError";
|
|
56
45
|
import { Nord } from "./Nord";
|
|
46
|
+
import { NordClient } from "./NordClient";
|
|
57
47
|
|
|
58
48
|
/**
|
|
59
49
|
* Parameters for creating a NordUser instance
|
|
@@ -114,6 +104,8 @@ export interface PlaceOrderParams {
|
|
|
114
104
|
|
|
115
105
|
/** Account ID to place the order from */
|
|
116
106
|
accountId?: number;
|
|
107
|
+
|
|
108
|
+
clientOrderId?: BigIntValue;
|
|
117
109
|
}
|
|
118
110
|
|
|
119
111
|
export interface AddTriggerParams {
|
|
@@ -190,26 +182,7 @@ export interface UserAtomicSubaction {
|
|
|
190
182
|
/**
|
|
191
183
|
* User class for interacting with the Nord protocol
|
|
192
184
|
*/
|
|
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
|
-
|
|
185
|
+
export class NordUser extends NordClient {
|
|
213
186
|
/** User balances by token symbol */
|
|
214
187
|
public balances: {
|
|
215
188
|
[key: string]: { accountId: number; balance: number; symbol: string }[];
|
|
@@ -249,24 +222,6 @@ export class NordUser {
|
|
|
249
222
|
/** User's account IDs */
|
|
250
223
|
public accountIds?: number[];
|
|
251
224
|
|
|
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
225
|
/** SPL token information */
|
|
271
226
|
public splTokenInfos: SPLTokenInfo[] = [];
|
|
272
227
|
|
|
@@ -297,28 +252,24 @@ export class NordUser {
|
|
|
297
252
|
throw new NordError("Session public key is required");
|
|
298
253
|
}
|
|
299
254
|
|
|
255
|
+
let parsedAddress: PublicKey;
|
|
300
256
|
try {
|
|
301
|
-
|
|
257
|
+
parsedAddress = new PublicKey(address);
|
|
302
258
|
} catch (error) {
|
|
303
259
|
throw new NordError("Invalid Solana address", { cause: error });
|
|
304
260
|
}
|
|
305
261
|
|
|
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
|
-
}
|
|
262
|
+
super({
|
|
263
|
+
nord,
|
|
264
|
+
address: parsedAddress,
|
|
265
|
+
walletSignFn,
|
|
266
|
+
sessionSignFn,
|
|
267
|
+
transactionSignFn,
|
|
268
|
+
connection,
|
|
269
|
+
sessionId,
|
|
270
|
+
sessionPubKey,
|
|
271
|
+
publicKey,
|
|
272
|
+
});
|
|
322
273
|
|
|
323
274
|
// Convert tokens from info endpoint to SPLTokenInfo
|
|
324
275
|
if (this.nord.tokens && this.nord.tokens.length > 0) {
|
|
@@ -344,8 +295,9 @@ export class NordUser {
|
|
|
344
295
|
sessionSignFn: this.sessionSignFn,
|
|
345
296
|
transactionSignFn: this.transactionSignFn,
|
|
346
297
|
connection: this.connection,
|
|
347
|
-
sessionPubKey: this.sessionPubKey,
|
|
298
|
+
sessionPubKey: new Uint8Array(this.sessionPubKey),
|
|
348
299
|
publicKey: this.publicKey,
|
|
300
|
+
sessionId: this.sessionId,
|
|
349
301
|
});
|
|
350
302
|
|
|
351
303
|
// Copy other properties
|
|
@@ -353,11 +305,8 @@ export class NordUser {
|
|
|
353
305
|
cloned.positions = { ...this.positions };
|
|
354
306
|
cloned.margins = { ...this.margins };
|
|
355
307
|
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
308
|
cloned.splTokenInfos = [...this.splTokenInfos];
|
|
309
|
+
this.cloneClientState(cloned);
|
|
361
310
|
|
|
362
311
|
return cloned;
|
|
363
312
|
}
|
|
@@ -486,7 +435,7 @@ export class NordUser {
|
|
|
486
435
|
}
|
|
487
436
|
|
|
488
437
|
/**
|
|
489
|
-
* Deposit SPL tokens to the
|
|
438
|
+
* Deposit SPL tokens to the app
|
|
490
439
|
*
|
|
491
440
|
* @param amount - Amount to deposit
|
|
492
441
|
* @param tokenId - Token ID
|
|
@@ -504,7 +453,7 @@ export class NordUser {
|
|
|
504
453
|
}
|
|
505
454
|
|
|
506
455
|
/**
|
|
507
|
-
* Deposit SPL tokens to the
|
|
456
|
+
* Deposit SPL tokens to the app
|
|
508
457
|
*
|
|
509
458
|
* @param amount - Amount to deposit
|
|
510
459
|
* @param tokenId - Token ID
|
|
@@ -573,7 +522,19 @@ export class NordUser {
|
|
|
573
522
|
* @returns Nonce as number
|
|
574
523
|
*/
|
|
575
524
|
getNonce(): number {
|
|
576
|
-
return
|
|
525
|
+
return this.nextActionNonce();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
private async submitSessionAction(
|
|
529
|
+
kind: proto.Action["kind"],
|
|
530
|
+
): Promise<proto.Receipt> {
|
|
531
|
+
return this.submitSignedAction(kind, async (message) => {
|
|
532
|
+
const signature = await this.sessionSignFn(message);
|
|
533
|
+
const signed = new Uint8Array(message.length + signature.length);
|
|
534
|
+
signed.set(message);
|
|
535
|
+
signed.set(signature, message.length);
|
|
536
|
+
return signed;
|
|
537
|
+
});
|
|
577
538
|
}
|
|
578
539
|
|
|
579
540
|
/**
|
|
@@ -763,19 +724,21 @@ export class NordUser {
|
|
|
763
724
|
}>): Promise<{ actionId: bigint }> {
|
|
764
725
|
try {
|
|
765
726
|
this.checkSessionValidity();
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
727
|
+
const token = findToken(this.nord.tokens, tokenId);
|
|
728
|
+
const scaledAmount = toScaledU64(amount, token.decimals);
|
|
729
|
+
if (scaledAmount <= 0n) {
|
|
730
|
+
throw new NordError("Withdraw amount must be positive");
|
|
731
|
+
}
|
|
732
|
+
const receipt = await this.submitSessionAction({
|
|
733
|
+
case: "withdraw",
|
|
734
|
+
value: create(proto.Action_WithdrawSchema, {
|
|
735
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
736
|
+
tokenId,
|
|
737
|
+
amount: scaledAmount,
|
|
738
|
+
}),
|
|
739
|
+
});
|
|
740
|
+
this.expectReceiptKind(receipt, "withdrawResult", "withdraw");
|
|
741
|
+
return { actionId: receipt.actionId };
|
|
779
742
|
} catch (error) {
|
|
780
743
|
throw new NordError(
|
|
781
744
|
`Failed to withdraw ${amount} of token ID ${tokenId}`,
|
|
@@ -802,27 +765,48 @@ export class NordUser {
|
|
|
802
765
|
if (!market) {
|
|
803
766
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
804
767
|
}
|
|
768
|
+
const sessionId = optExpect(this.sessionId, "No session");
|
|
769
|
+
const price = toScaledU64(params.price ?? 0, market.priceDecimals);
|
|
770
|
+
const size = toScaledU64(params.size ?? 0, market.sizeDecimals);
|
|
771
|
+
const scaledQuote = params.quoteSize
|
|
772
|
+
? params.quoteSize.toWire(market.priceDecimals, market.sizeDecimals)
|
|
773
|
+
: undefined;
|
|
774
|
+
assert(
|
|
775
|
+
price > 0n || size > 0n || scaledQuote !== undefined,
|
|
776
|
+
"OrderLimit must include at least one of: size, price, or quoteSize",
|
|
777
|
+
);
|
|
805
778
|
|
|
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,
|
|
779
|
+
const receipt = await this.submitSessionAction({
|
|
780
|
+
case: "placeOrder",
|
|
781
|
+
value: create(proto.Action_PlaceOrderSchema, {
|
|
782
|
+
sessionId: BigInt(sessionId),
|
|
783
|
+
senderAccountId: params.accountId,
|
|
816
784
|
marketId: params.marketId,
|
|
817
|
-
side: params.side,
|
|
818
|
-
fillMode: params.fillMode,
|
|
785
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
786
|
+
fillMode: fillModeToProtoFillMode(params.fillMode),
|
|
819
787
|
isReduceOnly: params.isReduceOnly,
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
quoteSize:
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
788
|
+
price,
|
|
789
|
+
size,
|
|
790
|
+
quoteSize:
|
|
791
|
+
scaledQuote === undefined
|
|
792
|
+
? undefined
|
|
793
|
+
: create(proto.QuoteSizeSchema, {
|
|
794
|
+
size: scaledQuote.size,
|
|
795
|
+
price: scaledQuote.price,
|
|
796
|
+
}),
|
|
797
|
+
clientOrderId:
|
|
798
|
+
params.clientOrderId === undefined
|
|
799
|
+
? undefined
|
|
800
|
+
: BigInt(params.clientOrderId),
|
|
801
|
+
}),
|
|
802
|
+
});
|
|
803
|
+
this.expectReceiptKind(receipt, "placeOrderResult", "place order");
|
|
804
|
+
const result = receipt.kind.value;
|
|
805
|
+
return {
|
|
806
|
+
actionId: receipt.actionId,
|
|
807
|
+
orderId: result.posted?.orderId,
|
|
808
|
+
fills: result.fills,
|
|
809
|
+
};
|
|
826
810
|
} catch (error) {
|
|
827
811
|
throw new NordError("Failed to place order", { cause: error });
|
|
828
812
|
}
|
|
@@ -848,18 +832,20 @@ export class NordUser {
|
|
|
848
832
|
providedAccountId != null ? providedAccountId : this.accountIds?.[0];
|
|
849
833
|
try {
|
|
850
834
|
this.checkSessionValidity();
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
835
|
+
const receipt = await this.submitSessionAction({
|
|
836
|
+
case: "cancelOrderById",
|
|
837
|
+
value: create(proto.Action_CancelOrderByIdSchema, {
|
|
838
|
+
orderId: BigInt(orderId),
|
|
839
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
840
|
+
senderAccountId: accountId,
|
|
841
|
+
}),
|
|
842
|
+
});
|
|
843
|
+
this.expectReceiptKind(receipt, "cancelOrderResult", "cancel order");
|
|
844
|
+
return {
|
|
845
|
+
actionId: receipt.actionId,
|
|
846
|
+
orderId: receipt.kind.value.orderId,
|
|
847
|
+
accountId: receipt.kind.value.accountId,
|
|
848
|
+
};
|
|
863
849
|
} catch (error) {
|
|
864
850
|
throw new NordError(`Failed to cancel order ${orderId}`, {
|
|
865
851
|
cause: error,
|
|
@@ -881,23 +867,41 @@ export class NordUser {
|
|
|
881
867
|
if (!market) {
|
|
882
868
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
883
869
|
}
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
870
|
+
const triggerPrice = toScaledU64(
|
|
871
|
+
params.triggerPrice,
|
|
872
|
+
market.priceDecimals,
|
|
873
|
+
);
|
|
874
|
+
assert(triggerPrice > 0n, "Trigger price must be positive");
|
|
875
|
+
const limitPrice =
|
|
876
|
+
params.limitPrice === undefined
|
|
877
|
+
? undefined
|
|
878
|
+
: toScaledU64(params.limitPrice, market.priceDecimals);
|
|
879
|
+
if (limitPrice !== undefined) {
|
|
880
|
+
assert(limitPrice > 0n, "Limit price must be positive");
|
|
881
|
+
}
|
|
882
|
+
const key = create(proto.TriggerKeySchema, {
|
|
883
|
+
kind:
|
|
884
|
+
params.kind === TriggerKind.StopLoss
|
|
885
|
+
? proto.TriggerKind.STOP_LOSS
|
|
886
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
887
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
888
|
+
});
|
|
889
|
+
const prices = create(proto.Action_TriggerPricesSchema, {
|
|
890
|
+
triggerPrice,
|
|
891
|
+
limitPrice,
|
|
892
|
+
});
|
|
893
|
+
const receipt = await this.submitSessionAction({
|
|
894
|
+
case: "addTrigger",
|
|
895
|
+
value: create(proto.Action_AddTriggerSchema, {
|
|
896
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
891
897
|
marketId: params.marketId,
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
priceDecimals: market.priceDecimals,
|
|
895
|
-
triggerPrice: params.triggerPrice,
|
|
896
|
-
limitPrice: params.limitPrice,
|
|
898
|
+
key,
|
|
899
|
+
prices,
|
|
897
900
|
accountId: params.accountId,
|
|
898
|
-
},
|
|
899
|
-
);
|
|
900
|
-
|
|
901
|
+
}),
|
|
902
|
+
});
|
|
903
|
+
this.expectReceiptKind(receipt, "triggerAdded", "add trigger");
|
|
904
|
+
return { actionId: receipt.actionId };
|
|
901
905
|
} catch (error) {
|
|
902
906
|
throw new NordError("Failed to add trigger", { cause: error });
|
|
903
907
|
}
|
|
@@ -919,80 +923,29 @@ export class NordUser {
|
|
|
919
923
|
if (!market) {
|
|
920
924
|
throw new NordError(`Market with ID ${params.marketId} not found`);
|
|
921
925
|
}
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
926
|
+
const key = create(proto.TriggerKeySchema, {
|
|
927
|
+
kind:
|
|
928
|
+
params.kind === TriggerKind.StopLoss
|
|
929
|
+
? proto.TriggerKind.STOP_LOSS
|
|
930
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
931
|
+
side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
932
|
+
});
|
|
933
|
+
const receipt = await this.submitSessionAction({
|
|
934
|
+
case: "removeTrigger",
|
|
935
|
+
value: create(proto.Action_RemoveTriggerSchema, {
|
|
936
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
929
937
|
marketId: params.marketId,
|
|
930
|
-
|
|
931
|
-
kind: params.kind,
|
|
938
|
+
key,
|
|
932
939
|
accountId: params.accountId,
|
|
933
|
-
},
|
|
934
|
-
);
|
|
935
|
-
|
|
940
|
+
}),
|
|
941
|
+
});
|
|
942
|
+
this.expectReceiptKind(receipt, "triggerRemoved", "remove trigger");
|
|
943
|
+
return { actionId: receipt.actionId };
|
|
936
944
|
} catch (error) {
|
|
937
945
|
throw new NordError("Failed to remove trigger", { cause: error });
|
|
938
946
|
}
|
|
939
947
|
}
|
|
940
948
|
|
|
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
949
|
/**
|
|
997
950
|
* Transfer tokens to another account
|
|
998
951
|
*
|
|
@@ -1004,20 +957,22 @@ export class NordUser {
|
|
|
1004
957
|
this.checkSessionValidity();
|
|
1005
958
|
const token = findToken(this.nord.tokens, params.tokenId);
|
|
1006
959
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
960
|
+
const amount = toScaledU64(params.amount, token.decimals);
|
|
961
|
+
if (amount <= 0n) {
|
|
962
|
+
throw new NordError("Transfer amount must be positive");
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const receipt = await this.submitSessionAction({
|
|
966
|
+
case: "transfer",
|
|
967
|
+
value: create(proto.Action_TransferSchema, {
|
|
968
|
+
sessionId: BigInt(optExpect(this.sessionId, "No session")),
|
|
1014
969
|
fromAccountId: optExpect(params.fromAccountId, "No source account"),
|
|
1015
970
|
toAccountId: optExpect(params.toAccountId, "No target account"),
|
|
1016
971
|
tokenId: params.tokenId,
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
);
|
|
972
|
+
amount,
|
|
973
|
+
}),
|
|
974
|
+
});
|
|
975
|
+
this.expectReceiptKind(receipt, "transferred", "transfer tokens");
|
|
1021
976
|
} catch (error) {
|
|
1022
977
|
throw new NordError("Failed to transfer tokens", { cause: error });
|
|
1023
978
|
}
|
|
@@ -1054,7 +1009,7 @@ export class NordUser {
|
|
|
1054
1009
|
);
|
|
1055
1010
|
}
|
|
1056
1011
|
|
|
1057
|
-
const apiActions:
|
|
1012
|
+
const apiActions: AtomicSubaction[] = userActions.map((act) => {
|
|
1058
1013
|
if (act.kind === "place") {
|
|
1059
1014
|
const market = findMarket(this.nord.markets, act.marketId!);
|
|
1060
1015
|
if (!market) {
|
|
@@ -1072,15 +1027,15 @@ export class NordUser {
|
|
|
1072
1027
|
price: act.price,
|
|
1073
1028
|
quoteSize: act.quoteSize,
|
|
1074
1029
|
clientOrderId: act.clientOrderId,
|
|
1075
|
-
} as
|
|
1030
|
+
} as AtomicSubaction;
|
|
1076
1031
|
}
|
|
1077
1032
|
return {
|
|
1078
1033
|
kind: "cancel",
|
|
1079
1034
|
orderId: act.orderId,
|
|
1080
|
-
} as
|
|
1035
|
+
} as AtomicSubaction;
|
|
1081
1036
|
});
|
|
1082
1037
|
|
|
1083
|
-
const result = await
|
|
1038
|
+
const result = await atomic(
|
|
1084
1039
|
this.nord.webServerUrl,
|
|
1085
1040
|
this.sessionSignFn,
|
|
1086
1041
|
await this.nord.getTimestamp(),
|
|
@@ -1252,13 +1207,4 @@ export class NordUser {
|
|
|
1252
1207
|
});
|
|
1253
1208
|
}
|
|
1254
1209
|
}
|
|
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
1210
|
}
|
package/src/nord/index.ts
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
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
|
+
NordAdminParams,
|
|
15
|
+
} from "./client/NordAdmin";
|
|
4
16
|
|
|
5
17
|
// Export utility classes
|
|
6
18
|
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,10 @@ 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"];
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
101
|
* Configuration options for the Nord client
|
package/src/nord/api/triggers.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import createClient from "openapi-fetch";
|
|
2
|
-
|
|
3
|
-
import { paths, components } from "../../gen/openapi";
|
|
4
|
-
|
|
5
|
-
type AccountTriggerInfo = components["schemas"]["AccountTriggerInfo"];
|
|
6
|
-
type TriggerHistoryPage =
|
|
7
|
-
components["schemas"]["PageResult_for_uint64_and_HistoryTriggerInfo"];
|
|
8
|
-
type HistoryTriggerQuery = components["schemas"]["AccountTriggersQuery"];
|
|
9
|
-
|
|
10
|
-
export type { AccountTriggerInfo, TriggerHistoryPage, HistoryTriggerQuery };
|
|
11
|
-
|
|
12
|
-
export async function getAccountTriggers(
|
|
13
|
-
serverUrl: string,
|
|
14
|
-
accountId: number,
|
|
15
|
-
): Promise<AccountTriggerInfo[]> {
|
|
16
|
-
const client = createClient<paths>({ baseUrl: serverUrl });
|
|
17
|
-
const response = await client.GET("/account/{account_id}/triggers", {
|
|
18
|
-
params: {
|
|
19
|
-
path: { account_id: accountId },
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
if (response.data === undefined) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`Failed to fetch triggers for account ${accountId}: HTTP ${response.response.status}`,
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return response.data ?? [];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function getAccountTriggerHistory(
|
|
33
|
-
serverUrl: string,
|
|
34
|
-
accountId: number,
|
|
35
|
-
options: HistoryTriggerQuery,
|
|
36
|
-
): Promise<TriggerHistoryPage> {
|
|
37
|
-
const client = createClient<paths>({ baseUrl: serverUrl });
|
|
38
|
-
const response = await client.GET("/account/{account_id}/triggers/history", {
|
|
39
|
-
params: {
|
|
40
|
-
path: { account_id: accountId },
|
|
41
|
-
query: {
|
|
42
|
-
since: options.since,
|
|
43
|
-
until: options.until,
|
|
44
|
-
pageSize: options.pageSize,
|
|
45
|
-
startInclusive: options.startInclusive,
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
if (!response.data) {
|
|
51
|
-
throw new Error(
|
|
52
|
-
`Failed to fetch trigger history for account ${accountId}: HTTP ${response.response.status}`,
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return response.data;
|
|
57
|
-
}
|