@okx_ai/okx-trade-cli 1.2.5 → 1.2.6
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 +668 -470
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1019,9 +1019,9 @@ var OKX_CODE_BEHAVIORS = {
|
|
|
1019
1019
|
"50100": { retry: false, suggestion: "API key lacks required permissions. Update API key permissions." },
|
|
1020
1020
|
"50110": { retry: false, suggestion: "API key expired. Generate a new API key." },
|
|
1021
1021
|
// Insufficient funds / margin → do not retry
|
|
1022
|
-
"51008": { retry: false, suggestion: "Insufficient balance.
|
|
1023
|
-
"51119": { retry: false, suggestion: "Insufficient margin. Add margin
|
|
1024
|
-
"51127": { retry: false, suggestion: "Insufficient available margin. Reduce position or
|
|
1022
|
+
"51008": { retry: false, suggestion: "Insufficient balance in trading account. Check funding account via account_get_asset_balance \u2014 funds may be there. Use account_transfer (from=18, to=6) to move funds to trading account, then retry." },
|
|
1023
|
+
"51119": { retry: false, suggestion: "Insufficient margin. Add margin or check funding account (account_get_asset_balance). Transfer via account_transfer (from=18, to=6) if needed." },
|
|
1024
|
+
"51127": { retry: false, suggestion: "Insufficient available margin. Reduce position, add margin, or transfer from funding account (account_transfer from=18 to=6)." },
|
|
1025
1025
|
// Instrument unavailable → do not retry
|
|
1026
1026
|
"51021": { retry: false, suggestion: "Instrument does not exist. Check instId." },
|
|
1027
1027
|
"51022": { retry: false, suggestion: "Instrument not available for trading." },
|
|
@@ -1104,6 +1104,15 @@ var OkxRestClient = class {
|
|
|
1104
1104
|
rateLimit
|
|
1105
1105
|
});
|
|
1106
1106
|
}
|
|
1107
|
+
async publicPost(path42, body, rateLimit) {
|
|
1108
|
+
return this.request({
|
|
1109
|
+
method: "POST",
|
|
1110
|
+
path: path42,
|
|
1111
|
+
auth: "public",
|
|
1112
|
+
body,
|
|
1113
|
+
rateLimit
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1107
1116
|
async privatePost(path42, body, rateLimit) {
|
|
1108
1117
|
return this.request({
|
|
1109
1118
|
method: "POST",
|
|
@@ -1258,46 +1267,6 @@ var OkxRestClient = class {
|
|
|
1258
1267
|
return this.processResponse(rawText, response, elapsed, traceId, reqConfig, requestPath);
|
|
1259
1268
|
}
|
|
1260
1269
|
};
|
|
1261
|
-
var DEFAULT_SOURCE_TAG = "MCP";
|
|
1262
|
-
var OKX_SITES = {
|
|
1263
|
-
global: {
|
|
1264
|
-
label: "Global",
|
|
1265
|
-
apiBaseUrl: "https://www.okx.com",
|
|
1266
|
-
webUrl: "https://www.okx.com"
|
|
1267
|
-
},
|
|
1268
|
-
eea: {
|
|
1269
|
-
label: "EEA",
|
|
1270
|
-
apiBaseUrl: "https://eea.okx.com",
|
|
1271
|
-
webUrl: "https://my.okx.com"
|
|
1272
|
-
},
|
|
1273
|
-
us: {
|
|
1274
|
-
label: "US",
|
|
1275
|
-
apiBaseUrl: "https://app.okx.com",
|
|
1276
|
-
webUrl: "https://app.okx.com"
|
|
1277
|
-
}
|
|
1278
|
-
};
|
|
1279
|
-
var SITE_IDS = Object.keys(OKX_SITES);
|
|
1280
|
-
var BOT_SUB_MODULE_IDS = [
|
|
1281
|
-
"bot.grid",
|
|
1282
|
-
"bot.dca"
|
|
1283
|
-
];
|
|
1284
|
-
var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
|
|
1285
|
-
var EARN_SUB_MODULE_IDS = [
|
|
1286
|
-
"earn.savings",
|
|
1287
|
-
"earn.onchain",
|
|
1288
|
-
"earn.dcd"
|
|
1289
|
-
];
|
|
1290
|
-
var MODULES = [
|
|
1291
|
-
"market",
|
|
1292
|
-
"spot",
|
|
1293
|
-
"swap",
|
|
1294
|
-
"futures",
|
|
1295
|
-
"option",
|
|
1296
|
-
"account",
|
|
1297
|
-
...EARN_SUB_MODULE_IDS,
|
|
1298
|
-
...BOT_SUB_MODULE_IDS
|
|
1299
|
-
];
|
|
1300
|
-
var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES];
|
|
1301
1270
|
function asRecord(value) {
|
|
1302
1271
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1303
1272
|
return {};
|
|
@@ -1422,6 +1391,152 @@ function assertNotDemo(config, endpoint) {
|
|
|
1422
1391
|
);
|
|
1423
1392
|
}
|
|
1424
1393
|
}
|
|
1394
|
+
var INDICATOR_BARS = [
|
|
1395
|
+
"3m",
|
|
1396
|
+
"5m",
|
|
1397
|
+
"15m",
|
|
1398
|
+
"1H",
|
|
1399
|
+
"4H",
|
|
1400
|
+
"12Hutc",
|
|
1401
|
+
"1Dutc",
|
|
1402
|
+
"3Dutc",
|
|
1403
|
+
"1Wutc"
|
|
1404
|
+
];
|
|
1405
|
+
var INDICATOR_CODE_OVERRIDES = {
|
|
1406
|
+
"rainbow": "BTCRAINBOW",
|
|
1407
|
+
"range-filter": "RANGEFILTER",
|
|
1408
|
+
"stoch-rsi": "STOCHRSI",
|
|
1409
|
+
"pi-cycle-top": "PI_CYCLE_TOP",
|
|
1410
|
+
"pi-cycle-bottom": "PI_CYCLE_BOTTOM",
|
|
1411
|
+
// boll is an alias for bb; server supports BB not BOLL
|
|
1412
|
+
"boll": "BB"
|
|
1413
|
+
};
|
|
1414
|
+
function resolveIndicatorCode(name) {
|
|
1415
|
+
const lower = name.toLowerCase();
|
|
1416
|
+
return INDICATOR_CODE_OVERRIDES[lower] ?? name.toUpperCase().replace(/-/g, "_");
|
|
1417
|
+
}
|
|
1418
|
+
function readNumberArray(args, key) {
|
|
1419
|
+
const value = args[key];
|
|
1420
|
+
if (value === void 0 || value === null) return void 0;
|
|
1421
|
+
if (!Array.isArray(value)) return void 0;
|
|
1422
|
+
return value.map((item) => Number(item));
|
|
1423
|
+
}
|
|
1424
|
+
function registerIndicatorTools() {
|
|
1425
|
+
return [
|
|
1426
|
+
{
|
|
1427
|
+
name: "market_get_indicator",
|
|
1428
|
+
module: "market",
|
|
1429
|
+
description: "Get technical indicator values for an instrument (MA, EMA, RSI, MACD, BB, KDJ, SUPERTREND, AHR999, BTCRAINBOW, and more). No credentials required.",
|
|
1430
|
+
isWrite: false,
|
|
1431
|
+
inputSchema: {
|
|
1432
|
+
type: "object",
|
|
1433
|
+
properties: {
|
|
1434
|
+
instId: {
|
|
1435
|
+
type: "string",
|
|
1436
|
+
description: "Instrument ID, e.g. BTC-USDT"
|
|
1437
|
+
},
|
|
1438
|
+
indicator: {
|
|
1439
|
+
type: "string",
|
|
1440
|
+
description: "Indicator name (case-insensitive). Examples: ma, ema, rsi, macd, bb, kdj, supertrend, ahr999, rainbow, pi-cycle-top, pi-cycle-bottom, mayer, envelope, halftrend, alphatrend, pmax, waddah, tdi, qqe, range-filter"
|
|
1441
|
+
},
|
|
1442
|
+
bar: {
|
|
1443
|
+
type: "string",
|
|
1444
|
+
enum: [...INDICATOR_BARS],
|
|
1445
|
+
description: "Timeframe. Default: 1H"
|
|
1446
|
+
},
|
|
1447
|
+
params: {
|
|
1448
|
+
type: "array",
|
|
1449
|
+
items: { type: "number" },
|
|
1450
|
+
description: "Indicator parameters, e.g. [5, 20] for MA with periods 5 and 20"
|
|
1451
|
+
},
|
|
1452
|
+
returnList: {
|
|
1453
|
+
type: "boolean",
|
|
1454
|
+
description: "Return a historical list instead of the latest value only. Default: false"
|
|
1455
|
+
},
|
|
1456
|
+
limit: {
|
|
1457
|
+
type: "integer",
|
|
1458
|
+
minimum: 1,
|
|
1459
|
+
maximum: 100,
|
|
1460
|
+
description: "Number of historical records to return (only used when returnList=true). Default: 10"
|
|
1461
|
+
},
|
|
1462
|
+
backtestTime: {
|
|
1463
|
+
type: "integer",
|
|
1464
|
+
description: "Backtest timestamp in milliseconds. Omit for live (real-time) mode"
|
|
1465
|
+
}
|
|
1466
|
+
},
|
|
1467
|
+
required: ["instId", "indicator"]
|
|
1468
|
+
},
|
|
1469
|
+
handler: async (rawArgs, context) => {
|
|
1470
|
+
const args = asRecord(rawArgs);
|
|
1471
|
+
const instId = requireString(args, "instId");
|
|
1472
|
+
const indicator = requireString(args, "indicator");
|
|
1473
|
+
const bar = readString(args, "bar") ?? "1H";
|
|
1474
|
+
const params = readNumberArray(args, "params");
|
|
1475
|
+
const returnList = readBoolean(args, "returnList") ?? false;
|
|
1476
|
+
const limit = readNumber(args, "limit") ?? 10;
|
|
1477
|
+
const backtestTime = readNumber(args, "backtestTime");
|
|
1478
|
+
const apiCode = resolveIndicatorCode(indicator);
|
|
1479
|
+
const indicatorConfig = compactObject({
|
|
1480
|
+
paramList: params && params.length > 0 ? params : void 0,
|
|
1481
|
+
returnList,
|
|
1482
|
+
limit: returnList ? limit : void 0
|
|
1483
|
+
});
|
|
1484
|
+
const body = compactObject({
|
|
1485
|
+
instId,
|
|
1486
|
+
timeframes: [bar],
|
|
1487
|
+
indicators: { [apiCode]: indicatorConfig },
|
|
1488
|
+
backtestTime
|
|
1489
|
+
});
|
|
1490
|
+
const response = await context.client.publicPost(
|
|
1491
|
+
"/api/v5/aigc/mcp/indicators",
|
|
1492
|
+
body,
|
|
1493
|
+
publicRateLimit("market_get_indicator", 5)
|
|
1494
|
+
);
|
|
1495
|
+
return normalizeResponse(response);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
];
|
|
1499
|
+
}
|
|
1500
|
+
var DEFAULT_SOURCE_TAG = "MCP";
|
|
1501
|
+
var OKX_SITES = {
|
|
1502
|
+
global: {
|
|
1503
|
+
label: "Global",
|
|
1504
|
+
apiBaseUrl: "https://www.okx.com",
|
|
1505
|
+
webUrl: "https://www.okx.com"
|
|
1506
|
+
},
|
|
1507
|
+
eea: {
|
|
1508
|
+
label: "EEA",
|
|
1509
|
+
apiBaseUrl: "https://eea.okx.com",
|
|
1510
|
+
webUrl: "https://my.okx.com"
|
|
1511
|
+
},
|
|
1512
|
+
us: {
|
|
1513
|
+
label: "US",
|
|
1514
|
+
apiBaseUrl: "https://app.okx.com",
|
|
1515
|
+
webUrl: "https://app.okx.com"
|
|
1516
|
+
}
|
|
1517
|
+
};
|
|
1518
|
+
var SITE_IDS = Object.keys(OKX_SITES);
|
|
1519
|
+
var BOT_SUB_MODULE_IDS = [
|
|
1520
|
+
"bot.grid",
|
|
1521
|
+
"bot.dca"
|
|
1522
|
+
];
|
|
1523
|
+
var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
|
|
1524
|
+
var EARN_SUB_MODULE_IDS = [
|
|
1525
|
+
"earn.savings",
|
|
1526
|
+
"earn.onchain",
|
|
1527
|
+
"earn.dcd"
|
|
1528
|
+
];
|
|
1529
|
+
var MODULES = [
|
|
1530
|
+
"market",
|
|
1531
|
+
"spot",
|
|
1532
|
+
"swap",
|
|
1533
|
+
"futures",
|
|
1534
|
+
"option",
|
|
1535
|
+
"account",
|
|
1536
|
+
...EARN_SUB_MODULE_IDS,
|
|
1537
|
+
...BOT_SUB_MODULE_IDS
|
|
1538
|
+
];
|
|
1539
|
+
var DEFAULT_MODULES = ["spot", "swap", "option", "account", ...BOT_DEFAULT_SUB_MODULES];
|
|
1425
1540
|
function registerAccountTools() {
|
|
1426
1541
|
return [
|
|
1427
1542
|
{
|
|
@@ -4059,7 +4174,12 @@ function buildContractTradeTools(cfg) {
|
|
|
4059
4174
|
},
|
|
4060
4175
|
sz: {
|
|
4061
4176
|
type: "string",
|
|
4062
|
-
description: "Contracts count
|
|
4177
|
+
description: "Contracts count by default. Set tgtCcy=quote_ccy to use USDT amount instead."
|
|
4178
|
+
},
|
|
4179
|
+
tgtCcy: {
|
|
4180
|
+
type: "string",
|
|
4181
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
4182
|
+
description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT"
|
|
4063
4183
|
},
|
|
4064
4184
|
px: { type: "string", description: "Required for limit/post_only/fok/ioc" },
|
|
4065
4185
|
reduceOnly: {
|
|
@@ -4087,6 +4207,7 @@ function buildContractTradeTools(cfg) {
|
|
|
4087
4207
|
posSide: readString(args, "posSide"),
|
|
4088
4208
|
ordType: requireString(args, "ordType"),
|
|
4089
4209
|
sz: requireString(args, "sz"),
|
|
4210
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
4090
4211
|
px: readString(args, "px"),
|
|
4091
4212
|
reduceOnly: typeof reduceOnly === "boolean" ? String(reduceOnly) : void 0,
|
|
4092
4213
|
clOrdId: readString(args, "clOrdId"),
|
|
@@ -5742,6 +5863,11 @@ function registerSpotTradeTools() {
|
|
|
5742
5863
|
type: "string",
|
|
5743
5864
|
description: "Buy market: quote amount, all others: base amount"
|
|
5744
5865
|
},
|
|
5866
|
+
tgtCcy: {
|
|
5867
|
+
type: "string",
|
|
5868
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
5869
|
+
description: "Size unit. base_ccy(default): sz in base (e.g. BTC), quote_ccy: sz in quote (e.g. USDT)"
|
|
5870
|
+
},
|
|
5745
5871
|
px: {
|
|
5746
5872
|
type: "string",
|
|
5747
5873
|
description: "Required for limit/post_only/fok/ioc"
|
|
@@ -5780,6 +5906,7 @@ function registerSpotTradeTools() {
|
|
|
5780
5906
|
side: requireString(args, "side"),
|
|
5781
5907
|
ordType: requireString(args, "ordType"),
|
|
5782
5908
|
sz: requireString(args, "sz"),
|
|
5909
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
5783
5910
|
px: readString(args, "px"),
|
|
5784
5911
|
clOrdId: readString(args, "clOrdId"),
|
|
5785
5912
|
tag: context.config.sourceTag,
|
|
@@ -6508,6 +6635,7 @@ function registerSwapTradeTools() {
|
|
|
6508
6635
|
function allToolSpecs() {
|
|
6509
6636
|
return [
|
|
6510
6637
|
...registerMarketTools(),
|
|
6638
|
+
...registerIndicatorTools(),
|
|
6511
6639
|
...registerSpotTradeTools(),
|
|
6512
6640
|
...registerSwapTradeTools(),
|
|
6513
6641
|
...registerFuturesTools(),
|
|
@@ -6539,20 +6667,38 @@ function readFullConfig() {
|
|
|
6539
6667
|
const path42 = configFilePath();
|
|
6540
6668
|
if (!existsSync(path42)) return { profiles: {} };
|
|
6541
6669
|
const raw = readFileSync(path42, "utf-8");
|
|
6542
|
-
|
|
6670
|
+
try {
|
|
6671
|
+
return parse(raw);
|
|
6672
|
+
} catch (err) {
|
|
6673
|
+
throw new ConfigError(
|
|
6674
|
+
`Failed to parse ${path42}: ${err instanceof Error ? err.message : String(err)}`,
|
|
6675
|
+
`If your passphrase or keys contain special characters:
|
|
6676
|
+
- Contains # \\ " \u2192 use single quotes: passphrase = 'your#pass'
|
|
6677
|
+
- Contains ' \u2192 use double quotes: passphrase = "your'pass"
|
|
6678
|
+
- Contains both \u2192 use triple quotes: passphrase = '''your'#pass'''
|
|
6679
|
+
Or re-run: okx config init`
|
|
6680
|
+
);
|
|
6681
|
+
}
|
|
6543
6682
|
}
|
|
6544
6683
|
function readTomlProfile(profileName) {
|
|
6545
6684
|
const config = readFullConfig();
|
|
6546
6685
|
const name = profileName ?? config.default_profile ?? "default";
|
|
6547
6686
|
return config.profiles?.[name] ?? {};
|
|
6548
6687
|
}
|
|
6688
|
+
var CONFIG_HEADER = `# OKX Trade Kit Configuration
|
|
6689
|
+
# If editing manually, wrap values containing special chars in quotes:
|
|
6690
|
+
# passphrase = 'value' (if value contains # \\ ")
|
|
6691
|
+
# passphrase = "value" (if value contains ')
|
|
6692
|
+
# passphrase = '''value''' (if value contains both)
|
|
6693
|
+
|
|
6694
|
+
`;
|
|
6549
6695
|
function writeFullConfig(config) {
|
|
6550
6696
|
const path42 = configFilePath();
|
|
6551
6697
|
const dir = dirname(path42);
|
|
6552
6698
|
if (!existsSync(dir)) {
|
|
6553
6699
|
mkdirSync(dir, { recursive: true });
|
|
6554
6700
|
}
|
|
6555
|
-
writeFileSync(path42, stringify(config), "utf-8");
|
|
6701
|
+
writeFileSync(path42, CONFIG_HEADER + stringify(config), "utf-8");
|
|
6556
6702
|
}
|
|
6557
6703
|
function expandShorthand(moduleId) {
|
|
6558
6704
|
if (moduleId === "all") return [...MODULES];
|
|
@@ -6877,6 +7023,73 @@ import tls from "tls";
|
|
|
6877
7023
|
// src/commands/diagnose-utils.ts
|
|
6878
7024
|
import fs2 from "fs";
|
|
6879
7025
|
import { createRequire } from "module";
|
|
7026
|
+
|
|
7027
|
+
// src/formatter.ts
|
|
7028
|
+
import { EOL } from "os";
|
|
7029
|
+
var stdioOutput = {
|
|
7030
|
+
out: (message) => process.stdout.write(message),
|
|
7031
|
+
err: (message) => process.stderr.write(message)
|
|
7032
|
+
};
|
|
7033
|
+
var activeOutput = stdioOutput;
|
|
7034
|
+
function setOutput(impl) {
|
|
7035
|
+
activeOutput = impl;
|
|
7036
|
+
}
|
|
7037
|
+
function output(message) {
|
|
7038
|
+
activeOutput.out(message);
|
|
7039
|
+
}
|
|
7040
|
+
function errorOutput(message) {
|
|
7041
|
+
activeOutput.err(message);
|
|
7042
|
+
}
|
|
7043
|
+
function outputLine(message) {
|
|
7044
|
+
activeOutput.out(message + EOL);
|
|
7045
|
+
}
|
|
7046
|
+
function errorLine(message) {
|
|
7047
|
+
activeOutput.err(message + EOL);
|
|
7048
|
+
}
|
|
7049
|
+
function printJson(data) {
|
|
7050
|
+
activeOutput.out(JSON.stringify(data, null, 2) + EOL);
|
|
7051
|
+
}
|
|
7052
|
+
function printTable(rows) {
|
|
7053
|
+
if (rows.length === 0) {
|
|
7054
|
+
activeOutput.out("(no data)" + EOL);
|
|
7055
|
+
return;
|
|
7056
|
+
}
|
|
7057
|
+
const keys = Object.keys(rows[0]);
|
|
7058
|
+
const widths = keys.map(
|
|
7059
|
+
(k) => Math.max(k.length, ...rows.map((r) => String(r[k] ?? "").length))
|
|
7060
|
+
);
|
|
7061
|
+
const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
|
|
7062
|
+
const divider = widths.map((w) => "-".repeat(w)).join(" ");
|
|
7063
|
+
activeOutput.out(header + EOL + divider + EOL);
|
|
7064
|
+
for (const row of rows) {
|
|
7065
|
+
activeOutput.out(keys.map((k, i) => String(row[k] ?? "").padEnd(widths[i])).join(" ") + EOL);
|
|
7066
|
+
}
|
|
7067
|
+
}
|
|
7068
|
+
function printKv(obj, indent = 0) {
|
|
7069
|
+
const pad = " ".repeat(indent);
|
|
7070
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
7071
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
7072
|
+
activeOutput.out(`${pad}${k}:${EOL}`);
|
|
7073
|
+
printKv(v, indent + 2);
|
|
7074
|
+
} else {
|
|
7075
|
+
activeOutput.out(`${pad}${k.padEnd(20 - indent)} ${v}${EOL}`);
|
|
7076
|
+
}
|
|
7077
|
+
}
|
|
7078
|
+
}
|
|
7079
|
+
function markFailedIfSCodeError(data) {
|
|
7080
|
+
if (!Array.isArray(data)) return;
|
|
7081
|
+
for (const item of data) {
|
|
7082
|
+
if (item !== null && typeof item === "object") {
|
|
7083
|
+
const sCode = item["sCode"];
|
|
7084
|
+
if (sCode !== void 0 && sCode !== "0" && sCode !== 0) {
|
|
7085
|
+
process.exitCode = 1;
|
|
7086
|
+
return;
|
|
7087
|
+
}
|
|
7088
|
+
}
|
|
7089
|
+
}
|
|
7090
|
+
}
|
|
7091
|
+
|
|
7092
|
+
// src/commands/diagnose-utils.ts
|
|
6880
7093
|
var _require = createRequire(import.meta.url);
|
|
6881
7094
|
function readCliVersion() {
|
|
6882
7095
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
@@ -6893,18 +7106,14 @@ var Report = class {
|
|
|
6893
7106
|
this.lines.push({ key, value });
|
|
6894
7107
|
}
|
|
6895
7108
|
print() {
|
|
6896
|
-
const w = process.stdout.write.bind(process.stdout);
|
|
6897
7109
|
const sep = "\u2500".repeat(52);
|
|
6898
|
-
|
|
6899
|
-
\u2500\u2500 Diagnostic Report (copy & share) ${sep.slice(35)}
|
|
6900
|
-
`);
|
|
7110
|
+
outputLine("");
|
|
7111
|
+
outputLine(` \u2500\u2500 Diagnostic Report (copy & share) ${sep.slice(35)}`);
|
|
6901
7112
|
for (const { key, value } of this.lines) {
|
|
6902
|
-
|
|
6903
|
-
`);
|
|
7113
|
+
outputLine(` ${key.padEnd(14)} ${value}`);
|
|
6904
7114
|
}
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
`);
|
|
7115
|
+
outputLine(` ${sep}`);
|
|
7116
|
+
outputLine("");
|
|
6908
7117
|
}
|
|
6909
7118
|
/** Write report to a file path, returns true on success. */
|
|
6910
7119
|
writeToFile(filePath) {
|
|
@@ -6925,31 +7134,25 @@ var Report = class {
|
|
|
6925
7134
|
}
|
|
6926
7135
|
};
|
|
6927
7136
|
function ok(label, detail) {
|
|
6928
|
-
|
|
6929
|
-
`);
|
|
7137
|
+
outputLine(` \u2713 ${label.padEnd(14)} ${detail}`);
|
|
6930
7138
|
}
|
|
6931
7139
|
function fail(label, detail, hints) {
|
|
6932
|
-
|
|
6933
|
-
`);
|
|
7140
|
+
outputLine(` \u2717 ${label.padEnd(14)} ${detail}`);
|
|
6934
7141
|
for (const hint of hints) {
|
|
6935
|
-
|
|
6936
|
-
`);
|
|
7142
|
+
outputLine(` \u2192 ${hint}`);
|
|
6937
7143
|
}
|
|
6938
7144
|
}
|
|
6939
7145
|
function section(title) {
|
|
6940
|
-
|
|
6941
|
-
${title}
|
|
6942
|
-
`);
|
|
7146
|
+
outputLine("");
|
|
7147
|
+
outputLine(` ${title}`);
|
|
6943
7148
|
}
|
|
6944
7149
|
function writeReportIfRequested(report, outputPath) {
|
|
6945
7150
|
if (!outputPath) return;
|
|
6946
7151
|
const written = report.writeToFile(outputPath);
|
|
6947
7152
|
if (written) {
|
|
6948
|
-
|
|
6949
|
-
`);
|
|
7153
|
+
outputLine(` Report saved to: ${outputPath}`);
|
|
6950
7154
|
} else {
|
|
6951
|
-
|
|
6952
|
-
`);
|
|
7155
|
+
errorLine(` Warning: failed to write report to: ${outputPath}`);
|
|
6953
7156
|
}
|
|
6954
7157
|
}
|
|
6955
7158
|
function sanitize(value) {
|
|
@@ -7149,8 +7352,7 @@ function checkMcpLogs(report) {
|
|
|
7149
7352
|
report.add("mcp_log", logPath);
|
|
7150
7353
|
if (lines.length > 0) {
|
|
7151
7354
|
ok("last lines", `(${lines.length} shown)`);
|
|
7152
|
-
for (const line of lines)
|
|
7153
|
-
`);
|
|
7355
|
+
for (const line of lines) outputLine(` ${sanitize(line)}`);
|
|
7154
7356
|
} else {
|
|
7155
7357
|
ok("last lines", "(empty log)");
|
|
7156
7358
|
}
|
|
@@ -7285,8 +7487,9 @@ function checkModuleLoading(entryPath, report) {
|
|
|
7285
7487
|
}
|
|
7286
7488
|
}
|
|
7287
7489
|
async function cmdDiagnoseMcp(options = {}) {
|
|
7288
|
-
|
|
7289
|
-
|
|
7490
|
+
outputLine("");
|
|
7491
|
+
outputLine(" OKX MCP Server Diagnostics");
|
|
7492
|
+
outputLine(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
7290
7493
|
const report = new Report();
|
|
7291
7494
|
report.add("ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
7292
7495
|
report.add("mode", "mcp");
|
|
@@ -7307,11 +7510,11 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7307
7510
|
handshakePassed = true;
|
|
7308
7511
|
}
|
|
7309
7512
|
const allPassed = nodePassed && entryPassed && cfgPassed && moduleLoadPassed && handshakePassed;
|
|
7310
|
-
|
|
7513
|
+
outputLine("");
|
|
7311
7514
|
if (allPassed) {
|
|
7312
|
-
|
|
7515
|
+
outputLine(" Result: All checks passed \u2713");
|
|
7313
7516
|
} else {
|
|
7314
|
-
|
|
7517
|
+
outputLine(" Result: Some checks failed \u2717");
|
|
7315
7518
|
process.exitCode = 1;
|
|
7316
7519
|
}
|
|
7317
7520
|
report.add("result", allPassed ? "PASS" : "FAIL");
|
|
@@ -7321,7 +7524,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7321
7524
|
|
|
7322
7525
|
// src/commands/diagnose.ts
|
|
7323
7526
|
var CLI_VERSION = readCliVersion();
|
|
7324
|
-
var GIT_HASH = true ? "
|
|
7527
|
+
var GIT_HASH = true ? "9f66f84" : "dev";
|
|
7325
7528
|
function maskKey2(key) {
|
|
7326
7529
|
if (!key) return "(not set)";
|
|
7327
7530
|
if (key.length <= 8) return "****";
|
|
@@ -7563,22 +7766,52 @@ async function cmdDiagnose(config, profile, options = {}) {
|
|
|
7563
7766
|
}
|
|
7564
7767
|
return runCliChecks(config, profile, options.output);
|
|
7565
7768
|
}
|
|
7769
|
+
function checkConfigFile(report) {
|
|
7770
|
+
section("Config File");
|
|
7771
|
+
const path5 = configFilePath();
|
|
7772
|
+
try {
|
|
7773
|
+
readFullConfig();
|
|
7774
|
+
ok("Config parse", `${path5} OK`);
|
|
7775
|
+
report.add("config_parse", "OK");
|
|
7776
|
+
return true;
|
|
7777
|
+
} catch (e) {
|
|
7778
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
7779
|
+
fail("Config parse", msg, [
|
|
7780
|
+
`If passphrase contains special characters (# \\ " '), wrap in quotes:`,
|
|
7781
|
+
` Contains # \\ " \u2192 passphrase = 'value'`,
|
|
7782
|
+
` Contains ' \u2192 passphrase = "value"`,
|
|
7783
|
+
" Contains both \u2192 passphrase = '''value'''",
|
|
7784
|
+
"Or re-run: okx config init"
|
|
7785
|
+
]);
|
|
7786
|
+
report.add("config_parse", `FAIL ${msg}`);
|
|
7787
|
+
return false;
|
|
7788
|
+
}
|
|
7789
|
+
}
|
|
7566
7790
|
async function runCliChecks(config, profile, outputPath) {
|
|
7567
7791
|
process.stdout.write("\n OKX Trade CLI Diagnostics\n");
|
|
7568
7792
|
process.stdout.write(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
|
|
7569
7793
|
const report = new Report();
|
|
7570
7794
|
report.add("ts", (/* @__PURE__ */ new Date()).toISOString());
|
|
7795
|
+
const configFilePassed = checkConfigFile(report);
|
|
7571
7796
|
const envPassed = checkEnvironment(report);
|
|
7797
|
+
if (!config) {
|
|
7798
|
+
fail("Config", "Could not load config (see Config File check above)", []);
|
|
7799
|
+
report.add("result", "FAIL");
|
|
7800
|
+
report.print();
|
|
7801
|
+
writeReportIfRequested(report, outputPath);
|
|
7802
|
+
process.exitCode = 1;
|
|
7803
|
+
return;
|
|
7804
|
+
}
|
|
7572
7805
|
const cfgPassed = checkConfig(config, profile, report);
|
|
7573
7806
|
const client = new OkxRestClient(config);
|
|
7574
7807
|
const netPassed = await checkNetwork(config, client, report);
|
|
7575
7808
|
const authPassed = await checkAuth(client, config, report);
|
|
7576
|
-
const allPassed = envPassed && cfgPassed && netPassed && authPassed;
|
|
7577
|
-
|
|
7809
|
+
const allPassed = configFilePassed && envPassed && cfgPassed && netPassed && authPassed;
|
|
7810
|
+
outputLine("");
|
|
7578
7811
|
if (allPassed) {
|
|
7579
|
-
|
|
7812
|
+
outputLine(" Result: All checks passed \u2713");
|
|
7580
7813
|
} else {
|
|
7581
|
-
|
|
7814
|
+
outputLine(" Result: Some checks failed \u2717");
|
|
7582
7815
|
process.exitCode = 1;
|
|
7583
7816
|
}
|
|
7584
7817
|
report.add("result", allPassed ? "PASS" : "FAIL");
|
|
@@ -7600,6 +7833,9 @@ function loadProfileConfig(opts) {
|
|
|
7600
7833
|
});
|
|
7601
7834
|
}
|
|
7602
7835
|
|
|
7836
|
+
// src/help.ts
|
|
7837
|
+
import { EOL as EOL2 } from "os";
|
|
7838
|
+
|
|
7603
7839
|
// src/commands/client-setup.ts
|
|
7604
7840
|
import * as fs5 from "fs";
|
|
7605
7841
|
var DETECTABLE_CLIENTS = ["claude-desktop", "cursor", "windsurf"];
|
|
@@ -7615,14 +7851,11 @@ function cmdSetupClients() {
|
|
|
7615
7851
|
}
|
|
7616
7852
|
}
|
|
7617
7853
|
if (detected.length > 0) {
|
|
7618
|
-
|
|
7619
|
-
`);
|
|
7854
|
+
outputLine("Detected clients:");
|
|
7620
7855
|
for (const { id, path: path5 } of detected) {
|
|
7621
|
-
|
|
7622
|
-
`);
|
|
7856
|
+
outputLine(` ${id.padEnd(16)} ${path5}`);
|
|
7623
7857
|
}
|
|
7624
|
-
|
|
7625
|
-
`);
|
|
7858
|
+
outputLine("");
|
|
7626
7859
|
}
|
|
7627
7860
|
printSetupUsage();
|
|
7628
7861
|
}
|
|
@@ -8197,13 +8430,12 @@ function printGlobalHelp() {
|
|
|
8197
8430
|
lines.push(` ${name.padEnd(colWidth)}${group.description}`);
|
|
8198
8431
|
}
|
|
8199
8432
|
lines.push("", 'Run "okx <module> --help" for module details.', "");
|
|
8200
|
-
|
|
8433
|
+
output(lines.join(EOL2));
|
|
8201
8434
|
}
|
|
8202
8435
|
function printModuleHelp(moduleName) {
|
|
8203
8436
|
const group = HELP_TREE[moduleName];
|
|
8204
8437
|
if (!group) {
|
|
8205
|
-
|
|
8206
|
-
`);
|
|
8438
|
+
errorLine(`Unknown module: ${moduleName}`);
|
|
8207
8439
|
process.exitCode = 1;
|
|
8208
8440
|
return;
|
|
8209
8441
|
}
|
|
@@ -8247,20 +8479,18 @@ function printModuleHelp(moduleName) {
|
|
|
8247
8479
|
}
|
|
8248
8480
|
}
|
|
8249
8481
|
lines.push("");
|
|
8250
|
-
|
|
8482
|
+
output(lines.join(EOL2));
|
|
8251
8483
|
}
|
|
8252
8484
|
function printSubgroupHelp(moduleName, subgroupName) {
|
|
8253
8485
|
const group = HELP_TREE[moduleName];
|
|
8254
8486
|
if (!group) {
|
|
8255
|
-
|
|
8256
|
-
`);
|
|
8487
|
+
errorLine(`Unknown module: ${moduleName}`);
|
|
8257
8488
|
process.exitCode = 1;
|
|
8258
8489
|
return;
|
|
8259
8490
|
}
|
|
8260
8491
|
const subgroup = group.subgroups?.[subgroupName];
|
|
8261
8492
|
if (!subgroup) {
|
|
8262
|
-
|
|
8263
|
-
`);
|
|
8493
|
+
errorLine(`Unknown subgroup: ${moduleName} ${subgroupName}`);
|
|
8264
8494
|
process.exitCode = 1;
|
|
8265
8495
|
return;
|
|
8266
8496
|
}
|
|
@@ -8276,7 +8506,7 @@ function printSubgroupHelp(moduleName, subgroupName) {
|
|
|
8276
8506
|
printCommandList(lines, subgroup.commands);
|
|
8277
8507
|
}
|
|
8278
8508
|
lines.push("");
|
|
8279
|
-
|
|
8509
|
+
output(lines.join(EOL2));
|
|
8280
8510
|
}
|
|
8281
8511
|
function printCommandList(lines, commands) {
|
|
8282
8512
|
const names = Object.keys(commands);
|
|
@@ -8327,6 +8557,7 @@ var CLI_OPTIONS = {
|
|
|
8327
8557
|
px: { type: "string" },
|
|
8328
8558
|
posSide: { type: "string" },
|
|
8329
8559
|
tdMode: { type: "string" },
|
|
8560
|
+
tgtCcy: { type: "string" },
|
|
8330
8561
|
// leverage
|
|
8331
8562
|
lever: { type: "string" },
|
|
8332
8563
|
mgnMode: { type: "string" },
|
|
@@ -8427,6 +8658,10 @@ var CLI_OPTIONS = {
|
|
|
8427
8658
|
maxTermDays: { type: "string" },
|
|
8428
8659
|
expDate: { type: "string" },
|
|
8429
8660
|
minAnnualizedYield: { type: "string" },
|
|
8661
|
+
// indicator
|
|
8662
|
+
params: { type: "string" },
|
|
8663
|
+
list: { type: "boolean", default: false },
|
|
8664
|
+
"backtest-time": { type: "string" },
|
|
8430
8665
|
// diagnostics — cli/mcp/all/output are diagnose-specific; verbose is shared
|
|
8431
8666
|
verbose: { type: "boolean", default: false },
|
|
8432
8667
|
mcp: { type: "boolean", default: false },
|
|
@@ -8461,42 +8696,6 @@ function parseCli(argv) {
|
|
|
8461
8696
|
return { values, positionals };
|
|
8462
8697
|
}
|
|
8463
8698
|
|
|
8464
|
-
// src/formatter.ts
|
|
8465
|
-
function printJson(data) {
|
|
8466
|
-
process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
8467
|
-
}
|
|
8468
|
-
function printTable(rows) {
|
|
8469
|
-
if (rows.length === 0) {
|
|
8470
|
-
process.stdout.write("(no data)\n");
|
|
8471
|
-
return;
|
|
8472
|
-
}
|
|
8473
|
-
const keys = Object.keys(rows[0]);
|
|
8474
|
-
const widths = keys.map(
|
|
8475
|
-
(k) => Math.max(k.length, ...rows.map((r) => String(r[k] ?? "").length))
|
|
8476
|
-
);
|
|
8477
|
-
const header = keys.map((k, i) => k.padEnd(widths[i])).join(" ");
|
|
8478
|
-
const divider = widths.map((w) => "-".repeat(w)).join(" ");
|
|
8479
|
-
process.stdout.write(header + "\n" + divider + "\n");
|
|
8480
|
-
for (const row of rows) {
|
|
8481
|
-
process.stdout.write(
|
|
8482
|
-
keys.map((k, i) => String(row[k] ?? "").padEnd(widths[i])).join(" ") + "\n"
|
|
8483
|
-
);
|
|
8484
|
-
}
|
|
8485
|
-
}
|
|
8486
|
-
function printKv(obj, indent = 0) {
|
|
8487
|
-
const pad = " ".repeat(indent);
|
|
8488
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
8489
|
-
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
8490
|
-
process.stdout.write(`${pad}${k}:
|
|
8491
|
-
`);
|
|
8492
|
-
printKv(v, indent + 2);
|
|
8493
|
-
} else {
|
|
8494
|
-
process.stdout.write(`${pad}${k.padEnd(20 - indent)} ${v}
|
|
8495
|
-
`);
|
|
8496
|
-
}
|
|
8497
|
-
}
|
|
8498
|
-
}
|
|
8499
|
-
|
|
8500
8699
|
// src/commands/market.ts
|
|
8501
8700
|
function getData(result) {
|
|
8502
8701
|
return result.data;
|
|
@@ -8532,7 +8731,7 @@ async function cmdMarketFundingRate(run, instId, opts) {
|
|
|
8532
8731
|
} else {
|
|
8533
8732
|
const r = items?.[0];
|
|
8534
8733
|
if (!r) {
|
|
8535
|
-
|
|
8734
|
+
outputLine("No data");
|
|
8536
8735
|
return;
|
|
8537
8736
|
}
|
|
8538
8737
|
printKv({
|
|
@@ -8605,7 +8804,7 @@ async function cmdMarketPriceLimit(run, instId, json) {
|
|
|
8605
8804
|
if (json) return printJson(items);
|
|
8606
8805
|
const r = items?.[0];
|
|
8607
8806
|
if (!r) {
|
|
8608
|
-
|
|
8807
|
+
outputLine("No data");
|
|
8609
8808
|
return;
|
|
8610
8809
|
}
|
|
8611
8810
|
printKv({
|
|
@@ -8633,7 +8832,7 @@ async function cmdMarketTicker(run, instId, json) {
|
|
|
8633
8832
|
const items = getData(result);
|
|
8634
8833
|
if (json) return printJson(items);
|
|
8635
8834
|
if (!items?.length) {
|
|
8636
|
-
|
|
8835
|
+
outputLine("No data");
|
|
8637
8836
|
return;
|
|
8638
8837
|
}
|
|
8639
8838
|
const t = items[0];
|
|
@@ -8667,17 +8866,16 @@ async function cmdMarketOrderbook(run, instId, sz, json) {
|
|
|
8667
8866
|
if (json) return printJson(data);
|
|
8668
8867
|
const book = data[0];
|
|
8669
8868
|
if (!book) {
|
|
8670
|
-
|
|
8869
|
+
outputLine("No data");
|
|
8671
8870
|
return;
|
|
8672
8871
|
}
|
|
8673
8872
|
const asks = book["asks"].slice(0, 5);
|
|
8674
8873
|
const bids = book["bids"].slice(0, 5);
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
`);
|
|
8678
|
-
|
|
8679
|
-
for (const [p, s] of bids)
|
|
8680
|
-
`);
|
|
8874
|
+
outputLine("Asks (price / size):");
|
|
8875
|
+
asks.reverse();
|
|
8876
|
+
for (const [p, s] of asks) outputLine(` ${p.padStart(16)} ${s}`);
|
|
8877
|
+
outputLine("Bids (price / size):");
|
|
8878
|
+
for (const [p, s] of bids) outputLine(` ${p.padStart(16)} ${s}`);
|
|
8681
8879
|
}
|
|
8682
8880
|
async function cmdMarketCandles(run, instId, opts) {
|
|
8683
8881
|
const result = await run("market_get_candles", { instId, bar: opts.bar, limit: opts.limit });
|
|
@@ -8694,6 +8892,54 @@ async function cmdMarketCandles(run, instId, opts) {
|
|
|
8694
8892
|
}))
|
|
8695
8893
|
);
|
|
8696
8894
|
}
|
|
8895
|
+
async function cmdMarketIndicator(run, indicator, instId, opts) {
|
|
8896
|
+
const params = opts.params ? opts.params.split(",").map((p) => Number(p.trim())).filter((n) => !Number.isNaN(n)) : void 0;
|
|
8897
|
+
const result = await run("market_get_indicator", {
|
|
8898
|
+
instId,
|
|
8899
|
+
indicator,
|
|
8900
|
+
bar: opts.bar,
|
|
8901
|
+
params: params && params.length > 0 ? params : void 0,
|
|
8902
|
+
returnList: opts.list ?? false,
|
|
8903
|
+
limit: opts.limit,
|
|
8904
|
+
backtestTime: opts.backtestTime
|
|
8905
|
+
});
|
|
8906
|
+
const outerArray = getData(result);
|
|
8907
|
+
if (opts.json) return printJson(outerArray);
|
|
8908
|
+
if (!outerArray?.length) {
|
|
8909
|
+
process.stdout.write("No data\n");
|
|
8910
|
+
return;
|
|
8911
|
+
}
|
|
8912
|
+
const apiCode = resolveIndicatorCode(indicator);
|
|
8913
|
+
const response = outerArray[0];
|
|
8914
|
+
const innerArray = response["data"];
|
|
8915
|
+
const instData = innerArray?.[0];
|
|
8916
|
+
const timeframes = instData?.["timeframes"];
|
|
8917
|
+
if (!timeframes) {
|
|
8918
|
+
process.stdout.write(JSON.stringify(outerArray, null, 2) + "\n");
|
|
8919
|
+
return;
|
|
8920
|
+
}
|
|
8921
|
+
for (const [tf, tfData] of Object.entries(timeframes)) {
|
|
8922
|
+
const indicators = tfData?.["indicators"];
|
|
8923
|
+
const values = indicators?.[apiCode];
|
|
8924
|
+
if (!values?.length) continue;
|
|
8925
|
+
process.stdout.write(`${instId} \xB7 ${apiCode} \xB7 ${tf}
|
|
8926
|
+
`);
|
|
8927
|
+
process.stdout.write("\u2500".repeat(40) + "\n");
|
|
8928
|
+
if (opts.list) {
|
|
8929
|
+
const tableRows = values.map((entry) => ({
|
|
8930
|
+
ts: new Date(Number(entry["ts"])).toLocaleString(),
|
|
8931
|
+
...entry["values"]
|
|
8932
|
+
}));
|
|
8933
|
+
printTable(tableRows);
|
|
8934
|
+
} else {
|
|
8935
|
+
const latest = values[0];
|
|
8936
|
+
printKv({
|
|
8937
|
+
ts: new Date(Number(latest["ts"])).toLocaleString(),
|
|
8938
|
+
...latest["values"]
|
|
8939
|
+
});
|
|
8940
|
+
}
|
|
8941
|
+
}
|
|
8942
|
+
}
|
|
8697
8943
|
async function cmdMarketStockTokens(run, opts) {
|
|
8698
8944
|
const result = await run("market_get_stock_tokens", { instType: opts.instType, instId: opts.instId });
|
|
8699
8945
|
const items = getData(result);
|
|
@@ -8751,7 +8997,7 @@ async function cmdAccountPositions(run, opts) {
|
|
|
8751
8997
|
if (opts.json) return printJson(positions);
|
|
8752
8998
|
const open = (positions ?? []).filter((p) => Number(p["pos"]) !== 0);
|
|
8753
8999
|
if (!open.length) {
|
|
8754
|
-
|
|
9000
|
+
outputLine("No open positions");
|
|
8755
9001
|
return;
|
|
8756
9002
|
}
|
|
8757
9003
|
printTable(
|
|
@@ -8789,7 +9035,7 @@ async function cmdAccountFees(run, opts) {
|
|
|
8789
9035
|
if (opts.json) return printJson(data);
|
|
8790
9036
|
const fee = data?.[0];
|
|
8791
9037
|
if (!fee) {
|
|
8792
|
-
|
|
9038
|
+
outputLine("No data");
|
|
8793
9039
|
return;
|
|
8794
9040
|
}
|
|
8795
9041
|
printKv({
|
|
@@ -8807,7 +9053,7 @@ async function cmdAccountConfig(run, json) {
|
|
|
8807
9053
|
if (json) return printJson(data);
|
|
8808
9054
|
const cfg = data?.[0];
|
|
8809
9055
|
if (!cfg) {
|
|
8810
|
-
|
|
9056
|
+
outputLine("No data");
|
|
8811
9057
|
return;
|
|
8812
9058
|
}
|
|
8813
9059
|
printKv({
|
|
@@ -8825,8 +9071,7 @@ async function cmdAccountSetPositionMode(run, posMode, json) {
|
|
|
8825
9071
|
const data = getData2(result);
|
|
8826
9072
|
if (json) return printJson(data);
|
|
8827
9073
|
const r = data?.[0];
|
|
8828
|
-
|
|
8829
|
-
`);
|
|
9074
|
+
outputLine(`Position mode set: ${r?.["posMode"]}`);
|
|
8830
9075
|
}
|
|
8831
9076
|
async function cmdAccountMaxSize(run, opts) {
|
|
8832
9077
|
const result = await run("account_get_max_size", { instId: opts.instId, tdMode: opts.tdMode, px: opts.px });
|
|
@@ -8834,7 +9079,7 @@ async function cmdAccountMaxSize(run, opts) {
|
|
|
8834
9079
|
if (opts.json) return printJson(data);
|
|
8835
9080
|
const r = data?.[0];
|
|
8836
9081
|
if (!r) {
|
|
8837
|
-
|
|
9082
|
+
outputLine("No data");
|
|
8838
9083
|
return;
|
|
8839
9084
|
}
|
|
8840
9085
|
printKv({ instId: r["instId"], maxBuy: r["maxBuy"], maxSell: r["maxSell"] });
|
|
@@ -8845,7 +9090,7 @@ async function cmdAccountMaxAvailSize(run, opts) {
|
|
|
8845
9090
|
if (opts.json) return printJson(data);
|
|
8846
9091
|
const r = data?.[0];
|
|
8847
9092
|
if (!r) {
|
|
8848
|
-
|
|
9093
|
+
outputLine("No data");
|
|
8849
9094
|
return;
|
|
8850
9095
|
}
|
|
8851
9096
|
printKv({ instId: r["instId"], availBuy: r["availBuy"], availSell: r["availSell"] });
|
|
@@ -8889,8 +9134,7 @@ async function cmdAccountTransfer(run, opts) {
|
|
|
8889
9134
|
const data = getData2(result);
|
|
8890
9135
|
if (opts.json) return printJson(data);
|
|
8891
9136
|
const r = data?.[0];
|
|
8892
|
-
|
|
8893
|
-
`);
|
|
9137
|
+
outputLine(`Transfer: ${r?.["transId"]} (${r?.["ccy"]} ${r?.["amt"]})`);
|
|
8894
9138
|
}
|
|
8895
9139
|
function readAuditLogs(logDir, days = 7) {
|
|
8896
9140
|
const entries = [];
|
|
@@ -8932,7 +9176,7 @@ function cmdAccountAudit(opts) {
|
|
|
8932
9176
|
entries = entries.slice(0, limit);
|
|
8933
9177
|
if (opts.json) return printJson(entries);
|
|
8934
9178
|
if (!entries.length) {
|
|
8935
|
-
|
|
9179
|
+
outputLine("No audit log entries");
|
|
8936
9180
|
return;
|
|
8937
9181
|
}
|
|
8938
9182
|
printTable(
|
|
@@ -8950,6 +9194,25 @@ function cmdAccountAudit(opts) {
|
|
|
8950
9194
|
function getData3(result) {
|
|
8951
9195
|
return result.data;
|
|
8952
9196
|
}
|
|
9197
|
+
function emitWriteResult(item, label, idKey) {
|
|
9198
|
+
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
9199
|
+
if (isError) {
|
|
9200
|
+
errorLine(`Error: ${item?.["sMsg"]} (sCode ${item?.["sCode"]})`);
|
|
9201
|
+
} else {
|
|
9202
|
+
outputLine(`${label}: ${item?.[idKey]} (OK)`);
|
|
9203
|
+
}
|
|
9204
|
+
}
|
|
9205
|
+
function emitBatchResults(items) {
|
|
9206
|
+
for (const r of items) {
|
|
9207
|
+
const isError = r["sCode"] !== "0" && r["sCode"] !== 0;
|
|
9208
|
+
const id = r["ordId"] ?? r["clOrdId"] ?? "?";
|
|
9209
|
+
if (isError) {
|
|
9210
|
+
errorLine(`${id}: ${r["sMsg"]} (sCode ${r["sCode"]})`);
|
|
9211
|
+
} else {
|
|
9212
|
+
outputLine(`${id}: OK`);
|
|
9213
|
+
}
|
|
9214
|
+
}
|
|
9215
|
+
}
|
|
8953
9216
|
async function cmdSpotOrders(run, opts) {
|
|
8954
9217
|
const result = await run("spot_get_orders", { instId: opts.instId, status: opts.status });
|
|
8955
9218
|
const orders = getData3(result);
|
|
@@ -8974,6 +9237,7 @@ async function cmdSpotPlace(run, opts) {
|
|
|
8974
9237
|
side: opts.side,
|
|
8975
9238
|
ordType: opts.ordType,
|
|
8976
9239
|
sz: opts.sz,
|
|
9240
|
+
tgtCcy: opts.tgtCcy,
|
|
8977
9241
|
px: opts.px,
|
|
8978
9242
|
tpTriggerPx: opts.tpTriggerPx,
|
|
8979
9243
|
tpOrdPx: opts.tpOrdPx,
|
|
@@ -8982,9 +9246,7 @@ async function cmdSpotPlace(run, opts) {
|
|
|
8982
9246
|
});
|
|
8983
9247
|
const data = getData3(result);
|
|
8984
9248
|
if (opts.json) return printJson(data);
|
|
8985
|
-
|
|
8986
|
-
process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
8987
|
-
`);
|
|
9249
|
+
emitWriteResult(data?.[0], "Order placed", "ordId");
|
|
8988
9250
|
}
|
|
8989
9251
|
async function cmdSpotCancel(run, opts) {
|
|
8990
9252
|
const { instId, ordId, clOrdId, json } = opts;
|
|
@@ -8992,9 +9254,7 @@ async function cmdSpotCancel(run, opts) {
|
|
|
8992
9254
|
const result = await run("spot_cancel_order", { instId, ...ordId ? { ordId } : { clOrdId } });
|
|
8993
9255
|
const data = getData3(result);
|
|
8994
9256
|
if (json) return printJson(data);
|
|
8995
|
-
|
|
8996
|
-
process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
8997
|
-
`);
|
|
9257
|
+
emitWriteResult(data?.[0], "Cancelled", "ordId");
|
|
8998
9258
|
}
|
|
8999
9259
|
async function cmdSpotAlgoPlace(run, opts) {
|
|
9000
9260
|
const result = await run("spot_place_algo_order", {
|
|
@@ -9013,11 +9273,7 @@ async function cmdSpotAlgoPlace(run, opts) {
|
|
|
9013
9273
|
});
|
|
9014
9274
|
const data = getData3(result);
|
|
9015
9275
|
if (opts.json) return printJson(data);
|
|
9016
|
-
|
|
9017
|
-
process.stdout.write(
|
|
9018
|
-
`Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9019
|
-
`
|
|
9020
|
-
);
|
|
9276
|
+
emitWriteResult(data?.[0], "Algo order placed", "algoId");
|
|
9021
9277
|
}
|
|
9022
9278
|
async function cmdSpotAlgoAmend(run, opts) {
|
|
9023
9279
|
const result = await run("spot_amend_algo_order", {
|
|
@@ -9031,21 +9287,13 @@ async function cmdSpotAlgoAmend(run, opts) {
|
|
|
9031
9287
|
});
|
|
9032
9288
|
const data = getData3(result);
|
|
9033
9289
|
if (opts.json) return printJson(data);
|
|
9034
|
-
|
|
9035
|
-
process.stdout.write(
|
|
9036
|
-
`Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9037
|
-
`
|
|
9038
|
-
);
|
|
9290
|
+
emitWriteResult(data?.[0], "Algo order amended", "algoId");
|
|
9039
9291
|
}
|
|
9040
9292
|
async function cmdSpotAlgoCancel(run, instId, algoId, json) {
|
|
9041
9293
|
const result = await run("spot_cancel_algo_order", { instId, algoId });
|
|
9042
9294
|
const data = getData3(result);
|
|
9043
9295
|
if (json) return printJson(data);
|
|
9044
|
-
|
|
9045
|
-
process.stdout.write(
|
|
9046
|
-
`Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9047
|
-
`
|
|
9048
|
-
);
|
|
9296
|
+
emitWriteResult(data?.[0], "Algo order cancelled", "algoId");
|
|
9049
9297
|
}
|
|
9050
9298
|
async function cmdSpotGet(run, opts) {
|
|
9051
9299
|
const result = await run("spot_get_order", { instId: opts.instId, ordId: opts.ordId, clOrdId: opts.clOrdId });
|
|
@@ -9053,7 +9301,7 @@ async function cmdSpotGet(run, opts) {
|
|
|
9053
9301
|
if (opts.json) return printJson(data);
|
|
9054
9302
|
const o = data?.[0];
|
|
9055
9303
|
if (!o) {
|
|
9056
|
-
|
|
9304
|
+
outputLine("No data");
|
|
9057
9305
|
return;
|
|
9058
9306
|
}
|
|
9059
9307
|
printKv({
|
|
@@ -9079,9 +9327,7 @@ async function cmdSpotAmend(run, opts) {
|
|
|
9079
9327
|
});
|
|
9080
9328
|
const data = getData3(result);
|
|
9081
9329
|
if (opts.json) return printJson(data);
|
|
9082
|
-
|
|
9083
|
-
process.stdout.write(`Order amended: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9084
|
-
`);
|
|
9330
|
+
emitWriteResult(data?.[0], "Order amended", "ordId");
|
|
9085
9331
|
}
|
|
9086
9332
|
async function cmdSpotAlgoOrders(run, opts) {
|
|
9087
9333
|
const result = await run("spot_get_algo_orders", {
|
|
@@ -9092,7 +9338,7 @@ async function cmdSpotAlgoOrders(run, opts) {
|
|
|
9092
9338
|
const orders = getData3(result);
|
|
9093
9339
|
if (opts.json) return printJson(orders);
|
|
9094
9340
|
if (!(orders ?? []).length) {
|
|
9095
|
-
|
|
9341
|
+
outputLine("No algo orders");
|
|
9096
9342
|
return;
|
|
9097
9343
|
}
|
|
9098
9344
|
printTable(
|
|
@@ -9136,23 +9382,19 @@ async function cmdSpotAlgoTrailPlace(run, opts) {
|
|
|
9136
9382
|
});
|
|
9137
9383
|
const data = getData3(result);
|
|
9138
9384
|
if (opts.json) return printJson(data);
|
|
9139
|
-
|
|
9140
|
-
process.stdout.write(
|
|
9141
|
-
`Trailing stop placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9142
|
-
`
|
|
9143
|
-
);
|
|
9385
|
+
emitWriteResult(data?.[0], "Trailing stop placed", "algoId");
|
|
9144
9386
|
}
|
|
9145
9387
|
async function cmdSpotBatch(run, opts) {
|
|
9146
9388
|
let parsed;
|
|
9147
9389
|
try {
|
|
9148
9390
|
parsed = JSON.parse(opts.orders);
|
|
9149
9391
|
} catch {
|
|
9150
|
-
|
|
9392
|
+
errorLine("Error: --orders must be a valid JSON array");
|
|
9151
9393
|
process.exitCode = 1;
|
|
9152
9394
|
return;
|
|
9153
9395
|
}
|
|
9154
9396
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
9155
|
-
|
|
9397
|
+
errorLine("Error: --orders must be a non-empty JSON array");
|
|
9156
9398
|
process.exitCode = 1;
|
|
9157
9399
|
return;
|
|
9158
9400
|
}
|
|
@@ -9163,31 +9405,46 @@ async function cmdSpotBatch(run, opts) {
|
|
|
9163
9405
|
};
|
|
9164
9406
|
const tool = toolMap[opts.action];
|
|
9165
9407
|
if (!tool) {
|
|
9166
|
-
|
|
9167
|
-
`);
|
|
9408
|
+
errorLine("Error: --action must be one of: place, amend, cancel");
|
|
9168
9409
|
process.exitCode = 1;
|
|
9169
9410
|
return;
|
|
9170
9411
|
}
|
|
9171
9412
|
const result = await run(tool, tool === "spot_batch_orders" ? { action: opts.action, orders: parsed } : { orders: parsed });
|
|
9172
9413
|
const data = getData3(result);
|
|
9173
9414
|
if (opts.json) return printJson(data);
|
|
9174
|
-
|
|
9175
|
-
process.stdout.write(`${r["ordId"] ?? r["clOrdId"] ?? "?"}: ${r["sCode"] === "0" ? "OK" : r["sMsg"]}
|
|
9176
|
-
`);
|
|
9177
|
-
}
|
|
9415
|
+
emitBatchResults(data ?? []);
|
|
9178
9416
|
}
|
|
9179
9417
|
|
|
9180
9418
|
// src/commands/swap.ts
|
|
9181
9419
|
function getData4(result) {
|
|
9182
9420
|
return result.data;
|
|
9183
9421
|
}
|
|
9422
|
+
function emitWriteResult2(item, label, idKey) {
|
|
9423
|
+
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
9424
|
+
if (isError) {
|
|
9425
|
+
errorLine(`Error: ${item?.["sMsg"]} (sCode ${item?.["sCode"]})`);
|
|
9426
|
+
} else {
|
|
9427
|
+
outputLine(`${label}: ${item?.[idKey]} (OK)`);
|
|
9428
|
+
}
|
|
9429
|
+
}
|
|
9430
|
+
function emitBatchResults2(items) {
|
|
9431
|
+
for (const r of items) {
|
|
9432
|
+
const isError = r["sCode"] !== "0" && r["sCode"] !== 0;
|
|
9433
|
+
const id = r["ordId"] ?? r["clOrdId"] ?? "?";
|
|
9434
|
+
if (isError) {
|
|
9435
|
+
errorLine(`${id}: ${r["sMsg"]} (sCode ${r["sCode"]})`);
|
|
9436
|
+
} else {
|
|
9437
|
+
outputLine(`${id}: OK`);
|
|
9438
|
+
}
|
|
9439
|
+
}
|
|
9440
|
+
}
|
|
9184
9441
|
async function cmdSwapPositions(run, instId, json) {
|
|
9185
9442
|
const result = await run("swap_get_positions", { instId });
|
|
9186
9443
|
const positions = getData4(result);
|
|
9187
9444
|
if (json) return printJson(positions);
|
|
9188
9445
|
const open = (positions ?? []).filter((p) => Number(p["pos"]) !== 0);
|
|
9189
9446
|
if (!open.length) {
|
|
9190
|
-
|
|
9447
|
+
outputLine("No open positions");
|
|
9191
9448
|
return;
|
|
9192
9449
|
}
|
|
9193
9450
|
printTable(
|
|
@@ -9226,6 +9483,7 @@ async function cmdSwapPlace(run, opts) {
|
|
|
9226
9483
|
side: opts.side,
|
|
9227
9484
|
ordType: opts.ordType,
|
|
9228
9485
|
sz: opts.sz,
|
|
9486
|
+
tgtCcy: opts.tgtCcy,
|
|
9229
9487
|
posSide: opts.posSide,
|
|
9230
9488
|
px: opts.px,
|
|
9231
9489
|
tpTriggerPx: opts.tpTriggerPx,
|
|
@@ -9235,9 +9493,7 @@ async function cmdSwapPlace(run, opts) {
|
|
|
9235
9493
|
});
|
|
9236
9494
|
const data = getData4(result);
|
|
9237
9495
|
if (opts.json) return printJson(data);
|
|
9238
|
-
|
|
9239
|
-
process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9240
|
-
`);
|
|
9496
|
+
emitWriteResult2(data?.[0], "Order placed", "ordId");
|
|
9241
9497
|
}
|
|
9242
9498
|
async function cmdSwapCancel(run, opts) {
|
|
9243
9499
|
const { instId, ordId, clOrdId, json } = opts;
|
|
@@ -9245,9 +9501,7 @@ async function cmdSwapCancel(run, opts) {
|
|
|
9245
9501
|
const result = await run("swap_cancel_order", { instId, ...ordId ? { ordId } : { clOrdId } });
|
|
9246
9502
|
const data = getData4(result);
|
|
9247
9503
|
if (json) return printJson(data);
|
|
9248
|
-
|
|
9249
|
-
process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9250
|
-
`);
|
|
9504
|
+
emitWriteResult2(data?.[0], "Cancelled", "ordId");
|
|
9251
9505
|
}
|
|
9252
9506
|
async function cmdSwapAlgoPlace(run, opts) {
|
|
9253
9507
|
const result = await run("swap_place_algo_order", {
|
|
@@ -9268,11 +9522,7 @@ async function cmdSwapAlgoPlace(run, opts) {
|
|
|
9268
9522
|
});
|
|
9269
9523
|
const data = getData4(result);
|
|
9270
9524
|
if (opts.json) return printJson(data);
|
|
9271
|
-
|
|
9272
|
-
process.stdout.write(
|
|
9273
|
-
`Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9274
|
-
`
|
|
9275
|
-
);
|
|
9525
|
+
emitWriteResult2(data?.[0], "Algo order placed", "algoId");
|
|
9276
9526
|
}
|
|
9277
9527
|
async function cmdSwapAlgoAmend(run, opts) {
|
|
9278
9528
|
const result = await run("swap_amend_algo_order", {
|
|
@@ -9286,11 +9536,7 @@ async function cmdSwapAlgoAmend(run, opts) {
|
|
|
9286
9536
|
});
|
|
9287
9537
|
const data = getData4(result);
|
|
9288
9538
|
if (opts.json) return printJson(data);
|
|
9289
|
-
|
|
9290
|
-
process.stdout.write(
|
|
9291
|
-
`Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9292
|
-
`
|
|
9293
|
-
);
|
|
9539
|
+
emitWriteResult2(data?.[0], "Algo order amended", "algoId");
|
|
9294
9540
|
}
|
|
9295
9541
|
async function cmdSwapAlgoTrailPlace(run, opts) {
|
|
9296
9542
|
const result = await run("swap_place_move_stop_order", {
|
|
@@ -9306,21 +9552,13 @@ async function cmdSwapAlgoTrailPlace(run, opts) {
|
|
|
9306
9552
|
});
|
|
9307
9553
|
const data = getData4(result);
|
|
9308
9554
|
if (opts.json) return printJson(data);
|
|
9309
|
-
|
|
9310
|
-
process.stdout.write(
|
|
9311
|
-
`Trailing stop placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9312
|
-
`
|
|
9313
|
-
);
|
|
9555
|
+
emitWriteResult2(data?.[0], "Trailing stop placed", "algoId");
|
|
9314
9556
|
}
|
|
9315
9557
|
async function cmdSwapAlgoCancel(run, instId, algoId, json) {
|
|
9316
9558
|
const result = await run("swap_cancel_algo_orders", { orders: [{ instId, algoId }] });
|
|
9317
9559
|
const data = getData4(result);
|
|
9318
9560
|
if (json) return printJson(data);
|
|
9319
|
-
|
|
9320
|
-
process.stdout.write(
|
|
9321
|
-
`Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9322
|
-
`
|
|
9323
|
-
);
|
|
9561
|
+
emitWriteResult2(data?.[0], "Algo order cancelled", "algoId");
|
|
9324
9562
|
}
|
|
9325
9563
|
async function cmdSwapAlgoOrders(run, opts) {
|
|
9326
9564
|
const result = await run("swap_get_algo_orders", {
|
|
@@ -9331,7 +9569,7 @@ async function cmdSwapAlgoOrders(run, opts) {
|
|
|
9331
9569
|
const orders = getData4(result);
|
|
9332
9570
|
if (opts.json) return printJson(orders);
|
|
9333
9571
|
if (!(orders ?? []).length) {
|
|
9334
|
-
|
|
9572
|
+
outputLine("No algo orders");
|
|
9335
9573
|
return;
|
|
9336
9574
|
}
|
|
9337
9575
|
printTable(
|
|
@@ -9368,7 +9606,7 @@ async function cmdSwapGet(run, opts) {
|
|
|
9368
9606
|
if (opts.json) return printJson(data);
|
|
9369
9607
|
const o = data?.[0];
|
|
9370
9608
|
if (!o) {
|
|
9371
|
-
|
|
9609
|
+
outputLine("No data");
|
|
9372
9610
|
return;
|
|
9373
9611
|
}
|
|
9374
9612
|
printKv({
|
|
@@ -9395,8 +9633,7 @@ async function cmdSwapClose(run, opts) {
|
|
|
9395
9633
|
const data = getData4(result);
|
|
9396
9634
|
if (opts.json) return printJson(data);
|
|
9397
9635
|
const r = data?.[0];
|
|
9398
|
-
|
|
9399
|
-
`);
|
|
9636
|
+
outputLine(`Position closed: ${r?.["instId"]} ${r?.["posSide"] ?? ""}`);
|
|
9400
9637
|
}
|
|
9401
9638
|
async function cmdSwapGetLeverage(run, opts) {
|
|
9402
9639
|
const result = await run("swap_get_leverage", { instId: opts.instId, mgnMode: opts.mgnMode });
|
|
@@ -9421,9 +9658,7 @@ async function cmdSwapAmend(run, opts) {
|
|
|
9421
9658
|
});
|
|
9422
9659
|
const data = getData4(result);
|
|
9423
9660
|
if (opts.json) return printJson(data);
|
|
9424
|
-
|
|
9425
|
-
process.stdout.write(`Order amended: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9426
|
-
`);
|
|
9661
|
+
emitWriteResult2(data?.[0], "Order amended", "ordId");
|
|
9427
9662
|
}
|
|
9428
9663
|
async function cmdSwapSetLeverage(run, opts) {
|
|
9429
9664
|
const result = await run("swap_set_leverage", {
|
|
@@ -9435,20 +9670,19 @@ async function cmdSwapSetLeverage(run, opts) {
|
|
|
9435
9670
|
const data = getData4(result);
|
|
9436
9671
|
if (opts.json) return printJson(data);
|
|
9437
9672
|
const r = data?.[0];
|
|
9438
|
-
|
|
9439
|
-
`);
|
|
9673
|
+
outputLine(`Leverage set: ${r?.["lever"]}x ${r?.["instId"]}`);
|
|
9440
9674
|
}
|
|
9441
9675
|
async function cmdSwapBatch(run, opts) {
|
|
9442
9676
|
let parsed;
|
|
9443
9677
|
try {
|
|
9444
9678
|
parsed = JSON.parse(opts.orders);
|
|
9445
9679
|
} catch {
|
|
9446
|
-
|
|
9680
|
+
errorLine("Error: --orders must be a valid JSON array");
|
|
9447
9681
|
process.exitCode = 1;
|
|
9448
9682
|
return;
|
|
9449
9683
|
}
|
|
9450
9684
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
9451
|
-
|
|
9685
|
+
errorLine("Error: --orders must be a non-empty JSON array");
|
|
9452
9686
|
process.exitCode = 1;
|
|
9453
9687
|
return;
|
|
9454
9688
|
}
|
|
@@ -9459,24 +9693,39 @@ async function cmdSwapBatch(run, opts) {
|
|
|
9459
9693
|
};
|
|
9460
9694
|
const tool = toolMap[opts.action];
|
|
9461
9695
|
if (!tool) {
|
|
9462
|
-
|
|
9463
|
-
`);
|
|
9696
|
+
errorLine("Error: --action must be one of: place, amend, cancel");
|
|
9464
9697
|
process.exitCode = 1;
|
|
9465
9698
|
return;
|
|
9466
9699
|
}
|
|
9467
9700
|
const result = await run(tool, tool === "swap_batch_orders" ? { action: opts.action, orders: parsed } : { orders: parsed });
|
|
9468
9701
|
const data = getData4(result);
|
|
9469
9702
|
if (opts.json) return printJson(data);
|
|
9470
|
-
|
|
9471
|
-
process.stdout.write(`${r["ordId"] ?? r["clOrdId"] ?? "?"}: ${r["sCode"] === "0" ? "OK" : r["sMsg"]}
|
|
9472
|
-
`);
|
|
9473
|
-
}
|
|
9703
|
+
emitBatchResults2(data ?? []);
|
|
9474
9704
|
}
|
|
9475
9705
|
|
|
9476
9706
|
// src/commands/futures.ts
|
|
9477
9707
|
function getData5(result) {
|
|
9478
9708
|
return result.data;
|
|
9479
9709
|
}
|
|
9710
|
+
function emitWriteResult3(item, label, idKey) {
|
|
9711
|
+
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
9712
|
+
if (isError) {
|
|
9713
|
+
errorLine(`Error: ${item?.["sMsg"]} (sCode ${item?.["sCode"]})`);
|
|
9714
|
+
} else {
|
|
9715
|
+
outputLine(`${label}: ${item?.[idKey]} (OK)`);
|
|
9716
|
+
}
|
|
9717
|
+
}
|
|
9718
|
+
function emitBatchResults3(items) {
|
|
9719
|
+
for (const r of items) {
|
|
9720
|
+
const isError = r["sCode"] !== "0" && r["sCode"] !== 0;
|
|
9721
|
+
const id = r["ordId"] ?? r["clOrdId"] ?? "?";
|
|
9722
|
+
if (isError) {
|
|
9723
|
+
errorLine(`${id}: ${r["sMsg"]} (sCode ${r["sCode"]})`);
|
|
9724
|
+
} else {
|
|
9725
|
+
outputLine(`${id}: OK`);
|
|
9726
|
+
}
|
|
9727
|
+
}
|
|
9728
|
+
}
|
|
9480
9729
|
async function cmdFuturesOrders(run, opts) {
|
|
9481
9730
|
const result = await run("futures_get_orders", { instId: opts.instId, status: opts.status });
|
|
9482
9731
|
const orders = getData5(result);
|
|
@@ -9500,7 +9749,7 @@ async function cmdFuturesPositions(run, instId, json) {
|
|
|
9500
9749
|
if (json) return printJson(positions);
|
|
9501
9750
|
const open = (positions ?? []).filter((p) => Number(p["pos"]) !== 0);
|
|
9502
9751
|
if (!open.length) {
|
|
9503
|
-
|
|
9752
|
+
outputLine("No open positions");
|
|
9504
9753
|
return;
|
|
9505
9754
|
}
|
|
9506
9755
|
printTable(
|
|
@@ -9536,6 +9785,7 @@ async function cmdFuturesPlace(run, opts) {
|
|
|
9536
9785
|
side: opts.side,
|
|
9537
9786
|
ordType: opts.ordType,
|
|
9538
9787
|
sz: opts.sz,
|
|
9788
|
+
tgtCcy: opts.tgtCcy,
|
|
9539
9789
|
posSide: opts.posSide,
|
|
9540
9790
|
px: opts.px,
|
|
9541
9791
|
reduceOnly: opts.reduceOnly,
|
|
@@ -9546,9 +9796,7 @@ async function cmdFuturesPlace(run, opts) {
|
|
|
9546
9796
|
});
|
|
9547
9797
|
const data = getData5(result);
|
|
9548
9798
|
if (opts.json) return printJson(data);
|
|
9549
|
-
|
|
9550
|
-
process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9551
|
-
`);
|
|
9799
|
+
emitWriteResult3(data?.[0], "Order placed", "ordId");
|
|
9552
9800
|
}
|
|
9553
9801
|
async function cmdFuturesCancel(run, opts) {
|
|
9554
9802
|
const { instId, ordId, clOrdId, json } = opts;
|
|
@@ -9556,9 +9804,7 @@ async function cmdFuturesCancel(run, opts) {
|
|
|
9556
9804
|
const result = await run("futures_cancel_order", { instId, ...ordId ? { ordId } : { clOrdId } });
|
|
9557
9805
|
const data = getData5(result);
|
|
9558
9806
|
if (json) return printJson(data);
|
|
9559
|
-
|
|
9560
|
-
process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9561
|
-
`);
|
|
9807
|
+
emitWriteResult3(data?.[0], "Cancelled", "ordId");
|
|
9562
9808
|
}
|
|
9563
9809
|
async function cmdFuturesGet(run, opts) {
|
|
9564
9810
|
const result = await run("futures_get_order", { instId: opts.instId, ordId: opts.ordId });
|
|
@@ -9566,7 +9812,7 @@ async function cmdFuturesGet(run, opts) {
|
|
|
9566
9812
|
if (opts.json) return printJson(data);
|
|
9567
9813
|
const o = data?.[0];
|
|
9568
9814
|
if (!o) {
|
|
9569
|
-
|
|
9815
|
+
outputLine("No data");
|
|
9570
9816
|
return;
|
|
9571
9817
|
}
|
|
9572
9818
|
printKv({
|
|
@@ -9593,9 +9839,7 @@ async function cmdFuturesAmend(run, opts) {
|
|
|
9593
9839
|
});
|
|
9594
9840
|
const data = getData5(result);
|
|
9595
9841
|
if (opts.json) return printJson(data);
|
|
9596
|
-
|
|
9597
|
-
process.stdout.write(`Order amended: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9598
|
-
`);
|
|
9842
|
+
emitWriteResult3(data?.[0], "Order amended", "ordId");
|
|
9599
9843
|
}
|
|
9600
9844
|
async function cmdFuturesClose(run, opts) {
|
|
9601
9845
|
const result = await run("futures_close_position", {
|
|
@@ -9607,8 +9851,7 @@ async function cmdFuturesClose(run, opts) {
|
|
|
9607
9851
|
const data = getData5(result);
|
|
9608
9852
|
if (opts.json) return printJson(data);
|
|
9609
9853
|
const r = data?.[0];
|
|
9610
|
-
|
|
9611
|
-
`);
|
|
9854
|
+
outputLine(`Position closed: ${r?.["instId"]} ${r?.["posSide"] ?? ""}`);
|
|
9612
9855
|
}
|
|
9613
9856
|
async function cmdFuturesSetLeverage(run, opts) {
|
|
9614
9857
|
const result = await run("futures_set_leverage", {
|
|
@@ -9620,8 +9863,7 @@ async function cmdFuturesSetLeverage(run, opts) {
|
|
|
9620
9863
|
const data = getData5(result);
|
|
9621
9864
|
if (opts.json) return printJson(data);
|
|
9622
9865
|
const r = data?.[0];
|
|
9623
|
-
|
|
9624
|
-
`);
|
|
9866
|
+
outputLine(`Leverage set: ${r?.["lever"]}x ${r?.["instId"]}`);
|
|
9625
9867
|
}
|
|
9626
9868
|
async function cmdFuturesGetLeverage(run, opts) {
|
|
9627
9869
|
const result = await run("futures_get_leverage", { instId: opts.instId, mgnMode: opts.mgnMode });
|
|
@@ -9641,12 +9883,12 @@ async function cmdFuturesBatch(run, opts) {
|
|
|
9641
9883
|
try {
|
|
9642
9884
|
parsed = JSON.parse(opts.orders);
|
|
9643
9885
|
} catch {
|
|
9644
|
-
|
|
9886
|
+
errorLine("Error: --orders must be a valid JSON array");
|
|
9645
9887
|
process.exitCode = 1;
|
|
9646
9888
|
return;
|
|
9647
9889
|
}
|
|
9648
9890
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
9649
|
-
|
|
9891
|
+
errorLine("Error: --orders must be a non-empty JSON array");
|
|
9650
9892
|
process.exitCode = 1;
|
|
9651
9893
|
return;
|
|
9652
9894
|
}
|
|
@@ -9657,18 +9899,14 @@ async function cmdFuturesBatch(run, opts) {
|
|
|
9657
9899
|
};
|
|
9658
9900
|
const tool = toolMap[opts.action];
|
|
9659
9901
|
if (!tool) {
|
|
9660
|
-
|
|
9661
|
-
`);
|
|
9902
|
+
errorLine("Error: --action must be one of: place, amend, cancel");
|
|
9662
9903
|
process.exitCode = 1;
|
|
9663
9904
|
return;
|
|
9664
9905
|
}
|
|
9665
9906
|
const result = await run(tool, tool === "futures_batch_orders" ? { orders: parsed } : { orders: parsed });
|
|
9666
9907
|
const data = getData5(result);
|
|
9667
9908
|
if (opts.json) return printJson(data);
|
|
9668
|
-
|
|
9669
|
-
process.stdout.write(`${r["ordId"] ?? r["clOrdId"] ?? "?"}: ${r["sCode"] === "0" ? "OK" : r["sMsg"]}
|
|
9670
|
-
`);
|
|
9671
|
-
}
|
|
9909
|
+
emitBatchResults3(data ?? []);
|
|
9672
9910
|
}
|
|
9673
9911
|
async function cmdFuturesAlgoPlace(run, opts) {
|
|
9674
9912
|
const result = await run("futures_place_algo_order", {
|
|
@@ -9689,11 +9927,7 @@ async function cmdFuturesAlgoPlace(run, opts) {
|
|
|
9689
9927
|
});
|
|
9690
9928
|
const data = getData5(result);
|
|
9691
9929
|
if (opts.json) return printJson(data);
|
|
9692
|
-
|
|
9693
|
-
process.stdout.write(
|
|
9694
|
-
`Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9695
|
-
`
|
|
9696
|
-
);
|
|
9930
|
+
emitWriteResult3(data?.[0], "Algo order placed", "algoId");
|
|
9697
9931
|
}
|
|
9698
9932
|
async function cmdFuturesAlgoTrailPlace(run, opts) {
|
|
9699
9933
|
const result = await run("futures_place_move_stop_order", {
|
|
@@ -9709,11 +9943,7 @@ async function cmdFuturesAlgoTrailPlace(run, opts) {
|
|
|
9709
9943
|
});
|
|
9710
9944
|
const data = getData5(result);
|
|
9711
9945
|
if (opts.json) return printJson(data);
|
|
9712
|
-
|
|
9713
|
-
process.stdout.write(
|
|
9714
|
-
`Trailing stop placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9715
|
-
`
|
|
9716
|
-
);
|
|
9946
|
+
emitWriteResult3(data?.[0], "Trailing stop placed", "algoId");
|
|
9717
9947
|
}
|
|
9718
9948
|
async function cmdFuturesAlgoAmend(run, opts) {
|
|
9719
9949
|
const result = await run("futures_amend_algo_order", {
|
|
@@ -9727,21 +9957,13 @@ async function cmdFuturesAlgoAmend(run, opts) {
|
|
|
9727
9957
|
});
|
|
9728
9958
|
const data = getData5(result);
|
|
9729
9959
|
if (opts.json) return printJson(data);
|
|
9730
|
-
|
|
9731
|
-
process.stdout.write(
|
|
9732
|
-
`Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9733
|
-
`
|
|
9734
|
-
);
|
|
9960
|
+
emitWriteResult3(data?.[0], "Algo order amended", "algoId");
|
|
9735
9961
|
}
|
|
9736
9962
|
async function cmdFuturesAlgoCancel(run, instId, algoId, json) {
|
|
9737
9963
|
const result = await run("futures_cancel_algo_orders", { orders: [{ instId, algoId }] });
|
|
9738
9964
|
const data = getData5(result);
|
|
9739
9965
|
if (json) return printJson(data);
|
|
9740
|
-
|
|
9741
|
-
process.stdout.write(
|
|
9742
|
-
`Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9743
|
-
`
|
|
9744
|
-
);
|
|
9966
|
+
emitWriteResult3(data?.[0], "Algo order cancelled", "algoId");
|
|
9745
9967
|
}
|
|
9746
9968
|
async function cmdFuturesAlgoOrders(run, opts) {
|
|
9747
9969
|
const result = await run("futures_get_algo_orders", {
|
|
@@ -9752,7 +9974,7 @@ async function cmdFuturesAlgoOrders(run, opts) {
|
|
|
9752
9974
|
const orders = getData5(result);
|
|
9753
9975
|
if (opts.json) return printJson(orders);
|
|
9754
9976
|
if (!(orders ?? []).length) {
|
|
9755
|
-
|
|
9977
|
+
outputLine("No algo orders");
|
|
9756
9978
|
return;
|
|
9757
9979
|
}
|
|
9758
9980
|
printTable(
|
|
@@ -9773,6 +9995,25 @@ async function cmdFuturesAlgoOrders(run, opts) {
|
|
|
9773
9995
|
function getData6(result) {
|
|
9774
9996
|
return result.data;
|
|
9775
9997
|
}
|
|
9998
|
+
function emitWriteResult4(item, label, idKey) {
|
|
9999
|
+
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
10000
|
+
if (isError) {
|
|
10001
|
+
errorLine(`Error: ${item?.["sMsg"]} (sCode ${item?.["sCode"]})`);
|
|
10002
|
+
} else {
|
|
10003
|
+
outputLine(`${label}: ${item?.[idKey]} (OK)`);
|
|
10004
|
+
}
|
|
10005
|
+
}
|
|
10006
|
+
function emitBatchResults4(items) {
|
|
10007
|
+
for (const r of items) {
|
|
10008
|
+
const isError = r["sCode"] !== "0" && r["sCode"] !== 0;
|
|
10009
|
+
const id = r["ordId"] ?? r["clOrdId"] ?? "?";
|
|
10010
|
+
if (isError) {
|
|
10011
|
+
errorLine(`${id}: ${r["sMsg"]} (sCode ${r["sCode"]})`);
|
|
10012
|
+
} else {
|
|
10013
|
+
outputLine(`${id}: OK`);
|
|
10014
|
+
}
|
|
10015
|
+
}
|
|
10016
|
+
}
|
|
9776
10017
|
async function cmdOptionOrders(run, opts) {
|
|
9777
10018
|
const result = await run("option_get_orders", {
|
|
9778
10019
|
instId: opts.instId,
|
|
@@ -9803,7 +10044,7 @@ async function cmdOptionGet(run, opts) {
|
|
|
9803
10044
|
if (opts.json) return printJson(data);
|
|
9804
10045
|
const o = data?.[0];
|
|
9805
10046
|
if (!o) {
|
|
9806
|
-
|
|
10047
|
+
outputLine("No data");
|
|
9807
10048
|
return;
|
|
9808
10049
|
}
|
|
9809
10050
|
printKv({
|
|
@@ -9828,7 +10069,7 @@ async function cmdOptionPositions(run, opts) {
|
|
|
9828
10069
|
if (opts.json) return printJson(positions);
|
|
9829
10070
|
const open = (positions ?? []).filter((p) => Number(p["pos"]) !== 0);
|
|
9830
10071
|
if (!open.length) {
|
|
9831
|
-
|
|
10072
|
+
outputLine("No open positions");
|
|
9832
10073
|
return;
|
|
9833
10074
|
}
|
|
9834
10075
|
printTable(
|
|
@@ -9918,9 +10159,7 @@ async function cmdOptionPlace(run, opts) {
|
|
|
9918
10159
|
});
|
|
9919
10160
|
const data = getData6(result);
|
|
9920
10161
|
if (opts.json) return printJson(data);
|
|
9921
|
-
|
|
9922
|
-
process.stdout.write(`Order placed: ${order?.["ordId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9923
|
-
`);
|
|
10162
|
+
emitWriteResult4(data?.[0], "Order placed", "ordId");
|
|
9924
10163
|
}
|
|
9925
10164
|
async function cmdOptionCancel(run, opts) {
|
|
9926
10165
|
const result = await run("option_cancel_order", {
|
|
@@ -9930,9 +10169,7 @@ async function cmdOptionCancel(run, opts) {
|
|
|
9930
10169
|
});
|
|
9931
10170
|
const data = getData6(result);
|
|
9932
10171
|
if (opts.json) return printJson(data);
|
|
9933
|
-
|
|
9934
|
-
process.stdout.write(`Cancelled: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9935
|
-
`);
|
|
10172
|
+
emitWriteResult4(data?.[0], "Cancelled", "ordId");
|
|
9936
10173
|
}
|
|
9937
10174
|
async function cmdOptionAmend(run, opts) {
|
|
9938
10175
|
const result = await run("option_amend_order", {
|
|
@@ -9944,31 +10181,26 @@ async function cmdOptionAmend(run, opts) {
|
|
|
9944
10181
|
});
|
|
9945
10182
|
const data = getData6(result);
|
|
9946
10183
|
if (opts.json) return printJson(data);
|
|
9947
|
-
|
|
9948
|
-
process.stdout.write(`Amended: ${r?.["ordId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
9949
|
-
`);
|
|
10184
|
+
emitWriteResult4(data?.[0], "Amended", "ordId");
|
|
9950
10185
|
}
|
|
9951
10186
|
async function cmdOptionBatchCancel(run, opts) {
|
|
9952
10187
|
let parsed;
|
|
9953
10188
|
try {
|
|
9954
10189
|
parsed = JSON.parse(opts.orders);
|
|
9955
10190
|
} catch {
|
|
9956
|
-
|
|
10191
|
+
errorLine("Error: --orders must be a valid JSON array");
|
|
9957
10192
|
process.exitCode = 1;
|
|
9958
10193
|
return;
|
|
9959
10194
|
}
|
|
9960
10195
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
9961
|
-
|
|
10196
|
+
errorLine("Error: --orders must be a non-empty JSON array");
|
|
9962
10197
|
process.exitCode = 1;
|
|
9963
10198
|
return;
|
|
9964
10199
|
}
|
|
9965
10200
|
const result = await run("option_batch_cancel", { orders: parsed });
|
|
9966
10201
|
const data = getData6(result);
|
|
9967
10202
|
if (opts.json) return printJson(data);
|
|
9968
|
-
|
|
9969
|
-
process.stdout.write(`${r["ordId"]}: ${r["sCode"] === "0" ? "OK" : r["sMsg"]}
|
|
9970
|
-
`);
|
|
9971
|
-
}
|
|
10203
|
+
emitBatchResults4(data ?? []);
|
|
9972
10204
|
}
|
|
9973
10205
|
async function cmdOptionAlgoPlace(run, opts) {
|
|
9974
10206
|
const result = await run("option_place_algo_order", {
|
|
@@ -9986,11 +10218,7 @@ async function cmdOptionAlgoPlace(run, opts) {
|
|
|
9986
10218
|
});
|
|
9987
10219
|
const data = getData6(result);
|
|
9988
10220
|
if (opts.json) return printJson(data);
|
|
9989
|
-
|
|
9990
|
-
process.stdout.write(
|
|
9991
|
-
`Algo order placed: ${order?.["algoId"]} (${order?.["sCode"] === "0" ? "OK" : order?.["sMsg"]})
|
|
9992
|
-
`
|
|
9993
|
-
);
|
|
10221
|
+
emitWriteResult4(data?.[0], "Algo order placed", "algoId");
|
|
9994
10222
|
}
|
|
9995
10223
|
async function cmdOptionAlgoAmend(run, opts) {
|
|
9996
10224
|
const result = await run("option_amend_algo_order", {
|
|
@@ -10004,21 +10232,13 @@ async function cmdOptionAlgoAmend(run, opts) {
|
|
|
10004
10232
|
});
|
|
10005
10233
|
const data = getData6(result);
|
|
10006
10234
|
if (opts.json) return printJson(data);
|
|
10007
|
-
|
|
10008
|
-
process.stdout.write(
|
|
10009
|
-
`Algo order amended: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10010
|
-
`
|
|
10011
|
-
);
|
|
10235
|
+
emitWriteResult4(data?.[0], "Algo order amended", "algoId");
|
|
10012
10236
|
}
|
|
10013
10237
|
async function cmdOptionAlgoCancel(run, opts) {
|
|
10014
10238
|
const result = await run("option_cancel_algo_orders", { orders: [{ instId: opts.instId, algoId: opts.algoId }] });
|
|
10015
10239
|
const data = getData6(result);
|
|
10016
10240
|
if (opts.json) return printJson(data);
|
|
10017
|
-
|
|
10018
|
-
process.stdout.write(
|
|
10019
|
-
`Algo order cancelled: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10020
|
-
`
|
|
10021
|
-
);
|
|
10241
|
+
emitWriteResult4(data?.[0], "Algo order cancelled", "algoId");
|
|
10022
10242
|
}
|
|
10023
10243
|
async function cmdOptionAlgoOrders(run, opts) {
|
|
10024
10244
|
const result = await run("option_get_algo_orders", {
|
|
@@ -10029,7 +10249,7 @@ async function cmdOptionAlgoOrders(run, opts) {
|
|
|
10029
10249
|
const orders = getData6(result);
|
|
10030
10250
|
if (opts.json) return printJson(orders);
|
|
10031
10251
|
if (!(orders ?? []).length) {
|
|
10032
|
-
|
|
10252
|
+
outputLine("No algo orders");
|
|
10033
10253
|
return;
|
|
10034
10254
|
}
|
|
10035
10255
|
printTable(
|
|
@@ -10130,21 +10350,18 @@ function prompt(rl, question) {
|
|
|
10130
10350
|
function cmdConfigShow(json) {
|
|
10131
10351
|
const config = readFullConfig();
|
|
10132
10352
|
if (json) return printJson(config);
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
`);
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
`);
|
|
10353
|
+
outputLine(`Config: ${configFilePath()}`);
|
|
10354
|
+
outputLine("");
|
|
10355
|
+
outputLine(`default_profile: ${config.default_profile ?? "(not set)"}`);
|
|
10356
|
+
outputLine("");
|
|
10139
10357
|
for (const [name, profile] of Object.entries(config.profiles)) {
|
|
10140
|
-
|
|
10141
|
-
`);
|
|
10358
|
+
outputLine(`[${name}]`);
|
|
10142
10359
|
printKv({
|
|
10143
10360
|
api_key: profile.api_key ? maskSecret(profile.api_key) : "(not set)",
|
|
10144
10361
|
demo: profile.demo ?? false,
|
|
10145
10362
|
base_url: profile.base_url ?? "(default)"
|
|
10146
10363
|
}, 2);
|
|
10147
|
-
|
|
10364
|
+
outputLine("");
|
|
10148
10365
|
}
|
|
10149
10366
|
}
|
|
10150
10367
|
function cmdConfigSet(key, value) {
|
|
@@ -10152,11 +10369,9 @@ function cmdConfigSet(key, value) {
|
|
|
10152
10369
|
if (key === "default_profile") {
|
|
10153
10370
|
config.default_profile = value;
|
|
10154
10371
|
writeCliConfig(config);
|
|
10155
|
-
|
|
10156
|
-
`);
|
|
10372
|
+
outputLine(`default_profile set to "${value}"`);
|
|
10157
10373
|
} else {
|
|
10158
|
-
|
|
10159
|
-
`);
|
|
10374
|
+
errorLine(`Unknown config key: ${key}`);
|
|
10160
10375
|
process.exitCode = 1;
|
|
10161
10376
|
}
|
|
10162
10377
|
}
|
|
@@ -10192,24 +10407,22 @@ function buildProfileEntry(siteKey, apiKey, secretKey, passphrase, demo) {
|
|
|
10192
10407
|
}
|
|
10193
10408
|
async function cmdConfigInit(lang = "en") {
|
|
10194
10409
|
const t = messages[lang];
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
`);
|
|
10410
|
+
outputLine(t.title);
|
|
10411
|
+
outputLine("");
|
|
10198
10412
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
10199
10413
|
try {
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
process.stdout.write(" 3) US (app.okx.com)\n");
|
|
10414
|
+
outputLine(t.selectSite);
|
|
10415
|
+
outputLine(" 1) Global (www.okx.com) [default]");
|
|
10416
|
+
outputLine(" 2) EEA (my.okx.com)");
|
|
10417
|
+
outputLine(" 3) US (app.okx.com)");
|
|
10205
10418
|
const siteRaw = (await prompt(rl, t.sitePrompt)).trim();
|
|
10206
10419
|
const siteKey = parseSiteKey(siteRaw);
|
|
10207
10420
|
const demoRaw = (await prompt(rl, t.demoPrompt)).trim().toLowerCase();
|
|
10208
10421
|
const demo = demoRaw !== "n";
|
|
10209
10422
|
const apiUrl = buildApiUrl(siteKey, demo);
|
|
10210
10423
|
const hintText = demo ? t.hintDemo : t.hintLive;
|
|
10211
|
-
|
|
10212
|
-
|
|
10424
|
+
output(t.createApiKey(apiUrl));
|
|
10425
|
+
output(t.hint(hintText));
|
|
10213
10426
|
try {
|
|
10214
10427
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
10215
10428
|
spawnSync2(opener, [apiUrl], { stdio: "ignore", shell: process.platform === "win32" });
|
|
@@ -10222,35 +10435,30 @@ async function cmdConfigInit(lang = "en") {
|
|
|
10222
10435
|
if (config.profiles[profileName]) {
|
|
10223
10436
|
const overwrite = (await prompt(rl, t.profileExists(profileName))).trim().toLowerCase();
|
|
10224
10437
|
if (overwrite !== "y") {
|
|
10225
|
-
|
|
10226
|
-
`);
|
|
10438
|
+
outputLine(t.cancelled);
|
|
10227
10439
|
return;
|
|
10228
10440
|
}
|
|
10229
10441
|
}
|
|
10230
10442
|
const apiKey = (await prompt(rl, "API Key: ")).trim();
|
|
10231
10443
|
if (!apiKey) {
|
|
10232
|
-
|
|
10233
|
-
`);
|
|
10444
|
+
errorLine(t.emptyApiKey);
|
|
10234
10445
|
process.exitCode = 1;
|
|
10235
10446
|
return;
|
|
10236
10447
|
}
|
|
10237
10448
|
const secretKey = (await prompt(rl, "Secret Key: ")).trim();
|
|
10238
10449
|
if (!secretKey) {
|
|
10239
|
-
|
|
10240
|
-
`);
|
|
10450
|
+
errorLine(t.emptySecretKey);
|
|
10241
10451
|
process.exitCode = 1;
|
|
10242
10452
|
return;
|
|
10243
10453
|
}
|
|
10244
10454
|
const passphrase = (await prompt(rl, "Passphrase: ")).trim();
|
|
10245
10455
|
if (!passphrase) {
|
|
10246
|
-
|
|
10247
|
-
`);
|
|
10456
|
+
errorLine(t.emptyPassphrase);
|
|
10248
10457
|
process.exitCode = 1;
|
|
10249
10458
|
return;
|
|
10250
10459
|
}
|
|
10251
10460
|
if (demo) {
|
|
10252
|
-
|
|
10253
|
-
`);
|
|
10461
|
+
outputLine(t.demoSelected);
|
|
10254
10462
|
}
|
|
10255
10463
|
const profileEntry = buildProfileEntry(siteKey, apiKey, secretKey, passphrase, demo);
|
|
10256
10464
|
config.profiles[profileName] = profileEntry;
|
|
@@ -10260,18 +10468,18 @@ async function cmdConfigInit(lang = "en") {
|
|
|
10260
10468
|
const configPath = configFilePath();
|
|
10261
10469
|
try {
|
|
10262
10470
|
writeCliConfig(config);
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10471
|
+
output(t.saved(configPath));
|
|
10472
|
+
output(t.defaultProfile(profileName));
|
|
10473
|
+
output(t.usage);
|
|
10266
10474
|
} catch (err) {
|
|
10267
10475
|
const message = err instanceof Error ? err.message : String(err);
|
|
10268
10476
|
const isPermission = err instanceof Error && "code" in err && (err.code === "EACCES" || err.code === "EPERM");
|
|
10269
|
-
|
|
10477
|
+
errorOutput(t.writeFailed(message));
|
|
10270
10478
|
if (isPermission) {
|
|
10271
|
-
|
|
10479
|
+
errorOutput(t.permissionDenied(configPath));
|
|
10272
10480
|
}
|
|
10273
|
-
|
|
10274
|
-
|
|
10481
|
+
errorOutput(t.manualWrite(configPath));
|
|
10482
|
+
outputLine(stringify(config));
|
|
10275
10483
|
process.exitCode = 1;
|
|
10276
10484
|
}
|
|
10277
10485
|
} finally {
|
|
@@ -10295,9 +10503,8 @@ function cmdConfigAddProfile(kvPairs, force) {
|
|
|
10295
10503
|
if (!sk) missing.push("SK");
|
|
10296
10504
|
if (!pp) missing.push("PP");
|
|
10297
10505
|
if (missing.length > 0) {
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
process.stderr.write("Usage: okx config add-profile AK=<key> SK=<secret> PP=<passphrase> [site=global|eea|us] [demo=true|false] [name=<name>] [--force]\n");
|
|
10506
|
+
errorLine(`Error: missing required parameter(s): ${missing.join(", ")}`);
|
|
10507
|
+
errorLine("Usage: okx config add-profile AK=<key> SK=<secret> PP=<passphrase> [site=global|eea|us] [demo=true|false] [name=<name>] [--force]");
|
|
10301
10508
|
process.exitCode = 1;
|
|
10302
10509
|
return;
|
|
10303
10510
|
}
|
|
@@ -10307,8 +10514,7 @@ function cmdConfigAddProfile(kvPairs, force) {
|
|
|
10307
10514
|
const profileName = params["NAME"] ?? defaultName;
|
|
10308
10515
|
const config = readFullConfig();
|
|
10309
10516
|
if (config.profiles[profileName] && !force) {
|
|
10310
|
-
|
|
10311
|
-
`);
|
|
10517
|
+
errorLine(`Error: profile "${profileName}" already exists. Use --force to overwrite.`);
|
|
10312
10518
|
process.exitCode = 1;
|
|
10313
10519
|
return;
|
|
10314
10520
|
}
|
|
@@ -10317,65 +10523,54 @@ function cmdConfigAddProfile(kvPairs, force) {
|
|
|
10317
10523
|
config.profiles[profileName] = entry;
|
|
10318
10524
|
config.default_profile = profileName;
|
|
10319
10525
|
writeCliConfig(config);
|
|
10320
|
-
|
|
10321
|
-
`);
|
|
10322
|
-
process.stdout.write(`Default profile set to: ${profileName}
|
|
10323
|
-
`);
|
|
10526
|
+
outputLine(`Profile "${profileName}" saved to ${configFilePath()}`);
|
|
10527
|
+
outputLine(`Default profile set to: ${profileName}`);
|
|
10324
10528
|
}
|
|
10325
10529
|
function cmdConfigListProfile() {
|
|
10326
10530
|
const config = readFullConfig();
|
|
10327
10531
|
const entries = Object.entries(config.profiles);
|
|
10328
10532
|
if (entries.length === 0) {
|
|
10329
|
-
|
|
10533
|
+
outputLine("No profiles found. Run: okx config add-profile AK=<key> SK=<secret> PP=<passphrase>");
|
|
10330
10534
|
return;
|
|
10331
10535
|
}
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
`);
|
|
10536
|
+
outputLine(`Config: ${configFilePath()}`);
|
|
10537
|
+
outputLine("");
|
|
10335
10538
|
for (const [name, profile] of entries) {
|
|
10336
10539
|
const isDefault = name === config.default_profile;
|
|
10337
10540
|
const marker = isDefault ? " *" : "";
|
|
10338
10541
|
const site = profile.site ?? inferSiteFromBaseUrl(profile.base_url);
|
|
10339
10542
|
const mode = profile.demo !== false ? "demo (\u6A21\u62DF\u76D8)" : "live (\u5B9E\u76D8)";
|
|
10340
|
-
|
|
10341
|
-
`);
|
|
10342
|
-
|
|
10343
|
-
`);
|
|
10344
|
-
|
|
10345
|
-
`);
|
|
10346
|
-
|
|
10347
|
-
`);
|
|
10348
|
-
process.stdout.write(` site: ${site}
|
|
10349
|
-
`);
|
|
10350
|
-
process.stdout.write(` mode: ${mode}
|
|
10351
|
-
`);
|
|
10352
|
-
process.stdout.write("\n");
|
|
10543
|
+
outputLine(`[${name}]${marker}`);
|
|
10544
|
+
outputLine(` api_key: ${maskSecret(profile.api_key)}`);
|
|
10545
|
+
outputLine(` secret_key: ${maskSecret(profile.secret_key)}`);
|
|
10546
|
+
outputLine(` passphrase: ${maskSecret(profile.passphrase)}`);
|
|
10547
|
+
outputLine(` site: ${site}`);
|
|
10548
|
+
outputLine(` mode: ${mode}`);
|
|
10549
|
+
outputLine("");
|
|
10353
10550
|
}
|
|
10354
10551
|
}
|
|
10355
10552
|
function cmdConfigUse(profileName) {
|
|
10356
10553
|
if (!profileName) {
|
|
10357
|
-
|
|
10554
|
+
errorLine("Error: profile name is required.");
|
|
10555
|
+
errorLine("Usage: okx config use <profile-name>");
|
|
10358
10556
|
process.exitCode = 1;
|
|
10359
10557
|
return;
|
|
10360
10558
|
}
|
|
10361
10559
|
const config = readFullConfig();
|
|
10362
10560
|
const available = Object.keys(config.profiles);
|
|
10363
10561
|
if (!config.profiles[profileName]) {
|
|
10364
|
-
|
|
10365
|
-
`);
|
|
10562
|
+
errorLine(`Error: profile "${profileName}" does not exist.`);
|
|
10366
10563
|
if (available.length > 0) {
|
|
10367
|
-
|
|
10368
|
-
`);
|
|
10564
|
+
errorLine(`Available profiles: ${available.join(", ")}`);
|
|
10369
10565
|
} else {
|
|
10370
|
-
|
|
10566
|
+
errorLine("No profiles configured. Run: okx config add-profile AK=<key> SK=<secret> PP=<passphrase>");
|
|
10371
10567
|
}
|
|
10372
10568
|
process.exitCode = 1;
|
|
10373
10569
|
return;
|
|
10374
10570
|
}
|
|
10375
10571
|
config.default_profile = profileName;
|
|
10376
10572
|
writeCliConfig(config);
|
|
10377
|
-
|
|
10378
|
-
`);
|
|
10573
|
+
outputLine(`Default profile set to: "${profileName}"`);
|
|
10379
10574
|
}
|
|
10380
10575
|
|
|
10381
10576
|
// src/commands/earn.ts
|
|
@@ -10392,7 +10587,7 @@ function printDataList(data, json, emptyMsg, mapper) {
|
|
|
10392
10587
|
return;
|
|
10393
10588
|
}
|
|
10394
10589
|
if (!data.length) {
|
|
10395
|
-
|
|
10590
|
+
outputLine(emptyMsg);
|
|
10396
10591
|
return;
|
|
10397
10592
|
}
|
|
10398
10593
|
printTable(data.map(mapper));
|
|
@@ -10416,7 +10611,7 @@ async function cmdEarnSavingsPurchase(run, opts) {
|
|
|
10416
10611
|
}
|
|
10417
10612
|
const r = data[0];
|
|
10418
10613
|
if (!r) {
|
|
10419
|
-
|
|
10614
|
+
outputLine("No response data");
|
|
10420
10615
|
return;
|
|
10421
10616
|
}
|
|
10422
10617
|
printKv({ ccy: r["ccy"], amt: r["amt"], side: r["side"], rate: r["rate"] });
|
|
@@ -10429,7 +10624,7 @@ async function cmdEarnSavingsRedeem(run, opts) {
|
|
|
10429
10624
|
}
|
|
10430
10625
|
const r = data[0];
|
|
10431
10626
|
if (!r) {
|
|
10432
|
-
|
|
10627
|
+
outputLine("No response data");
|
|
10433
10628
|
return;
|
|
10434
10629
|
}
|
|
10435
10630
|
printKv({ ccy: r["ccy"], amt: r["amt"], side: r["side"] });
|
|
@@ -10441,8 +10636,7 @@ async function cmdEarnSetLendingRate(run, opts) {
|
|
|
10441
10636
|
return;
|
|
10442
10637
|
}
|
|
10443
10638
|
const r = data[0];
|
|
10444
|
-
|
|
10445
|
-
`);
|
|
10639
|
+
outputLine(`Lending rate set: ${r?.["ccy"]} \u2192 ${r?.["rate"]}`);
|
|
10446
10640
|
}
|
|
10447
10641
|
async function cmdEarnLendingHistory(run, opts) {
|
|
10448
10642
|
const data = extractData(await run("earn_get_lending_history", { ccy: opts.ccy, limit: opts.limit }));
|
|
@@ -10474,6 +10668,14 @@ async function cmdEarnLendingRateHistory(run, opts) {
|
|
|
10474
10668
|
}
|
|
10475
10669
|
|
|
10476
10670
|
// src/commands/bot.ts
|
|
10671
|
+
function emitWriteResult5(item, label, idKey) {
|
|
10672
|
+
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
10673
|
+
if (isError) {
|
|
10674
|
+
errorLine(`Error: ${item?.["sMsg"]} (sCode ${item?.["sCode"]})`);
|
|
10675
|
+
} else {
|
|
10676
|
+
outputLine(`${label}: ${item?.[idKey]} (OK)`);
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10477
10679
|
function getData7(result) {
|
|
10478
10680
|
return result.data;
|
|
10479
10681
|
}
|
|
@@ -10487,7 +10689,7 @@ async function cmdGridOrders(run, opts) {
|
|
|
10487
10689
|
const orders = getData7(result) ?? [];
|
|
10488
10690
|
if (opts.json) return printJson(orders);
|
|
10489
10691
|
if (!orders.length) {
|
|
10490
|
-
|
|
10692
|
+
outputLine("No grid bots");
|
|
10491
10693
|
return;
|
|
10492
10694
|
}
|
|
10493
10695
|
printTable(
|
|
@@ -10511,7 +10713,7 @@ async function cmdGridDetails(run, opts) {
|
|
|
10511
10713
|
});
|
|
10512
10714
|
const detail = (getData7(result) ?? [])[0];
|
|
10513
10715
|
if (!detail) {
|
|
10514
|
-
|
|
10716
|
+
outputLine("Bot not found");
|
|
10515
10717
|
return;
|
|
10516
10718
|
}
|
|
10517
10719
|
if (opts.json) return printJson(detail);
|
|
@@ -10540,7 +10742,7 @@ async function cmdGridSubOrders(run, opts) {
|
|
|
10540
10742
|
const orders = getData7(result) ?? [];
|
|
10541
10743
|
if (opts.json) return printJson(orders);
|
|
10542
10744
|
if (!orders.length) {
|
|
10543
|
-
|
|
10745
|
+
outputLine("No sub-orders");
|
|
10544
10746
|
return;
|
|
10545
10747
|
}
|
|
10546
10748
|
printTable(
|
|
@@ -10574,10 +10776,7 @@ async function cmdGridCreate(run, opts) {
|
|
|
10574
10776
|
const data = getData7(result);
|
|
10575
10777
|
if (opts.json) return printJson(data);
|
|
10576
10778
|
const r = data?.[0];
|
|
10577
|
-
|
|
10578
|
-
`Grid bot created: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10579
|
-
`
|
|
10580
|
-
);
|
|
10779
|
+
emitWriteResult5(data?.[0], "Grid bot created", "algoId");
|
|
10581
10780
|
}
|
|
10582
10781
|
async function cmdGridStop(run, opts) {
|
|
10583
10782
|
const result = await run("grid_stop_order", {
|
|
@@ -10589,10 +10788,7 @@ async function cmdGridStop(run, opts) {
|
|
|
10589
10788
|
const data = getData7(result);
|
|
10590
10789
|
if (opts.json) return printJson(data);
|
|
10591
10790
|
const r = data?.[0];
|
|
10592
|
-
|
|
10593
|
-
`Grid bot stopped: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10594
|
-
`
|
|
10595
|
-
);
|
|
10791
|
+
emitWriteResult5(data?.[0], "Grid bot stopped", "algoId");
|
|
10596
10792
|
}
|
|
10597
10793
|
async function cmdDcaCreate(run, opts) {
|
|
10598
10794
|
const result = await run("dca_create_order", {
|
|
@@ -10615,10 +10811,7 @@ async function cmdDcaCreate(run, opts) {
|
|
|
10615
10811
|
const data = getData7(result);
|
|
10616
10812
|
if (opts.json) return printJson(data);
|
|
10617
10813
|
const r = data?.[0];
|
|
10618
|
-
|
|
10619
|
-
`DCA bot created: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10620
|
-
`
|
|
10621
|
-
);
|
|
10814
|
+
emitWriteResult5(data?.[0], "DCA bot created", "algoId");
|
|
10622
10815
|
}
|
|
10623
10816
|
async function cmdDcaStop(run, opts) {
|
|
10624
10817
|
const result = await run("dca_stop_order", {
|
|
@@ -10627,10 +10820,7 @@ async function cmdDcaStop(run, opts) {
|
|
|
10627
10820
|
const data = getData7(result);
|
|
10628
10821
|
if (opts.json) return printJson(data);
|
|
10629
10822
|
const r = data?.[0];
|
|
10630
|
-
|
|
10631
|
-
`DCA bot stopped: ${r?.["algoId"]} (${r?.["sCode"] === "0" ? "OK" : r?.["sMsg"]})
|
|
10632
|
-
`
|
|
10633
|
-
);
|
|
10823
|
+
emitWriteResult5(data?.[0], "DCA bot stopped", "algoId");
|
|
10634
10824
|
}
|
|
10635
10825
|
async function cmdDcaOrders(run, opts) {
|
|
10636
10826
|
const result = await run("dca_get_orders", {
|
|
@@ -10641,7 +10831,7 @@ async function cmdDcaOrders(run, opts) {
|
|
|
10641
10831
|
const orders = getData7(result) ?? [];
|
|
10642
10832
|
if (opts.json) return printJson(orders);
|
|
10643
10833
|
if (!orders.length) {
|
|
10644
|
-
|
|
10834
|
+
outputLine("No DCA bots");
|
|
10645
10835
|
return;
|
|
10646
10836
|
}
|
|
10647
10837
|
printTable(
|
|
@@ -10661,7 +10851,7 @@ async function cmdDcaDetails(run, opts) {
|
|
|
10661
10851
|
});
|
|
10662
10852
|
const detail = (getData7(result) ?? [])[0];
|
|
10663
10853
|
if (!detail) {
|
|
10664
|
-
|
|
10854
|
+
outputLine("DCA bot not found");
|
|
10665
10855
|
return;
|
|
10666
10856
|
}
|
|
10667
10857
|
if (opts.json) return printJson(detail);
|
|
@@ -10689,7 +10879,7 @@ async function cmdDcaSubOrders(run, opts) {
|
|
|
10689
10879
|
const orders = getData7(result) ?? [];
|
|
10690
10880
|
if (opts.json) return printJson(orders);
|
|
10691
10881
|
if (!orders.length) {
|
|
10692
|
-
|
|
10882
|
+
outputLine("No sub-orders");
|
|
10693
10883
|
return;
|
|
10694
10884
|
}
|
|
10695
10885
|
printTable(
|
|
@@ -10778,7 +10968,7 @@ async function cmdDcdPairs(run, json) {
|
|
|
10778
10968
|
return;
|
|
10779
10969
|
}
|
|
10780
10970
|
if (!data.length) {
|
|
10781
|
-
|
|
10971
|
+
outputLine("No currency pairs available");
|
|
10782
10972
|
return;
|
|
10783
10973
|
}
|
|
10784
10974
|
printTable(data.map((r) => ({
|
|
@@ -10843,7 +11033,7 @@ async function cmdDcdProducts(run, opts) {
|
|
|
10843
11033
|
return;
|
|
10844
11034
|
}
|
|
10845
11035
|
if (!data.length) {
|
|
10846
|
-
|
|
11036
|
+
outputLine("No products matched");
|
|
10847
11037
|
return;
|
|
10848
11038
|
}
|
|
10849
11039
|
printTable(data.map((r) => ({
|
|
@@ -10863,7 +11053,7 @@ async function cmdDcdRedeemExecute(run, opts) {
|
|
|
10863
11053
|
const quoteData = extractArray(quoteResult);
|
|
10864
11054
|
const q = quoteData[0];
|
|
10865
11055
|
if (!q) {
|
|
10866
|
-
|
|
11056
|
+
outputLine("Failed to get redeem quote");
|
|
10867
11057
|
return;
|
|
10868
11058
|
}
|
|
10869
11059
|
const redeemResult = await run("dcd_redeem", {
|
|
@@ -10873,7 +11063,7 @@ async function cmdDcdRedeemExecute(run, opts) {
|
|
|
10873
11063
|
const redeemData = extractArray(redeemResult);
|
|
10874
11064
|
const r = redeemData[0];
|
|
10875
11065
|
if (!r) {
|
|
10876
|
-
|
|
11066
|
+
outputLine("No response data");
|
|
10877
11067
|
return;
|
|
10878
11068
|
}
|
|
10879
11069
|
if (opts.json) {
|
|
@@ -10896,7 +11086,7 @@ async function cmdDcdOrderState(run, opts) {
|
|
|
10896
11086
|
}
|
|
10897
11087
|
const r = data[0];
|
|
10898
11088
|
if (!r) {
|
|
10899
|
-
|
|
11089
|
+
outputLine("Order not found");
|
|
10900
11090
|
return;
|
|
10901
11091
|
}
|
|
10902
11092
|
printKv({
|
|
@@ -10926,7 +11116,7 @@ async function cmdDcdOrders(run, opts) {
|
|
|
10926
11116
|
return;
|
|
10927
11117
|
}
|
|
10928
11118
|
if (!data.length) {
|
|
10929
|
-
|
|
11119
|
+
outputLine("No orders found");
|
|
10930
11120
|
return;
|
|
10931
11121
|
}
|
|
10932
11122
|
printTable(data.map((r) => ({
|
|
@@ -10957,7 +11147,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
10957
11147
|
const r = tradeData[0];
|
|
10958
11148
|
const q = result["quote"];
|
|
10959
11149
|
if (!r) {
|
|
10960
|
-
|
|
11150
|
+
outputLine("No quote returned");
|
|
10961
11151
|
return;
|
|
10962
11152
|
}
|
|
10963
11153
|
const ordId = r["ordId"];
|
|
@@ -10974,7 +11164,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
10974
11164
|
return;
|
|
10975
11165
|
}
|
|
10976
11166
|
if (q) {
|
|
10977
|
-
|
|
11167
|
+
outputLine("Quote:");
|
|
10978
11168
|
printKv({
|
|
10979
11169
|
quoteId: q["quoteId"],
|
|
10980
11170
|
annualizedYield: q["annualizedYield"] ? `${q["annualizedYield"]}%` : "\u2014",
|
|
@@ -10982,12 +11172,13 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
10982
11172
|
notionalSz: q["notionalSz"],
|
|
10983
11173
|
notionalCcy: q["notionalCcy"]
|
|
10984
11174
|
});
|
|
10985
|
-
|
|
11175
|
+
outputLine("");
|
|
10986
11176
|
}
|
|
10987
|
-
|
|
11177
|
+
outputLine("Order placed:");
|
|
10988
11178
|
printKv({ ordId: r["ordId"], quoteId: r["quoteId"], state: r["state"] ?? r["status"] });
|
|
10989
11179
|
if (stateRow) {
|
|
10990
|
-
|
|
11180
|
+
outputLine("");
|
|
11181
|
+
outputLine("Order state:");
|
|
10991
11182
|
printKv({
|
|
10992
11183
|
ordId: stateRow["ordId"],
|
|
10993
11184
|
state: stateRow["state"],
|
|
@@ -11002,7 +11193,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
11002
11193
|
// src/index.ts
|
|
11003
11194
|
var _require3 = createRequire3(import.meta.url);
|
|
11004
11195
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
11005
|
-
var GIT_HASH2 = true ? "
|
|
11196
|
+
var GIT_HASH2 = true ? "9f66f84" : "dev";
|
|
11006
11197
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
11007
11198
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
11008
11199
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -11011,8 +11202,7 @@ function handleConfigCommand(action, rest, json, lang, force) {
|
|
|
11011
11202
|
if (action === "add-profile") return cmdConfigAddProfile(rest, force ?? false);
|
|
11012
11203
|
if (action === "list-profile") return cmdConfigListProfile();
|
|
11013
11204
|
if (action === "use") return cmdConfigUse(rest[0]);
|
|
11014
|
-
|
|
11015
|
-
`);
|
|
11205
|
+
errorLine(`Unknown config command: ${action}`);
|
|
11016
11206
|
process.exitCode = 1;
|
|
11017
11207
|
}
|
|
11018
11208
|
function handleSetupCommand(v) {
|
|
@@ -11021,11 +11211,8 @@ function handleSetupCommand(v) {
|
|
|
11021
11211
|
return;
|
|
11022
11212
|
}
|
|
11023
11213
|
if (!SUPPORTED_CLIENTS.includes(v.client)) {
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
Supported: ${SUPPORTED_CLIENTS.join(", ")}
|
|
11027
|
-
`
|
|
11028
|
-
);
|
|
11214
|
+
errorLine(`Unknown client: "${v.client}"`);
|
|
11215
|
+
errorLine(`Supported: ${SUPPORTED_CLIENTS.join(", ")}`);
|
|
11029
11216
|
process.exitCode = 1;
|
|
11030
11217
|
return;
|
|
11031
11218
|
}
|
|
@@ -11049,6 +11236,18 @@ function handleMarketPublicCommand(run, action, rest, v, json) {
|
|
|
11049
11236
|
return cmdMarketOpenInterest(run, { instType: v.instType, instId: v.instId, json });
|
|
11050
11237
|
if (action === "stock-tokens")
|
|
11051
11238
|
return cmdMarketStockTokens(run, { instType: v.instType, instId: v.instId, json });
|
|
11239
|
+
if (action === "indicator") {
|
|
11240
|
+
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
11241
|
+
const backtestTime = v["backtest-time"] !== void 0 ? Number(v["backtest-time"]) : void 0;
|
|
11242
|
+
return cmdMarketIndicator(run, rest[0], rest[1], {
|
|
11243
|
+
bar: v.bar,
|
|
11244
|
+
params: v.params,
|
|
11245
|
+
list: v.list,
|
|
11246
|
+
limit,
|
|
11247
|
+
backtestTime,
|
|
11248
|
+
json
|
|
11249
|
+
});
|
|
11250
|
+
}
|
|
11052
11251
|
}
|
|
11053
11252
|
function handleMarketDataCommand(run, action, rest, v, json) {
|
|
11054
11253
|
const limit = v.limit !== void 0 ? Number(v.limit) : void 0;
|
|
@@ -11189,6 +11388,7 @@ function handleSpotCommand(run, action, rest, v, json) {
|
|
|
11189
11388
|
side: v.side,
|
|
11190
11389
|
ordType: v.ordType,
|
|
11191
11390
|
sz: v.sz,
|
|
11391
|
+
tgtCcy: v.tgtCcy,
|
|
11192
11392
|
px: v.px,
|
|
11193
11393
|
tpTriggerPx: v.tpTriggerPx,
|
|
11194
11394
|
tpOrdPx: v.tpOrdPx,
|
|
@@ -11298,6 +11498,7 @@ function handleSwapCommand(run, action, rest, v, json) {
|
|
|
11298
11498
|
posSide: v.posSide,
|
|
11299
11499
|
px: v.px,
|
|
11300
11500
|
tdMode: v.tdMode ?? "cross",
|
|
11501
|
+
tgtCcy: v.tgtCcy,
|
|
11301
11502
|
tpTriggerPx: v.tpTriggerPx,
|
|
11302
11503
|
tpOrdPx: v.tpOrdPx,
|
|
11303
11504
|
slTriggerPx: v.slTriggerPx,
|
|
@@ -11499,6 +11700,7 @@ function handleFuturesCommand(run, action, rest, v, json) {
|
|
|
11499
11700
|
ordType: v.ordType,
|
|
11500
11701
|
sz: v.sz,
|
|
11501
11702
|
tdMode: v.tdMode ?? "cross",
|
|
11703
|
+
tgtCcy: v.tgtCcy,
|
|
11502
11704
|
posSide: v.posSide,
|
|
11503
11705
|
px: v.px,
|
|
11504
11706
|
reduceOnly: v.reduceOnly,
|
|
@@ -11627,9 +11829,8 @@ function handleEarnCommand(run, submodule, rest, v, json) {
|
|
|
11627
11829
|
if (submodule === "savings") return handleEarnSavingsCommand(run, action, innerRest, v, json);
|
|
11628
11830
|
if (submodule === "onchain") return handleEarnOnchainCommand(run, action, v, json);
|
|
11629
11831
|
if (submodule === "dcd") return handleEarnDcdCommand(run, action, v, json);
|
|
11630
|
-
|
|
11631
|
-
Valid: savings, onchain, dcd
|
|
11632
|
-
`);
|
|
11832
|
+
errorLine(`Unknown earn sub-module: ${submodule}`);
|
|
11833
|
+
errorLine("Valid: savings, onchain, dcd");
|
|
11633
11834
|
process.exitCode = 1;
|
|
11634
11835
|
}
|
|
11635
11836
|
function handleEarnSavingsCommand(run, action, rest, v, json) {
|
|
@@ -11641,8 +11842,7 @@ function handleEarnSavingsCommand(run, action, rest, v, json) {
|
|
|
11641
11842
|
if (action === "lending-history") return cmdEarnLendingHistory(run, { ccy: v.ccy, limit, json });
|
|
11642
11843
|
if (action === "rate-summary") return cmdEarnLendingRateSummary(run, rest[0] ?? v.ccy, json);
|
|
11643
11844
|
if (action === "rate-history") return cmdEarnLendingRateHistory(run, { ccy: v.ccy, limit, json });
|
|
11644
|
-
|
|
11645
|
-
`);
|
|
11845
|
+
errorLine(`Unknown earn savings command: ${action}`);
|
|
11646
11846
|
process.exitCode = 1;
|
|
11647
11847
|
}
|
|
11648
11848
|
function handleEarnOnchainCommand(run, action, v, json) {
|
|
@@ -11652,8 +11852,7 @@ function handleEarnOnchainCommand(run, action, v, json) {
|
|
|
11652
11852
|
if (action === "cancel") return cmdOnchainEarnCancel(run, v).then((r) => outputResult(r, json));
|
|
11653
11853
|
if (action === "orders") return cmdOnchainEarnActiveOrders(run, v).then((r) => outputResult(r, json));
|
|
11654
11854
|
if (action === "history") return cmdOnchainEarnOrderHistory(run, v).then((r) => outputResult(r, json));
|
|
11655
|
-
|
|
11656
|
-
`);
|
|
11855
|
+
errorLine(`Unknown earn onchain command: ${action}`);
|
|
11657
11856
|
process.exitCode = 1;
|
|
11658
11857
|
}
|
|
11659
11858
|
function parseDcdOpts(v) {
|
|
@@ -11708,16 +11907,15 @@ function handleEarnDcdCommand(run, action, v, json) {
|
|
|
11708
11907
|
limit,
|
|
11709
11908
|
json
|
|
11710
11909
|
});
|
|
11711
|
-
|
|
11712
|
-
Valid: pairs, products, quote-and-buy, redeem-execute, order, orders
|
|
11713
|
-
`);
|
|
11910
|
+
errorLine(`Unknown earn dcd command: ${action}`);
|
|
11911
|
+
errorLine("Valid: pairs, products, quote-and-buy, redeem-execute, order, orders");
|
|
11714
11912
|
process.exitCode = 1;
|
|
11715
11913
|
}
|
|
11716
11914
|
function outputResult(result, json) {
|
|
11717
11915
|
if (json) {
|
|
11718
|
-
|
|
11916
|
+
outputLine(JSON.stringify(result, null, 2));
|
|
11719
11917
|
} else {
|
|
11720
|
-
|
|
11918
|
+
outputLine(JSON.stringify(result.data, null, 2));
|
|
11721
11919
|
}
|
|
11722
11920
|
}
|
|
11723
11921
|
function printHelpForLevel(positionals) {
|
|
@@ -11726,24 +11924,15 @@ function printHelpForLevel(positionals) {
|
|
|
11726
11924
|
else if (!subgroup) printHelp(module);
|
|
11727
11925
|
else printHelp(module, subgroup);
|
|
11728
11926
|
}
|
|
11729
|
-
function printVerboseConfigSummary(config, profile) {
|
|
11730
|
-
let authLabel = "\u2717";
|
|
11731
|
-
if (config.hasAuth && config.apiKey) {
|
|
11732
|
-
authLabel = `\u2713(${config.apiKey.slice(0, 3)}***${config.apiKey.slice(-3)})`;
|
|
11733
|
-
} else if (config.hasAuth) {
|
|
11734
|
-
authLabel = "\u2713";
|
|
11735
|
-
}
|
|
11736
|
-
process.stderr.write(
|
|
11737
|
-
`[verbose] config: profile=${profile ?? "default"} site=${config.site} base=${config.baseUrl} auth=${authLabel} demo=${config.demo ? "on" : "off"} modules=${config.modules.join(",")}
|
|
11738
|
-
`
|
|
11739
|
-
);
|
|
11740
|
-
}
|
|
11741
11927
|
async function main() {
|
|
11928
|
+
setOutput({
|
|
11929
|
+
out: (m) => process.stdout.write(m),
|
|
11930
|
+
err: (m) => process.stderr.write(m)
|
|
11931
|
+
});
|
|
11742
11932
|
checkForUpdates("@okx_ai/okx-trade-cli", CLI_VERSION2);
|
|
11743
11933
|
const { values, positionals } = parseCli(process.argv.slice(2));
|
|
11744
11934
|
if (values.version) {
|
|
11745
|
-
|
|
11746
|
-
`);
|
|
11935
|
+
outputLine(`${CLI_VERSION2} (${GIT_HASH2})`);
|
|
11747
11936
|
return;
|
|
11748
11937
|
}
|
|
11749
11938
|
if (values.help || positionals.length === 0) {
|
|
@@ -11755,11 +11944,25 @@ async function main() {
|
|
|
11755
11944
|
const json = v.json ?? false;
|
|
11756
11945
|
if (module === "config") return handleConfigCommand(action, rest, json, v.lang, v.force);
|
|
11757
11946
|
if (module === "setup") return handleSetupCommand(v);
|
|
11947
|
+
if (module === "diagnose") {
|
|
11948
|
+
let config2;
|
|
11949
|
+
try {
|
|
11950
|
+
config2 = loadProfileConfig({ profile: v.profile, demo: v.demo, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
|
|
11951
|
+
} catch {
|
|
11952
|
+
}
|
|
11953
|
+
return cmdDiagnose(config2, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
|
|
11954
|
+
}
|
|
11758
11955
|
const config = loadProfileConfig({ profile: v.profile, demo: v.demo, verbose: v.verbose, userAgent: `okx-trade-cli/${CLI_VERSION2}`, sourceTag: "CLI" });
|
|
11759
|
-
if (config.verbose) printVerboseConfigSummary(config, v.profile);
|
|
11760
|
-
if (module === "diagnose") return cmdDiagnose(config, v.profile ?? "default", { mcp: v.mcp, cli: v.cli, all: v.all, output: v.output });
|
|
11761
11956
|
const client = new OkxRestClient(config);
|
|
11762
|
-
const
|
|
11957
|
+
const baseRunner = createToolRunner(client, config);
|
|
11958
|
+
const writeToolNames = new Set(allToolSpecs().filter((t) => t.isWrite).map((t) => t.name));
|
|
11959
|
+
const run = async (toolName, args) => {
|
|
11960
|
+
const result = await baseRunner(toolName, args);
|
|
11961
|
+
if (writeToolNames.has(toolName)) {
|
|
11962
|
+
markFailedIfSCodeError(result.data);
|
|
11963
|
+
}
|
|
11964
|
+
return result;
|
|
11965
|
+
};
|
|
11763
11966
|
const moduleHandlers = {
|
|
11764
11967
|
market: () => handleMarketCommand(run, action, rest, v, json),
|
|
11765
11968
|
account: () => handleAccountCommand(run, action, rest, v, json),
|
|
@@ -11772,20 +11975,15 @@ async function main() {
|
|
|
11772
11975
|
};
|
|
11773
11976
|
const handler = moduleHandlers[module];
|
|
11774
11977
|
if (handler) return handler();
|
|
11775
|
-
|
|
11776
|
-
`);
|
|
11978
|
+
errorLine(`Unknown command: ${module} ${action ?? ""}`);
|
|
11777
11979
|
process.exitCode = 1;
|
|
11778
11980
|
}
|
|
11779
11981
|
main().catch((error) => {
|
|
11780
11982
|
const payload = toToolErrorPayload(error);
|
|
11781
|
-
|
|
11782
|
-
`);
|
|
11783
|
-
if (payload.
|
|
11784
|
-
`);
|
|
11785
|
-
if (payload.suggestion) process.stderr.write(`Hint: ${payload.suggestion}
|
|
11786
|
-
`);
|
|
11787
|
-
process.stderr.write(`Version: @okx_ai/okx-trade-cli@${CLI_VERSION2}
|
|
11788
|
-
`);
|
|
11983
|
+
errorLine(`Error: ${payload.message}`);
|
|
11984
|
+
if (payload.traceId) errorLine(`TraceId: ${payload.traceId}`);
|
|
11985
|
+
if (payload.suggestion) errorLine(`Hint: ${payload.suggestion}`);
|
|
11986
|
+
errorLine(`Version: @okx_ai/okx-trade-cli@${CLI_VERSION2}`);
|
|
11789
11987
|
process.exitCode = 1;
|
|
11790
11988
|
});
|
|
11791
11989
|
export {
|