@n1xyz/nord-ts 0.0.19 → 0.0.21
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/const.d.ts +8 -0
- package/dist/const.js +30 -0
- package/dist/gen/nord.d.ts +882 -0
- package/dist/gen/nord.js +6520 -0
- package/dist/gen/openapi.d.ts +2244 -0
- package/dist/gen/openapi.js +6 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/nord/api/actions.d.ts +135 -0
- package/dist/nord/api/actions.js +313 -0
- package/dist/nord/api/core.d.ts +16 -0
- package/dist/nord/api/core.js +81 -0
- package/dist/nord/api/metrics.d.ts +67 -0
- package/dist/nord/api/metrics.js +229 -0
- package/dist/nord/client/Nord.d.ts +282 -0
- package/dist/nord/client/Nord.js +528 -0
- package/dist/nord/client/NordUser.d.ts +340 -0
- package/dist/nord/client/NordUser.js +652 -0
- package/dist/nord/index.d.ts +7 -0
- package/dist/nord/index.js +31 -0
- package/dist/nord/models/Subscriber.d.ts +37 -0
- package/dist/nord/models/Subscriber.js +25 -0
- package/dist/nord/utils/NordError.d.ts +35 -0
- package/dist/nord/utils/NordError.js +49 -0
- package/dist/types.d.ts +251 -0
- package/dist/types.js +101 -0
- package/dist/utils.d.ts +98 -0
- package/dist/utils.js +237 -0
- package/dist/websocket/NordWebSocketClient.d.ts +57 -0
- package/dist/websocket/NordWebSocketClient.js +251 -0
- package/dist/websocket/events.d.ts +19 -0
- package/dist/websocket/events.js +2 -0
- package/dist/websocket/index.d.ts +2 -0
- package/dist/websocket/index.js +5 -0
- package/package.json +8 -2
- package/src/gen/.gitkeep +0 -0
- package/src/gen/nord.ts +7593 -0
- package/src/gen/openapi.ts +2245 -0
- package/src/nord/api/core.ts +1 -16
- package/src/nord/client/Nord.ts +7 -11
- package/src/types.ts +0 -11
- package/src/websocket/NordWebSocketClient.ts +0 -113
- package/.claude/settings.local.json +0 -11
- package/.local/qa.ts +0 -77
- package/.local/test-atomic.ts +0 -112
- package/.prettierignore +0 -2
- package/check.sh +0 -4
- package/default.nix +0 -47
- package/eslint.config.mjs +0 -66
- package/tests/utils.spec.ts +0 -121
- package/tsconfig.eslint.json +0 -12
- package/tsconfig.json +0 -24
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./utils"), exports);
|
|
19
|
+
__exportStar(require("./const"), exports);
|
|
20
|
+
__exportStar(require("./nord"), exports);
|
|
21
|
+
__exportStar(require("./websocket/index"), exports);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Decimal from "decimal.js";
|
|
2
|
+
import * as proto from "../../gen/nord";
|
|
3
|
+
import { FillMode, Side } from "../../types";
|
|
4
|
+
import { BigIntValue } from "../../utils";
|
|
5
|
+
declare function createSessionImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
6
|
+
userPubkey: Uint8Array;
|
|
7
|
+
sessionPubkey: Uint8Array;
|
|
8
|
+
expiryTimestamp?: bigint;
|
|
9
|
+
}): Promise<bigint>;
|
|
10
|
+
export declare function createSession(serverUrl: string, walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
11
|
+
userPubkey: Uint8Array;
|
|
12
|
+
sessionPubkey: Uint8Array;
|
|
13
|
+
expiryTimestamp?: bigint;
|
|
14
|
+
}): Promise<bigint>;
|
|
15
|
+
declare function revokeSessionImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
16
|
+
sessionId: BigIntValue;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function revokeSession(serverUrl: string, walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
19
|
+
sessionId: BigIntValue;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
declare function withdrawImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
22
|
+
sizeDecimals: number;
|
|
23
|
+
sessionId: BigIntValue;
|
|
24
|
+
tokenId: number;
|
|
25
|
+
amount: Decimal.Value;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
actionId: bigint;
|
|
28
|
+
} & proto.Receipt_WithdrawResult>;
|
|
29
|
+
export declare function withdraw(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
30
|
+
sizeDecimals: number;
|
|
31
|
+
sessionId: BigIntValue;
|
|
32
|
+
tokenId: number;
|
|
33
|
+
amount: number;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
actionId: bigint;
|
|
36
|
+
} & proto.Receipt_WithdrawResult>;
|
|
37
|
+
declare function placeOrderImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
38
|
+
sessionId: BigIntValue;
|
|
39
|
+
senderId?: number;
|
|
40
|
+
liquidateeId?: number;
|
|
41
|
+
sizeDecimals: number;
|
|
42
|
+
priceDecimals: number;
|
|
43
|
+
marketId: number;
|
|
44
|
+
side: Side;
|
|
45
|
+
fillMode: FillMode;
|
|
46
|
+
isReduceOnly: boolean;
|
|
47
|
+
size?: Decimal.Value;
|
|
48
|
+
price?: Decimal.Value;
|
|
49
|
+
quoteSizeSize?: Decimal.Value;
|
|
50
|
+
quoteSizePrice?: Decimal.Value;
|
|
51
|
+
clientOrderId?: BigIntValue;
|
|
52
|
+
}): Promise<bigint | undefined>;
|
|
53
|
+
export declare function placeOrder(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
54
|
+
sessionId: BigIntValue;
|
|
55
|
+
senderId?: number;
|
|
56
|
+
sizeDecimals: number;
|
|
57
|
+
priceDecimals: number;
|
|
58
|
+
marketId: number;
|
|
59
|
+
side: Side;
|
|
60
|
+
fillMode: FillMode;
|
|
61
|
+
isReduceOnly: boolean;
|
|
62
|
+
size?: Decimal.Value;
|
|
63
|
+
price?: Decimal.Value;
|
|
64
|
+
quoteSize?: Decimal.Value;
|
|
65
|
+
liquidateeId?: number;
|
|
66
|
+
clientOrderId?: BigIntValue;
|
|
67
|
+
}): Promise<bigint | undefined>;
|
|
68
|
+
declare function cancelOrderImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
69
|
+
sessionId: BigIntValue;
|
|
70
|
+
senderId?: number;
|
|
71
|
+
orderId: BigIntValue;
|
|
72
|
+
liquidateeId?: number;
|
|
73
|
+
}): Promise<bigint>;
|
|
74
|
+
export declare function cancelOrder(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
75
|
+
sessionId: BigIntValue;
|
|
76
|
+
senderId?: number;
|
|
77
|
+
orderId: BigIntValue;
|
|
78
|
+
liquidateeId?: number;
|
|
79
|
+
}): Promise<bigint>;
|
|
80
|
+
declare function transferImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
81
|
+
sessionId: BigIntValue;
|
|
82
|
+
fromAccountId: number;
|
|
83
|
+
toAccountId?: number;
|
|
84
|
+
tokenId: number;
|
|
85
|
+
tokenDecimals: number;
|
|
86
|
+
amount: Decimal.Value;
|
|
87
|
+
}): Promise<number | undefined>;
|
|
88
|
+
export declare function transfer(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
89
|
+
sessionId: BigIntValue;
|
|
90
|
+
fromAccountId: number;
|
|
91
|
+
toAccountId?: number;
|
|
92
|
+
tokenId: number;
|
|
93
|
+
tokenDecimals: number;
|
|
94
|
+
amount: Decimal.Value;
|
|
95
|
+
}): Promise<number | undefined>;
|
|
96
|
+
export type AtomicSubaction = {
|
|
97
|
+
kind: "place";
|
|
98
|
+
marketId: number;
|
|
99
|
+
side: Side;
|
|
100
|
+
fillMode: FillMode;
|
|
101
|
+
isReduceOnly: boolean;
|
|
102
|
+
sizeDecimals: number;
|
|
103
|
+
priceDecimals: number;
|
|
104
|
+
size?: Decimal.Value;
|
|
105
|
+
price?: Decimal.Value;
|
|
106
|
+
quoteSizeSize?: Decimal.Value;
|
|
107
|
+
quoteSizePrice?: Decimal.Value;
|
|
108
|
+
clientOrderId?: BigIntValue;
|
|
109
|
+
} | {
|
|
110
|
+
kind: "cancel";
|
|
111
|
+
orderId: BigIntValue;
|
|
112
|
+
};
|
|
113
|
+
declare function atomicImpl(sendFn: (encoded: Uint8Array) => Promise<Uint8Array>, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
114
|
+
sessionId: BigIntValue;
|
|
115
|
+
accountId?: number;
|
|
116
|
+
actions: AtomicSubaction[];
|
|
117
|
+
}): Promise<proto.Receipt_AtomicResult>;
|
|
118
|
+
export declare function atomic(serverUrl: string, signFn: (message: Uint8Array) => Promise<Uint8Array>, currentTimestamp: bigint, nonce: number, params: {
|
|
119
|
+
sessionId: BigIntValue;
|
|
120
|
+
accountId?: number;
|
|
121
|
+
actions: AtomicSubaction[];
|
|
122
|
+
}): Promise<proto.Receipt_AtomicResult>;
|
|
123
|
+
/**
|
|
124
|
+
* For testing purposes
|
|
125
|
+
*/
|
|
126
|
+
export declare const _private: {
|
|
127
|
+
createSessionImpl: typeof createSessionImpl;
|
|
128
|
+
revokeSessionImpl: typeof revokeSessionImpl;
|
|
129
|
+
withdrawImpl: typeof withdrawImpl;
|
|
130
|
+
placeOrderImpl: typeof placeOrderImpl;
|
|
131
|
+
cancelOrderImpl: typeof cancelOrderImpl;
|
|
132
|
+
transferImpl: typeof transferImpl;
|
|
133
|
+
atomicImpl: typeof atomicImpl;
|
|
134
|
+
};
|
|
135
|
+
export {};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports._private = void 0;
|
|
37
|
+
exports.createSession = createSession;
|
|
38
|
+
exports.revokeSession = revokeSession;
|
|
39
|
+
exports.withdraw = withdraw;
|
|
40
|
+
exports.placeOrder = placeOrder;
|
|
41
|
+
exports.cancelOrder = cancelOrder;
|
|
42
|
+
exports.transfer = transfer;
|
|
43
|
+
exports.atomic = atomic;
|
|
44
|
+
const proto = __importStar(require("../../gen/nord"));
|
|
45
|
+
const types_1 = require("../../types");
|
|
46
|
+
const utils_1 = require("../../utils");
|
|
47
|
+
async function sessionSign(signFn, message) {
|
|
48
|
+
const signature = await signFn(message);
|
|
49
|
+
return new Uint8Array([...message, ...signature]);
|
|
50
|
+
}
|
|
51
|
+
async function walletSign(walletSignFn, message) {
|
|
52
|
+
const signature = await walletSignFn(message);
|
|
53
|
+
return new Uint8Array([...message, ...signature]);
|
|
54
|
+
}
|
|
55
|
+
function makeSendHttp(serverUrl) {
|
|
56
|
+
return async (body) => {
|
|
57
|
+
// TODO: this should be changed to use openapi
|
|
58
|
+
const response = await (0, utils_1.checkedFetch)(`${serverUrl}/action`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: {
|
|
61
|
+
"Content-Type": "application/json",
|
|
62
|
+
},
|
|
63
|
+
body,
|
|
64
|
+
});
|
|
65
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async function sendAction(sendFn, makeSignedMessage, action, actionErrorDesc) {
|
|
69
|
+
const encoded = (0, utils_1.encodeLengthDelimited)(action, proto.Action);
|
|
70
|
+
const body = await makeSignedMessage(encoded);
|
|
71
|
+
const rawResp = await sendFn(body);
|
|
72
|
+
const resp = (0, utils_1.decodeLengthDelimited)(rawResp, proto.Receipt);
|
|
73
|
+
if (resp.kind?.$case === "err") {
|
|
74
|
+
throw new Error(`Could not ${actionErrorDesc}, reason: ${proto.errorToJSON(resp.kind.value)}`);
|
|
75
|
+
}
|
|
76
|
+
return resp;
|
|
77
|
+
}
|
|
78
|
+
async function createSessionImpl(sendFn, walletSignFn, currentTimestamp, nonce, params) {
|
|
79
|
+
(0, utils_1.checkPubKeyLength)(types_1.KeyType.Ed25519, params.userPubkey.length);
|
|
80
|
+
(0, utils_1.checkPubKeyLength)(types_1.KeyType.Ed25519, params.sessionPubkey.length);
|
|
81
|
+
let expiry = 0n;
|
|
82
|
+
if (params.expiryTimestamp !== undefined) {
|
|
83
|
+
expiry = params.expiryTimestamp;
|
|
84
|
+
(0, utils_1.assert)(expiry > currentTimestamp, "Cannot set expiry timestamp in the past");
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
expiry = currentTimestamp + utils_1.SESSION_TTL;
|
|
88
|
+
}
|
|
89
|
+
const action = {
|
|
90
|
+
currentTimestamp,
|
|
91
|
+
nonce,
|
|
92
|
+
kind: {
|
|
93
|
+
$case: "createSession",
|
|
94
|
+
value: {
|
|
95
|
+
userPubkey: params.userPubkey,
|
|
96
|
+
blstPubkey: params.sessionPubkey,
|
|
97
|
+
expiryTimestamp: expiry,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
const resp = await sendAction(sendFn, (m) => walletSign(walletSignFn, m), action, "create a new session");
|
|
102
|
+
if (resp.kind?.$case === "createSessionResult") {
|
|
103
|
+
return resp.kind.value.sessionId;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function createSession(serverUrl, walletSignFn, currentTimestamp, nonce, params) {
|
|
110
|
+
return createSessionImpl(makeSendHttp(serverUrl), walletSignFn, currentTimestamp, nonce, params);
|
|
111
|
+
}
|
|
112
|
+
async function revokeSessionImpl(sendFn, walletSignFn, currentTimestamp, nonce, params) {
|
|
113
|
+
const action = {
|
|
114
|
+
currentTimestamp,
|
|
115
|
+
nonce,
|
|
116
|
+
kind: {
|
|
117
|
+
$case: "revokeSession",
|
|
118
|
+
value: {
|
|
119
|
+
sessionId: BigInt(params.sessionId),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
await sendAction(sendFn, (m) => walletSign(walletSignFn, m), action, "create a new session");
|
|
124
|
+
}
|
|
125
|
+
async function revokeSession(serverUrl, walletSignFn, currentTimestamp, nonce, params) {
|
|
126
|
+
return revokeSessionImpl(makeSendHttp(serverUrl), walletSignFn, currentTimestamp, nonce, params);
|
|
127
|
+
}
|
|
128
|
+
async function withdrawImpl(sendFn, signFn, currentTimestamp, nonce, params) {
|
|
129
|
+
const amount = (0, utils_1.toScaledU64)(params.amount, params.sizeDecimals);
|
|
130
|
+
if (amount <= 0) {
|
|
131
|
+
throw new Error("Withdraw amount must be positive");
|
|
132
|
+
}
|
|
133
|
+
const action = {
|
|
134
|
+
currentTimestamp,
|
|
135
|
+
nonce,
|
|
136
|
+
kind: {
|
|
137
|
+
$case: "withdraw",
|
|
138
|
+
value: {
|
|
139
|
+
sessionId: BigInt(params.sessionId),
|
|
140
|
+
tokenId: params.tokenId,
|
|
141
|
+
amount,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
const resp = await sendAction(sendFn, (m) => sessionSign(signFn, m), action, "withdraw");
|
|
146
|
+
if (resp.kind?.$case === "withdrawResult") {
|
|
147
|
+
return { actionId: resp.actionId, ...resp.kind.value };
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function withdraw(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
154
|
+
return withdrawImpl(makeSendHttp(serverUrl), signFn, currentTimestamp, nonce, params);
|
|
155
|
+
}
|
|
156
|
+
async function placeOrderImpl(sendFn, signFn, currentTimestamp, nonce, params) {
|
|
157
|
+
const price = (0, utils_1.toScaledU64)(params.price ?? 0, params.priceDecimals);
|
|
158
|
+
const size = (0, utils_1.toScaledU64)(params.size ?? 0, params.sizeDecimals);
|
|
159
|
+
const quoteSize = (0, utils_1.toScaledU64)(params.quoteSizeSize ?? 0, params.sizeDecimals);
|
|
160
|
+
const quotePrice = (0, utils_1.toScaledU64)(params.quoteSizePrice ?? 0, params.priceDecimals);
|
|
161
|
+
// Compose action object
|
|
162
|
+
const action = {
|
|
163
|
+
currentTimestamp,
|
|
164
|
+
nonce,
|
|
165
|
+
kind: {
|
|
166
|
+
$case: "placeOrder",
|
|
167
|
+
value: {
|
|
168
|
+
sessionId: BigInt(params.sessionId),
|
|
169
|
+
senderAccountId: params.senderId,
|
|
170
|
+
marketId: params.marketId,
|
|
171
|
+
side: params.side === types_1.Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
172
|
+
fillMode: (0, types_1.fillModeToProtoFillMode)(params.fillMode),
|
|
173
|
+
isReduceOnly: params.isReduceOnly,
|
|
174
|
+
price,
|
|
175
|
+
size,
|
|
176
|
+
quoteSize: { size: quoteSize, price: quotePrice },
|
|
177
|
+
clientOrderId: params.clientOrderId === undefined
|
|
178
|
+
? undefined
|
|
179
|
+
: BigInt(params.clientOrderId),
|
|
180
|
+
delegatorAccountId: params.liquidateeId,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const resp = await sendAction(sendFn, (m) => sessionSign(signFn, m), action, "place the order");
|
|
185
|
+
if (resp.kind?.$case === "placeOrderResult") {
|
|
186
|
+
return resp.kind.value.posted?.orderId;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function placeOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
193
|
+
return placeOrderImpl(makeSendHttp(serverUrl), signFn, currentTimestamp, nonce, params);
|
|
194
|
+
}
|
|
195
|
+
async function cancelOrderImpl(sendFn, signFn, currentTimestamp, nonce, params) {
|
|
196
|
+
const action = {
|
|
197
|
+
currentTimestamp,
|
|
198
|
+
nonce: nonce,
|
|
199
|
+
kind: {
|
|
200
|
+
$case: "cancelOrderById",
|
|
201
|
+
value: {
|
|
202
|
+
orderId: BigInt(params.orderId),
|
|
203
|
+
sessionId: BigInt(params.sessionId),
|
|
204
|
+
senderAccountId: params.senderId,
|
|
205
|
+
delegatorAccountId: params.liquidateeId,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const resp = await sendAction(sendFn, (m) => sessionSign(signFn, m), action, "cancel the order");
|
|
210
|
+
if (resp.kind?.$case === "cancelOrderResult") {
|
|
211
|
+
return resp.kind.value.orderId;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function cancelOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
218
|
+
return cancelOrderImpl(makeSendHttp(serverUrl), signFn, currentTimestamp, nonce, params);
|
|
219
|
+
}
|
|
220
|
+
async function transferImpl(sendFn, signFn, currentTimestamp, nonce, params) {
|
|
221
|
+
const action = {
|
|
222
|
+
currentTimestamp,
|
|
223
|
+
nonce: nonce,
|
|
224
|
+
kind: {
|
|
225
|
+
$case: "transfer",
|
|
226
|
+
value: {
|
|
227
|
+
sessionId: BigInt(params.sessionId),
|
|
228
|
+
fromAccountId: params.fromAccountId,
|
|
229
|
+
toAccountId: params.toAccountId,
|
|
230
|
+
tokenId: params.tokenId,
|
|
231
|
+
amount: (0, utils_1.toScaledU64)(params.amount ?? 0, params.tokenDecimals),
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
const resp = await sendAction(sendFn, (m) => sessionSign(signFn, m), action, "transfer asset to other account");
|
|
236
|
+
if (resp.kind?.$case === "transferred") {
|
|
237
|
+
if (resp.kind.value.accountCreated) {
|
|
238
|
+
return resp.kind.value.toUserAccount;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function transfer(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
249
|
+
return transferImpl(makeSendHttp(serverUrl), signFn, currentTimestamp, nonce, params);
|
|
250
|
+
}
|
|
251
|
+
async function atomicImpl(sendFn, signFn, currentTimestamp, nonce, params) {
|
|
252
|
+
(0, utils_1.assert)(params.actions.length > 0 && params.actions.length <= 4, "Atomic action must contain between 1 and 4 sub-actions");
|
|
253
|
+
const subactions = params.actions.map((a) => {
|
|
254
|
+
if (a.kind === "place") {
|
|
255
|
+
const price = (0, utils_1.toScaledU64)(a.price ?? 0, a.priceDecimals);
|
|
256
|
+
const size = (0, utils_1.toScaledU64)(a.size ?? 0, a.sizeDecimals);
|
|
257
|
+
const quoteSizeSize = (0, utils_1.toScaledU64)(a.quoteSizeSize ?? 0, a.sizeDecimals);
|
|
258
|
+
const quoteSizePrice = (0, utils_1.toScaledU64)(a.quoteSizePrice ?? 0, a.priceDecimals);
|
|
259
|
+
const tradeOrPlace = {
|
|
260
|
+
marketId: a.marketId,
|
|
261
|
+
orderType: {
|
|
262
|
+
side: a.side === types_1.Side.Bid ? proto.Side.BID : proto.Side.ASK,
|
|
263
|
+
fillMode: (0, types_1.fillModeToProtoFillMode)(a.fillMode),
|
|
264
|
+
isReduceOnly: a.isReduceOnly,
|
|
265
|
+
},
|
|
266
|
+
limit: {
|
|
267
|
+
price,
|
|
268
|
+
size,
|
|
269
|
+
quoteSize: { size: quoteSizeSize, price: quoteSizePrice },
|
|
270
|
+
},
|
|
271
|
+
clientOrderId: a.clientOrderId === undefined ? undefined : BigInt(a.clientOrderId),
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
inner: { $case: "tradeOrPlace", value: tradeOrPlace },
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
inner: { $case: "cancelOrder", value: { orderId: BigInt(a.orderId) } },
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
const action = {
|
|
282
|
+
currentTimestamp,
|
|
283
|
+
nonce,
|
|
284
|
+
kind: {
|
|
285
|
+
$case: "atomic",
|
|
286
|
+
value: {
|
|
287
|
+
sessionId: BigInt(params.sessionId),
|
|
288
|
+
accountId: params.accountId, // optional
|
|
289
|
+
actions: subactions,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
const resp = await sendAction(sendFn, (m) => sessionSign(signFn, m), action, "execute atomic action");
|
|
294
|
+
if (resp.kind?.$case === "atomic") {
|
|
295
|
+
return resp.kind.value;
|
|
296
|
+
}
|
|
297
|
+
throw new Error(`Unexpected receipt kind ${resp.kind?.$case}`);
|
|
298
|
+
}
|
|
299
|
+
async function atomic(serverUrl, signFn, currentTimestamp, nonce, params) {
|
|
300
|
+
return atomicImpl(makeSendHttp(serverUrl), signFn, currentTimestamp, nonce, params);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* For testing purposes
|
|
304
|
+
*/
|
|
305
|
+
exports._private = {
|
|
306
|
+
createSessionImpl,
|
|
307
|
+
revokeSessionImpl,
|
|
308
|
+
withdrawImpl,
|
|
309
|
+
placeOrderImpl,
|
|
310
|
+
cancelOrderImpl,
|
|
311
|
+
transferImpl,
|
|
312
|
+
atomicImpl,
|
|
313
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SubscriptionPattern } from "../../types";
|
|
2
|
+
import { NordWebSocketClient } from "../../websocket/index";
|
|
3
|
+
/**
|
|
4
|
+
* Initialize a WebSocket client for Nord
|
|
5
|
+
*
|
|
6
|
+
* Connects to the Nord WebSocket endpoint with support for multiple subscription types:
|
|
7
|
+
* - trades@SYMBOL - For trade updates
|
|
8
|
+
* - deltas@SYMBOL - For orderbook delta updates
|
|
9
|
+
* - account@ACCOUNT_ID - For user-specific updates
|
|
10
|
+
*
|
|
11
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
12
|
+
* @param subscriptions - Array of subscriptions (e.g., ["trades@BTCUSDC", "deltas@BTCUSDC", "account@42"])
|
|
13
|
+
* @returns WebSocket client
|
|
14
|
+
* @throws {NordError} If initialization fails or invalid subscription is provided
|
|
15
|
+
*/
|
|
16
|
+
export declare function initWebSocketClient(webServerUrl: string, subscriptions?: SubscriptionPattern[] | "trades" | "delta" | "account"): NordWebSocketClient;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initWebSocketClient = initWebSocketClient;
|
|
4
|
+
const index_1 = require("../../websocket/index");
|
|
5
|
+
const NordError_1 = require("../utils/NordError");
|
|
6
|
+
/**
|
|
7
|
+
* Initialize a WebSocket client for Nord
|
|
8
|
+
*
|
|
9
|
+
* Connects to the Nord WebSocket endpoint with support for multiple subscription types:
|
|
10
|
+
* - trades@SYMBOL - For trade updates
|
|
11
|
+
* - deltas@SYMBOL - For orderbook delta updates
|
|
12
|
+
* - account@ACCOUNT_ID - For user-specific updates
|
|
13
|
+
*
|
|
14
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
15
|
+
* @param subscriptions - Array of subscriptions (e.g., ["trades@BTCUSDC", "deltas@BTCUSDC", "account@42"])
|
|
16
|
+
* @returns WebSocket client
|
|
17
|
+
* @throws {NordError} If initialization fails or invalid subscription is provided
|
|
18
|
+
*/
|
|
19
|
+
function initWebSocketClient(webServerUrl, subscriptions) {
|
|
20
|
+
try {
|
|
21
|
+
// Determine URL and subscriptions based on parameters
|
|
22
|
+
let wsUrl = webServerUrl.replace(/^http/, "ws") + `/ws`;
|
|
23
|
+
// Validate subscriptions parameter
|
|
24
|
+
if (typeof subscriptions === "string") {
|
|
25
|
+
// Legacy mode - handle endpoint string
|
|
26
|
+
if (subscriptions === "trades" ||
|
|
27
|
+
subscriptions === "delta" ||
|
|
28
|
+
subscriptions === "account") {
|
|
29
|
+
wsUrl += `/${subscriptions}`;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new NordError_1.NordError(`Invalid endpoint: ${subscriptions}. Must be "trades", "deltas", or "account".`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (Array.isArray(subscriptions) && subscriptions.length > 0) {
|
|
36
|
+
// New mode - validate and combine subscriptions in URL
|
|
37
|
+
subscriptions.forEach(validateSubscription);
|
|
38
|
+
wsUrl += `/${subscriptions.join("&")}`;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Default to trades endpoint if no subscriptions specified
|
|
42
|
+
wsUrl += `/trades`;
|
|
43
|
+
}
|
|
44
|
+
console.log(`Initializing WebSocket client with URL: ${wsUrl}`);
|
|
45
|
+
// Create and connect the WebSocket client
|
|
46
|
+
const ws = new index_1.NordWebSocketClient(wsUrl);
|
|
47
|
+
// Add error handler
|
|
48
|
+
ws.on("error", (error) => {
|
|
49
|
+
console.error("Nord WebSocket error:", error);
|
|
50
|
+
});
|
|
51
|
+
// Add connected handler for debugging
|
|
52
|
+
ws.on("connected", () => {
|
|
53
|
+
console.log("Nord WebSocket connected successfully");
|
|
54
|
+
});
|
|
55
|
+
// Connect the WebSocket
|
|
56
|
+
ws.connect();
|
|
57
|
+
return ws;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error("Failed to initialize WebSocket client:", error);
|
|
61
|
+
throw new NordError_1.NordError("Failed to initialize WebSocket client", {
|
|
62
|
+
cause: error,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validates a subscription string follows the correct format
|
|
68
|
+
*
|
|
69
|
+
* @param subscription - The subscription to validate
|
|
70
|
+
* @throws {NordError} If the subscription format is invalid
|
|
71
|
+
*/
|
|
72
|
+
function validateSubscription(subscription) {
|
|
73
|
+
const [type, param] = subscription.split("@");
|
|
74
|
+
if (!type || !param || !["trades", "deltas", "account"].includes(type)) {
|
|
75
|
+
throw new NordError_1.NordError(`Invalid subscription format: ${subscription}. Expected format: "trades@SYMBOL", "deltas@SYMBOL", or "account@ID"`);
|
|
76
|
+
}
|
|
77
|
+
// Additional validation for account subscriptions
|
|
78
|
+
if (type === "account" && isNaN(Number(param))) {
|
|
79
|
+
throw new NordError_1.NordError(`Invalid account ID in subscription: ${subscription}. Account ID must be a number.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { AggregateMetrics, PeakTpsPeriodUnit } from "../../types";
|
|
2
|
+
/**
|
|
3
|
+
* Time periods for metrics queries
|
|
4
|
+
*/
|
|
5
|
+
export declare enum MetricPeriod {
|
|
6
|
+
ONE_MINUTE = "1m",
|
|
7
|
+
FIVE_MINUTES = "5m",
|
|
8
|
+
FIFTEEN_MINUTES = "15m",
|
|
9
|
+
ONE_HOUR = "1h",
|
|
10
|
+
FOUR_HOURS = "4h",
|
|
11
|
+
ONE_DAY = "24h",
|
|
12
|
+
ONE_WEEK = "7d"
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Fetch aggregate metrics from the Nord API
|
|
16
|
+
*
|
|
17
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
18
|
+
* @param txPeakTpsPeriod - Period for peak TPS calculation
|
|
19
|
+
* @param txPeakTpsPeriodUnit - Unit for peak TPS period
|
|
20
|
+
* @returns Aggregate metrics
|
|
21
|
+
* @throws {NordError} If the request fails
|
|
22
|
+
*/
|
|
23
|
+
export declare function aggregateMetrics(webServerUrl: string, txPeakTpsPeriod?: number, txPeakTpsPeriodUnit?: PeakTpsPeriodUnit): Promise<AggregateMetrics>;
|
|
24
|
+
/**
|
|
25
|
+
* Get current transactions per second
|
|
26
|
+
*
|
|
27
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
28
|
+
* @param period - Time period for the query
|
|
29
|
+
* @returns Current TPS value
|
|
30
|
+
* @throws {NordError} If the request fails
|
|
31
|
+
*/
|
|
32
|
+
export declare function getCurrentTps(webServerUrl: string, period?: string): Promise<number>;
|
|
33
|
+
/**
|
|
34
|
+
* Get peak transactions per second
|
|
35
|
+
*
|
|
36
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
37
|
+
* @param period - Time period for the query
|
|
38
|
+
* @returns Peak TPS value
|
|
39
|
+
* @throws {NordError} If the request fails
|
|
40
|
+
*/
|
|
41
|
+
export declare function getPeakTps(webServerUrl: string, period?: string): Promise<number>;
|
|
42
|
+
/**
|
|
43
|
+
* Get median transaction latency
|
|
44
|
+
*
|
|
45
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
46
|
+
* @param period - Time period for the query
|
|
47
|
+
* @returns Median latency in milliseconds
|
|
48
|
+
* @throws {NordError} If the request fails
|
|
49
|
+
*/
|
|
50
|
+
export declare function getMedianLatency(webServerUrl: string, period?: string): Promise<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Get total transaction count
|
|
53
|
+
*
|
|
54
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
55
|
+
* @returns Total transaction count
|
|
56
|
+
* @throws {NordError} If the request fails
|
|
57
|
+
*/
|
|
58
|
+
export declare function getTotalTransactions(webServerUrl: string): Promise<number>;
|
|
59
|
+
/**
|
|
60
|
+
* Query Prometheus metrics
|
|
61
|
+
*
|
|
62
|
+
* @param webServerUrl - Base URL for the Nord web server
|
|
63
|
+
* @param params - Prometheus query parameters
|
|
64
|
+
* @returns Query result as a number
|
|
65
|
+
* @throws {NordError} If the request fails
|
|
66
|
+
*/
|
|
67
|
+
export declare function queryPrometheus(webServerUrl: string, params: string): Promise<number>;
|