@okx_ai/okx-trade-cli 1.2.8-beta.1 → 1.2.8-beta.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 +157 -86
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { createRequire as createRequire3 } from "module";
|
|
5
5
|
|
|
6
6
|
// ../core/dist/index.js
|
|
7
|
-
import {
|
|
7
|
+
import { ProxyAgent } from "undici";
|
|
8
8
|
import { createHmac } from "crypto";
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
@@ -847,13 +847,6 @@ import * as fs3 from "fs";
|
|
|
847
847
|
import * as path3 from "path";
|
|
848
848
|
import * as os3 from "os";
|
|
849
849
|
import { execFileSync } from "child_process";
|
|
850
|
-
async function resolveDoh(_domain) {
|
|
851
|
-
return {
|
|
852
|
-
ip: "47.242.161.22",
|
|
853
|
-
host: "okexweb.qqhrss.com",
|
|
854
|
-
ttl: 120
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
850
|
function getNow() {
|
|
858
851
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
859
852
|
}
|
|
@@ -1072,61 +1065,12 @@ var OkxRestClient = class {
|
|
|
1072
1065
|
config;
|
|
1073
1066
|
rateLimiter;
|
|
1074
1067
|
dispatcher;
|
|
1075
|
-
|
|
1076
|
-
dohResolverFn;
|
|
1077
|
-
dohResolved = false;
|
|
1078
|
-
dohNode = null;
|
|
1079
|
-
dohAgent = null;
|
|
1080
|
-
dohBaseUrl = null;
|
|
1081
|
-
/**
|
|
1082
|
-
* @param config - OKX API client configuration
|
|
1083
|
-
* @param options - Optional overrides (e.g. custom DoH resolver for testing).
|
|
1084
|
-
* Pass `{ resolveDoh: null }` to disable DoH entirely.
|
|
1085
|
-
*/
|
|
1086
|
-
constructor(config, options) {
|
|
1068
|
+
constructor(config) {
|
|
1087
1069
|
this.config = config;
|
|
1088
1070
|
this.rateLimiter = new RateLimiter(3e4, config.verbose);
|
|
1089
1071
|
if (config.proxyUrl) {
|
|
1090
1072
|
this.dispatcher = new ProxyAgent(config.proxyUrl);
|
|
1091
1073
|
}
|
|
1092
|
-
this.dohResolverFn = options?.resolveDoh !== void 0 ? options.resolveDoh : resolveDoh;
|
|
1093
|
-
}
|
|
1094
|
-
/**
|
|
1095
|
-
* Lazily resolve the DoH proxy node on the first request.
|
|
1096
|
-
* Skipped entirely when the user has configured proxy_url or DoH is disabled.
|
|
1097
|
-
* On failure, silently falls back to direct connection.
|
|
1098
|
-
*/
|
|
1099
|
-
async ensureDoh() {
|
|
1100
|
-
if (this.dohResolved || this.dispatcher || !this.dohResolverFn) return;
|
|
1101
|
-
this.dohResolved = true;
|
|
1102
|
-
try {
|
|
1103
|
-
const { hostname, protocol } = new URL(this.config.baseUrl);
|
|
1104
|
-
const node = await this.dohResolverFn(hostname);
|
|
1105
|
-
if (node) {
|
|
1106
|
-
this.dohNode = node;
|
|
1107
|
-
this.dohBaseUrl = `${protocol}//${node.host}`;
|
|
1108
|
-
this.dohAgent = new Agent({
|
|
1109
|
-
connect: {
|
|
1110
|
-
lookup: (_hostname, options, callback) => {
|
|
1111
|
-
if (options?.all) {
|
|
1112
|
-
callback(null, [{ address: node.ip, family: 4 }]);
|
|
1113
|
-
} else {
|
|
1114
|
-
callback(null, node.ip, 4);
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
});
|
|
1119
|
-
if (this.config.verbose) {
|
|
1120
|
-
vlog(`DoH proxy active: ${hostname} \u2192 ${node.host} (${node.ip}), ttl=${node.ttl}s`);
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
} catch (err) {
|
|
1124
|
-
if (this.config.verbose) {
|
|
1125
|
-
const cause = err instanceof Error ? err.message : String(err);
|
|
1126
|
-
vlog(`DoH resolution failed, falling back to direct: ${cause}`);
|
|
1127
|
-
}
|
|
1128
|
-
this.dohNode = null;
|
|
1129
|
-
}
|
|
1130
1074
|
}
|
|
1131
1075
|
logRequest(method, url, auth) {
|
|
1132
1076
|
if (!this.config.verbose) return;
|
|
@@ -1270,11 +1214,9 @@ var OkxRestClient = class {
|
|
|
1270
1214
|
};
|
|
1271
1215
|
}
|
|
1272
1216
|
async request(reqConfig) {
|
|
1273
|
-
await this.ensureDoh();
|
|
1274
1217
|
const queryString = buildQueryString(reqConfig.query);
|
|
1275
1218
|
const requestPath = queryString.length > 0 ? `${reqConfig.path}?${queryString}` : reqConfig.path;
|
|
1276
|
-
const
|
|
1277
|
-
const url = `${baseUrl}${requestPath}`;
|
|
1219
|
+
const url = `${this.config.baseUrl}${requestPath}`;
|
|
1278
1220
|
const bodyJson = reqConfig.body ? JSON.stringify(reqConfig.body) : "";
|
|
1279
1221
|
const timestamp = getNow();
|
|
1280
1222
|
this.logRequest(reqConfig.method, url, reqConfig.auth);
|
|
@@ -1285,9 +1227,7 @@ var OkxRestClient = class {
|
|
|
1285
1227
|
"Content-Type": "application/json",
|
|
1286
1228
|
Accept: "application/json"
|
|
1287
1229
|
});
|
|
1288
|
-
if (this.
|
|
1289
|
-
headers.set("User-Agent", "OKX/2.7.2");
|
|
1290
|
-
} else if (this.config.userAgent) {
|
|
1230
|
+
if (this.config.userAgent) {
|
|
1291
1231
|
headers.set("User-Agent", this.config.userAgent);
|
|
1292
1232
|
}
|
|
1293
1233
|
if (reqConfig.auth === "private") {
|
|
@@ -1307,8 +1247,6 @@ var OkxRestClient = class {
|
|
|
1307
1247
|
};
|
|
1308
1248
|
if (this.dispatcher) {
|
|
1309
1249
|
fetchOptions.dispatcher = this.dispatcher;
|
|
1310
|
-
} else if (this.dohAgent) {
|
|
1311
|
-
fetchOptions.dispatcher = this.dohAgent;
|
|
1312
1250
|
}
|
|
1313
1251
|
response = await fetch(url, fetchOptions);
|
|
1314
1252
|
} catch (error) {
|
|
@@ -7037,6 +6975,22 @@ function isNewerVersion(current, latest) {
|
|
|
7037
6975
|
if (lMin !== cMin) return lMin > cMin;
|
|
7038
6976
|
return lPat > cPat;
|
|
7039
6977
|
}
|
|
6978
|
+
async function fetchDistTags(packageName) {
|
|
6979
|
+
try {
|
|
6980
|
+
const controller = new AbortController();
|
|
6981
|
+
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
6982
|
+
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
|
|
6983
|
+
signal: controller.signal,
|
|
6984
|
+
headers: { accept: "application/json" }
|
|
6985
|
+
});
|
|
6986
|
+
clearTimeout(timeout);
|
|
6987
|
+
if (!res.ok) return null;
|
|
6988
|
+
const data = await res.json();
|
|
6989
|
+
return data["dist-tags"] ?? null;
|
|
6990
|
+
} catch {
|
|
6991
|
+
return null;
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
7040
6994
|
async function fetchLatestVersion(packageName) {
|
|
7041
6995
|
try {
|
|
7042
6996
|
const controller = new AbortController();
|
|
@@ -7838,7 +7792,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7838
7792
|
|
|
7839
7793
|
// src/commands/diagnose.ts
|
|
7840
7794
|
var CLI_VERSION = readCliVersion();
|
|
7841
|
-
var GIT_HASH = true ? "
|
|
7795
|
+
var GIT_HASH = true ? "43f321d" : "dev";
|
|
7842
7796
|
function maskKey2(key) {
|
|
7843
7797
|
if (!key) return "(not set)";
|
|
7844
7798
|
if (key.length <= 8) return "****";
|
|
@@ -8133,6 +8087,109 @@ async function runCliChecks(config, profile, outputPath) {
|
|
|
8133
8087
|
writeReportIfRequested(report, outputPath);
|
|
8134
8088
|
}
|
|
8135
8089
|
|
|
8090
|
+
// src/commands/upgrade.ts
|
|
8091
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
8092
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
8093
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
8094
|
+
import { homedir as homedir4 } from "os";
|
|
8095
|
+
var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
|
|
8096
|
+
var CACHE_FILE2 = join4(homedir4(), ".okx", "last_check");
|
|
8097
|
+
var THROTTLE_MS = 12 * 60 * 60 * 1e3;
|
|
8098
|
+
var NPM_BIN = join4(dirname3(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
|
|
8099
|
+
function readLastCheck() {
|
|
8100
|
+
try {
|
|
8101
|
+
return parseInt(readFileSync4(CACHE_FILE2, "utf-8").trim(), 10) || 0;
|
|
8102
|
+
} catch {
|
|
8103
|
+
return 0;
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8106
|
+
function writeLastCheck() {
|
|
8107
|
+
try {
|
|
8108
|
+
mkdirSync4(join4(homedir4(), ".okx"), { recursive: true });
|
|
8109
|
+
writeFileSync4(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
|
|
8110
|
+
} catch {
|
|
8111
|
+
}
|
|
8112
|
+
}
|
|
8113
|
+
function printResult(result, json) {
|
|
8114
|
+
if (json) {
|
|
8115
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
8116
|
+
} else {
|
|
8117
|
+
switch (result.status) {
|
|
8118
|
+
case "up-to-date":
|
|
8119
|
+
process.stderr.write(`[ok] Already up to date: ${result.currentVersion}
|
|
8120
|
+
`);
|
|
8121
|
+
break;
|
|
8122
|
+
case "update-available":
|
|
8123
|
+
process.stderr.write(
|
|
8124
|
+
`[info] Update available: ${result.currentVersion} \u2192 ${result.latestVersion}
|
|
8125
|
+
Run: okx upgrade
|
|
8126
|
+
`
|
|
8127
|
+
);
|
|
8128
|
+
break;
|
|
8129
|
+
case "updated":
|
|
8130
|
+
process.stderr.write(`[ok] Upgraded: ${result.currentVersion} \u2192 ${result.latestVersion}
|
|
8131
|
+
`);
|
|
8132
|
+
break;
|
|
8133
|
+
case "error":
|
|
8134
|
+
process.stderr.write(`[error] Failed to fetch latest version from npm registry
|
|
8135
|
+
`);
|
|
8136
|
+
break;
|
|
8137
|
+
}
|
|
8138
|
+
}
|
|
8139
|
+
}
|
|
8140
|
+
function isThrottled(options) {
|
|
8141
|
+
if (options.force || options.check) return false;
|
|
8142
|
+
return Date.now() - readLastCheck() * 1e3 < THROTTLE_MS;
|
|
8143
|
+
}
|
|
8144
|
+
async function resolveLatestVersion(beta) {
|
|
8145
|
+
if (beta) {
|
|
8146
|
+
const tags = await fetchDistTags("@okx_ai/okx-trade-cli");
|
|
8147
|
+
return tags?.["next"] ?? tags?.["latest"] ?? null;
|
|
8148
|
+
}
|
|
8149
|
+
return fetchLatestVersion("@okx_ai/okx-trade-cli");
|
|
8150
|
+
}
|
|
8151
|
+
function runNpmInstall(json) {
|
|
8152
|
+
const result = spawnSync2(NPM_BIN, ["install", "-g", ...PACKAGES], {
|
|
8153
|
+
stdio: json ? ["inherit", "ignore", process.stderr] : "inherit",
|
|
8154
|
+
shell: false
|
|
8155
|
+
});
|
|
8156
|
+
return result.status === 0;
|
|
8157
|
+
}
|
|
8158
|
+
async function cmdUpgrade(currentVersion, options, json) {
|
|
8159
|
+
if (isThrottled(options)) {
|
|
8160
|
+
if (json) {
|
|
8161
|
+
process.stdout.write(
|
|
8162
|
+
JSON.stringify({ currentVersion, latestVersion: currentVersion, status: "up-to-date", updated: false }) + "\n"
|
|
8163
|
+
);
|
|
8164
|
+
}
|
|
8165
|
+
return;
|
|
8166
|
+
}
|
|
8167
|
+
const latestVersion = await resolveLatestVersion(options.beta ?? false);
|
|
8168
|
+
if (!latestVersion) {
|
|
8169
|
+
printResult({ currentVersion, latestVersion: "unknown", status: "error", updated: false }, json);
|
|
8170
|
+
process.exitCode = 1;
|
|
8171
|
+
return;
|
|
8172
|
+
}
|
|
8173
|
+
const stableCurrentVersion = currentVersion.split(/[-+]/)[0] ?? currentVersion;
|
|
8174
|
+
const needsUpdate = options.force || isNewerVersion(stableCurrentVersion, latestVersion);
|
|
8175
|
+
if (!needsUpdate) {
|
|
8176
|
+
if (!options.check) writeLastCheck();
|
|
8177
|
+
printResult({ currentVersion, latestVersion, status: "up-to-date", updated: false }, json);
|
|
8178
|
+
return;
|
|
8179
|
+
}
|
|
8180
|
+
if (options.check) {
|
|
8181
|
+
printResult({ currentVersion, latestVersion, status: "update-available", updated: false }, json);
|
|
8182
|
+
return;
|
|
8183
|
+
}
|
|
8184
|
+
if (runNpmInstall(json)) {
|
|
8185
|
+
writeLastCheck();
|
|
8186
|
+
printResult({ currentVersion, latestVersion, status: "updated", updated: true }, json);
|
|
8187
|
+
} else {
|
|
8188
|
+
printResult({ currentVersion, latestVersion, status: "error", updated: false }, json);
|
|
8189
|
+
process.exitCode = 1;
|
|
8190
|
+
}
|
|
8191
|
+
}
|
|
8192
|
+
|
|
8136
8193
|
// src/config/loader.ts
|
|
8137
8194
|
function loadProfileConfig(opts) {
|
|
8138
8195
|
return loadConfig({
|
|
@@ -8735,6 +8792,10 @@ var HELP_TREE = {
|
|
|
8735
8792
|
diagnose: {
|
|
8736
8793
|
description: "Run network / MCP server diagnostics",
|
|
8737
8794
|
usage: "okx diagnose [--cli | --mcp | --all] [--profile <name>] [--demo] [--output <file>]"
|
|
8795
|
+
},
|
|
8796
|
+
upgrade: {
|
|
8797
|
+
description: "Upgrade okx CLI and MCP server to the latest stable version",
|
|
8798
|
+
usage: "okx upgrade [--check] [--beta] [--force] [--json]"
|
|
8738
8799
|
}
|
|
8739
8800
|
};
|
|
8740
8801
|
function printGlobalHelp() {
|
|
@@ -8984,6 +9045,9 @@ var CLI_OPTIONS = {
|
|
|
8984
9045
|
// audit
|
|
8985
9046
|
since: { type: "string" },
|
|
8986
9047
|
tool: { type: "string" },
|
|
9048
|
+
// upgrade
|
|
9049
|
+
beta: { type: "boolean", default: false },
|
|
9050
|
+
check: { type: "boolean", default: false },
|
|
8987
9051
|
// config profile
|
|
8988
9052
|
force: { type: "boolean", default: false },
|
|
8989
9053
|
// onchain-earn
|
|
@@ -9325,14 +9389,17 @@ async function cmdAccountBalance(run, ccy, json) {
|
|
|
9325
9389
|
const data = getData2(result);
|
|
9326
9390
|
if (json) return printJson(data);
|
|
9327
9391
|
const details = data?.[0]?.["details"] ?? [];
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9392
|
+
const rows = details.filter((d) => Number(d["eq"]) > 0).map((d) => ({
|
|
9393
|
+
currency: d["ccy"],
|
|
9394
|
+
equity: d["eq"],
|
|
9395
|
+
available: d["availEq"],
|
|
9396
|
+
frozen: d["frozenBal"]
|
|
9397
|
+
}));
|
|
9398
|
+
if (rows.length === 0 && data?.[0]) {
|
|
9399
|
+
printTable([{ currency: "Total", equity: data[0]["totalEq"] ?? "0", available: data[0]["adjEq"] ?? "0", frozen: "-" }]);
|
|
9400
|
+
return;
|
|
9401
|
+
}
|
|
9402
|
+
printTable(rows);
|
|
9336
9403
|
}
|
|
9337
9404
|
async function cmdAccountAssetBalance(run, ccy, json, showValuation) {
|
|
9338
9405
|
const result = await run("account_get_asset_balance", {
|
|
@@ -9341,14 +9408,17 @@ async function cmdAccountAssetBalance(run, ccy, json, showValuation) {
|
|
|
9341
9408
|
});
|
|
9342
9409
|
const data = result.data ?? [];
|
|
9343
9410
|
if (json) return printJson(showValuation ? { data, valuation: result.valuation } : data);
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9411
|
+
const assetRows = data.filter((r) => Number(r["bal"]) > 0).map((r) => ({
|
|
9412
|
+
ccy: r["ccy"],
|
|
9413
|
+
bal: r["bal"],
|
|
9414
|
+
availBal: r["availBal"],
|
|
9415
|
+
frozenBal: r["frozenBal"]
|
|
9416
|
+
}));
|
|
9417
|
+
if (assetRows.length === 0 && data.length > 0) {
|
|
9418
|
+
outputLine("Total balance: 0");
|
|
9419
|
+
} else {
|
|
9420
|
+
printTable(assetRows);
|
|
9421
|
+
}
|
|
9352
9422
|
if (showValuation && result.valuation) {
|
|
9353
9423
|
const valuationData = result.valuation ?? [];
|
|
9354
9424
|
outputLine("");
|
|
@@ -10653,7 +10723,7 @@ function writeCliConfig(config) {
|
|
|
10653
10723
|
|
|
10654
10724
|
// src/commands/config.ts
|
|
10655
10725
|
import { createInterface } from "readline";
|
|
10656
|
-
import { spawnSync as
|
|
10726
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
10657
10727
|
var messages = {
|
|
10658
10728
|
en: {
|
|
10659
10729
|
title: "OKX Trade CLI \u2014 Configuration Wizard",
|
|
@@ -10795,7 +10865,7 @@ function tryOpenUrl(url) {
|
|
|
10795
10865
|
} else {
|
|
10796
10866
|
opener = "xdg-open";
|
|
10797
10867
|
}
|
|
10798
|
-
|
|
10868
|
+
spawnSync3(opener, [url], { stdio: "ignore", shell: process.platform === "win32" });
|
|
10799
10869
|
} catch {
|
|
10800
10870
|
}
|
|
10801
10871
|
}
|
|
@@ -11693,7 +11763,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
11693
11763
|
// src/index.ts
|
|
11694
11764
|
var _require3 = createRequire3(import.meta.url);
|
|
11695
11765
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
11696
|
-
var GIT_HASH2 = true ? "
|
|
11766
|
+
var GIT_HASH2 = true ? "43f321d" : "dev";
|
|
11697
11767
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
11698
11768
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
11699
11769
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -12485,6 +12555,7 @@ async function main() {
|
|
|
12485
12555
|
const json = v.json ?? false;
|
|
12486
12556
|
if (module === "config") return handleConfigCommand(action, rest, json, v.lang, v.force);
|
|
12487
12557
|
if (module === "setup") return handleSetupCommand(v);
|
|
12558
|
+
if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
|
|
12488
12559
|
if (module === "diagnose") {
|
|
12489
12560
|
let config2;
|
|
12490
12561
|
try {
|