okx-trade-cli 1.0.2 → 1.0.3
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/index.js +237 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { createRequire } from "module";
|
|
|
6
6
|
|
|
7
7
|
// ../core/dist/index.js
|
|
8
8
|
import { createHmac } from "crypto";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import os from "os";
|
|
9
11
|
import { readFileSync, existsSync } from "fs";
|
|
10
12
|
import { join } from "path";
|
|
11
13
|
import { homedir } from "os";
|
|
@@ -24,6 +26,7 @@ var OkxMcpError = class extends Error {
|
|
|
24
26
|
code;
|
|
25
27
|
suggestion;
|
|
26
28
|
endpoint;
|
|
29
|
+
traceId;
|
|
27
30
|
constructor(type, message, options) {
|
|
28
31
|
super(message, options?.cause ? { cause: options.cause } : void 0);
|
|
29
32
|
this.name = type;
|
|
@@ -31,6 +34,7 @@ var OkxMcpError = class extends Error {
|
|
|
31
34
|
this.code = options?.code;
|
|
32
35
|
this.suggestion = options?.suggestion;
|
|
33
36
|
this.endpoint = options?.endpoint;
|
|
37
|
+
this.traceId = options?.traceId;
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
40
|
var ConfigError = class extends OkxMcpError {
|
|
@@ -39,13 +43,13 @@ var ConfigError = class extends OkxMcpError {
|
|
|
39
43
|
}
|
|
40
44
|
};
|
|
41
45
|
var RateLimitError = class extends OkxMcpError {
|
|
42
|
-
constructor(message, suggestion, endpoint) {
|
|
43
|
-
super("RateLimitError", message, { suggestion, endpoint });
|
|
46
|
+
constructor(message, suggestion, endpoint, traceId) {
|
|
47
|
+
super("RateLimitError", message, { suggestion, endpoint, traceId });
|
|
44
48
|
}
|
|
45
49
|
};
|
|
46
50
|
var AuthenticationError = class extends OkxMcpError {
|
|
47
|
-
constructor(message, suggestion, endpoint) {
|
|
48
|
-
super("AuthenticationError", message, { suggestion, endpoint });
|
|
51
|
+
constructor(message, suggestion, endpoint, traceId) {
|
|
52
|
+
super("AuthenticationError", message, { suggestion, endpoint, traceId });
|
|
49
53
|
}
|
|
50
54
|
};
|
|
51
55
|
var OkxApiError = class extends OkxMcpError {
|
|
@@ -71,6 +75,7 @@ function toToolErrorPayload(error, fallbackEndpoint) {
|
|
|
71
75
|
message: error.message,
|
|
72
76
|
suggestion: error.suggestion,
|
|
73
77
|
endpoint: error.endpoint ?? fallbackEndpoint,
|
|
78
|
+
traceId: error.traceId,
|
|
74
79
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
75
80
|
};
|
|
76
81
|
}
|
|
@@ -154,6 +159,9 @@ var RateLimiter = class {
|
|
|
154
159
|
function isDefined(value) {
|
|
155
160
|
return value !== void 0 && value !== null;
|
|
156
161
|
}
|
|
162
|
+
function extractTraceId(headers) {
|
|
163
|
+
return headers.get("x-trace-id") ?? headers.get("x-request-id") ?? headers.get("traceid") ?? void 0;
|
|
164
|
+
}
|
|
157
165
|
function stringifyQueryValue(value) {
|
|
158
166
|
if (Array.isArray(value)) {
|
|
159
167
|
return value.map((item) => String(item)).join(",");
|
|
@@ -180,28 +188,28 @@ var OkxRestClient = class {
|
|
|
180
188
|
constructor(config) {
|
|
181
189
|
this.config = config;
|
|
182
190
|
}
|
|
183
|
-
async publicGet(
|
|
191
|
+
async publicGet(path3, query, rateLimit) {
|
|
184
192
|
return this.request({
|
|
185
193
|
method: "GET",
|
|
186
|
-
path,
|
|
194
|
+
path: path3,
|
|
187
195
|
auth: "public",
|
|
188
196
|
query,
|
|
189
197
|
rateLimit
|
|
190
198
|
});
|
|
191
199
|
}
|
|
192
|
-
async privateGet(
|
|
200
|
+
async privateGet(path3, query, rateLimit) {
|
|
193
201
|
return this.request({
|
|
194
202
|
method: "GET",
|
|
195
|
-
path,
|
|
203
|
+
path: path3,
|
|
196
204
|
auth: "private",
|
|
197
205
|
query,
|
|
198
206
|
rateLimit
|
|
199
207
|
});
|
|
200
208
|
}
|
|
201
|
-
async privatePost(
|
|
209
|
+
async privatePost(path3, body, rateLimit) {
|
|
202
210
|
return this.request({
|
|
203
211
|
method: "POST",
|
|
204
|
-
path,
|
|
212
|
+
path: path3,
|
|
205
213
|
auth: "private",
|
|
206
214
|
body,
|
|
207
215
|
rateLimit
|
|
@@ -220,6 +228,9 @@ var OkxRestClient = class {
|
|
|
220
228
|
"Content-Type": "application/json",
|
|
221
229
|
Accept: "application/json"
|
|
222
230
|
});
|
|
231
|
+
if (this.config.userAgent) {
|
|
232
|
+
headers.set("User-Agent", this.config.userAgent);
|
|
233
|
+
}
|
|
223
234
|
if (config.auth === "private") {
|
|
224
235
|
if (!this.config.hasAuth) {
|
|
225
236
|
throw new ConfigError(
|
|
@@ -259,6 +270,7 @@ var OkxRestClient = class {
|
|
|
259
270
|
);
|
|
260
271
|
}
|
|
261
272
|
const rawText = await response.text();
|
|
273
|
+
const traceId = extractTraceId(response.headers);
|
|
262
274
|
let parsed;
|
|
263
275
|
try {
|
|
264
276
|
parsed = rawText ? JSON.parse(rawText) : {};
|
|
@@ -270,7 +282,8 @@ var OkxRestClient = class {
|
|
|
270
282
|
{
|
|
271
283
|
code: String(response.status),
|
|
272
284
|
endpoint: `${config.method} ${config.path}`,
|
|
273
|
-
suggestion: "Verify endpoint path and request parameters."
|
|
285
|
+
suggestion: "Verify endpoint path and request parameters.",
|
|
286
|
+
traceId
|
|
274
287
|
}
|
|
275
288
|
);
|
|
276
289
|
}
|
|
@@ -286,7 +299,8 @@ var OkxRestClient = class {
|
|
|
286
299
|
{
|
|
287
300
|
code: String(response.status),
|
|
288
301
|
endpoint: `${config.method} ${config.path}`,
|
|
289
|
-
suggestion: "Retry later or verify endpoint parameters."
|
|
302
|
+
suggestion: "Retry later or verify endpoint parameters.",
|
|
303
|
+
traceId
|
|
290
304
|
}
|
|
291
305
|
);
|
|
292
306
|
}
|
|
@@ -297,12 +311,14 @@ var OkxRestClient = class {
|
|
|
297
311
|
throw new AuthenticationError(
|
|
298
312
|
message,
|
|
299
313
|
"Check API key, secret, passphrase and permissions.",
|
|
300
|
-
`${config.method} ${config.path}
|
|
314
|
+
`${config.method} ${config.path}`,
|
|
315
|
+
traceId
|
|
301
316
|
);
|
|
302
317
|
}
|
|
303
318
|
throw new OkxApiError(message, {
|
|
304
319
|
code: responseCode,
|
|
305
|
-
endpoint: `${config.method} ${config.path}
|
|
320
|
+
endpoint: `${config.method} ${config.path}`,
|
|
321
|
+
traceId
|
|
306
322
|
});
|
|
307
323
|
}
|
|
308
324
|
return {
|
|
@@ -313,21 +329,24 @@ var OkxRestClient = class {
|
|
|
313
329
|
};
|
|
314
330
|
}
|
|
315
331
|
};
|
|
332
|
+
var DEFAULT_LOG_DIR = path.join(os.homedir(), ".okx", "logs");
|
|
316
333
|
var OKX_API_BASE_URL = "https://www.okx.com";
|
|
317
334
|
var MODULES = [
|
|
318
335
|
"market",
|
|
319
336
|
"spot",
|
|
320
337
|
"swap",
|
|
321
|
-
"
|
|
338
|
+
"futures",
|
|
339
|
+
"account",
|
|
340
|
+
"bot"
|
|
322
341
|
];
|
|
323
342
|
var DEFAULT_MODULES = ["spot", "swap", "account"];
|
|
324
343
|
function configFilePath() {
|
|
325
344
|
return join(homedir(), ".okx", "config.toml");
|
|
326
345
|
}
|
|
327
346
|
function readTomlProfile(profileName) {
|
|
328
|
-
const
|
|
329
|
-
if (!existsSync(
|
|
330
|
-
const raw = readFileSync(
|
|
347
|
+
const path3 = configFilePath();
|
|
348
|
+
if (!existsSync(path3)) return {};
|
|
349
|
+
const raw = readFileSync(path3, "utf-8");
|
|
331
350
|
const config = parse(raw);
|
|
332
351
|
const name = profileName ?? config.default_profile ?? "default";
|
|
333
352
|
return config.profiles?.[name] ?? {};
|
|
@@ -394,7 +413,8 @@ function loadConfig(cli) {
|
|
|
394
413
|
timeoutMs: Math.floor(rawTimeout),
|
|
395
414
|
modules: parseModuleList(cli.modules),
|
|
396
415
|
readOnly: cli.readOnly,
|
|
397
|
-
demo
|
|
416
|
+
demo,
|
|
417
|
+
userAgent: cli.userAgent
|
|
398
418
|
};
|
|
399
419
|
}
|
|
400
420
|
var CACHE_FILE = join2(homedir2(), ".okx", "update-check.json");
|
|
@@ -471,7 +491,8 @@ function loadProfileConfig(opts) {
|
|
|
471
491
|
profile: opts.profile,
|
|
472
492
|
modules: opts.modules,
|
|
473
493
|
readOnly: opts.readOnly ?? false,
|
|
474
|
-
demo: opts.demo ?? false
|
|
494
|
+
demo: opts.demo ?? false,
|
|
495
|
+
userAgent: opts.userAgent
|
|
475
496
|
});
|
|
476
497
|
}
|
|
477
498
|
|
|
@@ -955,13 +976,18 @@ function writeCliConfig(config) {
|
|
|
955
976
|
|
|
956
977
|
// src/commands/config.ts
|
|
957
978
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
958
|
-
import { parse as parse2 } from "smol-toml";
|
|
979
|
+
import { parse as parse2, stringify as stringify2 } from "smol-toml";
|
|
980
|
+
import { createInterface } from "readline";
|
|
981
|
+
import { spawnSync } from "child_process";
|
|
959
982
|
function readFullConfig() {
|
|
960
|
-
const
|
|
961
|
-
if (!existsSync4(
|
|
962
|
-
const raw = readFileSync3(
|
|
983
|
+
const path3 = configFilePath();
|
|
984
|
+
if (!existsSync4(path3)) return { profiles: {} };
|
|
985
|
+
const raw = readFileSync3(path3, "utf-8");
|
|
963
986
|
return parse2(raw);
|
|
964
987
|
}
|
|
988
|
+
function prompt(rl, question) {
|
|
989
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
990
|
+
}
|
|
965
991
|
function cmdConfigShow(json) {
|
|
966
992
|
const config = readFullConfig();
|
|
967
993
|
if (json) return printJson(config);
|
|
@@ -995,6 +1021,184 @@ function cmdConfigSet(key, value) {
|
|
|
995
1021
|
process.exitCode = 1;
|
|
996
1022
|
}
|
|
997
1023
|
}
|
|
1024
|
+
async function cmdConfigInit() {
|
|
1025
|
+
const apiUrl = "https://www.okx.com/account/my-api";
|
|
1026
|
+
process.stdout.write("OKX Trade CLI \u2014 \u914D\u7F6E\u5411\u5BFC\n\n");
|
|
1027
|
+
process.stdout.write(`\u8BF7\u524D\u5F80 ${apiUrl} \u521B\u5EFA API Key\uFF08\u9700\u8981 trade \u6743\u9650\uFF09
|
|
1028
|
+
|
|
1029
|
+
`);
|
|
1030
|
+
try {
|
|
1031
|
+
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
1032
|
+
spawnSync(opener, [apiUrl], { stdio: "ignore" });
|
|
1033
|
+
} catch {
|
|
1034
|
+
}
|
|
1035
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1036
|
+
try {
|
|
1037
|
+
const profileNameRaw = await prompt(rl, "Profile \u540D\u79F0 (\u9ED8\u8BA4: default): ");
|
|
1038
|
+
const profileName = profileNameRaw.trim() || "default";
|
|
1039
|
+
const apiKey = (await prompt(rl, "API Key: ")).trim();
|
|
1040
|
+
if (!apiKey) {
|
|
1041
|
+
process.stderr.write("\u9519\u8BEF: API Key \u4E0D\u80FD\u4E3A\u7A7A\n");
|
|
1042
|
+
process.exitCode = 1;
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
const secretKey = (await prompt(rl, "Secret Key: ")).trim();
|
|
1046
|
+
if (!secretKey) {
|
|
1047
|
+
process.stderr.write("\u9519\u8BEF: Secret Key \u4E0D\u80FD\u4E3A\u7A7A\n");
|
|
1048
|
+
process.exitCode = 1;
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
const passphrase = (await prompt(rl, "Passphrase: ")).trim();
|
|
1052
|
+
if (!passphrase) {
|
|
1053
|
+
process.stderr.write("\u9519\u8BEF: Passphrase \u4E0D\u80FD\u4E3A\u7A7A\n");
|
|
1054
|
+
process.exitCode = 1;
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
const demoRaw = (await prompt(rl, "\u4F7F\u7528\u6A21\u62DF\u76D8\uFF1F(Y/n) ")).trim().toLowerCase();
|
|
1058
|
+
const demo = demoRaw !== "n";
|
|
1059
|
+
if (demo) {
|
|
1060
|
+
process.stdout.write("\u5DF2\u9009\u62E9\u6A21\u62DF\u76D8\u6A21\u5F0F\uFF0C\u53EF\u968F\u65F6\u901A\u8FC7 okx config set \u5207\u6362\u4E3A\u5B9E\u76D8\u3002\n");
|
|
1061
|
+
}
|
|
1062
|
+
const config = readFullConfig();
|
|
1063
|
+
config.profiles[profileName] = { api_key: apiKey, secret_key: secretKey, passphrase, demo };
|
|
1064
|
+
const configPath = configFilePath();
|
|
1065
|
+
try {
|
|
1066
|
+
writeCliConfig(config);
|
|
1067
|
+
process.stdout.write(`
|
|
1068
|
+
\u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
1069
|
+
`);
|
|
1070
|
+
process.stdout.write(`\u4F7F\u7528\u65B9\u5F0F: okx --profile ${profileName} account balance
|
|
1071
|
+
`);
|
|
1072
|
+
if (!config.default_profile) {
|
|
1073
|
+
process.stdout.write(`\u63D0\u793A: \u8FD0\u884C okx config set default_profile ${profileName} \u53EF\u5C06\u5176\u8BBE\u4E3A\u9ED8\u8BA4
|
|
1074
|
+
`);
|
|
1075
|
+
}
|
|
1076
|
+
} catch (err) {
|
|
1077
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1078
|
+
const isPermission = err instanceof Error && "code" in err && (err.code === "EACCES" || err.code === "EPERM");
|
|
1079
|
+
process.stderr.write(`\u5199\u5165\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${message}
|
|
1080
|
+
`);
|
|
1081
|
+
if (isPermission) {
|
|
1082
|
+
process.stderr.write(`\u6743\u9650\u4E0D\u8DB3\uFF0C\u8BF7\u68C0\u67E5 ${configPath} \u53CA\u5176\u7236\u76EE\u5F55\u7684\u8BFB\u5199\u6743\u9650\u3002
|
|
1083
|
+
`);
|
|
1084
|
+
}
|
|
1085
|
+
process.stderr.write("\u8BF7\u624B\u52A8\u5C06\u4EE5\u4E0B\u5185\u5BB9\u5199\u5165 " + configPath + ":\n\n");
|
|
1086
|
+
process.stdout.write(stringify2(config) + "\n");
|
|
1087
|
+
process.exitCode = 1;
|
|
1088
|
+
}
|
|
1089
|
+
} finally {
|
|
1090
|
+
rl.close();
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// src/commands/client-setup.ts
|
|
1095
|
+
import * as fs from "fs";
|
|
1096
|
+
import * as path2 from "path";
|
|
1097
|
+
import * as os2 from "os";
|
|
1098
|
+
import * as readline from "readline";
|
|
1099
|
+
var CLIENTS = [
|
|
1100
|
+
{
|
|
1101
|
+
name: "Claude Desktop",
|
|
1102
|
+
configPath: path2.join(os2.homedir(), "Library/Application Support/Claude/claude_desktop_config.json"),
|
|
1103
|
+
mcpKey: "mcpServers"
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
name: "Cursor",
|
|
1107
|
+
configPath: path2.join(os2.homedir(), ".cursor/mcp.json"),
|
|
1108
|
+
mcpKey: "mcpServers"
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
name: "Windsurf",
|
|
1112
|
+
configPath: path2.join(os2.homedir(), ".codeium/windsurf/mcp_config.json"),
|
|
1113
|
+
mcpKey: "mcpServers"
|
|
1114
|
+
}
|
|
1115
|
+
];
|
|
1116
|
+
var MCP_ENTRY = {
|
|
1117
|
+
command: "okx-trade-mcp",
|
|
1118
|
+
args: ["--modules", "all"]
|
|
1119
|
+
};
|
|
1120
|
+
var MCP_SERVER_NAME = "okx-trade-mcp";
|
|
1121
|
+
function prompt2(rl, question) {
|
|
1122
|
+
return new Promise((resolve) => {
|
|
1123
|
+
rl.question(question, (answer) => {
|
|
1124
|
+
resolve(answer);
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
async function cmdSetupClients() {
|
|
1129
|
+
const detected = CLIENTS.filter((c) => fs.existsSync(c.configPath));
|
|
1130
|
+
if (detected.length === 0) {
|
|
1131
|
+
process.stdout.write(
|
|
1132
|
+
"No supported IDE/client installations detected.\nChecked:\n" + CLIENTS.map((c) => ` - ${c.name}: ${c.configPath}`).join("\n") + "\n"
|
|
1133
|
+
);
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
process.stdout.write(`Detected ${detected.length} client(s):
|
|
1137
|
+
`);
|
|
1138
|
+
for (const c of detected) {
|
|
1139
|
+
process.stdout.write(` - ${c.name}
|
|
1140
|
+
`);
|
|
1141
|
+
}
|
|
1142
|
+
process.stdout.write("\n");
|
|
1143
|
+
const rl = readline.createInterface({
|
|
1144
|
+
input: process.stdin,
|
|
1145
|
+
output: process.stdout
|
|
1146
|
+
});
|
|
1147
|
+
try {
|
|
1148
|
+
for (const client of detected) {
|
|
1149
|
+
const answer = await prompt2(rl, `Configure ${client.name}? (y/N) `);
|
|
1150
|
+
if (answer.trim().toLowerCase() !== "y") {
|
|
1151
|
+
process.stdout.write(` Skipped ${client.name}.
|
|
1152
|
+
`);
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
let data = { [client.mcpKey]: {} };
|
|
1156
|
+
if (fs.existsSync(client.configPath)) {
|
|
1157
|
+
const raw = fs.readFileSync(client.configPath, "utf-8");
|
|
1158
|
+
try {
|
|
1159
|
+
data = JSON.parse(raw);
|
|
1160
|
+
} catch {
|
|
1161
|
+
process.stderr.write(
|
|
1162
|
+
` Error: Failed to parse JSON for ${client.name} at ${client.configPath}. Skipping.
|
|
1163
|
+
`
|
|
1164
|
+
);
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
if (typeof data[client.mcpKey] !== "object" || data[client.mcpKey] === null) {
|
|
1169
|
+
data[client.mcpKey] = {};
|
|
1170
|
+
}
|
|
1171
|
+
const servers = data[client.mcpKey];
|
|
1172
|
+
if (Object.prototype.hasOwnProperty.call(servers, MCP_SERVER_NAME)) {
|
|
1173
|
+
process.stdout.write(` Already configured in ${client.name}. Skipping.
|
|
1174
|
+
`);
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
servers[MCP_SERVER_NAME] = MCP_ENTRY;
|
|
1178
|
+
const jsonOutput = JSON.stringify(data, null, 2);
|
|
1179
|
+
try {
|
|
1180
|
+
fs.writeFileSync(client.configPath, jsonOutput, "utf-8");
|
|
1181
|
+
process.stdout.write(` Configured ${client.name} successfully.
|
|
1182
|
+
`);
|
|
1183
|
+
} catch (err) {
|
|
1184
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1185
|
+
process.stderr.write(
|
|
1186
|
+
` Error: Failed to write config for ${client.name}: ${reason}
|
|
1187
|
+
Add the following to "${client.configPath}" manually:
|
|
1188
|
+
|
|
1189
|
+
"${MCP_SERVER_NAME}": ${JSON.stringify(MCP_ENTRY, null, 2).split("\n").join("\n ")}
|
|
1190
|
+
|
|
1191
|
+
`
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
} finally {
|
|
1196
|
+
rl.close();
|
|
1197
|
+
}
|
|
1198
|
+
process.stdout.write(
|
|
1199
|
+
"\nDone. Please restart any configured IDE/client for the changes to take effect.\n"
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
998
1202
|
|
|
999
1203
|
// src/index.ts
|
|
1000
1204
|
var _require = createRequire(import.meta.url);
|
|
@@ -1046,8 +1250,10 @@ Commands:
|
|
|
1046
1250
|
[--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]
|
|
1047
1251
|
swap algo cancel --instId <id> --algoId <id>
|
|
1048
1252
|
|
|
1253
|
+
config init
|
|
1049
1254
|
config show
|
|
1050
1255
|
config set <key> <value>
|
|
1256
|
+
config setup-clients
|
|
1051
1257
|
`);
|
|
1052
1258
|
}
|
|
1053
1259
|
async function main() {
|
|
@@ -1102,14 +1308,16 @@ async function main() {
|
|
|
1102
1308
|
const [module, action, ...rest] = positionals;
|
|
1103
1309
|
const json = values.json ?? false;
|
|
1104
1310
|
if (module === "config") {
|
|
1311
|
+
if (action === "init") return cmdConfigInit();
|
|
1105
1312
|
if (action === "show") return cmdConfigShow(json);
|
|
1106
1313
|
if (action === "set") return cmdConfigSet(rest[0], rest[1]);
|
|
1314
|
+
if (action === "setup-clients") return cmdSetupClients();
|
|
1107
1315
|
process.stderr.write(`Unknown config command: ${action}
|
|
1108
1316
|
`);
|
|
1109
1317
|
process.exitCode = 1;
|
|
1110
1318
|
return;
|
|
1111
1319
|
}
|
|
1112
|
-
const config = loadProfileConfig({ profile: values.profile });
|
|
1320
|
+
const config = loadProfileConfig({ profile: values.profile, userAgent: `okx-trade-cli/${CLI_VERSION}` });
|
|
1113
1321
|
const client = new OkxRestClient(config);
|
|
1114
1322
|
if (module === "market") {
|
|
1115
1323
|
if (action === "ticker") return cmdMarketTicker(client, rest[0], json);
|
|
@@ -1271,8 +1479,12 @@ async function main() {
|
|
|
1271
1479
|
main().catch((error) => {
|
|
1272
1480
|
const payload = toToolErrorPayload(error);
|
|
1273
1481
|
process.stderr.write(`Error: ${payload.message}
|
|
1482
|
+
`);
|
|
1483
|
+
if (payload.traceId) process.stderr.write(`TraceId: ${payload.traceId}
|
|
1274
1484
|
`);
|
|
1275
1485
|
if (payload.suggestion) process.stderr.write(`Hint: ${payload.suggestion}
|
|
1486
|
+
`);
|
|
1487
|
+
process.stderr.write(`Version: okx-trade-cli@${CLI_VERSION}
|
|
1276
1488
|
`);
|
|
1277
1489
|
process.exitCode = 1;
|
|
1278
1490
|
});
|