mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-07-27 16:57:44 +00:00
fix(strategy): add missing order_type/sub_order_type, condition_orders, and group_tag
- Add --order-type and --sub-order-type as required flags to order strategy create (server requires both; omitting them caused every create call to 400) - Remove --side from strategy create (field no longer exists in the API) - Make --open-price optional in strategy create (matches API spec) - Fix --gas-price in strategy create to convert gwei→wei (consistent with swap) - Add --condition-orders and --sell-ratio-type to swap command for take-profit/stop-loss conditions attached after a successful swap - Add --group-tag (LimitOrder/STMix) to order strategy list - Add --order-type to order strategy cancel - Add StrategyConditionOrder interface; extend SwapParams with condition_orders and sell_ratio_type; add order_type/sub_order_type to StrategyCreateParams; remove side; add order_type to StrategyCancelParams - Update docs/cli-usage.md: fix strategy create table, add chain fee requirement notes (SOL requires priority_fee+tip_fee; BSC requires gas_price), add condition_orders example and strategy_order_id response field, add TRADING_BOT_UNAVAILABLE error code Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+33
-10
@@ -400,6 +400,8 @@ npx gmgn-cli swap \
|
||||
[--gas-price <gwei>] \
|
||||
[--max-fee-per-gas <amount>] \
|
||||
[--max-priority-fee-per-gas <amount>] \
|
||||
[--condition-orders <json>] \
|
||||
[--sell-ratio-type <buy_amount|hold_amount>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
@@ -421,6 +423,16 @@ npx gmgn-cli swap \
|
||||
| `--gas-price` | No | Gas price in gwei (BSC ≥ 0.05 gwei / BASE/ETH ≥ 0.01 gwei) |
|
||||
| `--max-fee-per-gas` | No | EIP-1559 max fee per gas (Base/ETH only) |
|
||||
| `--max-priority-fee-per-gas` | No | EIP-1559 max priority fee per gas (Base/ETH only) |
|
||||
| `--condition-orders` | No | JSON array of take-profit/stop-loss conditions attached after a successful swap (see example below); only `profit_stop` and `loss_stop` are supported |
|
||||
| `--sell-ratio-type` | No | Sell ratio base for `--condition-orders`: `buy_amount` (default) / `hold_amount` |
|
||||
|
||||
**`--condition-orders` example** (100% sell at 2× price, 100% sell at 50% price):
|
||||
|
||||
```json
|
||||
[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]
|
||||
```
|
||||
|
||||
> Strategy creation is **best-effort**: if the swap succeeds but strategy creation fails, the swap result is still returned (with `strategy_order_id` absent). Only `order_type`, `side`, `price_scale`, and `sell_ratio` are accepted per condition — extra fields cause a 400 error.
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
@@ -439,6 +451,7 @@ npx gmgn-cli swap \
|
||||
| `output_token` | string | Output token contract address |
|
||||
| `filled_input_amount` | string | Actual input consumed (smallest unit); empty if not filled |
|
||||
| `filled_output_amount` | string | Actual output received (smallest unit); empty if not filled |
|
||||
| `strategy_order_id` | string | Strategy order ID; only present when `--condition-orders` was passed and strategy creation succeeded |
|
||||
|
||||
---
|
||||
|
||||
@@ -467,9 +480,10 @@ gmgn-cli order strategy create \
|
||||
--from <wallet_address> \
|
||||
--base-token <base_token_address> \
|
||||
--quote-token <quote_token_address> \
|
||||
--side <buy|sell> \
|
||||
--open-price <price> \
|
||||
--order-type <limit_order> \
|
||||
--sub-order-type <buy_low|buy_high|stop_loss|take_profit> \
|
||||
--check-price <price> \
|
||||
[--open-price <price>] \
|
||||
[--amount-in <amount> | --amount-in-percent <pct>] \
|
||||
[--slippage <n> | --auto-slippage] \
|
||||
[--limit-price-mode <exact|slippage>] \
|
||||
@@ -477,7 +491,7 @@ gmgn-cli order strategy create \
|
||||
[--sell-ratio-type <buy_amount|hold_amount>] \
|
||||
[--priority-fee <sol>] \
|
||||
[--tip-fee <amount>] \
|
||||
[--gas-price <amount>] \
|
||||
[--gas-price <gwei>] \
|
||||
[--anti-mev] \
|
||||
[--raw]
|
||||
```
|
||||
@@ -488,9 +502,10 @@ gmgn-cli order strategy create \
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--base-token` | Yes | Base token contract address |
|
||||
| `--quote-token` | Yes | Quote token contract address |
|
||||
| `--side` | Yes | `buy` / `sell` |
|
||||
| `--open-price` | Yes | Open price |
|
||||
| `--order-type` | Yes | Order type: `limit_order` |
|
||||
| `--sub-order-type` | Yes | Sub-order type: `buy_low` / `buy_high` / `stop_loss` / `take_profit` |
|
||||
| `--check-price` | Yes | Trigger check price |
|
||||
| `--open-price` | No | Open/entry price |
|
||||
| `--amount-in` | No* | Input amount (smallest unit); required unless `--amount-in-percent` is used |
|
||||
| `--amount-in-percent` | No* | Input as percentage (e.g. `50` = 50%); required unless `--amount-in` is used |
|
||||
| `--limit-price-mode` | No | `exact` / `slippage` (default: `slippage`) |
|
||||
@@ -498,11 +513,16 @@ gmgn-cli order strategy create \
|
||||
| `--sell-ratio-type` | No | `buy_amount` (default) / `hold_amount` |
|
||||
| `--slippage` | No | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--auto-slippage` | No | Enable automatic slippage |
|
||||
| `--priority-fee` | No | Priority fee in SOL (SOL only) |
|
||||
| `--tip-fee` | No | Tip fee |
|
||||
| `--gas-price` | No | Gas price in wei (EVM chains) |
|
||||
| `--priority-fee` | No | Priority fee in SOL (**required for SOL chain**) |
|
||||
| `--tip-fee` | No | Tip fee (**required for SOL chain**) |
|
||||
| `--gas-price` | No | Gas price in gwei (**required for BSC**; ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection |
|
||||
|
||||
> **Chain-specific fee requirements:**
|
||||
> - **SOL:** `--priority-fee` and `--tip-fee` are both **required** (returns 400 if missing)
|
||||
> - **BSC:** `--gas-price` is **required** (returns 400 if missing)
|
||||
> - **ETH/BASE:** no required fee fields
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
| Field | Type | Description |
|
||||
@@ -517,7 +537,7 @@ gmgn-cli order strategy create \
|
||||
List strategy orders. Uses normal auth.
|
||||
|
||||
```bash
|
||||
gmgn-cli order strategy list --chain <chain> [--type <open|history>] [--from <address>] [--base-token <address>] [--page-token <token>] [--limit <n>] [--raw]
|
||||
gmgn-cli order strategy list --chain <chain> [--type <open|history>] [--from <address>] [--group-tag <tag>] [--base-token <address>] [--page-token <token>] [--limit <n>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
@@ -525,6 +545,7 @@ gmgn-cli order strategy list --chain <chain> [--type <open|history>] [--from <ad
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--type` | No | `open` (default) / `history` |
|
||||
| `--from` | No | Filter by wallet address |
|
||||
| `--group-tag` | No | Filter by group: `LimitOrder` / `STMix` |
|
||||
| `--base-token` | No | Filter by token address |
|
||||
| `--page-token` | No | Pagination cursor from previous response |
|
||||
| `--limit` | No | Results per page |
|
||||
@@ -544,7 +565,7 @@ gmgn-cli order strategy list --chain <chain> [--type <open|history>] [--from <ad
|
||||
Cancel a strategy order. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli order strategy cancel --chain <chain> --from <wallet_address> --order-id <id> [--close-sell-model <model>] [--raw]
|
||||
gmgn-cli order strategy cancel --chain <chain> --from <wallet_address> --order-id <id> [--order-type <type>] [--close-sell-model <model>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
@@ -552,6 +573,7 @@ gmgn-cli order strategy cancel --chain <chain> --from <wallet_address> --order-i
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--order-id` | Yes | Order ID to cancel |
|
||||
| `--order-type` | No | Order type: `limit_order` / `smart_trade` |
|
||||
| `--close-sell-model` | No | Sell model when closing |
|
||||
|
||||
---
|
||||
@@ -662,4 +684,5 @@ Important notes:
|
||||
| `BAD_REQUEST` | 400 | Missing or invalid request parameters |
|
||||
| `INTERNAL_API_UNAVAILABLE` | 502 | Downstream market API unavailable |
|
||||
| `BROKER_UNAVAILABLE` | 502 | Downstream trade broker unavailable |
|
||||
| `TRADING_BOT_UNAVAILABLE` | 502 | Trading bot service unreachable (strategy endpoints) |
|
||||
| `INTERNAL_ERROR` | 500 | Internal server error |
|
||||
|
||||
@@ -85,6 +85,15 @@ export interface SwapParams {
|
||||
gas_price?: string;
|
||||
max_fee_per_gas?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
condition_orders?: StrategyConditionOrder[];
|
||||
sell_ratio_type?: string;
|
||||
}
|
||||
|
||||
export interface StrategyConditionOrder {
|
||||
order_type: string; // "profit_stop" | "loss_stop"
|
||||
side: string; // "sell"
|
||||
price_scale: string;
|
||||
sell_ratio: string;
|
||||
}
|
||||
|
||||
export interface StrategyCreateParams {
|
||||
@@ -92,9 +101,10 @@ export interface StrategyCreateParams {
|
||||
from_address: string;
|
||||
base_token: string;
|
||||
quote_token: string;
|
||||
side: string;
|
||||
open_price: string;
|
||||
order_type: string;
|
||||
sub_order_type: string;
|
||||
check_price: string;
|
||||
open_price?: string;
|
||||
amount_in?: string;
|
||||
amount_in_percent?: string;
|
||||
limit_price_mode?: string;
|
||||
@@ -118,6 +128,7 @@ export interface StrategyCancelParams {
|
||||
chain: string;
|
||||
from_address: string;
|
||||
order_id: string;
|
||||
order_type?: string;
|
||||
close_sell_model?: string;
|
||||
}
|
||||
|
||||
|
||||
+25
-8
@@ -24,6 +24,8 @@ export function registerSwapCommands(program: Command): void {
|
||||
.option("--gas-price <gwei>", "Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01)")
|
||||
.option("--max-fee-per-gas <amount>", "EIP-1559 max fee per gas (Base)")
|
||||
.option("--max-priority-fee-per-gas <amount>", "EIP-1559 max priority fee per gas (Base)")
|
||||
.option("--condition-orders <json>", 'JSON array of take-profit/stop-loss conditions, e.g. \'[{"order_type":"profit_stop","side":"sell","price_scale":"150","sell_ratio":"100"}]\'')
|
||||
.option("--sell-ratio-type <type>", "Sell ratio base: buy_amount (default) / hold_amount; only used with --condition-orders")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (opts.percent == null && !opts.amount) {
|
||||
@@ -54,6 +56,15 @@ export function registerSwapCommands(program: Command): void {
|
||||
if (opts.gasPrice) params.gas_price = String(Math.round(parseFloat(opts.gasPrice) * 1e9));
|
||||
if (opts.maxFeePerGas) params.max_fee_per_gas = opts.maxFeePerGas;
|
||||
if (opts.maxPriorityFeePerGas) params.max_priority_fee_per_gas = opts.maxPriorityFeePerGas;
|
||||
if (opts.conditionOrders) {
|
||||
try {
|
||||
params.condition_orders = JSON.parse(opts.conditionOrders);
|
||||
} catch {
|
||||
console.error("[gmgn-cli] --condition-orders must be valid JSON");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
if (opts.sellRatioType) params.sell_ratio_type = opts.sellRatioType;
|
||||
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.swap(params).catch(exitOnError);
|
||||
@@ -107,9 +118,10 @@ export function registerSwapCommands(program: Command): void {
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--base-token <address>", "Base token contract address")
|
||||
.requiredOption("--quote-token <address>", "Quote token contract address")
|
||||
.requiredOption("--side <side>", "Direction: buy / sell")
|
||||
.requiredOption("--open-price <price>", "Open price")
|
||||
.requiredOption("--order-type <type>", "Order type: limit_order")
|
||||
.requiredOption("--sub-order-type <type>", "Sub-order type: buy_low / buy_high / stop_loss / take_profit")
|
||||
.requiredOption("--check-price <price>", "Trigger check price")
|
||||
.option("--open-price <price>", "Open/entry price")
|
||||
.option("--amount-in <amount>", "Input amount (smallest unit)")
|
||||
.option("--amount-in-percent <pct>", "Input amount as a percentage (e.g. 50 = 50%)")
|
||||
.option("--limit-price-mode <mode>", "Price mode: exact / slippage (default: slippage)")
|
||||
@@ -117,9 +129,9 @@ export function registerSwapCommands(program: Command): void {
|
||||
.option("--sell-ratio-type <type>", "Sell ratio basis: buy_amount (default) / hold_amount")
|
||||
.option("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--auto-slippage", "Enable automatic slippage")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (SOL only)")
|
||||
.option("--tip-fee <amount>", "Tip fee")
|
||||
.option("--gas-price <amount>", "Gas price in wei (EVM chains)")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (required for SOL chain)")
|
||||
.option("--tip-fee <amount>", "Tip fee (required for SOL chain)")
|
||||
.option("--gas-price <gwei>", "Gas price in gwei (required for BSC; ≥ 0.05 gwei / BASE/ETH ≥ 0.01 gwei)")
|
||||
.option("--anti-mev", "Enable anti-MEV protection")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -137,10 +149,11 @@ export function registerSwapCommands(program: Command): void {
|
||||
from_address: opts.from,
|
||||
base_token: opts.baseToken,
|
||||
quote_token: opts.quoteToken,
|
||||
side: opts.side,
|
||||
open_price: opts.openPrice,
|
||||
order_type: opts.orderType,
|
||||
sub_order_type: opts.subOrderType,
|
||||
check_price: opts.checkPrice,
|
||||
};
|
||||
if (opts.openPrice) params.open_price = opts.openPrice;
|
||||
if (opts.amountIn) params.amount_in = opts.amountIn;
|
||||
if (opts.amountInPercent) params.amount_in_percent = opts.amountInPercent;
|
||||
if (opts.limitPriceMode) params.limit_price_mode = opts.limitPriceMode;
|
||||
@@ -150,7 +163,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
if (opts.autoSlippage) params.auto_slippage = true;
|
||||
if (opts.priorityFee) params.priority_fee = opts.priorityFee;
|
||||
if (opts.tipFee) params.tip_fee = opts.tipFee;
|
||||
if (opts.gasPrice) params.gas_price = opts.gasPrice;
|
||||
if (opts.gasPrice) params.gas_price = String(Math.round(parseFloat(opts.gasPrice) * 1e9));
|
||||
if (opts.antiMev) params.is_anti_mev = true;
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.createStrategyOrder(params).catch(exitOnError);
|
||||
@@ -163,6 +176,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.option("--type <type>", "open (default) / history")
|
||||
.option("--from <address>", "Filter by wallet address")
|
||||
.option("--group-tag <tag>", "Filter by group: LimitOrder / STMix")
|
||||
.option("--base-token <address>", "Filter by token address")
|
||||
.option("--page-token <token>", "Pagination cursor from previous response")
|
||||
.option("--limit <n>", "Results per page", parseInt)
|
||||
@@ -172,6 +186,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
const extra: Record<string, string | number> = {};
|
||||
if (opts.type) extra["type"] = opts.type;
|
||||
if (opts.from) extra["from_address"] = opts.from;
|
||||
if (opts.groupTag) extra["group_tag"] = opts.groupTag;
|
||||
if (opts.baseToken) extra["base_token"] = opts.baseToken;
|
||||
if (opts.pageToken) extra["page_token"] = opts.pageToken;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
@@ -186,6 +201,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--order-id <id>", "Order ID to cancel")
|
||||
.option("--order-type <type>", "Order type: limit_order / smart_trade")
|
||||
.option("--close-sell-model <model>", "Sell model when closing")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -195,6 +211,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
from_address: opts.from,
|
||||
order_id: opts.orderId,
|
||||
};
|
||||
if (opts.orderType) params.order_type = opts.orderType;
|
||||
if (opts.closeSellModel) params.close_sell_model = opts.closeSellModel;
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.cancelStrategyOrder(params).catch(exitOnError);
|
||||
|
||||
Reference in New Issue
Block a user