@okx_ai/okx-trade-cli 1.2.6 → 1.2.7-beta.2
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 +569 -188
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1524,7 +1524,8 @@ var BOT_DEFAULT_SUB_MODULES = ["bot.grid"];
|
|
|
1524
1524
|
var EARN_SUB_MODULE_IDS = [
|
|
1525
1525
|
"earn.savings",
|
|
1526
1526
|
"earn.onchain",
|
|
1527
|
-
"earn.dcd"
|
|
1527
|
+
"earn.dcd",
|
|
1528
|
+
"earn.autoearn"
|
|
1528
1529
|
];
|
|
1529
1530
|
var MODULES = [
|
|
1530
1531
|
"market",
|
|
@@ -2141,6 +2142,11 @@ function registerAlgoTradeTools() {
|
|
|
2141
2142
|
type: "string",
|
|
2142
2143
|
description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
|
|
2143
2144
|
},
|
|
2145
|
+
tgtCcy: {
|
|
2146
|
+
type: "string",
|
|
2147
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
2148
|
+
description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT"
|
|
2149
|
+
},
|
|
2144
2150
|
reduceOnly: {
|
|
2145
2151
|
type: "boolean",
|
|
2146
2152
|
description: "Ensure order only reduces position"
|
|
@@ -2164,6 +2170,7 @@ function registerAlgoTradeTools() {
|
|
|
2164
2170
|
posSide: readString(args, "posSide"),
|
|
2165
2171
|
ordType: requireString(args, "ordType"),
|
|
2166
2172
|
sz: requireString(args, "sz"),
|
|
2173
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
2167
2174
|
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
2168
2175
|
tpOrdPx: readString(args, "tpOrdPx"),
|
|
2169
2176
|
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
@@ -2468,6 +2475,11 @@ function registerFuturesAlgoTools() {
|
|
|
2468
2475
|
type: "string",
|
|
2469
2476
|
description: "Activation price; tracking starts after market reaches this level (move_order_stop only)"
|
|
2470
2477
|
},
|
|
2478
|
+
tgtCcy: {
|
|
2479
|
+
type: "string",
|
|
2480
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
2481
|
+
description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT"
|
|
2482
|
+
},
|
|
2471
2483
|
reduceOnly: {
|
|
2472
2484
|
type: "boolean",
|
|
2473
2485
|
description: "Ensure order only reduces position"
|
|
@@ -2491,6 +2503,7 @@ function registerFuturesAlgoTools() {
|
|
|
2491
2503
|
posSide: readString(args, "posSide"),
|
|
2492
2504
|
ordType: requireString(args, "ordType"),
|
|
2493
2505
|
sz: requireString(args, "sz"),
|
|
2506
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
2494
2507
|
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
2495
2508
|
tpOrdPx: readString(args, "tpOrdPx"),
|
|
2496
2509
|
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
@@ -2873,7 +2886,7 @@ function registerGridTools() {
|
|
|
2873
2886
|
enum: ["active", "history"],
|
|
2874
2887
|
description: "active=running (default); history=stopped"
|
|
2875
2888
|
},
|
|
2876
|
-
instId: { type: "string", description: "e.g. BTC-USDT" },
|
|
2889
|
+
instId: { type: "string", description: "e.g. BTC-USDT, BTC-USD-SWAP" },
|
|
2877
2890
|
algoId: { type: "string", description: "Grid bot algo order ID (not a trade ordId)" },
|
|
2878
2891
|
after: { type: "string", description: "Cursor for older records" },
|
|
2879
2892
|
before: { type: "string", description: "Cursor for newer records" },
|
|
@@ -2978,12 +2991,12 @@ function registerGridTools() {
|
|
|
2978
2991
|
{
|
|
2979
2992
|
name: "grid_create_order",
|
|
2980
2993
|
module: "bot.grid",
|
|
2981
|
-
description: "Create grid bot. [CAUTION]
|
|
2994
|
+
description: "Create grid bot (spot, USDT-margined, or coin-margined contract). [CAUTION] Locks funds. Spot: quoteSz|baseSz. Contract: direction+lever+sz.",
|
|
2982
2995
|
isWrite: true,
|
|
2983
2996
|
inputSchema: {
|
|
2984
2997
|
type: "object",
|
|
2985
2998
|
properties: {
|
|
2986
|
-
instId: { type: "string", description: "e.g. BTC-USDT" },
|
|
2999
|
+
instId: { type: "string", description: "e.g. BTC-USDT, BTC-USDT-SWAP, BTC-USD-SWAP (coin-margined)" },
|
|
2987
3000
|
algoOrdType: {
|
|
2988
3001
|
type: "string",
|
|
2989
3002
|
enum: ["grid", "contract_grid"],
|
|
@@ -3005,8 +3018,13 @@ function registerGridTools() {
|
|
|
3005
3018
|
description: "Contract only"
|
|
3006
3019
|
},
|
|
3007
3020
|
lever: { type: "string", description: "Leverage. Contract only" },
|
|
3008
|
-
sz: { type: "string", description: "Margin
|
|
3009
|
-
basePos: { type: "boolean", description: "Open base position for contract. Default: true" }
|
|
3021
|
+
sz: { type: "string", description: "Margin in USDT or base coin (CoinM). Contract only" },
|
|
3022
|
+
basePos: { type: "boolean", description: "Open base position for contract. Default: true" },
|
|
3023
|
+
tpTriggerPx: { type: "string", description: "TP trigger price" },
|
|
3024
|
+
slTriggerPx: { type: "string", description: "SL trigger price" },
|
|
3025
|
+
tpRatio: { type: "string", description: "TP ratio e.g. 0.1=10%. Contract only" },
|
|
3026
|
+
slRatio: { type: "string", description: "SL ratio e.g. 0.1=10%. Contract only" },
|
|
3027
|
+
algoClOrdId: { type: "string", description: "User-defined ID. Alphanumeric, max 32, unique per user" }
|
|
3010
3028
|
},
|
|
3011
3029
|
required: ["instId", "algoOrdType", "maxPx", "minPx", "gridNum"]
|
|
3012
3030
|
},
|
|
@@ -3025,9 +3043,15 @@ function registerGridTools() {
|
|
|
3025
3043
|
direction: readString(args, "direction"),
|
|
3026
3044
|
lever: readString(args, "lever"),
|
|
3027
3045
|
sz: readString(args, "sz"),
|
|
3046
|
+
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
3047
|
+
slTriggerPx: readString(args, "slTriggerPx"),
|
|
3048
|
+
tpRatio: readString(args, "tpRatio"),
|
|
3049
|
+
slRatio: readString(args, "slRatio"),
|
|
3050
|
+
algoClOrdId: readString(args, "algoClOrdId"),
|
|
3028
3051
|
tag: context.config.sourceTag
|
|
3029
3052
|
});
|
|
3030
3053
|
if (algoOrdType === "contract_grid") {
|
|
3054
|
+
requireString(args, "direction");
|
|
3031
3055
|
body.triggerParams = [{ triggerAction: "start", triggerStrategy: "instant" }];
|
|
3032
3056
|
body.basePos = readBoolean(args, "basePos") ?? true;
|
|
3033
3057
|
}
|
|
@@ -3053,11 +3077,11 @@ function registerGridTools() {
|
|
|
3053
3077
|
enum: ["grid", "contract_grid"],
|
|
3054
3078
|
description: "grid=Spot, contract_grid=Contract"
|
|
3055
3079
|
},
|
|
3056
|
-
instId: { type: "string", description: "e.g. BTC-USDT" },
|
|
3080
|
+
instId: { type: "string", description: "e.g. BTC-USDT, BTC-USD-SWAP" },
|
|
3057
3081
|
stopType: {
|
|
3058
3082
|
type: "string",
|
|
3059
3083
|
enum: ["1", "2", "3", "5", "6"],
|
|
3060
|
-
description: "1=close all; 2=keep assets
|
|
3084
|
+
description: "1=close all (default); 2=keep assets; 3=limit close; 5=partial; 6=no sell"
|
|
3061
3085
|
}
|
|
3062
3086
|
},
|
|
3063
3087
|
required: ["algoId", "algoOrdType", "instId"]
|
|
@@ -3070,7 +3094,7 @@ function registerGridTools() {
|
|
|
3070
3094
|
algoId: requireString(args, "algoId"),
|
|
3071
3095
|
algoOrdType: requireString(args, "algoOrdType"),
|
|
3072
3096
|
instId: requireString(args, "instId"),
|
|
3073
|
-
stopType: readString(args, "stopType") ?? "
|
|
3097
|
+
stopType: readString(args, "stopType") ?? "1"
|
|
3074
3098
|
})],
|
|
3075
3099
|
privateRateLimit("grid_stop_order", 20)
|
|
3076
3100
|
);
|
|
@@ -3107,32 +3131,44 @@ function registerDcaTools() {
|
|
|
3107
3131
|
{
|
|
3108
3132
|
name: "dca_create_order",
|
|
3109
3133
|
module: "bot.dca",
|
|
3110
|
-
description: "Create
|
|
3134
|
+
description: "Create a DCA (Martingale) bot. [CAUTION] Real trades. contract_dca requires lever; spot_dca must be long. If maxSafetyOrds>0: need safetyOrdAmt, pxSteps.",
|
|
3111
3135
|
isWrite: true,
|
|
3112
3136
|
inputSchema: {
|
|
3113
3137
|
type: "object",
|
|
3114
3138
|
properties: {
|
|
3115
|
-
instId: { type: "string", description: "
|
|
3116
|
-
|
|
3139
|
+
instId: { type: "string", description: "BTC-USDT (spot) or BTC-USDT-SWAP (contract)" },
|
|
3140
|
+
algoOrdType: { type: "string", enum: ["spot_dca", "contract_dca"] },
|
|
3141
|
+
lever: { type: "string", description: "Required for contract_dca" },
|
|
3117
3142
|
direction: { type: "string", enum: ["long", "short"] },
|
|
3118
|
-
initOrdAmt: { type: "string", description: "Initial
|
|
3119
|
-
maxSafetyOrds: { type: "string", description: "
|
|
3120
|
-
tpPct: { type: "string", description: "Take-profit ratio,
|
|
3121
|
-
safetyOrdAmt: { type: "string", description: "Safety order amount
|
|
3122
|
-
pxSteps: { type: "string", description: "Price drop
|
|
3123
|
-
pxStepsMult: { type: "string", description: "
|
|
3124
|
-
volMult: { type: "string", description: "
|
|
3125
|
-
slPct: { type: "string", description: "Stop-loss ratio,
|
|
3126
|
-
slMode: { type: "string", enum: ["limit", "market"]
|
|
3127
|
-
allowReinvest: { type: "
|
|
3128
|
-
triggerStrategy: { type: "string", enum: ["instant", "price"
|
|
3129
|
-
triggerPx: { type: "string", description: "
|
|
3143
|
+
initOrdAmt: { type: "string", description: "Initial amount in quote ccy" },
|
|
3144
|
+
maxSafetyOrds: { type: "string", description: "0=no DCA, max 100" },
|
|
3145
|
+
tpPct: { type: "string", description: "Take-profit ratio, 0.03=3%" },
|
|
3146
|
+
safetyOrdAmt: { type: "string", description: "Safety order amount. Need if maxSafetyOrds>0" },
|
|
3147
|
+
pxSteps: { type: "string", description: "Price drop per safety order. Need if maxSafetyOrds>0" },
|
|
3148
|
+
pxStepsMult: { type: "string", description: "Step multiplier. Required when maxSafetyOrds>0, e.g. '1'" },
|
|
3149
|
+
volMult: { type: "string", description: "Size multiplier. Required when maxSafetyOrds>0, e.g. '1'" },
|
|
3150
|
+
slPct: { type: "string", description: "Stop-loss ratio, 0.05=5%" },
|
|
3151
|
+
slMode: { type: "string", enum: ["limit", "market"] },
|
|
3152
|
+
allowReinvest: { type: "boolean", description: "Default true" },
|
|
3153
|
+
triggerStrategy: { type: "string", enum: ["instant", "price"] },
|
|
3154
|
+
triggerPx: { type: "string", description: "Need if triggerStrategy=price" },
|
|
3155
|
+
algoClOrdId: { type: "string", description: "Client order ID, 1-32 chars" },
|
|
3156
|
+
// Backend expects boolean, but kept as string for backward compatibility with older clients.
|
|
3157
|
+
reserveFunds: { type: "string", description: "'true' or 'false', default 'true'" },
|
|
3158
|
+
tradeQuoteCcy: { type: "string" }
|
|
3130
3159
|
},
|
|
3131
|
-
required: ["instId", "
|
|
3160
|
+
required: ["instId", "algoOrdType", "direction", "initOrdAmt", "maxSafetyOrds", "tpPct"]
|
|
3132
3161
|
},
|
|
3133
3162
|
handler: async (rawArgs, context) => {
|
|
3134
3163
|
const args = asRecord(rawArgs);
|
|
3135
3164
|
const instId = requireString(args, "instId");
|
|
3165
|
+
const algoOrdType = requireString(args, "algoOrdType");
|
|
3166
|
+
if (algoOrdType === "contract_dca" && !readString(args, "lever")) {
|
|
3167
|
+
throw new OkxApiError("lever is required for contract_dca", {
|
|
3168
|
+
code: "VALIDATION",
|
|
3169
|
+
endpoint: `${BASE}/create`
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3136
3172
|
const triggerStrategy = readString(args, "triggerStrategy") ?? "instant";
|
|
3137
3173
|
const triggerParam = {
|
|
3138
3174
|
triggerAction: "start",
|
|
@@ -3141,24 +3177,55 @@ function registerDcaTools() {
|
|
|
3141
3177
|
if (triggerStrategy === "price") {
|
|
3142
3178
|
triggerParam["triggerPx"] = requireString(args, "triggerPx");
|
|
3143
3179
|
}
|
|
3180
|
+
const maxSafetyOrds = requireString(args, "maxSafetyOrds");
|
|
3181
|
+
if (Number(maxSafetyOrds) > 0) {
|
|
3182
|
+
if (!readString(args, "safetyOrdAmt")) {
|
|
3183
|
+
throw new OkxApiError("safetyOrdAmt is required when maxSafetyOrds > 0", {
|
|
3184
|
+
code: "VALIDATION",
|
|
3185
|
+
endpoint: `${BASE}/create`
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
if (!readString(args, "pxSteps")) {
|
|
3189
|
+
throw new OkxApiError("pxSteps is required when maxSafetyOrds > 0", {
|
|
3190
|
+
code: "VALIDATION",
|
|
3191
|
+
endpoint: `${BASE}/create`
|
|
3192
|
+
});
|
|
3193
|
+
}
|
|
3194
|
+
if (!readString(args, "pxStepsMult")) {
|
|
3195
|
+
throw new OkxApiError("pxStepsMult is required when maxSafetyOrds > 0", {
|
|
3196
|
+
code: "VALIDATION",
|
|
3197
|
+
endpoint: `${BASE}/create`
|
|
3198
|
+
});
|
|
3199
|
+
}
|
|
3200
|
+
if (!readString(args, "volMult")) {
|
|
3201
|
+
throw new OkxApiError("volMult is required when maxSafetyOrds > 0", {
|
|
3202
|
+
code: "VALIDATION",
|
|
3203
|
+
endpoint: `${BASE}/create`
|
|
3204
|
+
});
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3144
3207
|
const response = await context.client.privatePost(
|
|
3145
3208
|
`${BASE}/create`,
|
|
3146
3209
|
compactObject({
|
|
3147
3210
|
instId,
|
|
3148
|
-
algoOrdType
|
|
3149
|
-
lever:
|
|
3211
|
+
algoOrdType,
|
|
3212
|
+
lever: readString(args, "lever"),
|
|
3150
3213
|
direction: requireString(args, "direction"),
|
|
3151
3214
|
initOrdAmt: requireString(args, "initOrdAmt"),
|
|
3152
3215
|
safetyOrdAmt: readString(args, "safetyOrdAmt"),
|
|
3153
|
-
maxSafetyOrds
|
|
3216
|
+
maxSafetyOrds,
|
|
3154
3217
|
pxSteps: readString(args, "pxSteps"),
|
|
3155
3218
|
pxStepsMult: readString(args, "pxStepsMult"),
|
|
3156
3219
|
volMult: readString(args, "volMult"),
|
|
3157
3220
|
tpPct: requireString(args, "tpPct"),
|
|
3158
3221
|
slPct: readString(args, "slPct"),
|
|
3159
3222
|
slMode: readString(args, "slMode"),
|
|
3160
|
-
allowReinvest:
|
|
3161
|
-
triggerParams: [triggerParam]
|
|
3223
|
+
allowReinvest: args["allowReinvest"] !== void 0 ? args["allowReinvest"] === true || args["allowReinvest"] === "true" : void 0,
|
|
3224
|
+
triggerParams: [triggerParam],
|
|
3225
|
+
tag: context.config.sourceTag,
|
|
3226
|
+
algoClOrdId: readString(args, "algoClOrdId"),
|
|
3227
|
+
reserveFunds: readString(args, "reserveFunds"),
|
|
3228
|
+
tradeQuoteCcy: readString(args, "tradeQuoteCcy")
|
|
3162
3229
|
}),
|
|
3163
3230
|
privateRateLimit("dca_create_order", 20)
|
|
3164
3231
|
);
|
|
@@ -3168,21 +3235,31 @@ function registerDcaTools() {
|
|
|
3168
3235
|
{
|
|
3169
3236
|
name: "dca_stop_order",
|
|
3170
3237
|
module: "bot.dca",
|
|
3171
|
-
description: "Stop a running
|
|
3238
|
+
description: "Stop a running DCA bot. [CAUTION] spot_dca needs stopType: 1=sell, 2=keep.",
|
|
3172
3239
|
isWrite: true,
|
|
3173
3240
|
inputSchema: {
|
|
3174
3241
|
type: "object",
|
|
3175
3242
|
properties: {
|
|
3176
|
-
algoId: { type: "string", description: "
|
|
3243
|
+
algoId: { type: "string", description: "Algo order ID" },
|
|
3244
|
+
algoOrdType: { type: "string", enum: ["spot_dca", "contract_dca"] },
|
|
3245
|
+
stopType: { type: "string", enum: ["1", "2"], description: "Required for spot_dca: 1=sell all, 2=keep tokens" }
|
|
3177
3246
|
},
|
|
3178
|
-
required: ["algoId"]
|
|
3247
|
+
required: ["algoId", "algoOrdType"]
|
|
3179
3248
|
},
|
|
3180
3249
|
handler: async (rawArgs, context) => {
|
|
3181
3250
|
const args = asRecord(rawArgs);
|
|
3182
3251
|
const algoId = requireString(args, "algoId");
|
|
3252
|
+
const algoOrdType = requireString(args, "algoOrdType");
|
|
3253
|
+
const stopType = readString(args, "stopType");
|
|
3254
|
+
if (algoOrdType === "spot_dca" && !stopType) {
|
|
3255
|
+
throw new OkxApiError(
|
|
3256
|
+
"stopType is required for spot_dca. Use '1' (sell all tokens) or '2' (keep tokens)",
|
|
3257
|
+
{ code: "VALIDATION", endpoint: `${BASE}/stop` }
|
|
3258
|
+
);
|
|
3259
|
+
}
|
|
3183
3260
|
const response = await context.client.privatePost(
|
|
3184
3261
|
`${BASE}/stop`,
|
|
3185
|
-
{ algoId, algoOrdType
|
|
3262
|
+
compactObject({ algoId, algoOrdType, stopType }),
|
|
3186
3263
|
privateRateLimit("dca_stop_order", 20)
|
|
3187
3264
|
);
|
|
3188
3265
|
return normalizeWrite2(response);
|
|
@@ -3191,21 +3268,18 @@ function registerDcaTools() {
|
|
|
3191
3268
|
{
|
|
3192
3269
|
name: "dca_get_orders",
|
|
3193
3270
|
module: "bot.dca",
|
|
3194
|
-
description: "List DCA bots.
|
|
3271
|
+
description: "List DCA bots. Default: active (running). Use status=history for stopped.",
|
|
3195
3272
|
isWrite: false,
|
|
3196
3273
|
inputSchema: {
|
|
3197
3274
|
type: "object",
|
|
3198
3275
|
properties: {
|
|
3199
|
-
status: {
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
},
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
after: { type: "string", description: "Cursor for older records" },
|
|
3207
|
-
before: { type: "string", description: "Cursor for newer records" },
|
|
3208
|
-
limit: { type: "number", description: "Default 100" }
|
|
3276
|
+
status: { type: "string", enum: ["active", "history"] },
|
|
3277
|
+
algoOrdType: { type: "string", enum: ["spot_dca", "contract_dca"], description: "Default: contract_dca" },
|
|
3278
|
+
algoId: { type: "string", description: "Algo order ID" },
|
|
3279
|
+
instId: { type: "string" },
|
|
3280
|
+
after: { type: "string", description: "Pagination cursor" },
|
|
3281
|
+
before: { type: "string", description: "Pagination cursor" },
|
|
3282
|
+
limit: { type: "number" }
|
|
3209
3283
|
},
|
|
3210
3284
|
required: []
|
|
3211
3285
|
},
|
|
@@ -3213,10 +3287,11 @@ function registerDcaTools() {
|
|
|
3213
3287
|
const args = asRecord(rawArgs);
|
|
3214
3288
|
const status = readString(args, "status") ?? "active";
|
|
3215
3289
|
const path42 = status === "history" ? `${BASE}/history-list` : `${BASE}/ongoing-list`;
|
|
3290
|
+
const algoOrdType = readString(args, "algoOrdType") ?? "contract_dca";
|
|
3216
3291
|
const response = await context.client.privateGet(
|
|
3217
3292
|
path42,
|
|
3218
3293
|
compactObject({
|
|
3219
|
-
algoOrdType
|
|
3294
|
+
algoOrdType,
|
|
3220
3295
|
algoId: readString(args, "algoId"),
|
|
3221
3296
|
instId: readString(args, "instId"),
|
|
3222
3297
|
after: readString(args, "after"),
|
|
@@ -3231,21 +3306,23 @@ function registerDcaTools() {
|
|
|
3231
3306
|
{
|
|
3232
3307
|
name: "dca_get_order_details",
|
|
3233
3308
|
module: "bot.dca",
|
|
3234
|
-
description: "Get DCA bot
|
|
3309
|
+
description: "Get DCA bot position details (avgPx, upl, liqPx, etc).",
|
|
3235
3310
|
isWrite: false,
|
|
3236
3311
|
inputSchema: {
|
|
3237
3312
|
type: "object",
|
|
3238
3313
|
properties: {
|
|
3239
|
-
algoId: { type: "string", description: "
|
|
3314
|
+
algoId: { type: "string", description: "Algo order ID" },
|
|
3315
|
+
algoOrdType: { type: "string", enum: ["spot_dca", "contract_dca"] }
|
|
3240
3316
|
},
|
|
3241
|
-
required: ["algoId"]
|
|
3317
|
+
required: ["algoId", "algoOrdType"]
|
|
3242
3318
|
},
|
|
3243
3319
|
handler: async (rawArgs, context) => {
|
|
3244
3320
|
const args = asRecord(rawArgs);
|
|
3245
3321
|
const algoId = requireString(args, "algoId");
|
|
3322
|
+
const algoOrdType = requireString(args, "algoOrdType");
|
|
3246
3323
|
const response = await context.client.privateGet(
|
|
3247
3324
|
`${BASE}/position-details`,
|
|
3248
|
-
{ algoId, algoOrdType
|
|
3325
|
+
{ algoId, algoOrdType },
|
|
3249
3326
|
privateRateLimit("dca_get_order_details", 20)
|
|
3250
3327
|
);
|
|
3251
3328
|
return normalizeResponse(response);
|
|
@@ -3254,29 +3331,31 @@ function registerDcaTools() {
|
|
|
3254
3331
|
{
|
|
3255
3332
|
name: "dca_get_sub_orders",
|
|
3256
3333
|
module: "bot.dca",
|
|
3257
|
-
description: "
|
|
3334
|
+
description: "Get DCA cycles or orders in a cycle. Omit cycleId=cycle list; with cycleId=orders.",
|
|
3258
3335
|
isWrite: false,
|
|
3259
3336
|
inputSchema: {
|
|
3260
3337
|
type: "object",
|
|
3261
3338
|
properties: {
|
|
3262
|
-
algoId: { type: "string", description: "
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3339
|
+
algoId: { type: "string", description: "Algo order ID" },
|
|
3340
|
+
algoOrdType: { type: "string", enum: ["spot_dca", "contract_dca"] },
|
|
3341
|
+
cycleId: { type: "string", description: "Omit for cycles; provide for orders" },
|
|
3342
|
+
after: { type: "string", description: "Pagination cursor" },
|
|
3343
|
+
before: { type: "string", description: "Pagination cursor" },
|
|
3344
|
+
limit: { type: "number" }
|
|
3267
3345
|
},
|
|
3268
|
-
required: ["algoId"]
|
|
3346
|
+
required: ["algoId", "algoOrdType"]
|
|
3269
3347
|
},
|
|
3270
3348
|
handler: async (rawArgs, context) => {
|
|
3271
3349
|
const args = asRecord(rawArgs);
|
|
3272
3350
|
const algoId = requireString(args, "algoId");
|
|
3351
|
+
const algoOrdType = requireString(args, "algoOrdType");
|
|
3273
3352
|
const cycleId = readString(args, "cycleId");
|
|
3274
3353
|
if (cycleId) {
|
|
3275
3354
|
const response2 = await context.client.privateGet(
|
|
3276
3355
|
`${BASE}/orders`,
|
|
3277
3356
|
compactObject({
|
|
3278
3357
|
algoId,
|
|
3279
|
-
algoOrdType
|
|
3358
|
+
algoOrdType,
|
|
3280
3359
|
cycleId,
|
|
3281
3360
|
limit: readNumber(args, "limit")
|
|
3282
3361
|
}),
|
|
@@ -3288,7 +3367,7 @@ function registerDcaTools() {
|
|
|
3288
3367
|
`${BASE}/cycle-list`,
|
|
3289
3368
|
compactObject({
|
|
3290
3369
|
algoId,
|
|
3291
|
-
algoOrdType
|
|
3370
|
+
algoOrdType,
|
|
3292
3371
|
after: readString(args, "after"),
|
|
3293
3372
|
before: readString(args, "before"),
|
|
3294
3373
|
limit: readNumber(args, "limit")
|
|
@@ -3311,7 +3390,7 @@ function registerEarnTools() {
|
|
|
3311
3390
|
{
|
|
3312
3391
|
name: "earn_get_savings_balance",
|
|
3313
3392
|
module: "earn.savings",
|
|
3314
|
-
description: "Get Simple Earn (savings/flexible earn) balance. Returns current holdings
|
|
3393
|
+
description: "Get Simple Earn (savings/flexible earn) balance. Returns current holdings, lent amount, pending interest, and the user's set rate. Response fields: amt (total held), loanAmt (actively lent), pendingAmt (awaiting match), earnings (cumulative interest), rate (user's own minimum lending rate setting \u2014 NOT market yield, NOT APY). To get the actual market lending rate, call earn_get_lending_rate_history instead.",
|
|
3315
3394
|
isWrite: false,
|
|
3316
3395
|
inputSchema: {
|
|
3317
3396
|
type: "object",
|
|
@@ -3350,7 +3429,7 @@ function registerEarnTools() {
|
|
|
3350
3429
|
},
|
|
3351
3430
|
rate: {
|
|
3352
3431
|
type: "string",
|
|
3353
|
-
description: "
|
|
3432
|
+
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Defaults to 0.01. Keep at 0.01 to maximize matching probability \u2014 do NOT raise this to increase yield, as actual yield (lendingRate) is determined by market supply/demand, not this setting."
|
|
3354
3433
|
}
|
|
3355
3434
|
},
|
|
3356
3435
|
required: ["ccy", "amt"]
|
|
@@ -3419,7 +3498,7 @@ function registerEarnTools() {
|
|
|
3419
3498
|
},
|
|
3420
3499
|
rate: {
|
|
3421
3500
|
type: "string",
|
|
3422
|
-
description: "
|
|
3501
|
+
description: "Minimum lending rate threshold (annual, decimal). e.g. 0.01 = 1%. Only matched when market rate \u2265 this value. Keep at 0.01 to maximize matching probability \u2014 do NOT raise this to increase yield, as actual yield (lendingRate) is determined by market supply/demand, not this setting."
|
|
3423
3502
|
}
|
|
3424
3503
|
},
|
|
3425
3504
|
required: ["ccy", "rate"]
|
|
@@ -3441,7 +3520,7 @@ function registerEarnTools() {
|
|
|
3441
3520
|
{
|
|
3442
3521
|
name: "earn_get_lending_history",
|
|
3443
3522
|
module: "earn.savings",
|
|
3444
|
-
description: "Get
|
|
3523
|
+
description: "Get personal lending records for Simple Earn (your own lending history). NOT for market rate queries. Returns your lending records with amount, rate, and earnings data.",
|
|
3445
3524
|
isWrite: false,
|
|
3446
3525
|
inputSchema: {
|
|
3447
3526
|
type: "object",
|
|
@@ -3479,34 +3558,10 @@ function registerEarnTools() {
|
|
|
3479
3558
|
return normalizeResponse(response);
|
|
3480
3559
|
}
|
|
3481
3560
|
},
|
|
3482
|
-
{
|
|
3483
|
-
name: "earn_get_lending_rate_summary",
|
|
3484
|
-
module: "earn.savings",
|
|
3485
|
-
description: "Get coin lending market rate summary. NOT related to Simple Earn. Use this to query the lending/borrowing market rates (\u501F\u5E01\u5E02\u573A\u5229\u7387). Returns aggregate overview: average rate (avgRate), estimated next-cycle rate (estRate), previous-cycle rate (preRate), and available lending amounts.",
|
|
3486
|
-
isWrite: false,
|
|
3487
|
-
inputSchema: {
|
|
3488
|
-
type: "object",
|
|
3489
|
-
properties: {
|
|
3490
|
-
ccy: {
|
|
3491
|
-
type: "string",
|
|
3492
|
-
description: "e.g. USDT. Omit for all."
|
|
3493
|
-
}
|
|
3494
|
-
}
|
|
3495
|
-
},
|
|
3496
|
-
handler: async (rawArgs, context) => {
|
|
3497
|
-
const args = asRecord(rawArgs);
|
|
3498
|
-
const response = await context.client.publicGet(
|
|
3499
|
-
"/api/v5/finance/savings/lending-rate-summary",
|
|
3500
|
-
compactObject({ ccy: readString(args, "ccy") }),
|
|
3501
|
-
publicRateLimit("earn_get_lending_rate_summary", 6)
|
|
3502
|
-
);
|
|
3503
|
-
return normalizeResponse(response);
|
|
3504
|
-
}
|
|
3505
|
-
},
|
|
3506
3561
|
{
|
|
3507
3562
|
name: "earn_get_lending_rate_history",
|
|
3508
3563
|
module: "earn.savings",
|
|
3509
|
-
description: "Query Simple Earn lending rates. Use this tool when the user asks about current or historical lending rates for Simple Earn, or when displaying savings balance with market rate context (\
|
|
3564
|
+
description: "Query Simple Earn lending rates. Public endpoint (no API key required). Use this tool when the user asks about current or historical lending rates for Simple Earn, or when displaying savings balance with market rate context. Response fields per record: rate (market lending rate \u2014 the rate borrowers pay this period; user's minimum setting must be \u2264 this to be eligible), lendingRate (actual yield received by lenders; stablecoins e.g. USDT/USDC only: subject to pro-rata dilution \u2014 when eligible supply exceeds borrowing demand total interest is shared so lendingRate < rate; non-stablecoins: lendingRate = rate, no dilution; always use lendingRate as the true APY to show users), ts (settlement timestamp ms). To get current APY: use limit=1 and read lendingRate.",
|
|
3510
3565
|
isWrite: false,
|
|
3511
3566
|
inputSchema: {
|
|
3512
3567
|
type: "object",
|
|
@@ -3890,7 +3945,7 @@ function registerDcdTools() {
|
|
|
3890
3945
|
properties: {
|
|
3891
3946
|
baseCcy: { type: "string", description: "Base currency, e.g. BTC" },
|
|
3892
3947
|
quoteCcy: { type: "string", description: "Quote currency, e.g. USDT" },
|
|
3893
|
-
optType: { type: "string", description: "Option type: C (Call
|
|
3948
|
+
optType: { type: "string", description: "Option type: C (Call, sell high) or P (Put, buy low)" }
|
|
3894
3949
|
},
|
|
3895
3950
|
required: ["baseCcy", "quoteCcy", "optType"]
|
|
3896
3951
|
},
|
|
@@ -4129,11 +4184,53 @@ function registerDcdTools() {
|
|
|
4129
4184
|
}
|
|
4130
4185
|
];
|
|
4131
4186
|
}
|
|
4187
|
+
function registerAutoEarnTools() {
|
|
4188
|
+
return [
|
|
4189
|
+
{
|
|
4190
|
+
name: "earn_auto_set",
|
|
4191
|
+
module: "earn.autoearn",
|
|
4192
|
+
description: "Enable or disable auto-earn for a currency. earnType='0' for auto-lend+stake (most currencies); earnType='1' for USDG earn (USDG, BUIDL). Use account_get_balance first: if autoLendStatus or autoStakingStatus != 'unsupported', use earnType='0'; for USDG/BUIDL use earnType='1'. [CAUTION] Cannot disable within 24h of enabling.",
|
|
4193
|
+
isWrite: true,
|
|
4194
|
+
inputSchema: {
|
|
4195
|
+
type: "object",
|
|
4196
|
+
properties: {
|
|
4197
|
+
ccy: {
|
|
4198
|
+
type: "string",
|
|
4199
|
+
description: "Currency, e.g. SOL, USDG"
|
|
4200
|
+
},
|
|
4201
|
+
action: {
|
|
4202
|
+
type: "string",
|
|
4203
|
+
description: "turn_on or turn_off"
|
|
4204
|
+
},
|
|
4205
|
+
earnType: {
|
|
4206
|
+
type: "string",
|
|
4207
|
+
description: "0=auto-lend+stake (default), 1=USDG earn. Omit to use default."
|
|
4208
|
+
}
|
|
4209
|
+
},
|
|
4210
|
+
required: ["ccy", "action"]
|
|
4211
|
+
},
|
|
4212
|
+
handler: async (rawArgs, context) => {
|
|
4213
|
+
const args = asRecord(rawArgs);
|
|
4214
|
+
const response = await context.client.privatePost(
|
|
4215
|
+
"/api/v5/account/set-auto-earn",
|
|
4216
|
+
compactObject({
|
|
4217
|
+
ccy: requireString(args, "ccy"),
|
|
4218
|
+
action: requireString(args, "action"),
|
|
4219
|
+
earnType: readString(args, "earnType") ?? "0"
|
|
4220
|
+
}),
|
|
4221
|
+
privateRateLimit("earn_auto_set", 10)
|
|
4222
|
+
);
|
|
4223
|
+
return normalizeResponse(response);
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
];
|
|
4227
|
+
}
|
|
4132
4228
|
function registerAllEarnTools() {
|
|
4133
4229
|
return [
|
|
4134
4230
|
...registerEarnTools(),
|
|
4135
4231
|
...registerOnchainEarnTools(),
|
|
4136
|
-
...registerDcdTools()
|
|
4232
|
+
...registerDcdTools(),
|
|
4233
|
+
...registerAutoEarnTools()
|
|
4137
4234
|
];
|
|
4138
4235
|
}
|
|
4139
4236
|
function buildContractTradeTools(cfg) {
|
|
@@ -5247,6 +5344,11 @@ function registerOptionAlgoTools() {
|
|
|
5247
5344
|
type: "string",
|
|
5248
5345
|
enum: ["last", "index", "mark"]
|
|
5249
5346
|
},
|
|
5347
|
+
tgtCcy: {
|
|
5348
|
+
type: "string",
|
|
5349
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
5350
|
+
description: "Size unit. base_ccy(default): sz in contracts, quote_ccy: sz in USDT (may not be supported for options)"
|
|
5351
|
+
},
|
|
5250
5352
|
reduceOnly: {
|
|
5251
5353
|
type: "boolean",
|
|
5252
5354
|
description: "Ensure order only reduces position"
|
|
@@ -5269,6 +5371,7 @@ function registerOptionAlgoTools() {
|
|
|
5269
5371
|
side: requireString(args, "side"),
|
|
5270
5372
|
ordType: requireString(args, "ordType"),
|
|
5271
5373
|
sz: requireString(args, "sz"),
|
|
5374
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
5272
5375
|
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
5273
5376
|
tpOrdPx: readString(args, "tpOrdPx"),
|
|
5274
5377
|
tpTriggerPxType: readString(args, "tpTriggerPxType"),
|
|
@@ -6116,6 +6219,11 @@ function registerSpotTradeTools() {
|
|
|
6116
6219
|
type: "string",
|
|
6117
6220
|
description: "SL order price, -1=market (conditional/oco only)"
|
|
6118
6221
|
},
|
|
6222
|
+
tgtCcy: {
|
|
6223
|
+
type: "string",
|
|
6224
|
+
enum: ["base_ccy", "quote_ccy"],
|
|
6225
|
+
description: "Size unit. base_ccy(default): sz in base (e.g. BTC), quote_ccy: sz in quote (e.g. USDT)"
|
|
6226
|
+
},
|
|
6119
6227
|
callbackRatio: {
|
|
6120
6228
|
type: "string",
|
|
6121
6229
|
description: "Callback ratio e.g. 0.01=1%, use ratio or spread (move_order_stop only)"
|
|
@@ -6141,6 +6249,7 @@ function registerSpotTradeTools() {
|
|
|
6141
6249
|
side: requireString(args, "side"),
|
|
6142
6250
|
ordType: requireString(args, "ordType"),
|
|
6143
6251
|
sz: requireString(args, "sz"),
|
|
6252
|
+
tgtCcy: readString(args, "tgtCcy"),
|
|
6144
6253
|
tpTriggerPx: readString(args, "tpTriggerPx"),
|
|
6145
6254
|
tpOrdPx: readString(args, "tpOrdPx"),
|
|
6146
6255
|
slTriggerPx: readString(args, "slTriggerPx"),
|
|
@@ -7142,6 +7251,12 @@ function fail(label, detail, hints) {
|
|
|
7142
7251
|
outputLine(` \u2192 ${hint}`);
|
|
7143
7252
|
}
|
|
7144
7253
|
}
|
|
7254
|
+
function warn(label, detail, hints = []) {
|
|
7255
|
+
outputLine(` \u26A0 ${label.padEnd(14)} ${detail}`);
|
|
7256
|
+
for (const hint of hints) {
|
|
7257
|
+
outputLine(` \u2192 ${hint}`);
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7145
7260
|
function section(title) {
|
|
7146
7261
|
outputLine("");
|
|
7147
7262
|
outputLine(` ${title}`);
|
|
@@ -7252,59 +7367,154 @@ function checkMcpEntryPoint(report) {
|
|
|
7252
7367
|
return { entryPath: null, passed: false };
|
|
7253
7368
|
}
|
|
7254
7369
|
}
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
return true;
|
|
7262
|
-
}
|
|
7263
|
-
if (!fs4.existsSync(configPath)) {
|
|
7264
|
-
fail("config file", `not found: ${configPath}`, [
|
|
7265
|
-
"Claude Desktop may not be installed",
|
|
7266
|
-
"Run: okx setup --client claude-desktop to configure"
|
|
7267
|
-
]);
|
|
7268
|
-
report.add("claude_cfg", `MISSING ${sanitize(configPath)}`);
|
|
7269
|
-
return false;
|
|
7270
|
-
}
|
|
7271
|
-
ok("config file", configPath);
|
|
7272
|
-
report.add("claude_cfg", sanitize(configPath));
|
|
7370
|
+
var MCP_SERVER_NAME = "okx-trade-mcp";
|
|
7371
|
+
var CLIENT_LIMITS = {
|
|
7372
|
+
cursor: { perServer: 40, total: 80 }
|
|
7373
|
+
};
|
|
7374
|
+
function checkJsonMcpConfig(configPath) {
|
|
7375
|
+
if (!fs4.existsSync(configPath)) return "missing";
|
|
7273
7376
|
try {
|
|
7274
7377
|
const raw = fs4.readFileSync(configPath, "utf8");
|
|
7275
7378
|
const parsed = JSON.parse(raw);
|
|
7276
7379
|
const mcpServers = parsed["mcpServers"];
|
|
7277
|
-
if (!mcpServers)
|
|
7278
|
-
fail("mcp entry", "no mcpServers section found", [
|
|
7279
|
-
"Run: okx setup --client claude-desktop"
|
|
7280
|
-
]);
|
|
7281
|
-
report.add("claude_mcp", "NO_SECTION");
|
|
7282
|
-
return false;
|
|
7283
|
-
}
|
|
7380
|
+
if (!mcpServers) return "not-configured";
|
|
7284
7381
|
const entries = Object.entries(mcpServers);
|
|
7285
|
-
const
|
|
7382
|
+
const found = entries.find(([name, v]) => {
|
|
7383
|
+
if (name.includes(MCP_SERVER_NAME)) return true;
|
|
7286
7384
|
const val = v;
|
|
7287
7385
|
const cmd = String(val["command"] ?? "");
|
|
7288
7386
|
const args = val["args"] ?? [];
|
|
7289
|
-
return cmd.includes(
|
|
7387
|
+
return cmd.includes(MCP_SERVER_NAME) || args.some((a) => a.includes(MCP_SERVER_NAME));
|
|
7290
7388
|
});
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7389
|
+
return found ? "found" : "not-configured";
|
|
7390
|
+
} catch (_e) {
|
|
7391
|
+
return "parse-error";
|
|
7392
|
+
}
|
|
7393
|
+
}
|
|
7394
|
+
function checkClaudeCodeConfig() {
|
|
7395
|
+
const home = os2.homedir();
|
|
7396
|
+
const candidates = [
|
|
7397
|
+
path2.join(home, ".claude", "settings.json"),
|
|
7398
|
+
path2.join(home, ".claude.json")
|
|
7399
|
+
];
|
|
7400
|
+
let anyFound = false;
|
|
7401
|
+
let anyParseError = false;
|
|
7402
|
+
for (const cfgPath of candidates) {
|
|
7403
|
+
if (!fs4.existsSync(cfgPath)) continue;
|
|
7404
|
+
anyFound = true;
|
|
7405
|
+
const result = checkJsonMcpConfig(cfgPath);
|
|
7406
|
+
if (result === "found") return "found";
|
|
7407
|
+
if (result === "parse-error") anyParseError = true;
|
|
7408
|
+
}
|
|
7409
|
+
if (!anyFound) return "missing";
|
|
7410
|
+
if (anyParseError) return "parse-error";
|
|
7411
|
+
return "not-configured";
|
|
7412
|
+
}
|
|
7413
|
+
function checkMcpClients(report) {
|
|
7414
|
+
section("MCP Client Config");
|
|
7415
|
+
const jsonClients = ["claude-desktop", "cursor", "windsurf"];
|
|
7416
|
+
const configuredClients = [];
|
|
7417
|
+
let anyFailed = false;
|
|
7418
|
+
for (const clientId of jsonClients) {
|
|
7419
|
+
const configPath = getConfigPath(clientId);
|
|
7420
|
+
if (!configPath) continue;
|
|
7421
|
+
const name = CLIENT_NAMES[clientId];
|
|
7422
|
+
const status = checkJsonMcpConfig(configPath);
|
|
7423
|
+
if (status === "missing") {
|
|
7424
|
+
continue;
|
|
7425
|
+
}
|
|
7426
|
+
if (status === "found") {
|
|
7427
|
+
ok(name, `configured (${sanitize(configPath)})`);
|
|
7428
|
+
report.add(`client_${clientId}`, `OK ${sanitize(configPath)}`);
|
|
7429
|
+
configuredClients.push(clientId);
|
|
7430
|
+
} else if (status === "not-configured") {
|
|
7431
|
+
fail(name, "okx-trade-mcp not found in mcpServers", [
|
|
7432
|
+
`Run: okx setup --client ${clientId}`
|
|
7433
|
+
]);
|
|
7434
|
+
report.add(`client_${clientId}`, "NOT_CONFIGURED");
|
|
7435
|
+
anyFailed = true;
|
|
7295
7436
|
} else {
|
|
7296
|
-
fail(
|
|
7297
|
-
|
|
7437
|
+
fail(name, `JSON parse error in ${sanitize(configPath)}`, [
|
|
7438
|
+
`Check ${sanitize(configPath)} for JSON syntax errors`,
|
|
7439
|
+
`Then run: okx setup --client ${clientId}`
|
|
7298
7440
|
]);
|
|
7299
|
-
report.add(
|
|
7300
|
-
|
|
7441
|
+
report.add(`client_${clientId}`, "PARSE_ERROR");
|
|
7442
|
+
anyFailed = true;
|
|
7301
7443
|
}
|
|
7302
|
-
}
|
|
7303
|
-
|
|
7304
|
-
|
|
7444
|
+
}
|
|
7445
|
+
const claudeCodeStatus = checkClaudeCodeConfig();
|
|
7446
|
+
if (claudeCodeStatus !== "missing") {
|
|
7447
|
+
const name = CLIENT_NAMES["claude-code"];
|
|
7448
|
+
if (claudeCodeStatus === "found") {
|
|
7449
|
+
ok(name, "configured");
|
|
7450
|
+
report.add("client_claude-code", "OK");
|
|
7451
|
+
configuredClients.push("claude-code");
|
|
7452
|
+
} else if (claudeCodeStatus === "not-configured") {
|
|
7453
|
+
warn(name, "installed but okx-trade-mcp not configured", [
|
|
7454
|
+
"Run: okx setup --client claude-code"
|
|
7455
|
+
]);
|
|
7456
|
+
report.add("client_claude-code", "NOT_CONFIGURED");
|
|
7457
|
+
} else {
|
|
7458
|
+
fail(name, "settings file has JSON parse error", [
|
|
7459
|
+
"Run: okx setup --client claude-code"
|
|
7460
|
+
]);
|
|
7461
|
+
report.add("client_claude-code", "PARSE_ERROR");
|
|
7462
|
+
anyFailed = true;
|
|
7463
|
+
}
|
|
7464
|
+
}
|
|
7465
|
+
if (configuredClients.length === 0 && !anyFailed) {
|
|
7466
|
+
fail("no client", "no MCP client configuration found", [
|
|
7467
|
+
"Run: okx setup --client <client>",
|
|
7468
|
+
"Supported clients: claude-desktop, cursor, windsurf, claude-code"
|
|
7305
7469
|
]);
|
|
7306
|
-
report.add("
|
|
7307
|
-
return false;
|
|
7470
|
+
report.add("client_cfg", "NONE_FOUND");
|
|
7471
|
+
return { passed: false, configuredClients };
|
|
7472
|
+
}
|
|
7473
|
+
const passed = configuredClients.length > 0 && !anyFailed;
|
|
7474
|
+
report.add("client_cfg", passed ? `OK (${configuredClients.join(",")})` : "FAIL");
|
|
7475
|
+
return { passed, configuredClients };
|
|
7476
|
+
}
|
|
7477
|
+
function checkToolCount(report, configuredClients, getSpecs = allToolSpecs) {
|
|
7478
|
+
section("Tool Count");
|
|
7479
|
+
const specs = getSpecs();
|
|
7480
|
+
const totalCount = specs.length;
|
|
7481
|
+
const defaultModuleSet = new Set(DEFAULT_MODULES);
|
|
7482
|
+
const defaultCount = specs.filter((s) => defaultModuleSet.has(s.module)).length;
|
|
7483
|
+
const defaultModulesArg = DEFAULT_MODULES.join(",");
|
|
7484
|
+
const applicableLimits = configuredClients.map((id) => ({ id, limits: CLIENT_LIMITS[id] })).filter((x) => x.limits !== void 0);
|
|
7485
|
+
if (applicableLimits.length === 0) {
|
|
7486
|
+
ok("total tools", `${totalCount} tools loaded`);
|
|
7487
|
+
report.add("tool_count", `${totalCount}`);
|
|
7488
|
+
return;
|
|
7489
|
+
}
|
|
7490
|
+
let anyExceeded = false;
|
|
7491
|
+
for (const { id, limits } of applicableLimits) {
|
|
7492
|
+
const name = CLIENT_NAMES[id];
|
|
7493
|
+
if (totalCount > limits.total) {
|
|
7494
|
+
warn(
|
|
7495
|
+
"tool count",
|
|
7496
|
+
`${totalCount} tools loaded \u2014 exceeds ${name} limit (${limits.total} total / ${limits.perServer} per server)`,
|
|
7497
|
+
[
|
|
7498
|
+
`Use --modules to reduce: okx-trade-mcp --modules ${defaultModulesArg} (${defaultCount} tools)`
|
|
7499
|
+
]
|
|
7500
|
+
);
|
|
7501
|
+
report.add("tool_count", `${totalCount} EXCEEDS_${id.toUpperCase()}_LIMIT`);
|
|
7502
|
+
anyExceeded = true;
|
|
7503
|
+
} else if (totalCount > limits.perServer) {
|
|
7504
|
+
warn(
|
|
7505
|
+
"tool count",
|
|
7506
|
+
`${totalCount} tools loaded \u2014 exceeds ${name} per-server limit (${limits.perServer})`,
|
|
7507
|
+
[
|
|
7508
|
+
`Use --modules to reduce: okx-trade-mcp --modules ${defaultModulesArg} (${defaultCount} tools)`
|
|
7509
|
+
]
|
|
7510
|
+
);
|
|
7511
|
+
report.add("tool_count", `${totalCount} EXCEEDS_${id.toUpperCase()}_PER_SERVER_LIMIT`);
|
|
7512
|
+
anyExceeded = true;
|
|
7513
|
+
}
|
|
7514
|
+
}
|
|
7515
|
+
if (!anyExceeded) {
|
|
7516
|
+
ok("total tools", `${totalCount} tools loaded (within limits for all configured clients)`);
|
|
7517
|
+
report.add("tool_count", `${totalCount} OK`);
|
|
7308
7518
|
}
|
|
7309
7519
|
}
|
|
7310
7520
|
function readLogTail(logPath) {
|
|
@@ -7497,9 +7707,10 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7497
7707
|
checkMcpPackageVersion(report);
|
|
7498
7708
|
const nodePassed = checkNodeCompat(report);
|
|
7499
7709
|
const { entryPath, passed: entryPassed } = checkMcpEntryPoint(report);
|
|
7500
|
-
const cfgPassed =
|
|
7710
|
+
const { passed: cfgPassed, configuredClients } = checkMcpClients(report);
|
|
7501
7711
|
checkMcpLogs(report);
|
|
7502
7712
|
const moduleLoadPassed = checkModuleLoading(entryPath, report);
|
|
7713
|
+
checkToolCount(report, configuredClients);
|
|
7503
7714
|
let handshakePassed = false;
|
|
7504
7715
|
if (entryPath && entryPassed && moduleLoadPassed) {
|
|
7505
7716
|
handshakePassed = await checkStdioHandshake(entryPath, report);
|
|
@@ -7524,7 +7735,7 @@ async function cmdDiagnoseMcp(options = {}) {
|
|
|
7524
7735
|
|
|
7525
7736
|
// src/commands/diagnose.ts
|
|
7526
7737
|
var CLI_VERSION = readCliVersion();
|
|
7527
|
-
var GIT_HASH = true ? "
|
|
7738
|
+
var GIT_HASH = true ? "c270a0b" : "dev";
|
|
7528
7739
|
function maskKey2(key) {
|
|
7529
7740
|
if (!key) return "(not set)";
|
|
7530
7741
|
if (key.length <= 8) return "****";
|
|
@@ -8253,11 +8464,7 @@ var HELP_TREE = {
|
|
|
8253
8464
|
},
|
|
8254
8465
|
"lending-history": {
|
|
8255
8466
|
usage: "okx earn savings lending-history [--ccy <ccy>] [--limit <n>]",
|
|
8256
|
-
description: "Get
|
|
8257
|
-
},
|
|
8258
|
-
"rate-summary": {
|
|
8259
|
-
usage: "okx earn savings rate-summary [<ccy>]",
|
|
8260
|
-
description: "Get coin lending market rate summary (not Simple Earn, public)"
|
|
8467
|
+
description: "Get personal lending records (requires auth)"
|
|
8261
8468
|
},
|
|
8262
8469
|
"rate-history": {
|
|
8263
8470
|
usage: "okx earn savings rate-history [--ccy <ccy>] [--limit <n>]",
|
|
@@ -8294,6 +8501,23 @@ var HELP_TREE = {
|
|
|
8294
8501
|
}
|
|
8295
8502
|
}
|
|
8296
8503
|
},
|
|
8504
|
+
"auto-earn": {
|
|
8505
|
+
description: "Auto-earn \u2014 automatically lend, stake, or earn on idle assets",
|
|
8506
|
+
commands: {
|
|
8507
|
+
status: {
|
|
8508
|
+
usage: "okx earn auto-earn status [<ccy>]",
|
|
8509
|
+
description: "Query auto-earn status for all or a specific currency"
|
|
8510
|
+
},
|
|
8511
|
+
on: {
|
|
8512
|
+
usage: "okx earn auto-earn on <ccy>",
|
|
8513
|
+
description: "Enable auto-earn for a currency (auto-detects lend/stake vs USDG earn)"
|
|
8514
|
+
},
|
|
8515
|
+
off: {
|
|
8516
|
+
usage: "okx earn auto-earn off <ccy>",
|
|
8517
|
+
description: "Disable auto-earn for a currency"
|
|
8518
|
+
}
|
|
8519
|
+
}
|
|
8520
|
+
},
|
|
8297
8521
|
dcd: {
|
|
8298
8522
|
description: "DCD (Dual Currency Deposit) \u2014 structured products with fixed yield",
|
|
8299
8523
|
commands: {
|
|
@@ -8344,7 +8568,7 @@ var HELP_TREE = {
|
|
|
8344
8568
|
description: "List sub-orders of a grid bot (filled or live)"
|
|
8345
8569
|
},
|
|
8346
8570
|
create: {
|
|
8347
|
-
usage: "okx bot grid create --instId <id> --algoOrdType <grid|contract_grid> --maxPx <px> --minPx <px> --gridNum <n>\n [--runType <1|2>] [--quoteSz <n>] [--baseSz <n>]\n [--direction <long|short|neutral>] [--lever <n>] [--sz <n>] [--basePos] [--no-basePos]",
|
|
8571
|
+
usage: "okx bot grid create --instId <id> --algoOrdType <grid|contract_grid> --maxPx <px> --minPx <px> --gridNum <n>\n [--runType <1|2>] [--quoteSz <n>] [--baseSz <n>]\n [--direction <long|short|neutral>] [--lever <n>] [--sz <n>] [--basePos] [--no-basePos]\n [--tpTriggerPx <px>] [--slTriggerPx <px>] [--tpRatio <n>] [--slRatio <n>] [--algoClOrdId <id>]",
|
|
8348
8572
|
description: "Create a new grid bot order (contract grid opens base position by default)"
|
|
8349
8573
|
},
|
|
8350
8574
|
stop: {
|
|
@@ -8354,27 +8578,27 @@ var HELP_TREE = {
|
|
|
8354
8578
|
}
|
|
8355
8579
|
},
|
|
8356
8580
|
dca: {
|
|
8357
|
-
description: "
|
|
8581
|
+
description: "DCA (Martingale) bot \u2014 spot or contract recurring buys",
|
|
8358
8582
|
commands: {
|
|
8359
8583
|
orders: {
|
|
8360
|
-
usage: "okx bot dca orders [--algoId <id>] [--instId <id>] [--history]",
|
|
8361
|
-
description: "List
|
|
8584
|
+
usage: "okx bot dca orders [--algoOrdType <spot_dca|contract_dca>] [--algoId <id>] [--instId <id>] [--history]",
|
|
8585
|
+
description: "List DCA bots (spot and/or contract)"
|
|
8362
8586
|
},
|
|
8363
8587
|
details: {
|
|
8364
|
-
usage: "okx bot dca details --algoId <id>",
|
|
8365
|
-
description: "Get
|
|
8588
|
+
usage: "okx bot dca details --algoOrdType <spot_dca|contract_dca> --algoId <id>",
|
|
8589
|
+
description: "Get DCA bot details (spot or contract)"
|
|
8366
8590
|
},
|
|
8367
8591
|
"sub-orders": {
|
|
8368
|
-
usage: "okx bot dca sub-orders --algoId <id> [--cycleId <id>]",
|
|
8369
|
-
description: "
|
|
8592
|
+
usage: "okx bot dca sub-orders --algoOrdType <spot_dca|contract_dca> --algoId <id> [--cycleId <id>]",
|
|
8593
|
+
description: "Get DCA cycles/orders (spot or contract)"
|
|
8370
8594
|
},
|
|
8371
8595
|
create: {
|
|
8372
|
-
usage: "okx bot dca create --
|
|
8373
|
-
description: "Create a
|
|
8596
|
+
usage: "okx bot dca create --algoOrdType <spot_dca|contract_dca> --instId <id> --direction <long|short>\n --initOrdAmt <n> --maxSafetyOrds <n> --tpPct <n>\n [--lever <n>] [--safetyOrdAmt <n>] [--pxSteps <n>] [--pxStepsMult <n>] [--volMult <n>]\n [--slPct <n>] [--slMode <limit|market>] [--allowReinvest <true|false>]\n [--triggerStrategy <instant|price|rsi>] [--triggerPx <price>]\n [--algoClOrdId <id>] [--reserveFunds <true|false>] [--tradeQuoteCcy <ccy>]\n Note: --lever required for contract_dca; safetyOrdAmt, pxSteps, pxStepsMult, volMult required when maxSafetyOrds > 0",
|
|
8597
|
+
description: "Create a DCA (Martingale) bot (spot or contract)"
|
|
8374
8598
|
},
|
|
8375
8599
|
stop: {
|
|
8376
|
-
usage: "okx bot dca stop --algoId <id>",
|
|
8377
|
-
description: "Stop a
|
|
8600
|
+
usage: "okx bot dca stop --algoOrdType <spot_dca|contract_dca> --algoId <id> [--stopType <1|2>]\n Note: --stopType required for spot_dca (1=sell all, 2=keep tokens)",
|
|
8601
|
+
description: "Stop a DCA bot (spot or contract)"
|
|
8378
8602
|
}
|
|
8379
8603
|
}
|
|
8380
8604
|
}
|
|
@@ -8588,6 +8812,9 @@ var CLI_OPTIONS = {
|
|
|
8588
8812
|
baseSz: { type: "string" },
|
|
8589
8813
|
direction: { type: "string" },
|
|
8590
8814
|
basePos: { type: "boolean", default: true },
|
|
8815
|
+
tpRatio: { type: "string" },
|
|
8816
|
+
slRatio: { type: "string" },
|
|
8817
|
+
algoClOrdId: { type: "string" },
|
|
8591
8818
|
stopType: { type: "string" },
|
|
8592
8819
|
live: { type: "boolean", default: false },
|
|
8593
8820
|
// market extras
|
|
@@ -8606,7 +8833,7 @@ var CLI_OPTIONS = {
|
|
|
8606
8833
|
autoCxl: { type: "boolean", default: false },
|
|
8607
8834
|
clOrdId: { type: "string" },
|
|
8608
8835
|
newPx: { type: "string" },
|
|
8609
|
-
// dca bot (contract
|
|
8836
|
+
// dca bot (spot & contract)
|
|
8610
8837
|
initOrdAmt: { type: "string" },
|
|
8611
8838
|
safetyOrdAmt: { type: "string" },
|
|
8612
8839
|
maxSafetyOrds: { type: "string" },
|
|
@@ -8620,6 +8847,8 @@ var CLI_OPTIONS = {
|
|
|
8620
8847
|
triggerStrategy: { type: "string" },
|
|
8621
8848
|
triggerPx: { type: "string" },
|
|
8622
8849
|
cycleId: { type: "string" },
|
|
8850
|
+
reserveFunds: { type: "string" },
|
|
8851
|
+
tradeQuoteCcy: { type: "string" },
|
|
8623
8852
|
// i18n
|
|
8624
8853
|
lang: { type: "string" },
|
|
8625
8854
|
// option
|
|
@@ -8839,10 +9068,15 @@ async function cmdMarketTicker(run, instId, json) {
|
|
|
8839
9068
|
printKv({
|
|
8840
9069
|
instId: t["instId"],
|
|
8841
9070
|
last: t["last"],
|
|
8842
|
-
"24h
|
|
9071
|
+
"24h open": t["open24h"],
|
|
8843
9072
|
"24h high": t["high24h"],
|
|
8844
9073
|
"24h low": t["low24h"],
|
|
8845
9074
|
"24h vol": t["vol24h"],
|
|
9075
|
+
"24h change %": (() => {
|
|
9076
|
+
const last = Number(t["last"]);
|
|
9077
|
+
const open24h = Number(t["open24h"]);
|
|
9078
|
+
return open24h !== 0 ? ((last - open24h) / open24h * 100).toFixed(2) + "%" : "N/A";
|
|
9079
|
+
})(),
|
|
8846
9080
|
time: new Date(Number(t["ts"])).toLocaleString()
|
|
8847
9081
|
});
|
|
8848
9082
|
}
|
|
@@ -9263,6 +9497,7 @@ async function cmdSpotAlgoPlace(run, opts) {
|
|
|
9263
9497
|
side: opts.side,
|
|
9264
9498
|
ordType: opts.ordType,
|
|
9265
9499
|
sz: opts.sz,
|
|
9500
|
+
tgtCcy: opts.tgtCcy,
|
|
9266
9501
|
tpTriggerPx: opts.tpTriggerPx,
|
|
9267
9502
|
tpOrdPx: opts.tpOrdPx,
|
|
9268
9503
|
slTriggerPx: opts.slTriggerPx,
|
|
@@ -9510,6 +9745,7 @@ async function cmdSwapAlgoPlace(run, opts) {
|
|
|
9510
9745
|
side: opts.side,
|
|
9511
9746
|
ordType: opts.ordType,
|
|
9512
9747
|
sz: opts.sz,
|
|
9748
|
+
tgtCcy: opts.tgtCcy,
|
|
9513
9749
|
posSide: opts.posSide,
|
|
9514
9750
|
tpTriggerPx: opts.tpTriggerPx,
|
|
9515
9751
|
tpOrdPx: opts.tpOrdPx,
|
|
@@ -9915,6 +10151,7 @@ async function cmdFuturesAlgoPlace(run, opts) {
|
|
|
9915
10151
|
side: opts.side,
|
|
9916
10152
|
ordType: opts.ordType,
|
|
9917
10153
|
sz: opts.sz,
|
|
10154
|
+
tgtCcy: opts.tgtCcy,
|
|
9918
10155
|
posSide: opts.posSide,
|
|
9919
10156
|
tpTriggerPx: opts.tpTriggerPx,
|
|
9920
10157
|
tpOrdPx: opts.tpOrdPx,
|
|
@@ -10209,6 +10446,7 @@ async function cmdOptionAlgoPlace(run, opts) {
|
|
|
10209
10446
|
side: opts.side,
|
|
10210
10447
|
ordType: opts.ordType,
|
|
10211
10448
|
sz: opts.sz,
|
|
10449
|
+
tgtCcy: opts.tgtCcy,
|
|
10212
10450
|
tpTriggerPx: opts.tpTriggerPx,
|
|
10213
10451
|
tpOrdPx: opts.tpOrdPx,
|
|
10214
10452
|
slTriggerPx: opts.slTriggerPx,
|
|
@@ -10648,15 +10886,6 @@ async function cmdEarnLendingHistory(run, opts) {
|
|
|
10648
10886
|
ts: new Date(Number(r["ts"])).toLocaleString()
|
|
10649
10887
|
}));
|
|
10650
10888
|
}
|
|
10651
|
-
async function cmdEarnLendingRateSummary(run, ccy, json) {
|
|
10652
|
-
const data = extractData(await run("earn_get_lending_rate_summary", { ccy }));
|
|
10653
|
-
printDataList(data, json, "No rate summary data", (r) => ({
|
|
10654
|
-
ccy: r["ccy"],
|
|
10655
|
-
avgRate: r["avgRate"],
|
|
10656
|
-
estRate: r["estRate"],
|
|
10657
|
-
avgAmt: r["avgAmt"]
|
|
10658
|
-
}));
|
|
10659
|
-
}
|
|
10660
10889
|
async function cmdEarnLendingRateHistory(run, opts) {
|
|
10661
10890
|
const data = extractData(await run("earn_get_lending_rate_history", { ccy: opts.ccy, limit: opts.limit }));
|
|
10662
10891
|
printDataList(data, opts.json, "No rate history data", (r) => ({
|
|
@@ -10667,6 +10896,92 @@ async function cmdEarnLendingRateHistory(run, opts) {
|
|
|
10667
10896
|
}));
|
|
10668
10897
|
}
|
|
10669
10898
|
|
|
10899
|
+
// src/commands/auto-earn.ts
|
|
10900
|
+
var USDG_EARN_CURRENCIES = /* @__PURE__ */ new Set(["USDG", "BUIDL"]);
|
|
10901
|
+
function isSupported(status) {
|
|
10902
|
+
return !!status && status !== "unsupported";
|
|
10903
|
+
}
|
|
10904
|
+
function inferEarnType(detail) {
|
|
10905
|
+
if (isSupported(detail.autoLendStatus) || isSupported(detail.autoStakingStatus)) return "0";
|
|
10906
|
+
if (USDG_EARN_CURRENCIES.has(detail.ccy)) return "1";
|
|
10907
|
+
return null;
|
|
10908
|
+
}
|
|
10909
|
+
async function getBalanceDetails(run, ccy) {
|
|
10910
|
+
const result = await run("account_get_balance", ccy ? { ccy } : {});
|
|
10911
|
+
const data = result.data;
|
|
10912
|
+
const first = data?.[0];
|
|
10913
|
+
return first?.details ?? [];
|
|
10914
|
+
}
|
|
10915
|
+
function earnTypeLabel(et) {
|
|
10916
|
+
return et === "1" ? "USDG earn" : "lend+stake";
|
|
10917
|
+
}
|
|
10918
|
+
async function cmdAutoEarnStatus(run, ccy, json) {
|
|
10919
|
+
const details = await getBalanceDetails(run, ccy);
|
|
10920
|
+
const relevant = details.filter((d) => inferEarnType(d) !== null);
|
|
10921
|
+
if (json) {
|
|
10922
|
+
printJson(relevant);
|
|
10923
|
+
return;
|
|
10924
|
+
}
|
|
10925
|
+
if (!relevant.length) {
|
|
10926
|
+
outputLine(ccy ? `${ccy} does not support auto-earn` : "No currencies support auto-earn");
|
|
10927
|
+
return;
|
|
10928
|
+
}
|
|
10929
|
+
printTable(relevant.map((d) => {
|
|
10930
|
+
const et = inferEarnType(d);
|
|
10931
|
+
return {
|
|
10932
|
+
ccy: d.ccy,
|
|
10933
|
+
earnType: earnTypeLabel(et),
|
|
10934
|
+
autoLend: d.autoLendStatus,
|
|
10935
|
+
autoStaking: d.autoStakingStatus,
|
|
10936
|
+
invested: et === "1" ? d.eq || "-" : d.autoLendAmt || "-",
|
|
10937
|
+
matched: d.autoLendMtAmt || "-",
|
|
10938
|
+
apr: d.autoLendApr ? `${(Number(d.autoLendApr) * 100).toFixed(2)}%` : "-"
|
|
10939
|
+
};
|
|
10940
|
+
}));
|
|
10941
|
+
}
|
|
10942
|
+
async function cmdAutoEarnOn(run, ccy, json) {
|
|
10943
|
+
const details = await getBalanceDetails(run, ccy);
|
|
10944
|
+
const detail = details.find((d) => d.ccy === ccy);
|
|
10945
|
+
if (!detail) {
|
|
10946
|
+
errorLine(`Currency ${ccy} not found in account balance`);
|
|
10947
|
+
process.exitCode = 1;
|
|
10948
|
+
return;
|
|
10949
|
+
}
|
|
10950
|
+
const earnType = inferEarnType(detail);
|
|
10951
|
+
if (earnType === null) {
|
|
10952
|
+
errorLine(`${ccy} does not support auto-earn`);
|
|
10953
|
+
process.exitCode = 1;
|
|
10954
|
+
return;
|
|
10955
|
+
}
|
|
10956
|
+
const result = await run("earn_auto_set", { ccy, action: "turn_on", earnType });
|
|
10957
|
+
if (json) {
|
|
10958
|
+
printJson(result.data);
|
|
10959
|
+
return;
|
|
10960
|
+
}
|
|
10961
|
+
outputLine(`Auto-earn enabled for ${ccy} (${earnTypeLabel(earnType)})`);
|
|
10962
|
+
}
|
|
10963
|
+
async function cmdAutoEarnOff(run, ccy, json) {
|
|
10964
|
+
const details = await getBalanceDetails(run, ccy);
|
|
10965
|
+
const detail = details.find((d) => d.ccy === ccy);
|
|
10966
|
+
if (!detail) {
|
|
10967
|
+
errorLine(`Currency ${ccy} not found in account balance`);
|
|
10968
|
+
process.exitCode = 1;
|
|
10969
|
+
return;
|
|
10970
|
+
}
|
|
10971
|
+
const earnType = inferEarnType(detail);
|
|
10972
|
+
if (earnType === null) {
|
|
10973
|
+
errorLine(`${ccy} does not support auto-earn`);
|
|
10974
|
+
process.exitCode = 1;
|
|
10975
|
+
return;
|
|
10976
|
+
}
|
|
10977
|
+
const result = await run("earn_auto_set", { ccy, action: "turn_off", earnType });
|
|
10978
|
+
if (json) {
|
|
10979
|
+
printJson(result.data);
|
|
10980
|
+
return;
|
|
10981
|
+
}
|
|
10982
|
+
outputLine(`Auto-earn disabled for ${ccy} (${earnTypeLabel(earnType)})`);
|
|
10983
|
+
}
|
|
10984
|
+
|
|
10670
10985
|
// src/commands/bot.ts
|
|
10671
10986
|
function emitWriteResult5(item, label, idKey) {
|
|
10672
10987
|
const isError = item?.["sCode"] !== "0" && item?.["sCode"] !== 0;
|
|
@@ -10771,7 +11086,12 @@ async function cmdGridCreate(run, opts) {
|
|
|
10771
11086
|
direction: opts.direction,
|
|
10772
11087
|
lever: opts.lever,
|
|
10773
11088
|
sz: opts.sz,
|
|
10774
|
-
basePos: opts.basePos
|
|
11089
|
+
basePos: opts.basePos,
|
|
11090
|
+
tpTriggerPx: opts.tpTriggerPx,
|
|
11091
|
+
slTriggerPx: opts.slTriggerPx,
|
|
11092
|
+
tpRatio: opts.tpRatio,
|
|
11093
|
+
slRatio: opts.slRatio,
|
|
11094
|
+
algoClOrdId: opts.algoClOrdId
|
|
10775
11095
|
});
|
|
10776
11096
|
const data = getData7(result);
|
|
10777
11097
|
if (opts.json) return printJson(data);
|
|
@@ -10793,6 +11113,7 @@ async function cmdGridStop(run, opts) {
|
|
|
10793
11113
|
async function cmdDcaCreate(run, opts) {
|
|
10794
11114
|
const result = await run("dca_create_order", {
|
|
10795
11115
|
instId: opts.instId,
|
|
11116
|
+
algoOrdType: opts.algoOrdType,
|
|
10796
11117
|
lever: opts.lever,
|
|
10797
11118
|
direction: opts.direction,
|
|
10798
11119
|
initOrdAmt: opts.initOrdAmt,
|
|
@@ -10806,25 +11127,29 @@ async function cmdDcaCreate(run, opts) {
|
|
|
10806
11127
|
slMode: opts.slMode,
|
|
10807
11128
|
allowReinvest: opts.allowReinvest,
|
|
10808
11129
|
triggerStrategy: opts.triggerStrategy,
|
|
10809
|
-
triggerPx: opts.triggerPx
|
|
11130
|
+
triggerPx: opts.triggerPx,
|
|
11131
|
+
algoClOrdId: opts.algoClOrdId,
|
|
11132
|
+
reserveFunds: opts.reserveFunds,
|
|
11133
|
+
tradeQuoteCcy: opts.tradeQuoteCcy
|
|
10810
11134
|
});
|
|
10811
11135
|
const data = getData7(result);
|
|
10812
11136
|
if (opts.json) return printJson(data);
|
|
10813
|
-
const r = data?.[0];
|
|
10814
11137
|
emitWriteResult5(data?.[0], "DCA bot created", "algoId");
|
|
10815
11138
|
}
|
|
10816
11139
|
async function cmdDcaStop(run, opts) {
|
|
10817
11140
|
const result = await run("dca_stop_order", {
|
|
10818
|
-
algoId: opts.algoId
|
|
11141
|
+
algoId: opts.algoId,
|
|
11142
|
+
algoOrdType: opts.algoOrdType,
|
|
11143
|
+
stopType: opts.stopType
|
|
10819
11144
|
});
|
|
10820
11145
|
const data = getData7(result);
|
|
10821
11146
|
if (opts.json) return printJson(data);
|
|
10822
|
-
const r = data?.[0];
|
|
10823
11147
|
emitWriteResult5(data?.[0], "DCA bot stopped", "algoId");
|
|
10824
11148
|
}
|
|
10825
11149
|
async function cmdDcaOrders(run, opts) {
|
|
10826
11150
|
const result = await run("dca_get_orders", {
|
|
10827
11151
|
status: opts.history ? "history" : "active",
|
|
11152
|
+
algoOrdType: opts.algoOrdType,
|
|
10828
11153
|
algoId: opts.algoId,
|
|
10829
11154
|
instId: opts.instId
|
|
10830
11155
|
});
|
|
@@ -10838,6 +11163,7 @@ async function cmdDcaOrders(run, opts) {
|
|
|
10838
11163
|
orders.map((o) => ({
|
|
10839
11164
|
algoId: o["algoId"],
|
|
10840
11165
|
instId: o["instId"],
|
|
11166
|
+
type: o["algoOrdType"],
|
|
10841
11167
|
state: o["state"],
|
|
10842
11168
|
pnl: o["pnl"],
|
|
10843
11169
|
pnlRatio: o["pnlRatio"],
|
|
@@ -10847,7 +11173,8 @@ async function cmdDcaOrders(run, opts) {
|
|
|
10847
11173
|
}
|
|
10848
11174
|
async function cmdDcaDetails(run, opts) {
|
|
10849
11175
|
const result = await run("dca_get_order_details", {
|
|
10850
|
-
algoId: opts.algoId
|
|
11176
|
+
algoId: opts.algoId,
|
|
11177
|
+
algoOrdType: opts.algoOrdType
|
|
10851
11178
|
});
|
|
10852
11179
|
const detail = (getData7(result) ?? [])[0];
|
|
10853
11180
|
if (!detail) {
|
|
@@ -10857,6 +11184,7 @@ async function cmdDcaDetails(run, opts) {
|
|
|
10857
11184
|
if (opts.json) return printJson(detail);
|
|
10858
11185
|
printKv({
|
|
10859
11186
|
algoId: detail["algoId"],
|
|
11187
|
+
algoOrdType: detail["algoOrdType"],
|
|
10860
11188
|
instId: detail["instId"],
|
|
10861
11189
|
sz: detail["sz"],
|
|
10862
11190
|
avgPx: detail["avgPx"],
|
|
@@ -10874,26 +11202,42 @@ async function cmdDcaDetails(run, opts) {
|
|
|
10874
11202
|
async function cmdDcaSubOrders(run, opts) {
|
|
10875
11203
|
const result = await run("dca_get_sub_orders", {
|
|
10876
11204
|
algoId: opts.algoId,
|
|
11205
|
+
algoOrdType: opts.algoOrdType,
|
|
10877
11206
|
cycleId: opts.cycleId
|
|
10878
11207
|
});
|
|
10879
|
-
const
|
|
10880
|
-
if (opts.json) return printJson(
|
|
10881
|
-
if (!
|
|
11208
|
+
const rows = getData7(result) ?? [];
|
|
11209
|
+
if (opts.json) return printJson(rows);
|
|
11210
|
+
if (!rows.length) {
|
|
10882
11211
|
outputLine("No sub-orders");
|
|
10883
11212
|
return;
|
|
10884
11213
|
}
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
11214
|
+
if (opts.cycleId) {
|
|
11215
|
+
printTable(
|
|
11216
|
+
rows.map((o) => ({
|
|
11217
|
+
ordId: o["ordId"],
|
|
11218
|
+
side: o["side"],
|
|
11219
|
+
ordType: o["ordType"],
|
|
11220
|
+
px: o["px"],
|
|
11221
|
+
filledSz: o["filledSz"],
|
|
11222
|
+
avgFillPx: o["avgFillPx"],
|
|
11223
|
+
state: o["state"],
|
|
11224
|
+
fee: o["fee"]
|
|
11225
|
+
}))
|
|
11226
|
+
);
|
|
11227
|
+
} else {
|
|
11228
|
+
printTable(
|
|
11229
|
+
rows.map((o) => ({
|
|
11230
|
+
cycleId: o["cycleId"],
|
|
11231
|
+
status: o["cycleStatus"],
|
|
11232
|
+
current: o["currentCycle"] ? "yes" : "",
|
|
11233
|
+
avgPx: o["avgPx"],
|
|
11234
|
+
tpPx: o["tpPx"],
|
|
11235
|
+
realizedPnl: o["realizedPnl"],
|
|
11236
|
+
fee: o["fee"],
|
|
11237
|
+
startTime: o["startTime"] ? new Date(Number(o["startTime"])).toLocaleString() : ""
|
|
11238
|
+
}))
|
|
11239
|
+
);
|
|
11240
|
+
}
|
|
10897
11241
|
}
|
|
10898
11242
|
|
|
10899
11243
|
// src/commands/onchain-earn.ts
|
|
@@ -11193,7 +11537,7 @@ async function cmdDcdQuoteAndBuy(run, opts) {
|
|
|
11193
11537
|
// src/index.ts
|
|
11194
11538
|
var _require3 = createRequire3(import.meta.url);
|
|
11195
11539
|
var CLI_VERSION2 = _require3("../package.json").version;
|
|
11196
|
-
var GIT_HASH2 = true ? "
|
|
11540
|
+
var GIT_HASH2 = true ? "c270a0b" : "dev";
|
|
11197
11541
|
function handleConfigCommand(action, rest, json, lang, force) {
|
|
11198
11542
|
if (action === "init") return cmdConfigInit(lang === "zh" ? "zh" : "en");
|
|
11199
11543
|
if (action === "show") return cmdConfigShow(json);
|
|
@@ -11331,6 +11675,7 @@ function handleSpotAlgoCommand(run, subAction, v, json) {
|
|
|
11331
11675
|
side: v.side,
|
|
11332
11676
|
ordType: v.ordType ?? "conditional",
|
|
11333
11677
|
sz: v.sz,
|
|
11678
|
+
tgtCcy: v.tgtCcy,
|
|
11334
11679
|
tpTriggerPx: v.tpTriggerPx,
|
|
11335
11680
|
tpOrdPx: v.tpOrdPx,
|
|
11336
11681
|
slTriggerPx: v.slTriggerPx,
|
|
@@ -11425,6 +11770,7 @@ function handleSwapAlgoCommand(run, subAction, v, json) {
|
|
|
11425
11770
|
sz: v.sz,
|
|
11426
11771
|
posSide: v.posSide,
|
|
11427
11772
|
tdMode: v.tdMode ?? "cross",
|
|
11773
|
+
tgtCcy: v.tgtCcy,
|
|
11428
11774
|
tpTriggerPx: v.tpTriggerPx,
|
|
11429
11775
|
tpOrdPx: v.tpOrdPx,
|
|
11430
11776
|
slTriggerPx: v.slTriggerPx,
|
|
@@ -11537,6 +11883,7 @@ function handleOptionAlgoCommand(run, subAction, v, json) {
|
|
|
11537
11883
|
side: v.side,
|
|
11538
11884
|
ordType: v.ordType ?? "conditional",
|
|
11539
11885
|
sz: v.sz,
|
|
11886
|
+
tgtCcy: v.tgtCcy,
|
|
11540
11887
|
tpTriggerPx: v.tpTriggerPx,
|
|
11541
11888
|
tpOrdPx: v.tpOrdPx,
|
|
11542
11889
|
slTriggerPx: v.slTriggerPx,
|
|
@@ -11637,6 +11984,7 @@ function handleFuturesAlgoCommand(run, subAction, v, json) {
|
|
|
11637
11984
|
sz: v.sz,
|
|
11638
11985
|
posSide: v.posSide,
|
|
11639
11986
|
tdMode: v.tdMode ?? "cross",
|
|
11987
|
+
tgtCcy: v.tgtCcy,
|
|
11640
11988
|
tpTriggerPx: v.tpTriggerPx,
|
|
11641
11989
|
tpOrdPx: v.tpOrdPx,
|
|
11642
11990
|
slTriggerPx: v.slTriggerPx,
|
|
@@ -11779,6 +12127,11 @@ function handleBotGridCommand(run, v, rest, json) {
|
|
|
11779
12127
|
lever: v.lever,
|
|
11780
12128
|
sz: v.sz,
|
|
11781
12129
|
basePos: v.basePos,
|
|
12130
|
+
tpTriggerPx: v.tpTriggerPx,
|
|
12131
|
+
slTriggerPx: v.slTriggerPx,
|
|
12132
|
+
tpRatio: v.tpRatio,
|
|
12133
|
+
slRatio: v.slRatio,
|
|
12134
|
+
algoClOrdId: v.algoClOrdId,
|
|
11782
12135
|
json
|
|
11783
12136
|
});
|
|
11784
12137
|
if (subAction === "stop")
|
|
@@ -11791,15 +12144,17 @@ function handleBotGridCommand(run, v, rest, json) {
|
|
|
11791
12144
|
});
|
|
11792
12145
|
}
|
|
11793
12146
|
function handleBotDcaCommand(run, subAction, v, json) {
|
|
12147
|
+
const algoOrdType = v.algoOrdType ?? "contract_dca";
|
|
11794
12148
|
if (subAction === "orders")
|
|
11795
|
-
return cmdDcaOrders(run, { algoId: v.algoId, instId: v.instId, history: v.history ?? false, json });
|
|
12149
|
+
return cmdDcaOrders(run, { algoOrdType, algoId: v.algoId, instId: v.instId, history: v.history ?? false, json });
|
|
11796
12150
|
if (subAction === "details")
|
|
11797
|
-
return cmdDcaDetails(run, { algoId: v.algoId, json });
|
|
12151
|
+
return cmdDcaDetails(run, { algoId: v.algoId, algoOrdType, json });
|
|
11798
12152
|
if (subAction === "sub-orders")
|
|
11799
|
-
return cmdDcaSubOrders(run, { algoId: v.algoId, cycleId: v.cycleId, json });
|
|
12153
|
+
return cmdDcaSubOrders(run, { algoId: v.algoId, algoOrdType, cycleId: v.cycleId, json });
|
|
11800
12154
|
if (subAction === "create")
|
|
11801
12155
|
return cmdDcaCreate(run, {
|
|
11802
12156
|
instId: v.instId,
|
|
12157
|
+
algoOrdType,
|
|
11803
12158
|
lever: v.lever,
|
|
11804
12159
|
direction: v.direction,
|
|
11805
12160
|
initOrdAmt: v.initOrdAmt,
|
|
@@ -11814,10 +12169,13 @@ function handleBotDcaCommand(run, subAction, v, json) {
|
|
|
11814
12169
|
allowReinvest: v.allowReinvest,
|
|
11815
12170
|
triggerStrategy: v.triggerStrategy,
|
|
11816
12171
|
triggerPx: v.triggerPx,
|
|
12172
|
+
algoClOrdId: v.algoClOrdId,
|
|
12173
|
+
reserveFunds: v.reserveFunds,
|
|
12174
|
+
tradeQuoteCcy: v.tradeQuoteCcy,
|
|
11817
12175
|
json
|
|
11818
12176
|
});
|
|
11819
12177
|
if (subAction === "stop")
|
|
11820
|
-
return cmdDcaStop(run, { algoId: v.algoId, json });
|
|
12178
|
+
return cmdDcaStop(run, { algoId: v.algoId, algoOrdType, stopType: v.stopType, json });
|
|
11821
12179
|
}
|
|
11822
12180
|
function handleBotCommand(run, action, rest, v, json) {
|
|
11823
12181
|
if (action === "grid") return handleBotGridCommand(run, v, rest, json);
|
|
@@ -11829,8 +12187,32 @@ function handleEarnCommand(run, submodule, rest, v, json) {
|
|
|
11829
12187
|
if (submodule === "savings") return handleEarnSavingsCommand(run, action, innerRest, v, json);
|
|
11830
12188
|
if (submodule === "onchain") return handleEarnOnchainCommand(run, action, v, json);
|
|
11831
12189
|
if (submodule === "dcd") return handleEarnDcdCommand(run, action, v, json);
|
|
12190
|
+
if (submodule === "auto-earn") return handleEarnAutoEarnCommand(run, action, innerRest, v, json);
|
|
11832
12191
|
errorLine(`Unknown earn sub-module: ${submodule}`);
|
|
11833
|
-
errorLine("Valid: savings, onchain, dcd");
|
|
12192
|
+
errorLine("Valid: savings, onchain, dcd, auto-earn");
|
|
12193
|
+
process.exitCode = 1;
|
|
12194
|
+
}
|
|
12195
|
+
function handleEarnAutoEarnCommand(run, action, rest, v, json) {
|
|
12196
|
+
const ccy = rest[0] ?? v.ccy;
|
|
12197
|
+
if (action === "status") return cmdAutoEarnStatus(run, ccy, json);
|
|
12198
|
+
if (action === "on") {
|
|
12199
|
+
if (!ccy) {
|
|
12200
|
+
errorLine("Currency required: okx earn auto-earn on <ccy>");
|
|
12201
|
+
process.exitCode = 1;
|
|
12202
|
+
return;
|
|
12203
|
+
}
|
|
12204
|
+
return cmdAutoEarnOn(run, ccy, json);
|
|
12205
|
+
}
|
|
12206
|
+
if (action === "off") {
|
|
12207
|
+
if (!ccy) {
|
|
12208
|
+
errorLine("Currency required: okx earn auto-earn off <ccy>");
|
|
12209
|
+
process.exitCode = 1;
|
|
12210
|
+
return;
|
|
12211
|
+
}
|
|
12212
|
+
return cmdAutoEarnOff(run, ccy, json);
|
|
12213
|
+
}
|
|
12214
|
+
errorLine(`Unknown auto-earn command: ${action}`);
|
|
12215
|
+
errorLine("Valid: status, on, off");
|
|
11834
12216
|
process.exitCode = 1;
|
|
11835
12217
|
}
|
|
11836
12218
|
function handleEarnSavingsCommand(run, action, rest, v, json) {
|
|
@@ -11840,7 +12222,6 @@ function handleEarnSavingsCommand(run, action, rest, v, json) {
|
|
|
11840
12222
|
if (action === "redeem") return cmdEarnSavingsRedeem(run, { ccy: v.ccy, amt: v.amt, json });
|
|
11841
12223
|
if (action === "set-rate") return cmdEarnSetLendingRate(run, { ccy: v.ccy, rate: v.rate, json });
|
|
11842
12224
|
if (action === "lending-history") return cmdEarnLendingHistory(run, { ccy: v.ccy, limit, json });
|
|
11843
|
-
if (action === "rate-summary") return cmdEarnLendingRateSummary(run, rest[0] ?? v.ccy, json);
|
|
11844
12225
|
if (action === "rate-history") return cmdEarnLendingRateHistory(run, { ccy: v.ccy, limit, json });
|
|
11845
12226
|
errorLine(`Unknown earn savings command: ${action}`);
|
|
11846
12227
|
process.exitCode = 1;
|