@okx_ai/okx-trade-cli 1.3.1-beta.3 → 1.3.1-beta.5
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 +923 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +9 -2
package/dist/index.js
CHANGED
|
@@ -876,6 +876,20 @@ import * as fs3 from "fs";
|
|
|
876
876
|
import * as path3 from "path";
|
|
877
877
|
import * as os3 from "os";
|
|
878
878
|
import { execFileSync } from "child_process";
|
|
879
|
+
import {
|
|
880
|
+
readFileSync as readFileSync7,
|
|
881
|
+
createWriteStream as createWriteStream2,
|
|
882
|
+
mkdirSync as mkdirSync8,
|
|
883
|
+
chmodSync,
|
|
884
|
+
existsSync as existsSync6,
|
|
885
|
+
unlinkSync as unlinkSync3,
|
|
886
|
+
renameSync as renameSync3
|
|
887
|
+
} from "fs";
|
|
888
|
+
import { createHash } from "crypto";
|
|
889
|
+
import { homedir as homedir7, platform, arch } from "os";
|
|
890
|
+
import { join as join9, dirname as dirname6 } from "path";
|
|
891
|
+
import { get as httpsGet } from "https";
|
|
892
|
+
import { get as httpGet } from "http";
|
|
879
893
|
var EXEC_TIMEOUT_MS = 3e4;
|
|
880
894
|
var ALLOWED_DOMAIN_RE = /^[\w.-]+\.okx\.com$/;
|
|
881
895
|
var DOH_BIN_DIR = join(homedir(), ".okx", "bin");
|
|
@@ -922,8 +936,10 @@ function execDohBinary(domain, exclude = [], userAgent) {
|
|
|
922
936
|
);
|
|
923
937
|
});
|
|
924
938
|
}
|
|
925
|
-
|
|
926
|
-
|
|
939
|
+
function getDefaultCachePath() {
|
|
940
|
+
return process.env.OKX_DOH_CACHE_PATH || join2(homedir2(), ".okx", "doh-cache.json");
|
|
941
|
+
}
|
|
942
|
+
function readCache(hostname, cachePath = getDefaultCachePath()) {
|
|
927
943
|
try {
|
|
928
944
|
const raw = readFileSync(cachePath, "utf-8");
|
|
929
945
|
const file = JSON.parse(raw);
|
|
@@ -932,7 +948,7 @@ function readCache(hostname, cachePath = DOH_CACHE_PATH) {
|
|
|
932
948
|
return null;
|
|
933
949
|
}
|
|
934
950
|
}
|
|
935
|
-
function writeCache(hostname, entry, cachePath =
|
|
951
|
+
function writeCache(hostname, entry, cachePath = getDefaultCachePath()) {
|
|
936
952
|
try {
|
|
937
953
|
const dir = dirname(cachePath);
|
|
938
954
|
mkdirSync(dir, { recursive: true });
|
|
@@ -1573,9 +1589,17 @@ var OkxRestClient = class _OkxRestClient {
|
|
|
1573
1589
|
headers.set("User-Agent", conn.userAgent);
|
|
1574
1590
|
}
|
|
1575
1591
|
const t0 = Date.now();
|
|
1576
|
-
|
|
1592
|
+
let response;
|
|
1593
|
+
try {
|
|
1594
|
+
response = await this.fetchBinary(path42, endpoint, headers, bodyJson, t0);
|
|
1595
|
+
} catch (error) {
|
|
1596
|
+
this.doh.handleNetworkFailure().catch(() => {
|
|
1597
|
+
});
|
|
1598
|
+
throw error;
|
|
1599
|
+
}
|
|
1577
1600
|
const elapsed = Date.now() - t0;
|
|
1578
1601
|
const traceId = extractTraceId(response.headers);
|
|
1602
|
+
this.doh.cacheDirectIfNeeded();
|
|
1579
1603
|
if (!response.ok) {
|
|
1580
1604
|
const text = await response.text();
|
|
1581
1605
|
this.logResponse(response.status, text.length, elapsed, traceId, String(response.status));
|
|
@@ -2106,6 +2130,30 @@ var MODULES = [
|
|
|
2106
2130
|
"skills"
|
|
2107
2131
|
];
|
|
2108
2132
|
var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES, "skills"];
|
|
2133
|
+
var SKILLS_MARKETPLACE_DESC = "OKX Skills Marketplace \u2014 search, install, and manage agent skills";
|
|
2134
|
+
var MODULE_DESCRIPTIONS = {
|
|
2135
|
+
market: "Market data (ticker, orderbook, candles, trades)",
|
|
2136
|
+
spot: "Spot trading (orders, algo orders)",
|
|
2137
|
+
swap: "Perpetual swap trading (orders, algo orders)",
|
|
2138
|
+
futures: "Futures trading (orders, positions, algo orders, leverage)",
|
|
2139
|
+
option: "Options trading (orders, positions, greeks)",
|
|
2140
|
+
account: "Account balance, positions, bills, and configuration",
|
|
2141
|
+
"earn.savings": "Simple Earn \u2014 flexible savings, fixed-term, and lending",
|
|
2142
|
+
"earn.onchain": "On-chain Earn \u2014 staking and DeFi products",
|
|
2143
|
+
"earn.dcd": "DCD (Dual Currency Deposit) \u2014 structured products with fixed yield",
|
|
2144
|
+
"earn.autoearn": "Auto-earn \u2014 automatically lend, stake, or earn on idle assets",
|
|
2145
|
+
"bot.grid": "Grid trading bot \u2014 create, monitor, and stop grid orders",
|
|
2146
|
+
"bot.dca": "DCA (Martingale) bot \u2014 spot or contract recurring buys",
|
|
2147
|
+
skills: SKILLS_MARKETPLACE_DESC,
|
|
2148
|
+
earn: "Earn products \u2014 Simple Earn, On-chain Earn, and DCD (Dual Currency Deposit)",
|
|
2149
|
+
bot: "Trading bot strategies (grid, dca)",
|
|
2150
|
+
config: "Manage CLI configuration profiles",
|
|
2151
|
+
setup: "Set up client integrations (Cursor, Windsurf, Claude, etc.)",
|
|
2152
|
+
doh: "Manage DoH (DNS-over-HTTPS) resolver binary",
|
|
2153
|
+
diagnose: "Run network / MCP server diagnostics",
|
|
2154
|
+
upgrade: "Upgrade okx CLI and MCP server to the latest stable version",
|
|
2155
|
+
skill: SKILLS_MARKETPLACE_DESC
|
|
2156
|
+
};
|
|
2109
2157
|
function registerAccountTools() {
|
|
2110
2158
|
return [
|
|
2111
2159
|
{
|
|
@@ -8439,13 +8487,13 @@ function findMsStoreClaudePath() {
|
|
|
8439
8487
|
}
|
|
8440
8488
|
function getConfigPath(client) {
|
|
8441
8489
|
const home = os3.homedir();
|
|
8442
|
-
const
|
|
8490
|
+
const platform2 = process.platform;
|
|
8443
8491
|
switch (client) {
|
|
8444
8492
|
case "claude-desktop":
|
|
8445
|
-
if (
|
|
8493
|
+
if (platform2 === "win32") {
|
|
8446
8494
|
return findMsStoreClaudePath() ?? path3.join(appData(), "Claude", CLAUDE_CONFIG_FILE);
|
|
8447
8495
|
}
|
|
8448
|
-
if (
|
|
8496
|
+
if (platform2 === "darwin") {
|
|
8449
8497
|
return path3.join(home, "Library", "Application Support", "Claude", CLAUDE_CONFIG_FILE);
|
|
8450
8498
|
}
|
|
8451
8499
|
return path3.join(process.env.XDG_CONFIG_HOME ?? path3.join(home, ".config"), "Claude", CLAUDE_CONFIG_FILE);
|
|
@@ -8547,6 +8595,269 @@ function runSetup(options) {
|
|
|
8547
8595
|
`);
|
|
8548
8596
|
}
|
|
8549
8597
|
}
|
|
8598
|
+
var CDN_SOURCES = [
|
|
8599
|
+
{ host: "static.jingyunyilian.com", protocol: "https" },
|
|
8600
|
+
{ host: "static.okx.com", protocol: "https" },
|
|
8601
|
+
{ host: "static.coinall.ltd", protocol: "https" }
|
|
8602
|
+
];
|
|
8603
|
+
var CDN_PATH_PREFIX = "/upgradeapp/doh";
|
|
8604
|
+
var DOWNLOAD_TIMEOUT_MS = 3e4;
|
|
8605
|
+
function getPlatformDir() {
|
|
8606
|
+
const p = platform();
|
|
8607
|
+
const a = arch();
|
|
8608
|
+
const map = {
|
|
8609
|
+
"darwin-arm64": "darwin-arm64",
|
|
8610
|
+
"darwin-x64": "darwin-x64",
|
|
8611
|
+
"linux-x64": "linux-x64",
|
|
8612
|
+
"win32-x64": "win32-x64"
|
|
8613
|
+
};
|
|
8614
|
+
return map[`${p}-${a}`] ?? null;
|
|
8615
|
+
}
|
|
8616
|
+
function getBinaryName() {
|
|
8617
|
+
return platform() === "win32" ? "okx-doh-resolver.exe" : "okx-doh-resolver";
|
|
8618
|
+
}
|
|
8619
|
+
function hashFile(filePath) {
|
|
8620
|
+
const buf = readFileSync7(filePath);
|
|
8621
|
+
return {
|
|
8622
|
+
size: buf.byteLength,
|
|
8623
|
+
sha256: createHash("sha256").update(buf).digest("hex")
|
|
8624
|
+
};
|
|
8625
|
+
}
|
|
8626
|
+
function getDohStatus(binaryPath, opts) {
|
|
8627
|
+
const resolvedPath = binaryPath ?? getDohBinaryPath();
|
|
8628
|
+
const platformDir = getPlatformDir();
|
|
8629
|
+
if (!existsSync6(resolvedPath)) {
|
|
8630
|
+
return {
|
|
8631
|
+
binaryPath: resolvedPath,
|
|
8632
|
+
exists: false,
|
|
8633
|
+
platform: platformDir
|
|
8634
|
+
};
|
|
8635
|
+
}
|
|
8636
|
+
if (opts?.skipHash) {
|
|
8637
|
+
return {
|
|
8638
|
+
binaryPath: resolvedPath,
|
|
8639
|
+
exists: true,
|
|
8640
|
+
platform: platformDir
|
|
8641
|
+
};
|
|
8642
|
+
}
|
|
8643
|
+
const { size, sha256 } = hashFile(resolvedPath);
|
|
8644
|
+
return {
|
|
8645
|
+
binaryPath: resolvedPath,
|
|
8646
|
+
exists: true,
|
|
8647
|
+
platform: platformDir,
|
|
8648
|
+
fileSize: size,
|
|
8649
|
+
sha256
|
|
8650
|
+
};
|
|
8651
|
+
}
|
|
8652
|
+
async function fetchCdnChecksum(sources = CDN_SOURCES, timeoutMs = DOWNLOAD_TIMEOUT_MS) {
|
|
8653
|
+
const platformDir = getPlatformDir();
|
|
8654
|
+
if (!platformDir) return null;
|
|
8655
|
+
const checksumPath = `${CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
|
|
8656
|
+
for (const { host, protocol } of sources) {
|
|
8657
|
+
try {
|
|
8658
|
+
const url = `${protocol}://${host}${checksumPath}`;
|
|
8659
|
+
const raw = await downloadText(url, timeoutMs);
|
|
8660
|
+
const data = JSON.parse(raw);
|
|
8661
|
+
if (typeof data.sha256 !== "string" || typeof data.size !== "number" || typeof data.target !== "string") {
|
|
8662
|
+
continue;
|
|
8663
|
+
}
|
|
8664
|
+
return {
|
|
8665
|
+
sha256: data.sha256,
|
|
8666
|
+
size: data.size,
|
|
8667
|
+
target: data.target,
|
|
8668
|
+
source: host
|
|
8669
|
+
};
|
|
8670
|
+
} catch {
|
|
8671
|
+
}
|
|
8672
|
+
}
|
|
8673
|
+
return null;
|
|
8674
|
+
}
|
|
8675
|
+
async function fetchAndValidateChecksum(host, protocol, checksumPath, platformDir, timeoutMs, onProgress) {
|
|
8676
|
+
const checksumUrl = `${protocol}://${host}${checksumPath}`;
|
|
8677
|
+
onProgress?.(`Fetching checksum from ${host}...`);
|
|
8678
|
+
const raw = await downloadText(checksumUrl, timeoutMs);
|
|
8679
|
+
const checksum = JSON.parse(raw);
|
|
8680
|
+
if (typeof checksum.sha256 !== "string" || typeof checksum.size !== "number" || typeof checksum.target !== "string") {
|
|
8681
|
+
throw new Error("Invalid checksum.json: missing sha256, size, or target");
|
|
8682
|
+
}
|
|
8683
|
+
if (checksum.target !== platformDir) {
|
|
8684
|
+
throw new Error(
|
|
8685
|
+
`Target mismatch: expected ${platformDir}, got ${checksum.target}`
|
|
8686
|
+
);
|
|
8687
|
+
}
|
|
8688
|
+
return { sha256: checksum.sha256, size: checksum.size, target: checksum.target };
|
|
8689
|
+
}
|
|
8690
|
+
async function downloadAndVerify(host, protocol, binaryPath, tmpPath, checksum, timeoutMs, onProgress) {
|
|
8691
|
+
const binaryUrl = `${protocol}://${host}${binaryPath}`;
|
|
8692
|
+
onProgress?.(`Downloading binary from ${host}...`);
|
|
8693
|
+
await download(binaryUrl, tmpPath, timeoutMs);
|
|
8694
|
+
const actual = hashFile(tmpPath);
|
|
8695
|
+
if (actual.size !== checksum.size) {
|
|
8696
|
+
throw new Error(
|
|
8697
|
+
`Size mismatch: expected ${checksum.size}, got ${actual.size}`
|
|
8698
|
+
);
|
|
8699
|
+
}
|
|
8700
|
+
if (actual.sha256 !== checksum.sha256) {
|
|
8701
|
+
throw new Error(
|
|
8702
|
+
`SHA-256 mismatch: expected ${checksum.sha256}, got ${actual.sha256}`
|
|
8703
|
+
);
|
|
8704
|
+
}
|
|
8705
|
+
}
|
|
8706
|
+
function atomicReplace(tmpPath, resolvedDest) {
|
|
8707
|
+
if (platform() === "win32") {
|
|
8708
|
+
try {
|
|
8709
|
+
unlinkSync3(resolvedDest);
|
|
8710
|
+
} catch {
|
|
8711
|
+
}
|
|
8712
|
+
}
|
|
8713
|
+
renameSync3(tmpPath, resolvedDest);
|
|
8714
|
+
if (platform() !== "win32") {
|
|
8715
|
+
chmodSync(resolvedDest, 493);
|
|
8716
|
+
}
|
|
8717
|
+
}
|
|
8718
|
+
function installPreChecks(destPath, sources) {
|
|
8719
|
+
if (!destPath && process.env.OKX_DOH_BINARY_PATH) {
|
|
8720
|
+
return { status: "up-to-date", source: "(env override)" };
|
|
8721
|
+
}
|
|
8722
|
+
if (!getPlatformDir()) {
|
|
8723
|
+
return { status: "failed", error: "Unsupported platform" };
|
|
8724
|
+
}
|
|
8725
|
+
if (sources.length === 0) {
|
|
8726
|
+
return { status: "failed", error: "No CDN sources available" };
|
|
8727
|
+
}
|
|
8728
|
+
return null;
|
|
8729
|
+
}
|
|
8730
|
+
function isLocalUpToDate(localHash, checksum) {
|
|
8731
|
+
return localHash !== null && localHash.size === checksum.size && localHash.sha256 === checksum.sha256;
|
|
8732
|
+
}
|
|
8733
|
+
async function installDohBinary(destPath, sources = CDN_SOURCES, onProgress) {
|
|
8734
|
+
const earlyResult = installPreChecks(destPath, sources);
|
|
8735
|
+
if (earlyResult) return earlyResult;
|
|
8736
|
+
const platformDir = getPlatformDir();
|
|
8737
|
+
const binaryName = getBinaryName();
|
|
8738
|
+
const resolvedDest = destPath ?? join9(homedir7(), ".okx", "bin", binaryName);
|
|
8739
|
+
const tmpPath = resolvedDest + ".tmp";
|
|
8740
|
+
mkdirSync8(dirname6(resolvedDest), { recursive: true });
|
|
8741
|
+
const localHash = existsSync6(resolvedDest) ? hashFile(resolvedDest) : null;
|
|
8742
|
+
const checksumPath = `${CDN_PATH_PREFIX}/${platformDir}/checksum.json`;
|
|
8743
|
+
const binaryPath = `${CDN_PATH_PREFIX}/${platformDir}/${binaryName}`;
|
|
8744
|
+
const errors = [];
|
|
8745
|
+
for (const { host, protocol } of sources) {
|
|
8746
|
+
try {
|
|
8747
|
+
const checksum = await fetchAndValidateChecksum(
|
|
8748
|
+
host,
|
|
8749
|
+
protocol,
|
|
8750
|
+
checksumPath,
|
|
8751
|
+
platformDir,
|
|
8752
|
+
DOWNLOAD_TIMEOUT_MS,
|
|
8753
|
+
onProgress
|
|
8754
|
+
);
|
|
8755
|
+
if (isLocalUpToDate(localHash, checksum)) {
|
|
8756
|
+
onProgress?.("Already up to date (checksum match)");
|
|
8757
|
+
return { status: "up-to-date", source: host };
|
|
8758
|
+
}
|
|
8759
|
+
await downloadAndVerify(host, protocol, binaryPath, tmpPath, checksum, DOWNLOAD_TIMEOUT_MS, onProgress);
|
|
8760
|
+
atomicReplace(tmpPath, resolvedDest);
|
|
8761
|
+
onProgress?.(`Downloaded and verified from ${host}`);
|
|
8762
|
+
return { status: "installed", source: host };
|
|
8763
|
+
} catch (err) {
|
|
8764
|
+
try {
|
|
8765
|
+
unlinkSync3(tmpPath);
|
|
8766
|
+
} catch {
|
|
8767
|
+
}
|
|
8768
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8769
|
+
errors.push(`${host}: ${msg}`);
|
|
8770
|
+
onProgress?.(`${host} failed: ${msg}`);
|
|
8771
|
+
}
|
|
8772
|
+
}
|
|
8773
|
+
return { status: "failed", error: `All CDN sources failed:
|
|
8774
|
+
${errors.join("\n")}` };
|
|
8775
|
+
}
|
|
8776
|
+
function removeDohBinary(binaryPath) {
|
|
8777
|
+
const resolvedPath = binaryPath ?? getDohBinaryPath();
|
|
8778
|
+
try {
|
|
8779
|
+
unlinkSync3(resolvedPath);
|
|
8780
|
+
return { status: "removed" };
|
|
8781
|
+
} catch (err) {
|
|
8782
|
+
if (err.code === "ENOENT") {
|
|
8783
|
+
return { status: "not-found" };
|
|
8784
|
+
}
|
|
8785
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8786
|
+
throw new Error(`Failed to remove ${resolvedPath}: ${msg}`);
|
|
8787
|
+
}
|
|
8788
|
+
}
|
|
8789
|
+
function isRedirect(statusCode) {
|
|
8790
|
+
return statusCode !== void 0 && statusCode >= 300 && statusCode < 400;
|
|
8791
|
+
}
|
|
8792
|
+
function validateRedirect(res, requestUrl, redirectCount, maxRedirects) {
|
|
8793
|
+
if (redirectCount > maxRedirects) {
|
|
8794
|
+
throw new Error(`Too many redirects (${maxRedirects})`);
|
|
8795
|
+
}
|
|
8796
|
+
const location = res.headers.location;
|
|
8797
|
+
if (requestUrl.startsWith("https") && !location.startsWith("https")) {
|
|
8798
|
+
throw new Error("Refused HTTPS \u2192 HTTP redirect downgrade");
|
|
8799
|
+
}
|
|
8800
|
+
return location;
|
|
8801
|
+
}
|
|
8802
|
+
function fetchResponse(url, timeoutMs) {
|
|
8803
|
+
return new Promise((resolve3, reject) => {
|
|
8804
|
+
let redirects = 0;
|
|
8805
|
+
const maxRedirects = 5;
|
|
8806
|
+
function doRequest(requestUrl) {
|
|
8807
|
+
const reqFn = requestUrl.startsWith("https") ? httpsGet : httpGet;
|
|
8808
|
+
const req = reqFn(requestUrl, { timeout: timeoutMs }, (res) => {
|
|
8809
|
+
if (isRedirect(res.statusCode) && res.headers.location) {
|
|
8810
|
+
redirects++;
|
|
8811
|
+
try {
|
|
8812
|
+
const location = validateRedirect(res, requestUrl, redirects, maxRedirects);
|
|
8813
|
+
res.resume();
|
|
8814
|
+
doRequest(location);
|
|
8815
|
+
} catch (err) {
|
|
8816
|
+
reject(err);
|
|
8817
|
+
}
|
|
8818
|
+
return;
|
|
8819
|
+
}
|
|
8820
|
+
if (res.statusCode !== 200) {
|
|
8821
|
+
reject(new Error(`HTTP ${res.statusCode ?? "unknown"}`));
|
|
8822
|
+
return;
|
|
8823
|
+
}
|
|
8824
|
+
resolve3(res);
|
|
8825
|
+
});
|
|
8826
|
+
req.on("error", reject);
|
|
8827
|
+
req.on("timeout", () => {
|
|
8828
|
+
req.destroy();
|
|
8829
|
+
reject(new Error("Download timed out"));
|
|
8830
|
+
});
|
|
8831
|
+
}
|
|
8832
|
+
doRequest(url);
|
|
8833
|
+
});
|
|
8834
|
+
}
|
|
8835
|
+
function download(url, destPath, timeoutMs) {
|
|
8836
|
+
return fetchResponse(url, timeoutMs).then(
|
|
8837
|
+
(res) => new Promise((resolve3, reject) => {
|
|
8838
|
+
const file = createWriteStream2(destPath);
|
|
8839
|
+
res.pipe(file);
|
|
8840
|
+
file.on("finish", () => file.close(() => resolve3()));
|
|
8841
|
+
file.on("error", (err) => {
|
|
8842
|
+
try {
|
|
8843
|
+
unlinkSync3(destPath);
|
|
8844
|
+
} catch {
|
|
8845
|
+
}
|
|
8846
|
+
reject(err);
|
|
8847
|
+
});
|
|
8848
|
+
})
|
|
8849
|
+
);
|
|
8850
|
+
}
|
|
8851
|
+
function downloadText(url, timeoutMs) {
|
|
8852
|
+
return fetchResponse(url, timeoutMs).then(
|
|
8853
|
+
(res) => new Promise((resolve3, reject) => {
|
|
8854
|
+
const chunks = [];
|
|
8855
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
8856
|
+
res.on("end", () => resolve3(Buffer.concat(chunks).toString("utf8")));
|
|
8857
|
+
res.on("error", reject);
|
|
8858
|
+
})
|
|
8859
|
+
);
|
|
8860
|
+
}
|
|
8550
8861
|
|
|
8551
8862
|
// src/commands/diagnose.ts
|
|
8552
8863
|
import dns from "dns/promises";
|
|
@@ -9179,7 +9490,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
9179
9490
|
|
|
9180
9491
|
// src/commands/diagnose.ts
|
|
9181
9492
|
var CLI_VERSION = readCliVersion();
|
|
9182
|
-
var GIT_HASH = true ? "
|
|
9493
|
+
var GIT_HASH = true ? "63a5613" : "dev";
|
|
9183
9494
|
function maskKey2(key) {
|
|
9184
9495
|
if (!key) return "(not set)";
|
|
9185
9496
|
if (key.length <= 8) return "****";
|
|
@@ -9421,6 +9732,44 @@ async function cmdDiagnose(config, profile, options = {}) {
|
|
|
9421
9732
|
}
|
|
9422
9733
|
return runCliChecks(config, profile, options.output);
|
|
9423
9734
|
}
|
|
9735
|
+
async function checkDoh(report) {
|
|
9736
|
+
section("DoH Resolver");
|
|
9737
|
+
const local = getDohStatus();
|
|
9738
|
+
if (!local.exists) {
|
|
9739
|
+
fail("DoH binary", "not installed", [
|
|
9740
|
+
"Run: okx doh install",
|
|
9741
|
+
"Or wait for the next npm install to auto-download"
|
|
9742
|
+
]);
|
|
9743
|
+
report.add("doh_binary", "not installed");
|
|
9744
|
+
return;
|
|
9745
|
+
}
|
|
9746
|
+
ok("DoH binary", local.binaryPath);
|
|
9747
|
+
report.add("doh_binary", `installed (${local.platform ?? "unknown"})`);
|
|
9748
|
+
const cdnChecksum = await fetchCdnChecksum(void 0, 5e3);
|
|
9749
|
+
if (!cdnChecksum) {
|
|
9750
|
+
warn("DoH checksum", "CDN unreachable \u2014 cannot verify");
|
|
9751
|
+
report.add("doh_checksum", "CDN unreachable");
|
|
9752
|
+
} else if (cdnChecksum.sha256 === local.sha256) {
|
|
9753
|
+
ok("DoH checksum", `match (${cdnChecksum.source})`);
|
|
9754
|
+
report.add("doh_checksum", `match (${cdnChecksum.source})`);
|
|
9755
|
+
} else {
|
|
9756
|
+
warn("DoH checksum", "mismatch \u2014 update available", ["Run: okx doh install"]);
|
|
9757
|
+
report.add("doh_checksum", "mismatch");
|
|
9758
|
+
}
|
|
9759
|
+
try {
|
|
9760
|
+
const cacheEntry = readCache("www.okx.com");
|
|
9761
|
+
if (cacheEntry) {
|
|
9762
|
+
ok("DoH mode", cacheEntry.mode);
|
|
9763
|
+
report.add("doh_mode", cacheEntry.mode);
|
|
9764
|
+
} else {
|
|
9765
|
+
ok("DoH mode", "no cache (will auto-detect on next request)");
|
|
9766
|
+
report.add("doh_mode", "no cache");
|
|
9767
|
+
}
|
|
9768
|
+
} catch {
|
|
9769
|
+
ok("DoH mode", "no cache");
|
|
9770
|
+
report.add("doh_mode", "no cache");
|
|
9771
|
+
}
|
|
9772
|
+
}
|
|
9424
9773
|
function checkConfigFile(report) {
|
|
9425
9774
|
section("Config File");
|
|
9426
9775
|
const path6 = configFilePath();
|
|
@@ -9449,6 +9798,7 @@ async function runCliChecks(config, profile, outputPath) {
|
|
|
9449
9798
|
report.add("ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
9450
9799
|
const configFilePassed = checkConfigFile(report);
|
|
9451
9800
|
const envPassed = checkEnvironment(report);
|
|
9801
|
+
await checkDoh(report);
|
|
9452
9802
|
if (!config) {
|
|
9453
9803
|
fail("Config", "Could not load config (see Config File check above)", []);
|
|
9454
9804
|
report.add("result", "FAIL");
|
|
@@ -9476,23 +9826,23 @@ async function runCliChecks(config, profile, outputPath) {
|
|
|
9476
9826
|
|
|
9477
9827
|
// src/commands/upgrade.ts
|
|
9478
9828
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
9479
|
-
import { readFileSync as
|
|
9480
|
-
import { dirname as
|
|
9481
|
-
import { homedir as
|
|
9829
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
|
|
9830
|
+
import { dirname as dirname7, join as join10 } from "path";
|
|
9831
|
+
import { homedir as homedir8 } from "os";
|
|
9482
9832
|
var PACKAGES = ["@okx_ai/okx-trade-mcp", "@okx_ai/okx-trade-cli"];
|
|
9483
|
-
var CACHE_FILE2 =
|
|
9833
|
+
var CACHE_FILE2 = join10(homedir8(), ".okx", "last_check");
|
|
9484
9834
|
var THROTTLE_MS = 12 * 60 * 60 * 1e3;
|
|
9485
|
-
var NPM_BIN =
|
|
9835
|
+
var NPM_BIN = join10(dirname7(process.execPath), process.platform === "win32" ? "npm.cmd" : "npm");
|
|
9486
9836
|
function readLastCheck() {
|
|
9487
9837
|
try {
|
|
9488
|
-
return parseInt(
|
|
9838
|
+
return parseInt(readFileSync8(CACHE_FILE2, "utf-8").trim(), 10) || 0;
|
|
9489
9839
|
} catch {
|
|
9490
9840
|
return 0;
|
|
9491
9841
|
}
|
|
9492
9842
|
}
|
|
9493
9843
|
function writeLastCheck() {
|
|
9494
9844
|
try {
|
|
9495
|
-
|
|
9845
|
+
mkdirSync9(join10(homedir8(), ".okx"), { recursive: true });
|
|
9496
9846
|
writeFileSync7(CACHE_FILE2, String(Math.floor(Date.now() / 1e3)), "utf-8");
|
|
9497
9847
|
} catch {
|
|
9498
9848
|
}
|
|
@@ -9577,24 +9927,6 @@ async function cmdUpgrade(currentVersion, options, json) {
|
|
|
9577
9927
|
}
|
|
9578
9928
|
}
|
|
9579
9929
|
|
|
9580
|
-
// src/config/loader.ts
|
|
9581
|
-
function loadProfileConfig(opts) {
|
|
9582
|
-
return loadConfig({
|
|
9583
|
-
profile: opts.profile,
|
|
9584
|
-
modules: opts.modules,
|
|
9585
|
-
readOnly: opts.readOnly ?? false,
|
|
9586
|
-
demo: opts.demo,
|
|
9587
|
-
live: opts.live,
|
|
9588
|
-
site: opts.site,
|
|
9589
|
-
userAgent: opts.userAgent,
|
|
9590
|
-
sourceTag: opts.sourceTag,
|
|
9591
|
-
verbose: opts.verbose
|
|
9592
|
-
});
|
|
9593
|
-
}
|
|
9594
|
-
|
|
9595
|
-
// src/help.ts
|
|
9596
|
-
import { EOL as EOL2 } from "os";
|
|
9597
|
-
|
|
9598
9930
|
// src/commands/client-setup.ts
|
|
9599
9931
|
import * as fs6 from "fs";
|
|
9600
9932
|
var DETECTABLE_CLIENTS = ["claude-desktop", "cursor", "windsurf"];
|
|
@@ -9619,154 +9951,213 @@ function cmdSetupClients() {
|
|
|
9619
9951
|
printSetupUsage();
|
|
9620
9952
|
}
|
|
9621
9953
|
|
|
9622
|
-
// src/
|
|
9623
|
-
var
|
|
9954
|
+
// src/cli-registry.ts
|
|
9955
|
+
var CLI_REGISTRY = {
|
|
9956
|
+
// ── market ─────────────────────────────────────────────────────────────────
|
|
9624
9957
|
market: {
|
|
9625
9958
|
description: "Market data (ticker, orderbook, candles, trades)",
|
|
9626
9959
|
commands: {
|
|
9627
9960
|
ticker: {
|
|
9961
|
+
toolName: "market_get_ticker",
|
|
9628
9962
|
usage: "okx market ticker <instId>",
|
|
9629
9963
|
description: "Get latest ticker data for an instrument"
|
|
9630
9964
|
},
|
|
9631
9965
|
tickers: {
|
|
9966
|
+
toolName: "market_get_tickers",
|
|
9632
9967
|
usage: "okx market tickers <instType>",
|
|
9633
9968
|
description: "Get all tickers for an instrument type (SPOT|SWAP|FUTURES|OPTION)"
|
|
9634
9969
|
},
|
|
9635
9970
|
orderbook: {
|
|
9971
|
+
toolName: "market_get_orderbook",
|
|
9636
9972
|
usage: "okx market orderbook <instId> [--sz <n>]",
|
|
9637
9973
|
description: "Get order book depth for an instrument"
|
|
9638
9974
|
},
|
|
9639
9975
|
candles: {
|
|
9976
|
+
toolName: "market_get_candles",
|
|
9640
9977
|
usage: "okx market candles <instId> [--bar <bar>] [--limit <n>]",
|
|
9641
9978
|
description: "Get candlestick (OHLCV) data"
|
|
9642
9979
|
},
|
|
9643
9980
|
instruments: {
|
|
9981
|
+
toolName: "market_get_instruments",
|
|
9644
9982
|
usage: "okx market instruments --instType <type> [--instId <id>]",
|
|
9645
9983
|
description: "List tradable instruments of a given type"
|
|
9646
9984
|
},
|
|
9647
9985
|
"funding-rate": {
|
|
9986
|
+
toolName: "market_get_funding_rate",
|
|
9648
9987
|
usage: "okx market funding-rate <instId> [--history] [--limit <n>]",
|
|
9649
9988
|
description: "Get current or historical funding rate for perpetual swaps"
|
|
9650
9989
|
},
|
|
9651
9990
|
"mark-price": {
|
|
9991
|
+
toolName: "market_get_mark_price",
|
|
9652
9992
|
usage: "okx market mark-price --instType <MARGIN|SWAP|FUTURES|OPTION> [--instId <id>]",
|
|
9653
9993
|
description: "Get mark price for instruments"
|
|
9654
9994
|
},
|
|
9655
9995
|
trades: {
|
|
9996
|
+
toolName: "market_get_trades",
|
|
9656
9997
|
usage: "okx market trades <instId> [--limit <n>]",
|
|
9657
9998
|
description: "Get recent trades for an instrument"
|
|
9658
9999
|
},
|
|
9659
10000
|
"index-ticker": {
|
|
10001
|
+
toolName: "market_get_index_ticker",
|
|
9660
10002
|
usage: "okx market index-ticker [--instId <id>] [--quoteCcy <ccy>]",
|
|
9661
10003
|
description: "Get index ticker data"
|
|
9662
10004
|
},
|
|
9663
10005
|
"index-candles": {
|
|
10006
|
+
toolName: "market_get_index_candles",
|
|
9664
10007
|
usage: "okx market index-candles <instId> [--bar <bar>] [--limit <n>] [--history]",
|
|
9665
10008
|
description: "Get index candlestick data"
|
|
9666
10009
|
},
|
|
9667
10010
|
"price-limit": {
|
|
10011
|
+
toolName: "market_get_price_limit",
|
|
9668
10012
|
usage: "okx market price-limit <instId>",
|
|
9669
10013
|
description: "Get price limit for an instrument"
|
|
9670
10014
|
},
|
|
9671
10015
|
"open-interest": {
|
|
10016
|
+
toolName: "market_get_open_interest",
|
|
9672
10017
|
usage: "okx market open-interest --instType <SWAP|FUTURES|OPTION> [--instId <id>]",
|
|
9673
10018
|
description: "Get open interest for instruments"
|
|
9674
10019
|
},
|
|
9675
10020
|
"stock-tokens": {
|
|
10021
|
+
toolName: "market_get_stock_tokens",
|
|
9676
10022
|
usage: "okx market stock-tokens [--instType <SPOT|SWAP>] [--instId <id>]",
|
|
9677
10023
|
description: "[Deprecated: use instruments-by-category --instCategory 3] List all stock token instruments (instCategory=3, e.g. AAPL-USDT-SWAP)"
|
|
9678
10024
|
},
|
|
9679
10025
|
"instruments-by-category": {
|
|
10026
|
+
toolName: "market_get_instruments_by_category",
|
|
9680
10027
|
usage: "okx market instruments-by-category --instCategory <4|5|6|7> [--instType <SPOT|SWAP>] [--instId <id>]",
|
|
9681
10028
|
description: "List instruments by asset category: 4=Metals (gold/silver), 5=Commodities (oil/gas), 6=Forex (EUR/USD), 7=Bonds"
|
|
9682
10029
|
}
|
|
10030
|
+
},
|
|
10031
|
+
subgroups: {
|
|
10032
|
+
indicator: {
|
|
10033
|
+
description: "Technical indicators and chart patterns",
|
|
10034
|
+
commands: {
|
|
10035
|
+
list: {
|
|
10036
|
+
toolName: "market_list_indicators",
|
|
10037
|
+
usage: "okx market indicator list",
|
|
10038
|
+
description: "List all supported technical indicators"
|
|
10039
|
+
},
|
|
10040
|
+
"<instId> <indicator>": {
|
|
10041
|
+
toolName: "market_get_indicator",
|
|
10042
|
+
usage: "okx market indicator <instId> <indicator> [--bar <bar>] [--limit <n>] [--backtest-time <ts>] [--params <json>]",
|
|
10043
|
+
description: "Get indicator values for an instrument (e.g. okx market indicator BTC-USDT-SWAP rsi)"
|
|
10044
|
+
}
|
|
10045
|
+
}
|
|
10046
|
+
}
|
|
9683
10047
|
}
|
|
9684
10048
|
},
|
|
10049
|
+
// ── account ────────────────────────────────────────────────────────────────
|
|
9685
10050
|
account: {
|
|
9686
10051
|
description: "Account balance, positions, bills, and configuration",
|
|
9687
10052
|
commands: {
|
|
9688
10053
|
balance: {
|
|
10054
|
+
toolName: "account_get_balance",
|
|
9689
10055
|
usage: "okx account balance [<ccy>]",
|
|
9690
10056
|
description: "Get trading account balance"
|
|
9691
10057
|
},
|
|
9692
10058
|
"asset-balance": {
|
|
10059
|
+
toolName: "account_get_asset_balance",
|
|
9693
10060
|
usage: "okx account asset-balance [--ccy <ccy>]",
|
|
9694
10061
|
description: "Get funding account asset balance"
|
|
9695
10062
|
},
|
|
9696
10063
|
positions: {
|
|
10064
|
+
toolName: "account_get_positions",
|
|
9697
10065
|
usage: "okx account positions [--instType <type>] [--instId <id>]",
|
|
9698
10066
|
description: "Get current open positions"
|
|
9699
10067
|
},
|
|
9700
10068
|
"positions-history": {
|
|
10069
|
+
toolName: "account_get_positions_history",
|
|
9701
10070
|
usage: "okx account positions-history [--instType <type>] [--instId <id>] [--limit <n>]",
|
|
9702
10071
|
description: "Get historical positions"
|
|
9703
10072
|
},
|
|
9704
10073
|
bills: {
|
|
10074
|
+
toolName: "account_get_bills",
|
|
10075
|
+
alternateTools: ["account_get_bills_archive"],
|
|
9705
10076
|
usage: "okx account bills [--instType <type>] [--ccy <ccy>] [--limit <n>] [--archive]",
|
|
9706
10077
|
description: "Get account bill history"
|
|
9707
10078
|
},
|
|
9708
10079
|
fees: {
|
|
10080
|
+
toolName: "account_get_trade_fee",
|
|
9709
10081
|
usage: "okx account fees --instType <type> [--instId <id>]",
|
|
9710
10082
|
description: "Get trading fee rates"
|
|
9711
10083
|
},
|
|
9712
10084
|
config: {
|
|
10085
|
+
toolName: "account_get_config",
|
|
9713
10086
|
usage: "okx account config",
|
|
9714
10087
|
description: "Get account configuration"
|
|
9715
10088
|
},
|
|
9716
10089
|
"set-position-mode": {
|
|
10090
|
+
toolName: "account_set_position_mode",
|
|
9717
10091
|
usage: "okx account set-position-mode --posMode <long_short_mode|net_mode>",
|
|
9718
10092
|
description: "Set position mode (long/short or net)"
|
|
9719
10093
|
},
|
|
9720
10094
|
"max-size": {
|
|
10095
|
+
toolName: "account_get_max_size",
|
|
9721
10096
|
usage: "okx account max-size --instId <id> --tdMode <cross|isolated> [--px <price>]",
|
|
9722
10097
|
description: "Get maximum order size for an instrument"
|
|
9723
10098
|
},
|
|
9724
10099
|
"max-avail-size": {
|
|
10100
|
+
toolName: "account_get_max_avail_size",
|
|
9725
10101
|
usage: "okx account max-avail-size --instId <id> --tdMode <cross|isolated|cash>",
|
|
9726
10102
|
description: "Get maximum available tradable amount"
|
|
9727
10103
|
},
|
|
9728
10104
|
"max-withdrawal": {
|
|
10105
|
+
toolName: "account_get_max_withdrawal",
|
|
9729
10106
|
usage: "okx account max-withdrawal [--ccy <ccy>]",
|
|
9730
10107
|
description: "Get maximum withdrawable amount"
|
|
9731
10108
|
},
|
|
9732
10109
|
transfer: {
|
|
10110
|
+
toolName: "account_transfer",
|
|
9733
10111
|
usage: "okx account transfer --ccy <ccy> --amt <n> --from <acct> --to <acct> [--transferType <0|1|2|3>]",
|
|
9734
10112
|
description: "Transfer funds between accounts"
|
|
9735
10113
|
},
|
|
9736
10114
|
audit: {
|
|
10115
|
+
// trade_get_history ToolSpec reads the same local log files as cmdAccountAudit.
|
|
10116
|
+
// CLI reads files directly without routing through ToolRunner for performance,
|
|
10117
|
+
// but conceptually this command is the CLI representation of the ToolSpec.
|
|
10118
|
+
toolName: "trade_get_history",
|
|
9737
10119
|
usage: "okx account audit [--tool <name>] [--since <ISO-date>] [--limit <n>]",
|
|
9738
10120
|
description: "Audit account activity and tool call history"
|
|
9739
10121
|
}
|
|
9740
10122
|
}
|
|
9741
10123
|
},
|
|
10124
|
+
// ── spot ───────────────────────────────────────────────────────────────────
|
|
9742
10125
|
spot: {
|
|
9743
10126
|
description: "Spot trading (orders, algo orders)",
|
|
9744
10127
|
commands: {
|
|
9745
10128
|
orders: {
|
|
10129
|
+
toolName: "spot_get_orders",
|
|
9746
10130
|
usage: "okx spot orders [--instId <id>] [--history]",
|
|
9747
10131
|
description: "List open or historical spot orders"
|
|
9748
10132
|
},
|
|
9749
10133
|
get: {
|
|
10134
|
+
toolName: "spot_get_order",
|
|
9750
10135
|
usage: "okx spot get --instId <id> --ordId <id>",
|
|
9751
10136
|
description: "Get details of a specific spot order"
|
|
9752
10137
|
},
|
|
9753
10138
|
fills: {
|
|
10139
|
+
toolName: "spot_get_fills",
|
|
9754
10140
|
usage: "okx spot fills [--instId <id>] [--ordId <id>]",
|
|
9755
10141
|
description: "Get trade fill history for spot orders"
|
|
9756
10142
|
},
|
|
9757
10143
|
place: {
|
|
10144
|
+
toolName: "spot_place_order",
|
|
9758
10145
|
usage: "okx spot place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--px <price>] [--tdMode <cash|cross|isolated>] [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--slTriggerPx <price>] [--slOrdPx <price|-1>]",
|
|
9759
10146
|
description: "Place a new spot order (supports attached TP/SL)"
|
|
9760
10147
|
},
|
|
9761
10148
|
amend: {
|
|
10149
|
+
toolName: "spot_amend_order",
|
|
9762
10150
|
usage: "okx spot amend --instId <id> --ordId <id> [--newSz <n>] [--newPx <price>]",
|
|
9763
10151
|
description: "Amend a pending spot order"
|
|
9764
10152
|
},
|
|
9765
10153
|
cancel: {
|
|
10154
|
+
toolName: "spot_cancel_order",
|
|
9766
10155
|
usage: "okx spot cancel <instId> --ordId <id>",
|
|
9767
10156
|
description: "Cancel a pending spot order"
|
|
9768
10157
|
},
|
|
9769
10158
|
batch: {
|
|
10159
|
+
toolName: "spot_batch_orders",
|
|
10160
|
+
alternateTools: ["spot_batch_amend", "spot_batch_cancel"],
|
|
9770
10161
|
usage: "okx spot batch --action <place|amend|cancel> --orders '<json>'",
|
|
9771
10162
|
description: "Batch place, amend, or cancel spot orders"
|
|
9772
10163
|
}
|
|
@@ -9776,18 +10167,27 @@ var HELP_TREE = {
|
|
|
9776
10167
|
description: "Spot algo orders (conditional, OCO, take-profit/stop-loss)",
|
|
9777
10168
|
commands: {
|
|
9778
10169
|
orders: {
|
|
10170
|
+
toolName: "spot_get_algo_orders",
|
|
9779
10171
|
usage: "okx spot algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]",
|
|
9780
10172
|
description: "List spot algo orders"
|
|
9781
10173
|
},
|
|
9782
10174
|
place: {
|
|
10175
|
+
toolName: "spot_place_algo_order",
|
|
9783
10176
|
usage: "okx spot algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--tdMode <cash|cross|isolated>]",
|
|
9784
10177
|
description: "Place a spot algo order (take-profit/stop-loss)"
|
|
9785
10178
|
},
|
|
10179
|
+
trail: {
|
|
10180
|
+
toolName: "spot_place_algo_order",
|
|
10181
|
+
usage: "okx spot algo trail --instId <id> --side <buy|sell> --sz <n> --callbackRatio <ratio>\n [--activePx <price>] [--tdMode <cash|cross|isolated>]",
|
|
10182
|
+
description: "Place a trailing stop algo order for spot"
|
|
10183
|
+
},
|
|
9786
10184
|
amend: {
|
|
10185
|
+
toolName: "spot_amend_algo_order",
|
|
9787
10186
|
usage: "okx spot algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]",
|
|
9788
10187
|
description: "Amend a pending spot algo order"
|
|
9789
10188
|
},
|
|
9790
10189
|
cancel: {
|
|
10190
|
+
toolName: "spot_cancel_algo_order",
|
|
9791
10191
|
usage: "okx spot algo cancel --instId <id> --algoId <id>",
|
|
9792
10192
|
description: "Cancel a pending spot algo order"
|
|
9793
10193
|
}
|
|
@@ -9795,50 +10195,64 @@ var HELP_TREE = {
|
|
|
9795
10195
|
}
|
|
9796
10196
|
}
|
|
9797
10197
|
},
|
|
10198
|
+
// ── swap ───────────────────────────────────────────────────────────────────
|
|
9798
10199
|
swap: {
|
|
9799
10200
|
description: "Perpetual swap trading (orders, algo orders)",
|
|
9800
10201
|
commands: {
|
|
9801
10202
|
positions: {
|
|
10203
|
+
toolName: "swap_get_positions",
|
|
9802
10204
|
usage: "okx swap positions [<instId>]",
|
|
9803
10205
|
description: "Get current perpetual swap positions"
|
|
9804
10206
|
},
|
|
9805
10207
|
orders: {
|
|
10208
|
+
toolName: "swap_get_orders",
|
|
9806
10209
|
usage: "okx swap orders [--instId <id>] [--history] [--archive]",
|
|
9807
10210
|
description: "List open or historical swap orders"
|
|
9808
10211
|
},
|
|
9809
10212
|
get: {
|
|
10213
|
+
toolName: "swap_get_order",
|
|
9810
10214
|
usage: "okx swap get --instId <id> --ordId <id>",
|
|
9811
10215
|
description: "Get details of a specific swap order"
|
|
9812
10216
|
},
|
|
9813
10217
|
fills: {
|
|
10218
|
+
toolName: "swap_get_fills",
|
|
9814
10219
|
usage: "okx swap fills [--instId <id>] [--ordId <id>] [--archive]",
|
|
9815
10220
|
description: "Get trade fill history for swap orders"
|
|
9816
10221
|
},
|
|
9817
10222
|
place: {
|
|
10223
|
+
toolName: "swap_place_order",
|
|
9818
10224
|
usage: "okx swap place --instId <id> --side <buy|sell> --ordType <type> --sz <n> [--posSide <side>] [--px <price>] [--tdMode <cross|isolated>] [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--slTriggerPx <price>] [--slOrdPx <price|-1>]",
|
|
9819
10225
|
description: "Place a new perpetual swap order (supports attached TP/SL)"
|
|
9820
10226
|
},
|
|
9821
10227
|
cancel: {
|
|
10228
|
+
toolName: "swap_cancel_order",
|
|
9822
10229
|
usage: "okx swap cancel <instId> --ordId <id>",
|
|
9823
10230
|
description: "Cancel a pending swap order"
|
|
9824
10231
|
},
|
|
9825
10232
|
amend: {
|
|
10233
|
+
// swap amend uses spot_amend_order (same OKX /trade/amend-order endpoint works for all types)
|
|
10234
|
+
toolName: "spot_amend_order",
|
|
9826
10235
|
usage: "okx swap amend --instId <id> --ordId <id> [--newSz <n>] [--newPx <price>]",
|
|
9827
10236
|
description: "Amend a pending swap order"
|
|
9828
10237
|
},
|
|
9829
10238
|
close: {
|
|
10239
|
+
toolName: "swap_close_position",
|
|
9830
10240
|
usage: "okx swap close --instId <id> --mgnMode <cross|isolated> [--posSide <net|long|short>] [--autoCxl]",
|
|
9831
10241
|
description: "Close a swap position"
|
|
9832
10242
|
},
|
|
9833
10243
|
leverage: {
|
|
10244
|
+
toolName: "swap_set_leverage",
|
|
9834
10245
|
usage: "okx swap leverage --instId <id> --lever <n> --mgnMode <cross|isolated> [--posSide <side>]",
|
|
9835
10246
|
description: "Set leverage for a swap instrument"
|
|
9836
10247
|
},
|
|
9837
10248
|
"get-leverage": {
|
|
10249
|
+
toolName: "swap_get_leverage",
|
|
9838
10250
|
usage: "okx swap get-leverage --instId <id> --mgnMode <cross|isolated>",
|
|
9839
10251
|
description: "Get current leverage setting for a swap instrument"
|
|
9840
10252
|
},
|
|
9841
10253
|
batch: {
|
|
10254
|
+
toolName: "swap_batch_orders",
|
|
10255
|
+
alternateTools: ["swap_batch_amend", "swap_batch_cancel"],
|
|
9842
10256
|
usage: "okx swap batch --action <place|amend|cancel> --orders '<json>'",
|
|
9843
10257
|
description: "Batch place, amend, or cancel swap orders"
|
|
9844
10258
|
}
|
|
@@ -9848,22 +10262,27 @@ var HELP_TREE = {
|
|
|
9848
10262
|
description: "Perpetual swap algo orders (trailing stop, conditional, OCO)",
|
|
9849
10263
|
commands: {
|
|
9850
10264
|
orders: {
|
|
10265
|
+
toolName: "swap_get_algo_orders",
|
|
9851
10266
|
usage: "okx swap algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]",
|
|
9852
10267
|
description: "List swap algo orders"
|
|
9853
10268
|
},
|
|
9854
10269
|
trail: {
|
|
10270
|
+
toolName: "swap_place_move_stop_order",
|
|
9855
10271
|
usage: "okx swap algo trail --instId <id> --side <buy|sell> --sz <n> --callbackRatio <ratio>\n [--activePx <price>] [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
|
|
9856
10272
|
description: "Place a trailing stop algo order for perpetual swap"
|
|
9857
10273
|
},
|
|
9858
10274
|
place: {
|
|
10275
|
+
toolName: "swap_place_algo_order",
|
|
9859
10276
|
usage: "okx swap algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
|
|
9860
10277
|
description: "Place a swap algo order (take-profit/stop-loss)"
|
|
9861
10278
|
},
|
|
9862
10279
|
amend: {
|
|
10280
|
+
toolName: "swap_amend_algo_order",
|
|
9863
10281
|
usage: "okx swap algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]",
|
|
9864
10282
|
description: "Amend a pending swap algo order"
|
|
9865
10283
|
},
|
|
9866
10284
|
cancel: {
|
|
10285
|
+
toolName: "swap_cancel_algo_orders",
|
|
9867
10286
|
usage: "okx swap algo cancel --instId <id> --algoId <id>",
|
|
9868
10287
|
description: "Cancel a pending swap algo order"
|
|
9869
10288
|
}
|
|
@@ -9871,50 +10290,63 @@ var HELP_TREE = {
|
|
|
9871
10290
|
}
|
|
9872
10291
|
}
|
|
9873
10292
|
},
|
|
10293
|
+
// ── futures ────────────────────────────────────────────────────────────────
|
|
9874
10294
|
futures: {
|
|
9875
10295
|
description: "Futures trading (orders, positions, algo orders, leverage)",
|
|
9876
10296
|
commands: {
|
|
9877
10297
|
orders: {
|
|
10298
|
+
toolName: "futures_get_orders",
|
|
9878
10299
|
usage: "okx futures orders [--instId <id>] [--history] [--archive]",
|
|
9879
10300
|
description: "List open or historical futures orders"
|
|
9880
10301
|
},
|
|
9881
10302
|
positions: {
|
|
10303
|
+
toolName: "futures_get_positions",
|
|
9882
10304
|
usage: "okx futures positions [--instId <id>]",
|
|
9883
10305
|
description: "Get current futures positions"
|
|
9884
10306
|
},
|
|
9885
10307
|
fills: {
|
|
10308
|
+
toolName: "futures_get_fills",
|
|
9886
10309
|
usage: "okx futures fills [--instId <id>] [--ordId <id>] [--archive]",
|
|
9887
10310
|
description: "Get trade fill history for futures orders"
|
|
9888
10311
|
},
|
|
9889
10312
|
place: {
|
|
10313
|
+
toolName: "futures_place_order",
|
|
9890
10314
|
usage: "okx futures place --instId <id> --side <buy|sell> --ordType <type> --sz <n>\n [--tdMode <cross|isolated>] [--posSide <net|long|short>] [--px <price>] [--reduceOnly]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>] [--slTriggerPx <price>] [--slOrdPx <price|-1>]",
|
|
9891
10315
|
description: "Place a new futures order (supports attached TP/SL)"
|
|
9892
10316
|
},
|
|
9893
10317
|
cancel: {
|
|
10318
|
+
toolName: "futures_cancel_order",
|
|
9894
10319
|
usage: "okx futures cancel <instId> --ordId <id>",
|
|
9895
10320
|
description: "Cancel a pending futures order"
|
|
9896
10321
|
},
|
|
9897
10322
|
amend: {
|
|
10323
|
+
toolName: "futures_amend_order",
|
|
9898
10324
|
usage: "okx futures amend --instId <id> [--ordId <id>] [--clOrdId <id>] [--newSz <n>] [--newPx <price>]",
|
|
9899
10325
|
description: "Amend a pending futures order"
|
|
9900
10326
|
},
|
|
9901
10327
|
get: {
|
|
10328
|
+
toolName: "futures_get_order",
|
|
9902
10329
|
usage: "okx futures get --instId <id> --ordId <id>",
|
|
9903
10330
|
description: "Get details of a specific futures order"
|
|
9904
10331
|
},
|
|
9905
10332
|
close: {
|
|
10333
|
+
toolName: "futures_close_position",
|
|
9906
10334
|
usage: "okx futures close --instId <id> --mgnMode <cross|isolated> [--posSide <net|long|short>] [--autoCxl]",
|
|
9907
10335
|
description: "Close a futures position"
|
|
9908
10336
|
},
|
|
9909
10337
|
"get-leverage": {
|
|
10338
|
+
toolName: "futures_get_leverage",
|
|
9910
10339
|
usage: "okx futures get-leverage --instId <id> --mgnMode <cross|isolated>",
|
|
9911
10340
|
description: "Get current leverage for a futures instrument"
|
|
9912
10341
|
},
|
|
9913
10342
|
leverage: {
|
|
10343
|
+
toolName: "futures_set_leverage",
|
|
9914
10344
|
usage: "okx futures leverage --instId <id> --lever <n> --mgnMode <cross|isolated> [--posSide <net|long|short>]",
|
|
9915
10345
|
description: "Set leverage for a futures instrument"
|
|
9916
10346
|
},
|
|
9917
10347
|
batch: {
|
|
10348
|
+
toolName: "futures_batch_orders",
|
|
10349
|
+
alternateTools: ["futures_batch_amend", "futures_batch_cancel"],
|
|
9918
10350
|
usage: "okx futures batch --action <place|amend|cancel> --orders '<json>'",
|
|
9919
10351
|
description: "Batch place, amend, or cancel futures orders"
|
|
9920
10352
|
}
|
|
@@ -9924,22 +10356,27 @@ var HELP_TREE = {
|
|
|
9924
10356
|
description: "Futures algo orders (trailing stop, conditional, OCO)",
|
|
9925
10357
|
commands: {
|
|
9926
10358
|
orders: {
|
|
10359
|
+
toolName: "futures_get_algo_orders",
|
|
9927
10360
|
usage: "okx futures algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]",
|
|
9928
10361
|
description: "List futures algo orders"
|
|
9929
10362
|
},
|
|
9930
10363
|
trail: {
|
|
10364
|
+
toolName: "futures_place_move_stop_order",
|
|
9931
10365
|
usage: "okx futures algo trail --instId <id> --side <buy|sell> --sz <n> --callbackRatio <ratio>\n [--activePx <price>] [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
|
|
9932
10366
|
description: "Place a trailing stop algo order for futures"
|
|
9933
10367
|
},
|
|
9934
10368
|
place: {
|
|
10369
|
+
toolName: "futures_place_algo_order",
|
|
9935
10370
|
usage: "okx futures algo place --instId <id> --side <buy|sell> --sz <n> [--ordType <conditional|oco>]\n [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>]\n [--posSide <net|long|short>] [--tdMode <cross|isolated>] [--reduceOnly]",
|
|
9936
10371
|
description: "Place a futures algo order (take-profit/stop-loss)"
|
|
9937
10372
|
},
|
|
9938
10373
|
amend: {
|
|
10374
|
+
toolName: "futures_amend_algo_order",
|
|
9939
10375
|
usage: "okx futures algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]",
|
|
9940
10376
|
description: "Amend a pending futures algo order"
|
|
9941
10377
|
},
|
|
9942
10378
|
cancel: {
|
|
10379
|
+
toolName: "futures_cancel_algo_orders",
|
|
9943
10380
|
usage: "okx futures algo cancel --instId <id> --algoId <id>",
|
|
9944
10381
|
description: "Cancel a pending futures algo order"
|
|
9945
10382
|
}
|
|
@@ -9947,51 +10384,90 @@ var HELP_TREE = {
|
|
|
9947
10384
|
}
|
|
9948
10385
|
}
|
|
9949
10386
|
},
|
|
10387
|
+
// ── option ─────────────────────────────────────────────────────────────────
|
|
9950
10388
|
option: {
|
|
9951
10389
|
description: "Options trading (orders, positions, greeks)",
|
|
9952
10390
|
commands: {
|
|
9953
10391
|
orders: {
|
|
10392
|
+
toolName: "option_get_orders",
|
|
9954
10393
|
usage: "okx option orders [--instId <id>] [--uly <uly>] [--history] [--archive]",
|
|
9955
10394
|
description: "List open or historical option orders"
|
|
9956
10395
|
},
|
|
9957
10396
|
get: {
|
|
10397
|
+
toolName: "option_get_order",
|
|
9958
10398
|
usage: "okx option get --instId <id> [--ordId <id>] [--clOrdId <id>]",
|
|
9959
10399
|
description: "Get details of a specific option order"
|
|
9960
10400
|
},
|
|
9961
10401
|
positions: {
|
|
10402
|
+
toolName: "option_get_positions",
|
|
9962
10403
|
usage: "okx option positions [--instId <id>] [--uly <uly>]",
|
|
9963
10404
|
description: "Get current option positions"
|
|
9964
10405
|
},
|
|
9965
10406
|
fills: {
|
|
10407
|
+
toolName: "option_get_fills",
|
|
9966
10408
|
usage: "okx option fills [--instId <id>] [--ordId <id>] [--archive]",
|
|
9967
10409
|
description: "Get trade fill history for option orders"
|
|
9968
10410
|
},
|
|
9969
10411
|
instruments: {
|
|
10412
|
+
toolName: "option_get_instruments",
|
|
9970
10413
|
usage: "okx option instruments --uly <uly> [--expTime <date>]",
|
|
9971
10414
|
description: "List tradable option instruments for an underlying"
|
|
9972
10415
|
},
|
|
9973
10416
|
greeks: {
|
|
10417
|
+
toolName: "option_get_greeks",
|
|
9974
10418
|
usage: "okx option greeks --uly <uly> [--expTime <date>]",
|
|
9975
10419
|
description: "Get option greeks (delta, gamma, theta, vega)"
|
|
9976
10420
|
},
|
|
9977
10421
|
place: {
|
|
10422
|
+
toolName: "option_place_order",
|
|
9978
10423
|
usage: "okx option place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --ordType <type> --sz <n>\n [--px <price>] [--reduceOnly] [--clOrdId <id>]",
|
|
9979
10424
|
description: "Place a new option order"
|
|
9980
10425
|
},
|
|
9981
10426
|
cancel: {
|
|
10427
|
+
toolName: "option_cancel_order",
|
|
9982
10428
|
usage: "okx option cancel --instId <id> [--ordId <id>] [--clOrdId <id>]",
|
|
9983
10429
|
description: "Cancel a pending option order"
|
|
9984
10430
|
},
|
|
9985
10431
|
amend: {
|
|
10432
|
+
toolName: "option_amend_order",
|
|
9986
10433
|
usage: "okx option amend --instId <id> [--ordId <id>] [--clOrdId <id>] [--newSz <n>] [--newPx <price>]",
|
|
9987
10434
|
description: "Amend a pending option order"
|
|
9988
10435
|
},
|
|
9989
10436
|
"batch-cancel": {
|
|
10437
|
+
toolName: "option_batch_cancel",
|
|
9990
10438
|
usage: "okx option batch-cancel --orders '<json>'",
|
|
9991
10439
|
description: "Batch cancel option orders"
|
|
9992
10440
|
}
|
|
10441
|
+
},
|
|
10442
|
+
subgroups: {
|
|
10443
|
+
algo: {
|
|
10444
|
+
description: "Option algo orders (conditional, TP/SL)",
|
|
10445
|
+
commands: {
|
|
10446
|
+
orders: {
|
|
10447
|
+
toolName: "option_get_algo_orders",
|
|
10448
|
+
usage: "okx option algo orders [--instId <id>] [--history] [--ordType <conditional|oco>]",
|
|
10449
|
+
description: "List option algo orders"
|
|
10450
|
+
},
|
|
10451
|
+
place: {
|
|
10452
|
+
toolName: "option_place_algo_order",
|
|
10453
|
+
usage: "okx option algo place --instId <id> --tdMode <cash|cross|isolated> --side <buy|sell> --sz <n>\n [--ordType <conditional|oco>] [--tpTriggerPx <price>] [--tpOrdPx <price|-1>]\n [--slTriggerPx <price>] [--slOrdPx <price|-1>] [--reduceOnly] [--clOrdId <id>]",
|
|
10454
|
+
description: "Place an option algo order (take-profit/stop-loss)"
|
|
10455
|
+
},
|
|
10456
|
+
amend: {
|
|
10457
|
+
toolName: "option_amend_algo_order",
|
|
10458
|
+
usage: "okx option algo amend --instId <id> --algoId <id> [--newSz <n>]\n [--newTpTriggerPx <price>] [--newTpOrdPx <price|-1>]\n [--newSlTriggerPx <price>] [--newSlOrdPx <price|-1>]",
|
|
10459
|
+
description: "Amend a pending option algo order"
|
|
10460
|
+
},
|
|
10461
|
+
cancel: {
|
|
10462
|
+
toolName: "option_cancel_algo_orders",
|
|
10463
|
+
usage: "okx option algo cancel --instId <id> --algoId <id>",
|
|
10464
|
+
description: "Cancel a pending option algo order"
|
|
10465
|
+
}
|
|
10466
|
+
}
|
|
10467
|
+
}
|
|
9993
10468
|
}
|
|
9994
10469
|
},
|
|
10470
|
+
// ── earn ───────────────────────────────────────────────────────────────────
|
|
9995
10471
|
earn: {
|
|
9996
10472
|
description: "Earn products \u2014 Simple Earn, On-chain Earn, and DCD (Dual Currency Deposit)",
|
|
9997
10473
|
subgroups: {
|
|
@@ -9999,38 +10475,47 @@ var HELP_TREE = {
|
|
|
9999
10475
|
description: "Simple Earn \u2014 flexible savings, fixed-term, and lending",
|
|
10000
10476
|
commands: {
|
|
10001
10477
|
balance: {
|
|
10478
|
+
toolName: "earn_get_savings_balance",
|
|
10002
10479
|
usage: "okx earn savings balance [<ccy>]",
|
|
10003
10480
|
description: "Get savings balance (optionally filter by currency)"
|
|
10004
10481
|
},
|
|
10005
10482
|
purchase: {
|
|
10483
|
+
toolName: "earn_savings_purchase",
|
|
10006
10484
|
usage: "okx earn savings purchase --ccy <ccy> --amt <n> [--rate <rate>]",
|
|
10007
10485
|
description: "Purchase Simple Earn (flexible savings). Rate defaults to 0.01 (1%)"
|
|
10008
10486
|
},
|
|
10009
10487
|
redeem: {
|
|
10488
|
+
toolName: "earn_savings_redeem",
|
|
10010
10489
|
usage: "okx earn savings redeem --ccy <ccy> --amt <n>",
|
|
10011
10490
|
description: "Redeem Simple Earn (flexible savings)"
|
|
10012
10491
|
},
|
|
10013
10492
|
"set-rate": {
|
|
10493
|
+
toolName: "earn_set_lending_rate",
|
|
10014
10494
|
usage: "okx earn savings set-rate --ccy <ccy> --rate <rate>",
|
|
10015
10495
|
description: "Set lending rate for a currency"
|
|
10016
10496
|
},
|
|
10017
10497
|
"lending-history": {
|
|
10498
|
+
toolName: "earn_get_lending_history",
|
|
10018
10499
|
usage: "okx earn savings lending-history [--ccy <ccy>] [--limit <n>]",
|
|
10019
10500
|
description: "Get personal lending records (requires auth)"
|
|
10020
10501
|
},
|
|
10021
10502
|
"rate-history": {
|
|
10503
|
+
toolName: "earn_get_lending_rate_history",
|
|
10022
10504
|
usage: "okx earn savings rate-history [--ccy <ccy>] [--limit <n>]",
|
|
10023
10505
|
description: "Query Simple Earn lending rates and fixed-term offers (requires auth)"
|
|
10024
10506
|
},
|
|
10025
10507
|
"fixed-orders": {
|
|
10508
|
+
toolName: "earn_get_fixed_order_list",
|
|
10026
10509
|
usage: "okx earn savings fixed-orders [--ccy <ccy>] [--state <pending|earning|expired|settled|cancelled>]",
|
|
10027
10510
|
description: "List fixed-term earn orders"
|
|
10028
10511
|
},
|
|
10029
10512
|
"fixed-purchase": {
|
|
10513
|
+
toolName: "earn_fixed_purchase",
|
|
10030
10514
|
usage: "okx earn savings fixed-purchase --ccy <ccy> --amt <n> --term <term> [--confirm]",
|
|
10031
10515
|
description: "Purchase Simple Earn Fixed (\u5B9A\u671F). Preview by default; add --confirm to execute. Funds locked until maturity"
|
|
10032
10516
|
},
|
|
10033
10517
|
"fixed-redeem": {
|
|
10518
|
+
toolName: "earn_fixed_redeem",
|
|
10034
10519
|
usage: "okx earn savings fixed-redeem <reqId>",
|
|
10035
10520
|
description: "Redeem a fixed-term earn order (full amount)"
|
|
10036
10521
|
}
|
|
@@ -10040,26 +10525,32 @@ var HELP_TREE = {
|
|
|
10040
10525
|
description: "On-chain Earn \u2014 staking and DeFi products",
|
|
10041
10526
|
commands: {
|
|
10042
10527
|
offers: {
|
|
10528
|
+
toolName: "onchain_earn_get_offers",
|
|
10043
10529
|
usage: "okx earn onchain offers [--productId <id>] [--protocolType <type>] [--ccy <ccy>]",
|
|
10044
10530
|
description: "Browse available on-chain earn products (staking, DeFi)"
|
|
10045
10531
|
},
|
|
10046
10532
|
purchase: {
|
|
10533
|
+
toolName: "onchain_earn_purchase",
|
|
10047
10534
|
usage: "okx earn onchain purchase --productId <id> --ccy <ccy> --amt <n> [--term <term>] [--tag <tag>]",
|
|
10048
10535
|
description: "Purchase an on-chain earn product (stake/deposit)"
|
|
10049
10536
|
},
|
|
10050
10537
|
redeem: {
|
|
10538
|
+
toolName: "onchain_earn_redeem",
|
|
10051
10539
|
usage: "okx earn onchain redeem --ordId <id> --protocolType <type> [--allowEarlyRedeem]",
|
|
10052
10540
|
description: "Redeem an on-chain earn position"
|
|
10053
10541
|
},
|
|
10054
10542
|
cancel: {
|
|
10543
|
+
toolName: "onchain_earn_cancel",
|
|
10055
10544
|
usage: "okx earn onchain cancel --ordId <id> --protocolType <type>",
|
|
10056
10545
|
description: "Cancel a pending on-chain earn order"
|
|
10057
10546
|
},
|
|
10058
10547
|
orders: {
|
|
10548
|
+
toolName: "onchain_earn_get_active_orders",
|
|
10059
10549
|
usage: "okx earn onchain orders [--productId <id>] [--protocolType <type>] [--ccy <ccy>] [--state <state>]",
|
|
10060
10550
|
description: "List active on-chain earn orders"
|
|
10061
10551
|
},
|
|
10062
10552
|
history: {
|
|
10553
|
+
toolName: "onchain_earn_get_order_history",
|
|
10063
10554
|
usage: "okx earn onchain history [--productId <id>] [--protocolType <type>] [--ccy <ccy>]",
|
|
10064
10555
|
description: "Get on-chain earn order history"
|
|
10065
10556
|
}
|
|
@@ -10069,14 +10560,19 @@ var HELP_TREE = {
|
|
|
10069
10560
|
description: "Auto-earn \u2014 automatically lend, stake, or earn on idle assets",
|
|
10070
10561
|
commands: {
|
|
10071
10562
|
status: {
|
|
10563
|
+
// CLI reads from account_get_balance; earn_auto_set is covered by 'on' command below
|
|
10564
|
+
toolName: null,
|
|
10072
10565
|
usage: "okx earn auto-earn status [<ccy>]",
|
|
10073
10566
|
description: "Query auto-earn status for all or a specific currency"
|
|
10074
10567
|
},
|
|
10075
10568
|
on: {
|
|
10569
|
+
toolName: "earn_auto_set",
|
|
10076
10570
|
usage: "okx earn auto-earn on <ccy>",
|
|
10077
10571
|
description: "Enable auto-earn for a currency (auto-detects lend/stake vs USDG earn)"
|
|
10078
10572
|
},
|
|
10079
10573
|
off: {
|
|
10574
|
+
// same tool as 'on'; earn_auto_set already registered above
|
|
10575
|
+
toolName: "earn_auto_set",
|
|
10080
10576
|
usage: "okx earn auto-earn off <ccy>",
|
|
10081
10577
|
description: "Disable auto-earn for a currency"
|
|
10082
10578
|
}
|
|
@@ -10086,26 +10582,32 @@ var HELP_TREE = {
|
|
|
10086
10582
|
description: "DCD (Dual Currency Deposit) \u2014 structured products with fixed yield",
|
|
10087
10583
|
commands: {
|
|
10088
10584
|
pairs: {
|
|
10585
|
+
toolName: "dcd_get_currency_pairs",
|
|
10089
10586
|
usage: "okx earn dcd pairs",
|
|
10090
10587
|
description: "List available DCD currency pairs"
|
|
10091
10588
|
},
|
|
10092
10589
|
products: {
|
|
10590
|
+
toolName: "dcd_get_products",
|
|
10093
10591
|
usage: "okx earn dcd products --baseCcy <ccy> --quoteCcy <ccy> --optType <C|P>\n [--minYield <n>] [--strikeNear <price>]\n [--termDays <n>] [--minTermDays <n>] [--maxTermDays <n>]\n [--expDate <YYYY-MM-DD|YYYY-MM-DDTHH:mm>]",
|
|
10094
10592
|
description: "List active DCD products (baseCcy, quoteCcy, optType required). Client-side filters: minYield (e.g. 0.05=5%), strikeNear (\xB110%), term range, expDate"
|
|
10095
10593
|
},
|
|
10096
10594
|
"quote-and-buy": {
|
|
10595
|
+
toolName: "dcd_subscribe",
|
|
10097
10596
|
usage: "okx earn dcd quote-and-buy --productId <id> --sz <n> --notionalCcy <ccy> [--clOrdId <id>] [--minAnnualizedYield <pct>]",
|
|
10098
10597
|
description: "[CAUTION] Subscribe to a DCD product atomically (quote + execute in one step)"
|
|
10099
10598
|
},
|
|
10100
10599
|
"redeem-execute": {
|
|
10600
|
+
toolName: "dcd_redeem",
|
|
10101
10601
|
usage: "okx earn dcd redeem-execute --ordId <id>",
|
|
10102
10602
|
description: "[CAUTION] Re-quote and execute early redemption in one step (recommended for AI agent use)"
|
|
10103
10603
|
},
|
|
10104
10604
|
order: {
|
|
10605
|
+
toolName: "dcd_get_order_state",
|
|
10105
10606
|
usage: "okx earn dcd order --ordId <id>",
|
|
10106
10607
|
description: "Query current state of a DCD order"
|
|
10107
10608
|
},
|
|
10108
10609
|
orders: {
|
|
10610
|
+
toolName: "dcd_get_orders",
|
|
10109
10611
|
usage: "okx earn dcd orders [--ordId <id>] [--productId <id>] [--uly <uly>] [--state <state>] [--limit <n>]",
|
|
10110
10612
|
description: "Get DCD order history. State: initial|live|pending_settle|settled|pending_redeem|redeemed|rejected"
|
|
10111
10613
|
}
|
|
@@ -10113,6 +10615,7 @@ var HELP_TREE = {
|
|
|
10113
10615
|
}
|
|
10114
10616
|
}
|
|
10115
10617
|
},
|
|
10618
|
+
// ── bot ────────────────────────────────────────────────────────────────────
|
|
10116
10619
|
bot: {
|
|
10117
10620
|
description: "Trading bot strategies (grid, dca)",
|
|
10118
10621
|
subgroups: {
|
|
@@ -10120,22 +10623,27 @@ var HELP_TREE = {
|
|
|
10120
10623
|
description: "Grid trading bot \u2014 create, monitor, and stop grid orders",
|
|
10121
10624
|
commands: {
|
|
10122
10625
|
orders: {
|
|
10626
|
+
toolName: "grid_get_orders",
|
|
10123
10627
|
usage: "okx bot grid orders --algoOrdType <grid|contract_grid|moon_grid> [--instId <id>] [--algoId <id>] [--history]",
|
|
10124
10628
|
description: "List active or historical grid bot orders"
|
|
10125
10629
|
},
|
|
10126
10630
|
details: {
|
|
10631
|
+
toolName: "grid_get_order_details",
|
|
10127
10632
|
usage: "okx bot grid details --algoOrdType <type> --algoId <id>",
|
|
10128
10633
|
description: "Get details of a specific grid bot order"
|
|
10129
10634
|
},
|
|
10130
10635
|
"sub-orders": {
|
|
10636
|
+
toolName: "grid_get_sub_orders",
|
|
10131
10637
|
usage: "okx bot grid sub-orders --algoOrdType <type> --algoId <id> [--live]",
|
|
10132
10638
|
description: "List sub-orders of a grid bot (filled or live)"
|
|
10133
10639
|
},
|
|
10134
10640
|
create: {
|
|
10641
|
+
toolName: "grid_create_order",
|
|
10135
10642
|
usage: "okx bot grid create --instId <id> --algoOrdType <grid|contract_grid> --maxPx <px> --minPx <px> --gridNum <n>\n [--runType <1|2>] [--quoteSz <n>] [--baseSz <n>]\n [--direction <long|short|neutral>] [--lever <n>] [--sz <n>] [--basePos] [--no-basePos]\n [--tpTriggerPx <px>] [--slTriggerPx <px>] [--tpRatio <n>] [--slRatio <n>] [--algoClOrdId <id>]",
|
|
10136
10643
|
description: "Create a new grid bot order (contract grid opens base position by default)"
|
|
10137
10644
|
},
|
|
10138
10645
|
stop: {
|
|
10646
|
+
toolName: "grid_stop_order",
|
|
10139
10647
|
usage: "okx bot grid stop --algoId <id> --algoOrdType <type> --instId <id> [--stopType <1|2|3|5|6>]",
|
|
10140
10648
|
description: "Stop a running grid bot order"
|
|
10141
10649
|
}
|
|
@@ -10145,22 +10653,27 @@ var HELP_TREE = {
|
|
|
10145
10653
|
description: "DCA (Martingale) bot \u2014 spot or contract recurring buys",
|
|
10146
10654
|
commands: {
|
|
10147
10655
|
orders: {
|
|
10656
|
+
toolName: "dca_get_orders",
|
|
10148
10657
|
usage: "okx bot dca orders [--algoOrdType <spot_dca|contract_dca>] [--algoId <id>] [--instId <id>] [--history]",
|
|
10149
10658
|
description: "List DCA bots (spot and/or contract)"
|
|
10150
10659
|
},
|
|
10151
10660
|
details: {
|
|
10661
|
+
toolName: "dca_get_order_details",
|
|
10152
10662
|
usage: "okx bot dca details --algoOrdType <spot_dca|contract_dca> --algoId <id>",
|
|
10153
10663
|
description: "Get DCA bot details (spot or contract)"
|
|
10154
10664
|
},
|
|
10155
10665
|
"sub-orders": {
|
|
10666
|
+
toolName: "dca_get_sub_orders",
|
|
10156
10667
|
usage: "okx bot dca sub-orders --algoOrdType <spot_dca|contract_dca> --algoId <id> [--cycleId <id>]",
|
|
10157
10668
|
description: "Get DCA cycles/orders (spot or contract)"
|
|
10158
10669
|
},
|
|
10159
10670
|
create: {
|
|
10671
|
+
toolName: "dca_create_order",
|
|
10160
10672
|
usage: "okx bot dca create --algoOrdType <spot_dca|contract_dca> --instId <id> --direction <long|short>\n --initOrdAmt <n> --maxSafetyOrds <n> --tpPct <n>\n [--lever <n>] [--safetyOrdAmt <n>] [--pxSteps <n>] [--pxStepsMult <n>] [--volMult <n>]\n [--slPct <n>] [--slMode <limit|market>] [--allowReinvest <true|false>]\n [--triggerStrategy <instant|price|rsi>] [--triggerPx <price>]\n [--triggerCond <cross_up|cross_down>] [--thold <n>] [--timeframe <tf>] [--timePeriod <n>]\n [--algoClOrdId <id>] [--reserveFunds <true|false>] [--tradeQuoteCcy <ccy>]\n Note: --lever required for contract_dca; safetyOrdAmt, pxSteps, pxStepsMult, volMult required when maxSafetyOrds > 0\n triggerStrategy: contract_dca supports instant|price|rsi; spot_dca supports instant|rsi",
|
|
10161
10673
|
description: "Create a DCA (Martingale) bot (spot or contract)"
|
|
10162
10674
|
},
|
|
10163
10675
|
stop: {
|
|
10676
|
+
toolName: "dca_stop_order",
|
|
10164
10677
|
usage: "okx bot dca stop --algoOrdType <spot_dca|contract_dca> --algoId <id> [--stopType <1|2>]\n Note: --stopType required for spot_dca (1=sell all, 2=keep tokens)",
|
|
10165
10678
|
description: "Stop a DCA bot (spot or contract)"
|
|
10166
10679
|
}
|
|
@@ -10168,73 +10681,254 @@ var HELP_TREE = {
|
|
|
10168
10681
|
}
|
|
10169
10682
|
}
|
|
10170
10683
|
},
|
|
10684
|
+
// ── config ─────────────────────────────────────────────────────────────────
|
|
10171
10685
|
config: {
|
|
10172
10686
|
description: "Manage CLI configuration profiles",
|
|
10173
10687
|
commands: {
|
|
10174
10688
|
init: {
|
|
10689
|
+
toolName: null,
|
|
10175
10690
|
usage: "okx config init [--lang zh]",
|
|
10176
10691
|
description: "Initialize a new configuration profile interactively"
|
|
10177
10692
|
},
|
|
10178
10693
|
show: {
|
|
10694
|
+
toolName: null,
|
|
10179
10695
|
usage: "okx config show",
|
|
10180
10696
|
description: `Show current configuration (file: ${configFilePath()})`
|
|
10181
10697
|
},
|
|
10182
10698
|
set: {
|
|
10699
|
+
toolName: null,
|
|
10183
10700
|
usage: "okx config set <key> <value>",
|
|
10184
10701
|
description: "Set a configuration value"
|
|
10185
10702
|
},
|
|
10186
10703
|
"setup-clients": {
|
|
10704
|
+
toolName: null,
|
|
10187
10705
|
usage: "okx config setup-clients",
|
|
10188
10706
|
description: "Set up MCP client integrations (Cursor, Windsurf, etc.)"
|
|
10189
10707
|
}
|
|
10190
10708
|
}
|
|
10191
10709
|
},
|
|
10710
|
+
// ── setup ──────────────────────────────────────────────────────────────────
|
|
10192
10711
|
setup: {
|
|
10193
10712
|
description: "Set up client integrations (Cursor, Windsurf, Claude, etc.)",
|
|
10194
10713
|
usage: `okx setup --client <${SUPPORTED_CLIENTS.join("|")}> [--profile <name>] [--modules <list>]`
|
|
10195
10714
|
},
|
|
10715
|
+
// ── doh ────────────────────────────────────────────────────────────────────
|
|
10716
|
+
doh: {
|
|
10717
|
+
description: "Manage DoH (DNS-over-HTTPS) resolver binary",
|
|
10718
|
+
commands: {
|
|
10719
|
+
status: {
|
|
10720
|
+
toolName: null,
|
|
10721
|
+
usage: "okx doh status [--json]",
|
|
10722
|
+
description: "Show DoH binary info, checksum, and CDN match status"
|
|
10723
|
+
},
|
|
10724
|
+
install: {
|
|
10725
|
+
toolName: null,
|
|
10726
|
+
usage: "okx doh install [--json]",
|
|
10727
|
+
description: "Download or update the DoH resolver binary"
|
|
10728
|
+
},
|
|
10729
|
+
remove: {
|
|
10730
|
+
toolName: null,
|
|
10731
|
+
usage: "okx doh remove [--force] [--json]",
|
|
10732
|
+
description: "Remove the DoH resolver binary (prompts for confirmation without --force)"
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
},
|
|
10736
|
+
// ── diagnose ───────────────────────────────────────────────────────────────
|
|
10196
10737
|
diagnose: {
|
|
10197
10738
|
description: "Run network / MCP server diagnostics",
|
|
10198
10739
|
usage: "okx diagnose [--cli | --mcp | --all] [--profile <name>] [--demo | --live] [--output <file>]"
|
|
10199
10740
|
},
|
|
10741
|
+
// ── skill ──────────────────────────────────────────────────────────────────
|
|
10200
10742
|
skill: {
|
|
10201
10743
|
description: "OKX Skills Marketplace \u2014 search, install, and manage agent skills",
|
|
10202
10744
|
commands: {
|
|
10203
10745
|
search: {
|
|
10746
|
+
toolName: "skills_search",
|
|
10204
10747
|
usage: "okx skill search [--keyword <kw>] [--categories <id>] [--page <n>] [--limit <n>]",
|
|
10205
10748
|
description: "Search for skills in the marketplace"
|
|
10206
10749
|
},
|
|
10207
10750
|
categories: {
|
|
10751
|
+
toolName: "skills_get_categories",
|
|
10208
10752
|
usage: "okx skill categories",
|
|
10209
10753
|
description: "List available skill categories"
|
|
10210
10754
|
},
|
|
10211
10755
|
add: {
|
|
10756
|
+
// Composite: downloads + installs via npx; no single ToolSpec
|
|
10757
|
+
toolName: null,
|
|
10212
10758
|
usage: "okx skill add <name>",
|
|
10213
10759
|
description: "Download and install a skill to detected agents"
|
|
10214
10760
|
},
|
|
10215
10761
|
download: {
|
|
10762
|
+
// CLI calls downloadSkillZip directly (same capability as skills_download ToolSpec)
|
|
10763
|
+
toolName: "skills_download",
|
|
10216
10764
|
usage: "okx skill download <name> [--dir <path>] [--format zip|skill]",
|
|
10217
10765
|
description: "Download a skill package without installing"
|
|
10218
10766
|
},
|
|
10219
10767
|
remove: {
|
|
10768
|
+
toolName: null,
|
|
10220
10769
|
usage: "okx skill remove <name>",
|
|
10221
10770
|
description: "Remove an installed skill"
|
|
10222
10771
|
},
|
|
10223
10772
|
check: {
|
|
10773
|
+
// Uses skills_search internally; skills_search already registered above
|
|
10774
|
+
toolName: null,
|
|
10224
10775
|
usage: "okx skill check <name>",
|
|
10225
10776
|
description: "Check if an installed skill has a newer version"
|
|
10226
10777
|
},
|
|
10227
10778
|
list: {
|
|
10779
|
+
toolName: null,
|
|
10228
10780
|
usage: "okx skill list",
|
|
10229
10781
|
description: "List all locally installed skills"
|
|
10230
10782
|
}
|
|
10231
10783
|
}
|
|
10232
10784
|
},
|
|
10785
|
+
// ── upgrade ────────────────────────────────────────────────────────────────
|
|
10233
10786
|
upgrade: {
|
|
10234
10787
|
description: "Upgrade okx CLI and MCP server to the latest stable version",
|
|
10235
10788
|
usage: "okx upgrade [--check] [--beta] [--force] [--json]"
|
|
10236
10789
|
}
|
|
10237
10790
|
};
|
|
10791
|
+
|
|
10792
|
+
// src/help-generator.ts
|
|
10793
|
+
function buildSpecMap() {
|
|
10794
|
+
return new Map(allToolSpecs().map((s) => [s.name, s]));
|
|
10795
|
+
}
|
|
10796
|
+
function resolveCommandDescription(entry, specMap, fallback = "(no description)") {
|
|
10797
|
+
if (entry.description) return entry.description;
|
|
10798
|
+
if (entry.toolName != null) {
|
|
10799
|
+
const spec = specMap.get(entry.toolName);
|
|
10800
|
+
if (spec?.description) return spec.description.split(/\.\s/)[0] + ".";
|
|
10801
|
+
}
|
|
10802
|
+
return fallback;
|
|
10803
|
+
}
|
|
10804
|
+
function buildCommands(commands, specMap) {
|
|
10805
|
+
const result = {};
|
|
10806
|
+
for (const [name, entry] of Object.entries(commands)) {
|
|
10807
|
+
result[name] = {
|
|
10808
|
+
usage: entry.usage,
|
|
10809
|
+
description: resolveCommandDescription(entry, specMap)
|
|
10810
|
+
};
|
|
10811
|
+
}
|
|
10812
|
+
return result;
|
|
10813
|
+
}
|
|
10814
|
+
function buildGroupInfo(key, mod, specMap) {
|
|
10815
|
+
const description = mod.description ?? MODULE_DESCRIPTIONS[key] ?? key;
|
|
10816
|
+
return {
|
|
10817
|
+
description,
|
|
10818
|
+
usage: mod.usage,
|
|
10819
|
+
commands: mod.commands ? buildCommands(mod.commands, specMap) : void 0,
|
|
10820
|
+
subgroups: mod.subgroups ? buildSubgroups(mod.subgroups, specMap) : void 0
|
|
10821
|
+
};
|
|
10822
|
+
}
|
|
10823
|
+
function buildSubgroups(subgroups, specMap) {
|
|
10824
|
+
const result = {};
|
|
10825
|
+
for (const [name, entry] of Object.entries(subgroups)) {
|
|
10826
|
+
result[name] = buildGroupInfo(name, entry, specMap);
|
|
10827
|
+
}
|
|
10828
|
+
return result;
|
|
10829
|
+
}
|
|
10830
|
+
var _cached = null;
|
|
10831
|
+
function generateHelpTree() {
|
|
10832
|
+
if (_cached) return _cached;
|
|
10833
|
+
const specMap = buildSpecMap();
|
|
10834
|
+
const tree = {};
|
|
10835
|
+
for (const [key, mod] of Object.entries(CLI_REGISTRY)) {
|
|
10836
|
+
tree[key] = buildGroupInfo(key, mod, specMap);
|
|
10837
|
+
}
|
|
10838
|
+
_cached = tree;
|
|
10839
|
+
return tree;
|
|
10840
|
+
}
|
|
10841
|
+
|
|
10842
|
+
// src/commands/discovery.ts
|
|
10843
|
+
function extractParameters(toolName, specMap) {
|
|
10844
|
+
if (toolName == null) return [];
|
|
10845
|
+
const spec = specMap.get(toolName);
|
|
10846
|
+
if (!spec?.inputSchema) return [];
|
|
10847
|
+
const schema = spec.inputSchema;
|
|
10848
|
+
if (!schema.properties) return [];
|
|
10849
|
+
const required = new Set(schema.required ?? []);
|
|
10850
|
+
return Object.entries(schema.properties).map(([name, prop]) => ({
|
|
10851
|
+
name,
|
|
10852
|
+
type: prop.type ?? "string",
|
|
10853
|
+
required: required.has(name),
|
|
10854
|
+
description: prop.description
|
|
10855
|
+
}));
|
|
10856
|
+
}
|
|
10857
|
+
function collectCommands(modulePath, mod, specMap, commands) {
|
|
10858
|
+
for (const [cmdName, entry] of Object.entries(mod.commands ?? {})) {
|
|
10859
|
+
commands.push({
|
|
10860
|
+
path: `${modulePath} ${cmdName}`,
|
|
10861
|
+
toolName: entry.toolName,
|
|
10862
|
+
description: resolveCommandDescription(entry, specMap, ""),
|
|
10863
|
+
parameters: extractParameters(entry.toolName, specMap)
|
|
10864
|
+
});
|
|
10865
|
+
}
|
|
10866
|
+
for (const [sgName, sg] of Object.entries(mod.subgroups ?? {})) {
|
|
10867
|
+
collectCommands(`${modulePath} ${sgName}`, sg, specMap, commands);
|
|
10868
|
+
}
|
|
10869
|
+
}
|
|
10870
|
+
function getDiscoveryOutput() {
|
|
10871
|
+
const specs = allToolSpecs();
|
|
10872
|
+
const specMap = new Map(specs.map((s) => [s.name, s]));
|
|
10873
|
+
const moduleDescMap = new Map(specs.map((s) => [s.module, s.description]));
|
|
10874
|
+
const version = readCliVersion();
|
|
10875
|
+
const modules = [];
|
|
10876
|
+
for (const [moduleKey, moduleEntry] of Object.entries(CLI_REGISTRY)) {
|
|
10877
|
+
const commands = [];
|
|
10878
|
+
collectCommands(`okx ${moduleKey}`, moduleEntry, specMap, commands);
|
|
10879
|
+
const description = moduleEntry.description ?? MODULE_DESCRIPTIONS[moduleKey] ?? moduleDescMap.get(moduleKey) ?? moduleKey;
|
|
10880
|
+
modules.push({
|
|
10881
|
+
name: moduleKey,
|
|
10882
|
+
description,
|
|
10883
|
+
commands
|
|
10884
|
+
});
|
|
10885
|
+
}
|
|
10886
|
+
const totalTools = modules.reduce(
|
|
10887
|
+
(sum, m) => sum + m.commands.filter((c) => c.toolName !== null).length,
|
|
10888
|
+
0
|
|
10889
|
+
);
|
|
10890
|
+
return { version, totalTools, modules };
|
|
10891
|
+
}
|
|
10892
|
+
function cmdListTools(json) {
|
|
10893
|
+
const data = getDiscoveryOutput();
|
|
10894
|
+
if (json) {
|
|
10895
|
+
output(JSON.stringify(data, null, 2) + "\n");
|
|
10896
|
+
return;
|
|
10897
|
+
}
|
|
10898
|
+
const lines = [
|
|
10899
|
+
"",
|
|
10900
|
+
`OKX CLI v${data.version} \u2014 ${data.totalTools} tool-backed commands across ${data.modules.length} modules`,
|
|
10901
|
+
"",
|
|
10902
|
+
"Modules:"
|
|
10903
|
+
];
|
|
10904
|
+
for (const mod of data.modules) {
|
|
10905
|
+
const toolCmds = mod.commands.filter((c) => c.toolName !== null).length;
|
|
10906
|
+
if (toolCmds > 0) {
|
|
10907
|
+
lines.push(` ${mod.name.padEnd(14)}${toolCmds} commands`);
|
|
10908
|
+
}
|
|
10909
|
+
}
|
|
10910
|
+
lines.push("", 'Use "okx list-tools --json" for machine-readable output.', "");
|
|
10911
|
+
output(lines.join("\n"));
|
|
10912
|
+
}
|
|
10913
|
+
|
|
10914
|
+
// src/config/loader.ts
|
|
10915
|
+
function loadProfileConfig(opts) {
|
|
10916
|
+
return loadConfig({
|
|
10917
|
+
profile: opts.profile,
|
|
10918
|
+
modules: opts.modules,
|
|
10919
|
+
readOnly: opts.readOnly ?? false,
|
|
10920
|
+
demo: opts.demo,
|
|
10921
|
+
live: opts.live,
|
|
10922
|
+
site: opts.site,
|
|
10923
|
+
userAgent: opts.userAgent,
|
|
10924
|
+
sourceTag: opts.sourceTag,
|
|
10925
|
+
verbose: opts.verbose
|
|
10926
|
+
});
|
|
10927
|
+
}
|
|
10928
|
+
|
|
10929
|
+
// src/help.ts
|
|
10930
|
+
import { EOL as EOL2 } from "os";
|
|
10931
|
+
var HELP_TREE = generateHelpTree();
|
|
10238
10932
|
function printGlobalHelp() {
|
|
10239
10933
|
const lines = [
|
|
10240
10934
|
"",
|
|
@@ -13356,14 +14050,14 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
13356
14050
|
}
|
|
13357
14051
|
|
|
13358
14052
|
// src/commands/skill.ts
|
|
13359
|
-
import { tmpdir, homedir as
|
|
13360
|
-
import { join as
|
|
13361
|
-
import { mkdirSync as
|
|
14053
|
+
import { tmpdir, homedir as homedir10 } from "os";
|
|
14054
|
+
import { join as join12, dirname as dirname8 } from "path";
|
|
14055
|
+
import { mkdirSync as mkdirSync10, rmSync, existsSync as existsSync8, copyFileSync as copyFileSync2 } from "fs";
|
|
13362
14056
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
13363
14057
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
13364
14058
|
function resolveNpx() {
|
|
13365
|
-
const sibling =
|
|
13366
|
-
if (
|
|
14059
|
+
const sibling = join12(dirname8(process.execPath), "npx");
|
|
14060
|
+
if (existsSync8(sibling)) return sibling;
|
|
13367
14061
|
return "npx";
|
|
13368
14062
|
}
|
|
13369
14063
|
var THIRD_PARTY_INSTALL_NOTICE = "Note: This skill was created by a third-party developer, not by OKX. Review SKILL.md before use.";
|
|
@@ -13416,13 +14110,13 @@ async function cmdSkillCategories(run, json) {
|
|
|
13416
14110
|
outputLine("");
|
|
13417
14111
|
}
|
|
13418
14112
|
async function cmdSkillAdd(name, config, json) {
|
|
13419
|
-
const tmpBase =
|
|
13420
|
-
|
|
14113
|
+
const tmpBase = join12(tmpdir(), `okx-skill-${randomUUID2()}`);
|
|
14114
|
+
mkdirSync10(tmpBase, { recursive: true });
|
|
13421
14115
|
try {
|
|
13422
14116
|
outputLine(`Downloading ${name}...`);
|
|
13423
14117
|
const client = new OkxRestClient(config);
|
|
13424
14118
|
const zipPath = await downloadSkillZip(client, name, tmpBase);
|
|
13425
|
-
const contentDir = await extractSkillZip(zipPath,
|
|
14119
|
+
const contentDir = await extractSkillZip(zipPath, join12(tmpBase, "content"));
|
|
13426
14120
|
const meta = readMetaJson(contentDir);
|
|
13427
14121
|
validateSkillMdExists(contentDir);
|
|
13428
14122
|
outputLine("Installing to detected agents...");
|
|
@@ -13432,7 +14126,7 @@ async function cmdSkillAdd(name, config, json) {
|
|
|
13432
14126
|
timeout: 6e4
|
|
13433
14127
|
});
|
|
13434
14128
|
} catch (e) {
|
|
13435
|
-
const savedZip =
|
|
14129
|
+
const savedZip = join12(process.cwd(), `${name}.zip`);
|
|
13436
14130
|
try {
|
|
13437
14131
|
copyFileSync2(zipPath, savedZip);
|
|
13438
14132
|
} catch {
|
|
@@ -13471,7 +14165,7 @@ function cmdSkillRemove(name, json) {
|
|
|
13471
14165
|
timeout: 6e4
|
|
13472
14166
|
});
|
|
13473
14167
|
} catch {
|
|
13474
|
-
const agentsPath =
|
|
14168
|
+
const agentsPath = join12(homedir10(), ".agents", "skills", name);
|
|
13475
14169
|
try {
|
|
13476
14170
|
rmSync(agentsPath, { recursive: true, force: true });
|
|
13477
14171
|
} catch {
|
|
@@ -13544,10 +14238,171 @@ function printSkillInstallResult(meta, json) {
|
|
|
13544
14238
|
}
|
|
13545
14239
|
}
|
|
13546
14240
|
|
|
14241
|
+
// src/commands/doh.ts
|
|
14242
|
+
import readline from "readline";
|
|
14243
|
+
function resolveChecksumMatch(local, cdnChecksum, cdnError) {
|
|
14244
|
+
if (!local.exists) return "not-installed";
|
|
14245
|
+
if (cdnError || !cdnChecksum) return "unavailable";
|
|
14246
|
+
if (cdnChecksum.sha256 === local.sha256) return "match";
|
|
14247
|
+
return "mismatch";
|
|
14248
|
+
}
|
|
14249
|
+
function checksumMatchLabel(match) {
|
|
14250
|
+
if (match === "match") return "\u2713 match";
|
|
14251
|
+
if (match === "mismatch") return "\u2717 mismatch (update available)";
|
|
14252
|
+
return "CDN unreachable";
|
|
14253
|
+
}
|
|
14254
|
+
function formatStatusText(local, checksumMatch, cdnChecksum, runtimeMode) {
|
|
14255
|
+
outputLine("");
|
|
14256
|
+
outputLine(" DoH Resolver Status");
|
|
14257
|
+
outputLine(" " + "\u2500".repeat(40));
|
|
14258
|
+
outputLine(` Binary path : ${local.binaryPath}`);
|
|
14259
|
+
outputLine(` Installed : ${local.exists ? "yes" : "no"}`);
|
|
14260
|
+
outputLine(` Platform : ${local.platform ?? "(unsupported)"}`);
|
|
14261
|
+
if (local.exists) {
|
|
14262
|
+
outputLine(` File size : ${formatBytes(local.fileSize)}`);
|
|
14263
|
+
outputLine(` SHA-256 : ${local.sha256 ?? "(unknown)"}`);
|
|
14264
|
+
outputLine(` CDN check : ${checksumMatchLabel(checksumMatch)}`);
|
|
14265
|
+
if (cdnChecksum) {
|
|
14266
|
+
outputLine(` CDN source : ${cdnChecksum.source}`);
|
|
14267
|
+
}
|
|
14268
|
+
}
|
|
14269
|
+
outputLine(` Runtime mode: ${runtimeMode}`);
|
|
14270
|
+
outputLine("");
|
|
14271
|
+
}
|
|
14272
|
+
async function cmdDohStatus(json, binaryPath) {
|
|
14273
|
+
const local = getDohStatus(binaryPath);
|
|
14274
|
+
let runtimeMode = "no cache";
|
|
14275
|
+
try {
|
|
14276
|
+
const cacheEntry = readCache("www.okx.com");
|
|
14277
|
+
if (cacheEntry) {
|
|
14278
|
+
runtimeMode = cacheEntry.mode;
|
|
14279
|
+
}
|
|
14280
|
+
} catch {
|
|
14281
|
+
}
|
|
14282
|
+
let cdnChecksum = null;
|
|
14283
|
+
let cdnError = null;
|
|
14284
|
+
if (local.exists) {
|
|
14285
|
+
try {
|
|
14286
|
+
cdnChecksum = await fetchCdnChecksum(void 0, 5e3);
|
|
14287
|
+
} catch (err) {
|
|
14288
|
+
cdnError = err instanceof Error ? err.message : String(err);
|
|
14289
|
+
}
|
|
14290
|
+
}
|
|
14291
|
+
const checksumMatch = resolveChecksumMatch(local, cdnChecksum, cdnError);
|
|
14292
|
+
if (json) {
|
|
14293
|
+
outputLine(
|
|
14294
|
+
JSON.stringify({
|
|
14295
|
+
binaryPath: local.binaryPath,
|
|
14296
|
+
exists: local.exists,
|
|
14297
|
+
platform: local.platform,
|
|
14298
|
+
fileSize: local.fileSize ?? null,
|
|
14299
|
+
sha256: local.sha256 ?? null,
|
|
14300
|
+
cdnMatch: checksumMatch,
|
|
14301
|
+
cdnSha256: cdnChecksum?.sha256 ?? null,
|
|
14302
|
+
cdnSource: cdnChecksum?.source ?? null,
|
|
14303
|
+
runtimeMode
|
|
14304
|
+
})
|
|
14305
|
+
);
|
|
14306
|
+
return;
|
|
14307
|
+
}
|
|
14308
|
+
formatStatusText(local, checksumMatch, cdnChecksum, runtimeMode);
|
|
14309
|
+
}
|
|
14310
|
+
async function cmdDohInstall(json, binaryPath) {
|
|
14311
|
+
const messages2 = [];
|
|
14312
|
+
const onProgress = (msg) => {
|
|
14313
|
+
if (!json) {
|
|
14314
|
+
outputLine(` ${msg}`);
|
|
14315
|
+
}
|
|
14316
|
+
messages2.push(msg);
|
|
14317
|
+
};
|
|
14318
|
+
if (!json) {
|
|
14319
|
+
outputLine("");
|
|
14320
|
+
outputLine(" Installing DoH resolver...");
|
|
14321
|
+
}
|
|
14322
|
+
const result = await installDohBinary(binaryPath, void 0, onProgress);
|
|
14323
|
+
if (json) {
|
|
14324
|
+
outputLine(JSON.stringify({ status: result.status, source: result.source ?? null, error: result.error ?? null, messages: messages2 }));
|
|
14325
|
+
if (result.status === "failed") {
|
|
14326
|
+
process.exitCode = 1;
|
|
14327
|
+
}
|
|
14328
|
+
return;
|
|
14329
|
+
}
|
|
14330
|
+
if (result.status === "installed") {
|
|
14331
|
+
outputLine(` \u2713 DoH resolver installed successfully (${result.source ?? ""})`);
|
|
14332
|
+
} else if (result.status === "up-to-date") {
|
|
14333
|
+
outputLine(" \u2713 DoH resolver is already up to date");
|
|
14334
|
+
} else {
|
|
14335
|
+
errorLine(` \u2717 Installation failed: ${result.error ?? "unknown error"}`);
|
|
14336
|
+
errorLine(" Hint: check network connectivity or try again later");
|
|
14337
|
+
process.exitCode = 1;
|
|
14338
|
+
}
|
|
14339
|
+
outputLine("");
|
|
14340
|
+
}
|
|
14341
|
+
async function cmdDohRemove(force, json, binaryPath) {
|
|
14342
|
+
const local = getDohStatus(binaryPath);
|
|
14343
|
+
if (!local.exists) {
|
|
14344
|
+
if (json) {
|
|
14345
|
+
outputLine(JSON.stringify({ status: "not-installed" }));
|
|
14346
|
+
} else {
|
|
14347
|
+
outputLine(" DoH resolver is not installed.");
|
|
14348
|
+
}
|
|
14349
|
+
return;
|
|
14350
|
+
}
|
|
14351
|
+
if (!force) {
|
|
14352
|
+
if (!process.stdin.isTTY) {
|
|
14353
|
+
errorLine(" Error: stdin is not a TTY. Use --force to skip confirmation.");
|
|
14354
|
+
process.exitCode = 1;
|
|
14355
|
+
return;
|
|
14356
|
+
}
|
|
14357
|
+
const confirmed = await askConfirmation(
|
|
14358
|
+
` Remove DoH resolver at ${local.binaryPath}? [y/N] `
|
|
14359
|
+
);
|
|
14360
|
+
if (!confirmed) {
|
|
14361
|
+
outputLine(" Cancelled.");
|
|
14362
|
+
return;
|
|
14363
|
+
}
|
|
14364
|
+
}
|
|
14365
|
+
const result = removeDohBinary(binaryPath);
|
|
14366
|
+
if (json) {
|
|
14367
|
+
outputLine(JSON.stringify({ status: result.status, path: local.binaryPath }));
|
|
14368
|
+
return;
|
|
14369
|
+
}
|
|
14370
|
+
if (result.status === "removed") {
|
|
14371
|
+
outputLine(` \u2713 Removed: ${local.binaryPath}`);
|
|
14372
|
+
} else {
|
|
14373
|
+
outputLine(" DoH resolver is not installed.");
|
|
14374
|
+
}
|
|
14375
|
+
}
|
|
14376
|
+
function formatBytes(bytes) {
|
|
14377
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
14378
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
14379
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
14380
|
+
}
|
|
14381
|
+
function askConfirmation(prompt2) {
|
|
14382
|
+
return new Promise((resolve3) => {
|
|
14383
|
+
const rl = readline.createInterface({
|
|
14384
|
+
input: process.stdin,
|
|
14385
|
+
output: process.stdout
|
|
14386
|
+
});
|
|
14387
|
+
rl.question(prompt2, (answer) => {
|
|
14388
|
+
rl.close();
|
|
14389
|
+
resolve3(answer.trim().toLowerCase() === "y");
|
|
14390
|
+
});
|
|
14391
|
+
});
|
|
14392
|
+
}
|
|
14393
|
+
|
|
13547
14394
|
// src/index.ts
|
|
13548
14395
|
var _require3 = createRequire3(import.meta.url);
|
|
13549
14396
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
13550
|
-
var GIT_HASH2 = true ? "
|
|
14397
|
+
var GIT_HASH2 = true ? "63a5613" : "dev";
|
|
14398
|
+
function handleDohCommand(action, json, force, binaryPath) {
|
|
14399
|
+
if (action === "status") return cmdDohStatus(json, binaryPath);
|
|
14400
|
+
if (action === "install") return cmdDohInstall(json, binaryPath);
|
|
14401
|
+
if (action === "remove") return cmdDohRemove(force, json, binaryPath);
|
|
14402
|
+
errorLine(`Unknown doh command: ${action}`);
|
|
14403
|
+
errorLine("Usage: okx doh <status|install|remove>");
|
|
14404
|
+
process.exitCode = 1;
|
|
14405
|
+
}
|
|
13551
14406
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
13552
14407
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
13553
14408
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -14399,6 +15254,24 @@ async function runDiagnose(v) {
|
|
|
14399
15254
|
}
|
|
14400
15255
|
return cmdDiagnose(config, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
|
|
14401
15256
|
}
|
|
15257
|
+
function printVersion() {
|
|
15258
|
+
outputLine(`${CLI_VERSION2} (${GIT_HASH2})`);
|
|
15259
|
+
const dohStatus = getDohStatus(void 0, { skipHash: true });
|
|
15260
|
+
if (dohStatus.exists) {
|
|
15261
|
+
outputLine(`DoH resolver: installed (${dohStatus.platform ?? "unknown"})`);
|
|
15262
|
+
} else {
|
|
15263
|
+
outputLine("DoH resolver: not installed");
|
|
15264
|
+
}
|
|
15265
|
+
}
|
|
15266
|
+
function routeManagementCommand(module, action, rest, json, v) {
|
|
15267
|
+
if (module === "config") return handleConfigCommand(action, rest, json, v.lang, v.force);
|
|
15268
|
+
if (module === "setup") return handleSetupCommand(v);
|
|
15269
|
+
if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
|
|
15270
|
+
if (module === "doh") return handleDohCommand(action, json, v.force ?? false);
|
|
15271
|
+
if (module === "diagnose") return runDiagnose(v);
|
|
15272
|
+
if (module === "list-tools") return cmdListTools(json);
|
|
15273
|
+
return void 0;
|
|
15274
|
+
}
|
|
14402
15275
|
async function main() {
|
|
14403
15276
|
setOutput({
|
|
14404
15277
|
out: (m) => process.stdout.write(m),
|
|
@@ -14407,7 +15280,7 @@ async function main() {
|
|
|
14407
15280
|
checkForUpdates("@okx_ai/okx-trade-cli", CLI_VERSION2);
|
|
14408
15281
|
const { values, positionals } = parseCli(process.argv.slice(2));
|
|
14409
15282
|
if (values.version) {
|
|
14410
|
-
|
|
15283
|
+
printVersion();
|
|
14411
15284
|
return;
|
|
14412
15285
|
}
|
|
14413
15286
|
if (values.help || positionals.length === 0) {
|
|
@@ -14417,10 +15290,8 @@ async function main() {
|
|
|
14417
15290
|
const [module, action, ...rest] = positionals;
|
|
14418
15291
|
const v = values;
|
|
14419
15292
|
const json = v.json ?? false;
|
|
14420
|
-
|
|
14421
|
-
if (
|
|
14422
|
-
if (module === "upgrade") return cmdUpgrade(CLI_VERSION2, { beta: v.beta, check: v.check, force: v.force }, json);
|
|
14423
|
-
if (module === "diagnose") return runDiagnose(v);
|
|
15293
|
+
const mgmt = routeManagementCommand(module, action, rest, json, v);
|
|
15294
|
+
if (mgmt) return mgmt;
|
|
14424
15295
|
const config = loadProfileConfig({ profile: v.profile, demo: v.demo, live: v.live, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
|
|
14425
15296
|
setEnvContext({ demo: config.demo, profile: v.profile ?? "default" });
|
|
14426
15297
|
setJsonEnvEnabled(v.env ?? false);
|
|
@@ -14458,6 +15329,7 @@ export {
|
|
|
14458
15329
|
handleBotDcaCommand,
|
|
14459
15330
|
handleBotGridCommand,
|
|
14460
15331
|
handleConfigCommand,
|
|
15332
|
+
handleDohCommand,
|
|
14461
15333
|
handleEarnCommand,
|
|
14462
15334
|
handleFuturesAlgoCommand,
|
|
14463
15335
|
handleFuturesCommand,
|