mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-07-28 09:17:45 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2949ea7de3 | |||
| 4dde77c481 | |||
| 02d497df92 | |||
| 48a06cd9b4 | |||
| 9e90bb9c07 | |||
| 31fababfd8 | |||
| 6833ff19cd | |||
| ccf3dc1c23 | |||
| 3c1ffdd7eb | |||
| 10d9c592d2 | |||
| ff3f52f3d8 | |||
| 1ea71149d9 | |||
| ca3c640afc | |||
| 2073b5fdaf | |||
| fce314b9ab | |||
| dbe3eec697 | |||
| a9979f9dd3 | |||
| 83aee6e759 | |||
| 567c5f92d1 | |||
| 25b9da3fdf | |||
| 7445c970bc | |||
| c525fba661 | |||
| 0ce0051e60 | |||
| 49397c2b62 | |||
| 8999d36d1d | |||
| 013a6c867c | |||
| 29eeb723e4 | |||
| 60a199cb80 | |||
| e4bc94c625 | |||
| ed27705826 | |||
| e9ff951083 |
@@ -42,6 +42,14 @@ Data across SOL / BSC / Base is live on every query. Supports multi-parameter cu
|
||||
- Market orders, limit orders, and strategy orders (take-profit / stop-loss) in a single command.
|
||||
- Sell by position percentage (`--percent 50`) without calculating exact amounts.
|
||||
|
||||
| Order Type | Description |
|
||||
|------------|-------------|
|
||||
| Market Order | Instant execution at current market price |
|
||||
| Limit Order | Trigger buy or sell at a specified price |
|
||||
| Take-Profit / Stop-Loss | Fixed-price exit conditions attached to a swap |
|
||||
| Trailing Take-Profit / Trailing Stop-Loss | Tracks price peak; fires after a specified drawdown % — rides momentum while protecting gains |
|
||||
| Multi-Wallet Batch Trading | Buy with multiple wallets simultaneously, each with its own take-profit / stop-loss / trailing take-profit / trailing stop-loss orders |
|
||||
|
||||
### 3. More comprehensive token data
|
||||
|
||||
No more scraping web pages or getting blocked by Cloudflare. Query all the professional analytics needed for high-frequency Meme token trading, with high concurrency in real time (including but not limited to):
|
||||
@@ -158,7 +166,7 @@ echo 'GMGN_API_KEY=<user_api_key>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
If the user also needs swap capability, append the private key:
|
||||
If the user also needs swap or order capability, append the private key:
|
||||
|
||||
```bash
|
||||
# Append private key (use the PEM content from Step 3)
|
||||
@@ -500,53 +508,7 @@ gmgn-cli track smartmoney --limit 100 --raw
|
||||
gmgn-cli track smartmoney --chain sol --side sell --limit 50 --raw
|
||||
```
|
||||
|
||||
### Limit Orders (requires private key)
|
||||
|
||||
```bash
|
||||
# Create a take-profit order
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type take_profit \
|
||||
--check-price 0.002 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# Create a stop-loss order
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type stop_loss \
|
||||
--check-price 0.0005 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# List open strategy orders
|
||||
gmgn-cli order strategy list --chain sol
|
||||
|
||||
# Cancel a strategy order
|
||||
gmgn-cli order strategy cancel --chain sol --from <wallet_address> --order-id <order_id>
|
||||
```
|
||||
|
||||
### Cooking (requires private key)
|
||||
|
||||
```bash
|
||||
# Buy token and automatically attach take-profit + stop-loss condition orders
|
||||
gmgn-cli cooking \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_address> \
|
||||
--amount 1000000000 \
|
||||
--slippage 0.1 \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"200","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]'
|
||||
```
|
||||
|
||||
### Swap (requires private key)
|
||||
### Swap / Quote / Query
|
||||
|
||||
```bash
|
||||
# Submit swap with fixed slippage
|
||||
@@ -585,10 +547,108 @@ gmgn-cli order quote \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# Quotes use critical auth and require GMGN_PRIVATE_KEY on every chain
|
||||
gmgn-cli order quote \
|
||||
--chain bsc \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount 1000000000000000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# Query order
|
||||
gmgn-cli order get --chain sol --order-id <order-id>
|
||||
```
|
||||
|
||||
> `order quote` uses critical auth on `sol` / `bsc` / `base` and requires `GMGN_PRIVATE_KEY`.
|
||||
|
||||
### Swap with Take-Profit / Stop-Loss Orders (requires private key)
|
||||
|
||||
**`hold_amount` mode** — each condition order fires based on current holdings at trigger time:
|
||||
|
||||
```bash
|
||||
# Buy token A with 0.01 SOL; take-profit 50% at +100%, take-profit remaining 50% at +300%, stop-loss 100% at -65%
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type hold_amount
|
||||
```
|
||||
|
||||
> `price_scale` for `profit_stop`: gain % from entry (`"100"` = +100% / 2×, `"300"` = +300% / 4×). For `loss_stop`: drop % from entry (`"65"` = drops 65%, triggers at 35% of entry).
|
||||
> `hold_amount`: the second take-profit fires on whatever is held at that point (the remaining 50%). If you added to your position in between, those additional tokens will be included as well.
|
||||
|
||||
**`buy_amount` mode** — each condition order fires based on the original bought amount:
|
||||
|
||||
```bash
|
||||
# Same strategy using fixed percentages of the original bought amount
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"50"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type buy_amount
|
||||
```
|
||||
|
||||
> `buy_amount`: each take-profit sells 50% of the **original** bought amount. Stop-loss sells 100% of the original bought amount.
|
||||
|
||||
---
|
||||
|
||||
### Limit Orders (requires private key)
|
||||
|
||||
```bash
|
||||
# Create a take-profit order
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type take_profit \
|
||||
--check-price 0.002 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# Create a stop-loss order
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type stop_loss \
|
||||
--check-price 0.0005 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# List open strategy orders (requires private key)
|
||||
gmgn-cli order strategy list --chain sol
|
||||
|
||||
# Cancel a strategy order
|
||||
gmgn-cli order strategy cancel --chain sol --from <wallet_address> --order-id <order_id>
|
||||
```
|
||||
|
||||
### Cooking (requires private key)
|
||||
|
||||
```bash
|
||||
# Buy token and automatically attach take-profit + stop-loss condition orders
|
||||
gmgn-cli cooking \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_address> \
|
||||
--amount 1000000000 \
|
||||
--slippage 0.3 \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]'
|
||||
```
|
||||
|
||||
## 9. Supported Chains
|
||||
|
||||
| Commands | Chains | Chain Currencies |
|
||||
|
||||
+108
-49
@@ -45,6 +45,14 @@ SOL / BSC / Base 多链数据每次查询均为实时,支持多参数个性化
|
||||
- 单条命令支持市价单、限价单、策略单(止盈 / 止损)。
|
||||
- 支持按仓位比例卖出(`--percent 50`),无需手动计算数量。
|
||||
|
||||
| 订单类型 | 说明 |
|
||||
|----------|------|
|
||||
| 市价单 | 以当前市价即时成交 |
|
||||
| 限价单 | 设定触发价格,到价买入或卖出 |
|
||||
| 止盈 / 止损 | 随买单附带固定价格的退出条件 |
|
||||
| 追踪止盈 / 追踪止损 | 跟踪价格峰值,回撤达到指定比例后触发,吃满行情同时保护收益 |
|
||||
| 多钱包批量交易 | 多个钱包同时买入,每个钱包分别创建对应的止盈 / 止损 / 追踪止盈 / 追踪止损订单 |
|
||||
|
||||
### 3. 特色数据更全
|
||||
|
||||
不用再爬网页,不会被Claudeflare拦截,现在就可以快速/多并发实时查询多链的 Meme 代币高频交易所需的所有专业分析指标数据 (包括不限于):
|
||||
@@ -164,7 +172,7 @@ echo 'GMGN_API_KEY=<user_api_key>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
如果用户需要 swap 能力,追加私钥:
|
||||
如果用户需要 swap 或 order 能力,追加私钥:
|
||||
|
||||
```bash
|
||||
# 追加私钥(使用第 3 步输出的 PEM 内容)
|
||||
@@ -443,7 +451,6 @@ solana 上的 <token_address> 安全吗,值得买入吗?
|
||||
完整参数说明:[docs/cli-usage.md](docs/cli-usage.md)。所有命令均支持 `--raw` 输出单行 JSON(方便 `jq` 等工具处理)。
|
||||
|
||||
### Token
|
||||
|
||||
```bash
|
||||
# 基本信息 + 实时价格
|
||||
gmgn-cli token info --chain sol --address <addr>
|
||||
@@ -532,53 +539,7 @@ gmgn-cli track smartmoney --limit 100 --raw
|
||||
gmgn-cli track smartmoney --chain sol --side sell --limit 50 --raw
|
||||
```
|
||||
|
||||
### 限价单(需要私钥)
|
||||
|
||||
```bash
|
||||
# 创建止盈单
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type take_profit \
|
||||
--check-price 0.002 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# 创建止损单
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type stop_loss \
|
||||
--check-price 0.0005 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# 查看当前挂单
|
||||
gmgn-cli order strategy list --chain sol
|
||||
|
||||
# 撤销策略单
|
||||
gmgn-cli order strategy cancel --chain sol --from <wallet_address> --order-id <order_id>
|
||||
```
|
||||
|
||||
### Cooking 一键策略单(需要私钥)
|
||||
|
||||
```bash
|
||||
# 买入代币,同时自动挂止盈 + 止损条件单
|
||||
gmgn-cli cooking \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_address> \
|
||||
--amount 1000000000 \
|
||||
--slippage 0.1 \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"200","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]'
|
||||
```
|
||||
|
||||
### Swap(需要私钥)
|
||||
### Swap / Quote / Query
|
||||
|
||||
```bash
|
||||
# 提交兑换(固定滑点)
|
||||
@@ -617,10 +578,108 @@ gmgn-cli order quote \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# 所有链上的 quote 都走关键鉴权,需要 GMGN_PRIVATE_KEY
|
||||
gmgn-cli order quote \
|
||||
--chain bsc \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount 1000000000000000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# 查询订单状态
|
||||
gmgn-cli order get --chain sol --order-id <order-id>
|
||||
```
|
||||
|
||||
> `order quote` 在 `sol` / `bsc` / `base` 上都走关键鉴权,必须配置 `GMGN_PRIVATE_KEY`。
|
||||
|
||||
### 带止盈止损的 Swap(需要私钥)
|
||||
|
||||
**`hold_amount` 模式** — 按触发时的实际持仓比例卖出:
|
||||
|
||||
```bash
|
||||
# 用 0.01 SOL 买入代币 A;涨 100% 卖 50%,涨 300% 卖剩余 50%,跌 65% 全卖
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type hold_amount
|
||||
```
|
||||
|
||||
> `price_scale` 止盈时为涨幅百分比(`"100"` = 涨 100% / 2×,`"300"` = 涨 300% / 4×);止损时为跌幅百分比(`"65"` = 跌 65%,触发价为入场价的 35%)。
|
||||
> `hold_amount`:第二个止盈单触发时,按触发时持仓(剩余 50%)的 100% 卖出。如果中间有加仓,加仓的部分也会一同被卖掉。
|
||||
|
||||
**`buy_amount` 模式** — 按原始买入量的固定百分比卖出:
|
||||
|
||||
```bash
|
||||
# 相同策略,使用原始买入量的固定百分比
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"50"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type buy_amount
|
||||
```
|
||||
|
||||
> `buy_amount`:每个止盈单各卖原始买入量的 50%,止损单卖原始买入量的 100%。
|
||||
|
||||
---
|
||||
|
||||
### 限价单(需要私钥)
|
||||
|
||||
```bash
|
||||
# 创建止盈单
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type take_profit \
|
||||
--check-price 0.002 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# 创建止损单
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--sub-order-type stop_loss \
|
||||
--check-price 0.0005 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# 查看当前挂单(需要私钥)
|
||||
gmgn-cli order strategy list --chain sol
|
||||
|
||||
# 撤销策略单
|
||||
gmgn-cli order strategy cancel --chain sol --from <wallet_address> --order-id <order_id>
|
||||
```
|
||||
|
||||
### Cooking 一键策略单(需要私钥)
|
||||
|
||||
```bash
|
||||
# 买入代币,同时自动挂止盈 + 止损条件单
|
||||
gmgn-cli cooking \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_address> \
|
||||
--amount 1000000000 \
|
||||
--slippage 0.3 \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]'
|
||||
```
|
||||
|
||||
## 9. 支持的链
|
||||
|
||||
| 接口类型 | 支持的链 | 链原生货币 |
|
||||
|
||||
+3
-3
@@ -344,7 +344,7 @@ npx gmgn-cli portfolio smartmoney [--limit <n>] [--raw]
|
||||
|
||||
## order quote
|
||||
|
||||
Get a swap quote without submitting a transaction. Uses normal auth — no private key required.
|
||||
Get a swap quote without submitting a transaction. All supported quote chains use critical auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
npx gmgn-cli order quote \
|
||||
@@ -359,7 +359,7 @@ npx gmgn-cli order quote \
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` (all require `GMGN_PRIVATE_KEY` for quote) |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--input-token` | Yes | Input token contract address |
|
||||
| `--output-token` | Yes | Output token contract address |
|
||||
@@ -532,7 +532,7 @@ gmgn-cli order strategy create \
|
||||
|
||||
## order strategy list
|
||||
|
||||
List strategy orders. Uses normal auth.
|
||||
List strategy orders. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli order strategy list --chain <chain> [--type <open|history>] [--from <address>] [--group-tag <tag>] [--base-token <address>] [--page-token <token>] [--limit <n>] [--raw]
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^12.1.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.3",
|
||||
"description": "GMGN OpenAPI CLI — call GMGN market, token, portfolio and swap APIs from the command line",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -66,6 +66,12 @@ When the user names a platform colloquially (e.g. "pump.fun", "four.meme", "Panc
|
||||
- `cooking create`: Both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` must be configured in `~/.config/gmgn/.env`. The private key must correspond to the wallet bound to the API Key.
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
|
||||
**IMPORTANT — Credential lookup order:** `gmgn-cli` loads `~/.config/gmgn/.env` first, then overlays any `.env` found in the **current working directory** (project-level overrides global). If credentials appear missing or wrong, check whether a `.env` in the workspace directory is shadowing the global config:
|
||||
```bash
|
||||
ls -la .env 2>/dev/null && echo "WARNING: local .env is overriding ~/.config/gmgn/.env"
|
||||
```
|
||||
If a local `.env` exists but lacks `GMGN_API_KEY` / `GMGN_PRIVATE_KEY`, either add them to that file or remove it so the global config is used.
|
||||
|
||||
## 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.
|
||||
@@ -78,6 +84,7 @@ All cooking routes go through GMGN's leaky-bucket limiter with `rate=10` and `ca
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers — Unix timestamp for when the limit resets.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- `cooking create` is a real transaction: **never loop or auto-resubmit** after a `429`. Wait until the reset time, then ask for confirmation again before retrying.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during cooldown extend the ban by 5 seconds each time, up to 5 minutes.
|
||||
|
||||
@@ -160,7 +167,7 @@ Token creation is **asynchronous**. If the initial `cooking create` response sho
|
||||
```bash
|
||||
gmgn-cli order get --chain <chain> --order-id <order_id>
|
||||
```
|
||||
2. The new token's contract / mint address is in the **`output_token`** field of the `order get` response — it is NOT returned by `cooking create` directly.
|
||||
2. The new token's contract / mint address is in the **`report.output_token`** field of the `order get` response (only present when `state = 30` and `status = "successful"`) — it is NOT returned by `cooking create` directly.
|
||||
3. Stop polling once `status` is `confirmed`, `failed`, or `expired`.
|
||||
4. On `confirmed`: display `output_token` as the token address and include the block explorer link.
|
||||
5. On `failed` / `expired`: report the `error_status` and do not retry automatically.
|
||||
@@ -270,13 +277,15 @@ Block explorer links:
|
||||
|
||||
## Guided Launch Flow
|
||||
|
||||
When a user says they want to launch / create / deploy a token but has not provided all required information, do NOT ask for everything at once. Collect information in this order, one step at a time:
|
||||
When a user says they want to launch / create / deploy a token but has not provided all required information, collect information **one required field at a time** — never bundle multiple required fields into a single question. The user should be able to reply with a single value, not a labeled list.
|
||||
|
||||
Ask each required field as a short, direct question. Wait for the answer before moving to the next. Optional fields are grouped into one question after all required fields are collected.
|
||||
|
||||
### Step 1 — Chain & Platform
|
||||
|
||||
Ask: *"Which chain and platform do you want to launch on?"*
|
||||
Ask: *"Which chain and platform?"*
|
||||
|
||||
Show the available options:
|
||||
Show the options concisely:
|
||||
|
||||
| Chain | Platform | `--dex` |
|
||||
|-------|----------|---------|
|
||||
@@ -294,39 +303,47 @@ Show the available options:
|
||||
| Base | Flaunch | `flaunch` |
|
||||
| Base | Virtuals | `virtuals_v2` |
|
||||
|
||||
If the user is unsure, recommend: **Pump.fun (SOL)** or **FourMeme (BSC)** — the two most active launchpads.
|
||||
If the user is unsure, recommend: **Pump.fun (SOL)** or **FourMeme (BSC)**.
|
||||
|
||||
### Step 2 — Token Identity
|
||||
### Step 2 — Token Name
|
||||
|
||||
Ask for name, symbol, and description together:
|
||||
Ask: *"Token name?"*
|
||||
|
||||
*"What is your token's name, ticker symbol, and a short description?"*
|
||||
Wait for the user's reply (e.g. `Doge Killer`).
|
||||
|
||||
- Name: the full display name (e.g. `Doge Killer`)
|
||||
- Symbol: short uppercase ticker, typically 3–8 characters (e.g. `DOGEK`)
|
||||
- Description: optional but recommended — a one-line pitch shown on the launchpad
|
||||
### Step 3 — Token Symbol
|
||||
|
||||
### Step 3 — Logo
|
||||
Ask: *"Ticker symbol?"*
|
||||
|
||||
Ask: *"Do you have a logo image? You can share a file path (e.g. `/Users/you/logo.png`) or an image URL."*
|
||||
Wait for the user's reply (e.g. `DOGEK`). Typically 3–8 uppercase characters.
|
||||
|
||||
- If the user provides a **file path**: silently run `base64 -i <path>` and pass the result to `--image`. Do not mention "base64" to the user.
|
||||
- If the user provides a **URL**: use `--image-url` directly.
|
||||
- If the user has no logo: note that most platforms accept a launch without one, but it significantly reduces visibility. Ask if they want to proceed without it.
|
||||
### Step 4 — Logo
|
||||
|
||||
### Step 4 — Social Links (optional)
|
||||
Ask: *"Logo image? (file path or URL — skip to launch without one)"*
|
||||
|
||||
Ask: *"Do you have a Twitter, Telegram, or website to attach to the token? You can skip this."*
|
||||
|
||||
Collect any combination of `--twitter`, `--telegram`, `--website`. If the user skips, proceed to the next step.
|
||||
- **File path** → silently run `base64 -i <path>` and pass the result to `--image`. Do not mention "base64" to the user.
|
||||
- **URL** → use `--image-url` directly.
|
||||
- **Skip / none** → proceed without a logo. Note that most platforms accept this, but it reduces visibility.
|
||||
|
||||
### Step 5 — Initial Buy Amount
|
||||
|
||||
Ask: *"How much {SOL / BNB / ETH} do you want to spend on the initial buy?"*
|
||||
Ask: *"How much {SOL / BNB / ETH} for the initial buy?"*
|
||||
|
||||
Pass the user's answer directly to `--buy-amt` — this is already in full token units (e.g. `0.01` = 0.01 SOL), do NOT convert to lamports or wei.
|
||||
Pass the user's answer directly to `--buy-amt` — already in full token units (e.g. `0.01` = 0.01 SOL). Do NOT convert to lamports or wei.
|
||||
|
||||
### Step 6 — Confirmation & Execute
|
||||
### Step 6 — Optional Details (single question)
|
||||
|
||||
Ask all optional fields together in one message:
|
||||
|
||||
*"Any optional extras? (skip any you don't need)"*
|
||||
- *Description* — one-line pitch shown on the launchpad
|
||||
- *Twitter* — Twitter / X URL
|
||||
- *Telegram* — Telegram group URL
|
||||
- *Website* — project website URL
|
||||
|
||||
The user can reply with just the ones they have, or say "skip" / "none" to proceed.
|
||||
|
||||
### Step 7 — Confirmation & Execute
|
||||
|
||||
Once all information is collected, present the pre-create confirmation summary (see Output Format section) and wait for the user to reply "confirm" before executing.
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ All market routes used by this skill go through GMGN's leaky-bucket limiter with
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes. Do not spam retries.
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ All portfolio routes used by this skill go through GMGN's leaky-bucket limiter w
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes. Do not spam retries.
|
||||
|
||||
@@ -211,6 +212,28 @@ The response is an object (or array for batch). Key fields:
|
||||
| `sell_count` | Number of sell transactions |
|
||||
| `pnl` | Profit/loss ratio = `realized_profit / total_cost` |
|
||||
|
||||
The response also includes a `common` object when available (absent if the upstream identity service is unavailable):
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `common.avatar` | Wallet avatar URL |
|
||||
| `common.name` | Display name |
|
||||
| `common.ens` | ENS domain (EVM chains only) |
|
||||
| `common.tag` | Primary wallet tag |
|
||||
| `common.tags` | All wallet tags (e.g. `["smart_money"]`) |
|
||||
| `common.twitter_username` | Twitter handle |
|
||||
| `common.twitter_name` | Twitter display name |
|
||||
| `common.followers_count` | Twitter follower count |
|
||||
| `common.is_blue_verified` | Twitter blue-verified badge |
|
||||
| `common.follow_count` | Number of GMGN users following this wallet |
|
||||
| `common.remark_count` | Number of GMGN users who have remarked this wallet |
|
||||
| `common.created_token_count` | Tokens created by this wallet |
|
||||
| `common.fund_from` | Funding source label |
|
||||
| `common.fund_from_address` | Address that funded this wallet |
|
||||
| `common.fund_amount` | Funding amount |
|
||||
|
||||
Use `common.tags` and `common.twitter_username` when building a wallet profile narrative. If `common` is absent in the response, omit identity fields silently — do not report it as an error.
|
||||
|
||||
**Do NOT guess field names not listed here.** If a field appears in the response but is not in this table, do not interpret it without reading the raw output first.
|
||||
|
||||
## Output Format
|
||||
@@ -250,9 +273,10 @@ Win Rate: {winrate × 100}%
|
||||
Total Spent: ${total_cost}
|
||||
Buys / Sells: {buy_count} / {sell_count}
|
||||
PnL Ratio: {pnl}x
|
||||
[Identity: {common.name or common.twitter_username} | Tags: {common.tags}]
|
||||
```
|
||||
|
||||
For batch queries (multiple wallets), present one summary block per wallet.
|
||||
Show the `[Identity: ...]` line only if `common` is present in the response. For batch queries (multiple wallets), present one summary block per wallet.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
+129
-37
@@ -12,7 +12,7 @@ metadata:
|
||||
|
||||
**⚠️ IPv6 NOT SUPPORTED: If you get a `401` or `403` error and credentials look correct, check for IPv6 immediately: (1) list all network interfaces and their IPv6 addresses — run `ifconfig | grep inet6` (macOS) or `ip addr show | grep inet6` (Linux); (2) send a test request to `https://ipv6.icanhazip.com` — if the response is an IPv6 address, outbound traffic is going via IPv6. Tell the user immediately: "Please disable IPv6 on your network interface — gmgn-cli commands only work over IPv4."**
|
||||
|
||||
Use the `gmgn-cli` tool to submit a token swap or query an existing order. **Requires private key** (`GMGN_PRIVATE_KEY` in `.env`).
|
||||
Use the `gmgn-cli` tool to submit a token swap or query an existing order. `GMGN_API_KEY` is always required. `GMGN_PRIVATE_KEY` is required for critical-auth commands such as `swap` and all `order` subcommands, including `order quote`.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
@@ -24,19 +24,19 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. **Req
|
||||
|
||||
- **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. Enabled by default.
|
||||
- **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.
|
||||
|
||||
- **Critical auth** — `swap` requires 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. Normal commands (like `order quote`) use API Key alone.
|
||||
- **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.
|
||||
|
||||
- **`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`.
|
||||
|
||||
- **`filled_input_amount` / `filled_output_amount`** — Actual amounts consumed/received, in smallest unit. Convert to human-readable using token decimals before displaying to the user.
|
||||
- **`report.input_amount` / `report.output_amount`** — Actual amounts consumed/received, in smallest unit. Only present when `state = 30` and `status = "successful"`. Convert to human-readable using `report.input_token_decimals` / `report.output_token_decimals` before displaying to the user.
|
||||
|
||||
## Financial Risk Notice
|
||||
|
||||
**This skill executes REAL, IRREVERSIBLE blockchain transactions.**
|
||||
|
||||
- Every `swap` command submits an on-chain transaction that moves real funds.
|
||||
- Every `swap` and `order strategy create` command submits an on-chain transaction that moves real funds.
|
||||
- Transactions cannot be undone once confirmed on-chain.
|
||||
- The AI agent must **never auto-execute a swap** — explicit user confirmation is required every time, without exception.
|
||||
- Only use this skill with funds you are willing to trade. Start with small amounts when testing.
|
||||
@@ -46,10 +46,10 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. **Req
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `swap` | Submit a token swap |
|
||||
| `order quote` | Get a swap quote (no transaction submitted) |
|
||||
| `order quote` | Get a swap quote (no transaction submitted; requires critical auth) |
|
||||
| `order get` | Query order status |
|
||||
| `order strategy create` | Create a limit/strategy order (requires private key) |
|
||||
| `order strategy list` | List strategy orders (normal auth) |
|
||||
| `order strategy list` | List strategy orders (requires private key) |
|
||||
| `order strategy cancel` | Cancel a strategy order (requires private key) |
|
||||
|
||||
## Supported Chains
|
||||
@@ -70,7 +70,7 @@ Currency tokens are the base/native assets of each chain. They are used to buy o
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` must be configured in `~/.config/gmgn/.env`. The private key must correspond to the wallet bound to the API Key.
|
||||
`GMGN_API_KEY` must be configured in `~/.config/gmgn/.env`. `GMGN_PRIVATE_KEY` is additionally required for `swap` and all `order` subcommands. The private key must correspond to the wallet bound to the API Key.
|
||||
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
|
||||
@@ -87,6 +87,7 @@ All swap-related routes used by this skill go through GMGN's leaky-bucket limite
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- `swap` is a real transaction: never loop or auto-submit repeated swap attempts after a `429`. Wait until the reset time, then ask for confirmation again before retrying.
|
||||
- The CLI may wait and retry once automatically for short cooldowns on read-only commands such as `order quote` and `order get`. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes.
|
||||
@@ -164,7 +165,7 @@ gmgn-cli swap \
|
||||
|
||||
## `order quote` Usage
|
||||
|
||||
Get an estimated output amount before submitting a swap. Uses normal auth — no private key required.
|
||||
Get an estimated output amount before submitting a swap. All supported quote chains use critical auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
@@ -206,33 +207,113 @@ gmgn-cli order get --chain sol --order-id <order_id>
|
||||
| `--slippage <n>` | No | Slippage tolerance, e.g. `0.01` = 1%. **Mutually exclusive with `--auto-slippage`** — use one or the other. |
|
||||
| `--auto-slippage` | No | Enable automatic slippage. **Mutually exclusive with `--slippage`.** |
|
||||
| `--min-output <n>` | No | Minimum output amount |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection (default true) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection — **recommended**; protects against frontrunning and sandwich attacks. Default: on |
|
||||
| `--priority-fee <sol>` | No | Priority fee in SOL (≥ 0.00001, SOL only) |
|
||||
| `--tip-fee <n>` | No | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB) |
|
||||
| `--max-auto-fee <n>` | No | Max automatic fee cap |
|
||||
| `--gas-price <gwei>` | No | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--max-fee-per-gas <n>` | No | EIP-1559 max fee per gas (Base only) |
|
||||
| `--max-priority-fee-per-gas <n>` | No | EIP-1559 max priority fee per gas (Base only) |
|
||||
| `--condition-orders <json>` | No | 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 | 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 |
|
||||
|
||||
## `swap` Response Fields
|
||||
### ConditionOrder Fields (for `--condition-orders`)
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `order_id` | string | Order ID for follow-up queries |
|
||||
| `hash` | string | Transaction hash |
|
||||
| `status` | string | Order status: `pending` / `processed` / `confirmed` / `failed` / `expired` |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `error_status` | string | Error description on failure |
|
||||
| `input_token` | string | Input token contract address |
|
||||
| `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 |
|
||||
Each element in the `--condition-orders` JSON array supports:
|
||||
|
||||
| Field | Required | Type | Description |
|
||||
|-------|----------|------|-------------|
|
||||
| `order_type` | Yes | string | Sub-order type: `profit_stop` (fixed take-profit), `loss_stop` (fixed stop-loss), `profit_stop_trace` (trailing take-profit), `loss_stop_trace` (trailing stop-loss) |
|
||||
| `side` | Yes | string | Always `"sell"` |
|
||||
| `price_scale` | Conditional | string | Gain/drop % from entry. Required for `profit_stop` / `loss_stop` / `profit_stop_trace`; optional for `loss_stop_trace`. For `profit_stop` / `profit_stop_trace`: gain % (e.g. `"100"` = +100% / 2× entry). For `loss_stop` / `loss_stop_trace`: drop % (e.g. `"65"` = drops 65%, triggers at 35% of entry). |
|
||||
| `sell_ratio` | Yes | string | Percentage of position to sell when triggered, e.g. `"100"` = 100% |
|
||||
| `drawdown_rate` | Conditional | string | Required for `profit_stop_trace` and `loss_stop_trace`. Trailing callback %: after price peaks, how far it must fall before the order fires. E.g. `"50"` = 50% drawdown from peak. |
|
||||
|
||||
**Example — attach take-profit at 2× (+100%) and stop-loss at -60%:**
|
||||
|
||||
```json
|
||||
[
|
||||
{"order_type": "profit_stop", "side": "sell", "price_scale": "100", "sell_ratio": "100"},
|
||||
{"order_type": "loss_stop", "side": "sell", "price_scale": "60", "sell_ratio": "100"}
|
||||
]
|
||||
```
|
||||
|
||||
**Example — buy token A with 0.01 SOL, take-profit 50% at +100%, take-profit remaining 50% at +300%, stop-loss 100% at -65% (trigger at 35% entry price) (`hold_amount` mode):**
|
||||
|
||||
```bash
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type hold_amount
|
||||
```
|
||||
|
||||
> `price_scale` for `profit_stop`: gain % from entry (`"100"` = +100% / 2×, `"300"` = +300% / 4×). For `loss_stop`: drop % from entry (`"65"` = drops 65%, triggers at 35% of entry).
|
||||
> `hold_amount`: the second take-profit fires on whatever is held at trigger time (the remaining 50%). If you added to your position in between, those additional tokens will be included as well.
|
||||
|
||||
**Same strategy using `buy_amount` mode — fixed percentage of the original bought amount at each trigger:**
|
||||
|
||||
```bash
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_A_address> \
|
||||
--amount 10000000 \
|
||||
--slippage 0.3 \
|
||||
--anti-mev \
|
||||
--condition-orders '[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"profit_stop","side":"sell","price_scale":"300","sell_ratio":"50"},{"order_type":"loss_stop","side":"sell","price_scale":"65","sell_ratio":"100"}]' \
|
||||
--sell-ratio-type buy_amount
|
||||
```
|
||||
|
||||
> `buy_amount`: each take-profit sells 50% of the **original** bought amount. Stop-loss sells 100% of the original bought amount.
|
||||
|
||||
## `swap` / `order get` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------- | ------ | ---- |
|
||||
| `order_id` | string | Order ID for follow-up queries |
|
||||
| `hash` | string | Transaction hash |
|
||||
| `status` | string | Order status: `pending` / `processed` / `confirmed` / `failed` / `expired` |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `error_status` | string | Error description on failure |
|
||||
| `strategy_order_id` | string | Strategy order ID; only present when `--condition-orders` was passed and strategy creation succeeded (best-effort) |
|
||||
| `report` | object | Execution report; only present when `state = 30` and `status = "successful"`. See Report Fields below. |
|
||||
|
||||
### Report Fields (present only when `status = "successful"`)
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----------------------- | ------- | ---- |
|
||||
| `input_token` | string | Input token contract address |
|
||||
| `input_token_decimals` | integer | Input token decimal places |
|
||||
| `swap_mode` | string | Swap mode: `ExactIn` / `ExactOut` |
|
||||
| `input_amount` | string | Actual input consumed (smallest unit) |
|
||||
| `output_token` | string | Output token contract address |
|
||||
| `output_token_decimals` | integer | Output token decimal places |
|
||||
| `output_amount` | string | Actual output received (smallest unit) |
|
||||
| `quote_token` | string | Quote token contract address |
|
||||
| `quote_decimals` | integer | Quote token decimal places |
|
||||
| `quote_amount` | string | Quote amount (smallest unit) |
|
||||
| `base_token` | string | Base token contract address |
|
||||
| `base_decimals` | integer | Base token decimal places |
|
||||
| `base_amount` | string | Base token amount (smallest unit) |
|
||||
| `price` | string | Execution price (quote/base token) |
|
||||
| `price_usd` | string | Execution price in USD |
|
||||
| `height` | integer | Block height of execution |
|
||||
| `order_height` | integer | Block height when order was placed |
|
||||
| `gas_native` | string | Gas fee in native token |
|
||||
| `gas_usd` | string | Gas fee in USD |
|
||||
|
||||
## Output Format
|
||||
|
||||
### Pre-swap Confirmation
|
||||
|
||||
Before displaying the confirmation, run `order quote` to get the estimated output (uses normal auth — no private key required):
|
||||
Before displaying the confirmation, run `order quote` to get the estimated output (requires critical auth and `GMGN_PRIVATE_KEY` on every supported quote chain):
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
@@ -274,13 +355,13 @@ After a confirmed swap, display:
|
||||
```
|
||||
✅ Swap Confirmed
|
||||
|
||||
Spent: {filled_input_amount in human units} {input symbol}
|
||||
Received: {filled_output_amount in human units} {output symbol}
|
||||
Spent: {report.input_amount in human units} {input symbol}
|
||||
Received: {report.output_amount in human units} {output symbol}
|
||||
Tx: {explorer link for hash}
|
||||
Order ID: {order_id}
|
||||
```
|
||||
|
||||
Convert `filled_input_amount` and `filled_output_amount` from smallest unit using token decimals before displaying.
|
||||
Convert `report.input_amount` and `report.output_amount` from smallest unit using `report.input_token_decimals` and `report.output_token_decimals` before displaying.
|
||||
|
||||
## `order strategy create` Parameters
|
||||
|
||||
@@ -290,22 +371,23 @@ Convert `filled_input_amount` and `filled_output_amount` from smallest unit usin
|
||||
| `--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 | Direction: `buy` / `sell` |
|
||||
| `--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 |
|
||||
| `--amount-in` | No* | Input amount (smallest unit). Mutually exclusive with `--amount-in-percent` |
|
||||
| `--amount-in-percent` | No* | Input as percentage (e.g. `50` = 50%). Mutually exclusive with `--amount-in` |
|
||||
| `--limit-price-mode` | No | `exact` / `slippage` (default: `slippage`) |
|
||||
| `--expire-in` | No | Order expiry in seconds |
|
||||
| `--sell-ratio-type` | No | `buy_amount` (default) / `hold_amount` |
|
||||
| `--sell-ratio-type` | No | `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 |
|
||||
| `--slippage` | No | Slippage tolerance, e.g. `0.01` = 1%. Mutually exclusive with `--auto-slippage` |
|
||||
| `--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) |
|
||||
| `--gas-price` | No | Gas price in gwei (BSC ≥ 0.05 gwei / BASE/ETH ≥ 0.01 gwei) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection |
|
||||
|
||||
|
||||
**`order strategy create` Response Fields:**
|
||||
### `order strategy create` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
@@ -319,11 +401,12 @@ Convert `filled_input_amount` and `filled_output_amount` from smallest unit usin
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--type` | No | `open` (default) / `history` |
|
||||
| `--from` | No | Filter by wallet address |
|
||||
| `--group-tag` | Yes | Filter by order group: `LimitOrder` (limit orders only) / `STMix` (mixed strategy orders: take-profit, stop-loss, trailing take-profit, trailing stop-loss) |
|
||||
| `--base-token` | No | Filter by token address |
|
||||
| `--page-token` | No | Pagination cursor from previous response |
|
||||
| `--limit` | No | Results per page (default 10 for history) |
|
||||
|
||||
**`order strategy list` Response Fields:**
|
||||
### `order strategy list` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
@@ -338,6 +421,7 @@ Convert `filled_input_amount` and `filled_output_amount` from smallest unit usin
|
||||
| `--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` (limit order) / `smart_trade` (mixed strategy order: take-profit, stop-loss, trailing take-profit, trailing stop-loss) |
|
||||
| `--close-sell-model` | No | Sell model when closing the order |
|
||||
|
||||
## `order strategy` Usage Examples
|
||||
@@ -349,6 +433,7 @@ gmgn-cli order strategy create \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--order-type limit_order \
|
||||
--sub-order-type take_profit \
|
||||
--check-price 0.002 \
|
||||
--amount-in 1000000 \
|
||||
@@ -360,16 +445,23 @@ gmgn-cli order strategy create \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--order-type limit_order \
|
||||
--sub-order-type stop_loss \
|
||||
--check-price 0.0005 \
|
||||
--amount-in-percent 100 \
|
||||
--slippage 0.01
|
||||
|
||||
# List open strategy orders
|
||||
gmgn-cli order strategy list --chain sol
|
||||
# List open condition orders (profit_stop / loss_stop / trace types) — use STMix
|
||||
gmgn-cli order strategy list --chain sol --group-tag STMix
|
||||
|
||||
# List history orders with pagination
|
||||
gmgn-cli order strategy list --chain sol --type history --limit 20
|
||||
# List open limit orders (buy_low / buy_high / stop_loss / take_profit) — use LimitOrder
|
||||
gmgn-cli order strategy list --chain sol --group-tag LimitOrder
|
||||
|
||||
# List condition order history with pagination
|
||||
gmgn-cli order strategy list --chain sol --group-tag STMix --type history --limit 20
|
||||
|
||||
# Filter by token
|
||||
gmgn-cli order strategy list --chain sol --group-tag STMix --base-token <token_address>
|
||||
|
||||
# Cancel a strategy order
|
||||
gmgn-cli order strategy cancel \
|
||||
@@ -383,7 +475,7 @@ gmgn-cli order strategy cancel \
|
||||
- Swap uses **critical 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` and `order strategy cancel` use critical auth (require `GMGN_PRIVATE_KEY`); `order strategy list` uses normal auth
|
||||
- `order strategy create`, `order strategy list`, and `order strategy cancel` use critical auth (require `GMGN_PRIVATE_KEY`)
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
|
||||
## Input Validation
|
||||
@@ -431,7 +523,7 @@ For full token research before swapping, see [`docs/workflow-token-research.md`]
|
||||
- **Percentage sell restriction** — `--percent` is ONLY valid when `input_token` is NOT a currency. Do NOT use `--percent` when `input_token` is SOL/BNB/ETH (native) or USDC. This includes: "sell 50% of my SOL", "use 30% of my BNB to buy X", "spend 50% of my USDC on X" — all unsupported. Explain the restriction to the user and ask for an explicit absolute amount instead.
|
||||
- **Chain-wallet compatibility** — SOL addresses are incompatible with EVM chains (bsc/base). Warn the user and abort if the address format does not match the chain.
|
||||
- **Credential sensitivity** — `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` can directly execute trades on the linked wallet. Never log, display, or expose these values.
|
||||
- **Order polling** — After a swap, if `status` is not yet `confirmed` / `failed` / `expired`, poll with `order get` up to 3 times at 5-second intervals before reporting a timeout. Once confirmed, display the trade result using `filled_input_amount` and `filled_output_amount` (convert from smallest unit using token decimals), e.g. "Spent 0.1 SOL → received 98.5 USDC" or "Sold 1000 TOKEN → received 0.08 SOL".
|
||||
- **Order polling** — After a swap, if `status` is not yet `confirmed` / `failed` / `expired`, poll with `order get` up to 3 times at 5-second intervals before reporting a timeout. Once confirmed, display the trade result using `report.input_amount` and `report.output_amount` (convert from smallest unit using `report.input_token_decimals` / `report.output_token_decimals`), e.g. "Spent 0.1 SOL → received 98.5 USDC" or "Sold 1000 TOKEN → received 0.08 SOL".
|
||||
- **Block explorer links** — After a successful swap, display a clickable explorer link for the returned `hash`:
|
||||
|
||||
| Chain | Explorer |
|
||||
|
||||
@@ -64,6 +64,7 @@ All token routes used by this skill go through GMGN's leaky-bucket limiter with
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes. Do not spam retries.
|
||||
|
||||
@@ -141,7 +142,7 @@ Recommended combinations for common use cases:
|
||||
|
||||
### `token info` — Key Fields
|
||||
|
||||
The response has four nested objects: `pool`, `link`, `stat`, `wallet_tags_stat`. Access fields with dot notation when parsing (e.g. `link.website`, `stat.top_10_holder_rate`).
|
||||
The response has five nested objects: `pool`, `dev`, `link`, `stat`, `wallet_tags_stat`. Access fields with dot notation when parsing (e.g. `link.website`, `stat.top_10_holder_rate`, `dev.creator_address`).
|
||||
|
||||
**Top-level Fields**
|
||||
|
||||
@@ -178,6 +179,31 @@ The response has four nested objects: `pool`, `link`, `stat`, `wallet_tags_stat`
|
||||
| `pool.fee_ratio` | Pool trading fee ratio (e.g. `0.1` = 0.1%) |
|
||||
| `pool.creation_timestamp` | Pool creation time (Unix seconds) |
|
||||
|
||||
**`dev` Object** — Token creator / developer info
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `dev.creator_address` | Creator wallet address |
|
||||
| `dev.creator_token_balance` | Creator's current token balance |
|
||||
| `dev.creator_token_status` | Creator holding status: `hold` (still holding) / `sell` (sold/exited) |
|
||||
| `dev.top_10_holder_rate` | Ratio of supply held by top 10 wallets (0–1) |
|
||||
| `dev.twitter_name_change_history` | Array of past Twitter username changes (each entry has `twitter_username`, `rename_timestamp`) |
|
||||
| `dev.dexscr_ad` | Creator bought a DEXScreener ad: `1` = yes, `0` = no |
|
||||
| `dev.dexscr_update_link` | Creator updated DEXScreener socials/links: `1` = yes, `0` = no |
|
||||
| `dev.dexscr_boost_fee` | Creator used DEXScreener Boost: `1` = yes, `0` = no |
|
||||
| `dev.dexscr_trending_bar` | Token appeared in DEXScreener trending bar: `1` = yes, `0` = no |
|
||||
| `dev.dexscr_ad_ts` | Timestamp of DEXScreener ad purchase (Unix seconds) |
|
||||
| `dev.dexscr_update_link_ts` | Timestamp of DEXScreener link update (Unix seconds) |
|
||||
| `dev.dexscr_boost_ts` | Timestamp of DEXScreener Boost (Unix seconds) |
|
||||
| `dev.dexscr_trending_bar_ts` | Timestamp of DEXScreener trending bar appearance (Unix seconds) |
|
||||
| `dev.cto_flag` | Token has been Community Takeover'd (original dev abandoned): `1` = yes, `0` = no |
|
||||
| `dev.fund_from` | Address that funded the creator wallet |
|
||||
| `dev.fund_from_ts` | Timestamp of that funding event (Unix seconds) |
|
||||
| `dev.creator_open_count` | Number of tokens this creator has previously launched |
|
||||
| `dev.twitter_del_post_token_count` | Number of posts the creator deleted from Twitter |
|
||||
| `dev.twitter_create_token_count` | Number of tokens the creator has promoted on Twitter |
|
||||
| `dev.offchain` | Whether the token is an offchain token |
|
||||
|
||||
**`link` Object** — Social and explorer links
|
||||
|
||||
| Field | Description |
|
||||
@@ -211,6 +237,7 @@ The response has four nested objects: `pool`, `link`, `stat`, `wallet_tags_stat`
|
||||
| `stat.bot_degen_count` | Number of bot degen wallets |
|
||||
| `stat.bot_degen_rate` | Ratio of bot degen wallets |
|
||||
| `stat.fresh_wallet_rate` | Ratio of fresh/new wallets among holders |
|
||||
| `stat.private_vault_hold_rate` | Ratio held by private vault (vanish) addresses — displayed as "vanish" in GMGN UI (0–1) |
|
||||
|
||||
**`wallet_tags_stat` Object** — Wallet type breakdown
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ All tracking routes used by this skill go through GMGN's leaky-bucket limiter wi
|
||||
When a request returns `429`:
|
||||
|
||||
- Read `X-RateLimit-Reset` from the response headers. It is a Unix timestamp in seconds that marks when the limit is expected to reset.
|
||||
- If the response body contains `reset_at` (e.g., `{"code":429,"error":"RATE_LIMIT_BANNED","message":"...","reset_at":1775184222}`), extract `reset_at` — it is the Unix timestamp when the ban lifts (typically 5 minutes). Convert to local time and tell the user exactly when they can retry.
|
||||
- The CLI may wait and retry once automatically when the remaining cooldown is short. If it still fails, stop and tell the user the exact retry time instead of sending more requests.
|
||||
- For `RATE_LIMIT_EXCEEDED` or `RATE_LIMIT_BANNED`, repeated requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes. Do not spam retries.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Auth modes:
|
||||
* Normal (market/token/portfolio): X-APIKEY + timestamp + client_id
|
||||
* Critical (swap/order): normal auth + X-Signature (private key signature)
|
||||
* Critical (swap and order routes): normal auth + X-Signature (private key signature)
|
||||
*/
|
||||
|
||||
import { buildAuthQuery, buildMessage, detectAlgorithm, sign } from "./signer.js";
|
||||
@@ -90,10 +90,11 @@ export interface SwapParams {
|
||||
}
|
||||
|
||||
export interface StrategyConditionOrder {
|
||||
order_type: string; // "profit_stop" | "loss_stop"
|
||||
order_type: string; // "profit_stop" | "loss_stop" | "profit_stop_trace" | "loss_stop_trace"
|
||||
side: string; // "sell"
|
||||
price_scale: string;
|
||||
price_scale?: string;
|
||||
sell_ratio: string;
|
||||
drawdown_rate?: string;
|
||||
}
|
||||
|
||||
export interface StrategyCreateParams {
|
||||
@@ -104,6 +105,7 @@ export interface StrategyCreateParams {
|
||||
order_type: string;
|
||||
sub_order_type: string;
|
||||
check_price: string;
|
||||
open_price?: string;
|
||||
amount_in?: string;
|
||||
amount_in_percent?: string;
|
||||
limit_price_mode?: string;
|
||||
@@ -291,9 +293,8 @@ export class OpenApiClient {
|
||||
input_amount: string,
|
||||
slippage: number
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/trade/quote", {
|
||||
chain, from_address, input_token, output_token, input_amount, slippage,
|
||||
});
|
||||
const query = { chain, from_address, input_token, output_token, input_amount, slippage };
|
||||
return this.criticalRequest("GET", "/v1/trade/quote", query, null);
|
||||
}
|
||||
|
||||
// ---- Swap endpoints (critical auth) ----
|
||||
@@ -306,14 +307,14 @@ export class OpenApiClient {
|
||||
return this.criticalRequest("GET", "/v1/trade/query_order", { order_id: orderId, chain }, null);
|
||||
}
|
||||
|
||||
// ---- Strategy order endpoints ----
|
||||
// ---- Strategy order endpoints (critical auth) ----
|
||||
|
||||
async createStrategyOrder(params: StrategyCreateParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/strategy/create", {}, params);
|
||||
}
|
||||
|
||||
async getStrategyOrders(chain: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/trade/strategy/orders", { chain, ...extra });
|
||||
return this.criticalRequest("GET", "/v1/trade/strategy/orders", { chain, ...extra }, null);
|
||||
}
|
||||
|
||||
async cancelStrategyOrder(params: StrategyCancelParams): Promise<unknown> {
|
||||
@@ -365,7 +366,7 @@ export class OpenApiClient {
|
||||
body: unknown
|
||||
): Promise<unknown> {
|
||||
if (!this.privateKeyPem) {
|
||||
throw new Error("GMGN_PRIVATE_KEY is required for swap/order commands");
|
||||
throw new Error("GMGN_PRIVATE_KEY is required for critical-auth commands (swap and all order commands)");
|
||||
}
|
||||
|
||||
return this.executePreparedRequest(() => {
|
||||
|
||||
@@ -24,7 +24,7 @@ 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("--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"}]\'; trace types: \'[{"order_type":"profit_stop_trace","side":"sell","price_scale":"150","sell_ratio":"100","drawdown_rate":"50"}]\'')
|
||||
.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) => {
|
||||
@@ -75,8 +75,8 @@ export function registerSwapCommands(program: Command): void {
|
||||
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.description("Get a swap quote without submitting a transaction (requires critical auth)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base (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")
|
||||
@@ -89,7 +89,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
validateAddress(opts.inputToken, opts.chain, "--input-token");
|
||||
validateAddress(opts.outputToken, opts.chain, "--output-token");
|
||||
validatePositiveInt(opts.amount, "--amount");
|
||||
const client = new OpenApiClient(getConfig());
|
||||
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);
|
||||
@@ -170,7 +170,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
|
||||
strategy
|
||||
.command("list")
|
||||
.description("List strategy orders (normal auth)")
|
||||
.description("List strategy orders (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.option("--type <type>", "open (default) / history")
|
||||
.option("--from <address>", "Filter by wallet address")
|
||||
@@ -188,7 +188,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
if (opts.baseToken) extra["base_token"] = opts.baseToken;
|
||||
if (opts.pageToken) extra["page_token"] = opts.pageToken;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.getStrategyOrders(opts.chain, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
+4
-2
@@ -14,11 +14,13 @@ export interface Config {
|
||||
}
|
||||
|
||||
let _config: Config | null = null;
|
||||
const PRIVATE_KEY_REQUIRED_MSG =
|
||||
"GMGN_PRIVATE_KEY is required for critical-auth commands (swap and all order commands)";
|
||||
|
||||
export function getConfig(requirePrivateKey = false): Config {
|
||||
if (_config) {
|
||||
if (requirePrivateKey && !_config.privateKeyPem) {
|
||||
die("GMGN_PRIVATE_KEY is required for swap/order commands");
|
||||
die(PRIVATE_KEY_REQUIRED_MSG);
|
||||
}
|
||||
return _config;
|
||||
}
|
||||
@@ -34,7 +36,7 @@ export function getConfig(requirePrivateKey = false): Config {
|
||||
// Support escaped newlines (e.g. from single-line .env values)
|
||||
privateKeyPem = privateKey.replace(/\\n/g, "\n");
|
||||
} else if (requirePrivateKey) {
|
||||
die("GMGN_PRIVATE_KEY is required for swap/order commands");
|
||||
die(PRIVATE_KEY_REQUIRED_MSG);
|
||||
}
|
||||
|
||||
const host = process.env.GMGN_HOST ?? "https://openapi.gmgn.ai";
|
||||
|
||||
Reference in New Issue
Block a user