mirror of
https://github.com/GMGNAI/gmgn-skills.git
synced 2026-07-29 09:47:44 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b18d7deb32 | |||
| ddbfafdac5 | |||
| 316840d84d | |||
| f6e3bc4ef7 | |||
| 1e45828c8c | |||
| 2c88807988 | |||
| 2670188acb | |||
| 2d7d0043e6 | |||
| 0e1ba6181c | |||
| b7b6250766 | |||
| e3b713b150 | |||
| ac1ea2e336 | |||
| b782743c8c | |||
| d56c904b26 | |||
| 3ecd76c572 | |||
| d0e9e42f17 | |||
| 18a0bf98b1 | |||
| 88643ca05c | |||
| d701420705 | |||
| 48a94a46a5 | |||
| ec35707d15 | |||
| cc2fc0ed00 | |||
| 5453373ffa | |||
| e8af4b88b5 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
|
||||
"name": "gmgn-cli",
|
||||
"description": "GMGN OpenAPI skills for AI coding assistants — token info, market data, wallet portfolio, and swap execution across sol / bsc / base / eth / monad",
|
||||
"description": "GMGN OpenAPI skills for AI coding assistants — token info, market data, wallet portfolio, and swap execution across sol / bsc / base / eth / robinhood",
|
||||
"owner": {
|
||||
"name": "GMGN"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"description": "GMGN OpenAPI skills — token info, market data, wallet portfolio, and swap execution across sol / bsc / base / eth / monad",
|
||||
"description": "GMGN OpenAPI skills — token info, market data, wallet portfolio, and swap execution across sol / bsc / base / eth / robinhood",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "GMGN"
|
||||
|
||||
@@ -726,9 +726,11 @@ gmgn-cli cooking \
|
||||
|
||||
| Commands | Chains | Chain Currencies |
|
||||
|----------|--------|-----------------|
|
||||
| token / market / portfolio / track | `sol` / `bsc` / `base` / `eth` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` / `eth` | sol: SOL, USDC · bsc: BNB, USDC · base: ETH, USDC · eth: ETH |
|
||||
| gas-price | `sol` / `bsc` / `base` / `eth` | — |
|
||||
| token / market / portfolio / track | `sol` / `bsc` / `base` / `eth` / `robinhood` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` / `eth` / `robinhood` | sol: SOL, USDC · bsc: BNB, USDC · base: ETH, USDC · eth: ETH |
|
||||
| gas-price | `sol` / `bsc` / `base` / `eth` / `robinhood` | — |
|
||||
| track kol / track smartmoney · market signal | `sol` / `bsc` / `base` / `eth` (kol/smartmoney) · `sol` / `bsc` (signal) — **no `robinhood`** | — |
|
||||
| cooking create | `sol` / `bsc` / `base` — **no `robinhood`** | — |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+5
-3
@@ -750,9 +750,11 @@ gmgn-cli cooking \
|
||||
|
||||
| 接口类型 | 支持的链 | 链原生货币 |
|
||||
|----------|----------|-----------|
|
||||
| token / market / portfolio / track | `sol` / `bsc` / `base` / `eth` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` / `eth` | sol: SOL、USDC · bsc: BNB、USDC · base: ETH、USDC · eth: ETH |
|
||||
| gas-price | `sol` / `bsc` / `base` / `eth` | — |
|
||||
| token / market / portfolio / track | `sol` / `bsc` / `base` / `eth` / `robinhood` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` / `eth` / `robinhood` | sol: SOL、USDC · bsc: BNB、USDC · base: ETH、USDC · eth: ETH |
|
||||
| gas-price | `sol` / `bsc` / `base` / `eth` / `robinhood` | — |
|
||||
| track kol / track smartmoney · market signal | `sol` / `bsc` / `base` / `eth`(kol/smartmoney)· `sol` / `bsc`(signal)— **不支持 `robinhood`** | — |
|
||||
| cooking create | `sol` / `bsc` / `base` — **不支持 `robinhood`** | — |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+10
-10
@@ -126,7 +126,7 @@ npx gmgn-cli market trending \
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--interval` | Yes | `1m` / `5m` / `1h` / `6h` / `24h` |
|
||||
| `--limit` | No | Number of results (default 100, max 100) |
|
||||
| `--order-by` | No | Sort field: `volume` / `swaps` / `liquidity` / `marketcap` / `holders` / `price` / `change` / `change1m` / `change5m` / `change1h` / `renowned_count` / `smart_degen_count` / `bluechip_owner_percentage` / `rank` / `creation_timestamp` / `square_mentions` / `history_highest_market_cap` / `gas_fee` |
|
||||
@@ -294,7 +294,7 @@ npx gmgn-cli market trenches --chain <chain> [--type <type...>] [--launchpad-pla
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--type` | No | Categories to query, repeatable: `new_creation` / `near_completion` / `completed` (default: all three) |
|
||||
| `--launchpad-platform` | No | Launchpad platform filter, repeatable (default: all platforms for the chain). Values depend on chain — see below. |
|
||||
| `--limit` | No | Max results per category, max 80 (default: 80) |
|
||||
@@ -367,7 +367,7 @@ gmgn-cli market signal --chain sol --groups '<json_array>' [--raw]
|
||||
Query the hot-search ranking — the most-searched tokens, ranked by `visiting_count` (search heat). Cross-chain top-500; one request can cover several chains at once. API Key auth only.
|
||||
|
||||
```bash
|
||||
# Default 7-chain set (sol/bsc/base/eth/hyperevm/megaeth/monad, each 24h):
|
||||
# Default 5-chain set (sol/bsc/base/eth/robinhood, each 24h):
|
||||
gmgn-cli market hot-searches [--raw]
|
||||
|
||||
# Specific chain(s) and interval:
|
||||
@@ -379,7 +379,7 @@ gmgn-cli market hot-searches --params '<json_array>' [--raw]
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | No | Repeatable: `sol` / `bsc` / `base` / `eth` / `monad` / `megaeth` / `hyperevm` / `tron`. Omit for the default 7-chain set. |
|
||||
| `--chain` | No | Repeatable: `sol` / `bsc` / `base` / `eth` / `robinhood`. Omit for the default 5-chain set. |
|
||||
| `--interval` | No | `1m` / `5m` / `1h` / `6h` / `24h` (default `24h`). Applies to every `--chain`. |
|
||||
| `--limit` | No | Max results per chain (default `500`). |
|
||||
| `--filter` | No | Repeatable **boolean** filter tags (downstream `filter.filters`). sol defaults: `renounced` / `frozen`; EVM defaults: `not_honeypot` / `verified` / `renounced`. Recognised tags: `renounced` / `frozen` (sol) / `is_burnt` / `token_burnt` / `not_wash_trading` / `not_honeypot` (EVM) / `verified` (EVM) / `locked` (EVM) / `has_social` / `distribed` / `not_risk` / `img_not_duplicate` / `social_not_duplicate` / `creator_hold` / `creator_close` / `dexscr_update_link` / `launching` / `migrated` / `hide_b20` (base) / `hide_non_b20` (base). Unknown tags are silent no-ops. |
|
||||
@@ -408,7 +408,7 @@ gmgn-cli track follow-tokens \
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--wallet` | Yes | Wallet address |
|
||||
| `--group-id` | No | `all_group` (all tokens), `default`, or a user-defined group ID |
|
||||
| `--interval` | No | Time interval for price change stats: `1m` / `5m` / `1h` / `6h` / `24h` |
|
||||
@@ -433,7 +433,7 @@ gmgn-cli track follow-token-groups \
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--wallet` | Yes | Wallet address |
|
||||
|
||||
---
|
||||
@@ -562,7 +562,7 @@ npx gmgn-cli swap \
|
||||
|
||||
| Option | Required | Chain | Description |
|
||||
|--------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--from` | Yes | all | Wallet address (must match the wallet bound to the API Key) |
|
||||
| `--input-token` | Yes | all | Input token contract address |
|
||||
| `--output-token` | Yes | all | Output token contract address |
|
||||
@@ -639,7 +639,7 @@ gmgn-cli multi-swap \
|
||||
|
||||
| Option | Required | Chain | Description |
|
||||
|--------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--accounts` | Yes | all | Comma-separated wallet addresses (1–100, all bound to API Key) |
|
||||
| `--input-token` | Yes | all | Input token contract address |
|
||||
| `--output-token` | Yes | all | Output token contract address |
|
||||
@@ -682,7 +682,7 @@ npx gmgn-cli order get --chain <chain> --order-id <order_id> [--raw]
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `monad` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--order-id` | Yes | Order ID (returned by the `swap` command) |
|
||||
|
||||
**Response fields (data):** Same structure as the `swap` response above.
|
||||
@@ -717,7 +717,7 @@ gmgn-cli order strategy create \
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--base-token` | Yes | Base token contract address |
|
||||
| `--quote-token` | Yes | Quote token contract address |
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.4.9",
|
||||
"version": "1.5.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.4.9",
|
||||
"version": "1.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^12.1.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.4.9",
|
||||
"version": "1.5.2",
|
||||
"description": "GMGN OpenAPI CLI — call GMGN market, token, portfolio and swap APIs from the command line",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -6,6 +6,8 @@ metadata:
|
||||
cliHelp: "gmgn-cli cooking --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai — all token creation operations must go through the CLI. The CLI handles signing and submission automatically.**
|
||||
|
||||
**IMPORTANT: Do NOT guess field names or values. When a field's meaning is unclear, look it up in the Response Fields sections below before using it.**
|
||||
@@ -100,23 +102,6 @@ When a request returns `429`:
|
||||
- `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.
|
||||
|
||||
**First-time setup** (if credentials are not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form (enable swap/cooking capability), then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then configure both credentials:
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
echo 'GMGN_API_KEY=<key_from_user>' > ~/.config/gmgn/.env
|
||||
echo 'GMGN_PRIVATE_KEY="<pem_content_from_step_1>"' >> ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
### Credential Model
|
||||
|
||||
- `GMGN_PRIVATE_KEY` is used exclusively for **local message signing** — the private key never leaves the machine. The CLI computes an Ed25519 signature in-process and transmits only the base64-encoded result in the `X-Signature` request header.
|
||||
|
||||
+12
-24
@@ -1,11 +1,13 @@
|
||||
---
|
||||
name: gmgn-market
|
||||
description: Get crypto and meme token price charts (K-line, candlestick, OHLCV), trending meme coin rankings by volume, newly launched tokens on launchpads (pump.fun, fourmeme, letsbonk, Raydium, etc.), and the hot-search ranking (most-searched tokens) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks for price chart, trending tokens, what's pumping, hot coins, most searched tokens, new launches, token signals, or wants to discover early-stage opportunities.
|
||||
argument-hint: "kline --chain <sol|bsc|base|eth> --address <token_address> --resolution <30s|1m|5m|15m|1h|4h|1d> [--from <unix_ts>] [--to <unix_ts>] | trending --chain <sol|bsc|base|eth> --interval <1m|5m|1h|6h|24h> | trenches --chain <sol|bsc|base|eth> | signal --chain <sol|bsc> | hot-searches [--chain <sol|bsc|base|eth|monad|megaeth|hyperevm|tron...>] [--interval <1m|5m|1h|6h|24h>]"
|
||||
argument-hint: "kline --chain <sol|bsc|base|eth|robinhood> --address <token_address> --resolution <30s|1m|5m|15m|1h|4h|1d> [--from <unix_ts>] [--to <unix_ts>] | trending --chain <sol|bsc|base|eth|robinhood> --interval <1m|5m|1h|6h|24h> | trenches --chain <sol|bsc|base|eth|robinhood> | signal --chain <sol|bsc> | hot-searches [--chain <sol|bsc|base|eth|robinhood...>] [--interval <1m|5m|1h|6h|24h>]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli market --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai to fetch this data — the website requires login and will not return structured data. The CLI is the only correct method.**
|
||||
|
||||
**IMPORTANT: Do NOT guess field names or values. When a field's meaning is unclear, look it up in the Response Fields sections below before using it.**
|
||||
@@ -53,7 +55,7 @@ Use the `gmgn-cli` tool to query K-line data for a token, browse trending tokens
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth` (kline / trending / trenches; signal: `sol` / `bsc` only; hot-searches: `sol` / `bsc` / `base` / `eth` / `monad` / `megaeth` / `hyperevm` / `tron`)
|
||||
`sol` / `bsc` / `base` / `eth` / `robinhood` (kline / trending / trenches; signal: `sol` / `bsc` only; hot-searches: `sol` / `bsc` / `base` / `eth` / `robinhood`)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -79,25 +81,11 @@ When a request returns `429`:
|
||||
- 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.
|
||||
|
||||
**First-time setup** (if `GMGN_API_KEY` is not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form, then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then save it with `gmgn-cli config` (creates `~/.config/gmgn/.env` and sets `chmod 600` automatically — do not hand-edit the file):
|
||||
```bash
|
||||
gmgn-cli config set-key <key_from_user>
|
||||
```
|
||||
|
||||
## `market kline` Parameters
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--address` | Yes | Token contract address |
|
||||
| `--resolution` | Yes | Candlestick resolution: `30s` / `1m` / `5m` / `15m` / `1h` / `4h` / `1d` |
|
||||
| `--from` | No | Start time (Unix seconds) |
|
||||
@@ -140,7 +128,7 @@ The response is an object with a `list` array. Each element in `list` is one can
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--interval` | Required. `1m` / `5m` / `1h` / `6h` / `24h` (default `1h`) |
|
||||
| `--limit <n>` | Number of results (default 100, max 100) |
|
||||
| `--order-by <field>` | Sort field: `default` / `swaps` / `marketcap` / `history_highest_market_cap` / `liquidity` / `volume` / `holder_count` / `smart_degen_count` / `renowned_count` / `gas_fee` / `price` / `change1m` / `change5m` / `change1h` / `creation_timestamp` |
|
||||
@@ -554,7 +542,7 @@ Use field combinations to determine what stage a token is in. This affects how s
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--type` | No | Categories to query, repeatable: `new_creation` / `near_completion` / `completed` (default: all three) |
|
||||
| `--launchpad-platform` | No | Launchpad platform filter, repeatable (default: all platforms for the chain) |
|
||||
| `--limit` | No | Max results per category, max 80 (default: 80) |
|
||||
@@ -1049,7 +1037,7 @@ Returns the hot-search ranking — the tokens people are searching for most righ
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain <chain...>` | Repeatable. `sol` / `bsc` / `base` / `eth` / `monad` / `megaeth` / `hyperevm` / `tron`. **Omit to query the default 7-chain set** (sol / bsc / base / eth / hyperevm / megaeth / monad, each at `24h` with chain-appropriate safety filters). |
|
||||
| `--chain <chain...>` | Repeatable. `sol` / `bsc` / `base` / `eth` / `robinhood`. **Omit to query the default 5-chain set** (sol / bsc / base / eth / robinhood, each at `24h` with chain-appropriate safety filters). |
|
||||
| `--interval <interval>` | `1m` / `5m` / `1h` / `6h` / `24h` (default `24h`). Applies to every `--chain` provided. |
|
||||
| `--limit <n>` | Max results per chain (default `500`). |
|
||||
| `--filter <tag...>` | Repeatable **boolean** filter tags (the downstream `filter.filters` array). **⚠️ SOL defaults: `renounced frozen`; EVM defaults: `not_honeypot verified renounced`.** Omitting `--filter` is NOT "no filter" — the server applies chain defaults. See the Filter Tags table below for the exact vocabulary. |
|
||||
@@ -1115,9 +1103,9 @@ Numeric bounds use the **same rank-style metric names as `market trending`**. Th
|
||||
|
||||
**Notes on behaviour:**
|
||||
|
||||
- `--chain all` is **not** valid. To aggregate across chains, pass `--chain` multiple times (or omit `--chain` for the default 7-chain set).
|
||||
- `--chain all` is **not** valid. To aggregate across chains, pass `--chain` multiple times (or omit `--chain` for the default 5-chain set).
|
||||
- When you pass `--chain` but omit `--filter`, the **server** applies the chain-appropriate default filters — so each chain is filtered even without an explicit `--filter`.
|
||||
- Different chains return different counts: a chain's token count depends on how many of its tokens made the global top-500 (sol is usually the largest; monad / megaeth are small).
|
||||
- Different chains return different counts: a chain's token count depends on how many of its tokens made the global top-500 (sol is usually the largest).
|
||||
|
||||
## `market hot-searches` Response Fields
|
||||
|
||||
@@ -1151,7 +1139,7 @@ See the [`market trending` Response Fields](#market-trending-response-fields) se
|
||||
### `market hot-searches` Usage Examples
|
||||
|
||||
```bash
|
||||
# Default 7-chain hot-search ranking (sol/bsc/base/eth/hyperevm/megaeth/monad, each 24h)
|
||||
# Default 5-chain hot-search ranking (sol/bsc/base/eth/robinhood, each 24h)
|
||||
gmgn-cli market hot-searches --raw
|
||||
|
||||
# SOL only, 24h hot-search list
|
||||
@@ -1194,7 +1182,7 @@ Present per chain, ranked by `visiting_count` (search heat):
|
||||
|
||||
- `market kline`: `--from` and `--to` are Unix timestamps in **seconds** — CLI converts to milliseconds automatically
|
||||
- `market trending`: `--filter` and `--platform` are repeatable flags
|
||||
- `market hot-searches`: `--chain` and `--filter` are repeatable flags; omit `--chain` to query the default 7-chain set. `--min-*`/`--max-*` range flags reuse the same metric names as `market trending` and are translated server-side per `--interval`
|
||||
- `market hot-searches`: `--chain` and `--filter` are repeatable flags; omit `--chain` to query the default 5-chain set. `--min-*`/`--max-*` range flags reuse the same metric names as `market trending` and are translated server-side per `--interval`
|
||||
- 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
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
---
|
||||
name: gmgn-portfolio
|
||||
description: Analyze any crypto wallet by address — holdings, realized/unrealized P&L, win rate, trading history, performance stats, specific token balance, and tokens created by a developer wallet (with ATH market cap and DEX graduation status) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks about a wallet's holdings, P&L, win rate, what tokens a dev has launched, the highest ATH token a dev ever created, or wants a wallet report to decide whether to copy-trade or follow.
|
||||
argument-hint: "<info|holdings|activity|stats|token-balance|created-tokens> [--chain <sol|bsc|base|eth>] [--wallet <wallet_address>]"
|
||||
argument-hint: "<info|holdings|activity|stats|token-balance|created-tokens> [--chain <sol|bsc|base|eth|robinhood>] [--wallet <wallet_address>]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli portfolio --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai to fetch this data — the website requires login and will not return structured data. The CLI is the only correct method.**
|
||||
|
||||
**⚠️ 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."**
|
||||
@@ -43,7 +45,7 @@ Use the `gmgn-cli` tool to query wallet portfolio data based on the user's reque
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
`sol` / `bsc` / `base` / `eth` / `robinhood`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -77,22 +79,6 @@ When a request returns `429`:
|
||||
- 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.
|
||||
|
||||
**First-time setup** (if `GMGN_API_KEY` is not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form, then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then configure:
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
echo 'GMGN_API_KEY=<key_from_user>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```bash
|
||||
|
||||
+17
-33
@@ -6,6 +6,8 @@ metadata:
|
||||
cliHelp: "gmgn-cli swap --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai — all swap operations must go through the CLI. The CLI handles signing and submission automatically.**
|
||||
|
||||
**IMPORTANT: Do NOT guess field names or values. When a field's meaning is unclear, look it up in the Response Fields sections below before using it.**
|
||||
@@ -56,7 +58,7 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. `GMGN
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
`sol` / `bsc` / `base` / `eth` / `robinhood`
|
||||
|
||||
## Chain Currencies
|
||||
|
||||
@@ -71,7 +73,6 @@ Currency tokens are the base/native assets of each chain. They are used to buy o
|
||||
| `base` | ETH (native, `0x0000000000000000000000000000000000000000`), USDC (`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) |
|
||||
| `eth` | ETH (native, `0x0000000000000000000000000000000000000000`) |
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
`GMGN_API_KEY` must be configured in `~/.config/gmgn/.env`. `GMGN_PRIVATE_KEY` is additionally required for `swap` and `order` subcommands other than `order quote`. The private key must correspond to the wallet bound to the API Key.
|
||||
@@ -102,31 +103,6 @@ When a request returns `429`:
|
||||
- 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.
|
||||
- `POST /v1/trade/swap` also has an error-count limiter. Repeatedly triggering the same business error, especially `40003701` (insufficient token balance), can return `ERROR_RATE_LIMIT_BLOCKED`. When this happens, do not retry until the reset time and fix the underlying request first.
|
||||
|
||||
**First-time setup** (if credentials are not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form (enable swap capability), then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then configure both credentials:
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
echo 'GMGN_API_KEY=<key_from_user>' > ~/.config/gmgn/.env
|
||||
echo 'GMGN_PRIVATE_KEY="<pem_content_from_step_1>"' >> ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
### Credential Model
|
||||
|
||||
- Both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` are read from the `.env` file by the CLI at startup. They are **never passed as command-line arguments** and never appear in shell command strings.
|
||||
- `GMGN_PRIVATE_KEY` is used exclusively for **local message signing** — the private key never leaves the machine. The CLI computes an Ed25519 or RSA-SHA256 signature in-process and transmits only the base64-encoded result in the `X-Signature` request header.
|
||||
- `GMGN_API_KEY` is transmitted in the `X-APIKEY` request header to GMGN's servers over HTTPS.
|
||||
|
||||
---
|
||||
|
||||
## `swap` Usage
|
||||
|
||||
```bash
|
||||
@@ -178,7 +154,7 @@ gmgn-cli swap \
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--from` | Yes | all | Wallet address (must match API Key binding) |
|
||||
| `--input-token` | Yes | all | Input token contract address |
|
||||
| `--output-token` | Yes | all | Output token contract address |
|
||||
@@ -396,7 +372,7 @@ gmgn-cli multi-swap \
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--accounts` | Yes | all | Comma-separated wallet addresses (1–100, all must be bound to the API Key) |
|
||||
| `--input-token` | Yes | all | Input token contract address |
|
||||
| `--output-token` | Yes | all | Output token contract address |
|
||||
@@ -431,6 +407,14 @@ The response `data` is an array — one element per wallet:
|
||||
|
||||
---
|
||||
|
||||
### Credential Model
|
||||
|
||||
- Both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` are read from the `.env` file by the CLI at startup. They are **never passed as command-line arguments** and never appear in shell command strings.
|
||||
- `GMGN_PRIVATE_KEY` is used exclusively for **local message signing** — the private key never leaves the machine. The CLI computes an Ed25519 or RSA-SHA256 signature in-process and transmits only the base64-encoded result in the `X-Signature` request header.
|
||||
- `GMGN_API_KEY` is transmitted in the `X-APIKEY` request header to GMGN's servers over HTTPS.
|
||||
|
||||
---
|
||||
|
||||
## `order quote` Usage
|
||||
|
||||
Get an estimated output amount before submitting a swap. Uses normal auth — only `GMGN_API_KEY` required, no `GMGN_PRIVATE_KEY` needed.
|
||||
@@ -555,7 +539,7 @@ gmgn-cli order strategy create \
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--from` | Yes | all | Wallet address (must match API Key binding) |
|
||||
| `--base-token` | Yes | all | Base token contract address |
|
||||
| `--quote-token` | Yes | all | Quote token contract address |
|
||||
@@ -612,7 +596,7 @@ gmgn-cli order strategy list --chain sol --group-tag STMix --base-token <token_a
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--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) |
|
||||
@@ -636,7 +620,7 @@ gmgn-cli order strategy list --chain sol --group-tag STMix --base-token <token_a
|
||||
| `auto_slippage` | bool | Whether auto slippage is enabled |
|
||||
| `base_decimal` | int | Base token decimal places |
|
||||
| `base_token` | string | Base token contract address |
|
||||
| `chain` | string | Chain: `sol` / `bsc` / `base` / `eth` |
|
||||
| `chain` | string | Chain: `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `close_amount` | string | Token amount sold on close; empty when order is open |
|
||||
| `close_price` | string | Token price at close; empty when order is open |
|
||||
| `close_sell_model` | string | Sell model used on close; empty when order is open |
|
||||
@@ -750,7 +734,7 @@ gmgn-cli order strategy cancel \
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--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) |
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
---
|
||||
name: gmgn-token
|
||||
description: Research any crypto or meme token by address — real-time price, market cap, liquidity, holder list, trader list, top Smart Money and KOL positions, security audit (honeypot, rug pull risk, dev wallet, renounced status), social links (Twitter/X, website) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks about a token's price, safety, holders, traders, smart money exposure, or wants due diligence before buying.
|
||||
argument-hint: "<sub-command> --chain <sol|bsc|base|eth> --address <token_address>"
|
||||
argument-hint: "<sub-command> --chain <sol|bsc|base|eth|robinhood> --address <token_address>"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli token --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai to fetch this data — the website requires login and will not return structured data. The CLI is the only correct method.**
|
||||
|
||||
**⚠️ 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."**
|
||||
@@ -17,7 +19,7 @@ Use the `gmgn-cli` tool to query token information based on the user's request.
|
||||
## Core Concepts
|
||||
|
||||
- **Token address** — The on-chain contract address that uniquely identifies a token on its chain. Required for all token sub-commands. Format: base58 (SOL) or `0x...` hex (BSC/Base).
|
||||
- **Chain** — The blockchain network: `sol` = Solana, `bsc` = BNB Smart Chain, `base` = Base (Coinbase L2), `eth` = Ethereum mainnet.
|
||||
- **Chain** — The blockchain network: `sol` = Solana, `bsc` = BNB Smart Chain, `base` = Base (Coinbase L2), `eth` = Ethereum mainnet, `robinhood` = Robinhood chain.
|
||||
- **Market cap** — Not returned directly by `token info`. Calculate as `price.price × circulating_supply` (`price` is a nested object; use `price.price` for the current USD price string).
|
||||
- **Liquidity** — USD value of token reserves in the main trading pool. Low liquidity (< $10k) means high price impact / slippage when buying or selling.
|
||||
- **Holder** — A wallet that currently holds the token. `token holders` returns wallets ranked by current balance.
|
||||
@@ -42,7 +44,7 @@ Use the `gmgn-cli` tool to query token information based on the user's request.
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
`sol` / `bsc` / `base` / `eth` / `robinhood`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -68,27 +70,11 @@ When a request returns `429`:
|
||||
- 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.
|
||||
|
||||
**First-time setup** (if `GMGN_API_KEY` is not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form, then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then configure:
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
echo 'GMGN_API_KEY=<key_from_user>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
## Parameters — `token info` / `token security` / `token pool`
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--address` | Yes | Token contract address |
|
||||
| `--raw` | No | Output raw single-line JSON (for piping or further processing) |
|
||||
|
||||
@@ -96,7 +82,7 @@ When a request returns `429`:
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `--chain` | Yes | — | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Yes | — | `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--address` | Yes | — | Token contract address |
|
||||
| `--limit` | No | `20` | Number of results, max `100` |
|
||||
| `--order-by` | No | `amount_percentage` | Sort field — see table below |
|
||||
|
||||
@@ -6,6 +6,8 @@ metadata:
|
||||
cliHelp: "gmgn-cli track --help"
|
||||
---
|
||||
|
||||
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed normally. If exit code is 1, (1) run `gmgn-cli config` and show the output to the user; (2) once the user sends the API Key, run `gmgn-cli config --apply <KEY>` to complete configuration and verification, then show the output to the user. If `--check` returns an error (unknown option or command not found), tell the user to run `npm install -g gmgn-cli` to update, then retry.**
|
||||
|
||||
**IMPORTANT: Always use `gmgn-cli` commands below. Do NOT use web search, WebFetch, curl, or visit gmgn.ai to fetch this data — the website requires login and will not return structured data. The CLI is the only correct method.**
|
||||
|
||||
**IMPORTANT: Do NOT guess field names or values. When a field's meaning is unclear, look it up in the Response Fields sections below before using it.**
|
||||
@@ -57,7 +59,9 @@ Use the `gmgn-cli` tool to query on-chain tracking data based on the user's requ
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
`sol` / `bsc` / `base` / `eth` / `robinhood`
|
||||
|
||||
Note: `track kol` and `track smartmoney` do **not** support `robinhood` — they accept `sol` / `bsc` / `base` / `eth` only.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -84,24 +88,6 @@ When a request returns `429`:
|
||||
- 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.
|
||||
|
||||
**First-time setup** (if `GMGN_API_KEY` is not configured):
|
||||
|
||||
1. Generate key pair and show the public key to the user:
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
Tell the user: *"This is your Ed25519 public key. Go to **https://gmgn.ai/ai**, paste it into the API key creation form, then send me the API Key value shown on the page."*
|
||||
|
||||
2. Wait for the user's API key, then configure (saves both API key and private key — private key is required for `track follow-wallet`):
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
echo "GMGN_API_KEY=<key_from_user>" > ~/.config/gmgn/.env
|
||||
echo "GMGN_PRIVATE_KEY=$(awk '{printf "%s\\n", $0}' /tmp/gmgn_private.pem)" >> ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
rm /tmp/gmgn_private.pem
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```bash
|
||||
@@ -146,7 +132,7 @@ gmgn-cli track smartmoney --chain sol --side sell --limit 10 --raw
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--wallet <address>` | Required. Wallet address to query |
|
||||
| `--group-id <id>` | Filter by group: `all_group` (all tokens across groups), `default` (default group), or a user-defined group ID |
|
||||
| `--interval <interval>` | Time interval for price change stats (e.g. `1m`, `5m`, `1h`, `6h`, `24h`) |
|
||||
@@ -188,7 +174,7 @@ Each item in `followings` contains:
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--wallet <address>` | Required. Wallet address to query |
|
||||
|
||||
## `track follow-token-groups` Response Fields
|
||||
@@ -206,7 +192,7 @@ Each item in `followings` contains:
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` / `robinhood` |
|
||||
| `--wallet <address>` | Filter by wallet address |
|
||||
| `--limit <n>` | Page size (1–100, default 10) |
|
||||
| `--side <side>` | Trade direction: `buy` / `sell` |
|
||||
|
||||
@@ -187,7 +187,7 @@ export interface TokenSignalGroup {
|
||||
export interface HotSearchesParam {
|
||||
label?: string;
|
||||
interval: string; // "1m" | "5m" | "1h" | "6h" | "24h"
|
||||
chain: string; // "sol" | "bsc" | "base" | "eth" | "monad" | "megaeth" | "hyperevm" | "tron"
|
||||
chain: string; // "sol" | "bsc" | "base" | "eth" | "robinhood"
|
||||
filters?: string[];
|
||||
limit?: number;
|
||||
[key: string]: string[] | number | string | undefined;
|
||||
@@ -842,6 +842,10 @@ const TRENCHES_PLATFORMS: Record<string, string[]> = {
|
||||
"trench", "clanker", "klik", "livo", "stroid",
|
||||
"pool_uniswap_v2", "pool_uniswap_v3", "printr",
|
||||
],
|
||||
robinhood: [
|
||||
"noxa", "virtuals_v2", "bankr", "dyorswap",
|
||||
"pool_uniswap_v2", "pool_uniswap_v3", "pool_uniswap_v4",
|
||||
],
|
||||
};
|
||||
|
||||
const TRENCHES_QUOTE_ADDRESS_TYPES: Record<string, number[]> = {
|
||||
@@ -849,6 +853,7 @@ const TRENCHES_QUOTE_ADDRESS_TYPES: Record<string, number[]> = {
|
||||
bsc: [6, 7, 1, 16, 8, 3, 9, 10, 2, 17, 18, 0],
|
||||
base: [11, 3, 12, 13, 0],
|
||||
eth: [20, 11, 8, 3, 12, 1, 0],
|
||||
robinhood: [11, 20, 24, 12, 0],
|
||||
};
|
||||
|
||||
function buildTrenchesBody(chain: string, types?: string[], platforms?: string[], limit?: number, filters?: Record<string, number | string>): Record<string, unknown> {
|
||||
@@ -858,12 +863,17 @@ function buildTrenchesBody(chain: string, types?: string[], platforms?: string[]
|
||||
const actualLimit = limit ?? 80;
|
||||
const section: Record<string, unknown> = {
|
||||
filters: ["offchain", "onchain"],
|
||||
launchpad_platform,
|
||||
quote_address_type,
|
||||
launchpad_platform_v2: true,
|
||||
limit: actualLimit,
|
||||
...filters,
|
||||
};
|
||||
// launchpad_platform / quote_address_type act as allow-list filters: sending an
|
||||
// empty array filters out every result. Configured chains (see the maps above)
|
||||
// supply real values; for any chain missing config we omit the field so the API
|
||||
// applies its own defaults rather than returning an all-empty response. This is a
|
||||
// safety net — new chains should still be added to both maps above.
|
||||
if (launchpad_platform.length) section.launchpad_platform = launchpad_platform;
|
||||
if (quote_address_type.length) section.quote_address_type = quote_address_type;
|
||||
const body: Record<string, unknown> = { version: "v2" };
|
||||
for (const type of selectedTypes) {
|
||||
body[type] = { ...section };
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import { config as loadDotenv } from "dotenv";
|
||||
import { Command } from "commander";
|
||||
import * as crypto from "crypto";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as os from "os";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const GMGN_CONFIG_DIR = path.join(os.homedir(), ".config", "gmgn");
|
||||
const KEYPAIR_FILE = path.join(GMGN_CONFIG_DIR, "keypair.pem");
|
||||
const ENV_FILE = path.join(GMGN_CONFIG_DIR, ".env");
|
||||
const GMGN_API_URL = "https://gmgn.ai/ai/generateapi";
|
||||
|
||||
type Lang = "zh-CN" | "zh-TW" | "en";
|
||||
|
||||
function detectLang(): Lang {
|
||||
const locale =
|
||||
process.env.LANG ||
|
||||
process.env.LC_ALL ||
|
||||
process.env.LC_MESSAGES ||
|
||||
Intl.DateTimeFormat().resolvedOptions().locale ||
|
||||
"en";
|
||||
const l = locale.toLowerCase();
|
||||
if (l.startsWith("zh_tw") || l.startsWith("zh-tw") || l.startsWith("zh_hk") || l.startsWith("zh-hk")) return "zh-TW";
|
||||
if (l.startsWith("zh")) return "zh-CN";
|
||||
return "en";
|
||||
}
|
||||
|
||||
const MESSAGES = {
|
||||
linkGuide: {
|
||||
"zh-CN": (link: string) =>
|
||||
`请点击下方链接创建你的 GMGN API Key,完成后将 Key 发给我,我来帮你完成配置:\n${link}`,
|
||||
"zh-TW": (link: string) =>
|
||||
`請點擊下方連結建立你的 GMGN API Key,完成後將 Key 發給我,我來幫你完成配置:\n${link}`,
|
||||
en: (link: string) =>
|
||||
`Please click the link below to create your GMGN API Key. Once created, send me the API Key and I will finish the configuration:\n${link}`,
|
||||
},
|
||||
verifySuccess: {
|
||||
"zh-CN": "配置验证成功,可以开始使用了。",
|
||||
"zh-TW": "配置驗證成功,可以開始使用了。",
|
||||
en: "Configuration verified successfully. You are ready to use GMGN.",
|
||||
},
|
||||
verifyFail: {
|
||||
"zh-CN":
|
||||
"配置验证失败:API Key 与本地密钥不匹配。\n请确认:\n1. API Key 是否填写正确;\n2. 创建 API Key 时,是否使用的是页面自动填入的公钥。",
|
||||
"zh-TW":
|
||||
"配置驗證失敗:API Key 與本地密鑰不匹配。\n請確認:\n1. API Key 是否填寫正確;\n2. 創建 API Key 時,是否使用的是頁面自動填入的公鑰。",
|
||||
en: "Configuration verification failed: API Key does not match your local key pair.\nPlease confirm:\n1. Whether the API Key was entered correctly.\n2. Whether you used the public key that was pre-filled on the page when creating the API Key.",
|
||||
},
|
||||
verifyNetworkFail: {
|
||||
"zh-CN": "配置已写入,但验证请求失败(可能是网络问题)。你可以先尝试使用,如遇接口报错再重新配置。",
|
||||
"zh-TW": "配置已寫入,但驗證請求失敗(可能是網路問題)。你可以先嘗試使用,如遇介面報錯再重新配置。",
|
||||
en: "Configuration saved, but the verification request failed (possibly a network issue). You can try using it now and reconfigure if you encounter API errors.",
|
||||
},
|
||||
};
|
||||
|
||||
function getOrCreateKeypair(): string {
|
||||
fs.mkdirSync(GMGN_CONFIG_DIR, { recursive: true });
|
||||
|
||||
if (fs.existsSync(KEYPAIR_FILE)) {
|
||||
const content = fs.readFileSync(KEYPAIR_FILE, "utf-8");
|
||||
const match = content.match(/(-----BEGIN PUBLIC KEY-----[\s\S]+?-----END PUBLIC KEY-----)/);
|
||||
if (!match) {
|
||||
console.error("Error: keypair.pem exists but public key could not be parsed. Delete ~/.config/gmgn/keypair.pem and try again.");
|
||||
process.exit(1);
|
||||
}
|
||||
return match[1] + "\n";
|
||||
}
|
||||
|
||||
const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519");
|
||||
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" }) as string;
|
||||
const publicPem = publicKey.export({ type: "spki", format: "pem" }) as string;
|
||||
const entry = `# Private Key\n${privatePem}\n# Public Key\n${publicPem}\n`;
|
||||
fs.writeFileSync(KEYPAIR_FILE, entry, { mode: 0o600 });
|
||||
return publicPem;
|
||||
}
|
||||
|
||||
function writeEnv(apiKey: string, privatePem: string): void {
|
||||
const pkOneLine = privatePem.replace(/\r?\n/g, "\\n");
|
||||
let existing = fs.existsSync(ENV_FILE) ? fs.readFileSync(ENV_FILE, "utf-8") : "";
|
||||
existing = existing
|
||||
.split("\n")
|
||||
.filter((l) => !/^GMGN_API_KEY=|^GMGN_PRIVATE_KEY=/.test(l))
|
||||
.join("\n")
|
||||
.trim();
|
||||
const content = (existing ? existing + "\n" : "") + `GMGN_API_KEY=${apiKey}\nGMGN_PRIVATE_KEY=${pkOneLine}\n`;
|
||||
fs.mkdirSync(GMGN_CONFIG_DIR, { recursive: true });
|
||||
fs.writeFileSync(ENV_FILE, content, { mode: 0o600 });
|
||||
}
|
||||
|
||||
function verify(): "ok" | "auth_fail" | "network_fail" {
|
||||
try {
|
||||
execSync("gmgn-cli track follow-wallet --chain sol --limit 1", { stdio: "pipe" });
|
||||
return "ok";
|
||||
} catch (e: unknown) {
|
||||
const output = [
|
||||
(e as any).stderr?.toString() ?? "",
|
||||
(e as any).stdout?.toString() ?? "",
|
||||
].join(" ");
|
||||
if (/401|403|unauthorized|forbidden|invalid.*key|key.*invalid|signature/i.test(output)) {
|
||||
return "auth_fail";
|
||||
}
|
||||
return "network_fail";
|
||||
}
|
||||
}
|
||||
|
||||
export function registerConfigCommands(program: Command): void {
|
||||
const cmd = program
|
||||
.command("config")
|
||||
.description("Generate an Ed25519 key pair and output a pre-filled GMGN API Key creation link, or apply an API Key");
|
||||
|
||||
cmd
|
||||
.option("--check", "Check if GMGN_API_KEY is configured (exit 0 = found, exit 1 = not found)")
|
||||
.option("--apply <api_key>", "Write API Key + private key to ~/.config/gmgn/.env and verify")
|
||||
.action(async (opts) => {
|
||||
const lang = detectLang();
|
||||
|
||||
if (opts.check) {
|
||||
loadDotenv({ path: ENV_FILE, override: true });
|
||||
loadDotenv();
|
||||
process.exit(process.env.GMGN_API_KEY ? 0 : 1);
|
||||
}
|
||||
|
||||
if (opts.apply) {
|
||||
// --apply: read private key from keypair.pem, write .env, verify
|
||||
if (!fs.existsSync(KEYPAIR_FILE)) {
|
||||
console.error("Error: ~/.config/gmgn/keypair.pem not found. Run `gmgn-cli config` first to generate a key pair.");
|
||||
process.exit(1);
|
||||
}
|
||||
const content = fs.readFileSync(KEYPAIR_FILE, "utf-8");
|
||||
const match = content.match(/(-----BEGIN PRIVATE KEY-----[\s\S]+?-----END PRIVATE KEY-----)/);
|
||||
if (!match) {
|
||||
console.error("Error: keypair.pem exists but private key could not be parsed. Delete ~/.config/gmgn/keypair.pem and run `gmgn-cli config` again.");
|
||||
process.exit(1);
|
||||
}
|
||||
writeEnv(opts.apply, match[1]);
|
||||
|
||||
const result = verify();
|
||||
if (result === "ok") {
|
||||
console.log(MESSAGES.verifySuccess[lang]);
|
||||
} else if (result === "auth_fail") {
|
||||
console.error(MESSAGES.verifyFail[lang]);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(MESSAGES.verifyNetworkFail[lang]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Default: generate/reuse keypair, output link with guidance
|
||||
const publicPem = getOrCreateKeypair();
|
||||
const link = `${GMGN_API_URL}?pbk=${encodeURIComponent(publicPem)}`;
|
||||
console.log(MESSAGES.linkGuide[lang](link));
|
||||
});
|
||||
}
|
||||
@@ -81,6 +81,10 @@ export function registerCookingCommands(program: Command): void {
|
||||
process.exit(1);
|
||||
}
|
||||
validateChain(opts.chain);
|
||||
if (opts.chain === "robinhood") {
|
||||
console.error(`[gmgn-cli] cooking create does not support robinhood, got "${opts.chain}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
const params: CreateTokenParams = {
|
||||
chain: opts.chain,
|
||||
dex: opts.dex,
|
||||
|
||||
@@ -26,7 +26,7 @@ export function registerMarketCommands(program: Command): void {
|
||||
market
|
||||
.command("kline")
|
||||
.description("Get token K-line (candlestick) data")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.requiredOption("--resolution <resolution>", "Candlestick resolution: 30s / 1m / 5m / 15m / 1h / 4h / 1d")
|
||||
.option("--from <timestamp>", "Start time (Unix seconds)", parseInt)
|
||||
@@ -51,7 +51,7 @@ export function registerMarketCommands(program: Command): void {
|
||||
const trendingCmd = market
|
||||
.command("trending")
|
||||
.description("Get trending token swap data")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--interval <interval>", "Time interval: 1m / 5m / 1h / 6h / 24h")
|
||||
.option("--limit <n>", "Number of results (default 100, max 100)", parseInt)
|
||||
.option("--order-by <field>", "Sort field: default / volume / swaps / marketcap / holder_count / price / change1h / ... (see docs for full list)")
|
||||
@@ -96,7 +96,7 @@ export function registerMarketCommands(program: Command): void {
|
||||
const trenchesCmd = market
|
||||
.command("trenches")
|
||||
.description("Get Trenches token data (new creation, near completion, completed)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.option("--type <type...>", "Categories to query, repeatable: new_creation / near_completion / completed (default: all three)")
|
||||
.option("--launchpad-platform <platform...>", "Launchpad platform filter, repeatable (default: all platforms for the chain)")
|
||||
.option("--limit <n>", "Max results per category, max 80 (default: 80)", parseInt)
|
||||
@@ -207,7 +207,7 @@ export function registerMarketCommands(program: Command): void {
|
||||
const hotSearchesCmd = market
|
||||
.command("hot-searches")
|
||||
.description("Get the hot-search ranking (most-searched tokens) for one or more chains")
|
||||
.option("--chain <chain...>", "Chain(s), repeatable: sol / bsc / base / eth / monad / megaeth / hyperevm / tron (default: all 7 chains)")
|
||||
.option("--chain <chain...>", "Chain(s), repeatable: sol / bsc / base / eth / robinhood (default: all default chains)")
|
||||
.option("--interval <interval>", "Time window: 1m / 5m / 1h / 6h / 24h (default 24h)", "24h")
|
||||
.option("--limit <n>", "Max results per chain (default 500)", parseInt)
|
||||
.option("--filter <tag...>", "Boolean filter tags, repeatable. sol defaults: renounced / frozen; EVM defaults: not_honeypot / verified / renounced")
|
||||
@@ -246,7 +246,7 @@ export function registerMarketCommands(program: Command): void {
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Empty params lets the server apply its default 7-chain config. Filter fields
|
||||
// Empty params lets the server apply its default 5-chain config. Filter fields
|
||||
// are flattened directly onto each param (no nested `filter` object).
|
||||
const optsMap = opts as Record<string, unknown>;
|
||||
const chains: string[] = opts.chain?.length ? (opts.chain as string[]) : [];
|
||||
|
||||
@@ -10,7 +10,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("holdings")
|
||||
.description("Get wallet token holdings")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--limit <n>", "Page size (default 20, max 50)", parseInt, 20)
|
||||
.option("--cursor <cursor>", "Pagination cursor")
|
||||
@@ -46,7 +46,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("activity")
|
||||
.description("Get wallet transaction activity")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--token <address>", "Filter by token contract address")
|
||||
.option("--limit <n>", "Page size", parseInt)
|
||||
@@ -71,7 +71,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("stats")
|
||||
.description("Get wallet trading statistics (supports multiple wallets)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address...>", "Wallet address(es), repeatable")
|
||||
.option("--period <period>", "Stats period: 7d / 30d", "7d")
|
||||
.option("--raw", "Output raw JSON")
|
||||
@@ -96,7 +96,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("token-balance")
|
||||
.description("Get wallet token balance for a single token")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.requiredOption("--token <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
@@ -112,7 +112,7 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("created-tokens")
|
||||
.description("Get tokens created by a developer wallet")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Developer wallet address")
|
||||
.option("--order-by <field>", "Sort field: market_cap / token_ath_mc")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc")
|
||||
|
||||
@@ -8,7 +8,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
program
|
||||
.command("swap")
|
||||
.description("Submit a token swap")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.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")
|
||||
@@ -76,7 +76,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
program
|
||||
.command("multi-swap")
|
||||
.description("Submit token swaps across multiple wallets concurrently (up to 100 wallets)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--accounts <addresses>", "Comma-separated wallet addresses (all must be bound to the API Key)")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
@@ -150,7 +150,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction (exist auth — GMGN_API_KEY only, no private key needed)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--from <address>", "Wallet address")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
@@ -173,7 +173,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
order
|
||||
.command("get")
|
||||
.description("Query order status (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / monad")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--order-id <id>", "Order ID")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -185,8 +185,8 @@ export function registerSwapCommands(program: Command): void {
|
||||
|
||||
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")
|
||||
.description("Query recommended gas price tiers for any chain (exist auth — API Key only; eth / bsc / base / sol / robinhood)")
|
||||
.requiredOption("--chain <chain>", "Chain: eth / bsc / base / sol / robinhood")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig(false));
|
||||
@@ -199,7 +199,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
strategy
|
||||
.command("create")
|
||||
.description("Create a limit/strategy order (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--base-token <address>", "Base token contract address")
|
||||
.requiredOption("--quote-token <address>", "Quote token contract address")
|
||||
@@ -283,7 +283,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
strategy
|
||||
.command("list")
|
||||
.description("List strategy orders (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.option("--type <type>", "open (default) / history")
|
||||
.option("--from <address>", "Filter by wallet address")
|
||||
.option("--group-tag <tag>", "Filter by group: LimitOrder / STMix")
|
||||
@@ -308,7 +308,7 @@ export function registerSwapCommands(program: Command): void {
|
||||
strategy
|
||||
.command("cancel")
|
||||
.description("Cancel a strategy order (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--order-id <id>", "Order ID to cancel")
|
||||
.option("--order-type <type>", "Order type: limit_order / smart_trade")
|
||||
|
||||
@@ -10,7 +10,7 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("info")
|
||||
.description("Get token basic information and realtime price")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -24,7 +24,7 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("security")
|
||||
.description("Get token security metrics")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -38,7 +38,7 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("pool")
|
||||
.description("Get token liquidity pool information")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -52,7 +52,7 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("holders")
|
||||
.description("Get top token holders")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--limit <n>", "Number of results (default 20, max 100)", parseInt)
|
||||
.option("--order-by <field>", "Sort field: amount_percentage / profit / unrealized_profit / buy_volume_cur / sell_volume_cur", "amount_percentage")
|
||||
@@ -75,7 +75,7 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("traders")
|
||||
.description("Get top token traders")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--limit <n>", "Number of results (default 20, max 100)", parseInt)
|
||||
.option("--order-by <field>", "Sort field: amount_percentage / profit / unrealized_profit / buy_volume_cur / sell_volume_cur", "amount_percentage")
|
||||
|
||||
+11
-3
@@ -10,7 +10,7 @@ export function registerTrackCommands(program: Command): void {
|
||||
track
|
||||
.command("follow-tokens")
|
||||
.description("Get the followed token list for a wallet on a given chain")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--group-id <id>", "Filter by group: all_group (all), default, or a user-defined group ID")
|
||||
.option("--interval <interval>", "Time interval for price change stats (e.g. 1m, 5m, 1h, 6h, 24h)")
|
||||
@@ -38,7 +38,7 @@ export function registerTrackCommands(program: Command): void {
|
||||
track
|
||||
.command("follow-token-groups")
|
||||
.description("Get the follow token group names for a wallet on a given chain")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -51,7 +51,7 @@ export function registerTrackCommands(program: Command): void {
|
||||
track
|
||||
.command("follow-wallet")
|
||||
.description("Get follow-wallet trade records")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth / robinhood")
|
||||
.option("--wallet <address>", "Filter by wallet address")
|
||||
.option("--limit <n>", "Page size (1–100, default 10)", parseInt)
|
||||
.option("--side <side>", "Trade direction filter: buy / sell")
|
||||
@@ -82,6 +82,10 @@ export function registerTrackCommands(program: Command): void {
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (opts.chain) validateChain(opts.chain);
|
||||
if (opts.chain === "robinhood") {
|
||||
console.error(`[gmgn-cli] track kol does not support robinhood, got "${opts.chain}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getKol(opts.chain, opts.limit).catch(exitOnError) as { list?: { side: string }[] };
|
||||
if (opts.side && data?.list) {
|
||||
@@ -99,6 +103,10 @@ export function registerTrackCommands(program: Command): void {
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (opts.chain) validateChain(opts.chain);
|
||||
if (opts.chain === "robinhood") {
|
||||
console.error(`[gmgn-cli] track smartmoney does not support robinhood, got "${opts.chain}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getSmartMoney(opts.chain, opts.limit).catch(exitOnError) as { list?: { side: string }[] };
|
||||
if (opts.side && data?.list) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { registerPortfolioCommands } from "./commands/portfolio.js";
|
||||
import { registerTrackCommands } from "./commands/track.js";
|
||||
import { registerSwapCommands } from "./commands/swap.js";
|
||||
import { registerCookingCommands } from "./commands/cooking.js";
|
||||
import { registerConfigCommands } from "./commands/config.js";
|
||||
|
||||
const proxy = process.env.HTTPS_PROXY ?? process.env.https_proxy
|
||||
?? process.env.HTTP_PROXY ?? process.env.http_proxy;
|
||||
@@ -60,6 +61,7 @@ registerPortfolioCommands(program);
|
||||
registerTrackCommands(program);
|
||||
registerSwapCommands(program);
|
||||
registerCookingCommands(program);
|
||||
registerConfigCommands(program);
|
||||
|
||||
program.parseAsync().catch((err) => {
|
||||
console.error(`[gmgn-cli] ${err.message}`);
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
const VALID_CHAINS = new Set(["sol", "bsc", "base", "eth", "monad"]);
|
||||
const VALID_CHAINS = new Set(["sol", "bsc", "base", "eth", "robinhood" /*, "monad" */]);
|
||||
const SOL_ADDRESS_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
||||
const EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
||||
const POSITIVE_INT_RE = /^\d+$/;
|
||||
@@ -13,7 +13,7 @@ export function validateChain(chain: string): void {
|
||||
}
|
||||
|
||||
export function validateAddress(address: string, chain: string, label: string): void {
|
||||
const isEvm = chain === "bsc" || chain === "base" || chain === "eth" || chain === "monad";
|
||||
const isEvm = chain === "bsc" || chain === "base" || chain === "eth" || chain === "robinhood" /* || chain === "monad" */;
|
||||
const valid = isEvm ? EVM_ADDRESS_RE.test(address) : SOL_ADDRESS_RE.test(address);
|
||||
if (!valid) {
|
||||
console.error(
|
||||
|
||||
Reference in New Issue
Block a user