@okx_ai/okx-trade-cli 1.3.3-beta.2 → 1.3.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 +155 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,9 +21,12 @@ import {
|
|
|
21
21
|
import { homedir as homedir2 } from "os";
|
|
22
22
|
import { join as join2, dirname } from "path";
|
|
23
23
|
import { createHmac } from "crypto";
|
|
24
|
-
import { spawn, execFile as execFile2 } from "child_process";
|
|
24
|
+
import { spawn as spawn2, execFile as execFile2 } from "child_process";
|
|
25
25
|
import { homedir as homedir3 } from "os";
|
|
26
26
|
import { join as join3 } from "path";
|
|
27
|
+
import { spawn } from "child_process";
|
|
28
|
+
import { createServer } from "net";
|
|
29
|
+
import { randomBytes } from "crypto";
|
|
27
30
|
import fs from "fs";
|
|
28
31
|
import path from "path";
|
|
29
32
|
import os from "os";
|
|
@@ -1279,6 +1282,105 @@ var EXIT_CODES = {
|
|
|
1279
1282
|
NOT_LOGGED_IN: 2,
|
|
1280
1283
|
REFRESH_FAILED: 3
|
|
1281
1284
|
};
|
|
1285
|
+
function finalizeToken(code, token, resolve3, reject) {
|
|
1286
|
+
if (code === EXIT_CODES.SUCCESS) {
|
|
1287
|
+
if (!token) {
|
|
1288
|
+
reject(new AuthenticationError(
|
|
1289
|
+
"okx-auth returned empty token.",
|
|
1290
|
+
"Run `okx auth login` to re-authenticate."
|
|
1291
|
+
));
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
resolve3(token);
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
if (code === EXIT_CODES.NOT_LOGGED_IN) {
|
|
1298
|
+
reject(new NotLoggedInError());
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
|
|
1302
|
+
reject(new AuthenticationError(
|
|
1303
|
+
"okx-auth rejected the caller (unauthorized).",
|
|
1304
|
+
"Ensure you are running from a trusted OKX tool."
|
|
1305
|
+
));
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
if (code === EXIT_CODES.REFRESH_FAILED) {
|
|
1309
|
+
reject(new AuthenticationError(
|
|
1310
|
+
"Token refresh failed.",
|
|
1311
|
+
"Run `okx auth login` to re-authenticate."
|
|
1312
|
+
));
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1315
|
+
reject(new AuthenticationError(
|
|
1316
|
+
`okx-auth token exited with code ${code}.`,
|
|
1317
|
+
"Run `okx auth login` to re-authenticate."
|
|
1318
|
+
));
|
|
1319
|
+
}
|
|
1320
|
+
function spawnFailedError(err) {
|
|
1321
|
+
return new ConfigError(
|
|
1322
|
+
`Failed to spawn okx-auth: ${err.message}`,
|
|
1323
|
+
"Ensure the okx-auth binary exists and is executable."
|
|
1324
|
+
);
|
|
1325
|
+
}
|
|
1326
|
+
var WIN_PIPE_PREFIX = String.raw`\\.\pipe\okx-auth-`;
|
|
1327
|
+
function defaultWindowsPipeName() {
|
|
1328
|
+
return WIN_PIPE_PREFIX + randomBytes(32).toString("hex");
|
|
1329
|
+
}
|
|
1330
|
+
function execAuthTokenWindows(binPath, makePipeName = defaultWindowsPipeName) {
|
|
1331
|
+
return new Promise((resolve3, reject) => {
|
|
1332
|
+
const pipeName = makePipeName();
|
|
1333
|
+
const server = createServer();
|
|
1334
|
+
const chunks = [];
|
|
1335
|
+
let connectionMade = false;
|
|
1336
|
+
let pipeClosed = false;
|
|
1337
|
+
let exitCode;
|
|
1338
|
+
let settled = false;
|
|
1339
|
+
const settle = (fn) => {
|
|
1340
|
+
if (settled) return;
|
|
1341
|
+
settled = true;
|
|
1342
|
+
try {
|
|
1343
|
+
server.close();
|
|
1344
|
+
} catch {
|
|
1345
|
+
}
|
|
1346
|
+
fn();
|
|
1347
|
+
};
|
|
1348
|
+
const tryFinalize = () => {
|
|
1349
|
+
if (!pipeClosed || exitCode === void 0) return;
|
|
1350
|
+
const token = Buffer.concat(chunks).toString("utf-8").trim();
|
|
1351
|
+
settle(() => finalizeToken(exitCode, token, resolve3, reject));
|
|
1352
|
+
};
|
|
1353
|
+
server.on("connection", (socket) => {
|
|
1354
|
+
connectionMade = true;
|
|
1355
|
+
socket.on("data", (c) => chunks.push(c));
|
|
1356
|
+
socket.on("end", () => {
|
|
1357
|
+
pipeClosed = true;
|
|
1358
|
+
tryFinalize();
|
|
1359
|
+
});
|
|
1360
|
+
socket.on("error", (err) => settle(() => reject(spawnFailedError(err))));
|
|
1361
|
+
});
|
|
1362
|
+
server.on("error", (err) => settle(() => reject(spawnFailedError(err))));
|
|
1363
|
+
server.listen(pipeName, () => {
|
|
1364
|
+
let child;
|
|
1365
|
+
try {
|
|
1366
|
+
child = spawn(binPath, ["token"], {
|
|
1367
|
+
stdio: ["ignore", "ignore", "inherit"],
|
|
1368
|
+
env: { ...process.env, OKX_AUTH_TOKEN_PIPE: pipeName },
|
|
1369
|
+
windowsHide: true
|
|
1370
|
+
});
|
|
1371
|
+
} catch (err) {
|
|
1372
|
+
settle(() => reject(spawnFailedError(err)));
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
child.on("error", (err) => settle(() => reject(spawnFailedError(err))));
|
|
1376
|
+
child.on("close", (code) => {
|
|
1377
|
+
exitCode = code;
|
|
1378
|
+
if (!connectionMade) pipeClosed = true;
|
|
1379
|
+
tryFinalize();
|
|
1380
|
+
});
|
|
1381
|
+
});
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1282
1384
|
var EXEC_TIMEOUT_MS2 = 5e3;
|
|
1283
1385
|
var AUTH_BIN_DIR = join3(homedir3(), ".okx", "bin");
|
|
1284
1386
|
function getAuthBinaryPath() {
|
|
@@ -1290,8 +1392,11 @@ function getAuthBinaryPath() {
|
|
|
1290
1392
|
}
|
|
1291
1393
|
function execAuthToken() {
|
|
1292
1394
|
const binPath = getAuthBinaryPath();
|
|
1395
|
+
return process.platform === "win32" ? execAuthTokenWindows(binPath) : execAuthTokenUnix(binPath);
|
|
1396
|
+
}
|
|
1397
|
+
function execAuthTokenUnix(binPath) {
|
|
1293
1398
|
return new Promise((resolve3, reject) => {
|
|
1294
|
-
const child =
|
|
1399
|
+
const child = spawn2(binPath, ["token"], {
|
|
1295
1400
|
stdio: ["ignore", "ignore", "inherit", "pipe"]
|
|
1296
1401
|
// stdin stdout stderr fd3 (pipe)
|
|
1297
1402
|
});
|
|
@@ -1299,46 +1404,11 @@ function execAuthToken() {
|
|
|
1299
1404
|
const fd3 = child.stdio[3];
|
|
1300
1405
|
fd3.on("data", (chunk) => chunks.push(chunk));
|
|
1301
1406
|
child.on("error", (err) => {
|
|
1302
|
-
reject(
|
|
1303
|
-
`Failed to spawn okx-auth: ${err.message}`,
|
|
1304
|
-
"Ensure the okx-auth binary exists and is executable."
|
|
1305
|
-
));
|
|
1407
|
+
reject(spawnFailedError(err));
|
|
1306
1408
|
});
|
|
1307
1409
|
child.on("close", (code) => {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
if (!token) {
|
|
1311
|
-
reject(new AuthenticationError(
|
|
1312
|
-
"okx-auth returned empty token.",
|
|
1313
|
-
"Run `okx auth login` to re-authenticate."
|
|
1314
|
-
));
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
resolve3(token);
|
|
1318
|
-
return;
|
|
1319
|
-
}
|
|
1320
|
-
if (code === EXIT_CODES.NOT_LOGGED_IN) {
|
|
1321
|
-
reject(new NotLoggedInError());
|
|
1322
|
-
return;
|
|
1323
|
-
}
|
|
1324
|
-
if (code === EXIT_CODES.UNAUTHORIZED_CALLER) {
|
|
1325
|
-
reject(new AuthenticationError(
|
|
1326
|
-
"okx-auth rejected the caller (unauthorized).",
|
|
1327
|
-
"Ensure you are running from a trusted OKX tool."
|
|
1328
|
-
));
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
if (code === EXIT_CODES.REFRESH_FAILED) {
|
|
1332
|
-
reject(new AuthenticationError(
|
|
1333
|
-
"Token refresh failed.",
|
|
1334
|
-
"Run `okx auth login` to re-authenticate."
|
|
1335
|
-
));
|
|
1336
|
-
return;
|
|
1337
|
-
}
|
|
1338
|
-
reject(new AuthenticationError(
|
|
1339
|
-
`okx-auth token exited with code ${code}.`,
|
|
1340
|
-
"Run `okx auth login` to re-authenticate."
|
|
1341
|
-
));
|
|
1410
|
+
const token = Buffer.concat(chunks).toString("utf-8").trim();
|
|
1411
|
+
finalizeToken(code, token, resolve3, reject);
|
|
1342
1412
|
});
|
|
1343
1413
|
});
|
|
1344
1414
|
}
|
|
@@ -11830,12 +11900,47 @@ function sanitize(value) {
|
|
|
11830
11900
|
}
|
|
11831
11901
|
return value;
|
|
11832
11902
|
}
|
|
11903
|
+
var PRUNE_MARKER = ".last-prune.json";
|
|
11904
|
+
var PRUNE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
11905
|
+
var DEFAULT_RETENTION_DAYS = 30;
|
|
11906
|
+
var MS_PER_DAY = 864e5;
|
|
11907
|
+
var LOG_FILE_PATTERN = /^trade-.+\.log$/;
|
|
11908
|
+
function pruneOldLogs(logDir, retentionDays, now) {
|
|
11909
|
+
if (retentionDays === 0) return;
|
|
11910
|
+
try {
|
|
11911
|
+
const markerPath = path2.join(logDir, PRUNE_MARKER);
|
|
11912
|
+
let checkedAt = 0;
|
|
11913
|
+
try {
|
|
11914
|
+
const raw = fs2.readFileSync(markerPath, "utf8");
|
|
11915
|
+
const data = JSON.parse(raw);
|
|
11916
|
+
if (typeof data.checkedAt === "number") {
|
|
11917
|
+
checkedAt = data.checkedAt;
|
|
11918
|
+
}
|
|
11919
|
+
} catch {
|
|
11920
|
+
}
|
|
11921
|
+
if (checkedAt > 0 && now - checkedAt <= PRUNE_INTERVAL_MS) return;
|
|
11922
|
+
const cutoff = now - retentionDays * MS_PER_DAY;
|
|
11923
|
+
for (const name of fs2.readdirSync(logDir).filter((f) => LOG_FILE_PATTERN.test(f))) {
|
|
11924
|
+
try {
|
|
11925
|
+
if (fs2.statSync(path2.join(logDir, name)).mtimeMs < cutoff) {
|
|
11926
|
+
fs2.unlinkSync(path2.join(logDir, name));
|
|
11927
|
+
}
|
|
11928
|
+
} catch {
|
|
11929
|
+
}
|
|
11930
|
+
}
|
|
11931
|
+
fs2.writeFileSync(markerPath, JSON.stringify({ checkedAt: now }), "utf8");
|
|
11932
|
+
} catch {
|
|
11933
|
+
}
|
|
11934
|
+
}
|
|
11833
11935
|
var TradeLogger = class {
|
|
11834
11936
|
logLevel;
|
|
11835
11937
|
logDir;
|
|
11836
11938
|
constructor(logLevel = "info", logDir) {
|
|
11837
11939
|
this.logLevel = logLevel;
|
|
11838
11940
|
this.logDir = logDir ?? path2.join(os2.homedir(), ".okx", "logs");
|
|
11941
|
+
const parsed = parseInt(process.env.OKX_LOG_RETENTION_DAYS ?? "", 10);
|
|
11942
|
+
const retentionDays = isNaN(parsed) || parsed < 0 ? DEFAULT_RETENTION_DAYS : parsed;
|
|
11943
|
+
pruneOldLogs(this.logDir, retentionDays, Date.now());
|
|
11839
11944
|
}
|
|
11840
11945
|
getLogPath(date) {
|
|
11841
11946
|
const d = date ?? /* @__PURE__ */ new Date();
|
|
@@ -12472,7 +12577,7 @@ function clearAuthBinaryCache() {
|
|
|
12472
12577
|
}
|
|
12473
12578
|
|
|
12474
12579
|
// src/commands/auth.ts
|
|
12475
|
-
import { spawn as
|
|
12580
|
+
import { spawn as spawn3 } from "child_process";
|
|
12476
12581
|
import readline from "readline";
|
|
12477
12582
|
|
|
12478
12583
|
// src/formatter.ts
|
|
@@ -12568,7 +12673,7 @@ function markFailedIfSCodeError(data) {
|
|
|
12568
12673
|
function runOkxAuth(args) {
|
|
12569
12674
|
const binPath = getAuthBinaryPath();
|
|
12570
12675
|
return new Promise((resolve3, reject) => {
|
|
12571
|
-
const child =
|
|
12676
|
+
const child = spawn3(binPath, args, {
|
|
12572
12677
|
stdio: "inherit"
|
|
12573
12678
|
});
|
|
12574
12679
|
child.on("error", (err) => {
|
|
@@ -12582,7 +12687,7 @@ function runOkxAuth(args) {
|
|
|
12582
12687
|
function runOkxAuthCapture(args) {
|
|
12583
12688
|
const binPath = getAuthBinaryPath();
|
|
12584
12689
|
return new Promise((resolve3, reject) => {
|
|
12585
|
-
const child =
|
|
12690
|
+
const child = spawn3(binPath, args, {
|
|
12586
12691
|
stdio: ["inherit", "pipe", "inherit"]
|
|
12587
12692
|
});
|
|
12588
12693
|
const chunks = [];
|
|
@@ -12929,7 +13034,7 @@ function sanitize2(value) {
|
|
|
12929
13034
|
import fs5 from "fs";
|
|
12930
13035
|
import path4 from "path";
|
|
12931
13036
|
import os4 from "os";
|
|
12932
|
-
import { spawnSync, spawn as
|
|
13037
|
+
import { spawnSync, spawn as spawn4 } from "child_process";
|
|
12933
13038
|
import { createRequire as createRequire2 } from "module";
|
|
12934
13039
|
import { fileURLToPath } from "url";
|
|
12935
13040
|
var _require2 = createRequire2(import.meta.url);
|
|
@@ -13263,7 +13368,7 @@ async function checkStdioHandshake(entryPath, report) {
|
|
|
13263
13368
|
clearTimeout(timer);
|
|
13264
13369
|
resolve3(passed);
|
|
13265
13370
|
};
|
|
13266
|
-
const child =
|
|
13371
|
+
const child = spawn4(process.execPath, [entryPath], {
|
|
13267
13372
|
stdio: ["pipe", "pipe", "pipe"],
|
|
13268
13373
|
env: { ...process.env }
|
|
13269
13374
|
});
|
|
@@ -13382,7 +13487,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
13382
13487
|
|
|
13383
13488
|
// src/commands/diagnose.ts
|
|
13384
13489
|
var CLI_VERSION = readCliVersion();
|
|
13385
|
-
var GIT_HASH = true ? "
|
|
13490
|
+
var GIT_HASH = true ? "e6ad1d1e" : "dev";
|
|
13386
13491
|
function maskKey2(key) {
|
|
13387
13492
|
if (!key) return "(not set)";
|
|
13388
13493
|
if (key.length <= 8) return "****";
|
|
@@ -14690,7 +14795,7 @@ var CLI_REGISTRY = {
|
|
|
14690
14795
|
commands: {
|
|
14691
14796
|
"traders-by-filter": {
|
|
14692
14797
|
toolName: "smartmoney_get_traders_by_filter",
|
|
14693
|
-
usage: "okx smartmoney traders-by-filter [--updateTime <
|
|
14798
|
+
usage: "okx smartmoney traders-by-filter [--updateTime <yyyyMMddHHmm UTC+8>] [--sortBy <pnl|pnlRatio, default pnl>] [--period <3|7|30|90, default 90>] [--minPnl <n>] [--minWinRate <r>] [--maxDrawdown <r>] [--minAum <n>] [--after <authorId>] [--before <authorId>] [--limit <n, default 10>] [--json]",
|
|
14694
14799
|
description: "Leaderboard of top smart-money traders, ranked and filtered by pool conditions"
|
|
14695
14800
|
},
|
|
14696
14801
|
"performance-by-trader": {
|
|
@@ -18868,12 +18973,12 @@ function filterByStrike(data, ref) {
|
|
|
18868
18973
|
});
|
|
18869
18974
|
}
|
|
18870
18975
|
function filterByTerm(data, termDays, minTermDays, maxTermDays) {
|
|
18871
|
-
const
|
|
18976
|
+
const MS_PER_DAY2 = 864e5;
|
|
18872
18977
|
return data.filter((r) => {
|
|
18873
18978
|
const exp = Number(r["expTime"]);
|
|
18874
18979
|
const start = Number(r["interestAccrualTime"]);
|
|
18875
18980
|
if (!exp || !start) return false;
|
|
18876
|
-
const days = Math.round((exp - start) /
|
|
18981
|
+
const days = Math.round((exp - start) / MS_PER_DAY2);
|
|
18877
18982
|
if (termDays !== void 0 && days !== termDays) return false;
|
|
18878
18983
|
if (minTermDays !== void 0 && days < minTermDays) return false;
|
|
18879
18984
|
if (maxTermDays !== void 0 && days > maxTermDays) return false;
|
|
@@ -19868,7 +19973,7 @@ async function cmdEventCancel(run, opts) {
|
|
|
19868
19973
|
// src/index.ts
|
|
19869
19974
|
var _require3 = createRequire3(import.meta.url);
|
|
19870
19975
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
19871
|
-
var GIT_HASH2 = true ? "
|
|
19976
|
+
var GIT_HASH2 = true ? "e6ad1d1e" : "dev";
|
|
19872
19977
|
function handlePilotCommand(action, json, force, binaryPath) {
|
|
19873
19978
|
if (action === "status") return cmdPilotStatus(json, binaryPath);
|
|
19874
19979
|
if (action === "install") return cmdPilotInstall(json, binaryPath);
|