mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-07-27 16:57:44 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d51f1c49d3 | |||
| f05e1d5d20 | |||
| 317c7d982b | |||
| 15872373cd | |||
| 674c7032a8 | |||
| 4649a7a287 | |||
| 2b33ee666c | |||
| 123bdba738 | |||
| 1d03fb1672 | |||
| 6f79600869 | |||
| 12ab55bb63 | |||
| aa09490a9b | |||
| 2b6c220581 | |||
| e181cba142 |
@@ -557,7 +557,7 @@ gmgn-cli order quote \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# Quotes use critical auth and require GMGN_PRIVATE_KEY on every chain
|
||||
# Quotes use signed auth and require GMGN_PRIVATE_KEY on every chain
|
||||
gmgn-cli order quote \
|
||||
--chain bsc \
|
||||
--from <wallet-address> \
|
||||
@@ -579,7 +579,7 @@ gmgn-cli multi-swap \
|
||||
--slippage 0.01
|
||||
```
|
||||
|
||||
> `order quote` uses critical auth on `sol` / `bsc` / `base` / `eth` and requires `GMGN_PRIVATE_KEY`.
|
||||
> `order quote` uses signed auth on `sol` / `bsc` / `base` / `eth` and requires `GMGN_PRIVATE_KEY`.
|
||||
|
||||
### Swap with Take-Profit / Stop-Loss Orders (requires private key)
|
||||
|
||||
|
||||
+8
-8
@@ -351,7 +351,7 @@ gmgn-cli market signal --chain sol --groups '<json_array>' [--raw]
|
||||
|
||||
## portfolio follow-wallet
|
||||
|
||||
Query follow-wallet trade records. Returns trades from wallets you personally follow on the GMGN platform. The follow list is resolved automatically from the GMGN user account bound to the API Key — `--wallet` is optional. Normal auth (API Key only, no private key needed).
|
||||
Query follow-wallet trade records. Returns trades from wallets you personally follow on the GMGN platform. The follow list is resolved automatically from the GMGN user account bound to the API Key — `--wallet` is optional. Signed auth (API Key + private key signature).
|
||||
|
||||
```bash
|
||||
gmgn-cli track follow-wallet \
|
||||
@@ -411,7 +411,7 @@ gmgn-cli track smartmoney [--chain <chain>] [--limit <n>] [--side <side>] [--raw
|
||||
|
||||
## order quote
|
||||
|
||||
Get a swap quote without submitting a transaction. All supported quote chains use critical auth and require `GMGN_PRIVATE_KEY`.
|
||||
Get a swap quote without submitting a transaction. All supported quote chains use signed auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
npx gmgn-cli order quote \
|
||||
@@ -487,11 +487,11 @@ npx gmgn-cli swap \
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB) |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — delegates fee selection to the trading bot for `--condition-orders` strategy |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas |
|
||||
| `--condition-orders` | No | all | JSON array of take-profit/stop-loss conditions attached after a successful swap (see example below) |
|
||||
| `--sell-ratio-type` | No | all | Sell ratio base for `--condition-orders`: `buy_amount` (default) / `hold_amount` |
|
||||
| `--sell-ratio-type` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount` |
|
||||
|
||||
**`--condition-orders` example** (100% sell at 2× price, 100% sell at 50% price):
|
||||
|
||||
@@ -564,11 +564,11 @@ gmgn-cli multi-swap \
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB) |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — delegates fee selection to the trading bot for `--condition-orders` strategy |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas |
|
||||
| `--condition-orders` | No | all | JSON array of take-profit/stop-loss conditions, attached to each successful wallet's swap (best-effort) |
|
||||
| `--sell-ratio-type` | No | all | Sell ratio base: `buy_amount` (default) / `hold_amount` |
|
||||
| `--sell-ratio-type` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount` |
|
||||
|
||||
**Response fields (data):** Array of per-wallet results:
|
||||
|
||||
@@ -801,7 +801,7 @@ Important notes:
|
||||
| `AUTH_SIGNATURE_INVALID` | 401 | Signature verification failed |
|
||||
| `AUTH_TIMESTAMP_EXPIRED` | 401 | Timestamp is outside the valid window (±5s) |
|
||||
| `AUTH_CLIENT_ID_REPLAYED` | 401 | client_id replayed within 7s |
|
||||
| `AUTH_REPLAY_CHECK_UNAVAILABLE` | 503 | Anti-replay Redis unavailable (critical auth only) |
|
||||
| `AUTH_REPLAY_CHECK_UNAVAILABLE` | 503 | Anti-replay Redis unavailable (signed auth only) |
|
||||
| `RATE_LIMIT_EXCEEDED` | 429 | Rate limit exceeded |
|
||||
| `RATE_LIMIT_BANNED` | 429 | Temporarily banned due to repeated rate limit violations |
|
||||
| `ERROR_RATE_LIMIT_BLOCKED` | 429 | Temporarily blocked after repeated business errors on `swap` |
|
||||
@@ -810,5 +810,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) |
|
||||
| `TRADING_BOT_UNAVAILABLE` | 502 | Strategy order service temporarily unreachable |
|
||||
| `INTERNAL_ERROR` | 500 | Internal server error |
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.9",
|
||||
"version": "1.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.9",
|
||||
"version": "1.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^12.1.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.9",
|
||||
"version": "1.3.0",
|
||||
"description": "GMGN OpenAPI CLI — call GMGN market, token, portfolio and swap APIs from the command line",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -26,7 +26,7 @@ Use the `gmgn-cli` tool to create a token on a launchpad platform or query token
|
||||
|
||||
- **Status polling via `order get`** — `cooking create` is asynchronous. The immediate response may show `pending`. Poll with `gmgn-cli order get --chain <chain> --order-id <order_id>` until `confirmed`. The new token's contract address is in the `output_token` field of the `order get` response, not in the initial create response.
|
||||
|
||||
- **Critical auth** — `cooking create` requires both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing. `cooking stats` uses normal auth (API Key only).
|
||||
- **Signed auth** — `cooking create` requires both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing. `cooking stats` uses exist auth (API Key only).
|
||||
|
||||
- **Slippage** — The initial buy is executed as part of the same transaction as token creation. Slippage applies to that buy. Use `--slippage` (decimal, e.g. `0.01` = 1%) or `--auto-slippage`. One of the two is required when `--buy-amt` is set.
|
||||
|
||||
@@ -43,8 +43,8 @@ Use the `gmgn-cli` tool to create a token on a launchpad platform or query token
|
||||
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `cooking stats` | Get token creation count statistics grouped by launchpad platform (normal auth) |
|
||||
| `cooking create` | Deploy a new token on a launchpad platform (requires private key) |
|
||||
| `cooking stats` | Get token creation count statistics grouped by launchpad platform (exist auth) |
|
||||
| `cooking create` | Deploy a new token on a launchpad platform (signed auth) |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
@@ -74,7 +74,7 @@ If a local `.env` exists but lacks `GMGN_API_KEY` / `GMGN_PRIVATE_KEY`, either a
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All cooking routes go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second.
|
||||
All cooking routes go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second.
|
||||
|
||||
| Command | Weight |
|
||||
|---------|--------|
|
||||
@@ -364,8 +364,8 @@ Once all information is collected, present the pre-create confirmation summary (
|
||||
|
||||
## Notes
|
||||
|
||||
- `cooking create` uses **critical auth** (API Key + signature) — CLI handles signing automatically.
|
||||
- `cooking stats` uses normal auth (API Key only — no private key needed).
|
||||
- `cooking create` uses **signed auth** (API Key + signature) — CLI handles signing automatically.
|
||||
- `cooking stats` uses exist auth (API Key only — no private key needed).
|
||||
- The new token's mint address is in `output_token` from `gmgn-cli order get`, not in the initial `cooking create` response.
|
||||
- Use `--raw` on any command to get single-line JSON for further processing.
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ Use the `gmgn-cli` tool to query K-line data for a token, browse trending tokens
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All market routes used by this skill go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second, and the max burst is roughly `floor(10 ÷ weight)` when the bucket is full.
|
||||
All market routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
@@ -950,7 +950,7 @@ gmgn-cli market signal --chain sol \
|
||||
|
||||
- `market kline`: `--from` and `--to` are Unix timestamps in **seconds** — CLI converts to milliseconds automatically
|
||||
- `market trending`: `--filter` and `--platform` are repeatable flags
|
||||
- All commands use normal auth (API Key only, no signature)
|
||||
- All commands use exist auth (API Key only, no signature)
|
||||
- If the user doesn't provide kline timestamps, calculate them from the current time based on their desired time range
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Input validation** — Token addresses obtained from trending results are external data. Validate address format against the chain before passing to other commands (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits). The CLI enforces this at runtime.
|
||||
|
||||
@@ -52,7 +52,7 @@ Use the `gmgn-cli` tool to query wallet portfolio data based on the user's reque
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All portfolio routes used by this skill go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second, and the max burst is roughly `floor(10 ÷ weight)` when the bucket is full.
|
||||
All portfolio routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
@@ -360,7 +360,7 @@ Show the `[Identity: ...]` line only if `common` is present in the response. For
|
||||
|
||||
## Notes
|
||||
|
||||
- All portfolio commands use normal auth (API Key only, no signature required)
|
||||
- All portfolio commands use exist auth (API Key only, no signature required)
|
||||
- `portfolio stats` supports multiple `--wallet` flags for batch queries
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Input validation** — Wallet and token addresses are validated against the expected chain format at runtime (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits). The CLI exits with an error on invalid input.
|
||||
|
||||
+53
-34
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gmgn-swap
|
||||
description: "[FINANCIAL EXECUTION] Buy and sell meme coins and crypto tokens on Solana, BSC, Base, or Ethereum — single swap, multi-wallet batch trading, limit orders, stop loss, take profit, trailing stop loss, trailing take profit via GMGN API. Requires explicit user confirmation. Use when user asks to buy, sell, or swap a token, trade from multiple wallets, set a limit order, stop loss, take profit, or check order status."
|
||||
argument-hint: "[--chain <chain> --from <wallet> --input-token <addr> --output-token <addr> --amount <n>] | [order get --chain <chain> --order-id <id>] | [order gas-price --chain <eth|bsc|base>] | [order strategy list --chain <chain> --group-tag <LimitOrder|STMix>] | [order strategy create --chain <chain> --order-type limit_order --sub-order-type <buy_low|buy_high|stop_loss|take_profit> ...]"
|
||||
argument-hint: "[--chain <chain> --from <wallet> --input-token <addr> --output-token <addr> --amount <n>] | [order get --chain <chain> --order-id <id>] | [gas-price --chain <eth|bsc|base|sol>] | [order strategy list --chain <chain> --group-tag <LimitOrder|STMix>] | [order strategy create --chain <chain> --order-type limit_order --sub-order-type <buy_low|buy_high|stop_loss|take_profit> ...]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli swap --help"
|
||||
---
|
||||
@@ -24,9 +24,9 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. `GMGN
|
||||
|
||||
- **Currency tokens** — Each chain has designated currency tokens (SOL, BNB, ETH, USDC). These are the base assets used to buy other tokens or receive swap proceeds. Their contract addresses are fixed — look them up in the Chain Currencies table, never guess them.
|
||||
|
||||
- **Anti-MEV** — MEV (Miner/Maximal Extractable Value) refers to frontrunning and sandwich attacks where bots exploit pending transactions. `--anti-mev` routes the transaction through protected channels to reduce this risk. **Recommended: always enable.** Default: on.
|
||||
- **Anti-MEV** — MEV (Miner/Maximal Extractable Value) refers to frontrunning and sandwich attacks where bots exploit pending transactions. `--anti-mev` routes the transaction through protected channels to reduce this risk. **Recommended: always enable.** Default: on. **Not supported on `base` chain.**
|
||||
|
||||
- **Critical auth** — `swap` and all `order` subcommands require both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing and sends only the resulting signature.
|
||||
- **Signed auth** — `swap` and all `order` subcommands require both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing and sends only the resulting signature.
|
||||
|
||||
- **`order_id` / `status`** — After submitting a swap, the response includes an `order_id`. Use `order get --order-id` to poll for final status. Possible values: `pending` → `processed` → `confirmed` (success) or `failed` / `expired`. Do not report success until status is `confirmed`.
|
||||
|
||||
@@ -47,9 +47,9 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. `GMGN
|
||||
|-------------|-------------|
|
||||
| `swap` | Submit a token swap |
|
||||
| `multi-swap` | Submit token swaps across multiple wallets concurrently (up to 100) |
|
||||
| `order quote` | Get a swap quote (no transaction submitted; requires critical auth) |
|
||||
| `order quote` | Get a swap quote (no transaction submitted; requires signed auth) |
|
||||
| `order get` | Query order status |
|
||||
| `order gas-price` | Query recommended EVM gas price (low / average / high tiers); normal auth |
|
||||
| `gas-price` | Query recommended gas price (low / average / high tiers) for any chain; exist auth (API Key only) |
|
||||
| `order strategy create` | Create a limit/strategy order (requires private key) |
|
||||
| `order strategy list` | List strategy orders (requires private key) |
|
||||
| `order strategy cancel` | Cancel a strategy order (requires private key) |
|
||||
@@ -80,7 +80,7 @@ Currency tokens are the base/native assets of each chain. They are used to buy o
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All swap-related routes used by this skill go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second, and the max burst is roughly `floor(10 ÷ weight)` when the bucket is full.
|
||||
All swap-related routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
@@ -88,7 +88,7 @@ All swap-related routes used by this skill go through GMGN's leaky-bucket limite
|
||||
| `multi-swap` | `POST /v1/trade/multi_swap` | 5 |
|
||||
| `order quote` | `GET /v1/trade/quote` | 2 |
|
||||
| `order get` | `GET /v1/trade/query_order` | 1 |
|
||||
| `order gas-price` | `GET /v1/trade/gas_price` | 1 |
|
||||
| `gas-price` | `GET /v1/trade/gas_price` | 1 |
|
||||
|
||||
When a request returns `429`:
|
||||
|
||||
@@ -184,16 +184,16 @@ gmgn-cli swap \
|
||||
| `--slippage <n>` | No | all | Slippage tolerance, e.g. `0.01` = 1%. **Mutually exclusive with `--auto-slippage`** — use one or the other. |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage. **Mutually exclusive with `--slippage`.** |
|
||||
| `--min-output <n>` | No | all | Minimum output amount |
|
||||
| `--anti-mev` | No | all | Enable anti-MEV protection — **recommended**; protects against frontrunning and sandwich attacks. Default: on |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection — **recommended**; protects against frontrunning and sandwich attacks. Default: on. **Not supported on `base`.** |
|
||||
| `--priority-fee <sol>` | No | `sol` | Priority fee in SOL (≥ 0.00001). Required when using `--condition-orders` on SOL. |
|
||||
| `--tip-fee <n>` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). Required when using `--condition-orders` on SOL. |
|
||||
| `--gas-price <gwei>` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). Required when using `--condition-orders` on BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level <level>` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — delegates fee selection to the trading bot for `--condition-orders` strategy. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas <n>` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. Defaults to `--gas-price` if omitted (BASE/ETH). |
|
||||
| `--max-priority-fee-per-gas <n>` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--condition-orders <json>` | No | all | JSON array of condition sub-orders (take-profit / stop-loss) to attach after a successful swap. **Max 10 sub-orders.** Strategy creation is best-effort: if the swap succeeds but strategy creation fails, the swap result is still returned. See ConditionOrder fields below. |
|
||||
| `--sell-ratio-type <type>` | No | all | Sell ratio basis for `--condition-orders`: `buy_amount` (default) — when triggered, sells a fixed token amount stored at strategy creation time; `hold_amount` — when triggered, sells a fixed percentage of the position held at trigger time |
|
||||
| `--sell-ratio-type <type>` | No | all | **Only with `--condition-orders`.** Sell ratio basis: `buy_amount` (default) — sells a fixed token amount stored at strategy creation time; `hold_amount` — sells a fixed percentage of the position held at trigger time |
|
||||
|
||||
### ConditionOrder Fields (for `--condition-orders`)
|
||||
|
||||
@@ -291,7 +291,7 @@ gmgn-cli swap \
|
||||
|
||||
### Pre-swap Confirmation
|
||||
|
||||
Before displaying the confirmation, run `order quote` to get the estimated output (requires critical auth and `GMGN_PRIVATE_KEY` on every supported quote chain):
|
||||
Before displaying the confirmation, run `order quote` to get the estimated output (requires signed auth and `GMGN_PRIVATE_KEY` on every supported quote chain):
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
@@ -402,16 +402,16 @@ gmgn-cli multi-swap \
|
||||
| `--output-amount` | No* | all | JSON map of `wallet_address → target output amount` (smallest unit). |
|
||||
| `--slippage <n>` | No | all | Slippage tolerance, e.g. `0.01` = 1%. Mutually exclusive with `--auto-slippage`. |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage. |
|
||||
| `--anti-mev` | No | all | Enable anti-MEV protection. |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection. Not supported on `base`. |
|
||||
| `--priority-fee <sol>` | No | `sol` | Priority fee in SOL (≥ 0.00001). Required when using `--condition-orders` on SOL. |
|
||||
| `--tip-fee <amount>` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). Required when using `--condition-orders` on SOL. |
|
||||
| `--gas-price <gwei>` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). Required when using `--condition-orders` on BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level <level>` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — delegates fee selection to the trading bot for `--condition-orders` strategy. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas <amount>` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. Defaults to `--gas-price` if omitted (BASE/ETH). |
|
||||
| `--max-priority-fee-per-gas <amount>` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--condition-orders <json>` | No | all | JSON array of condition sub-orders (take-profit / stop-loss) attached to each successful wallet's swap. Same structure as `swap --condition-orders`. Strategy creation is best-effort per wallet. |
|
||||
| `--sell-ratio-type <type>` | No | all | Sell ratio base for `--condition-orders`: `buy_amount` (default) / `hold_amount`. |
|
||||
| `--sell-ratio-type <type>` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount`. |
|
||||
|
||||
## `multi-swap` Response Fields
|
||||
|
||||
@@ -430,7 +430,7 @@ The response `data` is an array — one element per wallet:
|
||||
|
||||
## `order quote` Usage
|
||||
|
||||
Get an estimated output amount before submitting a swap. All supported quote chains use critical auth and require `GMGN_PRIVATE_KEY`.
|
||||
Get an estimated output amount before submitting a swap. All supported quote chains use signed auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
@@ -465,25 +465,44 @@ Response fields are shared with `swap` — see [`swap` / `order get` Response Fi
|
||||
|
||||
---
|
||||
|
||||
## `order gas-price` Usage
|
||||
## `gas-price` Usage
|
||||
|
||||
Query recommended EVM gas price tiers. Uses normal auth (API Key only — no private key required).
|
||||
Query recommended gas price tiers for any chain. API Key only — no signature or private key required.
|
||||
|
||||
```bash
|
||||
gmgn-cli order gas-price --chain eth
|
||||
gmgn-cli order gas-price --chain bsc
|
||||
gmgn-cli order gas-price --chain base
|
||||
gmgn-cli gas-price --chain eth
|
||||
gmgn-cli gas-price --chain bsc
|
||||
gmgn-cli gas-price --chain base
|
||||
gmgn-cli gas-price --chain sol
|
||||
```
|
||||
|
||||
### `order gas-price` Response Fields
|
||||
### `gas-price` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------ | ---- |
|
||||
| `chain` | string | Chain identifier |
|
||||
| `suggest_base_fee` | string | Suggested base fee (gwei) |
|
||||
| `low` | string | Low-priority gas price (gwei) |
|
||||
| `average` | string | Average-priority gas price (gwei) |
|
||||
| `high` | string | High-priority gas price (gwei) |
|
||||
All fields are omitempty — fields unsupported by a chain are omitted. Units are chain-native (wei for EVM chains; lamports / chain-native for SOL).
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | ------- | ----------- |
|
||||
| `chain` | string | Chain identifier |
|
||||
| `auto` | string | Automatic gas price |
|
||||
| `auto_mev` | string | Anti-MEV automatic gas price |
|
||||
| `last_block` | int64 | Latest block number |
|
||||
| `high` | string | High-priority gas price |
|
||||
| `average` | string | Average-priority gas price |
|
||||
| `low` | string | Low-priority gas price |
|
||||
| `suggest_base_fee` | string | Suggested base fee |
|
||||
| `high_prio_fee` | string | High-priority fee |
|
||||
| `average_prio_fee` | string | Average-priority fee |
|
||||
| `low_prio_fee` | string | Low-priority fee |
|
||||
| `high_prio_fee_mixed` | string | High mixed priority fee |
|
||||
| `average_prio_fee_mixed` | string | Average mixed priority fee |
|
||||
| `low_prio_fee_mixed` | string | Low mixed priority fee |
|
||||
| `native_token_usd_price` | float32 | Native token USD price |
|
||||
| `high_estimate_time` | int64 | Estimated confirmation time for high tier (seconds) |
|
||||
| `average_estimate_time` | int64 | Estimated confirmation time for average tier (seconds) |
|
||||
| `low_estimate_time` | int64 | Estimated confirmation time for low tier (seconds) |
|
||||
| `high_orign` | string | High-priority raw origin value |
|
||||
| `average_orign` | string | Average-priority raw origin value |
|
||||
| `low_orign` | string | Low-priority raw origin value |
|
||||
|
||||
---
|
||||
|
||||
@@ -535,12 +554,12 @@ gmgn-cli order strategy create \
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage |
|
||||
| `--priority-fee` | No | `sol` | Priority fee in SOL (≥ 0.00001). **Required** for SOL. |
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). **Required** for SOL. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — delegates fee selection to the trading bot. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — GMGN automatically selects the optimal fee. |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). **Required** for BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--anti-mev` | No | all | Enable anti-MEV protection |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection. Not supported on `base`. |
|
||||
|
||||
### `order strategy create` Response Fields
|
||||
|
||||
@@ -613,12 +632,12 @@ gmgn-cli order strategy cancel \
|
||||
|
||||
## Notes
|
||||
|
||||
- Swap uses **critical auth** (API Key + signature) — CLI handles signing automatically, no manual processing needed
|
||||
- Swap uses **signed auth** (API Key + signature) — CLI handles signing automatically, no manual processing needed
|
||||
- After submitting a swap, use `order get` to poll for confirmation
|
||||
- `--amount` is in the **smallest unit** (e.g., lamports for SOL)
|
||||
- `order strategy create`, `order strategy list`, and `order strategy cancel` use critical auth (require `GMGN_PRIVATE_KEY`)
|
||||
- `order strategy create`, `order strategy list`, and `order strategy cancel` use signed auth (require `GMGN_PRIVATE_KEY`)
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Chain restrictions for fee flags** — see the `Chain` column in each parameter table above. `--priority-fee` and `--tip-fee` are SOL/BSC only; `--gas-price`, `--max-fee-per-gas`, `--max-priority-fee-per-gas` are BSC/BASE/ETH only; `--gas-level` and `--auto-fee` are ETH only. The server returns 400 if a chain-restricted flag is sent on the wrong chain.
|
||||
- **Chain restrictions for fee flags** — see the `Chain` column in each parameter table above. `--priority-fee` and `--tip-fee` are SOL/BSC only; `--gas-price`, `--max-fee-per-gas`, `--max-priority-fee-per-gas` are BSC/BASE/ETH only; `--gas-level` and `--auto-fee` are ETH only. The server returns 400 if a chain-restricted flag is sent on the wrong chain. (`gas-price` itself supports all four chains including `sol`.)
|
||||
- **EIP-1559 minimum values per chain:**
|
||||
- BSC: `max_fee_per_gas` and `max_priority_fee_per_gas` min 50 000 000 wei (≈ 0.05 gwei); passing `"0"` returns 400
|
||||
- BASE / ETH: `max_fee_per_gas` and `max_priority_fee_per_gas` min 200 000 wei
|
||||
@@ -661,7 +680,7 @@ For full token research before swapping, see [`docs/workflow-token-research.md`]
|
||||
|
||||
## Execution Guidelines
|
||||
|
||||
- **[REQUIRED] Token security check** — Run before every swap. See **Pre-Swap Safety Check (REQUIRED)** section above. Uses normal auth (API Key only — no private key needed for this step).
|
||||
- **[REQUIRED] Token security check** — Run before every swap. See **Pre-Swap Safety Check (REQUIRED)** section above. Uses exist auth (API Key only — no private key needed for this step).
|
||||
- **Currency resolution** — When the user names a currency (SOL/BNB/ETH/USDC) instead of providing an address, look up its address in the Chain Currencies table and apply it automatically — never ask the user for it.
|
||||
- Buy ("buy X SOL of TOKEN", "spend 0.5 USDC on TOKEN") → resolve currency to `--input-token`
|
||||
- Sell ("sell TOKEN for SOL", "sell 50% of TOKEN to USDC") → resolve currency to `--output-token`
|
||||
|
||||
@@ -51,7 +51,7 @@ Use the `gmgn-cli` tool to query token information based on the user's request.
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All token routes used by this skill go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second, and the max burst is roughly `floor(10 ÷ weight)` when the bucket is full.
|
||||
All token routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
@@ -469,13 +469,18 @@ The response is an object with a `list` array. Each item in `list` represents on
|
||||
| `maker_token_tags` | Token-specific behavior tags for this wallet (e.g. `["bundler"]`, `["paper_hands"]`, `["top_holder"]`) |
|
||||
| `created_at` | Wallet creation timestamp (Unix seconds); `0` if unknown |
|
||||
|
||||
**Shared Funding**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `native_transfer` | First native token (SOL/BNB/ETH) transfer into this wallet — indicates the original funding source; wallets sharing the same `native_transfer.address` are likely funded from a common origin (coordinated wallets / same operator) |
|
||||
|
||||
**Last Transaction Records**
|
||||
|
||||
Each of the following is an object with `name`, `address`, `timestamp`, `tx_hash`, `type`:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `native_transfer` | Most recent native token (SOL/BNB/ETH) transfer associated with this wallet |
|
||||
| `token_transfer` | Most recent token transfer (buy or sell) |
|
||||
| `token_transfer_in` | Most recent inbound token transfer |
|
||||
| `token_transfer_out` | Most recent outbound token transfer |
|
||||
@@ -720,7 +725,7 @@ Show top rows only. Highlight wallets tagged `kol`, `smart_degen`, or flagged `b
|
||||
|
||||
- **Market cap is not returned directly** — calculate it as `price.price × circulating_supply` (`price` is now a nested object; use `price.price` for the current USD price string, and `circulating_supply` is a top-level field already in human-readable token units). Example: `price.price="3.11"` × `circulating_supply=999999151` ≈ $3.11B market cap.
|
||||
- **Trading volume (1h, 24h, etc.) is not included in `token info`** — to get volume or OHLCV data, use the `gmgn-market` skill and query K-line data: `gmgn-cli market kline --chain <chain> --address <token_address> --resolution <1m|5m|15m|1h|4h|1d>`. See the `gmgn-market` SKILL.md for full details.
|
||||
- All token commands use normal auth (API Key only, no signature required)
|
||||
- All token commands use exist auth (API Key only, no signature required)
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- `--tag` applies to both `holders` and `traders` and filters to only wallets with that tag — if few results are returned, try the other tag value
|
||||
- `amount_percentage` in holders/traders is a ratio (0–1), not a percentage — `0.05` means 5% of supply
|
||||
|
||||
@@ -61,11 +61,11 @@ Use the `gmgn-cli` tool to query on-chain tracking data based on the user's requ
|
||||
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
- `GMGN_API_KEY` configured in `~/.config/gmgn/.env` — required for all sub-commands
|
||||
- `GMGN_PRIVATE_KEY` — required for `track follow-wallet` only (critical auth); not needed for `kol` or `smartmoney`
|
||||
- `GMGN_PRIVATE_KEY` — required for `track follow-wallet` only (signed auth); not needed for `kol` or `smartmoney`
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All tracking routes used by this skill go through GMGN's leaky-bucket limiter with `rate=10` and `capacity=10`. Sustained throughput is roughly `10 ÷ weight` requests/second, and the max burst is roughly `floor(10 ÷ weight)` when the bucket is full.
|
||||
All tracking routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
@@ -311,7 +311,7 @@ To research any token surfaced by smart money activity, follow [`docs/workflow-t
|
||||
|
||||
## Notes
|
||||
|
||||
- `track follow-wallet` uses critical auth (API Key + private key signature); `track kol` and `track smartmoney` use normal auth (API Key only)
|
||||
- `track follow-wallet` uses signed auth (API Key + private key signature); `track kol` and `track smartmoney` use exist auth (API Key only)
|
||||
- `track follow-wallet` returns trades from wallets followed on the GMGN platform; the follow list is resolved automatically from the GMGN user account bound to the API Key — `--wallet` is optional
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- `track kol` / `track smartmoney` `--side` is a **client-side filter** — the CLI fetches all results then filters locally; it is NOT sent to the API
|
||||
|
||||
+39
-39
@@ -2,8 +2,8 @@
|
||||
* OpenApiClient — GMGN OpenAPI external client
|
||||
*
|
||||
* Auth modes:
|
||||
* Normal (market/token/portfolio): X-APIKEY + timestamp + client_id
|
||||
* Critical (swap and order routes): normal auth + X-Signature (private key signature)
|
||||
* Exist (market/token/portfolio): X-APIKEY + timestamp + client_id
|
||||
* Signed (swap and order routes): X-APIKEY + timestamp + client_id + X-Signature (private key signature)
|
||||
*/
|
||||
|
||||
import { buildAuthQuery, buildMessage, detectAlgorithm, sign } from "./signer.js";
|
||||
@@ -204,29 +204,29 @@ export class OpenApiClient {
|
||||
this.host = config.host.replace(/\/$/, "");
|
||||
}
|
||||
|
||||
// ---- Token endpoints (normal auth) ----
|
||||
// ---- Token endpoints (exist auth) ----
|
||||
|
||||
async getTokenInfo(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/info", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/info", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenSecurity(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/security", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/security", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenPoolInfo(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/pool_info", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/pool_info", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenTopHolders(chain: string, address: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_top_holders", { chain, address, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/token_top_holders", { chain, address, ...extra });
|
||||
}
|
||||
|
||||
async getTokenTopTraders(chain: string, address: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_top_traders", { chain, address, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/token_top_traders", { chain, address, ...extra });
|
||||
}
|
||||
|
||||
// ---- Market endpoints (normal auth) ----
|
||||
// ---- Market endpoints (exist auth) ----
|
||||
|
||||
async getTokenKline(
|
||||
chain: string,
|
||||
@@ -238,17 +238,17 @@ export class OpenApiClient {
|
||||
const query: Record<string, string | number> = { chain, address, resolution };
|
||||
if (from != null) query["from"] = from;
|
||||
if (to != null) query["to"] = to;
|
||||
return this.normalRequest("GET", "/v1/market/token_kline", query);
|
||||
return this.authExistRequest("GET", "/v1/market/token_kline", query);
|
||||
}
|
||||
|
||||
// ---- Portfolio endpoints (normal auth) ----
|
||||
// ---- Portfolio endpoints (exist auth) ----
|
||||
|
||||
async getWalletHoldings(
|
||||
chain: string,
|
||||
walletAddress: string,
|
||||
extra: Record<string, string | number> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_holdings", {
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_holdings", {
|
||||
chain,
|
||||
wallet_address: walletAddress,
|
||||
...extra,
|
||||
@@ -260,7 +260,7 @@ export class OpenApiClient {
|
||||
walletAddress: string,
|
||||
extra: Record<string, string | number | string[]> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_activity", {
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_activity", {
|
||||
chain,
|
||||
wallet_address: walletAddress,
|
||||
...extra,
|
||||
@@ -268,7 +268,7 @@ export class OpenApiClient {
|
||||
}
|
||||
|
||||
async getWalletStats(chain: string, walletAddresses: string[], period = "7d"): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_stats", {
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_stats", {
|
||||
chain,
|
||||
wallet_address: walletAddresses,
|
||||
period,
|
||||
@@ -280,54 +280,54 @@ export class OpenApiClient {
|
||||
walletAddress: string,
|
||||
tokenAddress: string
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_token_balance", { chain, wallet_address: walletAddress, token_address: tokenAddress });
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_token_balance", { chain, wallet_address: walletAddress, token_address: tokenAddress });
|
||||
}
|
||||
|
||||
async getTrenches(chain: string, types?: string[], platforms?: string[], limit?: number, filters?: Record<string, number | string>): Promise<unknown> {
|
||||
const body = buildTrenchesBody(chain, types, platforms, limit, filters);
|
||||
return this.normalRequest("POST", "/v1/trenches", { chain }, body);
|
||||
return this.authExistRequest("POST", "/v1/trenches", { chain }, body);
|
||||
}
|
||||
|
||||
// ---- Market trending endpoints (normal auth) ----
|
||||
// ---- Market trending endpoints (exist auth) ----
|
||||
|
||||
async getTrendingSwaps(
|
||||
chain: string,
|
||||
interval: string,
|
||||
extra: Record<string, string | number | string[]> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/rank", { chain, interval, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/rank", { chain, interval, ...extra });
|
||||
}
|
||||
|
||||
async getTokenSignalV2(chain: string, groups: TokenSignalGroup[]): Promise<unknown> {
|
||||
return this.normalRequest("POST", "/v1/market/token_signal", {}, { chain, groups });
|
||||
return this.authExistRequest("POST", "/v1/market/token_signal", {}, { chain, groups });
|
||||
}
|
||||
|
||||
// ---- User endpoints (normal auth) ----
|
||||
// ---- User endpoints (exist auth) ----
|
||||
|
||||
async getUserInfo(): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/info", {});
|
||||
return this.authExistRequest("GET", "/v1/user/info", {});
|
||||
}
|
||||
|
||||
async getFollowWallet(chain: string, extra: Record<string, string | number | string[]> = {}): Promise<unknown> {
|
||||
return this.criticalRequest("GET", "/v1/trade/follow_wallet", { chain, ...extra }, null);
|
||||
return this.authSignedRequest("GET", "/v1/trade/follow_wallet", { chain, ...extra }, null);
|
||||
}
|
||||
|
||||
async getKol(chain?: string, limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (chain) query["chain"] = chain;
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.normalRequest("GET", "/v1/user/kol", query);
|
||||
return this.authExistRequest("GET", "/v1/user/kol", query);
|
||||
}
|
||||
|
||||
async getSmartMoney(chain?: string, limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (chain) query["chain"] = chain;
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.normalRequest("GET", "/v1/user/smartmoney", query);
|
||||
return this.authExistRequest("GET", "/v1/user/smartmoney", query);
|
||||
}
|
||||
|
||||
async getCreatedTokens(chain: string, walletAddress: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/created_tokens", { chain, wallet_address: walletAddress, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/user/created_tokens", { chain, wallet_address: walletAddress, ...extra });
|
||||
}
|
||||
|
||||
async quoteOrder(
|
||||
@@ -339,54 +339,54 @@ export class OpenApiClient {
|
||||
slippage: number
|
||||
): Promise<unknown> {
|
||||
const query = { chain, from_address, input_token, output_token, input_amount, slippage };
|
||||
return this.criticalRequest("GET", "/v1/trade/quote", query, null);
|
||||
return this.authSignedRequest("GET", "/v1/trade/quote", query, null);
|
||||
}
|
||||
|
||||
// ---- Swap endpoints (critical auth) ----
|
||||
// ---- Swap endpoints (signed auth) ----
|
||||
|
||||
async swap(params: SwapParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/swap", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/trade/swap", {}, params);
|
||||
}
|
||||
|
||||
async multiSwap(params: MultiSwapParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/multi_swap", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/trade/multi_swap", {}, params);
|
||||
}
|
||||
|
||||
async queryOrder(orderId: string, chain: string): Promise<unknown> {
|
||||
return this.criticalRequest("GET", "/v1/trade/query_order", { order_id: orderId, chain }, null);
|
||||
return this.authSignedRequest("GET", "/v1/trade/query_order", { order_id: orderId, chain }, null);
|
||||
}
|
||||
|
||||
async getGasPrice(chain: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/trade/gas_price", { chain });
|
||||
return this.authExistRequest("GET", "/v1/trade/gas_price", { chain });
|
||||
}
|
||||
|
||||
// ---- Strategy order endpoints (critical auth) ----
|
||||
// ---- Strategy order endpoints (signed auth) ----
|
||||
|
||||
async createStrategyOrder(params: StrategyCreateParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/strategy/create", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/trade/strategy/create", {}, params);
|
||||
}
|
||||
|
||||
async getStrategyOrders(chain: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.criticalRequest("GET", "/v1/trade/strategy/orders", { chain, ...extra }, null);
|
||||
return this.authSignedRequest("GET", "/v1/trade/strategy/orders", { chain, ...extra }, null);
|
||||
}
|
||||
|
||||
async cancelStrategyOrder(params: StrategyCancelParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/strategy/cancel", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/trade/strategy/cancel", {}, params);
|
||||
}
|
||||
|
||||
// ---- Cooking endpoints ----
|
||||
|
||||
async getCookingStatistics(): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/cooking/statistics", {});
|
||||
return this.authExistRequest("GET", "/v1/cooking/statistics", {});
|
||||
}
|
||||
|
||||
async createToken(params: CreateTokenParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/cooking/create_token", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/cooking/create_token", {}, params);
|
||||
}
|
||||
|
||||
// ---- Internal methods ----
|
||||
|
||||
private async normalRequest(
|
||||
private async authExistRequest(
|
||||
method: string,
|
||||
subPath: string,
|
||||
queryExtra: Record<string, string | number | string[]>,
|
||||
@@ -412,7 +412,7 @@ export class OpenApiClient {
|
||||
}, true);
|
||||
}
|
||||
|
||||
private async criticalRequest(
|
||||
private async authSignedRequest(
|
||||
method: string,
|
||||
subPath: string,
|
||||
queryExtra: Record<string, string | number | string[]>,
|
||||
|
||||
@@ -30,7 +30,7 @@ export function buildAuthQuery(): { timestamp: number; client_id: string } {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the signature message (critical auth)
|
||||
* Build the signature message (signed auth)
|
||||
* Format: {sub_path}:{sorted_query_string}:{request_body}:{timestamp}
|
||||
* sorted_query_string: all query params (including timestamp, client_id) sorted alphabetically by key.
|
||||
* Array values are serialized as repeated k=v pairs (same as buildUrl / URLSearchParams), sorted by value.
|
||||
|
||||
@@ -9,7 +9,7 @@ export function registerCookingCommands(program: Command): void {
|
||||
|
||||
cooking
|
||||
.command("stats")
|
||||
.description("Get token creation statistics by launchpad (normal auth)")
|
||||
.description("Get token creation statistics by launchpad (exist auth)")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig());
|
||||
|
||||
@@ -290,13 +290,14 @@ const TRENCHES_FILTER_PRESETS: Record<string, Record<string, number | string>> =
|
||||
};
|
||||
|
||||
// Convert API snake_case field to Commander.js opts key
|
||||
// Commander.js camelCase: only converts -[a-z] patterns, digits stay as-is
|
||||
// e.g. min_volume_24h → min-volume-24h → minVolume-24h (digit prefix -24 is NOT converted)
|
||||
// e.g. min_smart_degen_count → min-smart-degen-count → minSmartDegenCount (all letters, converts fully)
|
||||
// Commander.js camelCase: converts -[a-z] to uppercase, and removes hyphen before digits
|
||||
// e.g. min_volume_24h → min-volume-24h → minVolume-24h → minVolume24h
|
||||
// e.g. min_smart_degen_count → min-smart-degen-count → minSmartDegenCount
|
||||
function apiFieldToCliKey(apiField: string): string {
|
||||
return apiField
|
||||
.replace(/_/g, '-')
|
||||
.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());
|
||||
.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())
|
||||
.replace(/-(\d)/g, '$1');
|
||||
}
|
||||
|
||||
// Client-side sort helpers (API does not support server-side sort for trenches)
|
||||
|
||||
+49
-49
@@ -73,55 +73,6 @@ export function registerSwapCommands(program: Command): void {
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const order = program.command("order").description("Order management commands");
|
||||
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction (requires critical auth)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth (requires GMGN_PRIVATE_KEY)")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
.requiredOption("--amount <amount>", "Input amount (smallest unit)")
|
||||
.requiredOption("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.from, opts.chain, "--from");
|
||||
validateAddress(opts.inputToken, opts.chain, "--input-token");
|
||||
validateAddress(opts.outputToken, opts.chain, "--output-token");
|
||||
validatePositiveInt(opts.amount, "--amount");
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client
|
||||
.quoteOrder(opts.chain, opts.from, opts.inputToken, opts.outputToken, opts.amount, opts.slippage)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
order
|
||||
.command("get")
|
||||
.description("Query order status (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / monad")
|
||||
.requiredOption("--order-id <id>", "Order ID")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.queryOrder(opts.orderId, opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
order
|
||||
.command("gas-price")
|
||||
.description("Query recommended EVM gas price (normal auth; eth / bsc / base)")
|
||||
.requiredOption("--chain <chain>", "EVM chain: eth / bsc / base")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig(false));
|
||||
const data = await client.getGasPrice(opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
program
|
||||
.command("multi-swap")
|
||||
.description("Submit token swaps across multiple wallets concurrently (up to 100 wallets)")
|
||||
@@ -194,6 +145,55 @@ export function registerSwapCommands(program: Command): void {
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const order = program.command("order").description("Order management commands");
|
||||
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction (signed auth — requires GMGN_PRIVATE_KEY)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth (requires GMGN_PRIVATE_KEY)")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
.requiredOption("--amount <amount>", "Input amount (smallest unit)")
|
||||
.requiredOption("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.from, opts.chain, "--from");
|
||||
validateAddress(opts.inputToken, opts.chain, "--input-token");
|
||||
validateAddress(opts.outputToken, opts.chain, "--output-token");
|
||||
validatePositiveInt(opts.amount, "--amount");
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client
|
||||
.quoteOrder(opts.chain, opts.from, opts.inputToken, opts.outputToken, opts.amount, opts.slippage)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
order
|
||||
.command("get")
|
||||
.description("Query order status (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / monad")
|
||||
.requiredOption("--order-id <id>", "Order ID")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.queryOrder(opts.orderId, opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
program
|
||||
.command("gas-price")
|
||||
.description("Query recommended gas price tiers for any chain (exist auth — API Key only; eth / bsc / base / sol)")
|
||||
.requiredOption("--chain <chain>", "Chain: eth / bsc / base / sol")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig(false));
|
||||
const data = await client.getGasPrice(opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const strategy = order.command("strategy").description("Limit/strategy order management");
|
||||
|
||||
strategy
|
||||
|
||||
Reference in New Issue
Block a user