@dbotx/copy-trading-mcp-server
Version:
Copy Trading MCP Server - Supports creating and managing complex copy trading tasks, automatically following other users' trading strategies
489 lines ⢠71.9 kB
JavaScript
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const client_js_1 = require("./client.js");
const types_js_2 = require("./types.js");
class CopyTradingMcpServer {
server;
client;
constructor() {
this.server = new index_js_1.Server({
name: 'copy-trading-mcp-server',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
// Validate wallet ID configuration
try {
(0, types_js_2.validateWalletIdConfig)();
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error('Wallet ID configuration error:', errorMessage);
throw error;
}
this.client = new client_js_1.DbotCopyTradingClient();
this.setupToolHandlers();
this.setupErrorHandling();
}
setupErrorHandling() {
this.server.onerror = (error) => {
console.error('[MCP Error]', error);
};
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
/**
* Format API error message
*/
formatApiError(response, operation, request) {
let errorText = `ā ${operation} failed:\n\n`;
// Show error status
errorText += `š Error Status: ${response.err ? 'Failed' : 'Unknown Error'}\n`;
// Show response content
if (response.res) {
errorText += `š API Response: ${JSON.stringify(response.res, null, 2)}\n`;
}
// Show request parameters (exclude sensitive info)
if (request) {
const safeRequest = { ...request };
if (safeRequest.walletId) {
safeRequest.walletId = safeRequest.walletId.substring(0, 8) + '***';
}
errorText += `š Request Parameters: ${JSON.stringify(safeRequest, null, 2)}\n`;
}
// Show documentation link
errorText += `\nš Documentation: ${response.docs || 'https://dbotx.com/docs'}`;
return errorText;
}
/**
* Format network error message
*/
formatNetworkError(error, operation, request) {
let errorText = `ā ${operation} failed:\n\n`;
if (error.response) {
// HTTP error response
errorText += `š HTTP Status: ${error.response.status} ${error.response.statusText}\n`;
errorText += `š Error Response: ${JSON.stringify(error.response.data, null, 2)}\n`;
}
else if (error.request) {
// Network request failed
errorText += `š Network Error: No response received, please check network connection\n`;
errorText += `š” Request Details: ${error.message}\n`;
}
else {
// Other errors
errorText += `ā ļø Unknown Error: ${error.message}\n`;
}
// Show request parameters (exclude sensitive info)
if (request) {
const safeRequest = { ...request };
if (safeRequest.walletId) {
safeRequest.walletId = safeRequest.walletId.substring(0, 8) + '***';
}
if (safeRequest.walletIdList) {
safeRequest.walletIdList = safeRequest.walletIdList.map((id) => id.substring(0, 8) + '***');
}
errorText += `š Request Parameters: ${JSON.stringify(safeRequest, null, 2)}\n`;
}
errorText += `\nš” Suggestions:\n`;
errorText += `- Check if API key is correct\n`;
errorText += `- Check if network connection is normal\n`;
errorText += `- Check if parameter format is correct\n`;
errorText += `- Check if wallet ID is valid\n`;
return errorText;
}
setupToolHandlers() {
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'create_copy_trading',
description: `Create multi-chain copy trading tasks - automatically follow the trading behavior of specified wallet addresses for buying and selling operations.
Request example:
{
"enabled": true,
"name": "Follow xxx",
"chain": "solana",
"targetIds": [
"xxx"
],
"buySettings": {
"enabled": true,
"maxBuyAmountUI": "0.1"
},
"sellSettings": {
"enabled": true
}
}
`,
inputSchema: {
type: 'object',
properties: {
enabled: {
type: 'boolean',
description: 'Task enabled status, true/false',
default: true,
},
name: {
type: 'string',
description: 'Name of the copy trading task',
},
chain: {
type: 'string',
enum: ['solana', 'ethereum', 'base', 'bsc', 'tron'],
description: 'Chain (solana/ethereum/base/bsc/tron)',
default: 'solana',
},
dexFilter: {
type: 'array',
items: { type: 'string' },
description: 'DEXs to follow, null means all, specifying names means only follow trades on those DEXs, including: raydium_amm,raydium_clmm,raydium_cpmm,raydium_launchpad,meteora_dlmm,meteora_dyn,meteora_dyn2,meteora_bc,pump,pump_swap,moonshot,orca_wp,uniswap_v2,uniswap_v3,pancake_v2,pancake_v3,sunswap_v2,sunpump,ether_vista,okx_v2,fourmeme,boop',
},
targetIds: {
type: 'array',
items: { type: 'string' },
description: 'Wallet addresses to copy trade (up to 10)',
maxItems: 10,
minItems: 1,
},
tokenBlacklist: {
type: 'array',
items: { type: 'string' },
description: 'Blacklisted token addresses for the current task (up to 20), buying and selling of these tokens will be skipped',
maxItems: 20,
},
walletId: {
type: 'string',
description: 'ID of the wallet to use, obtainable via "Wallet Info API"',
},
groupId: {
type: 'string',
description: 'Group ID',
},
buySettings: {
type: 'object',
description: 'Buy-related settings',
properties: {
enabled: { type: 'boolean', default: true, description: 'Buy task enabled status' },
startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: 'Enable time for follow buy or sell (UTC). Follow buys or sells will only execute after this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: 'Disable time for follow buy or sell (UTC). Follow buys or sells will only execute before this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
buyAmountType: {
type: 'string',
enum: ['fixed_amount', 'fixed_ratio', 'follow_amount'],
default: 'follow_amount',
description: 'Copy buy type, "fixed_amount" for fixed amount, "fixed_ratio" for fixed ratio, "follow_amount" for follow amount'
},
maxBuyAmountUI: { type: 'string', description: 'Maximum buy amount for copy trading, minimum 0.001 SOL, 0.0001 ETH, 0.0001 BNB, 1 TRX' },
buyRatio: { type: 'number', minimum: 0, maximum: 10, default: 1, description: 'Follow buy ratio (0-10), effective when buy type is fixed_ratio' },
maxBalanceUI: { type: 'number', minimum: 0, default: 100, description: 'Take-profit amount (ETH/SOL/BNB/TRX), no more copy buys when wallet balance exceeds this amount' },
reservedAmountUI: { type: 'number', minimum: 0, default: 0.01, description: 'Stop-loss amount (ETH/SOL/BNB/TRX), no more copy buys when wallet balance falls below this amount' },
targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: 'When in buy settings, it means only follow buy when smart money buy amount is greater than this value; when in sell settings, it means only follow sell when smart money sell income is greater than this value' },
targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: 'When in buy settings, it means only follow buy when smart money buy amount is less than this value; when in sell settings, it means only follow sell when smart money sell income is less than this value' },
minTokenMCUSD: { type: 'number', minimum: 0, default: 0, description: 'Minimum copy token market cap, only follow buy tokens with market cap higher than this value' },
maxTokenMCUSD: { type: 'number', minimum: 0, default: 999999999, description: 'Maximum copy token market cap, only follow buy tokens with market cap lower than this value' },
maxBuyTax: { type: 'number', minimum: 0, maximum: 1, description: 'Maximum token buy tax, effective for EVM chains, only follow buy tokens with tax rate lower than this value (data from GoPlus, may affect copy trading speed)' },
maxSellTax: { type: 'number', minimum: 0, maximum: 1, description: 'Maximum token sell tax, effective for EVM chains, only follow buy tokens with tax rate lower than this value (data from GoPlus, may affect copy trading speed)' },
customFeeAndTip: { type: 'boolean', default: false, description: '"true" means both priorityFee and jitoTip fields are effective, the system will execute the transaction with the specified values (null means auto priority fee/auto bribe), "false" means only priorityFee is effective in high-speed mode, and only jitoTip is effective in anti-sandwich mode, the system will allocate automatically' },
priorityFee: { type: 'string', default: '', description: 'Priority fee (SOL), effective for Solana, an empty string means use auto priority fee' },
gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: 'Additional gas (Gwei), effective for EVM chains' },
maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: 'No transaction will be made if base gas exceeds this value (Gwei), effective for EVM chains' },
jitoEnabled: { type: 'boolean', default: true, description: '"true" enables anti-sandwich mode (Solana & Ethereum & Bsc)' },
jitoTip: { type: 'number', minimum: 0, default: 0.001, description: 'Bribe fee for anti-sandwich mode (Solana)' },
maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: 'Maximum slippage (0.00-1.00). For buying, it is the difference between the actual and expected price. For selling, it is the difference between the expected and actual price. The difference multiple = 1/(1-slippage). 0.5 means accepting up to a 2x price difference, 1 means no limit.' },
skipFreezableToken: { type: 'boolean', default: false, description: '"true" means do not buy tokens with unrevoked freeze authority' },
skipMintableToken: { type: 'boolean', default: false, description: '"true" means do not buy tokens with unrevoked mint authority' },
skipDelegatedToken: { type: 'boolean', default: false, description: '"true" means do not buy delegated tokens' },
skipNotOpensource: { type: 'boolean', default: false, description: '"true" means do not buy tokens defined as not open-source by GoPlus, effective for EVM chains (enabling this may affect copy trading speed)' },
skipHoneyPot: { type: 'boolean', default: false, description: '"true" means do not buy tokens identified as honeypots by GoPlus, effective for EVM chains (enabling this may affect copy trading speed)' },
skipTargetIncreasePosition: { type: 'boolean', default: false, description: '"true" means do not buy tokens already held by the smart money address' },
minBurnedLp: { type: 'number', minimum: 0, maximum: 1, default: 0, description: 'Minimum LP burn ratio (0-1). Only follow buys for tokens with a liquidity burn ratio greater than or equal to this value. Supports Raydium (AMM) and Raydium (CPMM).' },
minLpUsd: { type: 'number', minimum: 0, default: 0, description: 'Minimum liquidity ($), only follow buy tokens with liquidity greater than or equal to this value' },
minTokenAgeMs: { type: 'number', minimum: 0, default: 0, description: 'Minimum token creation time (milliseconds), only follow buy tokens created at or after this time' },
maxTokenAgeMs: { type: 'number', minimum: 0, default: 999999999999, description: 'Maximum token creation time (milliseconds), only follow buy tokens created at or before this time' },
maxTopHoldPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: 'Maximum top 10 holders percentage (0-1), only follow buy tokens where the top 10 holders have less than this percentage (effective for Solana)' },
maxBuyTimesPerToken: { type: 'number', minimum: 1, default: 999, description: 'Maximum number of buys for a token in this task within 7 days. No more buys will occur if this number is exceeded.' },
maxBuyAmountPerToken: { type: 'number', minimum: 0, default: 999999, description: 'Maximum buy amount for a token in this task within 7 days (in SOL / ETH / BNB / TRX). No more buys will occur if this amount is exceeded.' },
buyExist: { type: 'boolean', default: false, description: 'Whether to continue following buys for tokens already held' },
buyOncePerWallet: { type: 'boolean', default: false, description: '"true" means buy only once, "false" means no limit on the number of buys (only for tokens bought via DBot)' },
concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: 'Number of concurrent nodes (1-3)' },
retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: 'Number of retries after failure (0-10)' },
},
required: ['maxBuyAmountUI'],
},
sellSettings: {
type: 'object',
description: 'Sell-related settings',
properties: {
enabled: { type: 'boolean', default: true, description: 'Sell task enabled status' },
startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: 'Enable time for follow buy or sell (UTC). Follow buys or sells will only execute after this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: 'Disable time for follow buy or sell (UTC). Follow buys or sells will only execute before this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
mode: {
type: 'string',
enum: ['mixed', 'only_copy', 'only_pnl'],
default: 'mixed',
description: 'Sell mode, "mixed" means both follow selling and take-profit/stop-loss are enabled, "only_copy" means only follow selling is enabled, "only_pnl" means only take-profit/stop-loss is enabled'
},
sellAmountType: {
type: 'string',
enum: ['all', 'follow_ratio', 'x_target_ratio'],
default: 'all',
description: 'Copy sell ratio, "all" for 100% sell, "follow_ratio" for sell by follow ratio, "x_target_ratio" for selling by multiplying smart money\'s sell ratio by a fixed multiplier'
},
xTargetRatio: { type: 'number', minimum: 0, maximum: 100, default: 1, description: 'Multiplier for smart money\'s sell ratio (0-100), e.g., if set to 0.5 and smart money sells 10%, you sell 10% * 0.5 = 5%; if set to 2, you sell 10% * 2 = 20%' },
sellSpeedType: {
type: 'string',
enum: ['fast', 'accurate'],
default: 'accurate',
description: 'Follow sell speed, invalid when mode is "only_pnl". Can be "fast" or "accurate". "fast" prioritizes speed but may cause inconsistent sell ratios with smart money. "accurate" prioritizes accuracy but may be slower.'
},
targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: 'When in buy settings, it means only follow buy when smart money buy amount is greater than this value; when in sell settings, it means only follow sell when smart money sell income is greater than this value' },
targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: 'When in buy settings, it means only follow buy when smart money buy amount is less than this value; when in sell settings, it means only follow sell when smart money sell income is less than this value' },
stopEarnPercent: { type: 'number', minimum: 0, description: 'Take-profit percentage (0.5 means 50%). Effective for "buy" type in quick buy/sell and in copy trading sell settings. Automatically sells when a token price increases by this percentage. "null" means take-profit is disabled.' },
stopLossPercent: { type: 'number', minimum: 0, description: 'Stop-loss percentage (0.5 means 50%). Effective for "buy" type in quick buy/sell and in copy trading sell settings. Automatically sells when a token price drops by this percentage. "null" means stop-loss is disabled.' },
stopEarnGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. In take-profit groups, it\'s the increase to sell at. In stop-loss groups, it\'s the decrease to sell at. In trailing stop-loss groups, it\'s the pullback ratio (cannot be >= 1).' },
amountPercent: { type: 'number', minimum: 0, maximum: 1, description: 'Sell ratio (0-1, 0.5 means 50%). E.g., for selling 50% at 100% gain and all at 200% gain, the sell ratios should be 0.5 and 1, not 0.5 and 0.5.' },
},
required: ['pricePercent', 'amountPercent'],
},
maxItems: 6,
description: 'Take-profit groups. Effective for "buy" type in quick buy/sell and in copy trading sell settings. Up to 6 groups supported. "null" means disabled. If both "stopEarnGroup" and "stopEarnPercent" are set, "stopEarnPercent" is ignored.'
},
stopLossGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. In take-profit groups, it\'s the increase to sell at. In stop-loss groups, it\'s the decrease to sell at. In trailing stop-loss groups, it\'s the pullback ratio (cannot be >= 1).' },
amountPercent: { type: 'number', minimum: 0, maximum: 1, description: 'Sell ratio (0-1, 0.5 means 50%). E.g., for selling 50% at 100% gain and all at 200% gain, the sell ratios should be 0.5 and 1, not 0.5 and 0.5.' },
},
required: ['pricePercent', 'amountPercent'],
},
maxItems: 6,
description: 'Stop-loss groups. Effective for "buy" type in quick buy/sell and in copy trading sell settings. Up to 6 groups supported. "null" means disabled. If both "stopLossGroup" and "stopLossPercent" are set, "stopLossPercent" is ignored.'
},
trailingStopGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. In take-profit groups, it\'s the increase to sell at. In stop-loss groups, it\'s the decrease to sell at. In trailing stop-loss groups, it\'s the pullback ratio (cannot be >= 1).' },
amountPercent: { type: 'number', minimum: 0, maximum: 1, description: 'Sell ratio (0-1, 0.5 means 50%). E.g., for selling 50% at 100% gain and all at 200% gain, the sell ratios should be 0.5 and 1, not 0.5 and 0.5.' },
},
required: ['pricePercent', 'amountPercent'],
},
maxItems: 1,
description: 'Trailing stop-loss group. Effective for "buy" type in quick buy/sell, and when copy trading sell mode is "mixed" or "only_pnl". Currently only 1 group is supported. "null" means trailing stop-loss is disabled.'
},
pnlOrderExpireDelta: { type: 'number', minimum: 0, maximum: 432000000, default: 43200000, description: 'Expiration time for take-profit/stop-loss tasks, max value is 432,000,000 (ms).' },
pnlOrderExpireExecute: { type: 'boolean', default: false, description: '"true" means that if the take-profit/stop-loss task is not triggered within its validity period, it will be executed automatically at the end of the task.' },
pnlOrderUseMidPrice: { type: 'boolean', default: false, description: '"true" enables anti-wick mode, using the median price within 1 second as the trigger price. It will try its best but cannot 100% guarantee avoiding wicks.' },
sellMode: { type: 'string', enum: ['smart', 'normal'], default: 'smart', description: 'Sell method, effective for EVM chains. When sell income is lower than gas cost, "smart" means no selling, "normal" means continue selling.' },
migrateSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0, description: 'Open sell percentage (0.00-1.00), effective for Pump tokens, 0 means no auto-sell.' },
minDevSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 0.5, description: 'Trigger ratio (0-1). When Dev sells more than this ratio, your tokens will be sold.' },
devSellPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: 'When the follow Dev sell task is triggered, this is the percentage of your tokens to sell. 0 means do not create a follow Dev sell task.' },
customFeeAndTip: { type: 'boolean', default: false, description: '"true" means both priorityFee and jitoTip fields are effective, the system will execute the transaction with the specified values (null means auto priority fee/auto bribe), "false" means only priorityFee is effective in high-speed mode, and only jitoTip is effective in anti-sandwich mode, the system will allocate automatically' },
priorityFee: { type: 'string', default: '', description: 'Priority fee (SOL), effective for Solana, an empty string means use auto priority fee' },
gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: 'Additional gas (Gwei), effective for EVM chains' },
maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: 'No transaction will be made if base gas exceeds this value (Gwei), effective for EVM chains' },
jitoEnabled: { type: 'boolean', default: true, description: '"true" enables anti-sandwich mode (Solana & Ethereum & Bsc)' },
jitoTip: { type: 'number', minimum: 0, default: 0.001, description: 'Bribe fee for anti-sandwich mode (Solana)' },
maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: 'Maximum slippage (0.00-1.00). For buying, it is the difference between the actual and expected price. For selling, it is the difference between the expected and actual price. The difference multiple = 1/(1-slippage). 0.5 means accepting up to a 2x price difference, 1 means no limit.' },
concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: 'Number of concurrent nodes (1-3)' },
retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: 'Number of retries after failure (0-10)' },
},
},
},
required: ['name', 'targetIds', 'buySettings', 'sellSettings'],
},
},
{
name: 'edit_copy_trading',
description: `Edit a copy trading task. Note that you need to provide **the fields to be modified and the required fields, which include (id, enabled, name, chain, targetIds, buySettings, sellSettings)**. You don't need to re-enter all fields.
Request example:
{
"id": "xxx",
"enabled": true,
"chain": "solana",
"targetIds": [
"xxxxx"
],
"buySettings": {
"enabled": true,
"maxBuyAmountUI": "0.001"
},
"sellSettings": {
"enabled": true,
"mode": "mixed"
}
}
`,
inputSchema: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'Copy trading task ID',
},
enabled: {
type: 'boolean',
description: 'Task enabled status, true/false',
},
name: {
type: 'string',
description: 'Name of the copy trading task',
},
chain: {
type: 'string',
enum: ['solana', 'ethereum', 'base', 'bsc', 'tron'],
description: 'Chain (solana/ethereum/base/bsc/tron)',
},
dexFilter: {
type: 'array',
items: { type: 'string' },
description: 'DEXs to follow, null means all, specifying names means only follow trades on those DEXs, including: raydium_amm,raydium_clmm,raydium_cpmm,raydium_launchpad,meteora_dlmm,meteora_dyn,meteora_dyn2,meteora_bc,pump,pump_swap,moonshot,orca_wp,uniswap_v2,uniswap_v3,pancake_v2,pancake_v3,sunswap_v2,sunpump,ether_vista,okx_v2,fourmeme,boop',
},
targetIds: {
type: 'array',
items: { type: 'string' },
description: 'Wallet addresses to copy trade (up to 10)',
maxItems: 10,
minItems: 1,
},
tokenBlacklist: {
type: 'array',
items: { type: 'string' },
description: 'Blacklisted token addresses for the current task (up to 20), buying and selling of these tokens will be skipped',
maxItems: 20,
},
walletId: {
type: 'string',
description: 'ID of the wallet to use, obtainable via "Wallet Info API"',
},
groupId: {
type: 'string',
description: 'Group ID',
},
buySettings: {
type: 'object',
description: 'Buy-related settings',
properties: {
enabled: { type: 'boolean', default: true, description: 'Buy task enabled status' },
startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: 'Enable time for follow buy or sell (UTC). Follow buys or sells will only execute after this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: 'Disable time for follow buy or sell (UTC). Follow buys or sells will only execute before this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
buyAmountType: {
type: 'string',
enum: ['fixed_amount', 'fixed_ratio', 'follow_amount'],
default: 'follow_amount',
description: 'Copy buy type, "fixed_amount" for fixed amount, "fixed_ratio" for fixed ratio, "follow_amount" for follow amount'
},
maxBuyAmountUI: { type: 'string', description: 'Maximum buy amount for copy trading, minimum "0.001", "0.0001", "0.0001", "1"' },
buyRatio: { type: 'number', minimum: 0, maximum: 10, default: 1, description: 'Follow buy ratio (0-10), effective when buy type is fixed_ratio' },
maxBalanceUI: { type: 'number', minimum: 0, default: 100, description: 'Take-profit amount (ETH/SOL/BNB/TRX), no more copy buys when wallet balance exceeds this amount' },
reservedAmountUI: { type: 'number', minimum: 0, default: 0.01, description: 'Stop-loss amount (ETH/SOL/BNB/TRX), no more copy buys when wallet balance falls below this amount' },
targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: 'When in buy settings, it means only follow buy when smart money buy amount is greater than this value; when in sell settings, it means only follow sell when smart money sell income is greater than this value' },
targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: 'When in buy settings, it means only follow buy when smart money buy amount is less than this value; when in sell settings, it means only follow sell when smart money sell income is less than this value' },
minTokenMCUSD: { type: 'number', minimum: 0, default: 0, description: 'Minimum copy token market cap, only follow buy tokens with market cap higher than this value' },
maxTokenMCUSD: { type: 'number', minimum: 0, default: 999999999, description: 'Maximum copy token market cap, only follow buy tokens with market cap lower than this value' },
maxBuyTax: { type: 'number', minimum: 0, maximum: 1, description: 'Maximum token buy tax, effective for EVM chains, only follow buy tokens with tax rate lower than this value (data from GoPlus, may affect copy trading speed)' },
maxSellTax: { type: 'number', minimum: 0, maximum: 1, description: 'Maximum token sell tax, effective for EVM chains, only follow buy tokens with tax rate lower than this value (data from GoPlus, may affect copy trading speed)' },
customFeeAndTip: { type: 'boolean', default: false, description: '"true" means both priorityFee and jitoTip fields are effective, the system will execute the transaction with the specified values (null means auto priority fee/auto bribe), "false" means only priorityFee is effective in high-speed mode, and only jitoTip is effective in anti-sandwich mode, the system will allocate automatically' },
priorityFee: { type: 'string', default: '', description: 'Priority fee (SOL), effective for Solana, an empty string means use auto priority fee' },
gasFeeDelta: { type: 'number', minimum: 0, default: 5, description: 'Additional gas (Gwei), effective for EVM chains' },
maxFeePerGas: { type: 'number', minimum: 0, default: 100, description: 'No transaction will be made if base gas exceeds this value (Gwei), effective for EVM chains' },
jitoEnabled: { type: 'boolean', default: true, description: '"true" enables anti-sandwich mode (Solana & Ethereum & Bsc)' },
jitoTip: { type: 'number', minimum: 0, default: 0.001, description: 'Bribe fee for anti-sandwich mode (Solana)' },
maxSlippage: { type: 'number', minimum: 0, maximum: 1, default: 0.1, description: 'Maximum slippage (0.00-1.00). For buying, it is the difference between the actual and expected price. For selling, it is the difference between the expected and actual price. The difference multiple = 1/(1-slippage). 0.5 means accepting up to a 2x price difference, 1 means no limit.' },
skipFreezableToken: { type: 'boolean', default: false, description: '"true" means do not buy tokens with unrevoked freeze authority' },
skipMintableToken: { type: 'boolean', default: false, description: '"true" means do not buy tokens with unrevoked mint authority' },
skipDelegatedToken: { type: 'boolean', default: false, description: '"true" means do not buy delegated tokens' },
skipNotOpensource: { type: 'boolean', default: false, description: '"true" means do not buy tokens defined as not open-source by GoPlus, effective for EVM chains (enabling this may affect copy trading speed)' },
skipHoneyPot: { type: 'boolean', default: false, description: '"true" means do not buy tokens identified as honeypots by GoPlus, effective for EVM chains (enabling this may affect copy trading speed)' },
skipTargetIncreasePosition: { type: 'boolean', default: false, description: '"true" means do not buy tokens already held by the smart money address' },
minBurnedLp: { type: 'number', minimum: 0, maximum: 1, default: 0, description: 'Minimum LP burn ratio (0-1). Only follow buys for tokens with a liquidity burn ratio greater than or equal to this value. Supports Raydium (AMM) and Raydium (CPMM).' },
minLpUsd: { type: 'number', minimum: 0, default: 0, description: 'Minimum liquidity ($), only follow buy tokens with liquidity greater than or equal to this value' },
minTokenAgeMs: { type: 'number', minimum: 0, default: 0, description: 'Minimum token creation time (milliseconds), only follow buy tokens created at or after this time' },
maxTokenAgeMs: { type: 'number', minimum: 0, default: 999999999999, description: 'Maximum token creation time (milliseconds), only follow buy tokens created at or before this time' },
maxTopHoldPercent: { type: 'number', minimum: 0, maximum: 1, default: 1, description: 'Maximum top 10 holders percentage (0-1), only follow buy tokens where the top 10 holders have less than this percentage (effective for Solana)' },
maxBuyTimesPerToken: { type: 'number', minimum: 1, default: 999, description: 'Maximum number of buys for a token in this task within 7 days. No more buys will occur if this number is exceeded.' },
maxBuyAmountPerToken: { type: 'number', minimum: 0, default: 999999, description: 'Maximum buy amount for a token in this task within 7 days (in SOL / ETH / BNB / TRX). No more buys will occur if this amount is exceeded.' },
buyExist: { type: 'boolean', default: false, description: 'Whether to continue following buys for tokens already held' },
buyOncePerWallet: { type: 'boolean', default: false, description: '"true" means buy only once, "false" means no limit on the number of buys (only for tokens bought via DBot)' },
concurrentNodes: { type: 'number', minimum: 1, maximum: 3, default: 2, description: 'Number of concurrent nodes (1-3)' },
retries: { type: 'number', minimum: 0, maximum: 10, default: 1, description: 'Number of retries after failure (0-10)' },
},
},
sellSettings: {
type: 'object',
description: 'Sell-related settings',
properties: {
enabled: { type: 'boolean', default: true, description: 'Sell task enabled status' },
startHour: { type: 'number', minimum: 0, maximum: 23, default: 0, description: 'Enable time for follow buy or sell (UTC). Follow buys or sells will only execute after this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
endHour: { type: 'number', minimum: 0, maximum: 23, default: 23, description: 'Disable time for follow buy or sell (UTC). Follow buys or sells will only execute before this time each day. Must be an integer between 0-23, e.g., 10 means 10:00 UTC.' },
mode: {
type: 'string',
enum: ['mixed', 'only_copy', 'only_pnl'],
default: 'mixed',
description: 'Sell mode, "mixed" means both follow selling and take-profit/stop-loss are enabled, "only_copy" means only follow selling is enabled, "only_pnl" means only take-profit/stop-loss is enabled'
},
sellAmountType: {
type: 'string',
enum: ['all', 'follow_ratio', 'x_target_ratio'],
default: 'all',
description: 'Copy sell ratio, "all" for 100% sell, "follow_ratio" for sell by follow ratio, "x_target_ratio" for selling by multiplying smart money\'s sell ratio by a fixed multiplier'
},
xTargetRatio: { type: 'number', minimum: 0, maximum: 100, default: 1, description: 'Multiplier for smart money\'s sell ratio (0-100), e.g., if set to 0.5 and smart money sells 10%, you sell 10% * 0.5 = 5%; if set to 2, you sell 10% * 2 = 20%' },
sellSpeedType: {
type: 'string',
enum: ['fast', 'accurate'],
default: 'accurate',
description: 'Follow sell speed, invalid when mode is "only_pnl". Can be "fast" or "accurate". "fast" prioritizes speed but may cause inconsistent sell ratios with smart money. "accurate" prioritizes accuracy but may be slower.'
},
targetMinAmountUI: { type: 'number', minimum: 0, default: 0, description: 'When in buy settings, it means only follow buy when smart money buy amount is greater than this value; when in sell settings, it means only follow sell when smart money sell income is greater than this value' },
targetMaxAmountUI: { type: 'number', minimum: 0, default: 999999, description: 'When in buy settings, it means only follow buy when smart money buy amount is less than this value; when in sell settings, it means only follow sell when smart money sell income is less than this value' },
stopEarnPercent: { type: 'number', minimum: 0, description: 'Take-profit percentage (0.5 means 50%). Effective for "buy" type in quick buy/sell and in copy trading sell settings. Automatically sells when a token price increases by this percentage. "null" means take-profit is disabled.' },
stopLossPercent: { type: 'number', minimum: 0, description: 'Stop-loss percentage (0.5 means 50%). Effective for "buy" type in quick buy/sell and in copy trading sell settings. Automatically sells when a token price drops by this percentage. "null" means stop-loss is disabled.' },
stopEarnGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. In take-profit groups, it\'s the increase to sell at. In stop-loss groups, it\'s the decrease to sell at. In trailing stop-loss groups, it\'s the pullback ratio (cannot be >= 1).' },
amountPercent: { type: 'number', minimum: 0, maximum: 1, description: 'Sell ratio (0-1, 0.5 means 50%). E.g., for selling 50% at 100% gain and all at 200% gain, the sell ratios should be 0.5 and 1, not 0.5 and 0.5.' },
},
required: ['pricePercent', 'amountPercent'],
},
maxItems: 6,
description: 'Take-profit groups. Effective for "buy" type in quick buy/sell and in copy trading sell settings. Up to 6 groups supported. "null" means disabled. If both "stopEarnGroup" and "stopEarnPercent" are set, "stopEarnPercent" is ignored.'
},
stopLossGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. All values are positive. In take-profit groups, it\'s the increase to sell at. In stop-loss groups, it\'s the decrease to sell at. In trailing stop-loss groups, it\'s the pullback ratio (cannot be >= 1).' },
amountPercent: { type: 'number', minimum: 0, maximum: 1, description: 'Sell ratio (0-1, 0.5 means 50%). E.g., for selling 50% at 100% gain and all at 200% gain, the sell ratios should be 0.5 and 1, not 0.5 and 0.5.' },
},
required: ['pricePercent', 'amountPercent'],
},
maxItems: 6,
description: 'Stop-loss groups. Effective for "buy" type in quick buy/sell and in copy trading sell settings. Up to 6 groups supported. "null" means disabled. If both "stopLossGroup" and "stopLossPercent" are set, "stopLossPercent" is ignored.'
},
trailingStopGroup: {
type: 'array',
items: {
type: 'object',
properties: {
pricePercent: { type: 'number', minimum: 0, maximum: 1, description: 'Price change percentage (0.5 means 50%) or pullback ratio. All values are positive. In take-profit groups, it\'s