@pionex/pionex-trade-mcp 0.2.44 → 0.2.45
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 +109 -72
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1777,23 +1777,6 @@ function asPositiveDecimalString2(value, field) {
|
|
|
1777
1777
|
function normalizePerpBase(base) {
|
|
1778
1778
|
return base.endsWith(".PERP") ? base : `${base}.PERP`;
|
|
1779
1779
|
}
|
|
1780
|
-
function parseSmartCopyBuOrderData(raw) {
|
|
1781
|
-
const quoteInvestment = asPositiveDecimalString2(raw.quoteInvestment, "buOrderData.quoteInvestment");
|
|
1782
|
-
const leverageType = asNonEmptyString3(raw.leverageType, "buOrderData.leverageType");
|
|
1783
|
-
assertEnum3(leverageType, "buOrderData.leverageType", ["follow", "fixed"]);
|
|
1784
|
-
if (leverageType === "fixed" && raw.leverage == null) {
|
|
1785
|
-
throw new Error('Invalid "buOrderData.leverage": required when leverageType is "fixed".');
|
|
1786
|
-
}
|
|
1787
|
-
const out = { quoteInvestment, leverageType };
|
|
1788
|
-
if (raw.leverage != null) out.leverage = asPositiveNumber3(raw.leverage, "buOrderData.leverage");
|
|
1789
|
-
if (raw.maxInvestPerOrder != null) out.maxInvestPerOrder = asPositiveDecimalString2(raw.maxInvestPerOrder, "buOrderData.maxInvestPerOrder");
|
|
1790
|
-
if (raw.copyMode != null) {
|
|
1791
|
-
const copyMode = asNonEmptyString3(raw.copyMode, "buOrderData.copyMode");
|
|
1792
|
-
assertEnum3(copyMode, "buOrderData.copyMode", ["fixed_amount", "fixed_ratio"]);
|
|
1793
|
-
out.copyMode = copyMode;
|
|
1794
|
-
}
|
|
1795
|
-
return out;
|
|
1796
|
-
}
|
|
1797
1780
|
function registerBotTools() {
|
|
1798
1781
|
return [
|
|
1799
1782
|
{
|
|
@@ -2283,62 +2266,76 @@ function registerBotTools() {
|
|
|
2283
2266
|
name: "pionex_bot_smart_copy_check_params",
|
|
2284
2267
|
module: "bot",
|
|
2285
2268
|
isWrite: false,
|
|
2286
|
-
description: "Validate smart copy bot parameters before creating an order.
|
|
2269
|
+
description: "Validate smart copy bot parameters before creating an order. Pass quote_investment='0' to get the allowed range only (no investment estimate). Returns max_investment, max_leverage, available_limit (and notional_limit when invest>0). Endpoint: POST /api/v1/bot/orders/smartCopy/checkParams",
|
|
2287
2270
|
inputSchema: {
|
|
2288
2271
|
type: "object",
|
|
2289
2272
|
additionalProperties: false,
|
|
2290
|
-
required: ["base", "quote", "
|
|
2273
|
+
required: ["base", "quote", "leverage", "quote_investment"],
|
|
2291
2274
|
properties: {
|
|
2292
2275
|
base: { type: "string", description: "Base currency (e.g. BTC)" },
|
|
2293
2276
|
quote: { type: "string", description: "Quote currency (e.g. USDT)" },
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
properties: {
|
|
2299
|
-
quoteInvestment: { type: "string", description: "Investment amount in quote currency." },
|
|
2300
|
-
leverageType: { type: "string", enum: ["follow", "fixed"], description: "Follow signal provider's leverage or use fixed value." },
|
|
2301
|
-
leverage: { type: "number", description: "Custom leverage (required when leverageType is 'fixed')." },
|
|
2302
|
-
maxInvestPerOrder: { type: "string", description: "Maximum investment per replicated order." },
|
|
2303
|
-
copyMode: { type: "string", enum: ["fixed_amount", "fixed_ratio"], description: "Copy mode." }
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2277
|
+
leverage: { type: "integer", description: "Leverage multiplier (e.g. 2)" },
|
|
2278
|
+
quote_investment: { type: "string", description: "Investment amount in quote currency; use '0' to get range only" },
|
|
2279
|
+
signal_type: { type: "string", description: "Optional; signal provider UUID to scope the check" },
|
|
2280
|
+
signal_param: { type: "string", description: "Optional; signal parameters as a JSON string" }
|
|
2306
2281
|
}
|
|
2307
2282
|
},
|
|
2308
2283
|
async handler(args, { client }) {
|
|
2309
2284
|
const base = asNonEmptyString3(args.base, "base");
|
|
2310
2285
|
const quote = asNonEmptyString3(args.quote, "quote");
|
|
2311
|
-
const
|
|
2312
|
-
|
|
2286
|
+
const leverage = asPositiveInteger3(args.leverage, "leverage");
|
|
2287
|
+
const quote_investment = asNonEmptyString3(args.quote_investment, "quote_investment");
|
|
2288
|
+
const body = { base, quote, leverage, quote_investment };
|
|
2289
|
+
if (args.signal_type != null) body.signal_type = String(args.signal_type);
|
|
2290
|
+
if (args.signal_param != null) body.signal_param = String(args.signal_param);
|
|
2291
|
+
return (await client.signedPost("/api/v1/bot/orders/smartCopy/checkParams", body)).data;
|
|
2313
2292
|
}
|
|
2314
2293
|
},
|
|
2315
2294
|
{
|
|
2316
2295
|
name: "pionex_bot_smart_copy_create",
|
|
2317
2296
|
module: "bot",
|
|
2318
2297
|
isWrite: true,
|
|
2319
|
-
description: "Create a smart copy bot order. Required: base, quote,
|
|
2298
|
+
description: "Create a smart copy bot order. Required: base, quote, bu_order_data.quote_total_investment, bu_order_data.portfolio (each portfolio item needs base, signal_type, leverage). Returns buOrderId on success. Endpoint: POST /api/v1/bot/orders/smartCopy/create",
|
|
2320
2299
|
inputSchema: {
|
|
2321
2300
|
type: "object",
|
|
2322
2301
|
additionalProperties: false,
|
|
2323
|
-
required: ["base", "quote", "
|
|
2302
|
+
required: ["base", "quote", "bu_order_data"],
|
|
2324
2303
|
properties: {
|
|
2325
2304
|
base: { type: "string", description: "Base currency (e.g. BTC)" },
|
|
2326
2305
|
quote: { type: "string", description: "Quote currency (e.g. USDT)" },
|
|
2327
|
-
|
|
2306
|
+
bu_order_data: {
|
|
2328
2307
|
type: "object",
|
|
2329
2308
|
additionalProperties: false,
|
|
2330
|
-
required: ["
|
|
2309
|
+
required: ["quote_total_investment", "portfolio"],
|
|
2331
2310
|
properties: {
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2311
|
+
quote_total_investment: { type: "string", description: "Total investment in quote currency" },
|
|
2312
|
+
portfolio: {
|
|
2313
|
+
type: "array",
|
|
2314
|
+
items: {
|
|
2315
|
+
type: "object",
|
|
2316
|
+
additionalProperties: false,
|
|
2317
|
+
required: ["base", "signal_type", "leverage"],
|
|
2318
|
+
properties: {
|
|
2319
|
+
base: { type: "string", description: "Base currency for this signal" },
|
|
2320
|
+
signal_type: { type: "string", description: "Signal provider UUID" },
|
|
2321
|
+
leverage: { type: "integer", description: "Leverage multiplier" },
|
|
2322
|
+
percent: { type: "string", description: "Allocation fraction of total investment (e.g. '1' for 100%)" },
|
|
2323
|
+
signal_param: { type: "string", description: "Signal parameters as a JSON string" },
|
|
2324
|
+
profit_stop_ratio: { type: "string", description: "Take-profit ratio" },
|
|
2325
|
+
loss_stop_ratio: { type: "string", description: "Stop-loss ratio" }
|
|
2326
|
+
}
|
|
2327
|
+
},
|
|
2328
|
+
description: "Portfolio of signals to copy"
|
|
2329
|
+
},
|
|
2330
|
+
compound: { type: "boolean", description: "Enable compound reinvestment" },
|
|
2331
|
+
profit_stop_maker: { type: "boolean", description: "Enable profit stop maker" }
|
|
2337
2332
|
}
|
|
2338
2333
|
},
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2334
|
+
key_id: { type: "string", description: "Optional key ID" },
|
|
2335
|
+
note: { type: "string", description: "Optional note" },
|
|
2336
|
+
copy_from: { type: "string", description: "Source bot order ID to copy settings from" },
|
|
2337
|
+
copy_type: { type: "string", description: "Copy type" },
|
|
2338
|
+
__dryRun: { type: "boolean", description: "If true, return resolved body without placing an order." }
|
|
2342
2339
|
}
|
|
2343
2340
|
},
|
|
2344
2341
|
async handler(args, { client, config }) {
|
|
@@ -2347,16 +2344,33 @@ function registerBotTools() {
|
|
|
2347
2344
|
}
|
|
2348
2345
|
const base = asNonEmptyString3(args.base, "base");
|
|
2349
2346
|
const quote = asNonEmptyString3(args.quote, "quote");
|
|
2350
|
-
const
|
|
2351
|
-
const
|
|
2352
|
-
if (
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2347
|
+
const rawBuOrderData = asObject(args.bu_order_data, "bu_order_data");
|
|
2348
|
+
const quote_total_investment = asNonEmptyString3(rawBuOrderData.quote_total_investment, "bu_order_data.quote_total_investment");
|
|
2349
|
+
if (!Array.isArray(rawBuOrderData.portfolio) || rawBuOrderData.portfolio.length === 0) {
|
|
2350
|
+
throw new Error('Invalid "bu_order_data.portfolio": expected non-empty array.');
|
|
2351
|
+
}
|
|
2352
|
+
const portfolio = rawBuOrderData.portfolio.map((item, i) => {
|
|
2353
|
+
const p = {
|
|
2354
|
+
base: asNonEmptyString3(item.base, `portfolio[${i}].base`),
|
|
2355
|
+
signal_type: asNonEmptyString3(item.signal_type, `portfolio[${i}].signal_type`),
|
|
2356
|
+
leverage: asPositiveInteger3(item.leverage, `portfolio[${i}].leverage`)
|
|
2359
2357
|
};
|
|
2358
|
+
if (item.percent != null) p.percent = asNonEmptyString3(item.percent, `portfolio[${i}].percent`);
|
|
2359
|
+
if (item.signal_param != null) p.signal_param = String(item.signal_param);
|
|
2360
|
+
if (item.profit_stop_ratio != null) p.profit_stop_ratio = String(item.profit_stop_ratio);
|
|
2361
|
+
if (item.loss_stop_ratio != null) p.loss_stop_ratio = String(item.loss_stop_ratio);
|
|
2362
|
+
return p;
|
|
2363
|
+
});
|
|
2364
|
+
const buOrderData = { quote_total_investment, portfolio };
|
|
2365
|
+
if (rawBuOrderData.compound != null) buOrderData.compound = asBoolean2(rawBuOrderData.compound, "bu_order_data.compound");
|
|
2366
|
+
if (rawBuOrderData.profit_stop_maker != null) buOrderData.profit_stop_maker = asBoolean2(rawBuOrderData.profit_stop_maker, "bu_order_data.profit_stop_maker");
|
|
2367
|
+
const body = { base, quote, bu_order_data: buOrderData };
|
|
2368
|
+
if (args.key_id != null) body.key_id = String(args.key_id);
|
|
2369
|
+
if (args.note != null) body.note = String(args.note);
|
|
2370
|
+
if (args.copy_from != null) body.copy_from = String(args.copy_from);
|
|
2371
|
+
if (args.copy_type != null) body.copy_type = String(args.copy_type);
|
|
2372
|
+
if (args.__dryRun === true) {
|
|
2373
|
+
return { dryRun: true, note: "No order was sent.", resolvedBody: body };
|
|
2360
2374
|
}
|
|
2361
2375
|
return (await client.signedPost("/api/v1/bot/orders/smartCopy/create", body)).data;
|
|
2362
2376
|
}
|
|
@@ -2369,23 +2383,21 @@ function registerBotTools() {
|
|
|
2369
2383
|
inputSchema: {
|
|
2370
2384
|
type: "object",
|
|
2371
2385
|
additionalProperties: false,
|
|
2372
|
-
required: ["
|
|
2386
|
+
required: ["bu_order_id"],
|
|
2373
2387
|
properties: {
|
|
2374
|
-
|
|
2375
|
-
|
|
2388
|
+
bu_order_id: { type: "string", description: "Smart copy bot order ID." },
|
|
2389
|
+
close_note: { type: "string", description: "Optional close note." },
|
|
2390
|
+
convert_into_earn_coin: { type: "boolean", description: "Whether to convert remaining funds into earn coin." }
|
|
2376
2391
|
}
|
|
2377
2392
|
},
|
|
2378
2393
|
async handler(args, { client, config }) {
|
|
2379
2394
|
if (config.readOnly) {
|
|
2380
2395
|
throw new Error("Server is running in --read-only mode; bot smart_copy cancel is disabled.");
|
|
2381
2396
|
}
|
|
2382
|
-
const
|
|
2383
|
-
const body = {
|
|
2384
|
-
if (args.
|
|
2385
|
-
|
|
2386
|
-
assertEnum3(closeSellModel, "closeSellModel", ["NOT_SELL", "TO_QUOTE", "TO_USDT"]);
|
|
2387
|
-
body.closeSellModel = closeSellModel;
|
|
2388
|
-
}
|
|
2397
|
+
const bu_order_id = asNonEmptyString3(args.bu_order_id, "bu_order_id");
|
|
2398
|
+
const body = { bu_order_id };
|
|
2399
|
+
if (args.close_note != null) body.close_note = String(args.close_note);
|
|
2400
|
+
if (args.convert_into_earn_coin != null) body.convert_into_earn_coin = asBoolean2(args.convert_into_earn_coin, "convert_into_earn_coin");
|
|
2389
2401
|
return (await client.signedPost("/api/v1/bot/orders/smartCopy/cancel", body)).data;
|
|
2390
2402
|
}
|
|
2391
2403
|
},
|
|
@@ -2394,24 +2406,49 @@ function registerBotTools() {
|
|
|
2394
2406
|
name: "pionex_bot_signal_add_listener",
|
|
2395
2407
|
module: "bot",
|
|
2396
2408
|
isWrite: true,
|
|
2397
|
-
description: "
|
|
2409
|
+
description: "Push a trading signal to the Pionex signal platform (signal provider use). The platform forwards the signal to all smart copy bots subscribed to the given signalType. Use action='buy' to open a position and action='sell' to close it. Endpoint: POST /api/v1/bot/signal/listener",
|
|
2398
2410
|
inputSchema: {
|
|
2399
2411
|
type: "object",
|
|
2400
2412
|
additionalProperties: false,
|
|
2401
|
-
required: ["
|
|
2413
|
+
required: ["signalType", "signalParam", "base", "quote", "time", "price", "data"],
|
|
2402
2414
|
properties: {
|
|
2403
|
-
|
|
2404
|
-
|
|
2415
|
+
signalType: { type: "string", description: "Signal provider UUID." },
|
|
2416
|
+
signalParam: { type: "string", description: "Signal parameters as a JSON string (use '{}' for no extra params)." },
|
|
2417
|
+
base: { type: "string", description: "Base currency (e.g. BTC)." },
|
|
2418
|
+
quote: { type: "string", description: "Quote currency (e.g. USDT)." },
|
|
2419
|
+
time: { type: "string", description: "Signal timestamp in RFC 3339 format (e.g. '2024-01-01T12:00:00Z')." },
|
|
2420
|
+
price: { type: "string", description: "Current price at time of signal (e.g. '85000')." },
|
|
2421
|
+
data: {
|
|
2422
|
+
type: "object",
|
|
2423
|
+
additionalProperties: false,
|
|
2424
|
+
required: ["action", "position_size", "contracts"],
|
|
2425
|
+
properties: {
|
|
2426
|
+
action: { type: "string", enum: ["buy", "sell"], description: "'buy' to open a position, 'sell' to close." },
|
|
2427
|
+
position_size: { type: "string", description: "Target position size as a fraction (e.g. '1' = 100%)." },
|
|
2428
|
+
contracts: { type: "string", description: "Number of contracts." },
|
|
2429
|
+
direction: { type: "string", description: "Optional trade direction." }
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2405
2432
|
}
|
|
2406
2433
|
},
|
|
2407
2434
|
async handler(args, { client, config }) {
|
|
2408
2435
|
if (config.readOnly) {
|
|
2409
2436
|
throw new Error("Server is running in --read-only mode; bot signal add_listener is disabled.");
|
|
2410
2437
|
}
|
|
2411
|
-
const
|
|
2412
|
-
const
|
|
2413
|
-
|
|
2414
|
-
|
|
2438
|
+
const signalType = asNonEmptyString3(args.signalType, "signalType");
|
|
2439
|
+
const signalParam = asNonEmptyString3(args.signalParam, "signalParam");
|
|
2440
|
+
const base = asNonEmptyString3(args.base, "base");
|
|
2441
|
+
const quote = asNonEmptyString3(args.quote, "quote");
|
|
2442
|
+
const time = asNonEmptyString3(args.time, "time");
|
|
2443
|
+
const price = asNonEmptyString3(args.price, "price");
|
|
2444
|
+
const rawData = asObject(args.data, "data");
|
|
2445
|
+
const action = asNonEmptyString3(rawData.action, "data.action");
|
|
2446
|
+
assertEnum3(action, "data.action", ["buy", "sell"]);
|
|
2447
|
+
const position_size = asNonEmptyString3(rawData.position_size, "data.position_size");
|
|
2448
|
+
const contracts = asNonEmptyString3(rawData.contracts, "data.contracts");
|
|
2449
|
+
const data = { action, position_size, contracts };
|
|
2450
|
+
if (rawData.direction != null) data.direction = String(rawData.direction);
|
|
2451
|
+
return (await client.signedPost("/api/v1/bot/signal/listener", { signalType, signalParam, base, quote, time, price, data })).data;
|
|
2415
2452
|
}
|
|
2416
2453
|
}
|
|
2417
2454
|
];
|