@okx_ai/okx-trade-cli 1.2.7 → 1.2.8-beta.1
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 +342 -214
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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 { ProxyAgent } from "undici";
|
|
7
|
+
import { Agent, ProxyAgent } from "undici";
|
|
8
8
|
import { createHmac } from "crypto";
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
@@ -847,6 +847,13 @@ 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
|
+
}
|
|
850
857
|
function getNow() {
|
|
851
858
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
852
859
|
}
|
|
@@ -1065,12 +1072,61 @@ var OkxRestClient = class {
|
|
|
1065
1072
|
config;
|
|
1066
1073
|
rateLimiter;
|
|
1067
1074
|
dispatcher;
|
|
1068
|
-
|
|
1075
|
+
// DoH proxy state (lazy-resolved on first request)
|
|
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) {
|
|
1069
1087
|
this.config = config;
|
|
1070
1088
|
this.rateLimiter = new RateLimiter(3e4, config.verbose);
|
|
1071
1089
|
if (config.proxyUrl) {
|
|
1072
1090
|
this.dispatcher = new ProxyAgent(config.proxyUrl);
|
|
1073
1091
|
}
|
|
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
|
+
}
|
|
1074
1130
|
}
|
|
1075
1131
|
logRequest(method, url, auth) {
|
|
1076
1132
|
if (!this.config.verbose) return;
|
|
@@ -1214,9 +1270,11 @@ var OkxRestClient = class {
|
|
|
1214
1270
|
};
|
|
1215
1271
|
}
|
|
1216
1272
|
async request(reqConfig) {
|
|
1273
|
+
await this.ensureDoh();
|
|
1217
1274
|
const queryString = buildQueryString(reqConfig.query);
|
|
1218
1275
|
const requestPath = queryString.length > 0 ? `${reqConfig.path}?${queryString}` : reqConfig.path;
|
|
1219
|
-
const
|
|
1276
|
+
const baseUrl = this.dohNode ? this.dohBaseUrl : this.config.baseUrl;
|
|
1277
|
+
const url = `${baseUrl}${requestPath}`;
|
|
1220
1278
|
const bodyJson = reqConfig.body ? JSON.stringify(reqConfig.body) : "";
|
|
1221
1279
|
const timestamp = getNow();
|
|
1222
1280
|
this.logRequest(reqConfig.method, url, reqConfig.auth);
|
|
@@ -1227,7 +1285,9 @@ var OkxRestClient = class {
|
|
|
1227
1285
|
"Content-Type": "application/json",
|
|
1228
1286
|
Accept: "application/json"
|
|
1229
1287
|
});
|
|
1230
|
-
if (this.
|
|
1288
|
+
if (this.dohNode) {
|
|
1289
|
+
headers.set("User-Agent", "OKX/2.7.2");
|
|
1290
|
+
} else if (this.config.userAgent) {
|
|
1231
1291
|
headers.set("User-Agent", this.config.userAgent);
|
|
1232
1292
|
}
|
|
1233
1293
|
if (reqConfig.auth === "private") {
|
|
@@ -1247,6 +1307,8 @@ var OkxRestClient = class {
|
|
|
1247
1307
|
};
|
|
1248
1308
|
if (this.dispatcher) {
|
|
1249
1309
|
fetchOptions.dispatcher = this.dispatcher;
|
|
1310
|
+
} else if (this.dohAgent) {
|
|
1311
|
+
fetchOptions.dispatcher = this.dohAgent;
|
|
1250
1312
|
}
|
|
1251
1313
|
response = await fetch(url, fetchOptions);
|
|
1252
1314
|
} catch (error) {
|
|
@@ -1671,7 +1733,7 @@ function registerAccountTools() {
|
|
|
1671
1733
|
{
|
|
1672
1734
|
name: "account_get_asset_balance",
|
|
1673
1735
|
module: "account",
|
|
1674
|
-
description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account.",
|
|
1736
|
+
description: "Get funding account balance (asset account). Different from account_get_balance which queries the trading account. Optionally includes total asset valuation across all account types (trading, funding, earn, etc.).",
|
|
1675
1737
|
isWrite: false,
|
|
1676
1738
|
inputSchema: {
|
|
1677
1739
|
type: "object",
|
|
@@ -1679,17 +1741,41 @@ function registerAccountTools() {
|
|
|
1679
1741
|
ccy: {
|
|
1680
1742
|
type: "string",
|
|
1681
1743
|
description: "e.g. BTC or BTC,ETH. Omit for all."
|
|
1744
|
+
},
|
|
1745
|
+
showValuation: {
|
|
1746
|
+
type: "boolean",
|
|
1747
|
+
description: "Include total asset valuation breakdown by account type (trading/funding/earn). Default false."
|
|
1682
1748
|
}
|
|
1683
1749
|
}
|
|
1684
1750
|
},
|
|
1685
1751
|
handler: async (rawArgs, context) => {
|
|
1686
1752
|
const args = asRecord(rawArgs);
|
|
1687
|
-
const
|
|
1753
|
+
const ccy = readString(args, "ccy");
|
|
1754
|
+
const showValuation = readBoolean(args, "showValuation");
|
|
1755
|
+
if (showValuation) {
|
|
1756
|
+
const balanceResp2 = await context.client.privateGet(
|
|
1757
|
+
"/api/v5/asset/balances",
|
|
1758
|
+
compactObject({ ccy }),
|
|
1759
|
+
privateRateLimit("account_get_asset_balance", 6)
|
|
1760
|
+
);
|
|
1761
|
+
let valuationData = null;
|
|
1762
|
+
try {
|
|
1763
|
+
const valuationResp = await context.client.privateGet(
|
|
1764
|
+
"/api/v5/asset/asset-valuation",
|
|
1765
|
+
{},
|
|
1766
|
+
privateRateLimit("account_get_asset_valuation", 1)
|
|
1767
|
+
);
|
|
1768
|
+
valuationData = valuationResp.data;
|
|
1769
|
+
} catch {
|
|
1770
|
+
}
|
|
1771
|
+
return { ...normalizeResponse(balanceResp2), valuation: valuationData };
|
|
1772
|
+
}
|
|
1773
|
+
const balanceResp = await context.client.privateGet(
|
|
1688
1774
|
"/api/v5/asset/balances",
|
|
1689
|
-
compactObject({ ccy
|
|
1775
|
+
compactObject({ ccy }),
|
|
1690
1776
|
privateRateLimit("account_get_asset_balance", 6)
|
|
1691
1777
|
);
|
|
1692
|
-
return normalizeResponse(
|
|
1778
|
+
return normalizeResponse(balanceResp);
|
|
1693
1779
|
}
|
|
1694
1780
|
},
|
|
1695
1781
|
{
|
|
@@ -3104,6 +3190,39 @@ function registerGridTools() {
|
|
|
3104
3190
|
];
|
|
3105
3191
|
}
|
|
3106
3192
|
var BASE = "/api/v5/tradingBot/dca";
|
|
3193
|
+
function buildTriggerParam(args, algoOrdType) {
|
|
3194
|
+
const triggerStrategy = readString(args, "triggerStrategy") ?? "instant";
|
|
3195
|
+
if (triggerStrategy === "price" && algoOrdType === "spot_dca") {
|
|
3196
|
+
throw new OkxApiError(
|
|
3197
|
+
"triggerStrategy 'price' is only supported for contract_dca. spot_dca supports: instant, rsi",
|
|
3198
|
+
{ code: "VALIDATION", endpoint: `${BASE}/create` }
|
|
3199
|
+
);
|
|
3200
|
+
}
|
|
3201
|
+
const param = { triggerAction: "start", triggerStrategy };
|
|
3202
|
+
if (triggerStrategy === "price") {
|
|
3203
|
+
param["triggerPx"] = requireString(args, "triggerPx");
|
|
3204
|
+
const triggerCond = readString(args, "triggerCond");
|
|
3205
|
+
if (triggerCond) param["triggerCond"] = triggerCond;
|
|
3206
|
+
} else if (triggerStrategy === "rsi") {
|
|
3207
|
+
param["triggerCond"] = requireString(args, "triggerCond");
|
|
3208
|
+
param["thold"] = requireString(args, "thold");
|
|
3209
|
+
param["timeframe"] = requireString(args, "timeframe");
|
|
3210
|
+
param["timePeriod"] = readString(args, "timePeriod") ?? "14";
|
|
3211
|
+
}
|
|
3212
|
+
return param;
|
|
3213
|
+
}
|
|
3214
|
+
function validateSafetyOrderParams(args, maxSafetyOrds) {
|
|
3215
|
+
if (Number(maxSafetyOrds) <= 0) return;
|
|
3216
|
+
const required = ["safetyOrdAmt", "pxSteps", "pxStepsMult", "volMult"];
|
|
3217
|
+
for (const field of required) {
|
|
3218
|
+
if (!readString(args, field)) {
|
|
3219
|
+
throw new OkxApiError(`${field} is required when maxSafetyOrds > 0`, {
|
|
3220
|
+
code: "VALIDATION",
|
|
3221
|
+
endpoint: `${BASE}/create`
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3107
3226
|
function normalizeWrite2(response) {
|
|
3108
3227
|
const data = response.data;
|
|
3109
3228
|
if (Array.isArray(data) && data.length > 0) {
|
|
@@ -3173,57 +3292,11 @@ function registerDcaTools() {
|
|
|
3173
3292
|
endpoint: `${BASE}/create`
|
|
3174
3293
|
});
|
|
3175
3294
|
}
|
|
3176
|
-
const
|
|
3177
|
-
if (triggerStrategy === "price" && algoOrdType === "spot_dca") {
|
|
3178
|
-
throw new OkxApiError("triggerStrategy 'price' is only supported for contract_dca. spot_dca supports: instant, rsi", {
|
|
3179
|
-
code: "VALIDATION",
|
|
3180
|
-
endpoint: `${BASE}/create`
|
|
3181
|
-
});
|
|
3182
|
-
}
|
|
3183
|
-
const triggerParam = {
|
|
3184
|
-
triggerAction: "start",
|
|
3185
|
-
triggerStrategy
|
|
3186
|
-
};
|
|
3187
|
-
if (triggerStrategy === "price") {
|
|
3188
|
-
triggerParam["triggerPx"] = requireString(args, "triggerPx");
|
|
3189
|
-
const triggerCond = readString(args, "triggerCond");
|
|
3190
|
-
if (triggerCond) {
|
|
3191
|
-
triggerParam["triggerCond"] = triggerCond;
|
|
3192
|
-
}
|
|
3193
|
-
} else if (triggerStrategy === "rsi") {
|
|
3194
|
-
triggerParam["triggerCond"] = requireString(args, "triggerCond");
|
|
3195
|
-
triggerParam["thold"] = requireString(args, "thold");
|
|
3196
|
-
triggerParam["timeframe"] = requireString(args, "timeframe");
|
|
3197
|
-
const timePeriod = readString(args, "timePeriod");
|
|
3198
|
-
triggerParam["timePeriod"] = timePeriod ?? "14";
|
|
3199
|
-
}
|
|
3295
|
+
const triggerParam = buildTriggerParam(args, algoOrdType);
|
|
3200
3296
|
const maxSafetyOrds = requireString(args, "maxSafetyOrds");
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
code: "VALIDATION",
|
|
3205
|
-
endpoint: `${BASE}/create`
|
|
3206
|
-
});
|
|
3207
|
-
}
|
|
3208
|
-
if (!readString(args, "pxSteps")) {
|
|
3209
|
-
throw new OkxApiError("pxSteps is required when maxSafetyOrds > 0", {
|
|
3210
|
-
code: "VALIDATION",
|
|
3211
|
-
endpoint: `${BASE}/create`
|
|
3212
|
-
});
|
|
3213
|
-
}
|
|
3214
|
-
if (!readString(args, "pxStepsMult")) {
|
|
3215
|
-
throw new OkxApiError("pxStepsMult is required when maxSafetyOrds > 0", {
|
|
3216
|
-
code: "VALIDATION",
|
|
3217
|
-
endpoint: `${BASE}/create`
|
|
3218
|
-
});
|
|
3219
|
-
}
|
|
3220
|
-
if (!readString(args, "volMult")) {
|
|
3221
|
-
throw new OkxApiError("volMult is required when maxSafetyOrds > 0", {
|
|
3222
|
-
code: "VALIDATION",
|
|
3223
|
-
endpoint: `${BASE}/create`
|
|
3224
|
-
});
|
|
3225
|
-
}
|
|
3226
|
-
}
|
|
3297
|
+
validateSafetyOrderParams(args, maxSafetyOrds);
|
|
3298
|
+
const allowReinvestRaw = args["allowReinvest"];
|
|
3299
|
+
const allowReinvest = allowReinvestRaw !== void 0 ? allowReinvestRaw === true || allowReinvestRaw === "true" : void 0;
|
|
3227
3300
|
const response = await context.client.privatePost(
|
|
3228
3301
|
`${BASE}/create`,
|
|
3229
3302
|
compactObject({
|
|
@@ -3240,7 +3313,7 @@ function registerDcaTools() {
|
|
|
3240
3313
|
tpPct: requireString(args, "tpPct"),
|
|
3241
3314
|
slPct: readString(args, "slPct"),
|
|
3242
3315
|
slMode: readString(args, "slMode"),
|
|
3243
|
-
allowReinvest
|
|
3316
|
+
allowReinvest,
|
|
3244
3317
|
triggerParams: [triggerParam],
|
|
3245
3318
|
tag: context.config.sourceTag,
|
|
3246
3319
|
algoClOrdId: readString(args, "algoClOrdId"),
|
|
@@ -4800,6 +4873,7 @@ function registerFuturesTools() {
|
|
|
4800
4873
|
}
|
|
4801
4874
|
];
|
|
4802
4875
|
}
|
|
4876
|
+
var TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
4803
4877
|
function registerMarketTools() {
|
|
4804
4878
|
return [
|
|
4805
4879
|
{
|
|
@@ -4899,7 +4973,7 @@ function registerMarketTools() {
|
|
|
4899
4973
|
{
|
|
4900
4974
|
name: "market_get_candles",
|
|
4901
4975
|
module: "market",
|
|
4902
|
-
description: "Get candlestick (OHLCV) data for an instrument.
|
|
4976
|
+
description: "Get candlestick (OHLCV) data for an instrument. Automatically retrieves historical data (back to 2021) when requesting older time ranges. Use the `after` parameter to paginate back in time (the old `history` parameter has been removed). IMPORTANT: Before fetching with `after`/`before`, estimate the number of candles: time_range_ms / bar_interval_ms. If the estimate exceeds ~500 candles, inform the user of the estimated count and ask for confirmation before proceeding.",
|
|
4903
4977
|
isWrite: false,
|
|
4904
4978
|
inputSchema: {
|
|
4905
4979
|
type: "object",
|
|
@@ -4924,29 +4998,29 @@ function registerMarketTools() {
|
|
|
4924
4998
|
limit: {
|
|
4925
4999
|
type: "number",
|
|
4926
5000
|
description: "Max results (default 100)"
|
|
4927
|
-
},
|
|
4928
|
-
history: {
|
|
4929
|
-
type: "boolean",
|
|
4930
|
-
description: "true=older historical data beyond recent window"
|
|
4931
5001
|
}
|
|
4932
5002
|
},
|
|
4933
5003
|
required: ["instId"]
|
|
4934
5004
|
},
|
|
4935
5005
|
handler: async (rawArgs, context) => {
|
|
4936
5006
|
const args = asRecord(rawArgs);
|
|
4937
|
-
const
|
|
4938
|
-
const
|
|
4939
|
-
const
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
5007
|
+
const afterTs = readString(args, "after");
|
|
5008
|
+
const beforeTs = readString(args, "before");
|
|
5009
|
+
const query = compactObject({
|
|
5010
|
+
instId: requireString(args, "instId"),
|
|
5011
|
+
bar: readString(args, "bar"),
|
|
5012
|
+
after: afterTs,
|
|
5013
|
+
before: beforeTs,
|
|
5014
|
+
limit: readNumber(args, "limit")
|
|
5015
|
+
});
|
|
5016
|
+
const rateLimit = publicRateLimit("market_get_candles", 40);
|
|
5017
|
+
const hasTimestamp = afterTs !== void 0 || beforeTs !== void 0;
|
|
5018
|
+
const useHistory = afterTs !== void 0 && Number(afterTs) < Date.now() - TWO_DAYS_MS;
|
|
5019
|
+
const path42 = useHistory ? "/api/v5/market/history-candles" : "/api/v5/market/candles";
|
|
5020
|
+
const response = await context.client.publicGet(path42, query, rateLimit);
|
|
5021
|
+
if (!useHistory && hasTimestamp && Array.isArray(response.data) && response.data.length === 0) {
|
|
5022
|
+
return normalizeResponse(await context.client.publicGet("/api/v5/market/history-candles", query, rateLimit));
|
|
5023
|
+
}
|
|
4950
5024
|
return normalizeResponse(response);
|
|
4951
5025
|
}
|
|
4952
5026
|
},
|
|
@@ -5799,7 +5873,14 @@ function registerOptionTools() {
|
|
|
5799
5873
|
handler: async (rawArgs, context) => {
|
|
5800
5874
|
const args = asRecord(rawArgs);
|
|
5801
5875
|
const status = readString(args, "status") ?? "live";
|
|
5802
|
-
|
|
5876
|
+
let path42;
|
|
5877
|
+
if (status === "archive") {
|
|
5878
|
+
path42 = "/api/v5/trade/orders-history-archive";
|
|
5879
|
+
} else if (status === "history") {
|
|
5880
|
+
path42 = "/api/v5/trade/orders-history";
|
|
5881
|
+
} else {
|
|
5882
|
+
path42 = "/api/v5/trade/orders-pending";
|
|
5883
|
+
}
|
|
5803
5884
|
const response = await context.client.privateGet(
|
|
5804
5885
|
path42,
|
|
5805
5886
|
compactObject({
|
|
@@ -7430,58 +7511,60 @@ function checkClaudeCodeConfig() {
|
|
|
7430
7511
|
if (anyParseError) return "parse-error";
|
|
7431
7512
|
return "not-configured";
|
|
7432
7513
|
}
|
|
7514
|
+
function handleJsonClient(clientId, report, configuredClients) {
|
|
7515
|
+
const configPath = getConfigPath(clientId);
|
|
7516
|
+
if (!configPath) return false;
|
|
7517
|
+
const name = CLIENT_NAMES[clientId];
|
|
7518
|
+
const status = checkJsonMcpConfig(configPath);
|
|
7519
|
+
if (status === "missing") return false;
|
|
7520
|
+
if (status === "found") {
|
|
7521
|
+
ok(name, `configured (${sanitize(configPath)})`);
|
|
7522
|
+
report.add(`client_${clientId}`, `OK ${sanitize(configPath)}`);
|
|
7523
|
+
configuredClients.push(clientId);
|
|
7524
|
+
return false;
|
|
7525
|
+
}
|
|
7526
|
+
if (status === "not-configured") {
|
|
7527
|
+
fail(name, "okx-trade-mcp not found in mcpServers", [`Run: okx setup --client ${clientId}`]);
|
|
7528
|
+
report.add(`client_${clientId}`, "NOT_CONFIGURED");
|
|
7529
|
+
} else {
|
|
7530
|
+
fail(name, `JSON parse error in ${sanitize(configPath)}`, [
|
|
7531
|
+
`Check ${sanitize(configPath)} for JSON syntax errors`,
|
|
7532
|
+
`Then run: okx setup --client ${clientId}`
|
|
7533
|
+
]);
|
|
7534
|
+
report.add(`client_${clientId}`, "PARSE_ERROR");
|
|
7535
|
+
}
|
|
7536
|
+
return true;
|
|
7537
|
+
}
|
|
7538
|
+
function handleClaudeCodeClient(report, configuredClients) {
|
|
7539
|
+
const status = checkClaudeCodeConfig();
|
|
7540
|
+
if (status === "missing") return false;
|
|
7541
|
+
const name = CLIENT_NAMES["claude-code"];
|
|
7542
|
+
if (status === "found") {
|
|
7543
|
+
ok(name, "configured");
|
|
7544
|
+
report.add("client_claude-code", "OK");
|
|
7545
|
+
configuredClients.push("claude-code");
|
|
7546
|
+
return false;
|
|
7547
|
+
}
|
|
7548
|
+
if (status === "not-configured") {
|
|
7549
|
+
warn(name, "installed but okx-trade-mcp not configured", [
|
|
7550
|
+
"Run: okx setup --client claude-code"
|
|
7551
|
+
]);
|
|
7552
|
+
report.add("client_claude-code", "NOT_CONFIGURED");
|
|
7553
|
+
return false;
|
|
7554
|
+
}
|
|
7555
|
+
fail(name, "settings file has JSON parse error", ["Run: okx setup --client claude-code"]);
|
|
7556
|
+
report.add("client_claude-code", "PARSE_ERROR");
|
|
7557
|
+
return true;
|
|
7558
|
+
}
|
|
7433
7559
|
function checkMcpClients(report) {
|
|
7434
7560
|
section("MCP Client Config");
|
|
7435
7561
|
const jsonClients = ["claude-desktop", "cursor", "windsurf"];
|
|
7436
7562
|
const configuredClients = [];
|
|
7437
7563
|
let anyFailed = false;
|
|
7438
7564
|
for (const clientId of jsonClients) {
|
|
7439
|
-
|
|
7440
|
-
if (!configPath) continue;
|
|
7441
|
-
const name = CLIENT_NAMES[clientId];
|
|
7442
|
-
const status = checkJsonMcpConfig(configPath);
|
|
7443
|
-
if (status === "missing") {
|
|
7444
|
-
continue;
|
|
7445
|
-
}
|
|
7446
|
-
if (status === "found") {
|
|
7447
|
-
ok(name, `configured (${sanitize(configPath)})`);
|
|
7448
|
-
report.add(`client_${clientId}`, `OK ${sanitize(configPath)}`);
|
|
7449
|
-
configuredClients.push(clientId);
|
|
7450
|
-
} else if (status === "not-configured") {
|
|
7451
|
-
fail(name, "okx-trade-mcp not found in mcpServers", [
|
|
7452
|
-
`Run: okx setup --client ${clientId}`
|
|
7453
|
-
]);
|
|
7454
|
-
report.add(`client_${clientId}`, "NOT_CONFIGURED");
|
|
7455
|
-
anyFailed = true;
|
|
7456
|
-
} else {
|
|
7457
|
-
fail(name, `JSON parse error in ${sanitize(configPath)}`, [
|
|
7458
|
-
`Check ${sanitize(configPath)} for JSON syntax errors`,
|
|
7459
|
-
`Then run: okx setup --client ${clientId}`
|
|
7460
|
-
]);
|
|
7461
|
-
report.add(`client_${clientId}`, "PARSE_ERROR");
|
|
7462
|
-
anyFailed = true;
|
|
7463
|
-
}
|
|
7464
|
-
}
|
|
7465
|
-
const claudeCodeStatus = checkClaudeCodeConfig();
|
|
7466
|
-
if (claudeCodeStatus !== "missing") {
|
|
7467
|
-
const name = CLIENT_NAMES["claude-code"];
|
|
7468
|
-
if (claudeCodeStatus === "found") {
|
|
7469
|
-
ok(name, "configured");
|
|
7470
|
-
report.add("client_claude-code", "OK");
|
|
7471
|
-
configuredClients.push("claude-code");
|
|
7472
|
-
} else if (claudeCodeStatus === "not-configured") {
|
|
7473
|
-
warn(name, "installed but okx-trade-mcp not configured", [
|
|
7474
|
-
"Run: okx setup --client claude-code"
|
|
7475
|
-
]);
|
|
7476
|
-
report.add("client_claude-code", "NOT_CONFIGURED");
|
|
7477
|
-
} else {
|
|
7478
|
-
fail(name, "settings file has JSON parse error", [
|
|
7479
|
-
"Run: okx setup --client claude-code"
|
|
7480
|
-
]);
|
|
7481
|
-
report.add("client_claude-code", "PARSE_ERROR");
|
|
7482
|
-
anyFailed = true;
|
|
7483
|
-
}
|
|
7565
|
+
if (handleJsonClient(clientId, report, configuredClients)) anyFailed = true;
|
|
7484
7566
|
}
|
|
7567
|
+
if (handleClaudeCodeClient(report, configuredClients)) anyFailed = true;
|
|
7485
7568
|
if (configuredClients.length === 0 && !anyFailed) {
|
|
7486
7569
|
fail("no client", "no MCP client configuration found", [
|
|
7487
7570
|
"Run: okx setup --client <client>",
|
|
@@ -7755,7 +7838,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7755
7838
|
|
|
7756
7839
|
// src/commands/diagnose.ts
|
|
7757
7840
|
var CLI_VERSION = readCliVersion();
|
|
7758
|
-
var GIT_HASH = true ? "
|
|
7841
|
+
var GIT_HASH = true ? "b691d23" : "dev";
|
|
7759
7842
|
function maskKey2(key) {
|
|
7760
7843
|
if (!key) return "(not set)";
|
|
7761
7844
|
if (key.length <= 8) return "****";
|
|
@@ -8676,6 +8759,45 @@ function printGlobalHelp() {
|
|
|
8676
8759
|
lines.push("", 'Run "okx <module> --help" for module details.', "");
|
|
8677
8760
|
output(lines.join(EOL2));
|
|
8678
8761
|
}
|
|
8762
|
+
function printSubgroupOnlyModule(lines, moduleName, group) {
|
|
8763
|
+
const subgroupNames = Object.keys(group.subgroups);
|
|
8764
|
+
const colWidth = Math.max(...subgroupNames.map((n) => n.length)) + 4;
|
|
8765
|
+
lines.push(`Usage: okx ${moduleName} <strategy> <action> [args...]`);
|
|
8766
|
+
lines.push("", `${group.description}.`, "");
|
|
8767
|
+
lines.push("Strategies:");
|
|
8768
|
+
for (const [sgName, sg] of Object.entries(group.subgroups)) {
|
|
8769
|
+
lines.push(` ${sgName.padEnd(colWidth)}${sg.description}`);
|
|
8770
|
+
}
|
|
8771
|
+
lines.push("", `Run "okx ${moduleName} <strategy> --help" for details.`);
|
|
8772
|
+
}
|
|
8773
|
+
function printMixedModule(lines, moduleName, group) {
|
|
8774
|
+
lines.push(`Usage: okx ${moduleName} <action> [args...]`);
|
|
8775
|
+
lines.push("", `${group.description}.`, "", "Commands:");
|
|
8776
|
+
printCommandList(lines, group.commands);
|
|
8777
|
+
lines.push("", "Subgroups:");
|
|
8778
|
+
const subgroupEntries = Object.entries(group.subgroups);
|
|
8779
|
+
const colWidth = Math.max(...subgroupEntries.map(([n]) => n.length)) + 4;
|
|
8780
|
+
for (const [sgName, sg] of subgroupEntries) {
|
|
8781
|
+
lines.push(` ${sgName.padEnd(colWidth)}${sg.description}`);
|
|
8782
|
+
}
|
|
8783
|
+
lines.push("", `Run "okx ${moduleName} <subgroup> --help" for subgroup details.`);
|
|
8784
|
+
}
|
|
8785
|
+
function printCommandsOnlyModule(lines, moduleName, group) {
|
|
8786
|
+
lines.push(`Usage: okx ${moduleName} <action> [args...]`);
|
|
8787
|
+
lines.push("", `${group.description}.`, "", "Commands:");
|
|
8788
|
+
printCommandList(lines, group.commands);
|
|
8789
|
+
}
|
|
8790
|
+
function printUsageModule(lines, group) {
|
|
8791
|
+
lines.push(`Usage: ${group.usage}`);
|
|
8792
|
+
lines.push("", `${group.description}.`);
|
|
8793
|
+
if (group.commands) {
|
|
8794
|
+
lines.push("");
|
|
8795
|
+
for (const cmd of Object.values(group.commands)) {
|
|
8796
|
+
lines.push(` ${cmd.description}`);
|
|
8797
|
+
lines.push(` Usage: ${cmd.usage}`);
|
|
8798
|
+
}
|
|
8799
|
+
}
|
|
8800
|
+
}
|
|
8679
8801
|
function printModuleHelp(moduleName) {
|
|
8680
8802
|
const group = HELP_TREE[moduleName];
|
|
8681
8803
|
if (!group) {
|
|
@@ -8687,40 +8809,13 @@ function printModuleHelp(moduleName) {
|
|
|
8687
8809
|
const hasCommands = group.commands && Object.keys(group.commands).length > 0;
|
|
8688
8810
|
const lines = [""];
|
|
8689
8811
|
if (hasSubgroups && !hasCommands) {
|
|
8690
|
-
|
|
8691
|
-
lines.push(`Usage: okx ${moduleName} <strategy> <action> [args...]`);
|
|
8692
|
-
lines.push("", `${group.description}.`, "");
|
|
8693
|
-
lines.push("Strategies:");
|
|
8694
|
-
const colWidth = Math.max(...subgroupNames.map((n) => n.length)) + 4;
|
|
8695
|
-
for (const [sgName, sg] of Object.entries(group.subgroups)) {
|
|
8696
|
-
lines.push(` ${sgName.padEnd(colWidth)}${sg.description}`);
|
|
8697
|
-
}
|
|
8698
|
-
lines.push("", `Run "okx ${moduleName} <strategy> --help" for details.`);
|
|
8812
|
+
printSubgroupOnlyModule(lines, moduleName, group);
|
|
8699
8813
|
} else if (hasSubgroups && hasCommands) {
|
|
8700
|
-
lines
|
|
8701
|
-
lines.push("", `${group.description}.`, "", "Commands:");
|
|
8702
|
-
printCommandList(lines, group.commands);
|
|
8703
|
-
lines.push("", "Subgroups:");
|
|
8704
|
-
const subgroupEntries = Object.entries(group.subgroups);
|
|
8705
|
-
const colWidth = Math.max(...subgroupEntries.map(([n]) => n.length)) + 4;
|
|
8706
|
-
for (const [sgName, sg] of subgroupEntries) {
|
|
8707
|
-
lines.push(` ${sgName.padEnd(colWidth)}${sg.description}`);
|
|
8708
|
-
}
|
|
8709
|
-
lines.push("", `Run "okx ${moduleName} <subgroup> --help" for subgroup details.`);
|
|
8814
|
+
printMixedModule(lines, moduleName, group);
|
|
8710
8815
|
} else if (hasCommands) {
|
|
8711
|
-
lines
|
|
8712
|
-
lines.push("", `${group.description}.`, "", "Commands:");
|
|
8713
|
-
printCommandList(lines, group.commands);
|
|
8816
|
+
printCommandsOnlyModule(lines, moduleName, group);
|
|
8714
8817
|
} else if (group.usage) {
|
|
8715
|
-
lines
|
|
8716
|
-
lines.push("", `${group.description}.`);
|
|
8717
|
-
if (group.commands) {
|
|
8718
|
-
lines.push("");
|
|
8719
|
-
for (const cmd of Object.values(group.commands)) {
|
|
8720
|
-
lines.push(` ${cmd.description}`);
|
|
8721
|
-
lines.push(` Usage: ${cmd.usage}`);
|
|
8722
|
-
}
|
|
8723
|
-
}
|
|
8818
|
+
printUsageModule(lines, group);
|
|
8724
8819
|
}
|
|
8725
8820
|
lines.push("");
|
|
8726
8821
|
output(lines.join(EOL2));
|
|
@@ -8791,6 +8886,8 @@ var CLI_OPTIONS = {
|
|
|
8791
8886
|
bar: { type: "string" },
|
|
8792
8887
|
limit: { type: "string" },
|
|
8793
8888
|
sz: { type: "string" },
|
|
8889
|
+
after: { type: "string" },
|
|
8890
|
+
before: { type: "string" },
|
|
8794
8891
|
// orders
|
|
8795
8892
|
instId: { type: "string" },
|
|
8796
8893
|
history: { type: "boolean", default: false },
|
|
@@ -8842,6 +8939,7 @@ var CLI_OPTIONS = {
|
|
|
8842
8939
|
quoteCcy: { type: "string" },
|
|
8843
8940
|
// account extras
|
|
8844
8941
|
archive: { type: "boolean", default: false },
|
|
8942
|
+
valuation: { type: "boolean", default: false },
|
|
8845
8943
|
posMode: { type: "string" },
|
|
8846
8944
|
ccy: { type: "string" },
|
|
8847
8945
|
from: { type: "string" },
|
|
@@ -9136,7 +9234,7 @@ async function cmdMarketOrderbook(run, instId, sz, json) {
|
|
|
9136
9234
|
for (const [p, s] of bids) outputLine(` ${p.padStart(16)} ${s}`);
|
|
9137
9235
|
}
|
|
9138
9236
|
async function cmdMarketCandles(run, instId, opts) {
|
|
9139
|
-
const result = await run("market_get_candles", { instId, bar: opts.bar, limit: opts.limit });
|
|
9237
|
+
const result = await run("market_get_candles", { instId, bar: opts.bar, limit: opts.limit, after: opts.after, before: opts.before });
|
|
9140
9238
|
const candles = getData(result);
|
|
9141
9239
|
if (opts.json) return printJson(candles);
|
|
9142
9240
|
printTable(
|
|
@@ -9236,18 +9334,38 @@ async function cmdAccountBalance(run, ccy, json) {
|
|
|
9236
9334
|
}))
|
|
9237
9335
|
);
|
|
9238
9336
|
}
|
|
9239
|
-
async function cmdAccountAssetBalance(run, ccy, json) {
|
|
9240
|
-
const result = await run("account_get_asset_balance", {
|
|
9241
|
-
|
|
9242
|
-
|
|
9337
|
+
async function cmdAccountAssetBalance(run, ccy, json, showValuation) {
|
|
9338
|
+
const result = await run("account_get_asset_balance", {
|
|
9339
|
+
ccy,
|
|
9340
|
+
...showValuation ? { showValuation: true } : {}
|
|
9341
|
+
});
|
|
9342
|
+
const data = result.data ?? [];
|
|
9343
|
+
if (json) return printJson(showValuation ? { data, valuation: result.valuation } : data);
|
|
9243
9344
|
printTable(
|
|
9244
|
-
|
|
9345
|
+
data.filter((r) => Number(r["bal"]) > 0).map((r) => ({
|
|
9245
9346
|
ccy: r["ccy"],
|
|
9246
9347
|
bal: r["bal"],
|
|
9247
9348
|
availBal: r["availBal"],
|
|
9248
9349
|
frozenBal: r["frozenBal"]
|
|
9249
9350
|
}))
|
|
9250
9351
|
);
|
|
9352
|
+
if (showValuation && result.valuation) {
|
|
9353
|
+
const valuationData = result.valuation ?? [];
|
|
9354
|
+
outputLine("");
|
|
9355
|
+
outputLine("Asset Valuation by Account Type:");
|
|
9356
|
+
printTable(
|
|
9357
|
+
valuationData.map((v) => {
|
|
9358
|
+
const details = v["details"] ?? {};
|
|
9359
|
+
return {
|
|
9360
|
+
totalBal: v["totalBal"],
|
|
9361
|
+
classic: details["classic"],
|
|
9362
|
+
earn: details["earn"],
|
|
9363
|
+
funding: details["funding"],
|
|
9364
|
+
trading: details["trading"]
|
|
9365
|
+
};
|
|
9366
|
+
})
|
|
9367
|
+
);
|
|
9368
|
+
}
|
|
9251
9369
|
}
|
|
9252
9370
|
async function cmdAccountPositions(run, opts) {
|
|
9253
9371
|
const result = await run("account_get_positions", { instType: opts.instType, instId: opts.instId });
|
|
@@ -10163,7 +10281,7 @@ async function cmdFuturesBatch(run, opts) {
|
|
|
10163
10281
|
process.exitCode = 1;
|
|
10164
10282
|
return;
|
|
10165
10283
|
}
|
|
10166
|
-
const result = await run(tool,
|
|
10284
|
+
const result = await run(tool, { orders: parsed });
|
|
10167
10285
|
const data = getData5(result);
|
|
10168
10286
|
if (opts.json) return printJson(data);
|
|
10169
10287
|
emitBatchResults3(data ?? []);
|
|
@@ -10667,6 +10785,58 @@ function buildProfileEntry(siteKey, apiKey, secretKey, passphrase, demo) {
|
|
|
10667
10785
|
}
|
|
10668
10786
|
return entry;
|
|
10669
10787
|
}
|
|
10788
|
+
function tryOpenUrl(url) {
|
|
10789
|
+
try {
|
|
10790
|
+
let opener;
|
|
10791
|
+
if (process.platform === "darwin") {
|
|
10792
|
+
opener = "open";
|
|
10793
|
+
} else if (process.platform === "win32") {
|
|
10794
|
+
opener = "start";
|
|
10795
|
+
} else {
|
|
10796
|
+
opener = "xdg-open";
|
|
10797
|
+
}
|
|
10798
|
+
spawnSync2(opener, [url], { stdio: "ignore", shell: process.platform === "win32" });
|
|
10799
|
+
} catch {
|
|
10800
|
+
}
|
|
10801
|
+
}
|
|
10802
|
+
async function promptCredentials(rl, t) {
|
|
10803
|
+
const apiKey = (await prompt(rl, "API Key: ")).trim();
|
|
10804
|
+
if (!apiKey) {
|
|
10805
|
+
errorLine(t.emptyApiKey);
|
|
10806
|
+
process.exitCode = 1;
|
|
10807
|
+
return null;
|
|
10808
|
+
}
|
|
10809
|
+
const secretKey = (await prompt(rl, "Secret Key: ")).trim();
|
|
10810
|
+
if (!secretKey) {
|
|
10811
|
+
errorLine(t.emptySecretKey);
|
|
10812
|
+
process.exitCode = 1;
|
|
10813
|
+
return null;
|
|
10814
|
+
}
|
|
10815
|
+
const passphrase = (await prompt(rl, "Passphrase: ")).trim();
|
|
10816
|
+
if (!passphrase) {
|
|
10817
|
+
errorLine(t.emptyPassphrase);
|
|
10818
|
+
process.exitCode = 1;
|
|
10819
|
+
return null;
|
|
10820
|
+
}
|
|
10821
|
+
return { apiKey, secretKey, passphrase };
|
|
10822
|
+
}
|
|
10823
|
+
function saveConfig(config, profileName, t) {
|
|
10824
|
+
const configPath = configFilePath();
|
|
10825
|
+
try {
|
|
10826
|
+
writeCliConfig(config);
|
|
10827
|
+
output(t.saved(configPath));
|
|
10828
|
+
output(t.defaultProfile(profileName));
|
|
10829
|
+
output(t.usage);
|
|
10830
|
+
} catch (err) {
|
|
10831
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
10832
|
+
const isPermission = err instanceof Error && "code" in err && (err.code === "EACCES" || err.code === "EPERM");
|
|
10833
|
+
errorOutput(t.writeFailed(message));
|
|
10834
|
+
if (isPermission) errorOutput(t.permissionDenied(configPath));
|
|
10835
|
+
errorOutput(t.manualWrite(configPath));
|
|
10836
|
+
outputLine(stringify(config));
|
|
10837
|
+
process.exitCode = 1;
|
|
10838
|
+
}
|
|
10839
|
+
}
|
|
10670
10840
|
async function cmdConfigInit(lang = "en") {
|
|
10671
10841
|
const t = messages[lang];
|
|
10672
10842
|
outputLine(t.title);
|
|
@@ -10682,14 +10852,9 @@ async function cmdConfigInit(lang = "en") {
|
|
|
10682
10852
|
const demoRaw = (await prompt(rl, t.demoPrompt)).trim().toLowerCase();
|
|
10683
10853
|
const demo = demoRaw !== "n";
|
|
10684
10854
|
const apiUrl = buildApiUrl(siteKey, demo);
|
|
10685
|
-
const hintText = demo ? t.hintDemo : t.hintLive;
|
|
10686
10855
|
output(t.createApiKey(apiUrl));
|
|
10687
|
-
output(t.hint(
|
|
10688
|
-
|
|
10689
|
-
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
10690
|
-
spawnSync2(opener, [apiUrl], { stdio: "ignore", shell: process.platform === "win32" });
|
|
10691
|
-
} catch {
|
|
10692
|
-
}
|
|
10856
|
+
output(t.hint(demo ? t.hintDemo : t.hintLive));
|
|
10857
|
+
tryOpenUrl(apiUrl);
|
|
10693
10858
|
const defaultProfileName = demo ? "okx-demo" : "okx-prod";
|
|
10694
10859
|
const profileNameRaw = await prompt(rl, t.profilePrompt(defaultProfileName));
|
|
10695
10860
|
const profileName = profileNameRaw.trim() || defaultProfileName;
|
|
@@ -10701,49 +10866,14 @@ async function cmdConfigInit(lang = "en") {
|
|
|
10701
10866
|
return;
|
|
10702
10867
|
}
|
|
10703
10868
|
}
|
|
10704
|
-
const
|
|
10705
|
-
if (!
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
return;
|
|
10709
|
-
}
|
|
10710
|
-
const secretKey = (await prompt(rl, "Secret Key: ")).trim();
|
|
10711
|
-
if (!secretKey) {
|
|
10712
|
-
errorLine(t.emptySecretKey);
|
|
10713
|
-
process.exitCode = 1;
|
|
10714
|
-
return;
|
|
10715
|
-
}
|
|
10716
|
-
const passphrase = (await prompt(rl, "Passphrase: ")).trim();
|
|
10717
|
-
if (!passphrase) {
|
|
10718
|
-
errorLine(t.emptyPassphrase);
|
|
10719
|
-
process.exitCode = 1;
|
|
10720
|
-
return;
|
|
10721
|
-
}
|
|
10722
|
-
if (demo) {
|
|
10723
|
-
outputLine(t.demoSelected);
|
|
10724
|
-
}
|
|
10725
|
-
const profileEntry = buildProfileEntry(siteKey, apiKey, secretKey, passphrase, demo);
|
|
10726
|
-
config.profiles[profileName] = profileEntry;
|
|
10869
|
+
const credentials = await promptCredentials(rl, t);
|
|
10870
|
+
if (!credentials) return;
|
|
10871
|
+
if (demo) outputLine(t.demoSelected);
|
|
10872
|
+
config.profiles[profileName] = buildProfileEntry(siteKey, credentials.apiKey, credentials.secretKey, credentials.passphrase, demo);
|
|
10727
10873
|
if (!config.default_profile || config.default_profile !== profileName) {
|
|
10728
10874
|
config.default_profile = profileName;
|
|
10729
10875
|
}
|
|
10730
|
-
|
|
10731
|
-
try {
|
|
10732
|
-
writeCliConfig(config);
|
|
10733
|
-
output(t.saved(configPath));
|
|
10734
|
-
output(t.defaultProfile(profileName));
|
|
10735
|
-
output(t.usage);
|
|
10736
|
-
} catch (err) {
|
|
10737
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
10738
|
-
const isPermission = err instanceof Error && "code" in err && (err.code === "EACCES" || err.code === "EPERM");
|
|
10739
|
-
errorOutput(t.writeFailed(message));
|
|
10740
|
-
if (isPermission) {
|
|
10741
|
-
errorOutput(t.permissionDenied(configPath));
|
|
10742
|
-
}
|
|
10743
|
-
errorOutput(t.manualWrite(configPath));
|
|
10744
|
-
outputLine(stringify(config));
|
|
10745
|
-
process.exitCode = 1;
|
|
10746
|
-
}
|
|
10876
|
+
saveConfig(config, profileName, t);
|
|
10747
10877
|
} finally {
|
|
10748
10878
|
rl.close();
|
|
10749
10879
|
}
|
|
@@ -11119,7 +11249,6 @@ async function cmdGridCreate(run, opts) {
|
|
|
11119
11249
|
});
|
|
11120
11250
|
const data = getData7(result);
|
|
11121
11251
|
if (opts.json) return printJson(data);
|
|
11122
|
-
const r = data?.[0];
|
|
11123
11252
|
emitWriteResult5(data?.[0], "Grid bot created", "algoId");
|
|
11124
11253
|
}
|
|
11125
11254
|
async function cmdGridStop(run, opts) {
|
|
@@ -11131,7 +11260,6 @@ async function cmdGridStop(run, opts) {
|
|
|
11131
11260
|
});
|
|
11132
11261
|
const data = getData7(result);
|
|
11133
11262
|
if (opts.json) return printJson(data);
|
|
11134
|
-
const r = data?.[0];
|
|
11135
11263
|
emitWriteResult5(data?.[0], "Grid bot stopped", "algoId");
|
|
11136
11264
|
}
|
|
11137
11265
|
async function cmdDcaCreate(run, opts) {
|
|
@@ -11565,7 +11693,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
11565
11693
|
// src/index.ts
|
|
11566
11694
|
var _require3 = createRequire3(import.meta.url);
|
|
11567
11695
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
11568
|
-
var GIT_HASH2 = true ? "
|
|
11696
|
+
var GIT_HASH2 = true ? "b691d23" : "dev";
|
|
11569
11697
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
11570
11698
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
11571
11699
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -11626,7 +11754,7 @@ function handleMarketDataCommand(run, action, rest, v, json) {
|
|
|
11626
11754
|
if (action === "orderbook")
|
|
11627
11755
|
return cmdMarketOrderbook(run, rest[0], v.sz !== void 0 ? Number(v.sz) : void 0, json);
|
|
11628
11756
|
if (action === "candles")
|
|
11629
|
-
return cmdMarketCandles(run, rest[0], { bar: v.bar, limit, json });
|
|
11757
|
+
return cmdMarketCandles(run, rest[0], { bar: v.bar, limit, after: v.after, before: v.before, json });
|
|
11630
11758
|
if (action === "funding-rate")
|
|
11631
11759
|
return cmdMarketFundingRate(run, rest[0], { history: v.history ?? false, limit, json });
|
|
11632
11760
|
if (action === "trades")
|
|
@@ -11661,7 +11789,7 @@ function handleAccountCommand(run, action, rest, v, json) {
|
|
|
11661
11789
|
return cmdAccountAudit({ limit: v.limit, tool: v.tool, since: v.since, json });
|
|
11662
11790
|
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
11663
11791
|
if (action === "balance") return cmdAccountBalance(run, rest[0], json);
|
|
11664
|
-
if (action === "asset-balance") return cmdAccountAssetBalance(run, v.ccy, json);
|
|
11792
|
+
if (action === "asset-balance") return cmdAccountAssetBalance(run, v.ccy, json, v.valuation);
|
|
11665
11793
|
if (action === "positions")
|
|
11666
11794
|
return cmdAccountPositions(run, { instType: v.instType, instId: v.instId, json });
|
|
11667
11795
|
if (action === "positions-history")
|