@n1xyz/nord-ts 0.1.0 → 0.1.2
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/gen/nord_pb.d.ts +196 -105
- package/dist/gen/nord_pb.js +117 -89
- package/dist/gen/openapi.d.ts +149 -7
- package/dist/nord/api/actions.d.ts +22 -1
- package/dist/nord/api/actions.js +85 -17
- package/dist/nord/api/triggers.d.ts +7 -0
- package/dist/nord/api/triggers.js +38 -0
- package/dist/nord/client/Nord.d.ts +10 -1
- package/dist/nord/client/Nord.js +21 -0
- package/dist/nord/client/NordUser.d.ts +54 -1
- package/dist/nord/client/NordUser.js +97 -0
- package/dist/types.d.ts +16 -3
- package/dist/types.js +30 -4
- package/dist/utils.js +1 -0
- package/package.json +2 -2
- package/src/gen/nord_pb.ts +268 -173
- package/src/gen/openapi.ts +149 -7
- package/src/nord/api/actions.ts +121 -19
- package/src/nord/api/triggers.ts +57 -0
- package/src/nord/client/Nord.ts +27 -0
- package/src/nord/client/NordUser.ts +160 -1
- package/src/types.ts +34 -3
- package/src/utils.ts +1 -0
- package/src/gen/nord.ts +0 -7593
package/dist/gen/openapi.d.ts
CHANGED
|
@@ -83,8 +83,12 @@ export interface paths {
|
|
|
83
83
|
get: {
|
|
84
84
|
parameters: {
|
|
85
85
|
query: {
|
|
86
|
+
/** @description Start action ID (exclusive) */
|
|
86
87
|
from: number;
|
|
88
|
+
/** @description End action ID (inclusive) */
|
|
87
89
|
to: number;
|
|
90
|
+
/** @description Optionally provided binary version of client, so nord server can ensure all actions provided are executable by client. */
|
|
91
|
+
clientVersion?: components["schemas"]["ExecutableVersion"] | null;
|
|
88
92
|
};
|
|
89
93
|
header?: never;
|
|
90
94
|
path?: never;
|
|
@@ -108,6 +112,14 @@ export interface paths {
|
|
|
108
112
|
"application/json": components["schemas"]["RangeTooLarge"];
|
|
109
113
|
};
|
|
110
114
|
};
|
|
115
|
+
501: {
|
|
116
|
+
headers: {
|
|
117
|
+
[name: string]: unknown;
|
|
118
|
+
};
|
|
119
|
+
content: {
|
|
120
|
+
"application/json": components["schemas"]["NotImplemented"];
|
|
121
|
+
};
|
|
122
|
+
};
|
|
111
123
|
};
|
|
112
124
|
};
|
|
113
125
|
put?: never;
|
|
@@ -136,6 +148,14 @@ export interface paths {
|
|
|
136
148
|
"application/octet-stream": unknown;
|
|
137
149
|
};
|
|
138
150
|
};
|
|
151
|
+
413: {
|
|
152
|
+
headers: {
|
|
153
|
+
[name: string]: unknown;
|
|
154
|
+
};
|
|
155
|
+
content: {
|
|
156
|
+
"application/json": components["schemas"]["PayloadTooLarge"];
|
|
157
|
+
};
|
|
158
|
+
};
|
|
139
159
|
415: {
|
|
140
160
|
headers: {
|
|
141
161
|
/**
|
|
@@ -778,7 +798,7 @@ export interface paths {
|
|
|
778
798
|
[name: string]: unknown;
|
|
779
799
|
};
|
|
780
800
|
content: {
|
|
781
|
-
"application/json": components["schemas"]["
|
|
801
|
+
"application/json": components["schemas"]["AccountTriggerInfo"][] | null;
|
|
782
802
|
};
|
|
783
803
|
};
|
|
784
804
|
};
|
|
@@ -975,6 +995,79 @@ export interface paths {
|
|
|
975
995
|
patch?: never;
|
|
976
996
|
trace?: never;
|
|
977
997
|
};
|
|
998
|
+
"/state/download": {
|
|
999
|
+
parameters: {
|
|
1000
|
+
query?: never;
|
|
1001
|
+
header?: never;
|
|
1002
|
+
path?: never;
|
|
1003
|
+
cookie?: never;
|
|
1004
|
+
};
|
|
1005
|
+
/** @description Returns state download link and metadata, as defined by nearest(up to equality) snapshot `time` or `action_id`` or `timestamp`. If not specified, returns latest snapshot. Example: /state/download?actionId=1 /state/download?time&2025-09-22T12:34:56Z /state/download?timestamp&1695380000 - Does not implemented yet. To get the latest snap use: /state/download - w/o any params.
|
|
1006
|
+
*
|
|
1007
|
+
* The link from responce can be inserted to search bar in browser to download. */
|
|
1008
|
+
get: {
|
|
1009
|
+
parameters: {
|
|
1010
|
+
query?: never;
|
|
1011
|
+
header?: never;
|
|
1012
|
+
path?: never;
|
|
1013
|
+
cookie?: never;
|
|
1014
|
+
};
|
|
1015
|
+
requestBody?: never;
|
|
1016
|
+
responses: {
|
|
1017
|
+
200: {
|
|
1018
|
+
headers: {
|
|
1019
|
+
[name: string]: unknown;
|
|
1020
|
+
};
|
|
1021
|
+
content: {
|
|
1022
|
+
"application/json": components["schemas"]["StateDownloadMeta"];
|
|
1023
|
+
};
|
|
1024
|
+
};
|
|
1025
|
+
501: {
|
|
1026
|
+
headers: {
|
|
1027
|
+
[name: string]: unknown;
|
|
1028
|
+
};
|
|
1029
|
+
content: {
|
|
1030
|
+
"application/json": components["schemas"]["NotImplemented"];
|
|
1031
|
+
};
|
|
1032
|
+
};
|
|
1033
|
+
};
|
|
1034
|
+
};
|
|
1035
|
+
put?: never;
|
|
1036
|
+
post?: never;
|
|
1037
|
+
delete?: never;
|
|
1038
|
+
options?: never;
|
|
1039
|
+
head?: never;
|
|
1040
|
+
patch?: never;
|
|
1041
|
+
trace?: never;
|
|
1042
|
+
};
|
|
1043
|
+
"/state/download/{snapshot_id}": {
|
|
1044
|
+
parameters: {
|
|
1045
|
+
query?: never;
|
|
1046
|
+
header?: never;
|
|
1047
|
+
path?: never;
|
|
1048
|
+
cookie?: never;
|
|
1049
|
+
};
|
|
1050
|
+
/** @description Typical HTTP file download endpoint. Actually same as provided by S3 storages. Means supports Range header, Content-Length, Content-Type, ETag and so on, and relevant headers. */
|
|
1051
|
+
get: {
|
|
1052
|
+
parameters: {
|
|
1053
|
+
query?: never;
|
|
1054
|
+
header?: never;
|
|
1055
|
+
path: {
|
|
1056
|
+
snapshot_id: string;
|
|
1057
|
+
};
|
|
1058
|
+
cookie?: never;
|
|
1059
|
+
};
|
|
1060
|
+
requestBody?: never;
|
|
1061
|
+
responses: never;
|
|
1062
|
+
};
|
|
1063
|
+
put?: never;
|
|
1064
|
+
post?: never;
|
|
1065
|
+
delete?: never;
|
|
1066
|
+
options?: never;
|
|
1067
|
+
head?: never;
|
|
1068
|
+
patch?: never;
|
|
1069
|
+
trace?: never;
|
|
1070
|
+
};
|
|
978
1071
|
"/tv": {
|
|
979
1072
|
parameters: {
|
|
980
1073
|
query?: never;
|
|
@@ -1910,12 +2003,25 @@ export interface components {
|
|
|
1910
2003
|
AcceptedMediaType: {
|
|
1911
2004
|
expected: string;
|
|
1912
2005
|
};
|
|
2006
|
+
PayloadTooLarge: {
|
|
2007
|
+
/** Format: uint */
|
|
2008
|
+
limit: number;
|
|
2009
|
+
};
|
|
1913
2010
|
ActionsQuery: {
|
|
1914
|
-
/**
|
|
2011
|
+
/**
|
|
2012
|
+
* Format: uint64
|
|
2013
|
+
* @description Start action ID (exclusive)
|
|
2014
|
+
*/
|
|
1915
2015
|
from: number;
|
|
1916
|
-
/**
|
|
2016
|
+
/**
|
|
2017
|
+
* Format: uint64
|
|
2018
|
+
* @description End action ID (inclusive)
|
|
2019
|
+
*/
|
|
1917
2020
|
to: number;
|
|
2021
|
+
/** @description Optionally provided binary version of client, so nord server can ensure all actions provided are executable by client. */
|
|
2022
|
+
clientVersion?: components["schemas"]["ExecutableVersion"] | null;
|
|
1918
2023
|
};
|
|
2024
|
+
ExecutableVersion: string;
|
|
1919
2025
|
ActionsItem: {
|
|
1920
2026
|
/** Format: uint64 */
|
|
1921
2027
|
actionId: number;
|
|
@@ -1928,6 +2034,10 @@ export interface components {
|
|
|
1928
2034
|
/** Format: uint16 */
|
|
1929
2035
|
maximal: number;
|
|
1930
2036
|
};
|
|
2037
|
+
NotImplemented: {
|
|
2038
|
+
/** @description Human readable message describing what to expect next. */
|
|
2039
|
+
message: string;
|
|
2040
|
+
};
|
|
1931
2041
|
ActionNotFound: null;
|
|
1932
2042
|
/** @description Returns fee parts per market per balance change per action per account. Fee is taken from user without return. Please note that some operations need some deposit which will be returned - these are not part of fees. */
|
|
1933
2043
|
FillRole: "maker" | "taker";
|
|
@@ -2258,14 +2368,23 @@ export interface components {
|
|
|
2258
2368
|
/** @enum {string} */
|
|
2259
2369
|
TriggerKind: "stopLoss" | "takeProfit";
|
|
2260
2370
|
/** @enum {string} */
|
|
2261
|
-
TriggerStatus: "
|
|
2262
|
-
|
|
2371
|
+
TriggerStatus: "Active" | "Success" | "Removed" | "Canceled";
|
|
2372
|
+
/** @description Trigger into per account. */
|
|
2373
|
+
AccountTriggerInfo: {
|
|
2263
2374
|
/** Format: uint32 */
|
|
2264
2375
|
marketId: number;
|
|
2376
|
+
key: components["schemas"]["TriggerKey"];
|
|
2377
|
+
triggerPrices: components["schemas"]["TriggerPrice"];
|
|
2378
|
+
/** Format: uint64 */
|
|
2379
|
+
actionId: number;
|
|
2380
|
+
};
|
|
2381
|
+
TriggerKey: {
|
|
2265
2382
|
side: components["schemas"]["Side"];
|
|
2266
2383
|
kind: components["schemas"]["TriggerKind"];
|
|
2267
|
-
|
|
2268
|
-
|
|
2384
|
+
};
|
|
2385
|
+
TriggerPrice: {
|
|
2386
|
+
trigger: components["schemas"]["PositivePriceMantissa"];
|
|
2387
|
+
settlement?: components["schemas"]["PositivePriceMantissa"] | null;
|
|
2269
2388
|
};
|
|
2270
2389
|
/**
|
|
2271
2390
|
* Format: uint64
|
|
@@ -2333,6 +2452,29 @@ export interface components {
|
|
|
2333
2452
|
*/
|
|
2334
2453
|
pageSize: number | null;
|
|
2335
2454
|
};
|
|
2455
|
+
DownloadFilter: components["schemas"]["Op_for_DataDateTime"] | components["schemas"]["Op_for_uint64"] | components["schemas"]["Op_for_uint64"] | null;
|
|
2456
|
+
/** @description Parses tag (anycase), and value in round braces using `from_str`. */
|
|
2457
|
+
Op_for_DataDateTime: {
|
|
2458
|
+
le: components["schemas"]["DataDateTime"];
|
|
2459
|
+
};
|
|
2460
|
+
DataDateTime: string;
|
|
2461
|
+
/** @description Parses tag (anycase), and value in round braces using `from_str`. */
|
|
2462
|
+
Op_for_uint64: {
|
|
2463
|
+
/** Format: uint64 */
|
|
2464
|
+
le: number;
|
|
2465
|
+
};
|
|
2466
|
+
StateDownloadMeta: {
|
|
2467
|
+
/** @description Hash of the state file. Used as ETag. */
|
|
2468
|
+
hash: number[];
|
|
2469
|
+
/**
|
|
2470
|
+
* Format: uri
|
|
2471
|
+
* @description Link to download the state file.
|
|
2472
|
+
*/
|
|
2473
|
+
link: string;
|
|
2474
|
+
/** @description Version of binary which produced this state snapshot. So can decide whether it is compatible with client. todo(repl): After upgrade release make it non-optional. */
|
|
2475
|
+
version?: components["schemas"]["BinaryId"] | null;
|
|
2476
|
+
};
|
|
2477
|
+
BinaryId: string;
|
|
2336
2478
|
/** @description TV config query response https://www.tradingview.com/charting-library-docs/latest/connecting_data/UDF/#data-feed-configuration-data */
|
|
2337
2479
|
TvConfigResponse: {
|
|
2338
2480
|
supported_resolutions: components["schemas"]["Resolution"][];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Decimal from "decimal.js";
|
|
2
2
|
import * as proto from "../../gen/nord_pb";
|
|
3
|
-
import { FillMode, Side, QuoteSize } from "../../types";
|
|
3
|
+
import { FillMode, Side, QuoteSize, TriggerKind } from "../../types";
|
|
4
4
|
import { BigIntValue } from "../../utils";
|
|
5
5
|
export declare function prepareAction(action: proto.Action, makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>): Promise<Uint8Array<ArrayBufferLike>>;
|
|
6
6
|
export declare function createSession(serverUrl: string, walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
@@ -68,6 +68,27 @@ export declare function transfer(serverUrl: string, signFn: (message: Uint8Array
|
|
|
68
68
|
amount: bigint;
|
|
69
69
|
accountCreated: boolean;
|
|
70
70
|
}>;
|
|
71
|
+
export declare function addTrigger(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
72
|
+
sessionId: BigIntValue;
|
|
73
|
+
marketId: number;
|
|
74
|
+
side: Side;
|
|
75
|
+
kind: TriggerKind;
|
|
76
|
+
priceDecimals: number;
|
|
77
|
+
triggerPrice: Decimal.Value;
|
|
78
|
+
limitPrice?: Decimal.Value;
|
|
79
|
+
accountId?: number;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
actionId: bigint;
|
|
82
|
+
}>;
|
|
83
|
+
export declare function removeTrigger(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
84
|
+
sessionId: BigIntValue;
|
|
85
|
+
marketId: number;
|
|
86
|
+
side: Side;
|
|
87
|
+
kind: TriggerKind;
|
|
88
|
+
accountId?: number;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
actionId: bigint;
|
|
91
|
+
}>;
|
|
71
92
|
export type AtomicSubaction = {
|
|
72
93
|
kind: "place";
|
|
73
94
|
marketId: number;
|
package/dist/nord/api/actions.js
CHANGED
|
@@ -43,6 +43,8 @@ exports.withdraw = withdraw;
|
|
|
43
43
|
exports.placeOrder = placeOrder;
|
|
44
44
|
exports.cancelOrder = cancelOrder;
|
|
45
45
|
exports.transfer = transfer;
|
|
46
|
+
exports.addTrigger = addTrigger;
|
|
47
|
+
exports.removeTrigger = removeTrigger;
|
|
46
48
|
exports.atomic = atomic;
|
|
47
49
|
const proto = __importStar(require("../../gen/nord_pb"));
|
|
48
50
|
const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
|
|
@@ -66,7 +68,7 @@ function createAction(currentTimestamp, nonce, kind) {
|
|
|
66
68
|
kind,
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
|
-
async function sendAction(serverUrl, makeSignedMessage, action
|
|
71
|
+
async function sendAction(serverUrl, makeSignedMessage, action) {
|
|
70
72
|
const body = await prepareAction(action, makeSignedMessage);
|
|
71
73
|
// NOTE: restructure and reuse client as it is in Nord.ts
|
|
72
74
|
const client = (0, openapi_fetch_1.default)({ baseUrl: serverUrl });
|
|
@@ -77,14 +79,18 @@ async function sendAction(serverUrl, makeSignedMessage, action, actionErrorDesc)
|
|
|
77
79
|
},
|
|
78
80
|
},
|
|
79
81
|
body: body,
|
|
82
|
+
// NOTE: openapi-fetch ignores headers and types/const headers in schema, and always assume all things are JSON
|
|
83
|
+
// to handle multi type bodies, need these overrides and later adhoc parsing
|
|
84
|
+
bodySerializer: (body) => body,
|
|
85
|
+
parseAs: "stream",
|
|
80
86
|
});
|
|
81
87
|
if (response.error) {
|
|
82
|
-
throw new Error(`Failed to ${
|
|
88
|
+
throw new Error(`Failed to ${action.kind.case}, HTTP status ${JSON.stringify(response.error)}`);
|
|
83
89
|
}
|
|
84
|
-
const rawResp = new Uint8Array(await response.response.
|
|
90
|
+
const rawResp = new Uint8Array(await response.response.bytes());
|
|
85
91
|
const resp = (0, utils_1.decodeLengthDelimited)(rawResp, proto.ReceiptSchema);
|
|
86
92
|
if (resp.kind?.case === "err") {
|
|
87
|
-
throw new Error(`Could not ${
|
|
93
|
+
throw new Error(`Could not execute ${action.kind.case}, reason: ${proto.Error[resp.kind.value]}`);
|
|
88
94
|
}
|
|
89
95
|
return resp;
|
|
90
96
|
}
|
|
@@ -92,12 +98,17 @@ async function sendAction(serverUrl, makeSignedMessage, action, actionErrorDesc)
|
|
|
92
98
|
// `makeSignedMessage` must include the original message and signature.
|
|
93
99
|
async function prepareAction(action, makeSignedMessage) {
|
|
94
100
|
const encoded = (0, wire_1.sizeDelimitedEncode)(proto.ActionSchema, action);
|
|
95
|
-
// NOTE(agent): keep in sync with
|
|
96
|
-
const
|
|
97
|
-
if (encoded.byteLength >
|
|
98
|
-
|
|
101
|
+
// NOTE(agent): keep in sync with MAX_ENCODED_ACTION_SIZE in Rust code
|
|
102
|
+
const MAX_ENCODED_ACTION_SIZE = 1024;
|
|
103
|
+
if (encoded.byteLength > MAX_ENCODED_ACTION_SIZE) {
|
|
104
|
+
console.warn("Encoded message:", encoded);
|
|
105
|
+
throw new Error(`Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`);
|
|
99
106
|
}
|
|
100
107
|
const body = await makeSignedMessage(encoded);
|
|
108
|
+
if (body.byteLength > MAX_ENCODED_ACTION_SIZE) {
|
|
109
|
+
console.warn("Encoded length:", encoded.byteLength);
|
|
110
|
+
throw new Error(`Signed message size (${body.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`);
|
|
111
|
+
}
|
|
101
112
|
return body;
|
|
102
113
|
}
|
|
103
114
|
async function createSession(serverUrl, walletSignFn, currentTimestamp, nonce, params) {
|
|
@@ -119,7 +130,7 @@ async function createSession(serverUrl, walletSignFn, currentTimestamp, nonce, p
|
|
|
119
130
|
expiryTimestamp: expiry,
|
|
120
131
|
}),
|
|
121
132
|
});
|
|
122
|
-
const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action
|
|
133
|
+
const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action);
|
|
123
134
|
if (resp.kind?.case === "createSessionResult") {
|
|
124
135
|
return {
|
|
125
136
|
actionId: resp.actionId,
|
|
@@ -137,7 +148,7 @@ async function revokeSession(serverUrl, walletSignFn, currentTimestamp, nonce, p
|
|
|
137
148
|
sessionId: BigInt(params.sessionId),
|
|
138
149
|
}),
|
|
139
150
|
});
|
|
140
|
-
const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action
|
|
151
|
+
const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action);
|
|
141
152
|
return { actionId: resp.actionId };
|
|
142
153
|
}
|
|
143
154
|
async function withdraw(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
@@ -153,7 +164,7 @@ async function withdraw(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
153
164
|
amount,
|
|
154
165
|
}),
|
|
155
166
|
});
|
|
156
|
-
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action
|
|
167
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
157
168
|
if (resp.kind?.case === "withdrawResult") {
|
|
158
169
|
return { actionId: resp.actionId, ...resp.kind.value };
|
|
159
170
|
}
|
|
@@ -165,7 +176,7 @@ async function placeOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
165
176
|
const price = (0, utils_1.toScaledU64)(params.price ?? 0, params.priceDecimals);
|
|
166
177
|
const size = (0, utils_1.toScaledU64)(params.size ?? 0, params.sizeDecimals);
|
|
167
178
|
const scaledQuote = params.quoteSize
|
|
168
|
-
? params.quoteSize.
|
|
179
|
+
? params.quoteSize.toWire(params.priceDecimals, params.sizeDecimals)
|
|
169
180
|
: undefined;
|
|
170
181
|
(0, utils_1.assert)(price > 0n || size > 0n || scaledQuote !== undefined, "OrderLimit must include at least one of: size, price, or quoteSize");
|
|
171
182
|
const action = createAction(currentTimestamp, nonce, {
|
|
@@ -191,7 +202,7 @@ async function placeOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
191
202
|
delegatorAccountId: params.liquidateeId,
|
|
192
203
|
}),
|
|
193
204
|
});
|
|
194
|
-
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action
|
|
205
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
195
206
|
if (resp.kind?.case === "placeOrderResult") {
|
|
196
207
|
return {
|
|
197
208
|
actionId: resp.actionId,
|
|
@@ -213,7 +224,7 @@ async function cancelOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
213
224
|
delegatorAccountId: params.liquidateeId,
|
|
214
225
|
}),
|
|
215
226
|
});
|
|
216
|
-
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action
|
|
227
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
217
228
|
if (resp.kind?.case === "cancelOrderResult") {
|
|
218
229
|
return {
|
|
219
230
|
actionId: resp.actionId,
|
|
@@ -236,7 +247,7 @@ async function transfer(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
236
247
|
amount: (0, utils_1.toScaledU64)(params.amount ?? 0, params.tokenDecimals),
|
|
237
248
|
}),
|
|
238
249
|
});
|
|
239
|
-
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action
|
|
250
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
240
251
|
if (resp.kind?.case === "transferred") {
|
|
241
252
|
return {
|
|
242
253
|
actionId: resp.actionId,
|
|
@@ -251,6 +262,63 @@ async function transfer(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
251
262
|
throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
|
|
252
263
|
}
|
|
253
264
|
}
|
|
265
|
+
async function addTrigger(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
266
|
+
const triggerPrice = (0, utils_1.toScaledU64)(params.triggerPrice, params.priceDecimals);
|
|
267
|
+
(0, utils_1.assert)(triggerPrice > 0n, "Trigger price must be positive");
|
|
268
|
+
const limitPrice = params.limitPrice === undefined
|
|
269
|
+
? undefined
|
|
270
|
+
: (0, utils_1.toScaledU64)(params.limitPrice, params.priceDecimals);
|
|
271
|
+
if (limitPrice !== undefined) {
|
|
272
|
+
(0, utils_1.assert)(limitPrice > 0n, "Limit price must be positive");
|
|
273
|
+
}
|
|
274
|
+
const key = (0, protobuf_1.create)(proto.TriggerKeySchema, {
|
|
275
|
+
kind: params.kind === types_1.TriggerKind.StopLoss
|
|
276
|
+
? proto.TriggerKind.STOP_LOSS
|
|
277
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
278
|
+
side: params.side === types_1.Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
279
|
+
});
|
|
280
|
+
const prices = (0, protobuf_1.create)(proto.Action_TriggerPricesSchema, {
|
|
281
|
+
triggerPrice,
|
|
282
|
+
limitPrice,
|
|
283
|
+
});
|
|
284
|
+
const action = createAction(currentTimestamp, nonce, {
|
|
285
|
+
case: "addTrigger",
|
|
286
|
+
value: (0, protobuf_1.create)(proto.Action_AddTriggerSchema, {
|
|
287
|
+
sessionId: BigInt(params.sessionId),
|
|
288
|
+
marketId: params.marketId,
|
|
289
|
+
key,
|
|
290
|
+
prices,
|
|
291
|
+
accountId: params.accountId,
|
|
292
|
+
}),
|
|
293
|
+
});
|
|
294
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
295
|
+
if (resp.kind?.case === "triggerAdded") {
|
|
296
|
+
return { actionId: resp.actionId };
|
|
297
|
+
}
|
|
298
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
|
|
299
|
+
}
|
|
300
|
+
async function removeTrigger(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
301
|
+
const key = (0, protobuf_1.create)(proto.TriggerKeySchema, {
|
|
302
|
+
kind: params.kind === types_1.TriggerKind.StopLoss
|
|
303
|
+
? proto.TriggerKind.STOP_LOSS
|
|
304
|
+
: proto.TriggerKind.TAKE_PROFIT,
|
|
305
|
+
side: params.side === types_1.Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
306
|
+
});
|
|
307
|
+
const action = createAction(currentTimestamp, nonce, {
|
|
308
|
+
case: "removeTrigger",
|
|
309
|
+
value: (0, protobuf_1.create)(proto.Action_RemoveTriggerSchema, {
|
|
310
|
+
sessionId: BigInt(params.sessionId),
|
|
311
|
+
marketId: params.marketId,
|
|
312
|
+
key,
|
|
313
|
+
accountId: params.accountId,
|
|
314
|
+
}),
|
|
315
|
+
});
|
|
316
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
317
|
+
if (resp.kind?.case === "triggerRemoved") {
|
|
318
|
+
return { actionId: resp.actionId };
|
|
319
|
+
}
|
|
320
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
|
|
321
|
+
}
|
|
254
322
|
async function atomic(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
255
323
|
(0, utils_1.assert)(params.actions.length > 0 && params.actions.length <= 4, "Atomic action must contain between 1 and 4 sub-actions");
|
|
256
324
|
const subactions = params.actions.map((a) => {
|
|
@@ -258,7 +326,7 @@ async function atomic(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
258
326
|
const price = (0, utils_1.toScaledU64)(a.price ?? 0, a.priceDecimals);
|
|
259
327
|
const size = (0, utils_1.toScaledU64)(a.size ?? 0, a.sizeDecimals);
|
|
260
328
|
const scaledQuote = a.quoteSize
|
|
261
|
-
? a.quoteSize.
|
|
329
|
+
? a.quoteSize.toWire(a.priceDecimals, a.sizeDecimals)
|
|
262
330
|
: undefined;
|
|
263
331
|
// Require at least one limit to be set (non-zero size, non-zero price, or quoteSize)
|
|
264
332
|
(0, utils_1.assert)(price > 0n || size > 0n || scaledQuote !== undefined, "OrderLimit must include at least one of: size, price, or quoteSize");
|
|
@@ -300,7 +368,7 @@ async function atomic(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
|
300
368
|
actions: subactions,
|
|
301
369
|
}),
|
|
302
370
|
});
|
|
303
|
-
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action
|
|
371
|
+
const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
|
|
304
372
|
if (resp.kind?.case === "atomic") {
|
|
305
373
|
return {
|
|
306
374
|
actionId: resp.actionId,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { components } from "../../gen/openapi";
|
|
2
|
+
type AccountTriggerInfo = components["schemas"]["AccountTriggerInfo"];
|
|
3
|
+
type TriggerHistoryPage = components["schemas"]["PageResult_for_uint64_and_HistoryTriggerInfo"];
|
|
4
|
+
type HistoryTriggerQuery = components["schemas"]["AccountTriggersQuery"];
|
|
5
|
+
export type { AccountTriggerInfo, TriggerHistoryPage, HistoryTriggerQuery };
|
|
6
|
+
export declare function getAccountTriggers(serverUrl: string, accountId: number): Promise<AccountTriggerInfo[]>;
|
|
7
|
+
export declare function getAccountTriggerHistory(serverUrl: string, accountId: number, options: HistoryTriggerQuery): Promise<TriggerHistoryPage>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAccountTriggers = getAccountTriggers;
|
|
7
|
+
exports.getAccountTriggerHistory = getAccountTriggerHistory;
|
|
8
|
+
const openapi_fetch_1 = __importDefault(require("openapi-fetch"));
|
|
9
|
+
async function getAccountTriggers(serverUrl, accountId) {
|
|
10
|
+
const client = (0, openapi_fetch_1.default)({ baseUrl: serverUrl });
|
|
11
|
+
const response = await client.GET("/account/{account_id}/triggers", {
|
|
12
|
+
params: {
|
|
13
|
+
path: { account_id: accountId },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
if (response.data === undefined) {
|
|
17
|
+
throw new Error(`Failed to fetch triggers for account ${accountId}: HTTP ${response.response.status}`);
|
|
18
|
+
}
|
|
19
|
+
return response.data ?? [];
|
|
20
|
+
}
|
|
21
|
+
async function getAccountTriggerHistory(serverUrl, accountId, options) {
|
|
22
|
+
const client = (0, openapi_fetch_1.default)({ baseUrl: serverUrl });
|
|
23
|
+
const response = await client.GET("/account/{account_id}/triggers/history", {
|
|
24
|
+
params: {
|
|
25
|
+
path: { account_id: accountId },
|
|
26
|
+
query: {
|
|
27
|
+
since: options.since,
|
|
28
|
+
until: options.until,
|
|
29
|
+
pageSize: options.pageSize,
|
|
30
|
+
startInclusive: options.startInclusive,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
if (!response.data) {
|
|
35
|
+
throw new Error(`Failed to fetch trigger history for account ${accountId}: HTTP ${response.response.status}`);
|
|
36
|
+
}
|
|
37
|
+
return response.data;
|
|
38
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ProtonClient } from "@n1xyz/proton";
|
|
2
2
|
import { PublicKey } from "@solana/web3.js";
|
|
3
3
|
import { EventEmitter } from "events";
|
|
4
|
-
import { Account, ActionResponse, AggregateMetrics, Info, Market, MarketStats, NordConfig, OrderbookQuery, OrderbookResponse, PeakTpsPeriodUnit, Token, TradesResponse, User } from "../../types";
|
|
4
|
+
import { Account, AccountPnlPage, AccountPnlQuery, ActionResponse, AggregateMetrics, Info, Market, MarketStats, NordConfig, OrderbookQuery, OrderbookResponse, PeakTpsPeriodUnit, Token, TradesResponse, User } from "../../types";
|
|
5
5
|
import { NordWebSocketClient } from "../../websocket/index";
|
|
6
6
|
import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
|
|
7
7
|
/**
|
|
@@ -263,6 +263,15 @@ export declare class Nord {
|
|
|
263
263
|
* @throws {NordError} If the request fails
|
|
264
264
|
*/
|
|
265
265
|
getAccount(accountId: number): Promise<Account>;
|
|
266
|
+
/**
|
|
267
|
+
* Get profit and loss history for an account
|
|
268
|
+
*
|
|
269
|
+
* @param accountId - Account ID to query
|
|
270
|
+
* @param query - Optional time and pagination filters
|
|
271
|
+
* @returns Page of PnL entries ordered from latest to oldest
|
|
272
|
+
* @throws {NordError} If the request fails
|
|
273
|
+
*/
|
|
274
|
+
getAccountPnl(accountId: number, query?: Partial<AccountPnlQuery>): Promise<AccountPnlPage>;
|
|
266
275
|
/**
|
|
267
276
|
* Get market statistics (alias for marketsStats for backward compatibility)
|
|
268
277
|
*
|
package/dist/nord/client/Nord.js
CHANGED
|
@@ -502,6 +502,27 @@ class Nord {
|
|
|
502
502
|
},
|
|
503
503
|
});
|
|
504
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Get profit and loss history for an account
|
|
507
|
+
*
|
|
508
|
+
* @param accountId - Account ID to query
|
|
509
|
+
* @param query - Optional time and pagination filters
|
|
510
|
+
* @returns Page of PnL entries ordered from latest to oldest
|
|
511
|
+
* @throws {NordError} If the request fails
|
|
512
|
+
*/
|
|
513
|
+
async getAccountPnl(accountId, query) {
|
|
514
|
+
return await this.GET("/account/{account_id}/pnl", {
|
|
515
|
+
params: {
|
|
516
|
+
path: { account_id: accountId },
|
|
517
|
+
query: {
|
|
518
|
+
since: query?.since,
|
|
519
|
+
until: query?.until,
|
|
520
|
+
startInclusive: query?.startInclusive,
|
|
521
|
+
pageSize: query?.pageSize,
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
});
|
|
525
|
+
}
|
|
505
526
|
/**
|
|
506
527
|
* Get market statistics (alias for marketsStats for backward compatibility)
|
|
507
528
|
*
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Connection, PublicKey, Transaction, SendOptions } from "@solana/web3.js";
|
|
2
2
|
import Decimal from "decimal.js";
|
|
3
|
-
import { FillMode, Side, SPLTokenInfo, QuoteSize } from "../../types";
|
|
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";
|
|
6
7
|
import { Nord } from "./Nord";
|
|
7
8
|
/**
|
|
8
9
|
* Parameters for creating a NordUser instance
|
|
@@ -48,6 +49,20 @@ export interface PlaceOrderParams {
|
|
|
48
49
|
/** Account ID to place the order from */
|
|
49
50
|
accountId?: number;
|
|
50
51
|
}
|
|
52
|
+
export interface AddTriggerParams {
|
|
53
|
+
marketId: number;
|
|
54
|
+
side: Side;
|
|
55
|
+
kind: TriggerKind;
|
|
56
|
+
triggerPrice: Decimal.Value;
|
|
57
|
+
limitPrice?: Decimal.Value;
|
|
58
|
+
accountId?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface RemoveTriggerParams {
|
|
61
|
+
marketId: number;
|
|
62
|
+
side: Side;
|
|
63
|
+
kind: TriggerKind;
|
|
64
|
+
accountId?: number;
|
|
65
|
+
}
|
|
51
66
|
/**
|
|
52
67
|
* Parameters for transferring tokens between accounts
|
|
53
68
|
*/
|
|
@@ -288,6 +303,44 @@ export declare class NordUser {
|
|
|
288
303
|
orderId: bigint;
|
|
289
304
|
accountId: number;
|
|
290
305
|
}>;
|
|
306
|
+
/**
|
|
307
|
+
* Add a trigger for the current session
|
|
308
|
+
*
|
|
309
|
+
* @param params - Trigger parameters including market, side, and prices
|
|
310
|
+
* @returns Object containing the actionId of the submitted trigger
|
|
311
|
+
* @throws {NordError} If the operation fails
|
|
312
|
+
*/
|
|
313
|
+
addTrigger(params: AddTriggerParams): Promise<{
|
|
314
|
+
actionId: bigint;
|
|
315
|
+
}>;
|
|
316
|
+
/**
|
|
317
|
+
* Remove a trigger for the current session
|
|
318
|
+
*
|
|
319
|
+
* @param params - Trigger parameters identifying the trigger to remove
|
|
320
|
+
* @returns Object containing the actionId of the removal action
|
|
321
|
+
* @throws {NordError} If the operation fails
|
|
322
|
+
*/
|
|
323
|
+
removeTrigger(params: RemoveTriggerParams): Promise<{
|
|
324
|
+
actionId: bigint;
|
|
325
|
+
}>;
|
|
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>;
|
|
291
344
|
/**
|
|
292
345
|
* Transfer tokens to another account
|
|
293
346
|
*
|