Compare commits
216 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d0cb7348d | |||
| ddc025bb97 | |||
| e9b08214a2 | |||
| f96519941e | |||
| fd8a1c4d2a | |||
| 0282a9a09b | |||
| 17d7de841e | |||
| bc64360e80 | |||
| 134a11593c | |||
| 32d2fd2aac | |||
| 8ed53df6d7 | |||
| a161bd733d | |||
| f172b1922d | |||
| 31f5b9f5b6 | |||
| c6fae6afe7 | |||
| ec5719ce12 | |||
| aebe509f29 | |||
| 26ebfe6843 | |||
| 412531f04e | |||
| b0b25118aa | |||
| 0a12f0615d | |||
| 0979d14d6a | |||
| 8729cff4d3 | |||
| 0cf2e514e6 | |||
| 693a63c723 | |||
| 81d67808fa | |||
| 8a095a99a8 | |||
| 0bc73a6430 | |||
| d00a1d3ce3 | |||
| 30e535617f | |||
| f64a3e086b | |||
| 60438dff5c | |||
| 6f0d4464e2 | |||
| 48e7346d8e | |||
| 2f76b375c5 | |||
| a65d5fd1cb | |||
| 7d16bd80e8 | |||
| 9dfccd129d | |||
| ce7f762e5b | |||
| d51f1c49d3 | |||
| 17b901c29f | |||
| f3738e0bd4 | |||
| f05e1d5d20 | |||
| beedf14b5b | |||
| 1b9e2c24d6 | |||
| a3dfa99763 | |||
| 317c7d982b | |||
| 15872373cd | |||
| 674c7032a8 | |||
| 4649a7a287 | |||
| 2b33ee666c | |||
| 123bdba738 | |||
| 1d03fb1672 | |||
| 6f79600869 | |||
| 12ab55bb63 | |||
| aa09490a9b | |||
| b3e99dde94 | |||
| 2b6c220581 | |||
| 072b180119 | |||
| e181cba142 | |||
| ee04212098 | |||
| e4496eafeb | |||
| f56cf1f966 | |||
| 698ae707e8 | |||
| 34fc2f9e2a | |||
| 5ef03579cf | |||
| 1d433724d3 | |||
| 26a50c7046 | |||
| 56a3a60352 | |||
| 211f7d6fd0 | |||
| 5e1560188e | |||
| 08f7b66251 | |||
| 48c596ab10 | |||
| ec099ea399 | |||
| 1012cfffb8 | |||
| f6f1d56b82 | |||
| b83422769f | |||
| 8922811e04 | |||
| cc1cb48db9 | |||
| 981600f170 | |||
| 1f49d61363 | |||
| 3046c6d6cd | |||
| ee4838d565 | |||
| f19a1919da | |||
| 4cfe0e0fb5 | |||
| 5755206b58 | |||
| 6ab9cb108b | |||
| 51d2214253 | |||
| 8d3541c2a3 | |||
| 39d80429f6 | |||
| fd226c654b | |||
| a08fc7b580 | |||
| f49c89e609 | |||
| ad4eab3852 | |||
| 6fd302af60 | |||
| cdcf4e11d3 | |||
| 319c4bbf33 | |||
| 2b61eb807a | |||
| 46c56b7e5d | |||
| b18738177c | |||
| cfb4270816 | |||
| 932bf8c82c | |||
| 4143e07266 | |||
| 4f96fedbb1 | |||
| eeb4a77cf7 | |||
| f7c051e2d1 | |||
| 8bc1b2be6b | |||
| 990601d031 | |||
| db55c77a26 | |||
| 91473cc366 | |||
| 38bff1aecb | |||
| 6d09536349 | |||
| cd9b285b3f | |||
| c6141c880f | |||
| 3551bc3a25 | |||
| 8448787176 | |||
| 04389b98f0 | |||
| 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 | |||
| f7a2d075e3 | |||
| 8e413cef25 | |||
| 7959eaaed3 | |||
| 8c27e42aff | |||
| ae7729f26c | |||
| 759ab74709 | |||
| dd1cb9d2e5 | |||
| b12a2294b7 | |||
| cb21fff38c | |||
| 138d571f8b | |||
| 2e71f283f0 | |||
| 56086fa692 | |||
| 221bf120a8 | |||
| 09351a9205 | |||
| 91128a887e | |||
| d2a91ef7d1 | |||
| 5ec76cb465 | |||
| 40f75e0b64 | |||
| 3951d9963e | |||
| 5547e9fd30 | |||
| 3ca831a976 | |||
| aa27e1560a | |||
| d47404856d | |||
| b898d20c29 | |||
| 1e3fbaf623 | |||
| 8bcb68aa3c | |||
| b995e84d16 | |||
| e4e331223e | |||
| a48205ea3f | |||
| 6a1dc62b6e | |||
| 4697985501 | |||
| e0c4be2946 | |||
| c2799c73d1 | |||
| fe80a8aba7 | |||
| 174a87c117 | |||
| b7302f5253 | |||
| 59d7c71e75 | |||
| 87540d6327 | |||
| a5ff97881c | |||
| 9c2a349ecf | |||
| fa2afae426 | |||
| 5fc9a86c4d | |||
| 56f1f574b1 | |||
| 28062887d8 | |||
| 58849a8c61 | |||
| 0239e42b50 | |||
| 12d3c358d8 | |||
| c6d55356a1 | |||
| 2c1c0210e7 | |||
| 71c239da39 | |||
| 0e5e5f8684 | |||
| b8bc81d915 | |||
| 08b48c8e24 | |||
| 5a8879c6d2 | |||
| 30ce20ff01 | |||
| 2b37e81d44 | |||
| c9b3034cf2 | |||
| 2ca2c24f9e | |||
| bd533cb85e | |||
| 247aaf96f9 | |||
| 45fb37d51f | |||
| 8301bf515f | |||
| 702eac9686 | |||
| 34456974f3 | |||
| 017672f480 | |||
| 9d871e9166 | |||
| d6b7247cc0 | |||
| c9dbb6f58b |
@@ -15,7 +15,7 @@
|
||||
"name": "GMGN"
|
||||
},
|
||||
"homepage": "https://gmgn.ai",
|
||||
"repository": "https://github.com/gmgn-ai/gmgn-skills",
|
||||
"repository": "https://github.com/GMGNAI/gmgn-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"gmgn",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "GMGN",
|
||||
"url": "https://gmgn.ai"
|
||||
},
|
||||
"repository": "https://github.com/gmgn-ai/gmgn-skills",
|
||||
"repository": "https://github.com/GMGNAI/gmgn-skills",
|
||||
"license": "MIT",
|
||||
"keywords": ["gmgn", "crypto", "solana", "token", "defi", "swap"],
|
||||
"skills": "./skills/"
|
||||
|
||||
@@ -12,7 +12,7 @@ Enable GMGN skills in Codex via native skill discovery. Just clone and symlink.
|
||||
1. **Clone the repository:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.codex/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.codex/gmgn-cli
|
||||
```
|
||||
|
||||
2. **Create the skills symlink:**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "GMGN"
|
||||
},
|
||||
"homepage": "https://gmgn.ai",
|
||||
"repository": "https://github.com/gmgn-ai/gmgn-skills",
|
||||
"repository": "https://github.com/GMGNAI/gmgn-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"gmgn",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (Node ${{ matrix.node-version }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version:
|
||||
- 20
|
||||
- 24
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Verify publish artifact
|
||||
run: npm pack --dry-run
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
registry-url: https://registry.npmjs.org
|
||||
cache: npm
|
||||
|
||||
- name: Ensure tag matches package version
|
||||
run: |
|
||||
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
|
||||
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
||||
|
||||
if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
|
||||
echo "package.json version ($PACKAGE_VERSION) does not match tag ($TAG_VERSION)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Verify publish artifact
|
||||
run: npm pack --dry-run
|
||||
|
||||
- name: Publish to npm
|
||||
run: npm publish --access public
|
||||
@@ -12,7 +12,7 @@ Enable GMGN skills in OpenCode via native skill discovery. Just clone and symlin
|
||||
1. **Clone the repository:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.opencode/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.opencode/gmgn-cli
|
||||
```
|
||||
|
||||
2. **Register the plugin:**
|
||||
|
||||
@@ -2,23 +2,71 @@
|
||||
|
||||
This file provides guidance to Claude Code when working with the gmgn-cli plugin.
|
||||
|
||||
## CRITICAL RULE — Read This First
|
||||
|
||||
**ALL queries about GMGN data MUST use `gmgn-cli` via the skills below.**
|
||||
|
||||
This includes: trending tokens, token info, security checks, K-line / price history, wallet holdings, KOL trades, Smart Money trades, swaps, and any other on-chain data.
|
||||
|
||||
**NEVER do any of the following to fetch GMGN data:**
|
||||
- Web search (e.g. searching "gmgn trending solana")
|
||||
- WebFetch / curl to gmgn.ai or any gmgn domain
|
||||
- Browser automation or scraping
|
||||
- Any method other than `gmgn-cli`
|
||||
|
||||
**Why:** The gmgn.ai website requires login, uses dynamic rendering, and does not expose structured data. The CLI is the only correct and supported method. If you attempt to scrape the site, you will get no data or be blocked.
|
||||
|
||||
**When a user asks anything about GMGN data — always invoke the matching skill and run the CLI command. No exceptions.**
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a **Claude Code plugin** — a collection of GMGN OpenAPI skills for on-chain operations. It provides CLI tools and skills for token queries, market data, wallet portfolio analysis, and swap execution across sol / bsc / base.
|
||||
This is a **Claude Code plugin** — a collection of GMGN OpenAPI skills for on-chain operations. It provides CLI tools and skills for token queries, market data, wallet portfolio analysis, and swap execution across sol / bsc / base / eth.
|
||||
|
||||
## Available Skills
|
||||
|
||||
| Skill | Purpose | When to Use |
|
||||
|-------|---------|-------------|
|
||||
| `gmgn-token` | Token info, security, pool, holders, traders | User asks about a token's price, market cap, security risk, liquidity pool, top holders, or top traders; user wants to research a token before buying; user asks "is this token safe", "who holds this token", "what's the liquidity" |
|
||||
| `gmgn-market` | K-line / candlestick market data + trending tokens | User asks for price history, chart data, OHLCV candles; user wants to analyze price trends over time; user asks "show me the 1h chart", "what was the price last week", "give me kline data for this token"; user wants to discover hot or trending tokens; user asks "what tokens are trending", "show me top tokens by volume", "find hot tokens on SOL" |
|
||||
| `gmgn-market` | K-line / candlestick market data + trending tokens + newly launched launchpad tokens | User asks for price history, chart data, OHLCV candles, trading volume over time; user wants to analyze price trends; user asks "show me the 1h chart", "what was the price last week", "give me kline data for this token"; user wants to discover hot or trending tokens; user asks "what tokens are trending", "show me top tokens by volume", "find hot tokens on SOL"; **user asks about newly launched tokens, fresh tokens, latest tokens on launchpads** — e.g. "show me new tokens on pump.fun", "what tokens just launched on SOL", "find newly created tokens", "latest tokens on letsbonk" → use `market trenches --type new_creation` |
|
||||
| `gmgn-portfolio` | Wallet holdings, activity, trading stats, token balance | User asks about a wallet's holdings, P&L, transaction history, trading statistics, or token balance; user wants to analyze a wallet; user asks "what tokens does this wallet hold", "show me recent trades", "what's the win rate of this wallet" |
|
||||
| `gmgn-track` | Track trade activity of wallets I follow, KOL trades, Smart Money trades across chains | User asks about trades from wallets they follow; user wants to see what KOLs or Smart Money are buying/selling; user asks "show me what wallets I follow have traded recently", "what are KOLs buying", "show me smart money moves on BSC" |
|
||||
| `gmgn-swap` | Token swap execution + order status query | User wants to swap tokens, execute a trade, or check an order status; user asks "swap SOL for USDC", "buy this token", "check my order"; **requires private key configured in `.env`** |
|
||||
|
||||
## Quick Decision Guide
|
||||
|
||||
Match the user's request to the right skill and workflow:
|
||||
|
||||
| User says | Action |
|
||||
|-----------|--------|
|
||||
| "is this token safe", "check this token", "research this token", token address provided | `gmgn-token` → full workflow: `docs/workflow-token-research.md` |
|
||||
| "deep report", "full analysis", "全面分析这个项目", "深度报告", "值不值得重仓" | `gmgn-token` + `gmgn-market` → `docs/workflow-project-deep-report.md` |
|
||||
| "what's trending", "hot tokens", "top tokens by volume" | `gmgn-market trending` |
|
||||
| "new tokens", "just launched", "pump.fun new" | `gmgn-market trenches --type new_creation` |
|
||||
| "early project screening", "新币筛选", "值得埋伏吗", "哪些新项目有聪明钱" | `gmgn-market trenches` → `docs/workflow-early-project-screening.md` |
|
||||
| "daily brief", "today's market", "每日简报", "今天市场怎么样", "聪明钱今天买了什么" | `gmgn-market` + `gmgn-track` → `docs/workflow-daily-brief.md` |
|
||||
| "what is smart money buying", "what are KOLs trading" | `gmgn-track smartmoney` / `gmgn-track kol` |
|
||||
| "wallets I follow", "my followed wallets traded" | `gmgn-track follow-wallet` |
|
||||
| "analyze this wallet", "is this wallet worth following", wallet address provided | `gmgn-portfolio` → full workflow: `docs/workflow-wallet-analysis.md` |
|
||||
| "wallet style", "smart money profile", "聪明钱画像", "这个钱包是长线还是短线", "跟着他买收益如何", "聪明钱排行榜" | `gmgn-portfolio` + `gmgn-track` → `docs/workflow-smart-money-profile.md` |
|
||||
| "risk warning", "风险预警", "有没有巨鲸出货", "流动性正常吗", "这个项目还安全吗" | `gmgn-token` + `gmgn-track` → `docs/workflow-risk-warning.md` |
|
||||
| "swap", "buy TOKEN", "sell TOKEN" | `gmgn-swap` — MUST run `gmgn-token security` on output token first |
|
||||
| "chart", "price history", "kline", "OHLCV" | `gmgn-market kline` |
|
||||
| "my holdings", "my portfolio", "what tokens do I hold" | `gmgn-portfolio holdings` |
|
||||
|
||||
**Workflow docs** (read these when the user wants a full multi-step analysis):
|
||||
- Token research (address → buy/watch/skip): `docs/workflow-token-research.md`
|
||||
- Project deep report (comprehensive analysis + verdict): `docs/workflow-project-deep-report.md`
|
||||
- Wallet analysis (address → follow/skip): `docs/workflow-wallet-analysis.md`
|
||||
- Smart money profile (trading style, copy-trade estimate, leaderboard): `docs/workflow-smart-money-profile.md`
|
||||
- Risk warning (whale exit, liquidity drain, dev dump check): `docs/workflow-risk-warning.md`
|
||||
- Early project screening (new tokens → smart money filter → verdict): `docs/workflow-early-project-screening.md`
|
||||
- Daily brief (market pulse + smart money moves + early watch + risk scan): `docs/workflow-daily-brief.md`
|
||||
- Market discovery (find opportunities from trending): `docs/workflow-market-opportunities.md`
|
||||
|
||||
## Architecture
|
||||
|
||||
- **`src/`** — TypeScript source (CLI commands, API client, signer)
|
||||
- **`skills/`** — 4 SKILL.md files for Claude Code skill definitions
|
||||
- **`skills/`** — 5 SKILL.md files for Claude Code skill definitions
|
||||
- **`dist/`** — Compiled output (generated by `npm run build`)
|
||||
- **`.claude-plugin/`** — Plugin metadata for Claude Code
|
||||
|
||||
@@ -45,15 +93,15 @@ EOF
|
||||
|
||||
| Mode | Commands | Requirements |
|
||||
|------|----------|--------------|
|
||||
| Normal | token / market / portfolio | `GMGN_API_KEY` only, no signature |
|
||||
| Critical | swap / order | `GMGN_API_KEY` + `GMGN_PRIVATE_KEY` — CLI handles signing automatically |
|
||||
| Normal | token / market / portfolio (except holdings) / track kol / track smartmoney | `GMGN_API_KEY` only, no signature |
|
||||
| Critical | swap / order / portfolio holdings / track follow-wallet | `GMGN_API_KEY` + `GMGN_PRIVATE_KEY` — CLI handles signing automatically |
|
||||
|
||||
## SKILL.md Authoring Rules
|
||||
|
||||
When creating or updating any file in `skills/`:
|
||||
|
||||
- **Language**: English only — no bilingual content. SKILL.md files are read by AI, not humans.
|
||||
- **Package runner**: Always use the pre-installed `gmgn-cli` binary (e.g. `gmgn-cli token info ...`). Never use `npx gmgn-cli` or `npx gmgn-cli@<version>` — npx downloads the package at runtime alongside live credentials. The package must be installed once with `npm install -g gmgn-cli@1.0.1`.
|
||||
- **Package runner**: Always use the pre-installed `gmgn-cli` binary (e.g. `gmgn-cli token info ...`). Never use `npx gmgn-cli` or `npx gmgn-cli@<version>` — npx downloads the package at runtime alongside live credentials. The package must be installed once with `npm install -g gmgn-cli`.
|
||||
- **Section order**: Sub-commands → Supported Chains → Prerequisites → Parameters/Options (if needed) → Usage Examples → Notes
|
||||
- **`--raw` flag**: All commands support `--raw` for single-line JSON output. Always document it in the Notes section.
|
||||
- **YAML frontmatter**: Quote `argument-hint` values that contain `|` characters to avoid YAML parsing errors.
|
||||
|
||||
@@ -1,8 +1,91 @@
|
||||
# gmgn-cli
|
||||
<div align="center">
|
||||
|
||||
> 中文文档:[Readme.zh.md](Readme.zh.md)
|
||||
<img src="static/gmgnagentskills.png" alt="GMGN Agent Skills" />
|
||||
|
||||
GMGN AI skills for on-chain operations — token research, market data, wallet analysis, and swap.
|
||||
[](https://x.com/gmgnai) [](https://t.me/gmgnagentapi) [](https://discord.gg/gmgnai)
|
||||
|
||||
English | [简体中文](Readme.zh.md)
|
||||
|
||||
</div>
|
||||
|
||||
## GMGN Agent Skills
|
||||
|
||||
With GMGN Agent Skills, you can use AI agents to query real-time trending token rankings across multiple chains, token fundamentals, social media signals, live trading activity, new tokens in Trenches, top holders, top traders, smart money positions, KOL holdings, insider wallets, bundled wallet exposure, and other professional on-chain analytics. It also supports market orders, limit orders, advanced take-profit/stop-loss strategy orders, one-command cooking orders (buy + condition orders in a single flow), and wallet management — including real-time holdings, recent P&L, and transaction history — all through natural language.
|
||||
|
||||
---
|
||||
|
||||
## Why GMGN Skills
|
||||
|
||||
> Built for AI agents to query and trade multi-chain Meme tokens at high speed in real time. gmgn-skills gives AI agents direct access to GMGN's trending tokens, Trenches new token listings, and professional on-chain data — including Smart Money, KOL, rat trader, and bundler analytics.
|
||||
>
|
||||
> With 500+ professional data dimensions, you can turn your AI agent into a 24/7 real-time chain-scanning trading tool — monitoring multi-chain token momentum, placing orders instantly, and managing exits with take-profit / stop-loss, all on autopilot.
|
||||
|
||||
### 1. Real-time on-chain data — faster
|
||||
|
||||
Data across SOL / BSC / Base / ETH is live on every query. Supports multi-parameter customization, no snapshot cache — built for AI agent real-time decision-making (including but not limited to):
|
||||
|
||||
| Data | Granularity |
|
||||
|------|-------------|
|
||||
| New token discovery (Trenches) | Real-time, filtered by launchpad, dev holdings, KOL entry, rat trader ratio |
|
||||
| Trending tokens | Real-time, `1m` / `5m` / `1h` / `6h` / `24h` — minimum **1-minute** window |
|
||||
| Token info | Real-time — trade activity / price / volume / market cap |
|
||||
| Token security | Real-time — open source, renounced, honeypot detection, etc. |
|
||||
| Token analytics | Real-time — Dev / KOL / Smart Money / rat trader / bundler wallet holdings |
|
||||
| Monitoring & tracking | Real-time — KOL / Smart Money / followed wallet trade activity |
|
||||
| K-line (OHLCV) | Real-time, `1m` / `5m` / `15m` / `1h` / `4h` / `1d` — minimum **1-minute** candles |
|
||||
| Wallet holdings | Real-time — holdings / P&L / trade activity |
|
||||
|
||||
### 2. Trade faster
|
||||
|
||||
- Same RPC routing as GMGN's web trading interface, multi-region deployment, millisecond response — order submission under **0.3 seconds** end-to-end.
|
||||
- Automatic best-route selection, the same routing engine as GMGN web.
|
||||
- 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):
|
||||
|
||||
- **Smart money count** (`smart_degen_count`) and **KOL holders** (`renowned_wallets`) — live
|
||||
- **Rat trader ratio** (`rat_trader_amount_rate`) — volume share from insider/sneak wallets
|
||||
- **Bundler bot exposure** (`bundler_trader_amount_rate`) — volume from bot-bundled buys
|
||||
- **Sniper wallets** (`sniper_count`) — wallets that bought at the exact moment of launch
|
||||
- **Suspected insider hold rate** (`suspected_insider_hold_rate`)
|
||||
- **Fresh wallet ratio** (`fresh_wallet_rate`)
|
||||
- **Rug ratio score** (0–1) + honeypot detection + wash-trade flag
|
||||
- **Bonding curve status** (`is_on_curve`) — whether the token has graduated to open DEX
|
||||
|
||||
### 4. What you can do with GMGN Skills
|
||||
|
||||
**Real-time chain scanning**
|
||||
- Scan Trenches for new tokens, filtered by launchpad (Pump.fun, letsbonk, fourmeme, clanker…), dev holdings, KOL entry, and rat trader ratio in real time
|
||||
- Browse multi-chain trending token rankings (minimum 1-minute granularity), sorted by volume, smart money count, market cap, and more
|
||||
- Track new tokens in real time — see which tokens KOLs, Smart Money, and wallets you follow are buying, and auto-analyze the latest hot tokens
|
||||
- Fetch real-time K-line / OHLCV data for any token (1m / 5m / 15m / 1h / 4h / 1d)
|
||||
|
||||
**Token analytics**
|
||||
- Query token fundamentals, social links, Bonding Curve status, and liquidity pool details
|
||||
- Security check: open source, renounced, honeypot, wash trading, Rug ratio score (0–1)
|
||||
- Deep holder analysis: Smart Money / KOL / rat trader / bundler / sniper / whale / fresh wallet — holdings breakdown and rankings
|
||||
|
||||
**Wallet & tracking**
|
||||
- Analyze any wallet: real-time holdings, realized / unrealized P&L, win rate, trade style, full history
|
||||
- Track the latest buys and sells from Smart Money, KOL, and wallets you follow in real time
|
||||
|
||||
**Automated trading**
|
||||
- Market orders, limit orders, take-profit / stop-loss strategy orders — end-to-end latency under 0.3 seconds
|
||||
- One-command sell by position percentage (`--percent 50`), no manual calculation needed
|
||||
|
||||
**AI workflows**
|
||||
- 9 built-in workflow docs: token research, project deep report, wallet analysis, Smart Money profiling, risk warning, early project screening, daily brief, market discovery, and more — ready to use out of the box
|
||||
|
||||
---
|
||||
|
||||
@@ -13,52 +96,210 @@ GMGN AI skills for on-chain operations — token research, market data, wallet a
|
||||
| [`/gmgn-token`](skills/gmgn-token/SKILL.md) | Token info, security, pool, holders, traders | [SKILL.md](skills/gmgn-token/SKILL.md) |
|
||||
| [`/gmgn-market`](skills/gmgn-market/SKILL.md) | K-line market data, trending tokens | [SKILL.md](skills/gmgn-market/SKILL.md) |
|
||||
| [`/gmgn-portfolio`](skills/gmgn-portfolio/SKILL.md) | Wallet holdings, activity, stats | [SKILL.md](skills/gmgn-portfolio/SKILL.md) |
|
||||
| [`/gmgn-swap`](skills/gmgn-swap/SKILL.md) | Swap submission + order query | [SKILL.md](skills/gmgn-swap/SKILL.md) |
|
||||
| [`/gmgn-track`](skills/gmgn-track/SKILL.md) | Follow-wallet trades, KOL trades, Smart Money trades | [SKILL.md](skills/gmgn-track/SKILL.md) |
|
||||
| [`/gmgn-swap`](skills/gmgn-swap/SKILL.md) | Swap submission + limit orders + strategy orders + order query | [SKILL.md](skills/gmgn-swap/SKILL.md) |
|
||||
| [`/gmgn-cooking`](skills/gmgn-cooking/SKILL.md) | One-command cooking orders (buy + take-profit/stop-loss in a single flow) | [SKILL.md](skills/gmgn-cooking/SKILL.md) |
|
||||
|
||||
> For detailed CLI commands, parameters, and recommended values, see the [Wiki documentation](https://github.com/GMGNAI/gmgn-skills/wiki).
|
||||
|
||||
### Quick Start
|
||||
|
||||
> **Note for AI assistants:** If you are an AI Agent helping the user install or configure gmgn-cli, jump directly to [Quick Start (AI Agent)](#quick-start-ai-agent) — it contains all the steps you need to complete, including how to guide the user through API key generation. If the user asks to upgrade, jump to [Upgrade (AI Agent)](#upgrade-ai-agent).
|
||||
|
||||
Ready to install? [Jump to Installation →](#1-installation)
|
||||
|
||||
Already installed? [Upgrade Skills and CLI →](#10-upgrade-skills-and-cli)
|
||||
|
||||
> **Tip:** If your AI agent tries to open or scrape the gmgn.ai website instead of using the CLI, add this to your prompt: `Use gmgn-cli commands. Do not call gmgn.ai web endpoints directly.`
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
## Quick Start (AI Agent)
|
||||
|
||||
Natural language prompts you can send to any AI assistant with gmgn-cli skills installed:
|
||||
> The following steps are for AI Agents. Some steps require the user to complete actions in a browser.
|
||||
|
||||
**Step 1 — Install CLI and Skills**
|
||||
|
||||
```bash
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
buy 0.1 SOL of <token_address>
|
||||
sell 50% of <token_address> on BSC
|
||||
check order status <order_id>
|
||||
is <token_address> safe to buy on solana?
|
||||
show top holders of <token_address>
|
||||
show my wallet holdings on SOL
|
||||
query token details for 0x1234...
|
||||
show trading stats for wallet <wallet_address> on BSC
|
||||
|
||||
**Step 2 — Verify CLI installation (demo key)**
|
||||
|
||||
```bash
|
||||
GMGN_API_KEY=gmgn_solbscbaseethmonadtron gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
If JSON output appears, the CLI is installed correctly. **Setup is NOT yet complete — this is a public demo key for testing only. You must continue to Steps 3–4 to configure the user's personal API key. Do not stop here.**
|
||||
|
||||
**Step 3 — REQUIRED: Set up personal API key**
|
||||
|
||||
⚠️ This step is mandatory. The demo key in Step 2 supports testing only and is not for actual use.
|
||||
|
||||
Immediately tell the user the following, then run the key generation command **without waiting for them to ask**:
|
||||
|
||||
> "To use GMGN Skills, you need your own API key from **https://gmgn.ai/ai**. I'm generating an Ed25519 key pair for you now."
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
|
||||
Show the **public key** to the user with the following instructions:
|
||||
|
||||
> This is your Ed25519 public key. Please complete these two steps:
|
||||
> 1. Go to **https://gmgn.ai/ai**, paste the public key above into the API Key creation form, and submit.
|
||||
> 2. Once created, copy the **API Key** shown on the page and send it back to me — I'll handle Step 4 configuration for you.
|
||||
|
||||
**Wait for the user to reply with their API Key before continuing to Step 4.**
|
||||
|
||||
**Step 4 — Configure credentials**
|
||||
|
||||
After the user receives their API key, write it to the global config:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
# Write API key (replace with the actual key the user provides)
|
||||
echo 'GMGN_API_KEY=<user_api_key>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
If the user also needs swap or order capability, append the private key:
|
||||
|
||||
```bash
|
||||
# Append private key (use the PEM content from Step 3)
|
||||
echo 'GMGN_PRIVATE_KEY="<pem_content>"' >> ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
**Step 5 — Verify**
|
||||
|
||||
```bash
|
||||
gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
If output appears without error, setup is complete.
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
## Upgrade (AI Agent)
|
||||
|
||||
### 0. Prepare
|
||||
> Run these two commands to upgrade both the CLI and Skills to the latest version.
|
||||
|
||||
Before applying for an API Key, get two things ready:
|
||||
```bash
|
||||
npm install -g gmgn-cli
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
**Generate an Ed25519 key pair**
|
||||
Check the installed version after upgrading:
|
||||
|
||||
Download and run the [Binance Asymmetric Key Generator](https://github.com/binance/asymmetric-key-generator/releases). You will need the **public key** when filling out the API Key application, and the **private key** in your `.env` later (for swap / order).
|
||||
```bash
|
||||
gmgn-cli --version
|
||||
```
|
||||
|
||||
**Get your public egress IP** (for the IP whitelist)
|
||||
> For the full upgrade reference, see [Section 10 — Upgrade Skills and CLI](#10-upgrade-skills-and-cli).
|
||||
|
||||
---
|
||||
|
||||
## Demo Cases
|
||||
|
||||
### Trending Token Rankings
|
||||
|
||||
Send this prompt to your AI Agent:
|
||||
|
||||
```
|
||||
Fetch Solana 1h trending, filter for pump.fun tokens created within 6h, sort by volume descending.
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Real-Time Token Trading Analysis
|
||||
|
||||
Send this prompt to your AI Agent:
|
||||
|
||||
```
|
||||
Check the first token's K-line, analyze entry timing, plot price + volume chart, and provide social media links and smart money/KOL trading analysis.
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
## 1. Installation
|
||||
|
||||
> **Prerequisites:** Before installing, create your API Key at **https://gmgn.ai/ai** (see [Section 3](#3-get-your-own-api-key) for the full setup guide).
|
||||
|
||||
Choose one of the following methods:
|
||||
|
||||
### 1.1 Via Agent (recommended)
|
||||
|
||||
Send this to your AI agent:
|
||||
|
||||
```bash
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
### 1.2 npm Global Install
|
||||
|
||||
```bash
|
||||
npm install -g gmgn-cli
|
||||
```
|
||||
|
||||
### 1.3 Local Development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
node dist/index.js <command> [options]
|
||||
```
|
||||
|
||||
## 2. Verify Connection
|
||||
|
||||
Test with the public API key — no registration required:
|
||||
|
||||
```bash
|
||||
GMGN_API_KEY=gmgn_solbscbaseethmonadtron gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
If you see JSON output, the CLI is working. The public key supports all read-only commands (token / market / portfolio) and is for testing only — apply for your own API key to use any feature (see step 3).
|
||||
|
||||
> **Troubleshooting — 401 / 403 errors:** If the command fails with `401` or `403` and credentials look correct, your outbound traffic may be going via IPv6 (not supported). Check immediately: (1) run `ifconfig | grep inet6` (macOS) or `ip addr show | grep inet6` (Linux) to list all network interfaces and their IPv6 addresses; (2) run `curl -s https://ipv6.icanhazip.com` — if it returns an IPv6 address, your traffic is going via IPv6. **Disable IPv6 on your network interface — gmgn-cli commands only work over IPv4.**
|
||||
|
||||
## 3. Get Your Own API Key
|
||||
|
||||
The public key in step 2 is for testing only. Apply for your own API key at **https://gmgn.ai/ai** — required for all actual use (read-only and swap). You will need:
|
||||
|
||||
### 3.1 Generate an Ed25519 Key Pair
|
||||
|
||||
**Option 1 — Ask your AI agent (recommended)**
|
||||
|
||||
Send this prompt to your agent:
|
||||
|
||||
```
|
||||
Generate an Ed25519 key pair for me using OpenSSL and show me:
|
||||
1. The public key (I need to fill it in the GMGN API Key application form)
|
||||
2. The private key in PEM format (I need to set it as GMGN_PRIVATE_KEY in my .env)
|
||||
```
|
||||
|
||||
**Option 2 — Binance Key Generator**
|
||||
|
||||
Download and run the [Binance Asymmetric Key Generator](https://github.com/binance/asymmetric-key-generator/releases).
|
||||
|
||||
Enter the **public key** in the application form.
|
||||
|
||||
### 3.2 Get Your Public Egress IP
|
||||
|
||||
For the IP whitelist (required when enabling swap capability on your API key):
|
||||
|
||||
```bash
|
||||
curl ip.me
|
||||
```
|
||||
|
||||
Or visit **https://ip.me** in your browser.
|
||||
## 4. Configure Your API Key
|
||||
|
||||
### 1. Get an API Key
|
||||
|
||||
Apply at **https://gmgn.ai/ai** — enter the public key and your IP address from the step above.
|
||||
|
||||
### 2. Configure
|
||||
|
||||
**Option A — Global config (recommended)**
|
||||
### Option 1: Global config (recommended)
|
||||
|
||||
Create `~/.config/gmgn/.env` once — works from any directory:
|
||||
|
||||
@@ -67,12 +308,12 @@ mkdir -p ~/.config/gmgn
|
||||
cat > ~/.config/gmgn/.env << 'EOF'
|
||||
GMGN_API_KEY=your_api_key_here
|
||||
|
||||
# Required for swap / order (private key from step 0):
|
||||
# Required for swap / order only:
|
||||
GMGN_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n<base64>\n-----END PRIVATE KEY-----\n"
|
||||
EOF
|
||||
```
|
||||
|
||||
**Option B — Project `.env`**
|
||||
### Option 2: Project `.env`
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
@@ -81,24 +322,16 @@ cp .env.example .env
|
||||
|
||||
Config lookup order: `~/.config/gmgn/.env` → project `.env` (project takes precedence).
|
||||
|
||||
### 3. CLI Install
|
||||
## 5. Try in AI Clients
|
||||
|
||||
Install a pinned version to avoid pulling untrusted updates at runtime:
|
||||
#### OpenClaw
|
||||
|
||||
Send the following prompt directly to test the query capabilities:
|
||||
|
||||
```bash
|
||||
npm install -g gmgn-cli@1.0.1
|
||||
```
|
||||
|
||||
Local development:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
node dist/index.js <command> [options]
|
||||
Show me the trending tokens on Solana in the last 1 hour.
|
||||
```
|
||||
|
||||
### 4. Connect to Your AI Tool
|
||||
|
||||
#### Claude Code
|
||||
|
||||
Skills are automatically discovered when the package is installed as a plugin.
|
||||
@@ -107,24 +340,22 @@ Skills are automatically discovered when the package is installed as a plugin.
|
||||
|
||||
Skills are automatically discovered via the `.cursor-plugin/` configuration.
|
||||
|
||||
1. Complete steps 1–3 above
|
||||
2. Configure credentials in `~/.config/gmgn/.env`
|
||||
3. Restart Cursor — skills will be available in Agent mode via `/gmgn-*` commands
|
||||
1. Complete the installation and configuration steps above
|
||||
2. Restart Cursor — skills will be available in Agent mode via `/gmgn-*` commands
|
||||
|
||||
#### Cline
|
||||
|
||||
1. Complete steps 1–3 above
|
||||
1. Complete the installation and configuration steps above
|
||||
2. In Cline settings → **Skills directory**: point to the installed package's `skills/` folder:
|
||||
```bash
|
||||
echo "$(npm root -g)/gmgn-skills/skills"
|
||||
```
|
||||
3. Configure credentials in `~/.config/gmgn/.env`
|
||||
4. Restart Cline — `/gmgn-token`, `/gmgn-market`, `/gmgn-portfolio`, `/gmgn-swap` will be available
|
||||
3. Restart Cline — `/gmgn-token`, `/gmgn-market`, `/gmgn-portfolio`, `/gmgn-track`, `/gmgn-swap`, `/gmgn-cooking` will be available
|
||||
|
||||
#### Codex CLI
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.codex/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.codex/gmgn-cli
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.codex/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
```
|
||||
@@ -134,7 +365,7 @@ See [.codex/INSTALL.md](.codex/INSTALL.md) for full instructions.
|
||||
#### OpenCode
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.opencode/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.opencode/gmgn-cli
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.opencode/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
```
|
||||
@@ -143,7 +374,35 @@ See [.opencode/INSTALL.md](.opencode/INSTALL.md) for full instructions.
|
||||
|
||||
---
|
||||
|
||||
## Typical Workflows
|
||||
## 6. Usage
|
||||
|
||||
### Examples
|
||||
|
||||
Natural language prompts you can send to any AI assistant with gmgn-cli skills installed:
|
||||
|
||||
```
|
||||
buy 0.1 SOL of <token_address>
|
||||
sell 50% of <token_address> on BSC
|
||||
sell 30% of my <token_address> position
|
||||
get a quote: how much <token_address> can I get for 1 SOL?
|
||||
check order status <order_id>
|
||||
is <token_address> safe to buy on solana?
|
||||
show top holders of <token_address>
|
||||
show smart money holdings of <token_address>, sorted by buy volume
|
||||
show recent KOL trades for <token_address>
|
||||
show my wallet holdings on SOL
|
||||
query token details for 0x1234...
|
||||
show 24h K-line and volume for <token_address>
|
||||
show trading stats for wallet <wallet_address> on BSC
|
||||
show recent trades for wallet <wallet_address>
|
||||
which wallets are linked to my API key, and what are their balances
|
||||
show the latest smart money trades on SOL
|
||||
show what KOLs are buying on SOL
|
||||
show newly launched tokens on Solana
|
||||
show Solana 1-minute trending tokens
|
||||
```
|
||||
|
||||
### Typical Workflows
|
||||
|
||||
**Research a token:**
|
||||
```
|
||||
@@ -167,37 +426,103 @@ market trending (top 50) → AI selects top 5 by multi-factor analysis → u
|
||||
|
||||
---
|
||||
|
||||
## CLI Reference
|
||||
## 7. Workflow Docs
|
||||
|
||||
Full parameter reference: [docs/cli-usage.md](docs/cli-usage.md)
|
||||
Step-by-step guides for common analysis tasks:
|
||||
|
||||
| Workflow | When to use |
|
||||
|----------|-------------|
|
||||
| [workflow-token-research.md](docs/workflow-token-research.md) | Pre-buy token due diligence (address → buy/watch/skip) |
|
||||
| [workflow-project-deep-report.md](docs/workflow-project-deep-report.md) | Comprehensive project analysis with scored dimensions and full written report |
|
||||
| [workflow-wallet-analysis.md](docs/workflow-wallet-analysis.md) | Wallet quality assessment (address → follow/skip) |
|
||||
| [workflow-smart-money-profile.md](docs/workflow-smart-money-profile.md) | Trading style analysis, copy-trade ROI estimate, smart money leaderboard |
|
||||
| [workflow-risk-warning.md](docs/workflow-risk-warning.md) | Active risk monitoring for held positions (whale exit, liquidity, dev dump) |
|
||||
| [workflow-early-project-screening.md](docs/workflow-early-project-screening.md) | Screen newly launched launchpad tokens for smart money entry |
|
||||
| [workflow-daily-brief.md](docs/workflow-daily-brief.md) | Daily market overview: trending + smart money moves + early watch + risk scan |
|
||||
| [workflow-market-opportunities.md](docs/workflow-market-opportunities.md) | Discover trading opportunities from trending data |
|
||||
| [workflow-token-due-diligence.md](docs/workflow-token-due-diligence.md) | 4-step token due diligence checklist |
|
||||
|
||||
## 8. CLI Reference
|
||||
|
||||
Full parameter reference: [docs/cli-usage.md](docs/cli-usage.md). All commands support `--raw` for single-line JSON output (pipe-friendly, e.g. `| jq '.price'`).
|
||||
|
||||
### Token
|
||||
|
||||
```bash
|
||||
npx gmgn-cli token info --chain sol --address <addr>
|
||||
gmgn-cli token info --chain sol --address <addr>
|
||||
```
|
||||
|
||||
### Market
|
||||
|
||||
```bash
|
||||
npx gmgn-cli market trending \
|
||||
gmgn-cli market trending \
|
||||
--chain sol \
|
||||
--interval 1h \
|
||||
--order-by volume --limit 20 \
|
||||
--filter not_risk --filter not_honeypot
|
||||
|
||||
gmgn-cli market trenches \
|
||||
--chain sol \
|
||||
--type new_creation --type near_completion --type completed \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform letsbonk \
|
||||
--limit 80
|
||||
|
||||
# With server-side filters: safe preset + require smart money + sort by smart degen count
|
||||
gmgn-cli market trenches \
|
||||
--chain sol --type new_creation \
|
||||
--filter-preset safe --min-smart-degen-count 1 --sort-by smart_degen_count
|
||||
|
||||
# Token signals — smart money buys on SOL (single group)
|
||||
gmgn-cli market signal --chain sol --signal-type 12 --raw
|
||||
|
||||
# Token signals — multi-group: smart money OR large buys in parallel
|
||||
gmgn-cli market signal --chain sol \
|
||||
--groups '[{"signal_type":[12]},{"signal_type":[14,16]}]' --raw
|
||||
```
|
||||
|
||||
### Portfolio
|
||||
|
||||
```bash
|
||||
npx gmgn-cli portfolio holdings --chain sol --wallet <addr>
|
||||
# Holdings
|
||||
gmgn-cli portfolio holdings --chain sol --wallet <addr>
|
||||
|
||||
# Activity
|
||||
gmgn-cli portfolio activity --chain sol --wallet <addr>
|
||||
|
||||
# Stats (supports multiple wallets)
|
||||
gmgn-cli portfolio stats --chain sol --wallet <addr1> --wallet <addr2>
|
||||
|
||||
# Wallets and balances linked to API key
|
||||
gmgn-cli portfolio info
|
||||
|
||||
# Single token balance
|
||||
gmgn-cli portfolio token-balance --chain sol --wallet <addr> --token <token_addr>
|
||||
|
||||
# Tokens created by a developer wallet
|
||||
gmgn-cli portfolio created-tokens --chain sol --wallet <addr>
|
||||
```
|
||||
|
||||
### Swap (requires private key)
|
||||
### Track
|
||||
|
||||
```bash
|
||||
# Submit swap
|
||||
npx gmgn-cli swap \
|
||||
# Follow-wallet trade records
|
||||
gmgn-cli track follow-wallet --chain sol
|
||||
gmgn-cli track follow-wallet --chain sol --limit 20 --min-amount-usd 1000
|
||||
|
||||
# KOL trade records
|
||||
gmgn-cli track kol --limit 100 --raw
|
||||
gmgn-cli track kol --chain sol --side buy --limit 50 --raw
|
||||
|
||||
# Smart Money trade records
|
||||
gmgn-cli track smartmoney --limit 100 --raw
|
||||
gmgn-cli track smartmoney --chain sol --side sell --limit 50 --raw
|
||||
```
|
||||
|
||||
### Swap / Quote / Query
|
||||
|
||||
```bash
|
||||
# Submit swap with fixed slippage
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
@@ -205,32 +530,208 @@ npx gmgn-cli swap \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# Submit swap with automatic slippage
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount 1000000 \
|
||||
--auto-slippage
|
||||
|
||||
# Sell by position percentage (e.g. sell 50%)
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <token-addr> \
|
||||
--output-token <usdc-addr> \
|
||||
--percent 50 \
|
||||
--auto-slippage
|
||||
|
||||
# Get quote (no transaction submitted)
|
||||
gmgn-cli order quote \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# Quotes use signed 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
|
||||
npx gmgn-cli order get --chain sol --order-id <order-id>
|
||||
gmgn-cli order get --chain sol --order-id <order-id>
|
||||
|
||||
# Query real-time gas price (all chains)
|
||||
gmgn-cli gas-price --chain sol
|
||||
gmgn-cli gas-price --chain eth
|
||||
gmgn-cli gas-price --chain bsc
|
||||
gmgn-cli gas-price --chain base
|
||||
|
||||
# Multi-wallet concurrent swap
|
||||
gmgn-cli multi-swap \
|
||||
--chain sol \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--input-amount '{"<addr1>":"1000000","<addr2>":"2000000"}' \
|
||||
--slippage 0.01
|
||||
```
|
||||
|
||||
> `order quote` uses signed auth on `sol` / `bsc` / `base` / `eth` and requires `GMGN_PRIVATE_KEY`.
|
||||
|
||||
### ETH Gas Control (ETH only)
|
||||
|
||||
```bash
|
||||
# Pick a gas tier instead of entering gwei manually (low / average / high)
|
||||
gmgn-cli swap \
|
||||
--chain eth \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount <amount> \
|
||||
--slippage 0.01 \
|
||||
--gas-level high
|
||||
|
||||
# Let GMGN auto-select the optimal gas fee for condition orders
|
||||
gmgn-cli swap \
|
||||
--chain eth \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount <amount> \
|
||||
--slippage 0.01 \
|
||||
--condition-orders '[...]' \
|
||||
--auto-fee
|
||||
```
|
||||
|
||||
> `--gas-level` and `--auto-fee` are ETH only. `--auto-fee` only takes effect when used with `--condition-orders`.
|
||||
> For other chains (SOL / BSC / BASE), use `gas-price` to query the current gas, then pass the result via `--gas-price`.
|
||||
|
||||
### 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.
|
||||
|
||||
---
|
||||
|
||||
## Supported Chains
|
||||
### 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 |
|
||||
|----------|--------|-----------------|
|
||||
| token / market / portfolio | `sol` / `bsc` / `base` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` | sol: SOL, USDC · bsc: BNB, USDC · base: ETH, USDC |
|
||||
| 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` | — |
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
Default: formatted JSON. Use `--raw` for single-line JSON (pipe-friendly):
|
||||
## 10. Upgrade Skills and CLI
|
||||
|
||||
```bash
|
||||
npx gmgn-cli token info --chain sol --address <addr> --raw | jq '.price'
|
||||
# Upgrade CLI
|
||||
npm install -g gmgn-cli
|
||||
|
||||
# Upgrade Skills
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
|
||||
# Check current version
|
||||
gmgn-cli --version
|
||||
```
|
||||
|
||||
> **Via AI Agent:** Tell your agent — "Upgrade gmgn-cli and the skills to the latest version." See also [Upgrade (AI Agent)](#upgrade-ai-agent).
|
||||
|
||||
---
|
||||
|
||||
## Security & Disclaimer
|
||||
## 11. Security & Disclaimer (Read Before Use)
|
||||
|
||||
This tool can be invoked by an AI Agent to submit real on-chain transactions automatically. It carries inherent risks including model hallucination, uncontrolled execution, and prompt injection. Once authorized, the AI Agent will submit transactions on behalf of your linked wallet address — **on-chain transactions are irreversible once confirmed** and may result in financial loss. Use with caution.
|
||||
|
||||
**About `GMGN_PRIVATE_KEY`**
|
||||
|
||||
@@ -241,11 +742,13 @@ npx gmgn-cli token info --chain sol --address <addr> --raw | jq '.price'
|
||||
- Restrict config file permissions: `chmod 600 ~/.config/gmgn/.env`
|
||||
- Never commit your `.env` file to version control — add it to `.gitignore`
|
||||
- Do not share `GMGN_API_KEY` or `GMGN_PRIVATE_KEY` in logs, screenshots, or chat messages
|
||||
- Use a pinned install (`npm install -g gmgn-cli@1.0.1`) rather than `npx gmgn-cli` to avoid executing unintended package updates alongside your credentials
|
||||
- Before every swap, carefully review the trade summary presented by the AI (chain, wallet, token addresses, amount) and confirm only when it matches your intent
|
||||
- Test with small amounts first before executing larger trades
|
||||
- Always use the latest version of gmgn-cli (`npm install -g gmgn-cli`). To check your current version: `gmgn-cli --version`
|
||||
|
||||
**Disclaimer**
|
||||
|
||||
Use of this tool and any financial decisions made based on its output are entirely at your own risk. GMGN is not liable for any trading losses, errors, or unauthorized access resulting from improper credential management.
|
||||
Use of this tool and any financial decisions made based on its output are entirely at your own risk. GMGN is not liable for any trading losses, errors, or unauthorized access resulting from model hallucination, prompt injection, improper credential management, or user confirmation errors. By using this tool, you acknowledge that you have fully understood the above risks and voluntarily accept all responsibility.
|
||||
|
||||
The npm package is published with provenance attestation, linking each release to a specific git commit and CI pipeline run. Verify with:
|
||||
```bash
|
||||
|
||||
@@ -1,8 +1,94 @@
|
||||
# gmgn-cli
|
||||
<div align="center">
|
||||
|
||||
> English: [Readme.md](Readme.md)
|
||||
<img src="static/gmgnagentskills.png" alt="GMGN Agent Skills" />
|
||||
|
||||
GMGN 链上操作 AI 技能套件 — Token 研究、行情数据、钱包分析和交易。
|
||||
[](https://x.com/gmgnai) [](https://t.me/gmgnagentapi) [](https://discord.gg/gmgnai)
|
||||
|
||||
[English](Readme.md) | 简体中文
|
||||
|
||||
</div>
|
||||
|
||||
## GMGN Agent Skills
|
||||
|
||||
使用 GMGN Agent Skills,你可以通过 AI Agent 实时查询多个链上热门代币排行榜,代币基础信息,社交媒体信息,实时交易动态,实时战壕新币,报持仓大户(Top Holder),交易大户(Top Trader),聪明钱持仓占比,KOL持仓占比,老鼠仓持仓,捆绑持仓占比,等代币专业数据分析数据,以及支持代币市价单交易、限价单交易、高级止盈止损策略单交易、一键 Cooking 策略单(买入 + 条件单一体化),以及钱包资产管理相关功能,例如查询钱包实时持仓、钱包最近盈亏、钱包交易动态等,全部通过自然语言与 AI Agent 交互即可完成。
|
||||
|
||||
---
|
||||
|
||||
## 为什么选择 GMGN Skills
|
||||
|
||||
> 专为 AI Agent 高速实时查询、交易多链 Meme 代币而生。GMGN Skills 让 AI Agent 可以实时批量查询 GMGN 网站展示的热门代币、Trenches新创建代币,以及聪明钱、KOL、老鼠仓等专业顶级交易数据。
|
||||
>
|
||||
> 凭借 500+ 专业数据分析维度,你可以将自己的 AI Agent 打造成 7×24 小时全天候托管的实时扫链交易工具——实时监控多链代币热点、实时下单、实时止盈止损,实现全自动化交易。
|
||||
|
||||
### 1. 链上实时数据查询快
|
||||
|
||||
SOL / BSC / Base / ETH 多链数据每次查询均为实时,支持多参数个性化调用,无快照缓存,方便AI Agent实时决策(包括不限于下表)。
|
||||
|
||||
| 数据类型 | 粒度 |
|
||||
|---------|------|
|
||||
| 新币发现(战壕) | 实时,按 Launchpad 平台,dev持仓,KOL持仓,老鼠仓持仓分类 |
|
||||
| 热门代币榜单 | 实时,`1m` / `5m` / `1h` / `6h` / `24h`,最低支持 **1 分钟**窗口 |
|
||||
| 代币信息 |实时,交易动态 / 代币价格 / 交易量 / 市值 等|
|
||||
|代币安全 |实时,是否开源,弃权,貔貅检测等 |
|
||||
|代币数据分析|实时,Dev / KOL / 聪明钱 / 老鼠仓 / 捆绑钱包等持仓占比 等|
|
||||
|监控追踪|实时,KOL / 聪明钱 / 关注的钱包交易动态 / 天眼信号(开发中) 等|
|
||||
| K 线(OHLCV) | 实时,`1m` / `5m` / `15m` / `1h` / `4h` / `1d`,最低支持 **1 分钟** |
|
||||
|资产持仓|实时,持仓/盈亏/交易动态 等|
|
||||
|
||||
|
||||
|
||||
|
||||
### 2. 交易更快
|
||||
|
||||
- 与 GMGN 网页端共享同一套 RPC 路由,多区域部署,毫秒级响应,从下单到上链延时小于 **0.3 秒**。
|
||||
- 交易自动找最佳路由,与 GMGN 网页端同一套
|
||||
- 单条命令支持市价单、限价单、策略单(止盈 / 止损)。
|
||||
- 支持按仓位比例卖出(`--percent 50`),无需手动计算数量。
|
||||
|
||||
| 订单类型 | 说明 |
|
||||
|----------|------|
|
||||
| 市价单 | 以当前市价即时成交 |
|
||||
| 限价单 | 设定触发价格,到价买入或卖出 |
|
||||
| 止盈 / 止损 | 随买单附带固定价格的退出条件 |
|
||||
| 追踪止盈 / 追踪止损 | 跟踪价格峰值,回撤达到指定比例后触发,吃满行情同时保护收益 |
|
||||
| 多钱包批量交易 | 多个钱包同时买入,每个钱包分别创建对应的止盈 / 止损 / 追踪止盈 / 追踪止损订单 |
|
||||
|
||||
### 3. 特色数据更全
|
||||
|
||||
不用再爬网页,不会被Claudeflare拦截,现在就可以快速/多并发实时查询多链的 Meme 代币高频交易所需的所有专业分析指标数据 (包括不限于):
|
||||
|
||||
- **聪明钱数量**(`smart_degen_count`)和 **KOL 持仓**(`renowned_wallets`)— 实时
|
||||
- **老鼠仓占比**(`rat_trader_amount_rate`)— 内幕 / 偷跑钱包的交易量份额
|
||||
- **捆绑钱包暴露度**(`bundler_trader_amount_rate`)— 机器人捆绑买入的交易量占比
|
||||
- **狙击钱包数**(`sniper_count`)— 在代币刚开盘瞬间买入的钱包数量
|
||||
- **疑似内幕持仓比**(`suspected_insider_hold_rate`)
|
||||
- **新钱包占比**(`fresh_wallet_rate`)
|
||||
- **Rug 风险评分**(0–1)+ 貔貅检测 + 对倒洗盘识别
|
||||
- **Bonding Curve 状态**(`is_on_curve`)— 代币是否已毕业到开放 DEX
|
||||
|
||||
### 4. 可以用 GMGN Skills 做什么
|
||||
|
||||
**实时查链**
|
||||
- 扫描战壕新币,按 Launchpad(Pump.fun、letsbonk、fourmeme、clanker……)、dev 持仓、KOL 进场、老鼠仓占比实时过滤
|
||||
- 浏览多链热门代币榜单(最低 1 分钟粒度),按交易量、聪明钱数量、市值等多维排序
|
||||
- 实时追踪新币,追踪KOL/聪明/已关注的钱包最近在买哪些新币,自动分析最新热门代币
|
||||
- 获取任意代币的实时 K 线 / OHLCV 数据(1m / 5m / 15m / 1h / 4h / 1d)
|
||||
|
||||
**代币数据分析**
|
||||
- 查询代币基础信息、社交链接、Bonding Curve 状态、流动性池详情
|
||||
- 安全核查:是否开源、弃权、貔貅、对倒洗盘、Rug 风险评分(0–1)
|
||||
- 深度持仓分析:聪明钱 / KOL / 老鼠仓 / 捆绑钱包 / 狙击手 / 巨鲸 / 新钱包 各类持仓占比及排名
|
||||
|
||||
**钱包与追踪**
|
||||
- 分析任意钱包:实时持仓、已实现 / 未实现盈亏、胜率、交易风格、历史流水
|
||||
- 实时追踪聪明钱、KOL 和关注钱包的最新买卖动态
|
||||
|
||||
**自动化交易**
|
||||
- 市价单、限价单、止盈止损策略单,从下单到上链延时 < 0.3 秒
|
||||
- 按仓位比例一键卖出(`--percent 50`),无需手动计算数量
|
||||
|
||||
**AI 工作流**
|
||||
- 9 个内置工作流文档:代币研究、项目深度报告、钱包分析、聪明钱画像、风险预警、早期项目筛选、每日简报、市场发现等,开箱即用
|
||||
|
||||
---
|
||||
|
||||
@@ -13,52 +99,211 @@ GMGN 链上操作 AI 技能套件 — Token 研究、行情数据、钱包分析
|
||||
| [`/gmgn-token`](skills/gmgn-token/SKILL.md) | Token 信息、安全、池子、持有者、交易者 | [SKILL.md](skills/gmgn-token/SKILL.md) |
|
||||
| [`/gmgn-market`](skills/gmgn-market/SKILL.md) | K 线行情数据、热门代币 | [SKILL.md](skills/gmgn-market/SKILL.md) |
|
||||
| [`/gmgn-portfolio`](skills/gmgn-portfolio/SKILL.md) | 钱包持仓、活动、统计 | [SKILL.md](skills/gmgn-portfolio/SKILL.md) |
|
||||
| [`/gmgn-swap`](skills/gmgn-swap/SKILL.md) | 兑换提交 + 订单查询 | [SKILL.md](skills/gmgn-swap/SKILL.md) |
|
||||
| [`/gmgn-track`](skills/gmgn-track/SKILL.md) | 追踪关注钱包交易动态、KOL 交易动态、聪明钱交易动态 | [SKILL.md](skills/gmgn-track/SKILL.md) |
|
||||
| [`/gmgn-swap`](skills/gmgn-swap/SKILL.md) | 兑换提交 + 限价单 + 策略单 + 订单查询 | [SKILL.md](skills/gmgn-swap/SKILL.md) |
|
||||
| [`/gmgn-cooking`](skills/gmgn-cooking/SKILL.md) | 一键 Cooking 策略单(买入 + 止盈止损条件单一体化) | [SKILL.md](skills/gmgn-cooking/SKILL.md) |
|
||||
|
||||
> 如需查看详细的 CLI 接口说明、传参格式和推荐值,请参阅 [Wiki 文档](https://github.com/GMGNAI/gmgn-skills/wiki/Home-Chinese)。
|
||||
|
||||
### 快速开始安装
|
||||
|
||||
> **AI Agent 注意:** 如果你是正在协助用户安装或配置 gmgn-cli 的 AI Agent,请直接跳转到 [AI Agent 快速开始](#ai-agent-快速开始) — 其中包含你需要完成的所有步骤,包括如何引导用户完成 API Key 申请。如果用户要求升级,请跳转到 [AI Agent 升级](#ai-agent-升级)。
|
||||
|
||||
已准备好?[点击这里开始安装 Skills →](#开始安装-skills)
|
||||
|
||||
已安装?[升级 Skills 和 CLI →](#10-升级-skills-和-cli)
|
||||
|
||||
> **提示:** 如果你的 AI Agent 尝试直接打开 gmgn.ai 网站而不是使用 CLI,请在提示词中加上:
|
||||
> ```
|
||||
> 用 gmgn-cli 命令,不要直接请求gmgn.ai网页接口。
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
## 用法示例
|
||||
## AI Agent 快速开始
|
||||
|
||||
安装技能后,向 AI 助手直接发送自然语言指令:
|
||||
> 以下步骤面向 AI Agent。部分步骤需要用户在浏览器中配合完成。
|
||||
|
||||
**第 1 步 — 安装 CLI 和 Skills**
|
||||
|
||||
```bash
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
buy 0.1 SOL of <token_address>
|
||||
sell 50% of <token_address> on BSC
|
||||
check order status <order_id>
|
||||
is <token_address> safe to buy on solana?
|
||||
show top holders of <token_address>
|
||||
show my wallet holdings on SOL
|
||||
query token details for 0x1234...
|
||||
show trading stats for wallet <wallet_address> on BSC
|
||||
|
||||
**第 2 步 — 验证 CLI 安装(演示 Key)**
|
||||
|
||||
```bash
|
||||
GMGN_API_KEY=gmgn_solbscbaseethmonadtron gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
看到 JSON 输出说明 CLI 已安装成功。**但配置尚未完成 —— 此公共演示 Key 仅用于测试,不可用于实际使用。必须继续完成第 3~4 步,为用户配置个人 API Key。请勿在此停止。**
|
||||
|
||||
**第 3 步 — 必须完成:配置个人 API Key**
|
||||
|
||||
⚠️ 此步骤为必填项。第 2 步中的演示 Key 仅支持测试,无法用于正式使用。
|
||||
|
||||
请**立即**告知用户以下内容,并**无需等待用户主动询问**,直接运行密钥生成命令:
|
||||
|
||||
> "使用 GMGN Skills 需要你自己的个人 API Key,申请地址:**https://gmgn.ai/ai**。我现在为你生成 Ed25519 密钥对。"
|
||||
|
||||
运行:
|
||||
|
||||
```bash
|
||||
openssl genpkey -algorithm ed25519 -out /tmp/gmgn_private.pem 2>/dev/null && \
|
||||
openssl pkey -in /tmp/gmgn_private.pem -pubout 2>/dev/null
|
||||
```
|
||||
|
||||
将**公钥**展示给用户,并附上以下说明:
|
||||
|
||||
> 以上是你的 Ed25519 公钥。接下来请你完成以下两步:
|
||||
> 1. 打开 **https://gmgn.ai/ai**,将上方公钥填入 API Key 生成表单,完成创建。
|
||||
> 2. 创建完成后,将页面上显示的 **API Key** 复制并发送给我,我来帮你完成第 4 步配置。
|
||||
|
||||
**等用户回复 API Key 后,再继续第 4 步。**
|
||||
|
||||
**第 4 步 — 配置凭证**
|
||||
|
||||
用户收到 API Key 后,写入全局配置:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/gmgn
|
||||
# 写入 API Key(替换为用户提供的实际 Key)
|
||||
echo 'GMGN_API_KEY=<user_api_key>' > ~/.config/gmgn/.env
|
||||
chmod 600 ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
如果用户需要 swap 或 order 能力,追加私钥:
|
||||
|
||||
```bash
|
||||
# 追加私钥(使用第 3 步输出的 PEM 内容)
|
||||
echo 'GMGN_PRIVATE_KEY="<pem_content>"' >> ~/.config/gmgn/.env
|
||||
```
|
||||
|
||||
**第 5 步 — 验证**
|
||||
|
||||
```bash
|
||||
gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
有输出且无报错即配置完成。
|
||||
|
||||
---
|
||||
|
||||
## 安装配置
|
||||
## AI Agent 升级
|
||||
|
||||
### 0. 准备工作
|
||||
> 运行以下两条命令,将 CLI 和 Skills 同时升级到最新版本。
|
||||
|
||||
申请 API Key 前,需要先准备两件事:
|
||||
```bash
|
||||
npm install -g gmgn-cli
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
**生成 Ed25519 密钥对**
|
||||
升级后检查版本:
|
||||
|
||||
下载并运行 [Binance Asymmetric Key Generator](https://github.com/binance/asymmetric-key-generator/releases)。申请 API Key 时需要填入**公钥**,**私钥**稍后配置到 `.env`(swap / order 接口使用)。
|
||||
```bash
|
||||
gmgn-cli --version
|
||||
```
|
||||
|
||||
**获取本机出口 IP**(用于填写 IP 白名单)
|
||||
> 完整升级说明请参阅[第 10 节 — 升级 Skills 和 CLI](#10-升级-skills-和-cli)。
|
||||
|
||||
---
|
||||
|
||||
## 使用案例
|
||||
|
||||
### 查询热门代币榜
|
||||
|
||||
发送下面提示词给 AI Agent:
|
||||
|
||||
```
|
||||
查 Solana 1h 热门榜,筛出 6 小时内创建的新币,并且platforms是pump.fun的代币,然后按交易量从高到低排列。
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 实时分析代币交易走势
|
||||
|
||||
发送下面提示词给 AI Agent:
|
||||
|
||||
```
|
||||
查看第一个代币的 K 线,分析入场时机,并提供社交媒体链接以及聪明资金 / KOL 的交易分析。
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
## 1. 安装
|
||||
|
||||
选择以下任意一种方式
|
||||
|
||||
### 1.1 通过 Agent 安装(推荐)
|
||||
|
||||
发送给你的 AI Agent:
|
||||
|
||||
```bash
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
### 1.2 npm 全局安装
|
||||
|
||||
```bash
|
||||
npm install -g gmgn-cli
|
||||
```
|
||||
|
||||
### 1.3 本地开发
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
node dist/index.js <command> [options]
|
||||
```
|
||||
|
||||
## 2. 验证连通性
|
||||
|
||||
使用公共 API Key 测试,无需注册:
|
||||
|
||||
```bash
|
||||
GMGN_API_KEY=gmgn_solbscbaseethmonadtron gmgn-cli market trending --chain sol --interval 1h --limit 3
|
||||
```
|
||||
|
||||
看到 JSON 输出即表示 CLI 正常工作。公共 Key 支持所有只读接口(token / market / portfolio),公共 Key 仅用于测试,正式使用任何接口均需申请个人 API Key(见第 3 步)。
|
||||
|
||||
> **排查 401 / 403 错误:** 如果命令返回 `401` 或 `403` 且凭证看起来正确,出口请求可能走了 IPv6(GMGN API 不支持)。立即排查:(1) 运行 `ifconfig | grep inet6`(macOS)或 `ip addr show | grep inet6`(Linux)列出所有网络接口及其 IPv6 地址;(2) 运行 `curl -s https://ipv6.icanhazip.com`——如果返回 IPv6 地址,说明流量走了 IPv6。**请立即关闭 IPv6,gmgn-cli 命令只能通过 IPv4 请求。**
|
||||
|
||||
## 3. 申请个人 API Key
|
||||
|
||||
第 2 步的公共 Key 仅用于测试。正式使用(只读接口和 swap)均需在 https://gmgn.ai/ai 申请个人 API Key,需要准备:
|
||||
|
||||
### 3.1 生成 Ed25519 密钥对
|
||||
|
||||
**方式一:输入提示词(推荐)**
|
||||
|
||||
将以下提示词发送给你的 AI Agent:
|
||||
|
||||
```
|
||||
帮我用 OpenSSL 生成一个 Ed25519 密钥对,并分别显示给我:
|
||||
1. 公钥(我需要填写到GMGN网站上的 API Key 创建表单中)
|
||||
2. PEM 格式的私钥(我需要将它设置为 .env 中的 GMGN_PRIVATE_KEY)
|
||||
```
|
||||
|
||||
**方式二:Binance Key Generator**
|
||||
|
||||
下载并运行 [Binance Asymmetric Key Generator](https://github.com/binance/asymmetric-key-generator/releases)。
|
||||
|
||||
申请时填入**公钥**。
|
||||
|
||||
### 3.2 获取本机出口 IP
|
||||
|
||||
用于填写 IP 白名单(开通 API Key 的交易能力时需要):
|
||||
|
||||
```bash
|
||||
curl ip.me
|
||||
```
|
||||
|
||||
或在浏览器访问 **https://ip.me**。
|
||||
## 4. 配置个人 API Key
|
||||
|
||||
### 1. 获取 API Key
|
||||
|
||||
申请地址:**https://gmgn.ai/ai** — 填入上一步准备好的公钥和 IP 地址。
|
||||
|
||||
### 2. 配置
|
||||
|
||||
**方式 A — 全局配置(推荐)**
|
||||
### 方式一:全局配置(推荐)
|
||||
|
||||
创建 `~/.config/gmgn/.env`,配置一次,所有目录均生效:
|
||||
|
||||
@@ -67,12 +312,12 @@ mkdir -p ~/.config/gmgn
|
||||
cat > ~/.config/gmgn/.env << 'EOF'
|
||||
GMGN_API_KEY=your_api_key_here
|
||||
|
||||
# swap / order 接口额外需要(第 0 步生成的私钥):
|
||||
# 仅 swap / order 接口需要:
|
||||
GMGN_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n<base64>\n-----END PRIVATE KEY-----\n"
|
||||
EOF
|
||||
```
|
||||
|
||||
**方式 B — 项目 `.env`**
|
||||
### 方式二:项目 `.env`
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
@@ -81,24 +326,16 @@ cp .env.example .env
|
||||
|
||||
配置加载顺序:`~/.config/gmgn/.env` → 项目 `.env`(项目级优先)。
|
||||
|
||||
### 3. CLI 安装
|
||||
## 5. 在 AI 客户端中使用
|
||||
|
||||
安装固定版本,避免运行时拉取未经验证的更新:
|
||||
#### OpenClaw
|
||||
|
||||
直接发送以下提示词,测试查询能力:
|
||||
|
||||
```bash
|
||||
npm install -g gmgn-cli@1.0.1
|
||||
```
|
||||
|
||||
本地开发:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
node dist/index.js <command> [options]
|
||||
查询 Solana 链 1 小时热门代币
|
||||
```
|
||||
|
||||
### 4. 接入 AI 工具
|
||||
|
||||
#### Claude Code
|
||||
|
||||
安装包后通过插件机制自动发现技能。
|
||||
@@ -107,24 +344,22 @@ node dist/index.js <command> [options]
|
||||
|
||||
技能通过 `.cursor-plugin/` 配置自动发现。
|
||||
|
||||
1. 完成上方步骤 1–3
|
||||
2. 配置凭证:`~/.config/gmgn/.env`
|
||||
3. 重启 Cursor — Agent 模式下可通过 `/gmgn-*` 命令使用技能
|
||||
1. 完成上方安装和配置步骤
|
||||
2. 重启 Cursor — Agent 模式下可通过 `/gmgn-*` 命令使用技能
|
||||
|
||||
#### Cline
|
||||
|
||||
1. 完成上方步骤 1–3
|
||||
1. 完成上方安装和配置步骤
|
||||
2. 在 Cline 设置 → **Skills directory**:填入已安装包的 `skills/` 目录路径:
|
||||
```bash
|
||||
echo "$(npm root -g)/gmgn-skills/skills"
|
||||
```
|
||||
3. 配置凭证:`~/.config/gmgn/.env`
|
||||
4. 重启 Cline — `/gmgn-token`、`/gmgn-market`、`/gmgn-portfolio`、`/gmgn-swap` 即可使用
|
||||
3. 重启 Cline — `/gmgn-token`、`/gmgn-market`、`/gmgn-portfolio`、`/gmgn-track`、`/gmgn-swap`、`/gmgn-cooking` 即可使用
|
||||
|
||||
#### Codex CLI
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.codex/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.codex/gmgn-cli
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.codex/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
```
|
||||
@@ -134,7 +369,7 @@ ln -s ~/.codex/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
#### OpenCode
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gmgn-ai/gmgn-skills ~/.opencode/gmgn-cli
|
||||
git clone https://github.com/GMGNAI/gmgn-skills ~/.opencode/gmgn-cli
|
||||
mkdir -p ~/.agents/skills
|
||||
ln -s ~/.opencode/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
```
|
||||
@@ -143,61 +378,175 @@ ln -s ~/.opencode/gmgn-cli/skills ~/.agents/skills/gmgn-cli
|
||||
|
||||
---
|
||||
|
||||
## 典型使用场景
|
||||
## 6. 使用示例
|
||||
|
||||
### 常用指令
|
||||
|
||||
安装技能后,向 AI 助手直接发送自然语言指令:
|
||||
|
||||
```
|
||||
用 0.1 SOL 买入 <token_address>
|
||||
卖出 BSC 上 <token_address> 的 50%
|
||||
把我持有的 <token_address> 卖掉 30%
|
||||
查询报价,我想用 1 SOL 换 <token_address>,能换多少
|
||||
查询订单状态 <order_id>
|
||||
solana 上的 <token_address> 安全吗,值得买入吗?
|
||||
查看 <token_address> 的前十大持有者
|
||||
查看 <token_address> 的聪明钱持仓,按买入量排序
|
||||
查看 <token_address> 最近的 KOL 交易动态
|
||||
查看我在 SOL 上的钱包持仓
|
||||
查询 0x1234... 的代币详情
|
||||
查看 <token_address> 过去 24 小时的 K 线和交易量
|
||||
查看 BSC 上钱包 <wallet_address> 的交易统计
|
||||
查看钱包 <wallet_address> 最近的交易记录
|
||||
我的 API Key 绑定了哪些钱包,余额各是多少
|
||||
查看 SOL 链上最新的聪明钱交易动态
|
||||
查看 SOL 链上 KOL 最近在买什么
|
||||
查询 Solana 上最新发布的代币
|
||||
查询 Solana 1 分钟交易热门代币
|
||||
```
|
||||
|
||||
### 典型使用场景
|
||||
|
||||
**研究 Token:**
|
||||
```
|
||||
token info → token security → token pool → token holders
|
||||
查询代币信息 → 查询安全指标 → 查询流动池 → 查询持有者
|
||||
```
|
||||
|
||||
**分析钱包:**
|
||||
```
|
||||
portfolio holdings → portfolio stats → portfolio activity
|
||||
查询钱包持仓 → 查询交易统计 → 查询交易记录
|
||||
```
|
||||
|
||||
**执行交易:**
|
||||
```
|
||||
token info(确认 Token) → portfolio token-balance(检查余额) → swap → order get(轮询状态)
|
||||
确认代币信息 → 检查余额 → 提交兑换 → 轮询订单状态
|
||||
```
|
||||
|
||||
**通过 Trending 发现交易机会:**
|
||||
**通过热门榜单发现交易机会:**
|
||||
```
|
||||
market trending(取 50 条) → AI 多维度分析选出 top 5 → 用户确认 → token info / token security → swap
|
||||
获取热门代币(50 条) → AI 多维度分析选出 top 5 → 用户确认 → 查询代币信息 / 安全指标 → 提交兑换
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI 参考
|
||||
## 7. 工作流文档
|
||||
|
||||
完整参数说明:[docs/cli-usage.md](docs/cli-usage.md)
|
||||
常用分析任务的分步指引:
|
||||
|
||||
| 工作流 | 适用场景 |
|
||||
|--------|---------|
|
||||
| [workflow-token-research.md](docs/workflow-token-research.md) | 买入前 Token 尽调(地址 → 买入/观望/跳过) |
|
||||
| [workflow-project-deep-report.md](docs/workflow-project-deep-report.md) | 多维度评分的深度项目报告 |
|
||||
| [workflow-wallet-analysis.md](docs/workflow-wallet-analysis.md) | 钱包质量评估(地址 → 是否值得跟随) |
|
||||
| [workflow-smart-money-profile.md](docs/workflow-smart-money-profile.md) | 聪明钱行为画像、跟单收益估算、排行榜对比 |
|
||||
| [workflow-risk-warning.md](docs/workflow-risk-warning.md) | 持仓风险预警(巨鲸出货、流动性、开发者跑路) |
|
||||
| [workflow-early-project-screening.md](docs/workflow-early-project-screening.md) | 筛选新发 Launchpad Token,识别聪明钱早入信号 |
|
||||
| [workflow-daily-brief.md](docs/workflow-daily-brief.md) | 每日市场简报:热门趋势 + 聪明钱动向 + 早期机会 + 风险扫描 |
|
||||
| [workflow-market-opportunities.md](docs/workflow-market-opportunities.md) | 从趋势数据中发现交易机会 |
|
||||
| [workflow-token-due-diligence.md](docs/workflow-token-due-diligence.md) | 4 步 Token 尽调清单 |
|
||||
|
||||
## 8. CLI 参考
|
||||
|
||||
完整参数说明:[docs/cli-usage.md](docs/cli-usage.md)。所有命令均支持 `--raw` 输出单行 JSON(方便 `jq` 等工具处理)。
|
||||
|
||||
### Token
|
||||
|
||||
```bash
|
||||
npx gmgn-cli token info --chain sol --address <addr>
|
||||
# 基本信息 + 实时价格
|
||||
gmgn-cli token info --chain sol --address <addr>
|
||||
|
||||
# 安全指标(蜜罐、税率、集中度、rug 风险)
|
||||
gmgn-cli token security --chain sol --address <addr>
|
||||
|
||||
# 流动池信息(DEX、储备量、深度)
|
||||
gmgn-cli token pool --chain sol --address <addr>
|
||||
|
||||
# 持仓大户(按持仓比例排序)
|
||||
gmgn-cli token holders --chain sol --address <addr> --limit 50
|
||||
|
||||
# 聪明钱持仓大户(按买入量排序)
|
||||
gmgn-cli token holders --chain sol --address <addr> \
|
||||
--tag smart_degen --order-by buy_volume_cur --limit 20
|
||||
|
||||
# 交易大户(KOL,按已实现盈利排序)
|
||||
gmgn-cli token traders --chain sol --address <addr> \
|
||||
--tag renowned --order-by profit --limit 20
|
||||
```
|
||||
|
||||
### Market
|
||||
|
||||
```bash
|
||||
npx gmgn-cli market trending \
|
||||
# K 线数据(1h 周期,最近 24 小时)
|
||||
# macOS:
|
||||
gmgn-cli market kline \
|
||||
--chain sol --address <addr> \
|
||||
--resolution 1h \
|
||||
--from $(date -v-24H +%s) --to $(date +%s)
|
||||
# Linux: $(date -d '24 hours ago' +%s)
|
||||
|
||||
# 热门代币榜(SOL,1h,按交易量排序)
|
||||
gmgn-cli market trending \
|
||||
--chain sol \
|
||||
--interval 1h \
|
||||
--order-by volume --limit 20 \
|
||||
--filter not_risk --filter not_honeypot
|
||||
|
||||
# 战壕新币列表
|
||||
gmgn-cli market trenches \
|
||||
--chain sol \
|
||||
--type new_creation --type near_completion --type completed \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform letsbonk \
|
||||
--limit 80
|
||||
|
||||
# 服务端过滤:安全预设 + 要求有聪明钱 + 按聪明钱数量排序
|
||||
gmgn-cli market trenches \
|
||||
--chain sol --type new_creation \
|
||||
--filter-preset safe --min-smart-degen-count 1 --sort-by smart_degen_count
|
||||
```
|
||||
|
||||
### Portfolio
|
||||
|
||||
```bash
|
||||
npx gmgn-cli portfolio holdings --chain sol --wallet <addr>
|
||||
# 钱包持仓
|
||||
gmgn-cli portfolio holdings --chain sol --wallet <addr>
|
||||
|
||||
# 交易记录
|
||||
gmgn-cli portfolio activity --chain sol --wallet <addr>
|
||||
|
||||
# 交易统计(支持多钱包)
|
||||
gmgn-cli portfolio stats --chain sol --wallet <addr1> --wallet <addr2>
|
||||
|
||||
# API Key 绑定的钱包及主币余额
|
||||
gmgn-cli portfolio info
|
||||
|
||||
# 单个 token 余额
|
||||
gmgn-cli portfolio token-balance --chain sol --wallet <addr> --token <token_addr>
|
||||
|
||||
# 查询开发者钱包创建的代币列表
|
||||
gmgn-cli portfolio created-tokens --chain sol --wallet <addr>
|
||||
```
|
||||
|
||||
### Swap(需要私钥)
|
||||
### Track
|
||||
|
||||
```bash
|
||||
# 提交兑换
|
||||
npx gmgn-cli swap \
|
||||
# 追踪关注钱包的交易动态
|
||||
gmgn-cli track follow-wallet --chain sol
|
||||
gmgn-cli track follow-wallet --chain sol --limit 20 --min-amount-usd 1000
|
||||
|
||||
# KOL 交易动态
|
||||
gmgn-cli track kol --limit 100 --raw
|
||||
gmgn-cli track kol --chain sol --side buy --limit 50 --raw
|
||||
|
||||
# 聪明钱交易动态
|
||||
gmgn-cli track smartmoney --limit 100 --raw
|
||||
gmgn-cli track smartmoney --chain sol --side sell --limit 50 --raw
|
||||
```
|
||||
|
||||
### Swap / Quote / Query
|
||||
|
||||
```bash
|
||||
# 提交兑换(固定滑点)
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
@@ -205,32 +554,223 @@ npx gmgn-cli swap \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# 查询订单
|
||||
npx gmgn-cli order get --chain sol --order-id <order-id>
|
||||
# 提交兑换(自动滑点)
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount 1000000 \
|
||||
--auto-slippage
|
||||
|
||||
# 按持仓比例卖出(例:卖出 50%)
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <token-addr> \
|
||||
--output-token <usdc-addr> \
|
||||
--percent 50 \
|
||||
--auto-slippage
|
||||
|
||||
# 获取报价(不提交交易)
|
||||
gmgn-cli order quote \
|
||||
--chain sol \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--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>
|
||||
|
||||
# 查询实时 Gas 价格(支持全链)
|
||||
gmgn-cli gas-price --chain sol
|
||||
gmgn-cli gas-price --chain eth
|
||||
gmgn-cli gas-price --chain bsc
|
||||
gmgn-cli gas-price --chain base
|
||||
|
||||
# 多钱包并发 Swap
|
||||
gmgn-cli multi-swap \
|
||||
--chain sol \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--input-amount '{"<addr1>":"1000000","<addr2>":"2000000"}' \
|
||||
--slippage 0.01
|
||||
```
|
||||
|
||||
> `order quote` 在 `sol` / `bsc` / `base` / `eth` 上都走关键鉴权,必须配置 `GMGN_PRIVATE_KEY`。
|
||||
|
||||
### ETH Gas 档位控制(仅限 ETH)
|
||||
|
||||
```bash
|
||||
# 按档位设置 Gas(low / average / high),替代手动填写 gwei
|
||||
gmgn-cli swap \
|
||||
--chain eth \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount <amount> \
|
||||
--slippage 0.01 \
|
||||
--gas-level high
|
||||
|
||||
# 策略单(condition-orders)由 GMGN 自动选择最优 Gas Fee
|
||||
gmgn-cli swap \
|
||||
--chain eth \
|
||||
--from <wallet-address> \
|
||||
--input-token <input-token-addr> \
|
||||
--output-token <output-token-addr> \
|
||||
--amount <amount> \
|
||||
--slippage 0.01 \
|
||||
--condition-orders '[...]' \
|
||||
--auto-fee
|
||||
```
|
||||
|
||||
> `--gas-level` 和 `--auto-fee` 仅支持 ETH 链。`--auto-fee` 仅在携带 `--condition-orders` 时生效。
|
||||
> 其他链(SOL / BSC / BASE)请先用 `gas-price` 查询当前 Gas,再通过 `--gas-price` 手动传入。
|
||||
|
||||
### 带止盈止损的 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. 支持的链
|
||||
|
||||
| 接口类型 | 支持的链 | 链原生货币 |
|
||||
|----------|----------|-----------|
|
||||
| token / market / portfolio | `sol` / `bsc` / `base` | — |
|
||||
| swap / order | `sol` / `bsc` / `base` | sol: SOL、USDC · bsc: BNB、USDC · base: ETH、USDC |
|
||||
| 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` | — |
|
||||
|
||||
---
|
||||
|
||||
## 输出格式
|
||||
## 10. 升级 Skills 和 CLI
|
||||
|
||||
默认输出格式化 JSON。使用 `--raw` 输出单行 JSON(方便 jq 等工具处理):
|
||||
将 `gmgn-cli` 和 Skills 升级到最新版本:
|
||||
|
||||
**方式一:通过 AI Agent(推荐)**
|
||||
|
||||
发送给你的 AI Agent:
|
||||
|
||||
```
|
||||
运行以下两条命令,更新 gmgn-cli 和 Skills 文档:
|
||||
1. npm install -g gmgn-cli
|
||||
2. npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
**方式二:通过 CLI**
|
||||
|
||||
```bash
|
||||
npx gmgn-cli token info --chain sol --address <addr> --raw | jq '.price'
|
||||
# 升级 gmgn-cli
|
||||
npm install -g gmgn-cli
|
||||
|
||||
# 升级 Skills
|
||||
npx skills add GMGNAI/gmgn-skills
|
||||
```
|
||||
|
||||
**查看当前版本号**
|
||||
|
||||
```bash
|
||||
gmgn-cli --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 安全与免责
|
||||
## 11. 安全与免责(使用前必读)
|
||||
|
||||
本工具可供 AI Agent 调用以自动执行链上交易,存在模型幻觉、执行不可控、提示词注入等固有风险。AI Agent 在获得授权后,将以您绑定的钱包地址提交真实的链上交易,**交易一经上链即不可撤销**,可能导致资金损失,请您谨慎使用。
|
||||
|
||||
**关于 `GMGN_PRIVATE_KEY`**
|
||||
|
||||
@@ -241,8 +781,10 @@ npx gmgn-cli token info --chain sol --address <addr> --raw | jq '.price'
|
||||
- 限制配置文件权限:`chmod 600 ~/.config/gmgn/.env`
|
||||
- 不要将 `.env` 文件提交到版本控制系统,请将其加入 `.gitignore`
|
||||
- 不要在日志、截图或聊天中泄露 `GMGN_API_KEY` 或 `GMGN_PRIVATE_KEY`
|
||||
- 使用固定版本安装(`npm install -g gmgn-cli@1.0.1`),而非 `npx gmgn-cli`,以避免在持有凭证的环境中执行未预期的包更新
|
||||
- 每次 swap 前,仔细核对 AI 呈现的交易摘要(链、钱包、代币地址、金额),确认无误后再回复确认
|
||||
- 建议先用小额资金验证配置后再进行大额操作
|
||||
- 请使用最新的 gmgn-cli(`npm install -g gmgn-cli`),查看当前版本请使用 `gmgn-cli --version`
|
||||
|
||||
**免责声明**
|
||||
|
||||
使用本工具及根据其输出做出的任何财务决策,风险由用户自行承担。GMGN 对因凭证管理不当导致的任何交易损失、错误或未授权访问不承担责任。
|
||||
使用本工具及根据其输出做出的任何财务决策,风险由用户自行承担。GMGN 对因模型幻觉、提示词注入、凭证管理不当或用户操作失误导致的任何交易损失、错误或未授权访问不承担责任。使用本工具即视为您已充分知悉上述风险并自愿承担全部责任。
|
||||
|
||||
@@ -255,6 +255,197 @@ npx gmgn-cli portfolio token-balance \
|
||||
|
||||
---
|
||||
|
||||
## portfolio created-tokens
|
||||
|
||||
Query tokens created by a developer wallet.
|
||||
|
||||
```bash
|
||||
npx gmgn-cli portfolio created-tokens \
|
||||
--chain <chain> \
|
||||
--wallet <wallet_address> \
|
||||
[--order-by <field>] \
|
||||
[--direction asc|desc] \
|
||||
[--migrate-state <state>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--wallet` | Yes | Developer wallet address |
|
||||
| `--order-by` | No | Sort field: `market_cap` / `token_ath_mc` |
|
||||
| `--direction` | No | Sort direction: `asc` / `desc` |
|
||||
| `--migrate-state` | No | Filter: `migrated` / `non_migrated` |
|
||||
|
||||
---
|
||||
|
||||
## market trenches
|
||||
|
||||
Query Trenches token lists (new creation, near completion, completed).
|
||||
|
||||
```bash
|
||||
npx gmgn-cli market trenches --chain <chain> [--type <type...>] [--launchpad-platform <platform...>] [--limit <n>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--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) |
|
||||
|
||||
**Response:** `data.new_creation`, `data.pump`, `data.completed` — each is an array of `RankItem` (same structure as `market trending` rank items). **Note: `data.pump` in the response corresponds to `--type near_completion` in the request. The API always returns this category under the key `pump`, not `near_completion`.**
|
||||
|
||||
---
|
||||
|
||||
## market signal
|
||||
|
||||
Query token signals — price spikes, smart money buys, large buys, Dex ads, CTO events, and more. Returns a list of `TokenSignalItem` sorted by `trigger_at` descending (most recent first). **Maximum 50 results per group.**
|
||||
|
||||
```bash
|
||||
# Single group (individual flags):
|
||||
gmgn-cli market signal --chain sol [--signal-type <n>...] [--mc-min <usd>] [--mc-max <usd>] [--raw]
|
||||
|
||||
# Multi-group override (JSON array):
|
||||
gmgn-cli market signal --chain sol --groups '<json_array>' [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` |
|
||||
| `--signal-type` | No | Signal type(s), repeatable (1–18, default: all). See Signal Types below. |
|
||||
| `--mc-min` | No | Min market cap at trigger time (USD) |
|
||||
| `--mc-max` | No | Max market cap at trigger time (USD) |
|
||||
| `--trigger-mc-min` | No | Min market cap at signal trigger moment (USD) |
|
||||
| `--trigger-mc-max` | No | Max market cap at signal trigger moment (USD) |
|
||||
| `--total-fee-min` | No | Min total fees paid (USD) |
|
||||
| `--total-fee-max` | No | Max total fees paid (USD) |
|
||||
| `--min-create-or-open-ts` | No | Min token creation or open timestamp (Unix seconds string) |
|
||||
| `--max-create-or-open-ts` | No | Max token creation or open timestamp (Unix seconds string) |
|
||||
| `--groups` | No | Multi-group JSON array — overrides all individual flags when provided |
|
||||
|
||||
**Signal Types:**
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 1 | SignalType1 | General signal (K-line price spike) |
|
||||
| 2 | SignalTypeDexAd | Dex ad placement |
|
||||
| 3 | SignalTypeDexUpdateLink | Dex social link updated |
|
||||
| 4 | SignalTypeDexTrendingBar | Dex trending bar |
|
||||
| 5 | SignalTypeDexBoost | Dex Boost |
|
||||
| 6 | SignalTypePriceUp | Price spike |
|
||||
| 7 | SignalTypePriceATH | All-time high price |
|
||||
| 8 | SignalTypeMcpKeyLevel | Market cap key level |
|
||||
| 9 | SignalTypeLive | Live stream |
|
||||
| 10 | SignalTypeBundlerSell | Bundler sell |
|
||||
| 11 | SignalTypeCto | Community takeover (CTO) |
|
||||
| 12 | SignalTypeSmartDegenBuy | Smart money buy |
|
||||
| 13 | SignalTypePlatformCall | Platform call |
|
||||
| 14 | SignalTypeLargeAmountBuy | Large amount buy |
|
||||
| 15 | SignalTypeMultiBuy | Multiple buys |
|
||||
| 16 | SignalTypeMultiLargeBuy | Multiple large buys |
|
||||
| 17 | SignalTypeBagsClaims | Bags Claim |
|
||||
| 18 | SignalTypePumpClaims | Pump Claim |
|
||||
|
||||
---
|
||||
|
||||
## portfolio follow-wallet
|
||||
|
||||
Query follow-wallet trade records. Returns trades from wallets you personally follow on the GMGN platform. The follow list is resolved automatically from the GMGN user account bound to the API Key — `--wallet` is optional. Signed auth (API Key + private key signature).
|
||||
|
||||
```bash
|
||||
gmgn-cli track follow-wallet \
|
||||
--chain <chain> \
|
||||
[--wallet <wallet_address>] \
|
||||
[--limit <n>] \
|
||||
[--side <side>] \
|
||||
[--filter <tag>] \
|
||||
[--min-amount-usd <n>] \
|
||||
[--max-amount-usd <n>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--wallet` | No | Wallet address (optional; follow list resolved from API Key's bound user account) |
|
||||
| `--limit` | No | Page size (1–100, default 10) |
|
||||
| `--side` | No | Trade direction: `buy` / `sell` |
|
||||
| `--filter` | No | Filter conditions (repeatable) |
|
||||
| `--min-amount-usd` | No | Minimum trade amount (USD) |
|
||||
| `--max-amount-usd` | No | Maximum trade amount (USD) |
|
||||
|
||||
---
|
||||
|
||||
## portfolio kol
|
||||
|
||||
Query KOL trade records.
|
||||
|
||||
```bash
|
||||
gmgn-cli track kol [--chain <chain>] [--limit <n>] [--side <side>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | No | `sol` / `bsc` / `base` (default `sol`) |
|
||||
| `--limit` | No | Page size (1–200, default 100) |
|
||||
| `--side` | No | Filter by trade direction: `buy` / `sell` (client-side filter) |
|
||||
|
||||
---
|
||||
|
||||
## portfolio smartmoney
|
||||
|
||||
Query Smart Money trade records.
|
||||
|
||||
```bash
|
||||
gmgn-cli track smartmoney [--chain <chain>] [--limit <n>] [--side <side>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | No | `sol` / `bsc` / `base` (default `sol`) |
|
||||
| `--limit` | No | Page size (1–200, default 100) |
|
||||
| `--side` | No | Filter by trade direction: `buy` / `sell` (client-side filter) |
|
||||
|
||||
---
|
||||
|
||||
## order quote
|
||||
|
||||
Get a swap quote without submitting a transaction. All supported quote chains use signed auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
npx gmgn-cli order quote \
|
||||
--chain <chain> \
|
||||
--from <wallet_address> \
|
||||
--input-token <input_token_address> \
|
||||
--output-token <output_token_address> \
|
||||
--amount <input_amount> \
|
||||
--slippage <n> \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--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 |
|
||||
| `--amount` | Yes | Input amount (smallest unit) |
|
||||
| `--slippage` | Yes | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `input_token` | string | Input token contract address |
|
||||
| `output_token` | string | Output token contract address |
|
||||
| `input_amount` | string | Input amount (smallest unit) |
|
||||
| `output_amount` | string | Expected output amount (smallest unit) |
|
||||
| `min_output_amount` | string | Minimum output after slippage |
|
||||
| `slippage` | number | Actual slippage percentage |
|
||||
|
||||
---
|
||||
|
||||
## swap
|
||||
|
||||
Submit a token swap. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
@@ -267,34 +458,48 @@ npx gmgn-cli swap \
|
||||
--output-token <output_token_address> \
|
||||
[--amount <input_amount> | --percent <pct>] \
|
||||
[--slippage <n>] \
|
||||
[--auto-slippage] \
|
||||
[--min-output <amount>] \
|
||||
[--anti-mev] \
|
||||
[--priority-fee <sol>] \
|
||||
[--tip-fee <amount>] \
|
||||
[--max-auto-fee <amount>] \
|
||||
[--gas-price <gwei>] \
|
||||
[--max-fee-per-gas <amount>] \
|
||||
[--max-priority-fee-per-gas <amount>] \
|
||||
[--condition-orders <json>] \
|
||||
[--sell-ratio-type <buy_amount|hold_amount>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--from` | Yes | Wallet address (must match the wallet bound to the API Key) |
|
||||
| `--input-token` | Yes | Input token contract address |
|
||||
| `--output-token` | Yes | Output token contract address |
|
||||
| `--amount` | No* | Input raw amount in minimal unit (e.g., lamports for SOL); required unless `--percent` is used |
|
||||
| `--percent` | No* | Input amount as a percentage, e.g. `50` = 50%; required unless `--amount` is used; only valid when input token is not a currency (not SOL/BNB/ETH/USDC) |
|
||||
| `--slippage` | No | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--min-output` | No | Minimum output amount (raw amount) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection (default true) |
|
||||
| `--priority-fee` | No | Priority fee in SOL (≥ 0.00001 SOL, SOL only) |
|
||||
| `--tip-fee` | No | Tip fee (SOL ≥ 0.00001 SOL / BSC ≥ 0.000001 BNB) |
|
||||
| `--max-auto-fee` | No | Max automatic fee cap |
|
||||
| `--gas-price` | No | Gas price in gwei (BSC ≥ 0.05 gwei / BASE/ETH ≥ 0.01 gwei) |
|
||||
| `--max-fee-per-gas` | No | EIP-1559 max fee per gas (Base/ETH only) |
|
||||
| `--max-priority-fee-per-gas` | No | EIP-1559 max priority fee per gas (Base/ETH only) |
|
||||
| Option | Required | Chain | Description |
|
||||
|--------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
| `--amount` | No* | all | Input raw amount in minimal unit (e.g., lamports for SOL); required unless `--percent` is used |
|
||||
| `--percent` | No* | all | Input amount as a percentage, e.g. `50` = 50%; required unless `--amount` is used; only valid when input token is not a currency (not SOL/BNB/ETH/USDC) |
|
||||
| `--slippage` | No | all | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage |
|
||||
| `--min-output` | No | all | Minimum output amount (raw amount) |
|
||||
| `--anti-mev` | No | all | Enable anti-MEV protection (default true) |
|
||||
| `--priority-fee` | No | `sol` | Priority fee in SOL (≥ 0.00001) |
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB) |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas |
|
||||
| `--condition-orders` | No | all | JSON array of take-profit/stop-loss conditions attached after a successful swap (see example below) |
|
||||
| `--sell-ratio-type` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount` |
|
||||
|
||||
**`--condition-orders` example** (100% sell at 2× price, 100% sell at 50% price):
|
||||
|
||||
```json
|
||||
[{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"100"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]
|
||||
```
|
||||
|
||||
> Strategy creation is **best-effort**: if the swap succeeds but strategy creation fails, the swap result is still returned (with `strategy_order_id` absent). Only `order_type`, `side`, `price_scale`, and `sell_ratio` are accepted per condition — extra fields cause a 400 error.
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
@@ -313,6 +518,68 @@ npx gmgn-cli swap \
|
||||
| `output_token` | string | Output token contract address |
|
||||
| `filled_input_amount` | string | Actual input consumed (smallest unit); empty if not filled |
|
||||
| `filled_output_amount` | string | Actual output received (smallest unit); empty if not filled |
|
||||
| `strategy_order_id` | string | Strategy order ID; only present when `--condition-orders` was passed and strategy creation succeeded |
|
||||
|
||||
---
|
||||
|
||||
## multi-swap
|
||||
|
||||
Submit token swaps across multiple wallets concurrently. Each wallet executes independently. Up to 100 wallets per request, all must be bound to the API Key. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli multi-swap \
|
||||
--chain <chain> \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token <input_token_address> \
|
||||
--output-token <output_token_address> \
|
||||
[--input-amount <json>] \
|
||||
[--input-amount-bps <json>] \
|
||||
[--output-amount <json>] \
|
||||
[--slippage <n>] \
|
||||
[--auto-slippage] \
|
||||
[--anti-mev] \
|
||||
[--priority-fee <sol>] \
|
||||
[--tip-fee <amount>] \
|
||||
[--gas-price <gwei>] \
|
||||
[--max-fee-per-gas <amount>] \
|
||||
[--max-priority-fee-per-gas <amount>] \
|
||||
[--condition-orders <json>] \
|
||||
[--sell-ratio-type <buy_amount|hold_amount>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Chain | Description |
|
||||
|--------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
| `--input-amount` | No* | all | JSON map `{"addr":"amount"}` in smallest unit; one of the three amount fields is required |
|
||||
| `--input-amount-bps` | No* | all | JSON map `{"addr":"bps"}` where 5000 = 50%; only valid when input token is not a currency |
|
||||
| `--output-amount` | No* | all | JSON map `{"addr":"amount"}` target output in smallest unit |
|
||||
| `--slippage` | No | all | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage |
|
||||
| `--anti-mev` | No | all | Enable anti-MEV protection |
|
||||
| `--priority-fee` | No | `sol` | Priority fee in SOL (≥ 0.00001) |
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB) |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas |
|
||||
| `--condition-orders` | No | all | JSON array of take-profit/stop-loss conditions, attached to each successful wallet's swap (best-effort) |
|
||||
| `--sell-ratio-type` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount` |
|
||||
|
||||
**Response fields (data):** Array of per-wallet results:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `account` | string | Wallet address |
|
||||
| `success` | bool | Whether this wallet's swap succeeded |
|
||||
| `error` | string | Error message on failure |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `result` | object | OrderResponse on success (same fields as `swap` response) |
|
||||
| `result.strategy_order_id` | string | Strategy order ID; only present when `--condition-orders` passed and strategy creation succeeded |
|
||||
|
||||
---
|
||||
|
||||
@@ -331,6 +598,241 @@ npx gmgn-cli order get --chain <chain> --order-id <order_id> [--raw]
|
||||
|
||||
**Response fields (data):** Same structure as the `swap` response above.
|
||||
|
||||
## order strategy create
|
||||
|
||||
Create a limit/strategy order. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli order strategy create \
|
||||
--chain <chain> \
|
||||
--from <wallet_address> \
|
||||
--base-token <base_token_address> \
|
||||
--quote-token <quote_token_address> \
|
||||
--order-type <limit_order|smart_trade> \
|
||||
--sub-order-type <buy_low|buy_high|stop_loss|take_profit|mix_trade> \
|
||||
[--check-price <price>] \
|
||||
[--open-price <price>] \
|
||||
[--amount-in <amount> | --amount-in-percent <pct>] \
|
||||
[--slippage <n> | --auto-slippage] \
|
||||
[--limit-price-mode <exact|slippage>] \
|
||||
[--expire-in <seconds>] \
|
||||
[--sell-ratio-type <buy_amount|hold_amount>] \
|
||||
[--quote-investment <amount>] \
|
||||
[--condition-orders <json>] \
|
||||
[--priority-fee <sol>] \
|
||||
[--tip-fee <amount>] \
|
||||
[--gas-price <gwei>] \
|
||||
[--anti-mev] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--base-token` | Yes | Base token contract address |
|
||||
| `--quote-token` | Yes | Quote token contract address |
|
||||
| `--order-type` | Yes | Order type: `limit_order` / `smart_trade` |
|
||||
| `--sub-order-type` | Yes | `limit_order`: `buy_low` / `buy_high` / `stop_loss` / `take_profit`; `smart_trade` with condition_orders: `mix_trade` |
|
||||
| `--check-price` | No* | Trigger check price — required for `limit_order`; omit for `smart_trade` (trigger is in the `buy_low` condition order) |
|
||||
| `--open-price` | No | Open price of the position |
|
||||
| `--amount-in` | No* | Input amount (smallest unit); required unless `--amount-in-percent` is used |
|
||||
| `--amount-in-percent` | No* | Input as percentage (e.g. `50` = 50%); required unless `--amount-in` is used |
|
||||
| `--limit-price-mode` | No | `exact` / `slippage` (default: `slippage`) |
|
||||
| `--expire-in` | No | Order expiry in seconds |
|
||||
| `--sell-ratio-type` | No | `buy_amount` (default) / `hold_amount` |
|
||||
| `--quote-investment` | No | Quote token investment amount (`smart_trade`) |
|
||||
| `--condition-orders` | No | JSON array of condition sub-orders for `smart_trade`. Must include one `buy_low` entry (with `check_price` lower than `open_price`) plus at least one TP/SL entry |
|
||||
| `--slippage` | No | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--auto-slippage` | No | Enable automatic slippage |
|
||||
| `--priority-fee` | No | Priority fee in SOL (**required for SOL chain**) |
|
||||
| `--tip-fee` | No | Tip fee (**required for SOL chain**) |
|
||||
| `--gas-price` | No | Gas price in gwei (**required for BSC**; ≥ 0.05 / BASE/ETH ≥ 0.01) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection |
|
||||
|
||||
> **Chain-specific fee requirements:**
|
||||
> - **SOL:** `--priority-fee` and `--tip-fee` are both **required** (returns 400 if missing)
|
||||
> - **BSC:** `--gas-price` is **required** (returns 400 if missing)
|
||||
> - **ETH/BASE:** no required fee fields
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `order_id` | string | Created strategy order ID |
|
||||
| `is_update` | bool | `true` if an existing order was updated |
|
||||
|
||||
---
|
||||
|
||||
## order strategy list
|
||||
|
||||
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]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--type` | No | `open` (default) / `history` |
|
||||
| `--from` | No | Filter by wallet address |
|
||||
| `--group-tag` | No | Filter by group: `LimitOrder` / `STMix` |
|
||||
| `--base-token` | No | Filter by token address |
|
||||
| `--page-token` | No | Pagination cursor from previous response |
|
||||
| `--limit` | No | Results per page |
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `next_page_token` | string | Cursor for next page; empty when no more data |
|
||||
| `total` | int | Total count (only when `--type open`) |
|
||||
| `list` | array | Strategy order list |
|
||||
|
||||
---
|
||||
|
||||
## order strategy cancel
|
||||
|
||||
Cancel a strategy order. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli order strategy cancel --chain <chain> --from <wallet_address> --order-id <id> [--order-type <type>] [--close-sell-model <model>] [--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--order-id` | Yes | Order ID to cancel |
|
||||
| `--order-type` | No | Order type: `limit_order` / `smart_trade` |
|
||||
| `--close-sell-model` | No | Sell model when closing |
|
||||
|
||||
---
|
||||
|
||||
## cooking stats
|
||||
|
||||
Get token creation statistics grouped by launchpad.
|
||||
|
||||
```bash
|
||||
gmgn-cli cooking stats [--raw]
|
||||
```
|
||||
|
||||
No additional options required. Returns an array of `{ launchpad, token_count }` entries.
|
||||
|
||||
---
|
||||
|
||||
## cooking create
|
||||
|
||||
Create a token on a launchpad platform. **Requires `GMGN_PRIVATE_KEY` configured in `.env`.**
|
||||
|
||||
```bash
|
||||
gmgn-cli cooking create \
|
||||
--chain <chain> \
|
||||
--dex <dex> \
|
||||
--from <wallet_address> \
|
||||
--name <name> \
|
||||
--symbol <symbol> \
|
||||
--buy-amt <amount> \
|
||||
[--image <base64> | --image-url <url>] \
|
||||
[--slippage <n> | --auto-slippage] \
|
||||
[--website <url>] [--twitter <url>] [--telegram <url>] \
|
||||
[--fee <amount>] [--priority-fee <sol>] [--tip-fee <amount>] [--gas-price <amount>] \
|
||||
[--max-fee-per-gas <amount>] [--max-priority-fee-per-gas <amount>] \
|
||||
[--anti-mev] [--anti-mev-mode <off|normal|secure>] \
|
||||
[--raised-token <symbol>] \
|
||||
[--dev-wallet-bps <n>] [--dev-gas <amount>] [--dev-priority <amount>] [--dev-tip <amount>] [--dev-max-fee-per-gas <amount>] \
|
||||
[--approve-vision <v1|v2>] [--source <source>] \
|
||||
[--is-mayhem] [--is-cashback] [--is-buy-back] \
|
||||
[--pump-fee-share-list <json>] \
|
||||
[--flap-rate-conf <json>] \
|
||||
[--fourmeme-rate-conf <json>] \
|
||||
[--bags-fee-share-list <json>] \
|
||||
[--bonk-model <model>] \
|
||||
[--buy-wallets <json>] [--snip-buy-wallets <json>] [--interval-seconds <n>] \
|
||||
[--buy-trade-config <json>] [--sell-trade-config <json>] [--sell-configs <json>] \
|
||||
[--raw]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--dex` | Yes | Launchpad per chain: `pump` / `bonk` / `bags` (sol), `fourmeme` / `flap` (bsc), `klik` / `clanker` (base) |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--name` | Yes | Token name |
|
||||
| `--symbol` | Yes | Token symbol |
|
||||
| `--buy-amt` | Yes | Initial buy amount in native token (e.g. `0.01` SOL) |
|
||||
| `--image` | No* | Token logo as base64-encoded data (max 2MB decoded); required unless `--image-url` is used |
|
||||
| `--image-url` | No* | Token logo URL; required unless `--image` is used |
|
||||
| `--slippage` | No* | Slippage tolerance, e.g. `0.01` = 1%; required unless `--auto-slippage` is used |
|
||||
| `--auto-slippage` | No* | Enable automatic slippage; required unless `--slippage` is used |
|
||||
| `--website` | No | Website URL |
|
||||
| `--twitter` | No | Twitter link |
|
||||
| `--telegram` | No | Telegram link |
|
||||
| `--fee` | No | Base gas / fee |
|
||||
| `--priority-fee` | No | Priority fee in SOL (**SOL only**, ≥ 0.0001 SOL) |
|
||||
| `--tip-fee` | No | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB; ignored on BASE) |
|
||||
| `--gas-price` | No | Gas price in wei (**EVM only**) |
|
||||
| `--max-fee-per-gas` | No | Max fee per gas in wei (**EVM only**) |
|
||||
| `--max-priority-fee-per-gas` | No | Max priority fee per gas in wei (**EVM only**) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection (**SOL only**) |
|
||||
| `--anti-mev-mode` | No | Anti-MEV mode: `off` / `normal` / `secure` (**SOL only**) |
|
||||
| `--raised-token` | No | Raise token symbol: `pump`→`USDC`; `bonk`→`USD1`; `fourmeme`→`USDT`/`USD1`; omit for native |
|
||||
| `--dev-wallet-bps` | No | Dev wallet fee share in basis points (100 = 1%) |
|
||||
| `--dev-gas` | No | Dev gas amount |
|
||||
| `--dev-priority` | No | Dev priority fee |
|
||||
| `--dev-tip` | No | Dev tip fee |
|
||||
| `--dev-max-fee-per-gas` | No | Dev tx feeCap in wei (**EVM EIP-1559**) |
|
||||
| `--approve-vision` | No | Approve vision version: `v1` / `v2` (default: `v2`) |
|
||||
| `--source` | No | Traffic source identifier |
|
||||
| `--is-mayhem` | No | Enable Mayhem mode (**Pump.fun only**) |
|
||||
| `--is-cashback` | No | Enable Cashback (**Pump.fun only**) |
|
||||
| `--is-buy-back` | No | Enable Agent Auto Buyback (**Pump.fun only**) |
|
||||
| `--pump-fee-share-list` | No | Fee share list as JSON array: `[{"provider":"twitter","username":"<handle>","basic_points":<n>}]` (**Pump.fun only**) |
|
||||
| `--flap-rate-conf` | No | Rate config as JSON object (**Flap only**) |
|
||||
| `--fourmeme-rate-conf` | No | Rate config as JSON object (**FourMeme only**) |
|
||||
| `--bags-fee-share-list` | No | Fee share list as JSON array: `[{"provider":"twitter","username":"<handle>","basic_points":<n>}]` (**BAGS only**) |
|
||||
| `--bonk-model` | No | Bonk model identifier (**bonk DEX only**) |
|
||||
| `--buy-wallets` | No | Multi-wallet buy config as JSON array: `[{"from_address":"<addr>","buy_amt":"<n>"}]` |
|
||||
| `--snip-buy-wallets` | No | Snipe-buy wallet config as JSON array: `[{"from_address":"<addr>","buy_amt":"<n>"}]` |
|
||||
| `--interval-seconds` | No | Interval between multi-wallet buys in seconds |
|
||||
| `--buy-trade-config` | No | Buy-side trade config for CondMarket orders as JSON (TradeParam) |
|
||||
| `--sell-trade-config` | No | Sell-side trade config for auto-sell / pending_sell as JSON (TradeParam) |
|
||||
| `--sell-configs` | No | Auto-sell strategy list as JSON array (CookingSellConfig[]): `[{"sell_type":"delay_sell","delay_sec":<n>,"sell_ratio":"0.5","wallet_addresses":["<addr>"]}]` |
|
||||
|
||||
**Response fields (data):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `status` | string | `pending` / `confirmed` / `failed` |
|
||||
| `hash` | string | Transaction hash |
|
||||
| `order_id` | string | Order ID for polling |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `error_status` | string | Error description on failure |
|
||||
|
||||
Token creation is asynchronous. Poll `order get` with the returned `order_id` if `status` is `pending`.
|
||||
|
||||
---
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All business routes are protected by GMGN's leaky-bucket limiter. Current production behavior is:
|
||||
|
||||
- `rate=10`, `capacity=10`
|
||||
- every limited `429` response includes `X-RateLimit-Reset`
|
||||
- `X-RateLimit-Reset` is a Unix timestamp in seconds, representing when the current cooldown is expected to end
|
||||
|
||||
CLI behavior:
|
||||
|
||||
- For read-only commands, `gmgn-cli` may wait until `X-RateLimit-Reset` and retry once automatically when the remaining cooldown is short.
|
||||
- For longer cooldowns, or for `swap`, the CLI stops and prints the exact reset time instead of repeatedly sending requests.
|
||||
- The auto-retry threshold defaults to `5000ms` and can be overridden with `GMGN_RATE_LIMIT_AUTO_RETRY_MAX_WAIT_MS=<milliseconds>`.
|
||||
|
||||
Important notes:
|
||||
|
||||
- `RATE_LIMIT_EXCEEDED` and `RATE_LIMIT_BANNED` are request-frequency limits. Continuing to send requests during the cooldown can extend the ban by 5 seconds each time, up to 5 minutes.
|
||||
- `ERROR_RATE_LIMIT_BLOCKED` is an error-count block on `POST /v1/trade/swap`. It is triggered by repeatedly hitting the same business error and should be treated as "fix the request first, then retry after reset".
|
||||
|
||||
---
|
||||
|
||||
## Error Codes
|
||||
@@ -343,11 +845,14 @@ npx gmgn-cli order get --chain <chain> --order-id <order_id> [--raw]
|
||||
| `AUTH_SIGNATURE_INVALID` | 401 | Signature verification failed |
|
||||
| `AUTH_TIMESTAMP_EXPIRED` | 401 | Timestamp is outside the valid window (±5s) |
|
||||
| `AUTH_CLIENT_ID_REPLAYED` | 401 | client_id replayed within 7s |
|
||||
| `AUTH_REPLAY_CHECK_UNAVAILABLE` | 503 | Anti-replay Redis unavailable (critical auth only) |
|
||||
| `AUTH_REPLAY_CHECK_UNAVAILABLE` | 503 | Anti-replay Redis unavailable (signed auth only) |
|
||||
| `RATE_LIMIT_EXCEEDED` | 429 | Rate limit exceeded |
|
||||
| `RATE_LIMIT_BANNED` | 429 | Temporarily banned due to repeated rate limit violations |
|
||||
| `ERROR_RATE_LIMIT_BLOCKED` | 429 | Temporarily blocked after repeated business errors on `swap` |
|
||||
| `TRADE_WALLET_MISMATCH` | 403 | `--from` address does not match the wallet bound to the API Key |
|
||||
| `CHAIN_NOT_SUPPORTED` | 400 | Unsupported chain |
|
||||
| `BAD_REQUEST` | 400 | Missing or invalid request parameters |
|
||||
| `INTERNAL_API_UNAVAILABLE` | 502 | Downstream market API unavailable |
|
||||
| `BROKER_UNAVAILABLE` | 502 | Downstream trade broker unavailable |
|
||||
| `TRADING_BOT_UNAVAILABLE` | 502 | Strategy order service temporarily unreachable |
|
||||
| `INTERNAL_ERROR` | 500 | Internal server error |
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
# Daily Market Brief — Workflow
|
||||
|
||||
Use this workflow to generate a structured morning/daily overview of market conditions, smart money activity, and risk signals — without needing a specific token or wallet in mind.
|
||||
|
||||
Use this workflow when:
|
||||
- "what's the market like today?"
|
||||
- "what is smart money buying today?"
|
||||
- "daily brief" / "give me a market overview"
|
||||
- "any opportunities worth watching?"
|
||||
- "any risks I should be aware of today?"
|
||||
- User wants a broad market situational awareness update
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Market Pulse (Trending Tokens)
|
||||
|
||||
Fetch trending tokens across multiple time windows to gauge market momentum:
|
||||
|
||||
```bash
|
||||
# Short-term heat (last 1h)
|
||||
gmgn-cli market trending --chain <chain> --interval 1h \
|
||||
--order-by volume --limit 20
|
||||
|
||||
# Medium-term momentum (last 6h)
|
||||
gmgn-cli market trending --chain <chain> --interval 6h \
|
||||
--order-by volume --limit 20
|
||||
```
|
||||
|
||||
From the results, assess:
|
||||
- **Market phase:** Are top tokens mostly meme/speculation (risk-on) or utility/DeFi (risk-off)?
|
||||
- **Breadth:** Are many tokens trending or just 1–2? Broad trends = healthier market.
|
||||
- **Smart money confirmation:** Do trending tokens have non-zero `smart_degen_count`? Trending without smart money = retail-driven pump.
|
||||
- **Volume quality:** Compare `volume` vs `swaps`. High volume with low swap count = whale activity. High swaps with low volume = retail noise.
|
||||
|
||||
Key signal summary from this step:
|
||||
```
|
||||
Market Phase: Risk-on (meme dominated) / Risk-off (utility) / Mixed
|
||||
Breadth: Broad ({N} tokens trending) / Narrow (1–2 tokens dominate)
|
||||
Smart Money: Confirmed in trending / Absent (retail-driven)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Smart Money Activity (What Are They Buying/Selling?)
|
||||
|
||||
```bash
|
||||
# What smart money traded in the last few hours
|
||||
gmgn-cli track smartmoney --chain <chain>
|
||||
|
||||
# What KOLs are doing
|
||||
gmgn-cli track kol --chain <chain>
|
||||
```
|
||||
|
||||
From the results:
|
||||
- Group trades by direction: **net buying** vs **net selling** per token
|
||||
- Identify tokens where **multiple** smart money wallets traded the same direction (cluster signal)
|
||||
- Note `price_change` on each trade — positive = their past entries aged well (good track record lately)
|
||||
- Flag any token appearing in both smart money AND trending data — double confirmation
|
||||
|
||||
Output for this step:
|
||||
```
|
||||
Smart Money Moves (last ~2h):
|
||||
Buying: TOKEN_A ({N} wallets), TOKEN_B ({N} wallets)
|
||||
Selling: TOKEN_C ({N} wallets)
|
||||
Notable: TOKEN_A appears in both trending AND smart money buys → strong signal
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — New Token Watch (Early Opportunities)
|
||||
|
||||
```bash
|
||||
# Tokens near graduation — imminent DEX listing
|
||||
gmgn-cli market trenches --chain <chain> --type near_completion
|
||||
|
||||
# Recently graduated tokens — fresh DEX liquidity
|
||||
gmgn-cli market trenches --chain <chain> --type completed
|
||||
```
|
||||
|
||||
Quick filter: from results, surface tokens with:
|
||||
- `smart_degen_count` ≥ 1
|
||||
- `rug_ratio` < 0.2
|
||||
- Non-zero `volume` and `swaps`
|
||||
|
||||
List up to 3 tokens that pass this quick filter as "early watch" candidates.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Risk Scan (Anything to Avoid Today?)
|
||||
|
||||
For any tokens the user currently holds (if known), or for the top tokens from steps 1–2:
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Flag immediately if any held/watched token shows:
|
||||
- `rug_ratio` increase (compare to prior knowledge)
|
||||
- `top_10_holder_rate` > 0.5
|
||||
- `creator_token_status` = `creator_hold` (dev still in)
|
||||
- `is_wash_trading` = `true`
|
||||
|
||||
If no specific tokens to check, skip this step and note it in the brief.
|
||||
|
||||
---
|
||||
|
||||
## Daily Brief Output
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════
|
||||
DAILY MARKET BRIEF — {chain} — {date}
|
||||
═══════════════════════════════════════════
|
||||
|
||||
📊 MARKET PULSE
|
||||
Phase: Risk-on / Risk-off / Mixed
|
||||
Breadth: {N} tokens trending (broad/narrow)
|
||||
Top movers: TOKEN_A (+X%), TOKEN_B (+X%), TOKEN_C (+X%)
|
||||
Smart money: Present in trending ✅ / Absent (retail-driven) ⚠️
|
||||
|
||||
🧠 SMART MONEY MOVES
|
||||
Buying:
|
||||
• TOKEN_A — {N} wallets accumulating, avg price_change +{X}%
|
||||
• TOKEN_B — {N} wallets, fresh entry
|
||||
Selling:
|
||||
• TOKEN_C — {N} wallets reducing positions
|
||||
Cluster signal: TOKEN_A (trending + smart money overlap) 🔥
|
||||
|
||||
🌱 EARLY WATCH
|
||||
• TOKEN_X — near graduation, {N} smart degens in, rug_ratio {X}
|
||||
• TOKEN_Y — just graduated, strong volume, clean security
|
||||
(Run /gmgn-token → workflow-early-project-screening for deeper check)
|
||||
|
||||
⚠️ RISK SIGNALS
|
||||
• No active warnings detected
|
||||
OR
|
||||
• TOKEN_Z: whale concentration rising (top_10 = {X}%), monitor closely
|
||||
|
||||
─── SUGGESTED ACTIONS ─────────────────────
|
||||
Opportunity: TOKEN_A worth researching → run full token research
|
||||
Caution: TOKEN_C seeing smart money exits → tighten stop
|
||||
New entry: TOKEN_X early screening recommended
|
||||
═══════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Follow-Up Actions
|
||||
|
||||
From the brief, typical next steps:
|
||||
- **Deep dive on an opportunity** → [`workflow-token-research.md`](workflow-token-research.md)
|
||||
- **Screen early tokens further** → [`workflow-early-project-screening.md`](workflow-early-project-screening.md)
|
||||
- **Check a specific wallet that showed up** → [`workflow-smart-money-profile.md`](workflow-smart-money-profile.md)
|
||||
- **Risk check on a held position** → [`workflow-risk-warning.md`](workflow-risk-warning.md)
|
||||
- **Execute a trade** → use `gmgn-swap` skill
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-market-opportunities.md`](workflow-market-opportunities.md) — focused opportunity discovery from trending
|
||||
- [`workflow-early-project-screening.md`](workflow-early-project-screening.md) — detailed new token screening
|
||||
- [`workflow-risk-warning.md`](workflow-risk-warning.md) — active risk monitoring
|
||||
@@ -0,0 +1,179 @@
|
||||
# Early Project Screening — Workflow
|
||||
|
||||
Use this workflow to rapidly screen newly launched tokens from launchpads and identify whether any are worth a closer look, before committing to a full token research deep dive.
|
||||
|
||||
Use this workflow when:
|
||||
- "early project screening" / "are any new tokens worth accumulating?"
|
||||
- "screen the latest launched tokens for me"
|
||||
- "which new tokens have smart money entering early?"
|
||||
- "any new tokens on pump.fun worth watching?"
|
||||
- User wants to filter new launchpad tokens for quality signals before buying
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Fetch Newly Launched Tokens
|
||||
|
||||
```bash
|
||||
# Tokens just created, still on bonding curve
|
||||
gmgn-cli market trenches --chain <chain> --type new_creation
|
||||
|
||||
# Tokens near bonding curve completion (about to graduate to DEX)
|
||||
gmgn-cli market trenches --chain <chain> --type near_completion
|
||||
|
||||
# Tokens that have already graduated to open market
|
||||
gmgn-cli market trenches --chain <chain> --type completed
|
||||
```
|
||||
|
||||
**Which type to use:**
|
||||
- `new_creation` — highest upside potential, highest risk. Many will fail.
|
||||
- `near_completion` — approaching graduation, momentum building. Tighter window.
|
||||
- `completed` — already trading on DEX, more liquidity but earlier gains may be gone.
|
||||
|
||||
From the results, note each token's `address`, `symbol`, `smart_degen_count`, `renowned_count`, `volume`, `swaps`, and `rug_ratio`.
|
||||
|
||||
**Tip — use filter flags to pre-screen at fetch time:**
|
||||
|
||||
```bash
|
||||
# Fetch with safe baseline filter (server-side)
|
||||
gmgn-cli market trenches --chain <chain> \
|
||||
--type new_creation --type near_completion \
|
||||
--filter-preset safe --sort-by smart_degen_count
|
||||
|
||||
# Strict: safe + require smart money + min 24h volume $1k
|
||||
gmgn-cli market trenches --chain <chain> \
|
||||
--type new_creation --type near_completion \
|
||||
--filter-preset strict --sort-by smart_degen_count
|
||||
|
||||
# Custom: manual range filters (all sent server-side)
|
||||
gmgn-cli market trenches --chain <chain> \
|
||||
--type new_creation \
|
||||
--max-rug-ratio 0.3 --max-bundler-rate 0.3 --max-insider-ratio 0.3 \
|
||||
--min-smart-degen-count 1 --min-volume-24h 1000
|
||||
```
|
||||
|
||||
Using `--filter-preset safe` (or `strict`) tells the server to pre-filter results before returning — equivalent to Steps 2's "Discard immediately" criteria, applied before the response is sent.
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — First-Pass Filter (In-Response Scan)
|
||||
|
||||
> **If you used `--filter-preset safe` or `--filter-preset strict` in Step 1, the rug_ratio, bundler_rate, and insider_ratio checks below are already applied server-side.** Verify the remaining signals manually.
|
||||
|
||||
Before running any CLI commands per token, apply a quick in-response filter on the trenches results:
|
||||
|
||||
**Discard immediately if:**
|
||||
- `rug_ratio` > 0.3
|
||||
- `is_wash_trading` = `true`
|
||||
- `bundler_rate` > 0.3
|
||||
- `rat_trader_amount_rate` > 0.3
|
||||
- Zero `smart_degen_count` AND zero `renowned_count` AND volume < $10k
|
||||
|
||||
**Keep for deeper screening if any of:**
|
||||
- `smart_degen_count` ≥ 1 (smart money has entered)
|
||||
- `renowned_count` ≥ 1 (KOL has entered)
|
||||
- `bluechip_owner_percentage` > 0 (quality wallet base)
|
||||
- `volume` is strong relative to token age
|
||||
|
||||
Select up to **5 tokens** that pass this filter.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Security Check (Per Token)
|
||||
|
||||
For each shortlisted token:
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Hard stops — discard token immediately if:
|
||||
|
||||
| Field | Hard Stop |
|
||||
|-------|-----------|
|
||||
| `is_honeypot` | `"yes"` (BSC/Base) |
|
||||
| `renounced_mint` (SOL) | `false` |
|
||||
| `renounced_freeze_account` (SOL) | `false` |
|
||||
| `rug_ratio` | `> 0.3` |
|
||||
| `sell_tax` | `> 0.10` |
|
||||
| `top_10_holder_rate` | `> 0.6` |
|
||||
|
||||
Proceed with tokens that pass all hard stops.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Smart Money Early Entry Check
|
||||
|
||||
```bash
|
||||
# Who's already in? (smart money holders)
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 10
|
||||
|
||||
# Top traders — any known wallets?
|
||||
gmgn-cli token traders --chain <chain> --address <token_address> \
|
||||
--order-by profit --direction desc --limit 10
|
||||
```
|
||||
|
||||
Strong signal:
|
||||
- Smart money wallets entered **early** (check `buy_30m` / `buy_1h` counts on the holder — or cross-reference `last_active_timestamp` being recent)
|
||||
- Multiple distinct smart money wallets (not one large wallet — that's concentration risk)
|
||||
- Top traders show profit (token has already rewarded early holders, positive momentum)
|
||||
|
||||
Weak signal:
|
||||
- Only one smart money wallet in
|
||||
- Smart money wallet entered but `profit` is negative (they're underwater)
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Token Info Spot Check
|
||||
|
||||
```bash
|
||||
gmgn-cli token info --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Check:
|
||||
- Social presence: `link.twitter_username`, `link.telegram`, `link.website` — at least one should exist
|
||||
- `holder_count` — growing is a positive sign
|
||||
- `wallet_tags_stat.smart_wallets` — confirms smart money count
|
||||
- `cto_flag` — if `1`, community has taken over, dev is gone (neutral to positive, evaluate context)
|
||||
- `creator_token_status` — `creator_close` means dev has sold (mixed: reduces dump risk, but also less team commitment for very new tokens)
|
||||
|
||||
---
|
||||
|
||||
## Screening Output
|
||||
|
||||
Present results as a table, then a per-token verdict:
|
||||
|
||||
```
|
||||
Early Project Screening — {chain} / {type}
|
||||
Screened: {N} tokens from trenches → {M} passed filter
|
||||
|
||||
# | Symbol | Address (short) | Smart Degens | Rug Risk | Security | Verdict
|
||||
1 | ... | ... | {N} wallets | {X} | ✅/⚠️/🚫 | Watch / Small position / Skip
|
||||
...
|
||||
|
||||
─── Top Pick ───────────────────────────────
|
||||
{SYMBOL}: Smart money in early, security clean, social present
|
||||
→ Suggested action: Small exploratory position / Watch for 1h / Skip
|
||||
```
|
||||
|
||||
**Verdict scale:**
|
||||
- 🟢 **Small position** — clean security + smart money early entry + social presence
|
||||
- 🟡 **Watch** — some positive signals but missing key indicators; monitor for 30–60 min
|
||||
- 🔴 **Skip** — any hard stop triggered, or no smart money interest at all
|
||||
|
||||
---
|
||||
|
||||
## Follow-Up Actions
|
||||
|
||||
For any token rated 🟢:
|
||||
- Run full due diligence: [`workflow-token-research.md`](workflow-token-research.md)
|
||||
- Check risk warnings before sizing up: [`workflow-risk-warning.md`](workflow-risk-warning.md)
|
||||
- Execute swap if satisfied: use `gmgn-swap` skill
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-token-research.md`](workflow-token-research.md) — full 5-step token analysis
|
||||
- [`workflow-risk-warning.md`](workflow-risk-warning.md) — ongoing risk monitoring for held positions
|
||||
- [`workflow-market-opportunities.md`](workflow-market-opportunities.md) — trending token discovery (graduated tokens with volume)
|
||||
@@ -0,0 +1,48 @@
|
||||
# Discover Trading Opportunities via Trending — Workflow
|
||||
|
||||
Use this workflow to surface high-potential tokens from trending data.
|
||||
|
||||
## Step 1 — Fetch trending data
|
||||
|
||||
Fetch a broad pool with safe filters:
|
||||
|
||||
```bash
|
||||
gmgn-cli market trending \
|
||||
--chain <chain> --interval 1h \
|
||||
--order-by volume --limit 50 \
|
||||
--filter not_honeypot --filter has_social --raw
|
||||
```
|
||||
|
||||
## Step 2 — AI multi-factor analysis
|
||||
|
||||
Analyze each record in the response using the following signals (apply judgment, not rigid rules):
|
||||
|
||||
| Signal | Field(s) | Weight | Notes |
|
||||
|--------|----------|--------|-------|
|
||||
| Smart money interest | `smart_degen_count`, `renowned_count` | High | Key conviction indicator |
|
||||
| Bluechip ownership | `bluechip_owner_percentage` | Medium | Quality of holder base |
|
||||
| Real trading activity | `volume`, `swaps` | Medium | Distinguishes genuine interest from wash trading |
|
||||
| Price momentum | `change1h`, `change5m` | Medium | Prefer positive, non-parabolic moves |
|
||||
| Pool safety | `liquidity` | Medium | Low liquidity = high slippage risk |
|
||||
| Token maturity | `creation_timestamp` | Low | Avoid tokens less than ~1h old unless other signals are very strong |
|
||||
|
||||
Select the **top 5** tokens with the best composite profile. Prefer tokens that perform well across multiple signals rather than excelling in just one.
|
||||
|
||||
## Step 3 — Present top 5 to user
|
||||
|
||||
Present results as a concise table, then give a one-line rationale for each pick:
|
||||
|
||||
```
|
||||
Top 5 Trending Tokens — SOL / 1h
|
||||
|
||||
# | Symbol | Address (short) | Smart Degens | Volume | 1h Chg | Reasoning
|
||||
1 | ... | ... | ... | ... | ... | Smart money accumulating + high volume
|
||||
2 | ...
|
||||
...
|
||||
```
|
||||
|
||||
## Step 4 — Follow-up actions
|
||||
|
||||
For each token, offer:
|
||||
- **Deep dive**: run full token research workflow — see [workflow-token-research.md](workflow-token-research.md)
|
||||
- **Swap**: execute directly if the user is satisfied with the trending data alone
|
||||
@@ -0,0 +1,224 @@
|
||||
# Project Deep Report — Comprehensive Token Analysis Workflow
|
||||
|
||||
Use this workflow when the user wants a thorough, multi-dimensional project analysis — going beyond basic due diligence to cover smart money conviction, holder quality, market positioning, and a final investment verdict.
|
||||
|
||||
Use this workflow when:
|
||||
- "give me a full analysis of this project"
|
||||
- "deep report" / "is this project worth a large position?"
|
||||
- "give me a complete investment research report"
|
||||
- User wants more than a quick check — they want a structured report before making a significant position decision
|
||||
|
||||
> For a quick pre-buy check, use [`workflow-token-research.md`](workflow-token-research.md) instead. This workflow is more comprehensive and produces a full written report.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Fundamentals
|
||||
|
||||
```bash
|
||||
gmgn-cli token info --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Extract and assess:
|
||||
|
||||
| Field | What to Note |
|
||||
|-------|-------------|
|
||||
| `price` | Current price |
|
||||
| Market cap | `price × circulating_supply` — compute this manually |
|
||||
| `liquidity` | USD in pool — < $50k is thin for a "serious" position |
|
||||
| `holder_count` | Total wallets holding. Growing = organic adoption |
|
||||
| `wallet_tags_stat.smart_wallets` | Smart money holders count |
|
||||
| `wallet_tags_stat.renowned_wallets` | KOL holders count |
|
||||
| `link.*` | Social presence: Twitter, Telegram, website |
|
||||
| `cto_flag` | Community takeover? |
|
||||
| `creator_token_status` | Dev still holding or has sold? |
|
||||
|
||||
**Fundamental score (0–3):**
|
||||
- +1 if market cap reasonable for the chain/category
|
||||
- +1 if strong social presence (2+ active channels)
|
||||
- +1 if `smart_wallets` ≥ 3 AND `holder_count` growing
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Security Assessment
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
**Hard stops (any one = do not proceed):**
|
||||
- `is_honeypot = "yes"` (BSC/Base)
|
||||
- `rug_ratio > 0.5`
|
||||
- `renounced_mint = false` AND `renounced_freeze_account = false` (SOL) — both unrenounced
|
||||
- `sell_tax > 0.15`
|
||||
|
||||
**Security score (0–4):**
|
||||
- +1 if contract open source / renounced
|
||||
- +1 if `rug_ratio < 0.1`
|
||||
- +1 if `top_10_holder_rate < 0.3`
|
||||
- +1 if no snipers (`sniper_count < 5`) and no wash trading
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Liquidity and Pool Health
|
||||
|
||||
```bash
|
||||
gmgn-cli token pool --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Assess:
|
||||
- **Liquidity depth:** > $100k = healthy; $10k–$100k = thin; < $10k = high exit slippage
|
||||
- **Pool age:** older pool = more stable price history
|
||||
- **DEX:** recognized exchange (Raydium, Uniswap v3, PancakeSwap) = better
|
||||
- **Bonding curve status** (`is_on_curve`): if still on curve, token has not graduated — higher volatility window
|
||||
|
||||
**Liquidity score (0–2):**
|
||||
- +1 if liquidity > $50k
|
||||
- +1 if DEX is major and pool age > 24h
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Smart Money Conviction Analysis
|
||||
|
||||
This is the key differentiator from basic token research.
|
||||
|
||||
```bash
|
||||
# Smart money holders — are they accumulating or distributing?
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 20
|
||||
|
||||
# KOL holders
|
||||
gmgn-cli token traders --chain <chain> --address <token_address> \
|
||||
--tag renowned --order-by profit --direction desc --limit 10
|
||||
|
||||
# Top holders overall — check concentration
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--order-by amount_percentage --direction desc --limit 20
|
||||
```
|
||||
|
||||
Assess smart money conviction:
|
||||
|
||||
| Signal | Bullish | Bearish |
|
||||
|--------|---------|---------|
|
||||
| Smart money count | ≥ 3 distinct wallets | 0 or 1 |
|
||||
| Net direction | `buy_volume_cur` > `sell_volume_cur` | Selling exceeds buying |
|
||||
| Unrealized profit | Large (still holding, not selling) | Small or negative |
|
||||
| Realized profit | Moderate (some took profit, healthy) | Very large (majority already exited) |
|
||||
| KOL involvement | ≥ 1 KOL with active position | None |
|
||||
| Wallet diversity | Multiple different wallets | One whale dominating |
|
||||
|
||||
**Smart money score (0–4):**
|
||||
- +1 if `smart_wallets` ≥ 3
|
||||
- +1 if net buy direction (buy_volume_cur > sell_volume_cur across smart wallets)
|
||||
- +1 if average `unrealized_profit` is positive (they're still in profit, still holding)
|
||||
- +1 if at least 1 KOL has an active position
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Price Action Context
|
||||
|
||||
```bash
|
||||
# Recent price action — 4h candles, last 3 days
|
||||
gmgn-cli market kline --chain <chain> --address <token_address> \
|
||||
--resolution 4h
|
||||
|
||||
# Is it currently trending?
|
||||
gmgn-cli market trending --chain <chain> --interval 1h \
|
||||
--order-by volume --limit 100 --raw | jq '.data.rank[] | select(.address == "<token_address>")'
|
||||
```
|
||||
|
||||
Look for:
|
||||
- **Entry context:** Is price near a local bottom (potential value) or after a run-up (chasing)?
|
||||
- **Volume confirmation:** Do bullish candles have higher volume than bearish candles?
|
||||
- **Trending:** If it appears in trending with `smart_degen_count > 0`, momentum + conviction overlap
|
||||
|
||||
**Price action score (0–2):**
|
||||
- +1 if price is not parabolic (< 5x from recent low) — not chasing
|
||||
- +1 if volume is rising on up-candles (healthy accumulation pattern)
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Risk Factors Summary
|
||||
|
||||
Aggregate all warning signals from Steps 1–5:
|
||||
|
||||
| Category | Risk Level | Key Signals |
|
||||
|----------|-----------|-------------|
|
||||
| Security | ✅/⚠️/🚫 | honeypot, rug_ratio, concentration |
|
||||
| Liquidity | ✅/⚠️/🚫 | pool size, pool age |
|
||||
| Smart Money | ✅/⚠️/🚫 | count, direction, conviction |
|
||||
| Holder Quality | ✅/⚠️/🚫 | bundler_rate, rat_trader_rate, wash_trading |
|
||||
| Price Action | ✅/⚠️/🚫 | entry timing, momentum |
|
||||
|
||||
---
|
||||
|
||||
## Deep Report Output
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════╗
|
||||
║ PROJECT DEEP REPORT — {SYMBOL} ║
|
||||
║ {chain} | {short_address} | {date} ║
|
||||
╚══════════════════════════════════════════════════════╝
|
||||
|
||||
📋 FUNDAMENTALS
|
||||
Price: ${price}
|
||||
Market Cap: ~${market_cap}
|
||||
Liquidity: ${liquidity} on {exchange}
|
||||
Holders: {holder_count}
|
||||
Social: Twitter ✅/❌ | Telegram ✅/❌ | Website ✅/❌
|
||||
Dev Status: {creator_close = sold ✅ / creator_hold = still in ⚠️}
|
||||
Fundamental Score: {X}/3
|
||||
|
||||
🔒 SECURITY
|
||||
Honeypot: ✅ No / 🚫 YES
|
||||
Contract: {open_source} | {renounced}
|
||||
Rug Risk: {rug_ratio} → ✅/⚠️/🚫
|
||||
Concentration: Top-10 hold {top_10_holder_rate%} → ✅/⚠️/🚫
|
||||
Wash Trading: ✅ None / ⚠️ Detected
|
||||
Security Score: {X}/4
|
||||
|
||||
💧 LIQUIDITY
|
||||
Pool: ${liquidity} | {exchange} | Age: {pool_age}
|
||||
Bonding Curve: Graduated ✅ / Still on curve ⚠️
|
||||
Liquidity Score: {X}/2
|
||||
|
||||
🧠 SMART MONEY CONVICTION
|
||||
SM Holders: {N} wallets
|
||||
Net Direction: Accumulating ✅ / Distributing ⚠️ / Mixed
|
||||
SM Unrealized: +{X}% avg (still holding) ✅ / Underwater ⚠️
|
||||
KOL Presence: {N} KOL wallets active
|
||||
Smart Money Score: {X}/4
|
||||
|
||||
📈 PRICE ACTION
|
||||
Recent trend: Healthy accumulation / Parabolic (avoid chasing) / Declining
|
||||
Trending now: Yes (rank #{rank}) ✅ / Not trending
|
||||
Price Action Score: {X}/2
|
||||
|
||||
─── RISK FLAGS ──────────────────────────────────────
|
||||
{List any ⚠️ or 🚫 signals here, or "No major risk flags"}
|
||||
|
||||
─── TOTAL SCORE ─────────────────────────────────────
|
||||
{X} / 15
|
||||
|
||||
─── VERDICT ─────────────────────────────────────────
|
||||
🟢 STRONG BUY CANDIDATE (score ≥ 11, no hard stops)
|
||||
Smart money confirmed, clean security, healthy liquidity
|
||||
→ Suggested: research position sizing, use gmgn-swap
|
||||
|
||||
🟡 WATCHLIST (score 7–10, no hard stops)
|
||||
Some positive signals but missing key conviction indicators
|
||||
→ Suggested: monitor for 24–48h, re-assess if SM increases
|
||||
|
||||
🔴 SKIP (any hard stop OR score < 7)
|
||||
Risk factors outweigh opportunity
|
||||
→ Reason: {specific flag}
|
||||
╚══════════════════════════════════════════════════════╝
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-token-research.md`](workflow-token-research.md) — faster pre-buy check (use when time-sensitive)
|
||||
- [`workflow-risk-warning.md`](workflow-risk-warning.md) — ongoing monitoring after entering a position
|
||||
- [`workflow-smart-money-profile.md`](workflow-smart-money-profile.md) — deep dive on specific smart money wallets holding this token
|
||||
- [`workflow-market-opportunities.md`](workflow-market-opportunities.md) — find tokens to run this report on
|
||||
@@ -0,0 +1,142 @@
|
||||
# Risk Warning — Structured Checklist Workflow
|
||||
|
||||
Use this workflow to assess whether a token currently held or being considered shows active risk signals: whale exit, liquidity drain, or developer dump.
|
||||
|
||||
Use this workflow when:
|
||||
- "are any whales dumping this token?"
|
||||
- "is the liquidity still healthy?"
|
||||
- "are there any signs the developer is exiting?"
|
||||
- "risk warning" / "is this project still safe to hold?"
|
||||
- User wants to check if a held position is turning dangerous
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Token Security Snapshot
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Immediate red flags (any one triggers danger):
|
||||
|
||||
| Field | Danger Signal |
|
||||
|-------|--------------|
|
||||
| `is_honeypot` | `"yes"` → sells are blocked, exit impossible (BSC/Base only) |
|
||||
| `rug_ratio` | `> 0.3` → high rug pull probability |
|
||||
| `top_10_holder_rate` | `> 0.5` → extreme concentration, whale exit risk |
|
||||
| `creator_token_status` | `creator_hold` → dev still holds, dump risk active |
|
||||
| `renounced_mint` (SOL) | `false` → dev can inflate supply at any time |
|
||||
| `renounced_freeze_account` (SOL) | `false` → dev can freeze wallets |
|
||||
| `sell_tax` | `> 0.10` → exit penalty is severe |
|
||||
| `bundler_rate` | `> 0.3` → heavily bot-bundled at launch, artificial price support |
|
||||
| `rat_trader_amount_rate` | `> 0.3` → insider trading detected |
|
||||
| `is_wash_trading` | `true` → volume is fake |
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Liquidity Check
|
||||
|
||||
```bash
|
||||
gmgn-cli token pool --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Check for liquidity drain:
|
||||
|
||||
- **Current liquidity (USD):** < $10k = extreme exit slippage risk
|
||||
- **Liquidity vs earlier baseline:** if you have a prior reading, compare. A drop of > 30% in a short period is a warning signal.
|
||||
- **Pool age (`creation_timestamp`):** very new pools (< 1h) combined with other risk signals = high risk.
|
||||
- **DEX (`exchange`):** verify it's a known DEX (Raydium, Uniswap, PancakeSwap). Unknown or single-sided pools are suspicious.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Whale Holder Analysis
|
||||
|
||||
```bash
|
||||
# Top holders by supply percentage
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--order-by amount_percentage --direction desc --limit 20
|
||||
|
||||
# Smart money holders — are they still in?
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--tag smart_degen --order-by amount_percentage --direction desc --limit 20
|
||||
```
|
||||
|
||||
Warning signals:
|
||||
|
||||
- **Concentration:** top 1–3 wallets hold > 20% combined → single exit can crash price
|
||||
- **Smart money exodus:** zero or declining `smart_degen` holders = conviction leaving
|
||||
- **Wallet tags:** wallets tagged `bundler` or `rat_trader` in top holders = insider concentration risk
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Recent Trade Flow (Smart Money Direction)
|
||||
|
||||
```bash
|
||||
gmgn-cli track smartmoney --chain <chain>
|
||||
```
|
||||
|
||||
Filter results for the token address in question. Check:
|
||||
|
||||
- Are smart money wallets **selling** this token recently? (`is_open_or_close` = 1 on sell side for kol/smartmoney)
|
||||
- Is `price_change` on recent smart money buys negative? (their entry is underwater — they may exit)
|
||||
- Cluster of sells from multiple tracked wallets = strong exit signal
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Price and Volume Anomaly (K-line)
|
||||
|
||||
```bash
|
||||
gmgn-cli market kline --chain <chain> --address <token_address> \
|
||||
--resolution 1h
|
||||
```
|
||||
|
||||
Look for:
|
||||
|
||||
- **Volume spike without price increase** — selling pressure absorbing buy volume
|
||||
- **Price drop with volume spike** — active dump in progress
|
||||
- **Volume collapse** — liquidity evaporating, exit windows closing
|
||||
- **Consecutive red candles after ATH** — distribution phase
|
||||
|
||||
---
|
||||
|
||||
## Risk Summary Output
|
||||
|
||||
After running all steps, output a structured risk verdict:
|
||||
|
||||
```
|
||||
Risk Assessment: {TOKEN_SYMBOL} ({short_address})
|
||||
Chain: {chain} | Checked: {timestamp}
|
||||
|
||||
─── Security ───────────────────────────────
|
||||
Honeypot: ✅ No / 🚫 YES — exit blocked
|
||||
Rug ratio: ✅ {X} / ⚠️ {X} / 🚫 {X} (> 0.3 danger)
|
||||
Mint renounced: ✅ Yes / 🚫 No
|
||||
Dev holding: ✅ Sold / 🚫 Still holding — dump risk
|
||||
|
||||
─── Liquidity ──────────────────────────────
|
||||
Current liquidity: ${X} [✅ healthy / ⚠️ low / 🚫 critical]
|
||||
Pool age: {X} hours/days
|
||||
|
||||
─── Whale Concentration ────────────────────
|
||||
Top 10 hold rate: {X}% [✅ < 20% / ⚠️ 20–50% / 🚫 > 50%]
|
||||
Smart money holders: {N} wallets still in
|
||||
|
||||
─── Smart Money Flow ───────────────────────
|
||||
Recent smart money: Buying ✅ / Mixed ⚠️ / Selling 🚫
|
||||
|
||||
─── Price Action ───────────────────────────
|
||||
1h volume trend: Normal / Spike (selling pressure) / Collapsing
|
||||
Recent candles: Accumulation / Distribution / Neutral
|
||||
|
||||
─── Overall Verdict ────────────────────────
|
||||
🟢 No active risk signals — position appears stable
|
||||
🟡 Watch closely — 1–2 warning signals present, monitor daily
|
||||
🔴 HIGH RISK — multiple danger signals, consider exiting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-token-research.md`](workflow-token-research.md) — full pre-buy due diligence
|
||||
- [`workflow-project-deep-report.md`](workflow-project-deep-report.md) — comprehensive project analysis
|
||||
@@ -0,0 +1,169 @@
|
||||
# Smart Money Profile — Behavior Analysis Workflow
|
||||
|
||||
When a user wants to understand a wallet's trading behavior in depth: what style they trade, when they take profit, when they cut losses, and whether copying them would be profitable.
|
||||
|
||||
Use this workflow when:
|
||||
- "is this wallet a long-term holder or a short-term trader?"
|
||||
- "what is this wallet's win rate, when does it take profit or cut losses?"
|
||||
- "if I copied this wallet, what would my return be?"
|
||||
- "smart money leaderboard, which wallets are most worth following?"
|
||||
- User provides a wallet address and asks about trading style or copy-trade potential
|
||||
|
||||
> For basic "is this wallet worth following" analysis, see [`workflow-wallet-analysis.md`](workflow-wallet-analysis.md). This workflow goes deeper into behavior patterns and copy-trade estimation.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Trading Stats (Both Periods)
|
||||
|
||||
Run stats for both 7d and 30d to detect performance trends:
|
||||
|
||||
```bash
|
||||
gmgn-cli portfolio stats --chain <chain> --wallet <address> --period 7d
|
||||
gmgn-cli portfolio stats --chain <chain> --wallet <address> --period 30d
|
||||
```
|
||||
|
||||
Key metrics:
|
||||
|
||||
| Field | Meaning | Threshold |
|
||||
|-------|---------|-----------|
|
||||
| `winrate` | % of profitable trades (0–1) | > 0.6 strong, > 0.5 acceptable |
|
||||
| `pnl` | realized_profit / total_cost multiplier | > 1.0 = net positive |
|
||||
| `realized_profit` | USD profit locked in | context-dependent |
|
||||
| `buy_count` / `sell_count` | trading frequency | high = active trader |
|
||||
| `token_num` | number of distinct tokens traded | high = diversified |
|
||||
|
||||
**Trend signal:** If 7d `winrate` is significantly higher than 30d, performance is improving. If lower, recent form is declining.
|
||||
|
||||
---
|
||||
|
||||
## Step 2 — Activity Analysis (Style Inference)
|
||||
|
||||
```bash
|
||||
gmgn-cli portfolio activity --chain <chain> --wallet <address> --limit 100
|
||||
```
|
||||
|
||||
For each token that appears in both a buy and a sell event, compute holding duration:
|
||||
- `sell.timestamp - buy.timestamp` in hours
|
||||
|
||||
**Style classification:**
|
||||
|
||||
| Holding Duration | Style Label |
|
||||
|-----------------|-------------|
|
||||
| < 1 hour | Scalper |
|
||||
| 1h – 24h | Day trader |
|
||||
| 1d – 7d | Swing trader |
|
||||
| > 7d | Position / long-term holder |
|
||||
|
||||
Also check:
|
||||
- **Position sizing consistency** — are buy amounts roughly similar (disciplined) or highly variable?
|
||||
- **Token concentration** — does the wallet repeatedly trade the same tokens (specialist) or always new ones (trend chaser)?
|
||||
- **Sell behavior** — do sells follow a pattern (e.g., always sells after 2–3x, or cuts at -30%)?
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — Take-Profit and Stop-Loss Pattern
|
||||
|
||||
From `portfolio activity`, cross-reference buy price vs sell price for completed round trips:
|
||||
|
||||
- For each token: find a `buy` event followed by a `sell` event
|
||||
- Compute approximate return: `(sell_total_usd - buy_total_usd) / buy_total_usd`
|
||||
- Group outcomes: wins vs losses
|
||||
|
||||
Look for:
|
||||
- **Typical gain at exit** — does the wallet consistently take profit at ~2x, ~5x, or higher?
|
||||
- **Typical loss at cut** — does the wallet cut quickly at -20% or hold through large drawdowns?
|
||||
- **Asymmetry** — wins larger than losses = positive expected value. Reverse = risk.
|
||||
|
||||
---
|
||||
|
||||
## Step 4 — Copy-Trade ROI Estimation (Approximate)
|
||||
|
||||
> **Note:** This is an approximation based on historical activity data, not a precise backtest.
|
||||
|
||||
For the wallet's last 20–30 completed trades (round-trip buys + sells):
|
||||
|
||||
1. List all buy events: token, amount_usd, timestamp
|
||||
2. List all sell events for the same tokens
|
||||
3. Compute per-trade return: `(sell_usd - buy_usd) / buy_usd`
|
||||
4. Average the returns
|
||||
|
||||
**If you want to estimate "if I had followed today":**
|
||||
For still-open positions (buy with no matching sell), use `portfolio holdings` to get current `usd_value` vs `cost`, computing unrealized return.
|
||||
|
||||
Present as:
|
||||
```
|
||||
Copy-trade estimate (last 30d completed trades):
|
||||
Avg return per trade: +X%
|
||||
Win rate: X / Y trades profitable
|
||||
Best trade: +X% on TOKEN
|
||||
Worst trade: -X% on TOKEN
|
||||
Approximate 30d return if equal-weight copy: ~X%
|
||||
⚠️ This is an approximation. Actual results depend on entry timing, slippage, and fees.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — Smart Money Leaderboard (Multi-Wallet Comparison)
|
||||
|
||||
When the user wants to compare multiple smart money wallets:
|
||||
|
||||
```bash
|
||||
# Batch stats — compare up to 10 wallets at once
|
||||
gmgn-cli portfolio stats --chain <chain> \
|
||||
--wallet <addr1> --wallet <addr2> --wallet <addr3> \
|
||||
--period 30d
|
||||
```
|
||||
|
||||
Rank wallets by composite score. Suggested weights:
|
||||
- `winrate` × 40%
|
||||
- `pnl` × 40%
|
||||
- `token_num` (diversity) × 10%
|
||||
- Recency (7d winrate vs 30d winrate improvement) × 10%
|
||||
|
||||
To discover active smart money wallets to compare, first run:
|
||||
```bash
|
||||
gmgn-cli track smartmoney --chain <chain>
|
||||
```
|
||||
Extract unique wallet addresses from the results, then batch-query their stats.
|
||||
|
||||
---
|
||||
|
||||
## Output Template
|
||||
|
||||
```
|
||||
Smart Money Profile: {short_address}
|
||||
Chain: {chain} | Data: 7d + 30d
|
||||
|
||||
─── Performance ────────────────────────────
|
||||
Win Rate (7d / 30d): {X}% / {X}% [trend: ↑ improving / ↓ declining / → stable]
|
||||
PnL Ratio (30d): {X}x
|
||||
Realized Profit (30d): ${X}
|
||||
|
||||
─── Trading Style ──────────────────────────
|
||||
Style: Scalper / Day trader / Swing trader / Long-term holder
|
||||
Avg Hold Time: ~{X} hours / days
|
||||
Position Size: Consistent (disciplined) / Variable (opportunistic)
|
||||
Token Focus: Specialist (repeats tokens) / Trend chaser (always new)
|
||||
|
||||
─── Exit Behavior ──────────────────────────
|
||||
Typical take-profit: ~+{X}% gain
|
||||
Typical stop-loss: ~-{X}% loss
|
||||
Win/loss ratio: {avg_win}x / {avg_loss}x
|
||||
|
||||
─── Copy-Trade Estimate ────────────────────
|
||||
Approx. 30d return if copied: ~{X}%
|
||||
Based on {N} completed trades
|
||||
⚠️ Approximation only
|
||||
|
||||
─── Verdict ────────────────────────────────
|
||||
🟢 High-conviction follow — strong stats, consistent style, favorable exit pattern
|
||||
🟡 Selective follow — good stats but inconsistent or high-risk behavior
|
||||
🔴 Avoid copying — low win rate, poor exit discipline, or declining form
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-wallet-analysis.md`](workflow-wallet-analysis.md) — general wallet quality assessment
|
||||
- [`workflow-token-research.md`](workflow-token-research.md) — deep dive on tokens this wallet holds
|
||||
@@ -0,0 +1,58 @@
|
||||
# Full Token Due Diligence — 4-Step Workflow
|
||||
|
||||
Use this workflow before deciding to buy a token. Run all four steps in sequence.
|
||||
|
||||
## Step 1 — Get basic info
|
||||
|
||||
```bash
|
||||
gmgn-cli token info --chain sol --address <token_address> --raw
|
||||
```
|
||||
|
||||
Check: `price`, `liquidity`, `holder_count`, `wallet_tags_stat.smart_wallets`, `wallet_tags_stat.renowned_wallets`, `link.website` / `link.twitter_username` / `link.telegram`.
|
||||
|
||||
**Red flags**: all `link.*` social fields empty, very low liquidity (<$10k), zero `wallet_tags_stat.smart_wallets` and `renowned_wallets`.
|
||||
|
||||
## Step 2 — Check security
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain sol --address <token_address> --raw
|
||||
```
|
||||
|
||||
Check these fields and their safe thresholds:
|
||||
|
||||
| Field | Safe | Warning | Danger |
|
||||
|-------|------|---------|--------|
|
||||
| `is_honeypot` | `"no"` | — | `"yes"` → Do not buy |
|
||||
| `open_source` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `owner_renounced` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `renounced_mint` (SOL) | `true` | — | `false` → mint risk |
|
||||
| `renounced_freeze_account` (SOL) | `true` | — | `false` → freeze risk |
|
||||
| `buy_tax` / `sell_tax` | `0` | `0.01–0.05` | `>0.10` → high tax |
|
||||
| `top_10_holder_rate` | `<0.20` | `0.20–0.40` | `>0.50` → whale risk |
|
||||
| `rug_ratio` | `<0.10` | `0.10–0.30` | `>0.30` → high rug risk |
|
||||
| `creator_token_status` | `creator_close` | — | `creator_hold` → dev not sold |
|
||||
| `sniper_count` | `<5` | `5–20` | `>20` → heavily sniped |
|
||||
|
||||
## Step 3 — Check liquidity pool
|
||||
|
||||
```bash
|
||||
gmgn-cli token pool --chain sol --address <token_address> --raw
|
||||
```
|
||||
|
||||
Check: liquidity amount, which DEX (`exchange`), pool age (`creation_timestamp`). Low liquidity means high slippage risk when buying or selling.
|
||||
|
||||
## Step 4 — Check smart money signals
|
||||
|
||||
```bash
|
||||
# Is smart money accumulating?
|
||||
gmgn-cli token holders --chain sol --address <token_address> \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 20 --raw
|
||||
|
||||
# Have KOLs already taken profit?
|
||||
gmgn-cli token traders --chain sol --address <token_address> \
|
||||
--tag renowned --order-by profit --direction desc --limit 20 --raw
|
||||
```
|
||||
|
||||
**Bullish signals**: smart_degen wallets buying heavily, unrealized_profit is large (still holding), renowned wallets accumulating, low sell_volume_cur.
|
||||
|
||||
**Bearish signals**: sell_volume_cur > buy_volume_cur for smart money, large realized profits already taken (they may be done), top holders with very high amount_percentage starting to sell.
|
||||
@@ -0,0 +1,109 @@
|
||||
# New Token Research — Full Workflow
|
||||
|
||||
When a user provides a token address or name and wants to know if it's worth researching or buying, run this full workflow in sequence.
|
||||
|
||||
## Step 1 — Basic Info
|
||||
|
||||
```bash
|
||||
gmgn-cli token info --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Check: `price`, `market_cap` (= `price × circulating_supply`), `liquidity`, `holder_count`, `wallet_tags_stat.smart_wallets`, `wallet_tags_stat.renowned_wallets`, `link.website` / `link.twitter_username` / `link.telegram`.
|
||||
|
||||
**Red flags**: all `link.*` social fields empty, liquidity < $10k, zero `wallet_tags_stat.smart_wallets` and `renowned_wallets`.
|
||||
|
||||
## Step 2 — Security Check
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Check each field against the thresholds below:
|
||||
|
||||
| Field | Safe ✅ | Warning ⚠️ | Danger 🚫 |
|
||||
|-------|---------|-----------|---------|
|
||||
| `is_honeypot` | `"no"` | — | `"yes"` → **Stop immediately. Do not buy.** BSC/Base only — empty string on SOL (not applicable). |
|
||||
| `open_source` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `owner_renounced` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `renounced_mint` (SOL) | `true` | — | `false` → mint risk |
|
||||
| `renounced_freeze_account` (SOL) | `true` | — | `false` → freeze risk |
|
||||
| `buy_tax` / `sell_tax` | `0` | `0.01–0.05` | `>0.10` |
|
||||
| `top_10_holder_rate` | `<0.20` | `0.20–0.50` | `>0.50` |
|
||||
| `rug_ratio` | `<0.10` | `0.10–0.30` | `>0.30` |
|
||||
| `creator_token_status` | `creator_close` | — | `creator_hold` |
|
||||
| `sniper_count` | `<5` | `5–20` | `>20` |
|
||||
|
||||
**If `is_honeypot = "yes"` → stop immediately and display: "🚫 HONEYPOT DETECTED — Do not buy this token." Do NOT proceed.**
|
||||
|
||||
## Step 3 — Liquidity Pool
|
||||
|
||||
```bash
|
||||
gmgn-cli token pool --chain <chain> --address <token_address>
|
||||
```
|
||||
|
||||
Check: liquidity amount, which DEX (`exchange`), pool age (`creation_timestamp`). Low liquidity means high slippage risk when buying or selling.
|
||||
|
||||
## Step 4 — Market Heat (Check if Currently Trending)
|
||||
|
||||
Check if this token appears in current trending data:
|
||||
|
||||
```bash
|
||||
gmgn-cli market trending --chain <chain> --interval 1h --order-by volume --limit 100 --raw | jq '.data.rank[] | select(.address == "<token_address>")'
|
||||
```
|
||||
|
||||
- **If found**: note its `rank`, `smart_degen_count`, `volume`, `price_change_percent1h` — this confirms active market interest.
|
||||
- **If not found**: token is not currently trending (neutral signal — not necessarily bad, just no active buzz).
|
||||
|
||||
## Step 5 — Smart Money Signals
|
||||
|
||||
```bash
|
||||
# Is smart money accumulating?
|
||||
gmgn-cli token holders --chain <chain> --address <token_address> \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 20
|
||||
|
||||
# What are KOL traders doing?
|
||||
gmgn-cli token traders --chain <chain> --address <token_address> \
|
||||
--tag renowned --order-by profit --direction desc --limit 20
|
||||
```
|
||||
|
||||
**Bullish signals**: smart_degen wallets buying heavily, unrealized_profit is large (still holding), low sell_volume_cur.
|
||||
|
||||
**Bearish signals**: sell_volume_cur > buy_volume_cur for smart money, large realized profits already taken (may be exiting), top holders with very high amount_percentage starting to sell.
|
||||
|
||||
## Decision Framework
|
||||
|
||||
After completing all steps, present a structured conclusion:
|
||||
|
||||
```
|
||||
Token Research Summary: {symbol} ({chain})
|
||||
Address: {short_address}
|
||||
─── Security ──────────────────────────────
|
||||
Honeypot: ✅ no / 🚫 YES — STOP
|
||||
Contract verified:✅ yes / 🚫 no / ⚠️ unknown
|
||||
Owner renounced: ✅ yes / 🚫 no / ⚠️ unknown
|
||||
Rug risk: {rug_ratio} → ✅ low / ⚠️ medium / 🚫 high
|
||||
Top-10 holders: {top_10_holder_rate%} → ✅ <20% / ⚠️ 20–50% / 🚫 >50%
|
||||
─── Liquidity ─────────────────────────────
|
||||
Pool liquidity: ${liquidity} on {exchange}
|
||||
─── Market Heat ───────────────────────────
|
||||
Trending: yes (rank #{rank}) / not trending
|
||||
─── Smart Money ───────────────────────────
|
||||
SM holders: {smart_wallets} | KOL holders: {renowned_wallets}
|
||||
SM activity: accumulating / distributing / absent
|
||||
─── Verdict ───────────────────────────────
|
||||
🟢 Buy — strong signals across all dimensions
|
||||
🟡 Watch — mixed signals, monitor for confirmation
|
||||
🔴 Skip — red flags present (specify which)
|
||||
```
|
||||
|
||||
**Scoring logic:**
|
||||
- If any 🚫 → skip (hard stop, especially if honeypot)
|
||||
- If 3+ ⚠️ with no 🚫 → needs more research / watch
|
||||
- If mostly ✅ with smart money accumulating → worth researching / buying
|
||||
|
||||
---
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-market-opportunities.md`](workflow-market-opportunities.md) — find tokens from trending first, then deep dive here
|
||||
- [`workflow-project-deep-report.md`](workflow-project-deep-report.md) — more comprehensive analysis with scored dimensions and a full written report
|
||||
@@ -0,0 +1,85 @@
|
||||
# Wallet Analysis — Full Workflow
|
||||
|
||||
When a user provides a wallet address and wants to know the wallet's investment style, track record, and whether it's worth following.
|
||||
|
||||
## Step 1 — Current Holdings
|
||||
|
||||
```bash
|
||||
gmgn-cli portfolio holdings --chain <chain> --wallet <address> \
|
||||
--order-by usd_value --direction desc --limit 50
|
||||
```
|
||||
|
||||
Check: what tokens they hold, position sizes, `usd_value`, `unrealized_profit` distribution, `profit_change` per position. A wallet holding many positions with strong unrealized gains is still in accumulation mode.
|
||||
|
||||
## Step 2 — Trading Stats
|
||||
|
||||
```bash
|
||||
gmgn-cli portfolio stats --chain <chain> --wallet <address> --period 30d
|
||||
```
|
||||
|
||||
Key metrics:
|
||||
- `winrate` — ratio of profitable trades (0–1); > 0.6 is strong
|
||||
- `realized_profit` — total USD profit locked in over 30 days
|
||||
- `pnl` — profit/loss ratio = `realized_profit / total_cost`; `2.0` = doubled money
|
||||
- `buy_count` / `sell_count` — trading frequency and style
|
||||
|
||||
## Step 3 — Recent Activity
|
||||
|
||||
```bash
|
||||
gmgn-cli portfolio activity --chain <chain> --wallet <address> --limit 50
|
||||
```
|
||||
|
||||
Look for:
|
||||
- Trading frequency (multiple trades per day = active trader)
|
||||
- Average holding duration: compare `last_active_timestamp` of buy vs sell events for the same token
|
||||
- Token diversity: does the wallet trade many different tokens or focus on a few?
|
||||
- Position sizing patterns: are buys consistent size or highly variable?
|
||||
|
||||
## Step 4 — If Wallet Is Followed on GMGN
|
||||
|
||||
If the user has followed this wallet on the GMGN platform:
|
||||
|
||||
> **Requires `GMGN_PRIVATE_KEY`** in `.env` — `track follow-wallet` uses signature auth. If the key is not configured, skip this step and note it in the conclusion.
|
||||
|
||||
```bash
|
||||
gmgn-cli track follow-wallet --chain <chain> --wallet <address>
|
||||
```
|
||||
|
||||
Shows real-time trade feed for this wallet. Check `is_open_or_close` (1 = full position open/close, 0 = partial) and `price_change` (how well past trades aged).
|
||||
|
||||
## Step 5 — Deep Dive: Evaluate Their Top Holdings
|
||||
|
||||
For the top 3–5 holdings by `usd_value`, run the full token research workflow to verify the quality of what this wallet holds.
|
||||
|
||||
→ See [`docs/workflow-token-research.md`](workflow-token-research.md) for the full 5-step token analysis.
|
||||
|
||||
## Conclusion Framework
|
||||
|
||||
After completing all steps, output a wallet profile:
|
||||
|
||||
```
|
||||
Wallet Analysis: {short_address}
|
||||
Chain: {chain} | Period: 30d
|
||||
─── Performance ────────────────────────────
|
||||
Win Rate: {winrate × 100}%
|
||||
Realized P&L: ${realized_profit}
|
||||
PnL Ratio: {pnl}x
|
||||
Trades: {buy_count} buys / {sell_count} sells
|
||||
─── Style ──────────────────────────────────
|
||||
Trading Style: Day trader / Swing trader / Holder
|
||||
(Day trader: many trades/day; Swing: holds days–weeks; Holder: few sells)
|
||||
Token Focus: Meme / DeFi / Mixed / Specific sector
|
||||
─── Current Positions ──────────────────────
|
||||
Top holdings by value: {token1}, {token2}, {token3}
|
||||
Open unrealized P&L: ${total_unrealized}
|
||||
─── Smart Money Score ──────────────────────
|
||||
Are their picks confirmed by other smart money? (check smart_degen_count on top holdings)
|
||||
─── Verdict ────────────────────────────────
|
||||
🟢 Worth following — strong win rate + consistent P&L + smart money overlap
|
||||
🟡 Watch first — promising stats but limited data or inconsistent style
|
||||
🔴 Not recommended — low win rate, losses, or high-risk behavior patterns
|
||||
```
|
||||
|
||||
## Related Workflows
|
||||
|
||||
- [`workflow-smart-money-profile.md`](workflow-smart-money-profile.md) — deeper behavior analysis: trading style, take-profit/stop-loss patterns, copy-trade ROI estimate, and leaderboard comparison
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.0.1",
|
||||
"version": "1.4.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.0.1",
|
||||
"version": "1.4.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^12.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gmgn-cli",
|
||||
"version": "1.0.1",
|
||||
"version": "1.4.1",
|
||||
"description": "GMGN OpenAPI CLI — call GMGN market, token, portfolio and swap APIs from the command line",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsx src/index.ts",
|
||||
"prepublishOnly": "npm run build",
|
||||
"prepublishOnly": "npm run build",
|
||||
"publish:provenance": "npm publish --provenance --access public"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -36,7 +36,7 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/gmgn-ai/gmgn-skills"
|
||||
"url": "https://github.com/GMGNAI/gmgn-skills"
|
||||
},
|
||||
"keywords": [
|
||||
"gmgn",
|
||||
|
||||
@@ -0,0 +1,652 @@
|
||||
---
|
||||
name: gmgn-cooking
|
||||
description: "[FINANCIAL EXECUTION] Create and launch meme coins and crypto tokens on launchpads (Pump.fun, FourMeme, Bonk, BAGS, Flap, Klik, Clanker, etc.) via bonding curve fair launch, or query token creation stats by launchpad via GMGN API. Requires explicit user confirmation. Use when user asks to create a token, launch a meme coin, cook a coin, deploy on a launchpad, or check launchpad creation stats on Solana, BSC, or Base."
|
||||
argument-hint: "stats | [create --chain <chain> --dex <dex> --from <addr> --name <name> --symbol <sym> --buy-amt <n> (--image <base64> | --image-url <url>)]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli cooking --help"
|
||||
---
|
||||
|
||||
**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.**
|
||||
|
||||
**⚠️ 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 create a token on a launchpad platform or query token creation statistics per launchpad. **Requires private key** (`GMGN_PRIVATE_KEY` in `.env`) for `cooking create`.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **Bonding curve** — Most launchpad platforms (Pump.fun, FourMeme, Flap, etc.) launch tokens on an internal bonding curve. The token price rises as buyers enter. Once the threshold is reached, the token "graduates" to an open DEX (e.g. Raydium on SOL, PancakeSwap on BSC). Token creation happens on the bonding curve — not the open market.
|
||||
|
||||
- **`--buy-amt` is in human units** — `--buy-amt` is expressed in full native token units, not smallest unit. `0.01` = 0.01 SOL. `0.05` = 0.05 BNB. Always confirm the human-readable amount with the user before executing.
|
||||
|
||||
- **`--dex` identifiers** — Each launchpad has a fixed identifier passed to `--dex`. These are not free-form names — use only the identifiers listed in the Supported Launchpads table. Never guess a `--dex` value not in that table.
|
||||
|
||||
- **Image input** — Token logo can be provided as base64-encoded data (`--image`, max 2MB decoded) or a publicly accessible URL (`--image-url`). Provide one or the other — not both. If the user gives a file path, read and base64-encode it before passing to `--image`. If they give a URL, use `--image-url` directly.
|
||||
|
||||
- **Status polling via `order get`** — `cooking create` is asynchronous. The immediate response may show `pending`. Poll with `gmgn-cli order get --chain <chain> --order-id <order_id>` until `confirmed`. The new token's contract address is in the `report.output_token` field of the `order get` response, not in the initial create response.
|
||||
|
||||
- **Signed auth** — `cooking create` requires both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing. `cooking stats` uses exist auth (API Key only).
|
||||
|
||||
- **Slippage** — The initial buy is executed as part of the same transaction as token creation. Slippage applies to that buy. Use `--slippage` (decimal, e.g. `0.01` = 1%) or `--auto-slippage`. One of the two is required when `--buy-amt` is set.
|
||||
|
||||
## Financial Risk Notice
|
||||
|
||||
**This skill executes REAL, IRREVERSIBLE blockchain transactions.**
|
||||
|
||||
- Every `cooking create` command deploys an on-chain token contract and spends real funds (initial buy amount).
|
||||
- Token deployments cannot be undone once confirmed on-chain.
|
||||
- The AI agent must **never auto-execute a create** — explicit user confirmation is required every time, without exception.
|
||||
- Only use this skill with funds you are willing to spend. Initial buy amounts are non-refundable.
|
||||
|
||||
## Sub-commands
|
||||
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `cooking stats` | Get token creation count statistics grouped by launchpad platform (exist auth) |
|
||||
| `cooking create` | Deploy a new token on a launchpad platform (signed auth) |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base`
|
||||
|
||||
## Supported Launchpads by Chain
|
||||
|
||||
| Chain | `--dex` values | Raise token (`--raised-token`) |
|
||||
| ------ | ---------------------- | ------------------------------ |
|
||||
| `sol` | `pump`, `bonk`, `bags` | `pump`: `""` (SOL) or `USDC`; `bonk`: `""` (SOL) or `USD1`; `bags`: `""` (SOL only) |
|
||||
| `bsc` | `fourmeme`, `flap` | `fourmeme`: `""` (BNB), `USD1`, `USDT`; `flap`: `""` (BNB only) |
|
||||
| `base` | `klik`, `clanker` | `""` only (quote token fixed to WETH) |
|
||||
|
||||
When the user names a platform colloquially (e.g. "pump.fun", "four.meme"), map it to the correct `--dex` identifier from this table before running the command.
|
||||
|
||||
**Anti-MEV** (`--anti-mev`) is only supported on `sol`. Passing it on `bsc` or `base` will return a 400 error.
|
||||
|
||||
### Quote Token conversion (when `--raised-token` is set)
|
||||
|
||||
`--buy-amt` is **always in native token units** (SOL / BNB / ETH), even when raising with a quote token like USDC / USD1 / USDT. If the user states the amount in the quote token, convert it to native yourself before passing it:
|
||||
|
||||
```
|
||||
buy_amt_in_native = quote_amount × quote_price / native_price
|
||||
```
|
||||
|
||||
This conversion applies to **`--buy-amt`, and the `buy_amt` field inside `--buy-wallets` and `--snip-buy-wallets`**. It does **not** apply to `--sell-configs` (`check_price` there is always a USD market cap, not a token amount). Round to the chain's native decimals. When `--raised-token` is empty/native, no conversion is needed.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `cooking stats`: Only `GMGN_API_KEY` required
|
||||
- `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=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second.
|
||||
|
||||
| Command | Weight |
|
||||
|---------|--------|
|
||||
| `cooking create` | 5 |
|
||||
| `cooking stats` | 1 |
|
||||
|
||||
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.
|
||||
|
||||
**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.
|
||||
- `GMGN_API_KEY` is transmitted in the `X-APIKEY` header over HTTPS.
|
||||
- Neither credential is ever passed as a command-line argument.
|
||||
|
||||
## `cooking stats` Usage
|
||||
|
||||
```bash
|
||||
gmgn-cli cooking stats [--raw]
|
||||
```
|
||||
|
||||
### `cooking stats` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `launchpad` | string | Launchpad identifier (e.g. `pump`, `bonk`, `fourmeme`) |
|
||||
| `token_count` | int | Number of tokens created via GMGN on that launchpad |
|
||||
|
||||
## `cooking create` Parameters
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | Chain: `sol` / `bsc` / `base` |
|
||||
| `--dex` | Yes | Launchpad platform identifier — see Supported Launchpads table. Never guess this value. |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--name` | Yes | Token full name (e.g. `Doge Killer`) |
|
||||
| `--symbol` | Yes | Token ticker symbol (e.g. `DOGEK`) |
|
||||
| `--buy-amt` | Yes | Initial buy amount in **human-readable native token units** (e.g. `0.01` = 0.01 SOL). This is NOT in smallest unit. |
|
||||
| `--image` | No* | Token logo as **base64-encoded** data (max 2MB decoded). Mutually exclusive with `--image-url`. One of the two is required. |
|
||||
| `--image-url` | No* | Token logo as a publicly accessible URL. Mutually exclusive with `--image`. One of the two is required. |
|
||||
| `--slippage` | No* | Slippage tolerance, e.g. `0.01` = 1%. **Mutually exclusive with `--auto-slippage`** — provide one or the other. |
|
||||
| `--auto-slippage` | No* | Enable automatic slippage. **Mutually exclusive with `--slippage`.** |
|
||||
| `--description` | No | Token description / project pitch |
|
||||
| `--website` | No | Project website URL |
|
||||
| `--twitter` | No | Twitter / X URL |
|
||||
| `--telegram` | No | Telegram group URL |
|
||||
| `--fee` | No | Base gas / fee |
|
||||
| `--priority-fee` | No | Priority fee in SOL (**SOL only**, ≥ 0.0001 SOL) |
|
||||
| `--tip-fee` | No | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB; ignored on BASE) |
|
||||
| `--gas-price` | No | Gas price in wei (EVM chains: BSC / BASE) |
|
||||
| `--max-fee-per-gas` | No | Max fee per gas in wei (**EVM only**) |
|
||||
| `--max-priority-fee-per-gas` | No | Max priority fee per gas in wei (**EVM only**) |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection (**SOL only**; rejected on BSC / BASE) |
|
||||
| `--anti-mev-mode` | No | Anti-MEV mode: `off` / `normal` / `secure` (**SOL only**) |
|
||||
| `--raised-token` | No | Raise token symbol. `pump`: `USDC`; `bonk`: `USD1`; `fourmeme`: `USDT` / `USD1`; omit or `""` for native |
|
||||
| `--dev-wallet-bps` | No | Dev wallet fee share in basis points (100 = 1%) |
|
||||
| `--dev-gas` | No | Dev gas amount |
|
||||
| `--dev-priority` | No | Dev priority fee |
|
||||
| `--dev-tip` | No | Dev tip fee |
|
||||
| `--dev-max-fee-per-gas` | No | Dev tx feeCap in wei (**EVM EIP-1559**) |
|
||||
| `--approve-vision` | No | Approve vision version: `v1` / `v2` (default: `v2`) |
|
||||
| `--source` | No | Traffic source identifier |
|
||||
| `--is-mayhem` | No | Enable Mayhem mode (**Pump.fun only**) |
|
||||
| `--is-cashback` | No | Enable Cashback (**Pump.fun only**) |
|
||||
| `--is-buy-back` | No | Enable Agent Auto Buyback (**Pump.fun only**) |
|
||||
| `--pump-fee-share-list` | No | Pump.fun fee share list as JSON array: `[{"provider":"twitter","username":"<handle>","basic_points":<n>}]` (**Pump.fun only**) |
|
||||
| `--flap-rate-conf` | No | Flap rate config as JSON object (**Flap only**) |
|
||||
| `--fourmeme-rate-conf` | No | FourMeme rate config as JSON object (**FourMeme only**) |
|
||||
| `--bags-fee-share-list` | No | BAGS fee share list as JSON array: `[{"provider":"twitter","username":"<handle>","basic_points":<n>}]` (**BAGS only**) |
|
||||
| `--bonk-model` | No | Bonk model identifier (**bonk DEX only**) |
|
||||
| `--buy-wallets` | No | Multi-wallet buy config as JSON array: `[{"from_address":"<addr>","buy_amt":"<n>"}]` |
|
||||
| `--snip-buy-wallets` | No | Snipe-buy wallet config as JSON array: `[{"from_address":"<addr>","buy_amt":"<n>"}]` |
|
||||
| `--interval-seconds` | No | Interval between multi-wallet buys in seconds |
|
||||
| `--buy-trade-config` | No | Buy-side trade config for CondMarket orders as JSON (TradeParam) — see Advanced API Fields |
|
||||
| `--sell-trade-config` | No | Sell-side trade config for auto-sell / pending_sell as JSON (TradeParam) — see Advanced API Fields |
|
||||
| `--sell-configs` | No | Auto-sell strategy list as JSON array (CookingSellConfig[]) — see Auto-Sell Configuration |
|
||||
|
||||
\* `--image` or `--image-url`: provide exactly one. `--slippage` or `--auto-slippage`: provide exactly one.
|
||||
|
||||
## Advanced API Fields
|
||||
|
||||
The structured flags (`--pump-fee-share-list`, `--bags-fee-share-list`, `--flap-rate-conf`, `--fourmeme-rate-conf`, `--buy-wallets`, `--snip-buy-wallets`, `--buy-trade-config`, `--sell-trade-config`, `--sell-configs`) each accept a **JSON string**. This section documents the exact JSON schema for each.
|
||||
|
||||
### Platform capability matrix
|
||||
|
||||
Which advanced features each platform supports. Do not send a field a platform does not support.
|
||||
|
||||
| Platform | `--dex` | Chain | Platform-specific fields | Bundle (`--buy-wallets`) | Sniper (`--snip-buy-wallets`) | Cashback | Mayhem |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| Pump.fun | `pump` | SOL | `--pump-fee-share-list` / `--dev-wallet-bps` / `--is-buy-back` | ✅ up to 12 wallets | ✅ up to 10 | ✅ | ✅ |
|
||||
| Bonk | `bonk` | SOL | `--bonk-model` | ❌ | ✅ up to 10 | ❌ | ❌ |
|
||||
| BAGS | `bags` | SOL | `--bags-fee-share-list` / `--dev-wallet-bps` | ❌ | ✅ up to 10 | ❌ | ❌ |
|
||||
| FourMeme | `fourmeme` | BSC | `--fourmeme-rate-conf` | ✅ up to 3 wallets | ✅ up to 10 | ❌ | ❌ |
|
||||
| Flap | `flap` | BSC | `--flap-rate-conf` | ❌ | ✅ up to 10 | ❌ | ❌ |
|
||||
| Klik | `klik` | Base | — | ❌ | ✅ up to 10 | ❌ | ❌ |
|
||||
| Clanker | `clanker` | Base | — | ❌ | ✅ up to 10 | ❌ | ❌ |
|
||||
|
||||
- `--is-cashback` / `--is-mayhem` are **Pump.fun only** — other platforms reject them.
|
||||
- Bundle/auto-sell (`--sell-configs`) and sniper (`--snip-buy-wallets`) are available where the matrix shows ✅.
|
||||
|
||||
**Basis-points rule:** any field named `*_bps` / `basic_points` is in basis points (`100` = 1%). Where a section says the shares must sum, all entries must add up to exactly **10000** (FourMeme uses whole percents summing to **100** instead — see below).
|
||||
|
||||
**Always talk to the user in percentages, never basis points.** When asking for or confirming any share, fee, or split, phrase it as a percentage (e.g. *"What % goes to this wallet?"* → user says `"50%"`). Convert to the field's unit yourself when building the JSON — never ask the user for a raw bps number:
|
||||
|
||||
| User says | `*_bps` field (×100) | FourMeme `*_rate` field (×1) |
|
||||
|---|---|---|
|
||||
| `5%` | `500` | `5` |
|
||||
| `50%` | `5000` | `50` |
|
||||
| `100%` | `10000` | `100` |
|
||||
|
||||
Never set a fee-share split without the user's explicit instruction — it permanently routes token revenue to the listed accounts.
|
||||
|
||||
### Pump.fun (`--dex pump`)
|
||||
|
||||
> `is_mayhem`, `is_cashback`, `is_buy_back` use their matching CLI flags (`--is-mayhem`, `--is-cashback`, `--is-buy-back`). `pump_fee_share_list` is passed via `--pump-fee-share-list`.
|
||||
|
||||
| Field | CLI flag | Description |
|
||||
|---|---|---|
|
||||
| `pump_fee_share_list` | `--pump-fee-share-list <json>` | Fee-share list — see JSON schema below |
|
||||
| `is_buy_back` | `--is-buy-back` | Enable Agent Auto Buyback |
|
||||
|
||||
**JSON schema for `--pump-fee-share-list`** — array of objects:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `provider` | string | Yes | `solana` / `twitter` / `github` |
|
||||
| `username` | string | Yes | Platform username; a SOL address when `provider` = `solana` |
|
||||
| `basic_points` | int | Yes | Share in bps — all entries must sum to **10000** |
|
||||
|
||||
Example: `--pump-fee-share-list '[{"provider":"twitter","username":"handle","basic_points":10000}]'`
|
||||
|
||||
### Bonk (`--dex bonk`)
|
||||
|
||||
`dev_wallet_bps` → `--dev-wallet-bps`, `bonk_model` → `--bonk-model`. No additional structured fields.
|
||||
|
||||
### BAGS (`--dex bags`)
|
||||
|
||||
`dev_wallet_bps` → `--dev-wallet-bps`. `bags_fee_share_list` is passed via `--bags-fee-share-list`.
|
||||
|
||||
**JSON schema for `--bags-fee-share-list`** — array of objects:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `provider` | string | Yes | `twitter` / `solana` / `kick` / `github` |
|
||||
| `username` | string | Yes | Platform username |
|
||||
| `basic_points` | int | Yes | Share in bps — combined with `dev_wallet_bps`, all must sum to **10000** |
|
||||
|
||||
### Flap (`--dex flap`)
|
||||
|
||||
`flap_rate_conf` is passed via `--flap-rate-conf`.
|
||||
|
||||
**JSON schema for `--flap-rate-conf`** — single object:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `beneficiary` | string | Yes | Fee recipient address |
|
||||
| `tax_rate` | int | Conditional | V5 unified tax rate in bps, e.g. 5% → `500` |
|
||||
| `buy_tax_rate` | int | Conditional | V6 separate buy tax rate in bps |
|
||||
| `sell_tax_rate` | int | Conditional | V6 separate sell tax rate in bps |
|
||||
| `mkt_bps` | int | Yes | Marketing / donation fund share |
|
||||
| `deflation_bps` | int | Yes | Burn (supply-reduction) share |
|
||||
| `dividend_bps` | int | Yes | Dividend (holder-reward) share |
|
||||
| `lp_bps` | int | Yes | Liquidity share |
|
||||
| `minimum_share_balance` | int | Yes | Min holding to qualify for dividends — minimum **10000** tokens |
|
||||
| `recipient_type` | string | Yes | `split` (proportional) / `gift` |
|
||||
| `twitter_account` | string | Yes | Twitter username |
|
||||
| `split_conf` | array | Yes | Split list — see below |
|
||||
|
||||
`split_conf` entries: `{ "recipient": "<address>", "bps": <n> }` — all `bps` must sum to **10000**.
|
||||
|
||||
> - Use `tax_rate` for V5 (unified rate); use `buy_tax_rate` + `sell_tax_rate` for V6 (separate rates).
|
||||
> - When the tax rate > 0: `mkt_bps + deflation_bps + dividend_bps + lp_bps` must sum to **10000**. When `lp_bps > 0`: `minimum_share_balance` must be > 0.
|
||||
|
||||
### FourMeme (`--dex fourmeme`)
|
||||
|
||||
`fourmeme_rate_conf` is passed via `--fourmeme-rate-conf`.
|
||||
|
||||
> `fourmeme_user_login_sign`, `is_approve_allowance`, `is_raised_swap` are broker/jobs **internal** fields — the public API does not accept them, so there is no flag. The multi-quote raise-token retry is handled server-side automatically (poll `order get`); the caller never sets these.
|
||||
|
||||
**JSON schema for `--fourmeme-rate-conf`** — single object:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `fee_plan` | bool | No | Enable the fee plan |
|
||||
| `recipient_address` | string | Yes | Fee recipient address |
|
||||
| `fee_rate` | int | Yes | Fee rate, e.g. 5% → `5` (whole percent, not bps) |
|
||||
| `burn_rate` | int | Yes | Burn share |
|
||||
| `divide_rate` | int | Yes | Dividend share |
|
||||
| `liquidity_rate` | int | Yes | Liquidity share |
|
||||
| `recipient_rate` | int | Yes | Recipient share |
|
||||
| `min_sharing` | int | Yes | Minimum sharing threshold |
|
||||
|
||||
> When `fee_rate > 0`: `burn_rate + divide_rate + liquidity_rate + recipient_rate` must sum to **100**. When `recipient_rate > 0`: `min_sharing` must be > 0.
|
||||
|
||||
## Auto-Sell Configuration
|
||||
|
||||
`sell_configs` is passed via `--sell-configs` as a JSON array. It schedules conditional sell orders to execute automatically once the token launch succeeds. Omit entirely for a standard launch with no auto-sell.
|
||||
|
||||
`--sell-configs` is a JSON array of `CookingSellConfig` objects:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `sell_type` | string | Yes | `delay_sell` / `limit_order` |
|
||||
| `delay_sec` | int64 | Conditional | Seconds after buy to trigger; required when `sell_type = delay_sell` |
|
||||
| `delay_mili_sec` | int64 | No | Milliseconds after buy to trigger; takes precedence over `delay_sec` |
|
||||
| `sell_ratio` | string | Yes | Fraction to sell — `"1"` = 100%, `"0.5"` = 50% |
|
||||
| `check_price` | string | Conditional | Market cap in USD to trigger sell; required when `sell_type = limit_order` |
|
||||
| `wallet_addresses` | []string | Yes | Wallets this strategy applies to (empty array = inert) |
|
||||
|
||||
Example: `--sell-configs '[{"sell_type":"delay_sell","delay_sec":60,"sell_ratio":"0.5","wallet_addresses":["<addr>"]}]'`
|
||||
|
||||
The buy/sell execution params for these CondMarket orders (slippage, fees, anti-MEV) can be tuned separately via `--buy-trade-config` / `--sell-trade-config` (TradeParam JSON). They do **not** affect the main creation tx, and fall back to the outer-level transaction flags when omitted.
|
||||
|
||||
> - **`check_price` is total market cap in USD** — e.g. `"50000"` triggers at a $50,000 market cap.
|
||||
> - `wallet_addresses` may mix `from_address` and `buy_wallets` entries. The server creates `signal_cooking` for snipe wallets and `pending_sell` for main/bundle wallets automatically.
|
||||
> - A wallet can carry multiple strategies (e.g. delay-sell 50%, then limit-sell the rest); each applies independently.
|
||||
|
||||
### TradeParam (`--buy-trade-config` / `--sell-trade-config`)
|
||||
|
||||
These tune the **execution params for the CondMarket buy/sell orders** (bundle buys, sniper buys, and auto-sell). They do **not** affect the main creation transaction (the dev tx uses the outer-level `--dev-*` flags). When omitted, they fall back to the outer-level transaction flags.
|
||||
|
||||
`--buy-trade-config` / `--sell-trade-config` each accept a single JSON object:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `slippage` | number | Slippage; only sent when truthy |
|
||||
| `fee` | string | Base gas / fee; only sent when truthy |
|
||||
| `priority_fee` | string | Priority fee; only sent when truthy |
|
||||
| `tip_fee` | string | SOL Jito tip; only sent when truthy |
|
||||
| `gas_price` | string | Gas price in wei (EVM); only sent when truthy |
|
||||
| `max_priority_fee_per_gas` | string | EVM EIP-1559; only sent when truthy |
|
||||
| `max_fee_per_gas` | string | EVM EIP-1559; only sent when truthy |
|
||||
| `auto_slippage` | bool | Always sent |
|
||||
| `is_anti_mev` | bool | Always sent |
|
||||
| `anti_mev_mode` | string | `off` / `normal` / `secure`; always sent |
|
||||
|
||||
Example: `--buy-trade-config '{"slippage":50,"auto_slippage":false,"priority_fee":"0.0005","tip_fee":"0.0001","is_anti_mev":true,"anti_mev_mode":"secure"}'`
|
||||
|
||||
> A standard launch with no `buyConfig` sends `{"is_anti_mev":false,"anti_mev_mode":"off"}` and an empty `buy_wallets` list.
|
||||
|
||||
## `cooking create` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `status` | string | `pending` / `confirmed` / `failed` |
|
||||
| `hash` | string | Transaction hash (may be empty while `pending`) |
|
||||
| `order_id` | string | Order ID — pass to `gmgn-cli order get` to poll for final status |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `error_status` | string | Error description on failure |
|
||||
|
||||
## Status Polling
|
||||
|
||||
Token creation is **asynchronous**. If the initial `cooking create` response shows `status: pending`:
|
||||
|
||||
1. Poll with `gmgn-cli order get` every **2 seconds**, up to **30 seconds**:
|
||||
```bash
|
||||
gmgn-cli order get --chain <chain> --order-id <order_id>
|
||||
```
|
||||
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.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```bash
|
||||
# Get token creation statistics per launchpad
|
||||
gmgn-cli cooking stats
|
||||
|
||||
# Create a token on Pump.fun (SOL) — with URL image
|
||||
gmgn-cli cooking create \
|
||||
--chain sol \
|
||||
--dex pump \
|
||||
--from <wallet_address> \
|
||||
--name "My Token" \
|
||||
--symbol MAT \
|
||||
--buy-amt 0.01 \
|
||||
--image-url https://example.com/logo.png \
|
||||
--slippage 0.01 \
|
||||
--priority-fee 0.001
|
||||
|
||||
# Create a token on FourMeme (BSC) — base64 image + USD1 raise token
|
||||
gmgn-cli cooking create \
|
||||
--chain bsc \
|
||||
--dex fourmeme \
|
||||
--from <wallet_address> \
|
||||
--name "Four Token" \
|
||||
--symbol FOUR \
|
||||
--buy-amt 0.05 \
|
||||
--image "$(base64 -i /path/to/logo.png)" \
|
||||
--auto-slippage \
|
||||
--raised-token USD1
|
||||
|
||||
# Create a token on Bonk (SOL) with anti-MEV
|
||||
gmgn-cli cooking create \
|
||||
--chain sol \
|
||||
--dex bonk \
|
||||
--from <wallet_address> \
|
||||
--name "Bonk Token" \
|
||||
--symbol BNKT \
|
||||
--buy-amt 0.01 \
|
||||
--image-url https://example.com/logo.png \
|
||||
--auto-slippage \
|
||||
--anti-mev
|
||||
|
||||
# Create on Pump.fun with auto-sell: sell 50% 60s after buy
|
||||
gmgn-cli cooking create \
|
||||
--chain sol \
|
||||
--dex pump \
|
||||
--from <wallet_address> \
|
||||
--name "My Token" \
|
||||
--symbol MAT \
|
||||
--buy-amt 0.01 \
|
||||
--image-url https://example.com/logo.png \
|
||||
--auto-slippage \
|
||||
--sell-configs '[{"sell_type":"delay_sell","delay_sec":60,"sell_ratio":"0.5","wallet_addresses":["<wallet_address>"]}]'
|
||||
```
|
||||
|
||||
### Full worked examples
|
||||
|
||||
These mirror real launch configurations end-to-end. Copy and adapt — every JSON flag below is a valid payload shape.
|
||||
|
||||
**Pump.fun (SOL) — Bundle + Sniper + Auto-Sell + Agent Auto Buyback**
|
||||
|
||||
```bash
|
||||
gmgn-cli cooking create \
|
||||
--chain sol \
|
||||
--dex pump \
|
||||
--from DevWallet... \
|
||||
--name "Demo Coin" \
|
||||
--symbol DEMO \
|
||||
--buy-amt 0.5 \
|
||||
--image-url https://cdn.example.com/coin.png \
|
||||
--twitter https://x.com/handle/status/123 \
|
||||
--priority-fee 0.0005 \
|
||||
--tip-fee 0.0001 \
|
||||
--is-buy-back \
|
||||
--buy-trade-config '{"slippage":50,"auto_slippage":false,"priority_fee":"0.0005","tip_fee":"0.0001","is_anti_mev":true,"anti_mev_mode":"secure"}' \
|
||||
--buy-wallets '[{"from_address":"Wallet1...","buy_amt":"0.1"},{"from_address":"Wallet2...","buy_amt":"0.1"}]' \
|
||||
--snip-buy-wallets '[{"from_address":"Sniper1...","buy_amt":"0.05"}]' \
|
||||
--sell-configs '[{"sell_type":"delay_sell","sell_ratio":"1","wallet_addresses":["Wallet1..."],"delay_mili_sec":5000}]'
|
||||
```
|
||||
|
||||
- `--is-buy-back` is the Agent Auto Buyback mode (the backend also sets the agent fee internally).
|
||||
- `buy_amt` values in `--buy-wallets` / `--snip-buy-wallets` are in native SOL.
|
||||
- Bundle wallets ≤ 12, sniper wallets ≤ 10 on Pump.fun (see capability matrix).
|
||||
|
||||
**FourMeme (BSC) — user fee split + raise token USDT**
|
||||
|
||||
```bash
|
||||
gmgn-cli cooking create \
|
||||
--chain bsc \
|
||||
--dex fourmeme \
|
||||
--from 0xDev... \
|
||||
--name "Demo BSC" \
|
||||
--symbol DBSC \
|
||||
--buy-amt 0.0123 \
|
||||
--image-url https://cdn.example.com/coin.png \
|
||||
--raised-token USDT \
|
||||
--website https://demo.com \
|
||||
--gas-price 1000000000 \
|
||||
--auto-slippage \
|
||||
--fourmeme-rate-conf '{"fee_rate":1,"recipient_rate":50,"burn_rate":20,"divide_rate":20,"liquidity_rate":10,"min_sharing":100000,"recipient_address":"0xDev..."}'
|
||||
```
|
||||
|
||||
- `--buy-amt 0.0123` is **already converted to native BNB** from the USDT amount the user wanted (see Quote Token conversion). Do the conversion before building the command.
|
||||
- `--gas-price 1000000000` is wei (1 Gwei).
|
||||
- In `--fourmeme-rate-conf`, `recipient_rate + burn_rate + divide_rate + liquidity_rate` must sum to **100**.
|
||||
|
||||
## Output Format
|
||||
|
||||
### Pre-create Confirmation
|
||||
|
||||
Before every `cooking create`, present this summary and wait for explicit user confirmation:
|
||||
|
||||
```
|
||||
⚠️ Token Creation Confirmation Required
|
||||
|
||||
Chain: {chain}
|
||||
Platform: {--dex} (e.g. pump / fourmeme)
|
||||
Wallet: {--from}
|
||||
Token Name: {--name}
|
||||
Symbol: {--symbol}
|
||||
Initial Buy: {--buy-amt} {native currency} (e.g. 0.01 SOL)
|
||||
Slippage: {--slippage}% (or "auto")
|
||||
Image: {--image-url or "base64 provided"}
|
||||
Social: {twitter / telegram / website if provided}
|
||||
Modes: {Mayhem / Cashback / Agent Auto Buyback if set, else "none"}
|
||||
Fee Share: {recipient → % list if set, else "none"}
|
||||
Auto-Sell: {sell_configs summary if set, else "none"}
|
||||
|
||||
Reply "confirm" to deploy this token. This action is IRREVERSIBLE.
|
||||
```
|
||||
|
||||
Omit the Modes / Fee Share / Auto-Sell lines if none were configured — or show them as `none` — but if any **are** set, they MUST appear here so the user re-confirms them explicitly.
|
||||
|
||||
### Post-create Receipt
|
||||
|
||||
After polling confirms a successful deployment:
|
||||
|
||||
```
|
||||
✅ Token Created
|
||||
|
||||
Token: {--name} ({--symbol})
|
||||
Address: {report.output_token from order get}
|
||||
Chain: {chain}
|
||||
Platform: {--dex}
|
||||
Tx: {explorer link for hash}
|
||||
Order ID: {order_id}
|
||||
```
|
||||
|
||||
Block explorer links:
|
||||
|
||||
| Chain | Explorer |
|
||||
|-------|----------|
|
||||
| sol | `https://solscan.io/tx/<hash>` |
|
||||
| bsc | `https://bscscan.com/tx/<hash>` |
|
||||
| base | `https://basescan.org/tx/<hash>` |
|
||||
|
||||
## Guided Launch Flow
|
||||
|
||||
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?"*
|
||||
|
||||
Show the options concisely:
|
||||
|
||||
| Chain | Platform | `--dex` |
|
||||
| ------ | ---------- | ---------- |
|
||||
| Solana | Pump.fun | `pump` |
|
||||
| Solana | Bonk | `bonk` |
|
||||
| Solana | BAGS | `bags` |
|
||||
| BSC | FourMeme | `fourmeme` |
|
||||
| BSC | Flap | `flap` |
|
||||
| Base | Klik | `klik` |
|
||||
| Base | Clanker | `clanker` |
|
||||
|
||||
If the user is unsure, recommend: **Pump.fun (SOL)** or **FourMeme (BSC)**.
|
||||
|
||||
The chosen platform determines which advanced options are available later in Step 7 (e.g. Mayhem/Cashback/Agent Auto Buyback on Pump.fun, fee-share splits on BAGS/Flap/FourMeme). Note the platform now; do not ask about advanced options yet.
|
||||
|
||||
### Step 2 — Token Name
|
||||
|
||||
Ask: *"Token name?"*
|
||||
|
||||
Wait for the user's reply (e.g. `Doge Killer`).
|
||||
|
||||
### Step 3 — Token Symbol
|
||||
|
||||
Ask: *"Ticker symbol?"*
|
||||
|
||||
Wait for the user's reply (e.g. `DOGEK`). Typically 3–8 uppercase characters.
|
||||
|
||||
### Step 4 — Logo
|
||||
|
||||
Ask: *"Logo image? (file path or URL — skip to launch without one)"*
|
||||
|
||||
- **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} for the initial buy?"*
|
||||
|
||||
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 — 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 — Platform Modes, Fees & Auto-Sell (platform-dependent)
|
||||
|
||||
After the basics are collected, ask **once** whether the user wants any advanced options for the platform they chose. Default everyone to a plain fair launch — only configure these when the user explicitly asks. Tailor the question to the selected platform; do not list options that don't apply to it.
|
||||
|
||||
Ask: *"Want any advanced options, or launch with defaults? (reply 'defaults' to skip)"* — then offer the relevant subset.
|
||||
|
||||
**Phrase the question around the platform the user picked — only ask about modes that exist on that platform.** For example, on **Pump.fun** ask specifically:
|
||||
- *"Enable Cashback mode?"* (`--is-cashback`)
|
||||
- *"Enable Agent Auto Buyback mode?"* (`--is-buy-back`)
|
||||
- *"Enable Mayhem mode?"* (`--is-mayhem`)
|
||||
- *"Set up a fee-share split?"* (`--pump-fee-share-list`)
|
||||
- *"Want me to remember these advanced settings for your next launch?"* — if yes, save them to memory so future launches can pre-fill the same choices.
|
||||
|
||||
Bonk / BAGS / Flap / FourMeme have **no mode toggles** — for those, skip the mode questions and only ask about fee-share split and auto-sell.
|
||||
|
||||
The relevant options per platform:
|
||||
|
||||
- **Pump.fun modes** — Mayhem (`--is-mayhem`), Cashback (`--is-cashback`), Agent Auto Buyback (`--is-buy-back`).
|
||||
- **Fee-share split** — Pump.fun (`--pump-fee-share-list`), BAGS (`--dev-wallet-bps` + `--bags-fee-share-list`), Bonk (`--dev-wallet-bps`), Flap (`--flap-rate-conf`), FourMeme (`--fourmeme-rate-conf`). See [Advanced API Fields](#advanced-api-fields) for JSON schemas. **Warn the user this permanently routes token revenue to the listed accounts.** Always ask the user for shares as percentages — convert to bps yourself. Shares must add up to 100%.
|
||||
- **Auto-sell** — `--sell-configs` (JSON): delay-sell (sell a fraction N seconds after the buy) and/or limit-sell (sell once market cap hits a USD target). See [Auto-Sell Configuration](#auto-sell-configuration). Confirm the sell ratio and trigger before setting it.
|
||||
|
||||
If the user says "defaults" / "skip" / "none", proceed with none of these set.
|
||||
|
||||
### Step 8 — 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. If any advanced options from Step 7 were set, they MUST appear in the summary so the user re-confirms them explicitly.
|
||||
|
||||
---
|
||||
|
||||
## Execution Guidelines
|
||||
|
||||
- **[REQUIRED] Pre-create confirmation** — Before executing `cooking create`, present the full summary above and receive explicit "confirm" from the user. No exceptions. Do NOT auto-create.
|
||||
- **[REQUIRED] `--dex` validation** — Before running, look up the user's named platform in the Supported Launchpads table and resolve to the correct `--dex` identifier. Never guess or pass a freeform platform name. If the chain/platform combination is not in the table, tell the user it is unsupported.
|
||||
- **Slippage requirement** — Either `--slippage` or `--auto-slippage` must be provided. If the user did not specify, suggest `--auto-slippage` for volatile new tokens or ask for a preference.
|
||||
- **Image handling** — If the user provides a file path, run `base64 -i <path>` and pass the result to `--image`. If they provide a URL, use `--image-url`. If neither is provided, ask before building the confirmation — most platforms require a logo.
|
||||
- **Fee-share / bps inputs** — Always collect and confirm shares as percentages with the user; convert to basis points yourself (50% → `5000`). Never ask for a raw bps value.
|
||||
- **Address validation** — Validate `--from` wallet address format before submitting:
|
||||
- `sol`: base58, 32–44 characters
|
||||
- `bsc` / `base`: `0x` + 40 hex digits
|
||||
- **Chain-wallet compatibility** — SOL addresses are incompatible with EVM chains and vice versa. Warn the user and abort if the address format does not match the chain.
|
||||
- **Order polling** — After `cooking create`, if `status` is `pending`, poll `order get` every 2 seconds up to 30 seconds. The token address is in `report.output_token`. Do not report success until `status` is `confirmed`.
|
||||
- **Credential sensitivity** — `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` can execute real transactions. Never log, display, or expose these values.
|
||||
|
||||
## Notes
|
||||
|
||||
- `cooking create` uses **signed auth** (API Key + signature) — CLI handles signing automatically.
|
||||
- `cooking stats` uses exist auth (API Key only — no private key needed).
|
||||
- The new token's mint address is in `report.output_token` from `gmgn-cli order get`, not in the initial `cooking create` response.
|
||||
- Use `--raw` on any command to get single-line JSON for further processing.
|
||||
|
||||
## References
|
||||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| [gmgn-swap](https://github.com/GMGNAI/gmgn-skills/tree/main/skills/gmgn-swap) | Contains `order get` command used for polling token creation status |
|
||||
| [gmgn-token](https://github.com/GMGNAI/gmgn-skills/tree/main/skills/gmgn-token) | Token security check, info, holders, and traders — useful after launch to monitor your token |
|
||||
| [gmgn-market](https://github.com/GMGNAI/gmgn-skills/tree/main/skills/gmgn-market) | `market trenches` for tracking bonding curve progress; `market trending` to see if your token is gaining traction |
|
||||
| [gmgn-track](https://github.com/GMGNAI/gmgn-skills/tree/main/skills/gmgn-track) | Smart money and KOL trade tracking — monitor whether smart wallets are buying your token after launch |
|
||||
| [gmgn-portfolio](https://github.com/GMGNAI/gmgn-skills/tree/main/skills/gmgn-portfolio) | Wallet holdings and P&L — check your own wallet balance before deciding on `--buy-amt` |
|
||||
@@ -1,56 +1,157 @@
|
||||
---
|
||||
name: gmgn-market
|
||||
description: Query GMGN market data — token K-line (candlestick) and trending token swap data. Supports sol / bsc / base.
|
||||
argument-hint: "kline --chain <sol|bsc|base> --address <token_address> --resolution <1m|5m|15m|1h|4h|1d> [--from <unix_ts>] [--to <unix_ts>] | trending --chain <sol|bsc|base> --interval <1h|3h|6h|24h>"
|
||||
description: Get crypto and meme token price charts (K-line, candlestick, OHLCV), trending meme coin rankings by volume, and newly launched tokens on launchpads (pump.fun, fourmeme, letsbonk, Raydium, etc.) via GMGN API on Solana, BSC, Base, or Ethereum. Use when user asks for price chart, trending tokens, what's pumping, hot coins, new launches, token signals, or wants to discover early-stage opportunities.
|
||||
argument-hint: "kline --chain <sol|bsc|base|eth> --address <token_address> --resolution <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> | signal --chain <sol|bsc>"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli market --help"
|
||||
---
|
||||
|
||||
Use the `gmgn-cli` tool to query K-line data for a token or browse trending tokens.
|
||||
**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.**
|
||||
|
||||
**⚠️ 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 query K-line data for a token, browse trending tokens, or view Trenches token lists.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **`--filter` chain defaults** — SOL and EVM chains have different default safety filters that are applied automatically when `--filter` is omitted. Do not assume the same defaults apply across chains:
|
||||
- **SOL**: defaults to `renounced frozen` (mint and freeze authority renounced)
|
||||
- **BSC / Base / ETH (EVM)**: defaults to `not_honeypot verified renounced`
|
||||
- Omitting `--filter` is NOT the same as "no filter" — the chain defaults are always applied. To use a custom filter set, explicitly specify all desired filter tags.
|
||||
|
||||
- **`volume` vs `amount` (kline)** — Naming is counterintuitive. `volume` = USD dollar value of trades; `amount` = token units traded. For a token priced at $0.0002, these differ by 5,000×. Always use `volume` for "how much USD was traded" and `amount` for "how many tokens changed hands."
|
||||
|
||||
- **`rug_ratio`** — A 0–1 score estimating rug pull likelihood. Values above `0.3` are high-risk. Do not treat as binary — combine with `top_10_holder_rate`, `dev_team_hold_rate`, and `is_honeypot` for a full picture.
|
||||
|
||||
- **`smart_degen_count` / `renowned_count`** — Number of platform-tagged smart money wallets (`smart_degen`) and KOL wallets (`renowned`) holding or trading this token. High values are bullish signals. These are GMGN-tagged wallet lists, not user-defined.
|
||||
|
||||
- **`hot_level`** — Trending intensity score. Higher = more actively traded right now. Not normalized — compare relative values within the same result set, not across time windows.
|
||||
|
||||
- **`renounced_mint` / `renounced_freeze_account`** — SOL-specific. Indicate whether the creator gave up the ability to mint more tokens or freeze wallets. Both being `1` is a safety baseline on Solana. Always `false` on EVM chains (concept does not apply).
|
||||
|
||||
- **`is_honeypot`** — EVM-specific (BSC / Base). Indicates whether the token contract prevents selling. Always empty/null on SOL — do not interpret an empty value as "not a honeypot" on Solana.
|
||||
|
||||
- **`creator_token_status`** — Dev holding status. `creator_hold` = dev still holds tokens (sell pressure risk). `creator_close` = dev has sold or burned their allocation (exit signal confirmed).
|
||||
|
||||
- **`cto_flag`** — Community Takeover flag. `1` = original dev abandoned the project and a community group took over marketing/development. Neutral to positive signal; evaluate in context.
|
||||
|
||||
- **Trenches categories** — Three lifecycle stages of launchpad tokens: `new_creation` (just created, still on bonding curve), `near_completion` (bonding curve nearly full, about to graduate), `completed` (graduated to open market / DEX). In the response, `near_completion` is always returned under the key `data.pump` regardless of the input `--type`.
|
||||
|
||||
- **`wash_trading` / `rat_trader_amount_rate` / `bundler_rate`** — Risk signals for artificial activity. `is_wash_trading` = coordinated fake volume detected. `rat_trader_amount_rate` = ratio of insider/sneak trading. `bundler_rate` = ratio of bot-bundled buys at launch. High values (> 0.3) suggest manipulated price action.
|
||||
|
||||
## Sub-commands
|
||||
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `market kline` | Token candlestick data |
|
||||
| `market trending` | Trending token swap data |
|
||||
| `market kline` | Token candlestick / OHLCV data and trading volume over a time range |
|
||||
| `market trending` | Trending tokens ranked by swap activity — use `--interval` to specify the time window (e.g. `1m` for 1-minute hottest, `1h` for 1-hour trending) |
|
||||
| `market trenches` | Newly launched launchpad platform tokens — **use this when the user asks for "new tokens", "just launched tokens", "latest tokens on pump.fun/letsbonk"**. Three categories: `new_creation` (just created), `near_completion` (bonding curve almost full), `completed` (graduated to open market / DEX) |
|
||||
| `market signal` | Real-time token signal feed — price spikes, smart money buys, large buys, Dex ads, CTO events, and more. Results sorted by `trigger_at` descending. **sol / bsc only. Max 50 results per group.** |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base`
|
||||
`sol` / `bsc` / `base` / `eth` (kline / trending only; trenches: `sol` / `bsc` / `base`; signal: `sol` / `bsc` only)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `.env` file with `GMGN_API_KEY` set
|
||||
- Run from the directory where your `.env` file is located, or set `GMGN_HOST` in your environment
|
||||
- `gmgn-cli` installed globally: `npm install -g gmgn-cli@1.0.1`
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
- `GMGN_API_KEY` configured in `~/.config/gmgn/.env`
|
||||
|
||||
## Kline Parameters
|
||||
## Rate Limit Handling
|
||||
|
||||
All market routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `market kline` | `GET /v1/market/token_kline` | 2 |
|
||||
| `market trending` | `GET /v1/market/rank` | 1 |
|
||||
| `market trenches` | `POST /v1/trenches` | 3 |
|
||||
| `market signal` | `POST /v1/market/token_signal` | 3 |
|
||||
|
||||
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.
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
## `market kline` Parameters
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--address` | Yes | Token contract address |
|
||||
| `--resolution` | Yes | Candlestick resolution |
|
||||
| `--resolution` | Yes | Candlestick resolution: `1m` / `5m` / `15m` / `1h` / `4h` / `1d` |
|
||||
| `--from` | No | Start time (Unix seconds) |
|
||||
| `--to` | No | End time (Unix seconds) |
|
||||
|
||||
## Resolutions
|
||||
## `market kline` Response Fields
|
||||
|
||||
`1m` / `5m` / `15m` / `1h` / `4h` / `1d`
|
||||
The response is an object with a `list` array. Each element in `list` is one candlestick:
|
||||
|
||||
## Trending Options
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `time` | number | Candle open time — Unix timestamp in **milliseconds** (divide by 1000 for seconds) |
|
||||
| `open` | string | Opening price in USD at the start of the period |
|
||||
| `close` | string | Closing price in USD at the end of the period |
|
||||
| `high` | string | Highest price in USD during the period |
|
||||
| `low` | string | Lowest price in USD during the period |
|
||||
| `volume` | string | Trading volume in **USD** (dollar value of all trades in this period) |
|
||||
| `amount` | string | Trading volume in **base token units** (number of tokens traded) |
|
||||
|
||||
**Important distinctions (naming is counterintuitive — do not guess):**
|
||||
- `volume` = USD dollar value (e.g. `1214` means ~$1,214 traded) — use this for "how much was traded in USD"
|
||||
- `amount` = token count (e.g. `5379110` means ~5.38M tokens changed hands) — use this for "how many tokens were traded"
|
||||
- For tokens not priced at $1, `volume` and `amount` will differ by orders of magnitude (e.g. a $0.0002 token: $1,214 volume = 5,379,110 tokens)
|
||||
- To get **total USD volume over a time range**, sum `volume` across all candles in the range
|
||||
- To get **price trend**, read `close` values in chronological order (`time` ascending)
|
||||
- To detect **volatility**, compare `high` vs `low` within each candle
|
||||
- Candles are returned in chronological order (oldest first)
|
||||
|
||||
## `market trending` Options
|
||||
|
||||
**`--interval` selection guide — always match to the user's stated time window:**
|
||||
|
||||
| User says | `--interval` |
|
||||
|-----------|-------------|
|
||||
| "1m trending" / "hottest right now" | `1m` |
|
||||
| "5m" / "5 minute" | `5m` |
|
||||
| "1h" / "1 hour" / no time specified (default) | `1h` |
|
||||
| "6h" / "6 hour" | `6h` |
|
||||
| "24h" / "today" / "daily" | `24h` |
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` |
|
||||
| `--interval` | Required. `1h` / `3h` / `6h` / `24h` |
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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` |
|
||||
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
||||
| `--filter <tag...>` | Repeatable filter tags (chain-specific). **sol** (defaults: `renounced frozen`): `renounced` / `frozen` / `burn` / `token_burnt` / `has_social` / `not_social_dup` / `not_image_dup` / `dexscr_update_link` / `not_wash_trading` / `is_internal_market` / `is_out_market`. **evm** (defaults: `not_honeypot verified renounced`): `not_honeypot` / `verified` / `renounced` / `locked` / `token_burnt` / `has_social` / `not_social_dup` / `not_image_dup` / `dexscr_update_link` / `is_internal_market` / `is_out_market` |
|
||||
| `--platform <name...>` | Repeatable platform filter (chain-specific). **sol**: `Pump.fun` / `pump_mayhem` / `pump_mayhem_agent` / `pump_agent` / `letsbonk` / `bonkers` / `bags` / `memoo` / `liquid` / `bankr` / `zora` / `surge` / `anoncoin` / `moonshot_app` / `wendotdev` / `heaven` / `sugar` / `token_mill` / `believe` / `trendsfun` / `trends_fun` / `jup_studio` / `Moonshot` / `boop` / `xstocks` / `ray_launchpad` / `meteora_virtual_curve` / `pool_ray` / `pool_meteora` / `pool_pump_amm` / `pool_orca`. **bsc**: `fourmeme` / `fourmeme_agent` / `bn_fourmeme` / `flap` / `clanker` / `lunafun` / `pool_uniswap` / `pool_pancake`. **base**: `clanker` / `bankr` / `flaunch` / `zora` / `zora_creator` / `baseapp` / `basememe` / `virtuals_v2` / `klik` |
|
||||
| `--filter <tag...>` | Repeatable filter tags (chain-specific). **⚠️ SOL defaults: `renounced frozen`; BSC/Base/ETH defaults: `not_honeypot verified renounced`.** Omitting `--filter` is NOT "no filter" — chain defaults always apply. **sol** tags: `renounced` / `frozen` / `burn` / `token_burnt` / `has_social` / `not_social_dup` / `not_image_dup` / `dexscr_update_link` / `not_wash_trading` / `is_internal_market` / `is_out_market`. **evm** tags: `not_honeypot` / `verified` / `renounced` / `locked` / `token_burnt` / `has_social` / `not_social_dup` / `not_image_dup` / `dexscr_update_link` / `is_internal_market` / `is_out_market` |
|
||||
| `--platform <name...>` | Repeatable platform filter (chain-specific). **sol**: `Pump.fun` / `pump_mayhem` / `pump_mayhem_agent` / `pump_agent` / `letsbonk` / `bonkers` / `bags` / `memoo` / `liquid` / `bankr` / `zora` / `surge` / `anoncoin` / `moonshot_app` / `wendotdev` / `heaven` / `sugar` / `token_mill` / `believe` / `trendsfun` / `trends_fun` / `jup_studio` / `Moonshot` / `boop` / `xstocks` / `ray_launchpad` / `meteora_virtual_curve` / `pool_ray` / `pool_meteora` / `pool_pump_amm` / `pool_orca`. **bsc**: `fourmeme` / `fourmeme_agent` / `bn_fourmeme` / `flap` / `clanker` / `lunafun` / `pool_uniswap` / `pool_pancake`. **base**: `clanker` / `bankr` / `flaunch` / `zora` / `zora_creator` / `baseapp` / `basememe` / `virtuals_v2` / `klik`. **eth**: no platform filter (omit `--platform` for ETH) |
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Kline
|
||||
|
||||
```bash
|
||||
# Last 1 hour of 1-minute candles
|
||||
# macOS:
|
||||
@@ -72,74 +173,784 @@ gmgn-cli market kline \
|
||||
--to $(date +%s)
|
||||
# Linux: use $(date -d '24 hours ago' +%s) instead of $(date -v-24H +%s)
|
||||
|
||||
# Raw output for further processing
|
||||
gmgn-cli market kline --chain sol --address <addr> \
|
||||
--resolution 5m --from <ts> --to <ts> --raw | jq '.[]'
|
||||
|
||||
# ETH token kline — last 24h, 1h candles (macOS)
|
||||
gmgn-cli market kline \
|
||||
--chain eth \
|
||||
--address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
||||
--resolution 1h \
|
||||
--from $(date -v-24H +%s) \
|
||||
--to $(date +%s)
|
||||
```
|
||||
|
||||
### Trending — General
|
||||
|
||||
```bash
|
||||
# Top 20 hot tokens on SOL in the last 1 hour, sorted by volume
|
||||
gmgn-cli market trending --chain sol --interval 1h --order-by volume --limit 20
|
||||
|
||||
# Top 50 tokens on SOL, 5m window, sorted by volume
|
||||
gmgn-cli market trending --chain sol --interval 5m --order-by volume --limit 50
|
||||
|
||||
# Hot tokens with social links only, verified and not honeypot, on BSC over 24h
|
||||
gmgn-cli market trending \
|
||||
--chain bsc --interval 24h \
|
||||
--filter has_social --filter not_honeypot --filter verified
|
||||
|
||||
# Pump.fun platform tokens on SOL, last 6 hours
|
||||
gmgn-cli market trending --chain sol --interval 6h --platform Pump.fun
|
||||
|
||||
# Raw output for further processing
|
||||
gmgn-cli market kline --chain sol --address <addr> \
|
||||
--resolution 5m --from <ts> --to <ts> --raw | jq '.[]'
|
||||
```
|
||||
|
||||
### Trending — SOL by Launchpad Platform
|
||||
|
||||
Use `--platform` to filter trending results to tokens from specific launchpads only.
|
||||
|
||||
```bash
|
||||
# SOL 1m hottest — Pump.fun + letsbonk only (most active launchpads), sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain sol --interval 1m \
|
||||
--platform Pump.fun --platform letsbonk \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# SOL 5m hottest — Pump.fun + letsbonk + Moonshot, sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain sol --interval 5m \
|
||||
--platform Pump.fun --platform letsbonk --platform moonshot_app \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# SOL 1h trending — Pump.fun only, with safety filters
|
||||
gmgn-cli market trending \
|
||||
--chain sol --interval 1h \
|
||||
--platform Pump.fun \
|
||||
--filter renounced --filter frozen --filter not_wash_trading \
|
||||
--order-by volume --limit 20 --raw
|
||||
|
||||
# SOL 1h trending — all major launchpads combined
|
||||
gmgn-cli market trending \
|
||||
--chain sol --interval 1h \
|
||||
--platform Pump.fun --platform letsbonk --platform moonshot_app \
|
||||
--platform pump_mayhem --platform pump_mayhem_agent --platform bonkers \
|
||||
--order-by volume --limit 50 --raw
|
||||
```
|
||||
|
||||
### Trending — BSC by Launchpad Platform
|
||||
|
||||
```bash
|
||||
# BSC 1m hottest — fourmeme (main BSC launchpad), sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain bsc --interval 1m \
|
||||
--platform fourmeme --platform four_xmode_agent \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# BSC 5m hottest — fourmeme family, sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain bsc --interval 5m \
|
||||
--platform fourmeme --platform fourmeme_agent --platform bn_fourmeme --platform four_xmode_agent \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# BSC 1h trending — fourmeme with safety filters
|
||||
gmgn-cli market trending \
|
||||
--chain bsc --interval 1h \
|
||||
--platform fourmeme --platform fourmeme_agent --platform bn_fourmeme --platform four_xmode_agent \
|
||||
--filter not_honeypot --filter verified \
|
||||
--order-by volume --limit 20 --raw
|
||||
```
|
||||
|
||||
### Trending — ETH (No Platform Filter)
|
||||
|
||||
```bash
|
||||
# ETH 1h trending — all tokens, sorted by volume
|
||||
gmgn-cli market trending --chain eth --interval 1h --order-by volume --limit 20
|
||||
|
||||
# ETH 1h trending — with safety filters
|
||||
gmgn-cli market trending \
|
||||
--chain eth --interval 1h \
|
||||
--filter not_honeypot --filter verified \
|
||||
--order-by volume --limit 20 --raw
|
||||
|
||||
# ETH 24h trending — sorted by smart money count
|
||||
gmgn-cli market trending \
|
||||
--chain eth --interval 24h \
|
||||
--filter not_honeypot --filter verified \
|
||||
--order-by smart_degen_count --limit 20 --raw
|
||||
```
|
||||
|
||||
### Trending — Base by Launchpad Platform
|
||||
|
||||
```bash
|
||||
# Base 1m hottest — clanker + zora (main Base launchpads), sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain base --interval 1m \
|
||||
--platform clanker --platform zora --platform zora_creator \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# Base 5m hottest — clanker + zora + virtuals_v2 + flaunch, sorted by volume
|
||||
gmgn-cli market trending \
|
||||
--chain base --interval 5m \
|
||||
--platform clanker --platform zora --platform zora_creator \
|
||||
--platform virtuals_v2 --platform flaunch \
|
||||
--order-by volume --limit 50 --raw
|
||||
|
||||
# Base 1h trending — all major launchpads with safety filters
|
||||
gmgn-cli market trending \
|
||||
--chain base --interval 1h \
|
||||
--platform clanker --platform zora --platform zora_creator \
|
||||
--platform virtuals_v2 --platform flaunch --platform baseapp \
|
||||
--filter not_honeypot --filter verified \
|
||||
--order-by volume --limit 20 --raw
|
||||
```
|
||||
|
||||
## `market trending` Response Fields
|
||||
|
||||
The response is `data.rank` — an array of rank items. Each item represents one token.
|
||||
|
||||
**Basic Info**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `address` | Token contract address |
|
||||
| `symbol` / `name` | Token ticker and full name |
|
||||
| `logo` | Token logo image URL |
|
||||
| `chain` | Chain identifier |
|
||||
| `total_supply` | Total token supply |
|
||||
| `creator` | Creator wallet address |
|
||||
| `launchpad_platform` | Launch/pool platform (e.g. `Pump.fun`, `letsbonk`, `pool_meteora`, `fourmeme`) |
|
||||
| `exchange` | Current DEX (e.g. `meteora_damm_v2`, `raydium`, `pump_amm`) |
|
||||
| `open_timestamp` | Open market listing time (Unix seconds) |
|
||||
| `creation_timestamp` | Token creation time (Unix seconds) |
|
||||
| `rank` | Position in this trending list (lower = hotter) |
|
||||
| `hot_level` | Trending intensity level (higher = hotter) |
|
||||
|
||||
**Price & Market**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `price` | Current price in USD |
|
||||
| `market_cap` | Market cap in USD (directly available — no calculation needed) |
|
||||
| `liquidity` | Current liquidity in USD |
|
||||
| `volume` | Trading volume in USD for the queried interval |
|
||||
| `history_highest_market_cap` | All-time highest market cap in USD |
|
||||
| `initial_liquidity` | Initial liquidity at token launch |
|
||||
| `price_change_percent` | Price change % for the queried interval |
|
||||
| `price_change_percent1m` | Price change % in last 1 minute |
|
||||
| `price_change_percent5m` | Price change % in last 5 minutes |
|
||||
| `price_change_percent1h` | Price change % in last 1 hour |
|
||||
|
||||
**Trading Activity**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `swaps` | Total swap count in the queried interval |
|
||||
| `buys` / `sells` | Buy / sell count in the interval |
|
||||
| `holder_count` | Number of unique token holders |
|
||||
| `gas_fee` | Average gas fee per transaction |
|
||||
|
||||
**Security & Risk**
|
||||
|
||||
| Field | Chains | Description |
|
||||
|-------|--------|-------------|
|
||||
| `renounced_mint` | SOL | Mint authority renounced (`1` = yes, `0` = no) |
|
||||
| `renounced_freeze_account` | SOL | Freeze authority renounced (`1` = yes, `0` = no) |
|
||||
| `is_honeypot` | BSC / Base | Honeypot flag (`1` = yes, `0` = no) |
|
||||
| `is_open_source` | all | Contract verified (`1` = yes, `0` = no) |
|
||||
| `is_renounced` | all | Ownership renounced (`1` = yes, `0` = no) |
|
||||
| `buy_tax` / `sell_tax` | all | Tax rate — empty string means `0` (no tax) |
|
||||
| `burn_status` | all | Liquidity burn status (e.g. `"none"`, `"burn"`) |
|
||||
| `top_10_holder_rate` | all | Top 10 wallets concentration (0–1) |
|
||||
| `rug_ratio` | all | Rug pull risk score (0–1) |
|
||||
| `is_wash_trading` | all | Wash trading detected (`true` / `false`) |
|
||||
| `rat_trader_amount_rate` | all | Ratio of insider/sneak trading volume |
|
||||
| `bundler_rate` | all | Ratio of bundle bot trading volume |
|
||||
| `entrapment_ratio` | all | Entrapment trading ratio |
|
||||
| `sniper_count` | all | Number of sniper wallets at launch |
|
||||
| `bot_degen_count` / `bot_degen_rate` | all | Bot degen wallet count / ratio |
|
||||
| `dev_team_hold_rate` | all | Dev team holding ratio |
|
||||
| `top70_sniper_hold_rate` | all | Top 70 sniper current holding ratio |
|
||||
| `lock_percent` | all | Liquidity lock percentage |
|
||||
|
||||
**Dev Status**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `creator_token_status` | Dev holding status: `creator_hold` (still holding) / `creator_close` (sold/closed) |
|
||||
| `creator_close` | Boolean shorthand for `creator_token_status == creator_close` |
|
||||
| `dev_token_burn_ratio` | Ratio of dev's tokens that have been burned |
|
||||
|
||||
**Smart Money**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `smart_degen_count` | Number of smart money wallets holding the token |
|
||||
| `renowned_count` | Number of renowned / KOL wallets holding the token |
|
||||
| `bluechip_owner_percentage` | Ratio of holders that are bluechip wallets (0–1) |
|
||||
|
||||
**Social**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `twitter_username` | Twitter / X username (not a full URL — prepend `https://x.com/` to get the link) |
|
||||
| `website` | Project website URL |
|
||||
| `telegram` | Telegram URL |
|
||||
| `cto_flag` | Community takeover flag (`1` = CTO has occurred) |
|
||||
|
||||
**Dexscreener Marketing**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `dexscr_ad` | Dexscreener ad placed (`1` = yes) |
|
||||
| `dexscr_update_link` | Social links updated on Dexscreener (`1` = yes) |
|
||||
| `dexscr_trending_bar` | Paid for Dexscreener trending bar (`1` = yes) |
|
||||
| `dexscr_boost_fee` | Dexscreener boost amount paid (0 = none) |
|
||||
|
||||
---
|
||||
|
||||
## Workflow: Discover Trading Opportunities via Trending
|
||||
|
||||
### Step 1 — Fetch trending data
|
||||
Full workflow for discovering market opportunities: [`docs/workflow-market-opportunities.md`](../../docs/workflow-market-opportunities.md)
|
||||
|
||||
Fetch a broad pool with safe filters:
|
||||
Steps: fetch trending (50 results, safe filters) → AI multi-factor analysis (smart money, volume, momentum, liquidity, maturity) → present top 5 table with rationale → offer deep dive or swap.
|
||||
|
||||
When results contain interesting tokens, proceed to full token due diligence: [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md)
|
||||
|
||||
**For new / launchpad tokens** (`market trenches`): apply the structured early project screening workflow that includes security check and smart money entry detection — [`docs/workflow-early-project-screening.md`](../../docs/workflow-early-project-screening.md)
|
||||
|
||||
**For a daily market overview** (user asks "what's the market like today", "give me a daily brief", "what is smart money buying today"): combine `market trending` + `market trenches` with `gmgn-track smartmoney` — [`docs/workflow-daily-brief.md`](../../docs/workflow-daily-brief.md)
|
||||
|
||||
## Token Quality Filter Criteria
|
||||
|
||||
When evaluating tokens returned from `market trending` or `market trenches`, apply these criteria to quickly separate high-quality opportunities from noise. Do not present raw results without filtering.
|
||||
|
||||
### Pass / Watch / Skip Criteria
|
||||
|
||||
| Signal | 🟢 Pass | 🟡 Watch | 🔴 Skip |
|
||||
|--------|---------|---------|---------|
|
||||
| `smart_degen_count` | ≥ 3 | 1–2 | 0 |
|
||||
| `rug_ratio` | < 0.1 | 0.1–0.3 | > 0.3 |
|
||||
| `creator_token_status` | `creator_close` | — | `creator_hold` |
|
||||
| `is_wash_trading` | `false` | — | `true` → skip immediately |
|
||||
| `top_10_holder_rate` | < 0.20 | 0.20–0.50 | > 0.50 |
|
||||
| `liquidity` | > $50k | $10k–$50k | < $10k |
|
||||
| `has_social` (or any social field present) | yes | — | no (weak signal only) |
|
||||
|
||||
**Quick disqualification rule:** If `rug_ratio > 0.3` OR `is_wash_trading = true` OR `is_honeypot = 1` → skip immediately, no further analysis needed.
|
||||
|
||||
**Strong buy signal combination:** `smart_degen_count ≥ 3` + `rug_ratio < 0.2` + `creator_close` + `is_wash_trading = false` + `liquidity > $50k` → high-quality opportunity, proceed to full token research.
|
||||
|
||||
For full due diligence on any token surfaced here: [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md)
|
||||
|
||||
## Token Lifecycle Stage
|
||||
|
||||
Use field combinations to determine what stage a token is in. This affects how signals should be interpreted.
|
||||
|
||||
### Stage 1 — Early (New Born)
|
||||
|
||||
**Indicators:**
|
||||
- `creation_timestamp` < 1 hour ago
|
||||
- `hot_level` low or just starting to rise
|
||||
- `smart_degen_count = 0`, `renowned_count = 0`
|
||||
|
||||
**Interpretation:** Too early for smart money signals. No on-chain track record. High risk, high potential reward. **Wait for Stage 2 confirmation before acting.** Only the most risk-tolerant traders enter here.
|
||||
|
||||
### Stage 2 — Breakout
|
||||
|
||||
**Indicators:**
|
||||
- `smart_degen_count ≥ 3` AND rising
|
||||
- Volume surging (compare `swaps_1h` vs `swaps_24h / 24` — significantly higher)
|
||||
- `price_change_percent1h > 20%`
|
||||
- `creator_token_status = creator_hold` is OK at this stage (dev hasn't distributed yet)
|
||||
|
||||
**Interpretation:** Strongest entry signal. Smart money is accumulating. Verify security before acting. This window is often short — act on confirmation, not anticipation.
|
||||
|
||||
### Stage 3 — Distribution
|
||||
|
||||
**Indicators:**
|
||||
- `creator_token_status = creator_close` (dev has sold their allocation)
|
||||
- `renowned_count` buying (late social signal — KOLs often enter after smart money)
|
||||
- `smart_degen_count` plateauing or declining
|
||||
- Volume still high but momentum slowing
|
||||
|
||||
**Interpretation:** Late stage entry. Smart money may be exiting into retail/KOL demand. Higher risk for new entries. If already holding from Stage 2, evaluate exit levels.
|
||||
|
||||
### Stage 4 — Decline
|
||||
|
||||
**Indicators:**
|
||||
- Volume declining across all windows
|
||||
- `holder_count` declining
|
||||
- `rat_trader_amount_rate` high (insider/sneak trading dominating)
|
||||
- `smart_degen_count = 0` or clearly declining
|
||||
|
||||
**Interpretation:** Avoid new entries entirely. If still holding, consider exiting. The opportunity has likely passed.
|
||||
|
||||
## `market trenches` Parameters
|
||||
|
||||
**Intent → `--type` mapping (always specify `--type` explicitly):**
|
||||
|
||||
| User intent | `--type` value |
|
||||
|-------------|----------------|
|
||||
| "new tokens", "just launched", "newly created", "latest tokens" | `new_creation` |
|
||||
| "about to graduate", "near completion", "bonding curve almost full" | `near_completion` |
|
||||
| "graduated tokens", "already on DEX", "open market tokens" | `completed` |
|
||||
| No specific stage mentioned | omit `--type` (returns all three) |
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--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) |
|
||||
| `--filter-preset` | No | Named server-side filter preset: `safe` / `smart-money` / `strict` |
|
||||
| `--sort-by` | No | Client-side sort per category: `smart_degen_count` / `renowned_count` / `volume_24h` / `volume_1h` / `swaps_24h` / `swaps_1h` / `rug_ratio` / `holder_count` / `usd_market_cap` / `created_timestamp` |
|
||||
| `--direction` | No | Sort direction: `asc` / `desc` (default: `desc`; `asc` for `rug_ratio`) |
|
||||
| `--min-*` / `--max-*` | No | Server-side filter range flags — see Filter Fields Reference below |
|
||||
|
||||
### Filter Presets
|
||||
|
||||
Presets are applied server-side: the API filters tokens before returning results.
|
||||
|
||||
| Preset | Server-side filters applied |
|
||||
|--------|----------------------------|
|
||||
| `safe` | `max_rug_ratio=0.3` + `max_bundler_rate=0.3` + `max_insider_ratio=0.3` |
|
||||
| `smart-money` | `min_smart_degen_count=1` |
|
||||
| `strict` | `max_rug_ratio=0.3` + `max_bundler_rate=0.3` + `max_insider_ratio=0.3` + `min_smart_degen_count=1` + `min_volume_24h=1000` |
|
||||
|
||||
**Preset + explicit flag interaction:** Explicit filter flags always override preset values. For example, `--filter-preset safe --max-rug-ratio 0.1` applies the `safe` preset but overrides rug_ratio threshold to `0.1`.
|
||||
|
||||
**All filter flags are sent as part of the API request body (server-side)** — the server filters tokens before returning results. Use `--limit 80` (the default maximum) to maximise the pool.
|
||||
|
||||
Response fields: `data.new_creation`, `data.pump`, `data.completed` — each is an array of `RankItem` (same fields as `market trending` rank items). **Important: `data.pump` in the response corresponds to `--type near_completion` in the request. The API always returns this category under the key `pump`, not `near_completion`.**
|
||||
|
||||
### Server-Side Filter Fields
|
||||
|
||||
All filter flags are sent as part of the API request body — the server filters tokens before returning results. Flags follow the naming convention `--min-{field}` / `--max-{field}`.
|
||||
|
||||
| Flag pair | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `--min-volume-24h` / `--max-volume-24h` | float | 24h trading volume (USD) |
|
||||
| `--min-net-buy-24h` / `--max-net-buy-24h` | float | 24h net buy volume (USD) |
|
||||
| `--min-swaps-24h` / `--max-swaps-24h` | int | 24h total swap count |
|
||||
| `--min-buys-24h` / `--max-buys-24h` | int | 24h buy count |
|
||||
| `--min-sells-24h` / `--max-sells-24h` | int | 24h sell count |
|
||||
| `--min-visiting-count` / `--max-visiting-count` | int | Visitor count |
|
||||
| `--min-progress` / `--max-progress` | float | Bonding curve progress (0–1) |
|
||||
| `--min-marketcap` / `--max-marketcap` | float | Market cap (USD) |
|
||||
| `--min-liquidity` / `--max-liquidity` | float | Liquidity (USD) |
|
||||
| `--min-created` / `--max-created` | duration | Token age — unit suffix recommended: seconds (`30s`, `10s`) or minutes (`0.5m`, `1m`, `5m`, `30m`). Bare numbers (e.g. `5`) are treated as minutes with a warning. |
|
||||
| `--min-holder-count` / `--max-holder-count` | int | Holder count |
|
||||
| `--min-top-holder-rate` / `--max-top-holder-rate` | float | Top-10 holder concentration (0–1) |
|
||||
| `--min-rug-ratio` / `--max-rug-ratio` | float | Rug pull risk score (0–1) |
|
||||
| `--min-bundler-rate` / `--max-bundler-rate` | float | Bundle-bot trading ratio (0–1) |
|
||||
| `--min-insider-ratio` / `--max-insider-ratio` | float | Insider trading ratio (0–1) |
|
||||
| `--min-entrapment-ratio` / `--max-entrapment-ratio` | float | Entrapment/Phishing trading ratio (0–1) |
|
||||
| `--min-private-vault-hold-rate` / `--max-private-vault-hold-rate` | float | Private vault holding ratio (0–1) |
|
||||
| `--min-top70-sniper-hold-rate` / `--max-top70-sniper-hold-rate` | float | Top-70 sniper holding ratio (0–1) |
|
||||
| `--min-bot-count` / `--max-bot-count` | int | Bot wallet count |
|
||||
| `--min-bot-degen-rate` / `--max-bot-degen-rate` | float | Bot-degen wallet ratio (0–1) |
|
||||
| `--min-fresh-wallet-rate` / `--max-fresh-wallet-rate` | float | Fresh wallet ratio (0–1) |
|
||||
| `--min-total-fee` / `--max-total-fee` | float | Total fee |
|
||||
| `--min-smart-degen-count` / `--max-smart-degen-count` | int | Smart-money holder count |
|
||||
| `--min-renowned-count` / `--max-renowned-count` | int | KOL / renowned wallet count |
|
||||
| `--min-creator-balance-rate` / `--max-creator-balance-rate` | float | Creator holding ratio (0–1) |
|
||||
| `--min-creator-created-count` / `--max-creator-created-count` | int | Creator's total token creation count |
|
||||
| `--min-creator-created-open-count` / `--max-creator-created-open-count` | int | Creator's graduated token count |
|
||||
| `--min-creator-created-open-ratio` / `--max-creator-created-open-ratio` | float | Creator's graduation ratio (0–1) |
|
||||
| `--min-x-follower` / `--max-x-follower` | int | Twitter / X follower count |
|
||||
| `--min-twitter-rename-count` / `--max-twitter-rename-count` | int | Twitter rename count |
|
||||
| `--min-tg-call-count` / `--max-tg-call-count` | int | Telegram call count |
|
||||
|
||||
### Trenches Filter Examples
|
||||
|
||||
```bash
|
||||
gmgn-cli market trending \
|
||||
--chain <chain> --interval 1h \
|
||||
--order-by volume --limit 50 \
|
||||
--filter not_honeypot --filter has_social --raw
|
||||
# Apply the safe preset (server-side)
|
||||
gmgn-cli market trenches --chain sol --type new_creation --filter-preset safe
|
||||
|
||||
# Require at least 1 smart money holder (server-side)
|
||||
gmgn-cli market trenches --chain sol --type new_creation --min-smart-degen-count 1
|
||||
|
||||
# Safe preset + require smart money + sort by smart degen count (server-side filter, client-side sort)
|
||||
gmgn-cli market trenches --chain sol --type new_creation \
|
||||
--filter-preset safe --min-smart-degen-count 1 --sort-by smart_degen_count
|
||||
|
||||
# Strict preset — safe + smart money + min $1k volume (server-side)
|
||||
gmgn-cli market trenches --chain sol --type new_creation --type near_completion \
|
||||
--filter-preset strict --sort-by smart_degen_count
|
||||
|
||||
# Manual range filters (all sent server-side)
|
||||
gmgn-cli market trenches --chain sol --type new_creation \
|
||||
--max-rug-ratio 0.3 --max-bundler-rate 0.3 --max-insider-ratio 0.3 \
|
||||
--min-smart-degen-count 1 --min-volume-24h 1000
|
||||
|
||||
# Filter by token age: only tokens created within the last 30 minutes
|
||||
gmgn-cli market trenches --chain sol --type new_creation --max-created 30m
|
||||
|
||||
# Filter by market cap range
|
||||
gmgn-cli market trenches --chain sol --type new_creation \
|
||||
--min-marketcap 10000 --max-marketcap 500000
|
||||
```
|
||||
|
||||
### Step 2 — AI multi-factor analysis
|
||||
## `market trenches` Response Fields
|
||||
|
||||
Analyze each record in the response using the following signals (apply judgment, not rigid rules):
|
||||
**Basic Info**
|
||||
|
||||
| Signal | Field(s) | Weight | Notes |
|
||||
|--------|----------|--------|-------|
|
||||
| Smart money interest | `smart_degen_count`, `renowned_count` | High | Key conviction indicator |
|
||||
| Bluechip ownership | `bluechip_owner_percentage` | Medium | Quality of holder base |
|
||||
| Real trading activity | `volume`, `swaps` | Medium | Distinguishes genuine interest from wash trading |
|
||||
| Price momentum | `change1h`, `change5m` | Medium | Prefer positive, non-parabolic moves |
|
||||
| Pool safety | `liquidity` | Medium | Low liquidity = high slippage risk |
|
||||
| Token maturity | `creation_timestamp` | Low | Avoid tokens less than ~1h old unless other signals are very strong |
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `address` | Token contract address |
|
||||
| `symbol` / `name` | Token symbol and name |
|
||||
| `launchpad_platform` | Launch platform (e.g. `Pump.fun`, `letsbonk`) |
|
||||
| `exchange` | Current exchange (e.g. `pump_amm`, `raydium`) |
|
||||
| `usd_market_cap` | Market cap in USD |
|
||||
| `liquidity` | Liquidity in USD |
|
||||
| `total_supply` | Total token supply |
|
||||
| `created_timestamp` | Creation time (Unix seconds) |
|
||||
| `open_timestamp` | Open market listing time (Unix seconds, `completed` only) |
|
||||
| `complete_timestamp` | Bonding curve completion time (Unix seconds) |
|
||||
| `complete_cost_time` | Time from creation to completion in seconds |
|
||||
|
||||
Select the **top 5** tokens with the best composite profile. Prefer tokens that perform well across multiple signals rather than excelling in just one.
|
||||
**Trading Data**
|
||||
|
||||
### Step 3 — Present top 5 to user
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `swaps_1m` / `swaps_1h` / `swaps_24h` | Swap count per time window |
|
||||
| `volume_1h` / `volume_24h` | Trading volume in USD |
|
||||
| `buys_24h` / `sells_24h` | Buy / sell count in 24h |
|
||||
| `net_buy_24h` | Net buy volume in 24h |
|
||||
| `holder_count` | Number of token holders |
|
||||
|
||||
Present results as a concise table, then give a one-line rationale for each pick:
|
||||
**Security & Risk**
|
||||
|
||||
```
|
||||
Top 5 Trending Tokens — SOL / 1h
|
||||
| Field | Chains | Description |
|
||||
|-------|--------|-------------|
|
||||
| `renounced_mint` | SOL | Whether mint authority is renounced (SOL-specific concept; always `false` on EVM chains) |
|
||||
| `renounced_freeze_account` | SOL | Whether freeze authority is renounced (SOL-specific concept; always `false` on EVM chains) |
|
||||
| `burn_status` | all | Liquidity burn status |
|
||||
| `rug_ratio` | all | Rug pull risk ratio |
|
||||
| `top_10_holder_rate` | all | Top 10 holders concentration ratio |
|
||||
| `rat_trader_amount_rate` | all | Insider / sneak trading volume ratio |
|
||||
| `bundler_trader_amount_rate` | all | Bundle trading volume ratio |
|
||||
| `is_wash_trading` | all | Whether wash trading is detected |
|
||||
| `sniper_count` | all | Number of sniper wallets |
|
||||
| `suspected_insider_hold_rate` | all | Suspected insider holding ratio |
|
||||
| `open_source` | all | Whether contract source code is verified (`"yes"` / `"no"` / `"unknown"`) |
|
||||
| `owner_renounced` | all | Whether contract ownership is renounced (`"yes"` / `"no"` / `"unknown"`) |
|
||||
| `is_honeypot` | BSC / Base | Whether token is a honeypot (`"yes"` / `"no"`); returns empty string on SOL (not applicable) |
|
||||
| `buy_tax` | all | Buy tax ratio (e.g. `0.03` = 3%) |
|
||||
| `dev_team_hold_rate` | all | Dev team holding ratio |
|
||||
|
||||
# | Symbol | Address (short) | Smart Degens | Volume | 1h Chg | Reasoning
|
||||
1 | ... | ... | ... | ... | ... | Smart money accumulating + high volume
|
||||
2 | ...
|
||||
...
|
||||
**Dev Holdings**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `creator_token_status` | Dev holding status (e.g. `creator_hold`, `creator_close`) |
|
||||
| `creator_balance_rate` | Dev holding ratio as a proportion of total supply |
|
||||
|
||||
**Smart Money**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `smart_degen_count` | Number of smart money holders |
|
||||
| `renowned_count` | Number of renowned wallet holders (KOL) |
|
||||
|
||||
**Social Media**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `twitter` | Twitter / X link |
|
||||
| `telegram` | Telegram link |
|
||||
| `website` | Website link |
|
||||
| `instagram` | Instagram link |
|
||||
| `tiktok` | TikTok link |
|
||||
| `has_at_least_one_social` | Whether any social media link exists |
|
||||
| `x_user_follower` | Twitter follower count |
|
||||
| `cto_flag` | Whether community takeover (CTO) has occurred |
|
||||
|
||||
**Dexscreener Marketing**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `dexscr_ad` | Whether a Dexscreener ad has been placed |
|
||||
| `dexscr_update_link` | Whether social links have been updated on Dexscreener |
|
||||
| `dexscr_trending_bar` | Whether paid for Dexscreener trending bar placement |
|
||||
| `dexscr_boost_fee` | Amount paid for Dexscreener boost (0 = none) |
|
||||
|
||||
**After fetching trenches results, apply the Token Quality Filter Criteria section before presenting tokens to the user.** Do not dump raw results — filter first, then surface the strongest candidates.
|
||||
|
||||
### Trenches Filter Examples
|
||||
|
||||
```bash
|
||||
# Quick safe screen — exclude rugs, wash trading, and bundlers
|
||||
gmgn-cli market trenches --chain sol --type new_creation \
|
||||
--filter-preset safe --raw
|
||||
|
||||
# Smart money screen — only tokens with smart money or KOL presence
|
||||
gmgn-cli market trenches --chain sol \
|
||||
--type new_creation --type near_completion \
|
||||
--filter-preset smart-money \
|
||||
--sort-by smart_degen_count --raw
|
||||
|
||||
# Strict screen — safe + smart money + minimum volume, sorted by smart degens
|
||||
gmgn-cli market trenches --chain sol --type completed \
|
||||
--filter-preset strict --sort-by smart_degen_count --raw
|
||||
|
||||
# Custom filter — no wash trading, rug_ratio <= 0.2, at least 1 smart degen
|
||||
gmgn-cli market trenches --chain sol \
|
||||
--type new_creation --type near_completion \
|
||||
--exclude-wash-trading --max-rug-ratio 0.2 --min-smart-degen 1 \
|
||||
--sort-by smart_degen_count --raw
|
||||
|
||||
# BSC — safe screen on new tokens from fourmeme
|
||||
gmgn-cli market trenches --chain bsc --type new_creation \
|
||||
--launchpad-platform fourmeme --launchpad-platform fourmeme_agent \
|
||||
--filter-preset safe --sort-by volume_1h --raw
|
||||
|
||||
# Sort by rug_ratio ascending (safest first), no other filters
|
||||
gmgn-cli market trenches --chain sol --type completed \
|
||||
--sort-by rug_ratio --raw
|
||||
|
||||
# Find tokens with many holders and strong 1h swap activity
|
||||
gmgn-cli market trenches --chain sol --type completed \
|
||||
--min-holders 100 --min-swaps 50 \
|
||||
--sort-by swaps_1h --raw
|
||||
```
|
||||
|
||||
### Step 4 — Follow-up actions
|
||||
### Solana Trenches Examples
|
||||
|
||||
For each token, offer:
|
||||
- **Deep dive**: `token info` + `token security` for full due diligence
|
||||
- **Swap**: execute directly if the user is satisfied with the trending data alone
|
||||
```bash
|
||||
# All three categories at once
|
||||
gmgn-cli market trenches --chain sol --raw \
|
||||
--type new_creation --type near_completion --type completed \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform pump_mayhem_agent --launchpad-platform pump_agent --launchpad-platform letsbonk --launchpad-platform bonkers --launchpad-platform bags \
|
||||
--limit 80
|
||||
|
||||
# New creation only
|
||||
gmgn-cli market trenches --chain sol --raw \
|
||||
--type new_creation \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform pump_mayhem_agent --launchpad-platform pump_agent --launchpad-platform letsbonk --launchpad-platform bonkers --launchpad-platform bags \
|
||||
--limit 80
|
||||
|
||||
# Near completion only
|
||||
gmgn-cli market trenches --chain sol --raw \
|
||||
--type near_completion \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform pump_mayhem_agent --launchpad-platform pump_agent --launchpad-platform letsbonk --launchpad-platform bonkers --launchpad-platform bags \
|
||||
--limit 80
|
||||
|
||||
# Completed (open market) only
|
||||
gmgn-cli market trenches --chain sol --raw \
|
||||
--type completed \
|
||||
--launchpad-platform Pump.fun --launchpad-platform pump_mayhem --launchpad-platform pump_mayhem_agent --launchpad-platform pump_agent --launchpad-platform letsbonk --launchpad-platform bonkers --launchpad-platform bags \
|
||||
--limit 80
|
||||
```
|
||||
|
||||
### BSC Trenches Examples
|
||||
|
||||
```bash
|
||||
# All three categories at once
|
||||
gmgn-cli market trenches --chain bsc --raw \
|
||||
--type new_creation --type near_completion --type completed \
|
||||
--launchpad-platform fourmeme --launchpad-platform fourmeme_agent --launchpad-platform bn_fourmeme --launchpad-platform four_xmode_agent --launchpad-platform flap --launchpad-platform clanker --launchpad-platform lunafun \
|
||||
--limit 80
|
||||
|
||||
# New creation only
|
||||
gmgn-cli market trenches --chain bsc --raw \
|
||||
--type new_creation \
|
||||
--launchpad-platform fourmeme --launchpad-platform fourmeme_agent --launchpad-platform bn_fourmeme --launchpad-platform four_xmode_agent --launchpad-platform flap --launchpad-platform clanker --launchpad-platform lunafun \
|
||||
--limit 80
|
||||
|
||||
# Near completion only
|
||||
gmgn-cli market trenches --chain bsc --raw \
|
||||
--type near_completion \
|
||||
--launchpad-platform fourmeme --launchpad-platform fourmeme_agent --launchpad-platform bn_fourmeme --launchpad-platform four_xmode_agent --launchpad-platform flap --launchpad-platform clanker --launchpad-platform lunafun \
|
||||
--limit 80
|
||||
|
||||
# Completed (open market) only
|
||||
gmgn-cli market trenches --chain bsc --raw \
|
||||
--type completed \
|
||||
--launchpad-platform fourmeme --launchpad-platform fourmeme_agent --launchpad-platform bn_fourmeme --launchpad-platform four_xmode_agent --launchpad-platform flap --launchpad-platform clanker --launchpad-platform lunafun \
|
||||
--limit 80
|
||||
```
|
||||
|
||||
### Base Trenches Examples
|
||||
|
||||
```bash
|
||||
# All three categories at once
|
||||
gmgn-cli market trenches --chain base --raw \
|
||||
--type new_creation --type near_completion --type completed \
|
||||
--launchpad-platform clanker --launchpad-platform bankr --launchpad-platform flaunch --launchpad-platform zora --launchpad-platform zora_creator --launchpad-platform baseapp --launchpad-platform basememe --launchpad-platform virtuals_v2 --launchpad-platform klik \
|
||||
--limit 80
|
||||
|
||||
# New creation only
|
||||
gmgn-cli market trenches --chain base --raw \
|
||||
--type new_creation \
|
||||
--launchpad-platform clanker --launchpad-platform bankr --launchpad-platform flaunch --launchpad-platform zora --launchpad-platform zora_creator --launchpad-platform baseapp --launchpad-platform basememe --launchpad-platform virtuals_v2 --launchpad-platform klik \
|
||||
--limit 80
|
||||
|
||||
# Near completion only
|
||||
gmgn-cli market trenches --chain base --raw \
|
||||
--type near_completion \
|
||||
--launchpad-platform clanker --launchpad-platform bankr --launchpad-platform flaunch --launchpad-platform zora --launchpad-platform zora_creator --launchpad-platform baseapp --launchpad-platform basememe --launchpad-platform virtuals_v2 --launchpad-platform klik \
|
||||
--limit 80
|
||||
|
||||
# Completed (open market) only
|
||||
gmgn-cli market trenches --chain base --raw \
|
||||
--type completed \
|
||||
--launchpad-platform clanker --launchpad-platform bankr --launchpad-platform flaunch --launchpad-platform zora --launchpad-platform zora_creator --launchpad-platform baseapp --launchpad-platform basememe --launchpad-platform virtuals_v2 --launchpad-platform klik \
|
||||
--limit 80
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
### `market kline` — Price Summary
|
||||
|
||||
After fetching candles, present a brief price analysis. Do not dump raw candle arrays.
|
||||
|
||||
```
|
||||
{symbol} — {resolution} chart ({from} → {to})
|
||||
Open: ${open of first candle} | Close: ${close of last candle} | Range: ${min low} – ${max high}
|
||||
Total volume: ${sum of all volume fields} USD
|
||||
Trend: [brief description — e.g. "steady uptrend", "sharp drop then recovery", "sideways"]
|
||||
```
|
||||
|
||||
### `market trending` — Top Tokens Table
|
||||
|
||||
Present the top results (default: top 10, or as requested) as a table:
|
||||
|
||||
```
|
||||
# | Symbol | Price | MCap | Volume ({interval}) | 1h Chg | SM | Liq | Platform | Signal
|
||||
```
|
||||
|
||||
Where **Signal** = quality flag derived from the token's data:
|
||||
- 🟢 Pass: `smart_degen_count ≥ 3` AND `rug_ratio < 0.2` AND `is_wash_trading = false`
|
||||
- 🔴 Skip: `rug_ratio > 0.3` OR `is_wash_trading = true` OR `is_honeypot = 1`
|
||||
- 🟡 Watch: everything else
|
||||
|
||||
Then give a one-line highlight for any standout tokens (e.g. "TOKEN1 has 12 smart money holders and +85% in 1h — 🟢 strong signal").
|
||||
|
||||
### `market trenches` — Grouped by Category
|
||||
|
||||
Present each category separately with a header:
|
||||
|
||||
```
|
||||
🆕 New Creation ({count} tokens)
|
||||
# | Symbol | Created | Liquidity | Swaps (1h) | Smart Degens | Social
|
||||
|
||||
⏳ Near Completion ({count} tokens)
|
||||
# | Symbol | Market Cap | Swaps (1h) | Smart Degens | Social
|
||||
|
||||
✅ Graduated ({count} tokens)
|
||||
# | Symbol | Market Cap | Volume (1h) | Smart Degens | Social
|
||||
```
|
||||
|
||||
## `market signal` Parameters
|
||||
|
||||
Chains: `sol` / `bsc` only. **Maximum 50 results per group** — use multiple groups via `--groups` to cover different signal types in a single request.
|
||||
|
||||
**Single-group (individual flags):**
|
||||
|
||||
Do **not** pass signal types **14, 15, or 16** in `signal_type` / `--signal-type` / `--groups` JSON — OpenAPI returns **400** if any group includes them. Omitting `--signal-type` (empty filter) still queries all types upstream; responses may still include 14–16 in that case.
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` |
|
||||
| `--signal-type` | No | Signal type(s), repeatable (1–18, default: all). See Signal Types below. |
|
||||
| `--mc-min` | No | Min market cap at trigger time (USD) |
|
||||
| `--mc-max` | No | Max market cap at trigger time (USD) |
|
||||
| `--trigger-mc-min` | No | Min market cap at signal trigger moment (USD) |
|
||||
| `--trigger-mc-max` | No | Max market cap at signal trigger moment (USD) |
|
||||
| `--total-fee-min` | No | Min total fees paid (USD) |
|
||||
| `--total-fee-max` | No | Max total fees paid (USD) |
|
||||
| `--min-create-or-open-ts` | No | Min token creation or open timestamp (Unix seconds string) |
|
||||
| `--max-create-or-open-ts` | No | Max token creation or open timestamp (Unix seconds string) |
|
||||
|
||||
**Multi-group override:**
|
||||
|
||||
Pass `--groups '<json_array>'` to query multiple filter groups in a single request. The upstream executes all groups in parallel and merges results sorted by `trigger_at` descending. When `--groups` is present, all individual flags above are ignored.
|
||||
|
||||
```bash
|
||||
gmgn-cli market signal --chain sol \
|
||||
--groups '[{"signal_type":[12,13]},{"signal_type":[6,7],"mc_min":50000}]'
|
||||
```
|
||||
|
||||
### Signal Types
|
||||
|
||||
| Value | Name | Description |
|
||||
|-------|------|-------------|
|
||||
| 1 | SignalType1 | General signal (K-line price spike) |
|
||||
| 2 | SignalTypeDexAd | Dex ad placement |
|
||||
| 3 | SignalTypeDexUpdateLink | Dex social link updated |
|
||||
| 4 | SignalTypeDexTrendingBar | Dex trending bar |
|
||||
| 5 | SignalTypeDexBoost | Dex Boost |
|
||||
| 6 | SignalTypePriceUp | Price spike |
|
||||
| 7 | SignalTypePriceATH | All-time high price |
|
||||
| 8 | SignalTypeMcpKeyLevel | Market cap key level |
|
||||
| 9 | SignalTypeLive | Live stream |
|
||||
| 10 | SignalTypeBundlerSell | Bundler sell |
|
||||
| 11 | SignalTypeCto | Community takeover (CTO) |
|
||||
| 12 | SignalTypeSmartDegenBuy | Smart money buy |
|
||||
| 13 | SignalTypePlatformCall | Platform call |
|
||||
| 14 | SignalTypeLargeAmountBuy | Large amount buy |
|
||||
| 15 | SignalTypeMultiBuy | Multiple buys |
|
||||
| 16 | SignalTypeMultiLargeBuy | Multiple large buys |
|
||||
| 17 | SignalTypeBagsClaims | Bags Claim |
|
||||
| 18 | SignalTypePumpClaims | Pump Claim |
|
||||
|
||||
### `market signal` Response Fields
|
||||
|
||||
Each item in the response array is one signal event:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | Signal event ID |
|
||||
| `token_address` | string | Token contract address |
|
||||
| `signal_type` | number | Signal type (1–18, see Signal Types above) |
|
||||
| `trigger_at` | number | Unix timestamp (seconds) when the signal was triggered |
|
||||
| `trigger_mc` | number | Market cap at signal trigger time (USD) |
|
||||
| `first_trigger_mc` | number | Market cap at the very first trigger for this token (USD) |
|
||||
| `market_cap` | number | Current market cap (USD) |
|
||||
| `ath` | number | All-time high market cap (USD) |
|
||||
| `signal_times` | number | Total number of times this signal has triggered for this token |
|
||||
| `signal_times_by_type` | object | Signal trigger count broken down by type |
|
||||
| `cur_data` | object | Real-time token stats at query time (see below) |
|
||||
| `data` | object | Full upstream snapshot at trigger time (chain-specific, raw passthrough) |
|
||||
|
||||
**`cur_data` fields:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `top_10_holder_rate` | number | Top 10 holder concentration ratio (0–1) |
|
||||
| `holder_count` | number | Current holder count |
|
||||
| `liquidity` | number | Current liquidity (USD) |
|
||||
|
||||
### Usage Examples
|
||||
|
||||
```bash
|
||||
# All signals on SOL (no --signal-type: upstream returns all types, including 14–16 if present)
|
||||
gmgn-cli market signal --chain sol --raw
|
||||
|
||||
# Smart money buys only (type 12)
|
||||
gmgn-cli market signal --chain sol --signal-type 12 --raw
|
||||
|
||||
# Price spikes + ATH (types 6 and 7) with market cap filter
|
||||
gmgn-cli market signal --chain sol \
|
||||
--signal-type 6 --signal-type 7 \
|
||||
--mc-min 50000 --mc-max 5000000 --raw
|
||||
|
||||
# Smart money buys on BSC
|
||||
gmgn-cli market signal --chain bsc --signal-type 12 --raw
|
||||
|
||||
# Multi-group: parallel groups (do not use signal_type 14–16 — API returns 400)
|
||||
gmgn-cli market signal --chain sol \
|
||||
--groups '[{"signal_type":[12]},{"signal_type":[6,7]}]' --raw
|
||||
|
||||
# Multi-group: combine signal type filter with market cap range per group
|
||||
gmgn-cli market signal --chain sol \
|
||||
--groups '[{"signal_type":[12,13],"mc_min":100000},{"signal_type":[6,7],"mc_min":50000,"mc_max":1000000}]' --raw
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- `market kline`: `--from` and `--to` are Unix timestamps in **seconds** — CLI converts to milliseconds automatically
|
||||
- `market trending`: `--filter` and `--platform` are repeatable flags
|
||||
- All commands use normal auth (API Key only, no signature)
|
||||
- All commands use exist auth (API Key only, no signature)
|
||||
- If the user doesn't provide kline timestamps, calculate them from the current time based on their desired time range
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Input validation** — Token addresses obtained from trending results are external data. Validate address format against the chain before passing to other commands (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits). The CLI enforces this at runtime.
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
---
|
||||
name: gmgn-portfolio
|
||||
description: Query GMGN wallet portfolio — API Key wallet info, holdings, transaction activity, trading stats, and token balance. Supports sol / bsc / base.
|
||||
argument-hint: "<info|holdings|activity|stats|token-balance> [--chain <sol|bsc|base>] [--wallet <wallet_address>]"
|
||||
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>]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli portfolio --help"
|
||||
---
|
||||
|
||||
**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."**
|
||||
|
||||
Use the `gmgn-cli` tool to query wallet portfolio data based on the user's request.
|
||||
|
||||
**For full wallet analysis (holdings + stats + activity + verdict), follow [`docs/workflow-wallet-analysis.md`](../../docs/workflow-wallet-analysis.md)**
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **`realized_profit` vs `unrealized_profit`** — `realized_profit` = profit locked in from completed sells (cash in hand). `unrealized_profit` = paper gains on positions still held, calculated at current price. These are separate numbers — do not add them unless answering "total P&L including open positions."
|
||||
|
||||
- **`profit_change`** — A multiplier ratio, not a dollar amount. `1.5` = +150% return. `0` = break-even. `-0.5` = -50% loss. Computed as `total_profit / cost`. Do not display this as a raw decimal — convert to percentage for user-facing output.
|
||||
|
||||
- **`pnl`** — Profit/loss ratio from `portfolio stats`: `realized_profit / total_cost`. Same multiplier format as `profit_change`. A `pnl` of `2.0` means the wallet doubled its money on completed trades over the period.
|
||||
|
||||
- **`winrate`** — Ratio of profitable trades over the period (0–1). `0.6` = 60% of trades were profitable. Does not reflect the size of wins vs losses — a wallet can have high winrate but net negative if losses are large.
|
||||
|
||||
- **`cost` vs `usd_value`** — In holdings: `cost` is the historical amount spent buying this token (your cost basis); `usd_value` is the current market value of the position. The difference is unrealized P&L.
|
||||
|
||||
- **`history_bought_cost` vs `cost`** — `history_bought_cost` is the all-time cumulative spend on this token (including positions already sold). `cost` is the cost basis of the current open position only.
|
||||
|
||||
- **Pagination (`cursor`)** — Activity results are paginated. The response includes a `next` field; pass it as `--cursor` to fetch the next page. An empty or missing `next` means you are on the last page.
|
||||
|
||||
## Sub-commands
|
||||
|
||||
| Sub-command | Description |
|
||||
@@ -15,16 +39,59 @@ Use the `gmgn-cli` tool to query wallet portfolio data based on the user's reque
|
||||
| `portfolio activity` | Transaction history |
|
||||
| `portfolio stats` | Trading statistics (supports batch) |
|
||||
| `portfolio token-balance` | Token balance for a specific token |
|
||||
| `portfolio created-tokens` | Tokens created by a developer wallet, with market cap and ATH info |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base`
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `.env` file with `GMGN_API_KEY` set
|
||||
- Run from the directory where your `.env` file is located, or set `GMGN_HOST` in your environment
|
||||
- `gmgn-cli` installed globally: `npm install -g gmgn-cli@1.0.1`
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
- `GMGN_API_KEY` configured in `~/.config/gmgn/.env`
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All portfolio routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
**Critical auth** (`GMGN_API_KEY` + `GMGN_PRIVATE_KEY` required):
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `portfolio holdings` | `GET /v1/user/wallet_holdings` | 5 |
|
||||
|
||||
**Exist auth** (`GMGN_API_KEY` only):
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `portfolio info` | `GET /v1/user/info` | 1 |
|
||||
| `portfolio activity` | `GET /v1/user/wallet_activity` | 3 |
|
||||
| `portfolio stats` | `GET /v1/user/wallet_stats` | 3 |
|
||||
| `portfolio token-balance` | `GET /v1/user/wallet_token_balance` | 1 |
|
||||
| `portfolio created-tokens` | `GET /v1/user/created_tokens` | 2 |
|
||||
|
||||
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.
|
||||
|
||||
**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
|
||||
|
||||
@@ -67,9 +134,39 @@ gmgn-cli portfolio stats --chain sol \
|
||||
# Token balance
|
||||
gmgn-cli portfolio token-balance \
|
||||
--chain sol --wallet <wallet_address> --token <token_address>
|
||||
|
||||
# Tokens created by a developer wallet
|
||||
gmgn-cli portfolio created-tokens --chain sol --wallet <wallet_address>
|
||||
|
||||
# Created tokens sorted by all-time high market cap
|
||||
gmgn-cli portfolio created-tokens \
|
||||
--chain sol --wallet <wallet_address> \
|
||||
--order-by token_ath_mc --direction desc
|
||||
|
||||
# Only migrated tokens
|
||||
gmgn-cli portfolio created-tokens \
|
||||
--chain sol --wallet <wallet_address> --migrate-state migrated
|
||||
|
||||
# ETH wallet holdings
|
||||
gmgn-cli portfolio holdings --chain eth --wallet <0x_wallet_address>
|
||||
|
||||
# ETH wallet transaction activity
|
||||
gmgn-cli portfolio activity --chain eth --wallet <0x_wallet_address>
|
||||
|
||||
# ETH token balance
|
||||
gmgn-cli portfolio token-balance \
|
||||
--chain eth --wallet <0x_wallet_address> --token <0x_token_address>
|
||||
```
|
||||
|
||||
## Holdings Options
|
||||
## `portfolio created-tokens` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--order-by <field>` | Sort field: `market_cap` / `token_ath_mc` |
|
||||
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
||||
| `--migrate-state <state>` | Filter by migration status: `migrated` (graduated to DEX) / `non_migrated` (still on bonding curve) |
|
||||
|
||||
## `portfolio holdings` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
@@ -77,33 +174,214 @@ gmgn-cli portfolio token-balance \
|
||||
| `--cursor <cursor>` | Pagination cursor |
|
||||
| `--order-by <field>` | Sort field: `usd_value` / `last_active_timestamp` / `realized_profit` / `unrealized_profit` / `total_profit` / `history_bought_cost` / `history_sold_income` (default `usd_value`) |
|
||||
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
||||
| `--sell-out` | Include sold-out positions |
|
||||
| `--show-small` | Include small-value positions |
|
||||
| `--hide-abnormal` | Hide abnormal positions |
|
||||
| `--hide-airdrop` | Hide airdrop positions |
|
||||
| `--hide-closed` | Hide closed positions |
|
||||
| `--hide-abnormal <bool>` | Hide abnormal positions: `true` / `false` (default: `false`) |
|
||||
| `--hide-airdrop <bool>` | Hide airdrop positions: `true` / `false` (default: `true`) |
|
||||
| `--hide-closed <bool>` | Hide closed positions: `true` / `false` (default: `true`) |
|
||||
| `--hide-open` | Hide open positions |
|
||||
|
||||
## Activity Options
|
||||
## `portfolio activity` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--token <address>` | Filter by token |
|
||||
| `--limit <n>` | Page size |
|
||||
| `--cursor <cursor>` | Pagination cursor (pass the `next` value from the previous response) |
|
||||
| `--type <type>` | Repeatable: `buy` / `sell` / `add` / `remove` / `transfer` |
|
||||
| `--type <type>` | Repeatable: `buy` / `sell` / `transferIn` / `transferOut` / `add` / `remove` |
|
||||
|
||||
The activity response includes a `next` field. Pass it to `--cursor` to fetch the next page.
|
||||
|
||||
## Stats Options
|
||||
## `portfolio stats` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--period <period>` | Stats period: `7d` / `30d` (default `7d`) |
|
||||
|
||||
## Response Field Reference
|
||||
|
||||
### `portfolio holdings` — Key Fields
|
||||
|
||||
The response has a `holdings` array. Each item is one token position.
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `token.address` | Token contract address |
|
||||
| `token.symbol` / `token.name` | Token ticker and full name |
|
||||
| `token.price` | Current token price in USD |
|
||||
| `balance` | Current token balance (human-readable units) |
|
||||
| `usd_value` | Current USD value of this position |
|
||||
| `cost` | Total amount spent buying this token (USD) |
|
||||
| `realized_profit` | Profit from completed sells (USD) |
|
||||
| `unrealized_profit` | Profit on current unsold holdings at current price (USD) |
|
||||
| `total_profit` | `realized_profit + unrealized_profit` (USD) |
|
||||
| `profit_change` | Total profit ratio = `total_profit / cost` (e.g. `1.5` = +150%) |
|
||||
| `avg_cost` | Average buy price per token (USD) |
|
||||
| `buy_tx_count` | Number of buy transactions |
|
||||
| `sell_tx_count` | Number of sell transactions |
|
||||
| `last_active_timestamp` | Unix timestamp of the most recent transaction |
|
||||
| `history_bought_cost` | Total USD spent buying (all-time) |
|
||||
| `history_sold_income` | Total USD received from selling (all-time) |
|
||||
|
||||
### `portfolio activity` — Key Fields
|
||||
|
||||
The response has a `activities` array and a `next` cursor field for pagination.
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `transaction_hash` | On-chain transaction hash |
|
||||
| `type` | Transaction type: `buy` / `sell` / `add` / `remove` / `transfer` |
|
||||
| `token.address` | Token contract address |
|
||||
| `token.symbol` | Token ticker |
|
||||
| `token_amount` | Token quantity in this transaction |
|
||||
| `cost_usd` | USD value of this transaction |
|
||||
| `price` | Token price denominated in the quote token of the trading pair at time of transaction |
|
||||
| `price_usd` | Token price in USD at time of transaction |
|
||||
| `timestamp` | Unix timestamp of the transaction |
|
||||
| `next` | Pagination cursor — pass to `--cursor` to fetch the next page |
|
||||
|
||||
### `portfolio stats` — Key Fields
|
||||
|
||||
The response is an object (or array for batch). Key fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `realized_profit` | Total realized profit over the period (USD) |
|
||||
| `unrealized_profit` | Total unrealized profit on open positions (USD) |
|
||||
| `winrate` | Win rate — ratio of profitable trades (0–1) |
|
||||
| `total_cost` | Total amount spent buying in the period (USD) |
|
||||
| `buy_count` | Number of buy transactions |
|
||||
| `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.created_at` | Wallet creation time (Unix seconds) — records when the first funding transaction arrived; use this as the wallet's age indicator |
|
||||
| `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.
|
||||
|
||||
### `portfolio created-tokens` — Key Fields
|
||||
|
||||
The response `data` object has a `tokens` array plus aggregate stats.
|
||||
|
||||
Top-level fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `last_create_timestamp` | Unix timestamp of the most recent token creation |
|
||||
| `inner_count` | Number of tokens still on the bonding curve (NOT graduated) |
|
||||
| `open_count` | Number of tokens that have graduated to DEX |
|
||||
| `open_ratio` | Graduation rate (string, e.g. `"0.25"`) |
|
||||
|
||||
> **Total created = `inner_count + open_count`**. Do NOT use `len(tokens)` as the total — the `tokens` array is capped at 100 entries and may be truncated.
|
||||
| `creator_ath_info` | Best-performing token created by this wallet (ATH market cap) |
|
||||
| `tokens` | Array of created tokens — see below |
|
||||
|
||||
`creator_ath_info` fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `creator` | Wallet address |
|
||||
| `ath_token` | Token address with highest ATH market cap |
|
||||
| `ath_mc` | ATH market cap (USD string) |
|
||||
| `token_symbol` / `token_name` | Token ticker and name |
|
||||
| `token_logo` | Logo URL |
|
||||
|
||||
Per-token fields (`tokens[*]`):
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `token_address` | Token contract address |
|
||||
| `symbol` | Token ticker |
|
||||
| `chain` | Chain name |
|
||||
| `create_timestamp` | Unix timestamp of creation |
|
||||
| `is_open` | `true` if graduated to DEX |
|
||||
| `market_cap` | Current market cap (USD string) |
|
||||
| `token_ath_mc` | All-time high market cap (USD string) |
|
||||
| `pool_liquidity` | Current liquidity (USD string) |
|
||||
| `holders` | Current holder count |
|
||||
| `swap_1h` | Swap count in the last hour |
|
||||
| `volume_1h` | Trading volume in the last hour (USD string) |
|
||||
| `launchpad_platform` | Launch platform name (e.g. `Pump.fun`) |
|
||||
| `is_pump` | `true` if launched on Pump.fun |
|
||||
| `bundler_rate` | Bundler participation rate (0–1) |
|
||||
| `cto_flag` | `true` if community-takeover token |
|
||||
|
||||
**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
|
||||
|
||||
**Do NOT dump raw JSON.** Always parse and present data in the structured formats below. Use `--raw` only when piping to `jq` or further processing.
|
||||
|
||||
### `portfolio holdings` — Holdings Table
|
||||
|
||||
Present a table sorted by `usd_value` (descending). Show total portfolio value at the top.
|
||||
|
||||
```
|
||||
Wallet: {wallet} | Chain: {chain}
|
||||
Total value: ~${sum of usd_value across all positions}
|
||||
|
||||
# | Token | Balance | USD Value | Total P&L | P&L% | Avg Cost | Buys / Sells
|
||||
```
|
||||
|
||||
Flag positions where `profit_change` is strongly negative (e.g. < -50%) or positive (e.g. > 200%) with a brief note.
|
||||
|
||||
### `portfolio activity` — Activity Feed
|
||||
|
||||
Present as a chronological list (newest first). Use human-readable timestamps.
|
||||
|
||||
```
|
||||
{type} {token.symbol} | {token_amount} tokens | ${cost_usd} | {timestamp} | tx: {short hash}
|
||||
```
|
||||
|
||||
Group by token if the user asks about a specific token.
|
||||
|
||||
### `portfolio stats` — Stats Summary
|
||||
|
||||
```
|
||||
Wallet: {wallet} | Period: {period}
|
||||
Realized P&L: ${realized_profit}
|
||||
Unrealized P&L: ${unrealized_profit}
|
||||
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}]
|
||||
```
|
||||
|
||||
Show the `[Identity: ...]` line only if `common` is present in the response. For batch queries (multiple wallets), present one summary block per wallet.
|
||||
|
||||
## Notes
|
||||
|
||||
- All portfolio commands use normal auth (API Key only, no signature required)
|
||||
- `portfolio holdings` uses **critical auth** (`GMGN_API_KEY` + `GMGN_PRIVATE_KEY` required — CLI signs the request automatically). All other portfolio commands use exist auth (API Key only, no signature required).
|
||||
- `portfolio stats` supports multiple `--wallet` flags for batch queries
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Input validation** — Wallet and token addresses are validated against the expected chain format at runtime (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits). The CLI exits with an error on invalid input.
|
||||
- For follow-wallet, KOL, and Smart Money trade records, use the `gmgn-track` skill (`track follow-wallet` / `track kol` / `track smartmoney`)
|
||||
|
||||
## Workflow
|
||||
|
||||
For full wallet analysis including trade history and follow-through on top holdings, see [`docs/workflow-wallet-analysis.md`](../../docs/workflow-wallet-analysis.md)
|
||||
|
||||
For in-depth trading style analysis, copy-trade ROI estimation, and smart money leaderboard comparison, see [`docs/workflow-smart-money-profile.md`](../../docs/workflow-smart-money-profile.md)
|
||||
|
||||
**When to use which:**
|
||||
- User asks "is this wallet worth following" → [`docs/workflow-wallet-analysis.md`](../../docs/workflow-wallet-analysis.md)
|
||||
- User asks "what's this wallet's trading style", "when does he take profit", "smart money profile", "if I copied this wallet what would my return be" → [`docs/workflow-smart-money-profile.md`](../../docs/workflow-smart-money-profile.md)
|
||||
- User wants to compare multiple smart money wallets by winrate/PnL → [`docs/workflow-smart-money-profile.md`](../../docs/workflow-smart-money-profile.md) Step 5 (leaderboard)
|
||||
- User asks "what tokens did this dev create", "dev 发过哪些币", "查一下这个 dev 的代币", "dev 创建记录" → use `portfolio created-tokens --chain <chain> --wallet <creator_address>` directly. Get the creator address first via `token info` if only a token address is given.
|
||||
|
||||
@@ -1,16 +1,42 @@
|
||||
---
|
||||
name: gmgn-swap
|
||||
description: "[FINANCIAL EXECUTION] Submit a real blockchain token swap or query order status. Executes irreversible on-chain transactions. Requires explicit user confirmation before every swap. Supports sol / bsc / base."
|
||||
argument-hint: "[--chain <chain> --from <wallet> --input-token <addr> --output-token <addr> --amount <n>] | [order get --chain <chain> --order-id <id>]"
|
||||
description: "[FINANCIAL EXECUTION] Buy and sell meme coins and crypto tokens on Solana, BSC, Base, or Ethereum — single swap, multi-wallet batch trading, limit orders, stop loss, take profit, trailing stop loss, trailing take profit via GMGN API. Requires explicit user confirmation. Use when user asks to buy, sell, or swap a token, trade from multiple wallets, set a limit order, stop loss, take profit, or check order status."
|
||||
argument-hint: "[--chain <chain> --from <wallet> --input-token <addr> --output-token <addr> --amount <n>] | [order get --chain <chain> --order-id <id>] | [gas-price --chain <eth|bsc|base|sol>] | [order strategy list --chain <chain> --group-tag <LimitOrder|STMix>] | [order strategy create --chain <chain> --order-type <limit_order|smart_trade> --sub-order-type <buy_low|buy_high|stop_loss|take_profit|mix_trade> ...]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli swap --help"
|
||||
---
|
||||
|
||||
Use the `gmgn-cli` tool to submit a token swap or query an existing order. **Requires private key** (`GMGN_PRIVATE_KEY` in `.env`).
|
||||
**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.**
|
||||
|
||||
**⚠️ 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. `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
|
||||
|
||||
- **Smallest unit** — `--amount` is always in the token's smallest indivisible unit, not human-readable amounts. For SOL: 1 SOL = 1,000,000,000 lamports. For EVM tokens: depends on decimals (most ERC-20 tokens use 18 decimals). Always convert before passing to the command — do not pass human amounts directly.
|
||||
|
||||
- **`slippage`** — Price tolerance expressed as a decimal, not a percentage. `0.01` = 1% slippage. `0.5` = 50% slippage. If the price moves beyond this threshold before the transaction confirms, the swap is rejected. Use `--auto-slippage` for volatile tokens to let GMGN set an appropriate value automatically.
|
||||
|
||||
- **`--amount` vs `--percent`** — Mutually exclusive. `--amount` specifies an exact input quantity (in smallest unit). `--percent` sells a percentage of the current balance and is only valid when `input_token` is NOT a currency (SOL/BNB/ETH/USDC). Never use `--percent` to spend a fraction of SOL/BNB/ETH.
|
||||
|
||||
- **Currency tokens** — Each chain has designated currency tokens (SOL, BNB, ETH, USDC). These are the base assets used to buy other tokens or receive swap proceeds. Their contract addresses are fixed — look them up in the Chain Currencies table, never guess them.
|
||||
|
||||
- **Anti-MEV** — MEV (Miner/Maximal Extractable Value) refers to frontrunning and sandwich attacks where bots exploit pending transactions. `--anti-mev` routes the transaction through protected channels to reduce this risk. **Recommended: always enable.** Default: on. **Not supported on `base` chain.**
|
||||
|
||||
- **Signed auth** — `swap` and all `order` subcommands require both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY`. The private key never leaves the machine — the CLI uses it only for local signing and sends only the resulting signature.
|
||||
|
||||
- **`order_id` / `status`** — After submitting a swap, the response includes an `order_id`. Use `order get --order-id` to poll for final status. Possible values: `pending` → `processed` → `confirmed` (success) or `failed` / `expired`. Do not report success until status is `confirmed`.
|
||||
|
||||
- **`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.
|
||||
@@ -20,33 +46,78 @@ Use the `gmgn-cli` tool to submit a token swap or query an existing order. **Req
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `swap` | Submit a token swap |
|
||||
| `multi-swap` | Submit token swaps across multiple wallets concurrently (up to 100) |
|
||||
| `order quote` | Get a swap quote (no transaction submitted; requires signed auth) |
|
||||
| `order get` | Query order status |
|
||||
| `gas-price` | Query recommended gas price (low / average / high tiers) for any chain; exist auth (API Key only) |
|
||||
| `order strategy create` | Create a limit/strategy order (requires private key) |
|
||||
| `order strategy list` | List strategy orders (requires private key) |
|
||||
| `order strategy cancel` | Cancel a strategy order (requires private key) |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base`
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
|
||||
## Chain Currencies
|
||||
|
||||
Currency tokens are the base/native assets of each chain. They are used to buy other tokens or receive proceeds from selling. Knowing which tokens are currencies is critical for `--percent` usage (see Swap Parameters below).
|
||||
|
||||
| Chain | Currency tokens |
|
||||
|-------|----------------|
|
||||
| `sol` | SOL (native, So11111111111111111111111111111111111111112), USDC (`EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`) |
|
||||
| `bsc` | BNB (native, 0x0000000000000000000000000000000000000000), USDC (`0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d`) |
|
||||
| `base` | ETH (native, 0x0000000000000000000000000000000000000000), USDC (`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) |
|
||||
> ⚠️ **CRITICAL: Always copy currency addresses from this table — NEVER rely on memory or training data.** A wrong address (e.g. `So11111111111111111111111111111111111111111` instead of `So11111111111111111111111111111111111111112`) will cause silent failures or `jupiter has no route` errors with no clear indication of what went wrong.
|
||||
|
||||
| Chain | Currency tokens |
|
||||
| ------ | --------------- |
|
||||
| `sol` | SOL (native, `So11111111111111111111111111111111111111112`), USDC (`EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`) |
|
||||
| `bsc` | BNB (native, `0x0000000000000000000000000000000000000000`), USDC (`0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d`) |
|
||||
| `base` | ETH (native, `0x0000000000000000000000000000000000000000`), USDC (`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) |
|
||||
| `eth` | ETH (native, `0x0000000000000000000000000000000000000000`) |
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Both `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` must be set in `.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` must be installed globally before use (one-time setup):
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
|
||||
```bash
|
||||
npm install -g gmgn-cli@1.0.1
|
||||
```
|
||||
## Rate Limit Handling
|
||||
|
||||
All swap-related routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `swap` | `POST /v1/trade/swap` | 5 |
|
||||
| `multi-swap` | `POST /v1/trade/multi_swap` | 5 |
|
||||
| `order quote` | `GET /v1/trade/quote` | 2 |
|
||||
| `order get` | `GET /v1/trade/query_order` | 1 |
|
||||
| `order strategy create` | `POST /v1/trade/strategy/create` | 5 |
|
||||
| `order strategy cancel` | `POST /v1/trade/strategy/cancel` | 2 |
|
||||
| `order strategy list` | `GET /v1/trade/strategy/orders` | 1 |
|
||||
| `gas-price` | `GET /v1/trade/gas_price` | 1 |
|
||||
|
||||
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.
|
||||
- `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
|
||||
|
||||
@@ -54,7 +125,9 @@ npm install -g gmgn-cli@1.0.1
|
||||
- `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
|
||||
---
|
||||
|
||||
## `swap` Usage
|
||||
|
||||
```bash
|
||||
# Basic swap
|
||||
@@ -74,6 +147,15 @@ gmgn-cli swap \
|
||||
--amount 1000000 \
|
||||
--slippage 0.01
|
||||
|
||||
# With automatic slippage
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token <input_token_address> \
|
||||
--output-token <output_token_address> \
|
||||
--amount 1000000 \
|
||||
--auto-slippage
|
||||
|
||||
# With anti-MEV (SOL)
|
||||
gmgn-cli swap \
|
||||
--chain sol \
|
||||
@@ -92,56 +174,599 @@ gmgn-cli swap \
|
||||
--percent 50
|
||||
```
|
||||
|
||||
## Order Query
|
||||
## `swap` Parameters
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
| `--amount` | No* | all | Input amount in smallest unit. **Mutually exclusive with `--percent`** — provide one or the other, never both. Required unless `--percent` is used. |
|
||||
| `--percent <pct>` | No* | all | Sell percentage of `input_token`, e.g. `50` = 50%, `1` = 1%. Sets `input_amount` to `0` automatically. **Mutually exclusive with `--amount`. Only valid when `input_token` is NOT a currency (SOL/BNB/ETH/USDC).** |
|
||||
| `--slippage <n>` | No | all | Slippage tolerance, e.g. `0.01` = 1%. **Mutually exclusive with `--auto-slippage`** — use one or the other. |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage. **Mutually exclusive with `--slippage`.** |
|
||||
| `--min-output <n>` | No | all | Minimum output amount |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection — **recommended**; protects against frontrunning and sandwich attacks. Default: on. **Not supported on `base`.** |
|
||||
| `--priority-fee <sol>` | No | `sol` | Priority fee in SOL (≥ 0.00001). Required when using `--condition-orders` on SOL. |
|
||||
| `--tip-fee <n>` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). Required when using `--condition-orders` on SOL. |
|
||||
| `--gas-price <gwei>` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). Required when using `--condition-orders` on BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level <level>` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas <n>` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. Defaults to `--gas-price` if omitted (BASE/ETH). |
|
||||
| `--max-priority-fee-per-gas <n>` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--condition-orders <json>` | No | all | JSON array of condition sub-orders (take-profit / stop-loss) to attach after a successful swap. **Max 10 sub-orders.** Strategy creation is best-effort: if the swap succeeds but strategy creation fails, the swap result is still returned. See ConditionOrder fields below. |
|
||||
| `--sell-ratio-type <type>` | No | all | **Only with `--condition-orders`.** Sell ratio basis: `buy_amount` (default) — sells a fixed token amount stored at strategy creation time; `hold_amount` — sells a fixed percentage of the position held at trigger time |
|
||||
|
||||
### ConditionOrder Fields (for `--condition-orders`)
|
||||
|
||||
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 (requires signed auth and `GMGN_PRIVATE_KEY` on every supported quote chain):
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
--chain <chain> \
|
||||
--from <wallet> \
|
||||
--input-token <input_token> \
|
||||
--output-token <output_token> \
|
||||
--amount <amount> \
|
||||
--slippage <slippage>
|
||||
```
|
||||
|
||||
Then display the confirmation summary using `output_amount` from the quote response:
|
||||
|
||||
```
|
||||
⚠️ Swap Confirmation Required
|
||||
|
||||
Chain: {chain}
|
||||
Wallet: {--from}
|
||||
Sell: {input amount in human units} {input token symbol}
|
||||
Buy: {output token symbol}
|
||||
Slippage: {slippage}% (or "auto")
|
||||
Est. output: ~{output_amount from quote} {output token symbol}
|
||||
Risk Level: 🟢 Low / 🟡 Medium / 🔴 High (based on rug_ratio from security check)
|
||||
|
||||
Reply "confirm" to proceed.
|
||||
```
|
||||
|
||||
**Note**: `Risk Level` is derived from the required security check:
|
||||
- 🟢 Low: `rug_ratio < 0.1`
|
||||
- 🟡 Medium: `rug_ratio 0.1–0.3`
|
||||
- 🔴 High: `rug_ratio > 0.3` (requires re-confirmation)
|
||||
|
||||
If the user explicitly skipped the security check, omit the Risk Level line and add a note: "(Security check skipped by user)"
|
||||
|
||||
### Post-swap Receipt
|
||||
|
||||
After a confirmed swap, display:
|
||||
|
||||
```
|
||||
✅ Swap Confirmed
|
||||
|
||||
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 `report.input_amount` and `report.output_amount` from smallest unit using `report.input_token_decimals` and `report.output_token_decimals` before displaying.
|
||||
|
||||
---
|
||||
|
||||
## `multi-swap` Usage
|
||||
|
||||
Submit a token swap across multiple wallets concurrently. Each wallet executes independently — one wallet's failure does not affect others. Up to 100 wallets per request. All wallets must be bound to the API Key. Requires `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
# Basic multi-wallet swap
|
||||
gmgn-cli multi-swap \
|
||||
--chain sol \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token <input_token_address> \
|
||||
--output-token <output_token_address> \
|
||||
--input-amount '{"<addr1>":"1000000","<addr2>":"2000000"}' \
|
||||
--slippage 0.01
|
||||
|
||||
# Sell a percentage of each wallet's balance (use --input-amount-bps)
|
||||
gmgn-cli multi-swap \
|
||||
--chain sol \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token <token_address> \
|
||||
--output-token <sol_address> \
|
||||
--input-amount-bps '{"<addr1>":"5000","<addr2>":"10000"}' \
|
||||
--slippage 0.01
|
||||
|
||||
# With per-wallet take-profit / stop-loss (condition_orders)
|
||||
gmgn-cli multi-swap \
|
||||
--chain sol \
|
||||
--accounts <addr1>,<addr2> \
|
||||
--input-token So11111111111111111111111111111111111111112 \
|
||||
--output-token <token_address> \
|
||||
--input-amount '{"<addr1>":"1000000","<addr2>":"2000000"}' \
|
||||
--slippage 0.3 \
|
||||
--priority-fee 0.00001 \
|
||||
--tip-fee 0.00001 \
|
||||
--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"}]'
|
||||
|
||||
# ETH multi-wallet swap (EIP-1559 gas)
|
||||
gmgn-cli multi-swap \
|
||||
--chain eth \
|
||||
--accounts <0xaddr1>,<0xaddr2> \
|
||||
--input-token 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 \
|
||||
--output-token <token_address> \
|
||||
--input-amount '{"<0xaddr1>":"1000000","<0xaddr2>":"2000000"}' \
|
||||
--slippage 0.01 \
|
||||
--gas-price 5
|
||||
```
|
||||
|
||||
## `multi-swap` Parameters
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
| `--input-amount` | No* | all | JSON map of `wallet_address → input amount` (smallest unit). One of `--input-amount`, `--input-amount-bps`, or `--output-amount` is required. |
|
||||
| `--input-amount-bps` | No* | all | JSON map of `wallet_address → percent in bps` (1–10000; 5000 = 50%). Only valid when `input_token` is NOT a currency. |
|
||||
| `--output-amount` | No* | all | JSON map of `wallet_address → target output amount` (smallest unit). |
|
||||
| `--slippage <n>` | No | all | Slippage tolerance, e.g. `0.01` = 1%. Mutually exclusive with `--auto-slippage`. |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage. |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection. Not supported on `base`. |
|
||||
| `--priority-fee <sol>` | No | `sol` | Priority fee in SOL (≥ 0.00001). Required when using `--condition-orders` on SOL. |
|
||||
| `--tip-fee <amount>` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). Required when using `--condition-orders` on SOL. |
|
||||
| `--gas-price <gwei>` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). Required when using `--condition-orders` on BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level <level>` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--auto-fee` | No | `eth` | **Only with `--condition-orders`.** GMGN automatically selects the optimal fee. |
|
||||
| `--max-fee-per-gas <amount>` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. Defaults to `--gas-price` if omitted (BASE/ETH). |
|
||||
| `--max-priority-fee-per-gas <amount>` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--condition-orders <json>` | No | all | JSON array of condition sub-orders (take-profit / stop-loss) attached to each successful wallet's swap. Same structure as `swap --condition-orders`. Strategy creation is best-effort per wallet. |
|
||||
| `--sell-ratio-type <type>` | No | all | **Only with `--condition-orders`.** Sell ratio base: `buy_amount` (default) / `hold_amount`. |
|
||||
|
||||
## `multi-swap` Response Fields
|
||||
|
||||
The response `data` is an array — one element per wallet:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `account` | string | Wallet address |
|
||||
| `success` | bool | Whether this wallet's swap succeeded |
|
||||
| `error` | string | Error message on failure; absent on success |
|
||||
| `error_code` | string | Error code on failure; absent on success |
|
||||
| `result` | object | On success: OrderResponse (same fields as `swap` response). On failure: absent. |
|
||||
| `result.strategy_order_id` | string | Strategy order ID; only present when `--condition-orders` was passed and strategy creation succeeded (best-effort) |
|
||||
|
||||
---
|
||||
|
||||
## `order quote` Usage
|
||||
|
||||
Get an estimated output amount before submitting a swap. All supported quote chains use signed auth and require `GMGN_PRIVATE_KEY`.
|
||||
|
||||
```bash
|
||||
gmgn-cli order quote \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--input-token <input_token_address> \
|
||||
--output-token <output_token_address> \
|
||||
--amount <input_amount_smallest_unit> \
|
||||
--slippage 0.01
|
||||
```
|
||||
|
||||
### `order quote` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `input_token` | string | Input token contract address |
|
||||
| `output_token` | string | Output token contract address |
|
||||
| `input_amount` | string | Input amount (smallest unit) |
|
||||
| `output_amount` | string | Expected output amount (smallest unit) |
|
||||
| `min_output_amount` | string | Minimum output after slippage |
|
||||
| `slippage` | number | Actual slippage percentage |
|
||||
|
||||
---
|
||||
|
||||
## `order get` Usage
|
||||
|
||||
```bash
|
||||
gmgn-cli order get --chain sol --order-id <order_id>
|
||||
```
|
||||
|
||||
## Swap Parameters
|
||||
Response fields are shared with `swap` — see [`swap` / `order get` Response Fields](#swap--order-get-response-fields) above.
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
||||
| `--from` | Yes | Wallet address (must match API Key binding) |
|
||||
| `--input-token` | Yes | Input token contract address |
|
||||
| `--output-token` | Yes | Output token contract address |
|
||||
| `--amount` | No* | Input amount in smallest unit. Required unless `--percent` is used. |
|
||||
| `--percent <pct>` | No* | Sell percentage of `input_token`, e.g. `50` = 50%, `1` = 1%. Sets `input_amount` to `0` automatically. **Only valid when `input_token` is NOT a currency (SOL/BNB/ETH/USDC).** |
|
||||
| `--slippage <n>` | No | Slippage tolerance, e.g. `0.01` = 1% |
|
||||
| `--min-output <n>` | No | Minimum output amount |
|
||||
| `--anti-mev` | No | Enable anti-MEV protection (default true) |
|
||||
| `--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) |
|
||||
---
|
||||
|
||||
## Swap Response Fields
|
||||
## `gas-price` Usage
|
||||
|
||||
Query recommended gas price tiers for any chain. API Key only — no signature or private key required.
|
||||
|
||||
```bash
|
||||
gmgn-cli gas-price --chain eth
|
||||
gmgn-cli gas-price --chain bsc
|
||||
gmgn-cli gas-price --chain base
|
||||
gmgn-cli gas-price --chain sol
|
||||
```
|
||||
|
||||
### `gas-price` Response Fields
|
||||
|
||||
All fields are omitempty — fields unsupported by a chain are omitted. Units are chain-native (wei for EVM chains; lamports / chain-native for SOL).
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | ------- | ----------- |
|
||||
| `chain` | string | Chain identifier |
|
||||
| `auto` | string | Automatic gas price |
|
||||
| `auto_mev` | string | Anti-MEV automatic gas price |
|
||||
| `last_block` | int64 | Latest block number |
|
||||
| `high` | string | High-priority gas price |
|
||||
| `average` | string | Average-priority gas price |
|
||||
| `low` | string | Low-priority gas price |
|
||||
| `suggest_base_fee` | string | Suggested base fee |
|
||||
| `high_prio_fee` | string | High-priority fee |
|
||||
| `average_prio_fee` | string | Average-priority fee |
|
||||
| `low_prio_fee` | string | Low-priority fee |
|
||||
| `high_prio_fee_mixed` | string | High mixed priority fee |
|
||||
| `average_prio_fee_mixed` | string | Average mixed priority fee |
|
||||
| `low_prio_fee_mixed` | string | Low mixed priority fee |
|
||||
| `native_token_usd_price` | float32 | Native token USD price |
|
||||
| `high_estimate_time` | int64 | Estimated confirmation time for high tier (seconds) |
|
||||
| `average_estimate_time` | int64 | Estimated confirmation time for average tier (seconds) |
|
||||
| `low_estimate_time` | int64 | Estimated confirmation time for low tier (seconds) |
|
||||
| `high_orign` | string | High-priority raw origin value |
|
||||
| `average_orign` | string | Average-priority raw origin value |
|
||||
| `low_orign` | string | Low-priority raw origin value |
|
||||
|
||||
---
|
||||
|
||||
## `order strategy create` Usage
|
||||
|
||||
```bash
|
||||
# Create a take-profit order: sell when price rises to target (limit_order)
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--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 \
|
||||
--slippage 0.01
|
||||
|
||||
# Create a stop-loss order: sell when price drops to target (limit_order)
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--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
|
||||
|
||||
# Create a smart_trade with buy_low entry + take-profit + stop-loss (smart_trade)
|
||||
gmgn-cli order strategy create \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--base-token <token_address> \
|
||||
--quote-token <sol_address> \
|
||||
--order-type smart_trade \
|
||||
--sub-order-type mix_trade \
|
||||
--open-price 0.000082 \
|
||||
--amount-in 1000000 \
|
||||
--slippage 0.01 \
|
||||
--condition-orders '[{"order_type":"buy_low","side":"buy","check_price":"0.00008"},{"order_type":"profit_stop","side":"sell","price_scale":"100","sell_ratio":"50"},{"order_type":"loss_stop","side":"sell","price_scale":"50","sell_ratio":"100"}]'
|
||||
```
|
||||
|
||||
## `order strategy create` Parameters
|
||||
|
||||
| Parameter | Required | Chain | Description |
|
||||
|-----------|----------|-------|-------------|
|
||||
| `--chain` | Yes | all | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
| `--order-type` | Yes | all | Order type: `limit_order` / `smart_trade` |
|
||||
| `--sub-order-type` | Yes | all | `limit_order`: `buy_low` / `buy_high` / `stop_loss` / `take_profit`; `smart_trade` with condition_orders: `mix_trade` |
|
||||
| `--check-price` | No* | all | Trigger price — required for `limit_order`; omit for `smart_trade` (trigger is in the `buy_low` condition order) |
|
||||
| `--open-price` | No | all | Open price of the position |
|
||||
| `--amount-in` | No* | all | Input amount (smallest unit). Mutually exclusive with `--amount-in-percent` |
|
||||
| `--amount-in-percent` | No* | all | Input as percentage (e.g. `50` = 50%). Mutually exclusive with `--amount-in` |
|
||||
| `--limit-price-mode` | No | all | `exact` / `slippage` (default: `slippage`) |
|
||||
| `--expire-in` | No | all | Order expiry in seconds |
|
||||
| `--sell-ratio-type` | No | all | `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 |
|
||||
| `--quote-investment` | No | all | Quote token investment amount (`smart_trade`) |
|
||||
| `--slippage` | No | all | Slippage tolerance, e.g. `0.01` = 1%. Mutually exclusive with `--auto-slippage` |
|
||||
| `--auto-slippage` | No | all | Enable automatic slippage |
|
||||
| `--priority-fee` | No | `sol` | Priority fee in SOL (≥ 0.00001). **Required** for SOL. |
|
||||
| `--tip-fee` | No | `sol` / `bsc` | Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB). **Required** for SOL. |
|
||||
| `--auto-fee` | No | `eth` | Auto fee mode — GMGN automatically selects the optimal fee. |
|
||||
| `--gas-price` | No | `bsc` / `base` / `eth` | Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01). **Required** for BSC. Mutually exclusive with `--gas-level`. |
|
||||
| `--gas-level` | No | `eth` | Gas price tier: `low` / `average` / `high`. Mutually exclusive with `--gas-price`. |
|
||||
| `--max-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max fee per gas. Clamped per chain minimums. |
|
||||
| `--max-priority-fee-per-gas` | No | `bsc` / `base` / `eth` | EIP-1559 max priority fee per gas. Clamped per chain minimums; capped to `--max-fee-per-gas`. |
|
||||
| `--anti-mev` | No | sol / bsc / eth | Enable anti-MEV protection. Not supported on `base`. |
|
||||
| `--condition-orders` | No | all | JSON array of condition sub-orders for `smart_trade`. Must include one `buy_low` entry (with `check_price` lower than `open_price`) plus at least one TP/SL entry. |
|
||||
|
||||
### `order strategy create` Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `order_id` | string | Order ID for follow-up queries |
|
||||
| `hash` | string | Transaction hash |
|
||||
| `state` | int | Order state code |
|
||||
| `confirmation.state` | string | `processed` / `confirmed` / `failed` / `expired` |
|
||||
| `confirmation.detail` | string | Confirmation detail message |
|
||||
| `error_code` | string | Error code on failure |
|
||||
| `error_status` | string | Error description on failure |
|
||||
| `height` | number | Block height of the transaction |
|
||||
| `order_height` | number | Block height when the order was placed |
|
||||
| `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 |
|
||||
| `order_id` | string | Created strategy order ID |
|
||||
| `is_update` | bool | `true` if an existing order was updated, `false` if newly created |
|
||||
|
||||
---
|
||||
|
||||
## `order strategy list` Usage
|
||||
|
||||
```bash
|
||||
# List open condition orders (profit_stop / loss_stop / trace types) — use STMix
|
||||
gmgn-cli order strategy list --chain sol --group-tag STMix
|
||||
|
||||
# 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>
|
||||
```
|
||||
|
||||
## `order strategy list` Parameters
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----------------- | ------ | ---- |
|
||||
| `next_page_token` | string | Cursor for next page; empty when no more data |
|
||||
| `total` | int | Total count (only returned when `--type open`) |
|
||||
| `list` | array | Array of strategy order objects; see fields below |
|
||||
|
||||
#### `list[]` — Strategy Order Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| -------------------------- | ------ | ---- |
|
||||
| `anti_mev_mode` | string | Anti-MEV mode string; empty when not set |
|
||||
| `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` |
|
||||
| `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 |
|
||||
| `close_sign_hash` | string | Close transaction hash; empty when order is open |
|
||||
| `close_time` | int | Close timestamp (ms); `0` when order is open |
|
||||
| `condition_orders` | array | Condition sub-orders; each element is an object — see `condition_orders[]` below |
|
||||
| `create_time` | int | Creation timestamp (ms) |
|
||||
| `custom_rpc` | string | Custom RPC endpoint; empty string when not set |
|
||||
| `dev_sell_ratio` | string | Dev sell trigger ratio; empty when not set |
|
||||
| `drawdown_rate` | string | Trailing drawdown rate for `profit_stop_trace` / `loss_stop_trace`; empty when not set |
|
||||
| `expire_time` | int | Expiration timestamp (ms) |
|
||||
| `fee` | string | Base transaction fee |
|
||||
| `gas_price` | string | Gas price |
|
||||
| `is_anti_mev` | bool | Whether anti-MEV protection is active |
|
||||
| `limit_price_mode` | string | Limit price mode; empty when not set |
|
||||
| `loss_stop` | string | Stop-loss trigger price; empty when not set |
|
||||
| `loss_stop_type` | string | Stop-loss type; empty when not set |
|
||||
| `max_fee_per_gas` | string | EIP-1559 max fee per gas; EVM only; empty on SOL |
|
||||
| `max_priority_fee_per_gas` | string | EIP-1559 max priority fee per gas; EVM only; empty on SOL |
|
||||
| `open_amount` | string | Token amount at open (smallest unit) |
|
||||
| `open_price` | string | Token price at open |
|
||||
| `open_sign_hash` | string | Open transaction hash; empty before confirmed |
|
||||
| `order_id` | string | Unique order ID (UUID) |
|
||||
| `order_statistic` | object | Cumulative order statistics; see `order_statistic` Object below |
|
||||
| `order_type` | string | Order type: `smart_trade` / `limit_order` |
|
||||
| `place_action` | string | Placement action; empty when not applicable |
|
||||
| `prepare_status` | string | Preparation status; empty when not applicable |
|
||||
| `priority_fee` | string | Priority fee; SOL / BSC only |
|
||||
| `profit_stop` | string | Take-profit trigger price; empty when not set |
|
||||
| `profit_stop_type` | string | Take-profit type; empty when not set |
|
||||
| `quote_decimal` | int | Quote token decimal places |
|
||||
| `quote_investment` | string | Quote token investment amount (smallest unit) |
|
||||
| `quote_token` | string | Quote token contract address |
|
||||
| `reason_by` | string | Entity that triggered the close; empty when open |
|
||||
| `reason_code` | string | Reason code for the close action; empty when open |
|
||||
| `record_high_price` | string | Highest recorded price since open; used for trailing stops |
|
||||
| `sell_param` | object | Sell transaction parameters; see `sell_param` Object below |
|
||||
| `sell_ratio` | string | Sell ratio; empty when not set |
|
||||
| `sell_ratio_type` | string | Sell ratio base: `buy_amount` / others |
|
||||
| `slippage` | int | Slippage tolerance (0 = auto) |
|
||||
| `status` | string | Order lifecycle status: `open` / `closed` |
|
||||
| `strategy_status` | string | Strategy running status: `running` / `stopped` |
|
||||
| `sub_order_type` | string | Sub-order type: `mix_trade` / others |
|
||||
| `tip_fee` | string | Tip fee; SOL only |
|
||||
| `token_balance` | string | Remaining token balance; empty when not available |
|
||||
| `token_logo` | string | Token logo URL |
|
||||
| `token_name` | string | Token display name |
|
||||
| `token_price` | string | Current token price; empty when not available |
|
||||
| `total_supply` | string | Token total supply |
|
||||
| `version` | int | Order schema version |
|
||||
| `wallet_address` | string | Wallet address that placed the order |
|
||||
|
||||
#### `condition_orders[]` — Condition Sub-Order Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------- | ------ | ---- |
|
||||
| `cid` | string | Condition sub-order ID (UUID) |
|
||||
| `order_type` | string | Sub-order type: `profit_stop` / `loss_stop` / `profit_stop_trace` / `loss_stop_trace` |
|
||||
| `side` | string | Trade side: `sell` |
|
||||
| `price_scale` | string | Price ratio relative to open price (string); `profit_stop` / `loss_stop` required |
|
||||
| `sell_ratio` | string | Sell ratio (string), e.g. `"100"` |
|
||||
| `check_price` | string | Computed trigger price derived from `price_scale` and open price |
|
||||
| `status` | string | Sub-order status: `cancel` / `success` / `failed` |
|
||||
|
||||
#### `order_statistic` Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------------- | ------ | ---- |
|
||||
| `buy_amount` | string | Bought token amount (smallest unit) |
|
||||
| `buy_quote_price` | string | Quote token price at buy |
|
||||
| `buy_usdt_price` | string | USDT-denominated price at buy |
|
||||
| `quote_profit` | string | Realized profit in quote token |
|
||||
| `sell_amount` | string | Total token amount sold |
|
||||
| `sell_num` | int | Total number of sell attempts |
|
||||
| `success_sell_amount` | string | Successfully sold token amount |
|
||||
| `success_sell_num` | int | Number of successful sells |
|
||||
| `usdt_profit` | string | Realized profit in USDT |
|
||||
|
||||
#### `sell_param` Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| -------------------------- | ------ | ---- |
|
||||
| `anti_mev_mode` | string | Anti-MEV mode for the sell transaction |
|
||||
| `auto_fee` | bool | Whether auto fee is enabled for the sell |
|
||||
| `auto_slippage` | bool | Whether auto slippage is enabled for the sell |
|
||||
| `auto_tip` | bool | Whether auto tip is enabled |
|
||||
| `custom_rpc` | string | Custom RPC endpoint; empty string when not set |
|
||||
| `fee` | string | Sell transaction fee |
|
||||
| `gas_price` | string | Gas price for the sell |
|
||||
| `is_anti_mev` | bool | Whether anti-MEV protection is active for the sell |
|
||||
| `max_fee_per_gas` | string | EIP-1559 max fee per gas for the sell; EVM only |
|
||||
| `max_priority_fee_per_gas` | string | EIP-1559 max priority fee per gas for the sell; EVM only |
|
||||
| `max_tip_fee` | string | Maximum tip fee; empty when not set |
|
||||
| `priority_fee` | string | Priority fee for the sell; SOL / BSC only |
|
||||
| `slippage` | int | Slippage tolerance for the sell (0 = auto) |
|
||||
| `tip_fee` | string | Tip fee for the sell; SOL only |
|
||||
|
||||
---
|
||||
|
||||
## `order strategy cancel` Usage
|
||||
|
||||
```bash
|
||||
# Cancel a strategy order
|
||||
gmgn-cli order strategy cancel \
|
||||
--chain sol \
|
||||
--from <wallet_address> \
|
||||
--order-id <order_id>
|
||||
```
|
||||
|
||||
## `order strategy cancel` Parameters
|
||||
|
||||
| Parameter | Required | Description |
|
||||
|-----------|----------|-------------|
|
||||
| `--chain` | Yes | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--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 |
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Swap uses **critical auth** (API Key + signature) — CLI handles signing automatically, no manual processing needed
|
||||
- Swap uses **signed auth** (API Key + signature) — CLI handles signing automatically, no manual processing needed
|
||||
- After submitting a swap, use `order get` to poll for confirmation
|
||||
- `--amount` is in the **smallest unit** (e.g., lamports for SOL)
|
||||
- `order strategy create`, `order strategy list`, and `order strategy cancel` use signed auth (require `GMGN_PRIVATE_KEY`)
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Chain restrictions for fee flags** — see the `Chain` column in each parameter table above. `--priority-fee` and `--tip-fee` are SOL/BSC only; `--gas-price`, `--max-fee-per-gas`, `--max-priority-fee-per-gas` are BSC/BASE/ETH only; `--gas-level` and `--auto-fee` are ETH only. The server returns 400 if a chain-restricted flag is sent on the wrong chain. (`gas-price` itself supports all four chains including `sol`.)
|
||||
- **EIP-1559 minimum values per chain:**
|
||||
- BSC: `max_fee_per_gas` and `max_priority_fee_per_gas` min 50 000 000 wei (≈ 0.05 gwei); passing `"0"` returns 400
|
||||
- BASE / ETH: `max_fee_per_gas` and `max_priority_fee_per_gas` min 200 000 wei
|
||||
- EIP-1559 clamping applies only when `--condition-orders` is present (swap / multi-swap) or on every request (strategy/create)
|
||||
|
||||
## Input Validation
|
||||
|
||||
@@ -160,8 +785,27 @@ Before passing any address or amount to a command:
|
||||
|
||||
4. **User confirmation** — See "Execution Guidelines" below — always present resolved parameters to the user before executing a swap. This creates a human review checkpoint for any unexpected values.
|
||||
|
||||
## Pre-Swap Safety Check (REQUIRED)
|
||||
|
||||
Before swapping into any token, run a mandatory security check using `gmgn-cli`:
|
||||
|
||||
```bash
|
||||
gmgn-cli token security --chain <chain> --address <output_token>
|
||||
```
|
||||
|
||||
Check the two critical fields:
|
||||
- **`is_honeypot`**: If `"yes"` → **abort immediately**. Display: "🚫 HONEYPOT DETECTED — swap aborted." Do NOT proceed.
|
||||
- **`rug_ratio`**: If `> 0.3` → display 🔴 High Risk warning and require explicit re-confirmation from the user before proceeding.
|
||||
|
||||
**User override**: The user may explicitly skip this check by saying "I already checked" or "skip security check". In that case, document that the check was skipped in the confirmation summary. This is the only valid override — do NOT skip the check silently.
|
||||
|
||||
For a quick pre-swap due diligence checklist (info + security + pool + smart money, 4 steps), see [`docs/workflow-token-due-diligence.md`](../../docs/workflow-token-due-diligence.md)
|
||||
|
||||
For full token research before swapping, see [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md)
|
||||
|
||||
## Execution Guidelines
|
||||
|
||||
- **[REQUIRED] Token security check** — Run before every swap. See **Pre-Swap Safety Check (REQUIRED)** section above. Uses exist auth (API Key only — no private key needed for this step).
|
||||
- **Currency resolution** — When the user names a currency (SOL/BNB/ETH/USDC) instead of providing an address, look up its address in the Chain Currencies table and apply it automatically — never ask the user for it.
|
||||
- Buy ("buy X SOL of TOKEN", "spend 0.5 USDC on TOKEN") → resolve currency to `--input-token`
|
||||
- Sell ("sell TOKEN for SOL", "sell 50% of TOKEN to USDC") → resolve currency to `--output-token`
|
||||
@@ -169,7 +813,7 @@ Before passing any address or amount to a command:
|
||||
- **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 `confirmation.state` 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 |
|
||||
|
||||
@@ -1,73 +1,732 @@
|
||||
---
|
||||
name: gmgn-token
|
||||
description: Query GMGN token information — basic info, security, pool, top holders and top traders. Supports sol / bsc / base.
|
||||
argument-hint: <sub-command> --chain <sol|bsc|base> --address <token_address>
|
||||
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>"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli token --help"
|
||||
---
|
||||
|
||||
**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."**
|
||||
|
||||
**IMPORTANT: Do NOT guess field names or values. When a field's meaning is unclear, look it up in the Response Field Reference tables below before using it.**
|
||||
|
||||
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.
|
||||
- **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.
|
||||
- **Trader** — Any wallet that has transacted with the token (bought or sold), regardless of current holdings. `token traders` covers both current holders and past traders.
|
||||
- **Smart money (`smart_degen`)** — Wallets with a proven track record of profitable trading, tagged by GMGN's algorithm. High `smart_degen_count` is a bullish signal.
|
||||
- **KOL (`renowned`)** — Known influencer, fund, or public figure wallets, tagged by GMGN. Their positions are publicly tracked.
|
||||
- **Honeypot** — A token where buy transactions succeed but sell transactions always fail. User funds become permanently trapped. Only detectable on BSC/Base (`is_honeypot`); not applicable on SOL.
|
||||
- **Renounced (mint / freeze / ownership)** — The developer has permanently given up that authority. On SOL: `renounced_mint` (cannot create new supply) and `renounced_freeze_account` (cannot freeze wallets) both `true` is the safe baseline. On EVM: `owner_renounced` `"yes"` means no admin backdoors.
|
||||
- **rug_ratio** — A 0–1 risk score estimating the likelihood of a rug pull. Values above `0.3` are high-risk. Do not treat as a binary safe/unsafe flag — use in combination with other signals.
|
||||
- **Bonding curve** — Price discovery mechanism used by launchpads (e.g. Pump.fun, letsbonk). Token price rises as more is bought. When the curve fills, the token "graduates" to an open DEX pool. `is_on_curve: true` means the token has not graduated yet.
|
||||
- **Wallet tags** — GMGN-assigned labels on wallets: `smart_degen` (smart money), `renowned` (KOL), `sniper` (launched at token open), `bundler` (bot-bundled buy), `rat_trader` (insider/sneak trading). Use `--tag` to filter `token holders` / `token traders` by these labels.
|
||||
|
||||
## Sub-commands
|
||||
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `token info` | Basic info + realtime price |
|
||||
| `token security` | Security metrics (holder concentration, contract risks) |
|
||||
| `token pool` | Liquidity pool info |
|
||||
| `token holders` | Top token holders list |
|
||||
| `token traders` | Top token traders list |
|
||||
| `token info` | Basic info + realtime price, liquidity, market cap, total supply, holder count, social links (market cap = price.price × circulating_supply) |
|
||||
| `token security` | Security metrics (honeypot, taxes, holder concentration, contract risks) |
|
||||
| `token pool` | Liquidity pool info (DEX, reserves, liquidity depth) |
|
||||
| `token holders` | Top token holders list with profit/loss breakdown |
|
||||
| `token traders` | Top token traders list with profit/loss breakdown |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base`
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `.env` file with `GMGN_API_KEY` set
|
||||
- Run from the directory where your `.env` file is located, or set `GMGN_HOST` in your environment
|
||||
- `gmgn-cli` installed globally: `npm install -g gmgn-cli@1.0.1`
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
- `GMGN_API_KEY` configured in `~/.config/gmgn/.env`
|
||||
|
||||
## Info / Security / Pool Options
|
||||
## Rate Limit Handling
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` |
|
||||
| `--address` | Required. Token contract address |
|
||||
All token routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
## Holders / Traders Options
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `token info` | `GET /v1/token/info` | 1 |
|
||||
| `token security` | `GET /v1/token/security` | 1 |
|
||||
| `token pool` | `GET /v1/token/pool_info` | 1 |
|
||||
| `token holders` | `GET /v1/market/token_top_holders` | 5 |
|
||||
| `token traders` | `GET /v1/market/token_top_traders` | 5 |
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` |
|
||||
| `--address` | Required. Token contract address |
|
||||
| `--limit <n>` | Number of results (default `20`, max `100`) |
|
||||
| `--order-by <field>` | Sort field: `amount_percentage` / `profit` / `unrealized_profit` / `buy_volume_cur` / `sell_volume_cur` (default `amount_percentage`) |
|
||||
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
||||
| `--tag <tag>` | Wallet tag filter: `renowned` / `smart_degen` (default `renowned`) |
|
||||
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.
|
||||
|
||||
**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` |
|
||||
| `--address` | Yes | Token contract address |
|
||||
| `--raw` | No | Output raw single-line JSON (for piping or further processing) |
|
||||
|
||||
## Parameters — `token holders` / `token traders`
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|----------|---------|-------------|
|
||||
| `--chain` | Yes | — | `sol` / `bsc` / `base` / `eth` |
|
||||
| `--address` | Yes | — | Token contract address |
|
||||
| `--limit` | No | `20` | Number of results, max `100` |
|
||||
| `--order-by` | No | `amount_percentage` | Sort field — see table below |
|
||||
| `--direction` | No | `desc` | Sort direction: `asc` / `desc` |
|
||||
| `--tag` | No | — | Wallet filter: `smart_degen` / `renowned` / `fresh_wallet` / `dev` / `sniper` / `rat_trader` / `bundler` / `transfer_in` / `dex_bot` / `bluechip_owner`. Omit to return all wallets. |
|
||||
| `--raw` | No | — | Output raw single-line JSON |
|
||||
|
||||
### `--order-by` Values
|
||||
|
||||
| Value | Description |
|
||||
|-------|-------------|
|
||||
| `amount_percentage` | Sort by percentage of total supply held (default) |
|
||||
| `profit` | Sort by realized profit in USD |
|
||||
| `unrealized_profit` | Sort by unrealized profit in USD |
|
||||
| `buy_volume_cur` | Sort by buy volume |
|
||||
| `sell_volume_cur` | Sort by sell volume |
|
||||
|
||||
### `--tag` Values
|
||||
|
||||
| Value | Description |
|
||||
| -------------- | ----------- |
|
||||
| `smart_degen` | Smart money wallets (historically high-performing traders) |
|
||||
| `renowned` | KOL / well-known wallets (influencers, funds, public figures) |
|
||||
| `fresh_wallet` | New wallets with no prior trading history |
|
||||
| `dev` | Token developer / creator wallets |
|
||||
| `sniper` | Wallets that sniped the token at launch |
|
||||
| `rat_trader` | Insider / sneak-trading wallets |
|
||||
| `bundler` | Bot-bundled buy wallets |
|
||||
| `transfer_in` | Wallets with a transfer-in record for this token |
|
||||
| `dex_bot` | DEX bot wallets (Axiom, Photon, BullX, Trojan, GMGN, Drops, PepeBoost, Padre) |
|
||||
| `bluechip_owner` | Wallets holding established bluechip tokens |
|
||||
|
||||
### `--tag` + `--order-by` Combination Guide
|
||||
|
||||
`--tag` and `--order-by` are independent — all `--order-by` values are valid with or without `--tag`. Omitting `--tag` returns all wallets (no filter).
|
||||
|
||||
Recommended combinations for common use cases:
|
||||
|
||||
| Goal | `--tag` | `--order-by` |
|
||||
|------|---------|--------------|
|
||||
| Largest smart money holders by supply | `smart_degen` | `amount_percentage` |
|
||||
| Smart money with highest realized profit | `smart_degen` | `profit` |
|
||||
| Smart money sitting on unrealized gains | `smart_degen` | `unrealized_profit` |
|
||||
| Smart money aggressively accumulating | `smart_degen` | `buy_volume_cur` |
|
||||
| Smart money distributing (exit signal) | `smart_degen` | `sell_volume_cur` |
|
||||
| KOLs who already took profit | `renowned` | `profit` |
|
||||
| KOLs still holding with paper gains | `renowned` | `unrealized_profit` |
|
||||
| Largest holders overall (no filter) | *(omit)* | `amount_percentage` |
|
||||
|
||||
## Response Field Reference
|
||||
|
||||
### `token info` — Key Fields
|
||||
|
||||
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**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `address` | Token contract address |
|
||||
| `symbol` / `name` | Token ticker and full name |
|
||||
| `decimals` | Token decimal places |
|
||||
| `total_supply` | Total token supply (same as `circulating_supply` for most tokens) |
|
||||
| `circulating_supply` | Circulating supply |
|
||||
| `max_supply` | Maximum supply |
|
||||
| `price` | **Object** — price and trading stats (see `price` Object below). Access current price as `price.price`. |
|
||||
| `liquidity` | Total liquidity in USD (from biggest pool) |
|
||||
| `holder_count` | Number of unique token holders |
|
||||
| `logo` | Token logo image URL |
|
||||
| `creation_timestamp` | Token creation time (Unix seconds) |
|
||||
| `open_timestamp` | Time the token opened for trading (Unix seconds) |
|
||||
| `biggest_pool_address` | Address of the main liquidity pool |
|
||||
| `og` | Whether the token is flagged as an OG token (`true` / `false`) |
|
||||
| `launchpad` | Launchpad identifier (e.g. `pump`, `moonshot`) |
|
||||
| `launchpad_status` | Launchpad state: `0` = not opened, `1` = live, `2` = migrated |
|
||||
| `launchpad_progress` | Launchpad bonding-curve progress (0–1) |
|
||||
| `launchpad_platform` | Launchpad platform name |
|
||||
| `migrated_pool` | Pool address after migration |
|
||||
| `migration_market_cap` | Market cap at migration time (USD, float) |
|
||||
| `migration_market_cap_quote` | Quote currency for `migration_market_cap` |
|
||||
| `ath_price` | All-time-high price (USD, float) |
|
||||
| `locked_ratio` | Ratio of supply locked (0–1, float) |
|
||||
|
||||
**`pool` Object** — Main liquidity pool details
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `pool.pool_address` | Pool contract address |
|
||||
| `pool.quote_address` | Quote token address (e.g. USDC, SOL, WETH) |
|
||||
| `pool.quote_symbol` | Quote token symbol (e.g. `USDC`, `SOL`) |
|
||||
| `pool.exchange` | DEX name (e.g. `meteora_dlmm`, `raydium`, `pump_amm`, `uniswap_v3`) |
|
||||
| `pool.liquidity` | Pool liquidity in USD |
|
||||
| `pool.base_reserve` | Base token reserve amount |
|
||||
| `pool.quote_reserve` | Quote token reserve amount |
|
||||
| `pool.base_reserve_value` | Base reserve USD value |
|
||||
| `pool.quote_reserve_value` | Quote reserve USD value |
|
||||
| `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 |
|
||||
| `dev.ath_token_info` | Creator's all-time-high token info object (optional); see sub-fields below |
|
||||
| `dev.ath_token_info.ath_token` | Contract address of the creator's best-performing token ever |
|
||||
| `dev.ath_token_info.ath_mc` | All-time-high market cap of that token (USD, string) |
|
||||
| `dev.ath_token_info.avatar` | Token logo URL |
|
||||
| `dev.ath_token_info.symbol` | Token symbol |
|
||||
| `dev.ath_token_info.name` | Token name |
|
||||
| `dev.ath_token_info.creation_timestamp` | Token creation time (Unix seconds) |
|
||||
|
||||
**`link` Object** — Social and explorer links
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `link.twitter_username` | Twitter / X username (not full URL) |
|
||||
| `link.website` | Project website URL |
|
||||
| `link.telegram` | Telegram URL |
|
||||
| `link.discord` | Discord URL |
|
||||
| `link.instagram` | Instagram URL |
|
||||
| `link.tiktok` | TikTok URL |
|
||||
| `link.youtube` | YouTube URL |
|
||||
| `link.description` | Token description text |
|
||||
| `link.gmgn` | GMGN token page URL |
|
||||
| `link.geckoterminal` | GeckoTerminal page URL |
|
||||
| `link.verify_status` | Social verification status (integer) |
|
||||
|
||||
**`stat` Object** — On-chain statistics
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `stat.holder_count` | Number of holders (same as top-level `holder_count`) |
|
||||
| `stat.top_10_holder_rate` | Ratio of supply held by top 10 wallets (0–1) |
|
||||
| `stat.dev_team_hold_rate` | Ratio held by dev team wallets |
|
||||
| `stat.creator_hold_rate` | Ratio held by creator wallet |
|
||||
| `stat.creator_token_balance` | Raw creator token balance |
|
||||
| `stat.top_rat_trader_percentage` | Ratio of volume from rat/insider traders |
|
||||
| `stat.top_bundler_trader_percentage` | Ratio of volume from bundler bots |
|
||||
| `stat.top_entrapment_trader_percentage` | Ratio of volume from entrapment traders |
|
||||
| `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
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `wallet_tags_stat.smart_wallets` | Number of smart money wallets holding the token |
|
||||
| `wallet_tags_stat.renowned_wallets` | Number of renowned / KOL wallets holding the token |
|
||||
| `wallet_tags_stat.sniper_wallets` | Number of sniper wallets |
|
||||
| `wallet_tags_stat.rat_trader_wallets` | Number of rat trader wallets |
|
||||
| `wallet_tags_stat.bundler_wallets` | Number of bundler bot wallets |
|
||||
| `wallet_tags_stat.whale_wallets` | Number of whale wallets |
|
||||
| `wallet_tags_stat.fresh_wallets` | Number of fresh wallets |
|
||||
| `wallet_tags_stat.top_wallets` | Number of top-ranked wallets |
|
||||
|
||||
**`price` Object** — Price and trading statistics (access current price via `price.price`)
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `price.price` | Current price in USD (string) |
|
||||
| `price.price_{window}` | Price at the start of the window; windows: `1m`, `5m`, `1h`, `6h`, `24h` |
|
||||
| `price.buys_{window}` | Buy transaction count in the window |
|
||||
| `price.sells_{window}` | Sell transaction count in the window |
|
||||
| `price.volume_{window}` | Total trading volume in USD for the window |
|
||||
| `price.buy_volume_{window}` | Buy volume in USD for the window |
|
||||
| `price.sell_volume_{window}` | Sell volume in USD for the window |
|
||||
| `price.swaps_{window}` | Total swap count for the window |
|
||||
| `price.hot_level` | Heat level integer |
|
||||
|
||||
**`fee_distribution` Object** — Launchpad fee-sharing config (optional; present for `pump` / `bankr` tokens). Use `token info` to check fee distribution, creator reward claim status (`has_claimed_fee`), and royalty allocation for pump/bankr tokens.
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `fee_distribution.launchpad` | Launchpad identifier: `"pump"`, `"bankr"`, or `""` (unknown) |
|
||||
| `fee_distribution.platform_data` | Platform-specific fee config; structure varies by `launchpad` (see below) |
|
||||
|
||||
When `fee_distribution.launchpad = "pump"`:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `platform_data.fee_authority` | Fee authority wallet address |
|
||||
| `platform_data.is_locked` | Whether the fee config is locked |
|
||||
| `platform_data.show` | Whether fee distribution is displayed in the UI |
|
||||
| `platform_data.list` | Array of fee-share holders (see FeeShareHolder below) |
|
||||
| `platform_data.bonus_category` | Bonus category list (e.g. `creator_reward`, `cashback`) |
|
||||
|
||||
When `fee_distribution.launchpad = "bankr"`:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `platform_data.deployer` | Original deployer wallet address |
|
||||
| `platform_data.fee_recipient` | Fee recipient wallet address |
|
||||
| `platform_data.list` | Array of fee-share holders (see FeeShareHolder below) |
|
||||
|
||||
FeeShareHolder fields (each item in `platform_data.list`):
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `wallet` | Wallet address |
|
||||
| `royalty_bps` | Royalty share in basis points (10000 = 100%) |
|
||||
| `is_creator` | Whether this is the original creator |
|
||||
| `has_claimed_fee` | Whether fees have been claimed |
|
||||
| `username` | Display name |
|
||||
| `pfp` | Avatar URL |
|
||||
| `twitter_username` | Twitter / X username |
|
||||
|
||||
---
|
||||
|
||||
### `token security` — Key Fields
|
||||
|
||||
**Contract Safety**
|
||||
|
||||
| Field | Chains | Description |
|
||||
|-------|--------|-------------|
|
||||
| `is_honeypot` | BSC / Base | Whether token is a honeypot (`"yes"` / `"no"`); empty string on SOL |
|
||||
| `open_source` | all | Contract source code verified: `"yes"` / `"no"` / `"unknown"` |
|
||||
| `owner_renounced` | all | Contract ownership renounced: `"yes"` / `"no"` / `"unknown"` |
|
||||
| `renounced_mint` | SOL | Mint authority renounced (SOL-specific; always `false` on EVM) |
|
||||
| `renounced_freeze_account` | SOL | Freeze authority renounced (SOL-specific; always `false` on EVM) |
|
||||
| `buy_tax` / `sell_tax` | all | Tax ratio — e.g. `0.03` = 3%; `0` = no tax |
|
||||
|
||||
**Holder Concentration & Risk**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `top_10_holder_rate` | Ratio of supply held by top 10 wallets (0–1); higher = more concentrated |
|
||||
| `dev_team_hold_rate` | Ratio held by dev team wallets |
|
||||
| `creator_balance_rate` | Ratio held by the token creator wallet |
|
||||
| `creator_token_status` | Dev holding status: `creator_hold` (still holding) / `creator_close` (sold/closed) |
|
||||
| `suspected_insider_hold_rate` | Ratio held by suspected insider wallets |
|
||||
|
||||
**Trading Risk**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `rug_ratio` | Rug pull risk score (0–1); higher = more risky |
|
||||
| `is_wash_trading` | Whether wash trading activity is detected (`true` / `false`) |
|
||||
| `rat_trader_amount_rate` | Ratio of volume from sneak/insider trading |
|
||||
| `bundler_trader_amount_rate` | Ratio of volume from bundle trading (bot-driven) |
|
||||
| `sniper_count` | Number of sniper wallets that bought at launch |
|
||||
| `burn_status` | Liquidity pool burn status (e.g. `"burn"` = burned, `""` = not burned) |
|
||||
|
||||
---
|
||||
|
||||
### `token pool` — Key Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `address` | Pool contract address |
|
||||
| `base_address` | Base token address (the queried token) |
|
||||
| `quote_address` | Quote token address (e.g. SOL, USDC, WETH) |
|
||||
| `exchange` | DEX name (e.g. `raydium`, `pump_amm`, `uniswap_v3`, `pancakeswap`) |
|
||||
| `liquidity` | Pool liquidity in USD |
|
||||
| `base_reserve` | Base token reserve amount |
|
||||
| `quote_reserve` | Quote token reserve amount |
|
||||
| `price` | Current price in USD derived from pool reserves |
|
||||
| `creation_timestamp` | Pool creation time (Unix seconds) |
|
||||
|
||||
---
|
||||
|
||||
### `token holders` / `token traders` — Response Fields
|
||||
|
||||
The response is an object with a `list` array. Each item in `list` represents one wallet.
|
||||
|
||||
**Identity & Holdings**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `address` | Wallet address |
|
||||
| `account_address` | Token account address (the on-chain account holding the token, distinct from the wallet address) |
|
||||
| `addr_type` | Address type: `0` = regular wallet, `2` = exchange / liquidity pool |
|
||||
| `exchange` | Exchange or pool name if `addr_type` is `2` (e.g. `pump_amm`, `raydium`) |
|
||||
| `wallet_tag_v2` | Rank label in this list (e.g. `TOP1`, `TOP2`, ...) |
|
||||
| `native_balance` | Native token balance in smallest unit (lamports for SOL) |
|
||||
| `balance` | Current token balance (human-readable units) |
|
||||
| `amount_cur` | Same as `balance` — current token amount held |
|
||||
| `usd_value` | USD value of current holdings at current price |
|
||||
| `amount_percentage` | Ratio of total supply held (0–1); e.g. `0.05` = 5% |
|
||||
| `is_on_curve` | `true` = still on bonding curve (pump.fun pre-graduation); `false` = open market |
|
||||
| `is_new` | Whether this is a newly created wallet |
|
||||
| `is_suspicious` | Whether this wallet is flagged as suspicious |
|
||||
| `transfer_in` | Whether the current holding was received via transfer (not bought) |
|
||||
|
||||
**Trading Summary**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `buy_volume_cur` | Total buy volume in USD |
|
||||
| `sell_volume_cur` | Total sell volume in USD |
|
||||
| `buy_amount_cur` | Total tokens bought |
|
||||
| `sell_amount_cur` | Total tokens sold |
|
||||
| `sell_amount_percentage` | Ratio of bought tokens that have been sold (0–1); `1.0` = fully exited |
|
||||
| `buy_tx_count_cur` | Number of buy transactions |
|
||||
| `sell_tx_count_cur` | Number of sell transactions |
|
||||
| `netflow_usd` | Net USD flow = sell income − buy cost (negative = net spent) |
|
||||
| `netflow_amount` | Net token flow = bought − sold (positive = still holding net position) |
|
||||
|
||||
**Cost & P&L**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `avg_cost` | Average buy price in USD per token |
|
||||
| `avg_sold` | Average sell price in USD per token |
|
||||
| `history_bought_cost` | Total USD spent buying |
|
||||
| `history_bought_fee` | Total fees paid on buys in USD |
|
||||
| `history_sold_income` | Total USD received from selling |
|
||||
| `history_sold_fee` | Total fees paid on sells in USD |
|
||||
| `total_cost` | Total cost basis including fees |
|
||||
| `profit` | Total profit in USD (realized + unrealized) |
|
||||
| `profit_change` | Total profit ratio = profit / total_cost |
|
||||
| `realized_profit` | Realized profit in USD from completed sells |
|
||||
| `realized_pnl` | Realized profit ratio = realized_profit / buy_cost |
|
||||
| `unrealized_profit` | Unrealized profit in USD on current holdings at current price |
|
||||
| `unrealized_pnl` | Unrealized profit ratio; `null` if no current holdings |
|
||||
|
||||
**Transfer History**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `current_transfer_in_amount` | Tokens received via transfer (not bought) in current period |
|
||||
| `current_transfer_out_amount` | Tokens sent out via transfer (not sold) in current period |
|
||||
| `history_transfer_in_amount` | Historical total tokens received via transfer |
|
||||
| `history_transfer_in_cost` | Estimated cost basis of transferred-in tokens |
|
||||
| `history_transfer_out_amount` | Historical total tokens sent out via transfer |
|
||||
| `history_transfer_out_income` | Estimated income from transferred-out tokens |
|
||||
| `history_transfer_out_fee` | Fees paid on transfer-outs |
|
||||
| `transfer_in_count` | Number of inbound transfers |
|
||||
| `transfer_out_count` | Number of outbound transfers |
|
||||
|
||||
**Timing**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `start_holding_at` | Unix timestamp when wallet first acquired this token |
|
||||
| `end_holding_at` | Unix timestamp when wallet fully exited; `null` if still holding |
|
||||
| `last_active_timestamp` | Unix timestamp of most recent on-chain activity for this token |
|
||||
| `last_block` | Block number of last activity |
|
||||
|
||||
**Wallet Identity**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `name` | Wallet display name (if known) |
|
||||
| `twitter_username` | Twitter / X username |
|
||||
| `twitter_name` | Twitter / X display name |
|
||||
| `avatar` | Avatar image URL |
|
||||
| `tags` | Platform-level wallet tags (e.g. `["kol"]`, `["smart_degen"]`, `["axiom"]`) |
|
||||
| `maker_token_tags` | Token-specific behavior tags for this wallet (e.g. `["bundler"]`, `["paper_hands"]`, `["top_holder"]`) |
|
||||
| `created_at` | Wallet creation timestamp (Unix seconds); `0` if unknown |
|
||||
|
||||
**Shared Funding**
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `native_transfer` | First native token (SOL/BNB/ETH) transfer into this wallet — indicates the original funding source; wallets sharing the same `native_transfer.address` are likely funded from a common origin (coordinated wallets / same operator) |
|
||||
|
||||
**Last Transaction Records**
|
||||
|
||||
Each of the following is an object with `name`, `address`, `timestamp`, `tx_hash`, `type`:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `token_transfer` | Most recent token transfer (buy or sell) |
|
||||
| `token_transfer_in` | Most recent inbound token transfer |
|
||||
| `token_transfer_out` | Most recent outbound token transfer |
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### `token info` — Fetch Basic Info and Price
|
||||
|
||||
```bash
|
||||
# Basic token info
|
||||
gmgn-cli token info --chain sol --address <token_address>
|
||||
# Get current price and market cap for a SOL token
|
||||
gmgn-cli token info --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
|
||||
|
||||
# Security metrics
|
||||
gmgn-cli token security --chain sol --address <token_address>
|
||||
# Get basic info for a BSC token
|
||||
gmgn-cli token info --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8
|
||||
|
||||
# Liquidity pool
|
||||
gmgn-cli token pool --chain sol --address <token_address>
|
||||
# Get basic info for a Base token
|
||||
gmgn-cli token info --chain base --address 0x4200000000000000000000000000000000000006
|
||||
|
||||
# Top holders
|
||||
gmgn-cli token holders --chain sol --address <token_address> --limit 50
|
||||
# Get basic info for an ETH token
|
||||
gmgn-cli token info --chain eth --address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
|
||||
|
||||
# Top traders
|
||||
gmgn-cli token traders --chain sol --address <token_address> --limit 50
|
||||
|
||||
# Raw JSON output (for piping)
|
||||
gmgn-cli token info --chain sol --address <token_address> --raw
|
||||
# Raw JSON output for downstream processing
|
||||
gmgn-cli token info --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v --raw
|
||||
```
|
||||
|
||||
### `token security` — Check Safety Before Buying
|
||||
|
||||
```bash
|
||||
# Check if a SOL token has renounced mint + freeze authority
|
||||
gmgn-cli token security --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
|
||||
|
||||
# Check if a BSC token is honeypot and whether contract is verified
|
||||
gmgn-cli token security --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8
|
||||
|
||||
# Check a Base token for tax, rug ratio, and insider concentration
|
||||
gmgn-cli token security --chain base --address 0x4200000000000000000000000000000000000006
|
||||
|
||||
# Check an ETH token for honeypot and contract risks
|
||||
gmgn-cli token security --chain eth --address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
|
||||
|
||||
# Raw output for parsing key fields (e.g. is_honeypot, buy_tax, rug_ratio)
|
||||
gmgn-cli token security --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 --raw
|
||||
```
|
||||
|
||||
### `token pool` — Check Liquidity Depth
|
||||
|
||||
```bash
|
||||
# Get pool info for a SOL token (liquidity, reserves, DEX)
|
||||
gmgn-cli token pool --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
|
||||
|
||||
# Get pool info for a BSC token
|
||||
gmgn-cli token pool --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8
|
||||
|
||||
# Get pool info for an ETH token
|
||||
gmgn-cli token pool --chain eth --address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
|
||||
```
|
||||
|
||||
### `token holders` — Analyze Holder Distribution
|
||||
|
||||
```bash
|
||||
# Top 20 holders by supply percentage (default)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
|
||||
|
||||
# Top 50 holders sorted by percentage held
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--limit 50 --order-by amount_percentage --direction desc
|
||||
|
||||
# Top 50 smart money holders (highest conviction wallets)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--limit 50 --tag smart_degen --order-by amount_percentage
|
||||
|
||||
# Top KOL wallets ranked by realized profit (who has already taken profit)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag renowned --order-by profit --direction desc --limit 20
|
||||
|
||||
# Smart money with most unrealized profit (who is sitting on biggest gains)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag smart_degen --order-by unrealized_profit --direction desc --limit 20
|
||||
|
||||
# Holders who have been buying the most recently (buy momentum signal)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 20
|
||||
|
||||
# Holders who are selling the most (exit signal / distribution warning)
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag renowned --order-by sell_volume_cur --direction desc --limit 20
|
||||
|
||||
# BSC token holders — KOL wallets by profit
|
||||
gmgn-cli token holders --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 \
|
||||
--tag renowned --order-by profit --direction desc --limit 50
|
||||
|
||||
# ETH token holders — smart money by supply percentage
|
||||
gmgn-cli token holders --chain eth --address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
||||
--tag smart_degen --order-by amount_percentage --direction desc --limit 20
|
||||
|
||||
# Raw output for downstream analysis
|
||||
gmgn-cli token holders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--limit 100 --raw
|
||||
```
|
||||
|
||||
### `token traders` — `--tag` + `--order-by` Combination Guide
|
||||
|
||||
Use this table to pick the right combination for common `token traders` use cases:
|
||||
|
||||
| Use case | `--tag` | `--order-by` |
|
||||
|----------|---------|-------------|
|
||||
| Smart money with highest buy volume | `smart_degen` | `buy_volume_cur` |
|
||||
| Smart money with highest sell volume (exit signal) | `smart_degen` | `sell_volume_cur` |
|
||||
| KOLs recently active | `renowned` | `last_active_timestamp` |
|
||||
| Smart money most profitable traders | `smart_degen` | `profit` |
|
||||
| Snipers still holding | `sniper` | `amount_percentage` |
|
||||
| Smart money sitting on biggest unrealized gains | `smart_degen` | `unrealized_profit` |
|
||||
| KOLs who already took profit | `renowned` | `profit` |
|
||||
|
||||
### `token traders` — Find Active Traders
|
||||
|
||||
```bash
|
||||
# Top 20 active traders by supply held (default)
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
|
||||
|
||||
# Smart money traders ranked by realized profit
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag smart_degen --order-by profit --direction desc --limit 50
|
||||
|
||||
# KOL traders ranked by unrealized profit (still holding with paper gains)
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag renowned --order-by unrealized_profit --direction desc --limit 20
|
||||
|
||||
# Smart money traders with highest buy volume (aggressive accumulation)
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag smart_degen --order-by buy_volume_cur --direction desc --limit 20
|
||||
|
||||
# Smart money traders ranked by sell volume (who is distributing)
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag smart_degen --order-by sell_volume_cur --direction desc --limit 20
|
||||
|
||||
# Worst performing KOL traders (who lost the most — contrarian signal)
|
||||
gmgn-cli token traders --chain sol --address EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
|
||||
--tag renowned --order-by profit --direction asc --limit 20
|
||||
|
||||
# BSC token traders by profit
|
||||
gmgn-cli token traders --chain bsc --address 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 \
|
||||
--tag smart_degen --order-by profit --direction desc --limit 50
|
||||
|
||||
# ETH token traders by profit
|
||||
gmgn-cli token traders --chain eth --address 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
|
||||
--tag smart_degen --order-by profit --direction desc --limit 50
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Token Quick Scoring Card
|
||||
|
||||
After fetching `token security` and `token info`, apply this scoring card to give a structured verdict. Do not skip this step when the user asks for a safety check or due diligence.
|
||||
|
||||
| Field | ✅ Safe | ⚠️ Warning | 🚫 Danger (Hard Stop) |
|
||||
|-------|---------|-----------|----------------------|
|
||||
| `is_honeypot` | `"no"` | — | `"yes"` → **stop immediately** |
|
||||
| `open_source` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `owner_renounced` | `"yes"` | `"unknown"` | `"no"` |
|
||||
| `renounced_mint` (SOL) | `true` | — | `false` |
|
||||
| `renounced_freeze_account` (SOL) | `true` | — | `false` |
|
||||
| `rug_ratio` | `< 0.10` | `0.10–0.30` | `> 0.30` |
|
||||
| `top_10_holder_rate` | `< 0.20` | `0.20–0.50` | `> 0.50` |
|
||||
| `creator_token_status` | `creator_close` | — | `creator_hold` |
|
||||
| `buy_tax` / `sell_tax` | `0` | `0.01–0.05` | `> 0.10` |
|
||||
| `sniper_count` | `< 5` | `5–20` | `> 20` |
|
||||
| `smart_wallets` (from `wallet_tags_stat`) | `≥ 3` | `1–2` | `0` (bearish, not a hard stop) |
|
||||
| `renowned_wallets` (from `wallet_tags_stat`) | `≥ 1` | — | `0` (neutral, not a hard stop) |
|
||||
|
||||
**Final scoring logic:**
|
||||
- If `is_honeypot = "yes"` → **hard stop immediately**, do not proceed regardless of other signals
|
||||
- If other 🚫 fields present → **skip** (strong warning — present to user)
|
||||
- `smart_wallets = 0` alone is NOT a hard stop — it means no smart money interest yet, which is bearish but not disqualifying for very new tokens
|
||||
- If 3+ ⚠️ with no 🚫 → **needs more research** — present findings and ask user how to proceed
|
||||
- If mostly ✅ with `smart_wallets ≥ 3` → **worth researching** — proceed to holders/traders analysis
|
||||
|
||||
## Workflow: Full Token Due Diligence
|
||||
|
||||
When the user asks for a full token research / due diligence, follow the steps in [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md).
|
||||
|
||||
Steps: `token info` → `token security` → `token pool` → market heat check → `token holders/traders` (smart money signals) → Decision Framework.
|
||||
|
||||
**For a more comprehensive report** (user asks for a "deep report", "full analysis", "is this worth a large position"), use the extended workflow: [`docs/workflow-project-deep-report.md`](../../docs/workflow-project-deep-report.md). This adds a scored multi-dimension analysis (fundamentals + security + liquidity + smart money conviction + price action) and produces a full written report.
|
||||
|
||||
**For active risk monitoring** on a held position (user asks "any risk warnings", "are whales dumping", "is liquidity still healthy"), follow: [`docs/workflow-risk-warning.md`](../../docs/workflow-risk-warning.md). Uses `token security` + `token pool` + `token holders` to flag whale exits, liquidity drain, and developer dumps.
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
### `token info` — Summary Card
|
||||
|
||||
Present as a concise card. Do not dump raw JSON.
|
||||
|
||||
```
|
||||
{symbol} ({name})
|
||||
Price: ${price.price} | Market Cap: ~${price.price × circulating_supply} | Liquidity: ${liquidity}
|
||||
Holders: {holder_count} | Smart Money: {wallet_tags_stat.smart_wallets} | KOLs: {wallet_tags_stat.renowned_wallets}
|
||||
Social: @{link.twitter_username} | {link.website} | {link.telegram}
|
||||
```
|
||||
|
||||
If any social fields are empty, omit them rather than showing `null`.
|
||||
|
||||
### `token security` — Risk Assessment Summary
|
||||
|
||||
After fetching security data, present a structured risk summary using this format:
|
||||
|
||||
```
|
||||
Token: {symbol} | Chain: {chain} | Address: {short address}
|
||||
─── Security ──────────────────────────────────────
|
||||
Contract verified: ✅ yes / 🚫 no / ⚠️ unknown
|
||||
Owner renounced: ✅ yes / 🚫 no / ⚠️ unknown
|
||||
Honeypot: ✅ no / 🚫 YES — DO NOT BUY
|
||||
Mint renounced (SOL): ✅ yes / ⚠️ no
|
||||
Freeze renounced(SOL):✅ yes / ⚠️ no
|
||||
Rug risk score: {rug_ratio} → ✅ <0.1 Low / ⚠️ 0.1–0.3 Med / 🚫 >0.3 High
|
||||
Top-10 holder %: {top_10_holder_rate%} → ✅ <20% / ⚠️ 20–50% / 🚫 >50%
|
||||
Dev still holding: ✅ sold (creator_close) / ⚠️ holding (creator_hold)
|
||||
Sniper wallets: ✅ <5 / ⚠️ 5–20 / 🚫 >20
|
||||
─── Smart Money ───────────────────────────────────
|
||||
SM holders: {smart_wallets} KOL holders: {renowned_wallets}
|
||||
─── Verdict ───────────────────────────────────────
|
||||
🟢 Clean — worth researching
|
||||
🟡 Mixed signals — proceed with caution
|
||||
🔴 Red flags present — skip or verify manually
|
||||
```
|
||||
|
||||
**If `is_honeypot = "yes"`, stop immediately and display: "🚫 HONEYPOT DETECTED — Do not buy this token." Do NOT proceed to further analysis steps.**
|
||||
|
||||
### `token holders` / `token traders` — Ranked Table
|
||||
|
||||
```
|
||||
# | Wallet (name or short addr) | Hold% | Avg Buy | Realized P&L | Unrealized P&L | Tags
|
||||
```
|
||||
|
||||
Show top rows only. Highlight wallets tagged `kol`, `smart_degen`, or flagged `bundler` / `rat_trader` in `maker_token_tags`.
|
||||
|
||||
## Notes
|
||||
|
||||
- All token commands use normal auth (API Key only, no signature required)
|
||||
- **Market cap is not returned directly** — calculate it as `price.price × circulating_supply` (`price` is now a nested object; use `price.price` for the current USD price string, and `circulating_supply` is a top-level field already in human-readable token units). Example: `price.price="3.11"` × `circulating_supply=999999151` ≈ $3.11B market cap.
|
||||
- **Trading volume and swap counts by window are available in `token info`** via the `price` object: `volume_{window}`, `buy_volume_{window}`, `sell_volume_{window}`, `buys_{window}`, `sells_{window}`, `swaps_{window}` (windows: `1m`, `5m`, `1h`, `6h`, `24h`). For OHLCV candlestick data, use `gmgn-market kline`.
|
||||
- All token commands use exist auth (API Key only, no signature required)
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- **Input validation** — Token addresses from API responses are treated as external data. Validate that addresses match the expected chain format (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits) before passing them to commands. The CLI enforces this at runtime and will exit with an error on invalid input.
|
||||
- `--tag` applies to both `holders` and `traders` and filters to only wallets with that tag — if few results are returned, try the other tag value
|
||||
- `amount_percentage` in holders/traders is a ratio (0–1), not a percentage — `0.05` means 5% of supply
|
||||
- **Input validation** — Token addresses are external data. Validate that addresses match the expected chain format (sol: base58 32–44 chars; bsc/base/eth: `0x` + 40 hex digits) before passing them to commands. The CLI enforces this at runtime and will exit with an error on invalid input.
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
---
|
||||
name: gmgn-track
|
||||
description: Get real-time crypto buy/sell activity from Smart Money wallets, KOL influencer wallets, and personally followed wallets via GMGN API — alpha signals, whale tracking, meme token copy-trading ideas on Solana, BSC, Base, or Ethereum. Use when user asks what smart money or KOLs are buying, wants whale alerts, on-chain alpha, or copy-trade signals. (For a specific wallet address, use gmgn-portfolio.)
|
||||
argument-hint: "<follow-wallet|kol|smartmoney> --chain <sol|bsc|base|eth> [--wallet <wallet_address>]"
|
||||
metadata:
|
||||
cliHelp: "gmgn-cli track --help"
|
||||
---
|
||||
|
||||
**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.**
|
||||
|
||||
**⚠️ 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 query on-chain tracking data based on the user's request.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **`follow-wallet` vs `kol` vs `smartmoney`** — Three distinct data sources. `follow-wallet` returns trades from wallets the user has personally followed on the GMGN platform (user-specific; the follow list is resolved from the GMGN user account bound to the API Key). `kol` and `smartmoney` return trades from platform-tagged public wallet lists (not user-specific). Never substitute one for another.
|
||||
|
||||
- **KOL (Key Opinion Leader)** — Wallets publicly identified as influencers or well-known traders on GMGN. Tagged as `renowned` in the platform's wallet label system. Their trades carry social/marketing signal, not necessarily alpha.
|
||||
|
||||
- **Smart Money (`smart_degen`)** — Wallets with a statistically proven record of profitable trading, identified by GMGN's algorithm. Same concept as `smart_degen` in gmgn-token. Their trades are a stronger alpha signal than KOL trades.
|
||||
|
||||
- **`is_open_or_close`** — Indicates whether a trade is a full position event. Interpretation differs by sub-command:
|
||||
- `follow-wallet`: `1` = full position open or close; `0` = partial add or reduce.
|
||||
- `kol` / `smartmoney`: `0` = position opened / added; `1` = position closed / reduced.
|
||||
Do not apply the same interpretation to both sub-commands.
|
||||
|
||||
- **`price_change`** — Ratio of price change since the trade was made. `6.66` = the token is now 6.66× what it was when the wallet traded (i.e. +566%). `0.5` = price halved since the trade (-50%). Use this to assess "how well did this trade age."
|
||||
|
||||
- **`base_address` vs `quote_address`** — In a trading pair, `base_address` is the token being bought/sold; `quote_address` is what it was priced in (typically SOL native address on Solana). To get the token of interest, always read `base_address`.
|
||||
|
||||
- **`maker_info.tags`** — Array of platform labels on the wallet (e.g. `["kol", "gmgn"]`, `["smart_degen", "photon"]`). A wallet can carry multiple tags. Use `tag_rank` (follow-wallet only) to see the wallet's rank within each tag category.
|
||||
|
||||
- **Cluster signal** — When multiple followed/tracked wallets trade the same token in the same direction within a short time window, this is a stronger conviction signal than a single wallet. Highlight this pattern when it appears in results.
|
||||
|
||||
**When to use which sub-command:**
|
||||
- `track follow-wallet` — user asks "what did the wallets I follow trade?", "show me my follow list trades", "show my followed wallet activity" → requires wallets followed via GMGN platform
|
||||
- `track kol` — user asks "what are KOLs buying?", "show me influencer trades", "what are KOLs doing recently" → returns trades from known KOL wallets
|
||||
- `track smartmoney` — user asks "what is smart money doing?", "show me whale trades", "what is smart money buying recently" → returns trades from smart money / whale wallets
|
||||
|
||||
**Do NOT confuse these three:**
|
||||
- `follow-wallet` = wallets the user has personally followed on GMGN
|
||||
- `kol` = platform-tagged KOL / influencer wallets (not user-specific)
|
||||
- `smartmoney` = platform-tagged smart money / whale wallets (not user-specific)
|
||||
|
||||
## Sub-commands
|
||||
|
||||
| Sub-command | Description |
|
||||
|-------------|-------------|
|
||||
| `track follow-wallet` | Trade records from wallets the user personally follows on GMGN |
|
||||
| `track kol` | Real-time trades from KOL / influencer wallets tagged by GMGN |
|
||||
| `track smartmoney` | Real-time trades from smart money / whale wallets tagged by GMGN |
|
||||
|
||||
## Supported Chains
|
||||
|
||||
`sol` / `bsc` / `base` / `eth`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `gmgn-cli` installed globally — if missing, run: `npm install -g gmgn-cli`
|
||||
- `GMGN_API_KEY` configured in `~/.config/gmgn/.env` — required for all sub-commands
|
||||
- `GMGN_PRIVATE_KEY` — required for `track follow-wallet` only (signed auth); not needed for `kol` or `smartmoney`
|
||||
|
||||
## Rate Limit Handling
|
||||
|
||||
All tracking routes used by this skill go through GMGN's leaky-bucket limiter with `rate=20` and `capacity=20`. Sustained throughput is roughly `20 ÷ weight` requests/second, and the max burst is roughly `floor(20 ÷ weight)` when the bucket is full.
|
||||
|
||||
| Command | Route | Weight |
|
||||
|---------|-------|--------|
|
||||
| `track follow-wallet` | `GET /v1/trade/follow_wallet` | 3 |
|
||||
| `track kol` | `GET /v1/user/kol` | 1 |
|
||||
| `track smartmoney` | `GET /v1/user/smartmoney` | 1 |
|
||||
|
||||
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.
|
||||
|
||||
**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
|
||||
# Follow-wallet trades (all wallets you follow)
|
||||
gmgn-cli track follow-wallet --chain sol
|
||||
|
||||
# Follow-wallet trades filtered by wallet
|
||||
gmgn-cli track follow-wallet --chain sol --wallet <wallet_address>
|
||||
|
||||
# Follow-wallet filtered by trade direction
|
||||
gmgn-cli track follow-wallet --chain sol --side buy
|
||||
|
||||
# Follow-wallet filtered by USD amount range
|
||||
gmgn-cli track follow-wallet --chain sol --min-amount-usd 100 --max-amount-usd 10000
|
||||
|
||||
# KOL trade records (SOL, default)
|
||||
gmgn-cli track kol --limit 10 --raw
|
||||
|
||||
# KOL trade records on SOL, buy only
|
||||
gmgn-cli track kol --chain sol --side buy --limit 10 --raw
|
||||
|
||||
# Smart Money trade records (SOL, default)
|
||||
gmgn-cli track smartmoney --limit 10 --raw
|
||||
|
||||
# Smart Money trade records, sell only
|
||||
gmgn-cli track smartmoney --chain sol --side sell --limit 10 --raw
|
||||
```
|
||||
|
||||
## `track follow-wallet` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain` | Required. `sol` / `bsc` / `base` / `eth` |
|
||||
| `--wallet <address>` | Filter by wallet address |
|
||||
| `--limit <n>` | Page size (1–100, default 10) |
|
||||
| `--side <side>` | Trade direction: `buy` / `sell` |
|
||||
| `--filter <tag...>` | Repeatable filter conditions |
|
||||
| `--min-amount-usd <n>` | Minimum trade amount (USD) |
|
||||
| `--max-amount-usd <n>` | Maximum trade amount (USD) |
|
||||
|
||||
## `track kol` / `track smartmoney` Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--chain <chain>` | Required. Chain: `sol` / `bsc` / `base` / `eth` |
|
||||
| `--limit <n>` | Page size (1–200, default 100) |
|
||||
| `--side <side>` | Filter by trade direction: `buy` / `sell` (client-side filter — applied locally after fetching results) |
|
||||
|
||||
## `track follow-wallet` Response Fields
|
||||
|
||||
Top-level fields:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `next_page_token` | Opaque token for fetching the next page of results |
|
||||
| `list` | Array of trade records |
|
||||
|
||||
Each item in `list` contains:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `id` | Record ID (base64-encoded, use as cursor) |
|
||||
| `chain` | Chain name (e.g. `sol`) |
|
||||
| `transaction_hash` | On-chain transaction hash |
|
||||
| `maker` | Wallet address of the followed wallet |
|
||||
| `side` | Trade direction: `buy` or `sell` |
|
||||
| `base_address` | Token contract address |
|
||||
| `quote_address` | Quote token address (SOL native address for buys/sells on SOL) |
|
||||
| `base_amount` | Token quantity in smallest unit |
|
||||
| `quote_amount` | Quote token amount spent / received (e.g. SOL) |
|
||||
| `amount_usd` | Trade value in USD |
|
||||
| `cost_usd` | Same as `amount_usd` — USD value of this transaction leg |
|
||||
| `buy_cost_usd` | Original buy cost in USD (`0` if this record is the buy itself) |
|
||||
| `price` | Token price denominated in quote token at time of trade |
|
||||
| `price_usd` | Token price in USD at time of trade |
|
||||
| `price_now` | Token current price in USD |
|
||||
| `price_change` | Price change ratio since trade time (e.g. `6.66` = +666%) |
|
||||
| `timestamp` | Unix timestamp of the trade |
|
||||
| `is_open_or_close` | `1` = full position open or close; `0` = partial add or reduce |
|
||||
| `launchpad` | Launchpad display name (e.g. `Pump.fun`) |
|
||||
| `launchpad_platform` | Launchpad platform identifier (e.g. `Pump.fun`, `pump_agent`) |
|
||||
| `migrated_pool_exchange` | DEX the token migrated to, if any (e.g. `pump_amm`); empty if not migrated |
|
||||
| `base_token.symbol` | Token ticker symbol |
|
||||
| `base_token.logo` | Token logo image URL |
|
||||
| `base_token.hot_level` | Hotness level (`0` = normal, higher = trending) |
|
||||
| `base_token.total_supply` | Total token supply (string) |
|
||||
| `base_token.token_create_time` | Unix timestamp when token was created |
|
||||
| `base_token.token_open_time` | Unix timestamp when trading opened (`0` if not yet migrated/opened) |
|
||||
| `maker_info.address` | Followed wallet address |
|
||||
| `maker_info.name` | Wallet display name |
|
||||
| `maker_info.twitter_username` | Twitter / X username |
|
||||
| `maker_info.twitter_name` | Twitter / X display name |
|
||||
| `maker_info.tags` | Array of wallet tags (e.g. `["kol","gmgn"]`) |
|
||||
| `maker_info.tag_rank` | Map of tag → rank within that category (e.g. `{"kol": 854}`) |
|
||||
| `balance_info` | Wallet token balance info; `null` if not available |
|
||||
|
||||
## `track kol` / `track smartmoney` Response Fields
|
||||
|
||||
The response is an object with a `list` array. Each item in `list` contains:
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `transaction_hash` | On-chain transaction hash |
|
||||
| `maker` | Wallet address of the trader (KOL / Smart Money) |
|
||||
| `side` | Trade direction: `buy` or `sell` |
|
||||
| `base_address` | Token contract address |
|
||||
| `base_token.symbol` | Token ticker symbol |
|
||||
| `base_token.launchpad` | Launchpad platform (e.g. `pump`) |
|
||||
| `amount_usd` | Trade value in USD |
|
||||
| `token_amount` | Token quantity traded |
|
||||
| `price_usd` | Token price in USD at time of trade |
|
||||
| `buy_cost_usd` | Original buy cost in USD (0 if this record is the buy) |
|
||||
| `is_open_or_close` | `0` = position opened / added, `1` = position closed / reduced |
|
||||
| `timestamp` | Unix timestamp of the trade |
|
||||
| `maker_info.twitter_username` | KOL's Twitter username |
|
||||
| `maker_info.tags` | Wallet tags (e.g. `kol`, `smart_degen`, `photon`) |
|
||||
|
||||
## Smart Money Behavior Interpretation
|
||||
|
||||
After receiving trade data, interpret the signals using these frameworks before presenting results. Do not just list trades — analyze what they mean.
|
||||
|
||||
### 1. Signal Strength Levels
|
||||
|
||||
| Level | Criteria |
|
||||
|-------|----------|
|
||||
| Weak | 1 KOL buys |
|
||||
| Medium | 2–3 smart money buys in the same direction, OR 1 smart money full position open |
|
||||
| Strong | ≥ 3 smart money wallets same direction within 30 min (cluster signal) |
|
||||
| Very Strong | Cluster signal + full position opens + KOL joining the same trade |
|
||||
|
||||
### 2. Reading `is_open_or_close` — Conviction Signals
|
||||
|
||||
The field has opposite meanings by sub-command:
|
||||
|
||||
- **`follow-wallet`**: `1` = full position open or close; `0` = partial add or reduce.
|
||||
- **`kol` / `smartmoney`**: `0` = position opened / added; `1` = position closed / reduced.
|
||||
|
||||
Full position events (full open or full close) carry much stronger conviction than partial adds. A wallet opening a full new position signals high confidence. A wallet doing a full close signals they are exiting completely — treat this as a potential exit signal for that token.
|
||||
|
||||
### 3. Using `price_change` to Evaluate Track Record
|
||||
|
||||
`price_change` is a ratio of current price vs price at trade time:
|
||||
- `price_change > 2` → this wallet's trade aged well (token is now 2x+ since they bought) — strong conviction signal
|
||||
- `price_change 1–2` → modest gain, trade is in profit
|
||||
- `price_change < 1` → trade is underwater (current price below entry)
|
||||
|
||||
Use this to build a mental model of a wallet's past performance before acting on their current trades.
|
||||
|
||||
### 4. Cluster Signal Detection
|
||||
|
||||
When multiple trades hit the same `base_address` in a short time window, this is a convergence signal — stronger than any single trade. To identify:
|
||||
- Group results by `base_address`
|
||||
- Count distinct `maker` addresses trading the same direction
|
||||
- If ≥ 3 distinct wallets buy the same token within ~30 min → highlight as **cluster signal**
|
||||
|
||||
Cluster signals from `smartmoney` are stronger than from `kol` alone.
|
||||
|
||||
### 5. Red Flags in Smart Money Data
|
||||
|
||||
- **Smart money selling** (`side = sell` + `is_open_or_close` = full close) → exit signal — evaluate whether to exit or reduce position
|
||||
- **Only KOL buying, zero smart_degen** → social hype without fundamental backing; higher risk
|
||||
- **Renowned buying + smart money selling simultaneously** → divergence signal — insiders may be distributing into retail/KOL demand; high risk
|
||||
- **Single very large buy, no follow-through** → may be one-off; wait for confirmation from other wallets
|
||||
|
||||
## Output Format
|
||||
|
||||
### `track follow-wallet` / `track kol` / `track smartmoney` — Trade Feed
|
||||
|
||||
Present as a reverse-chronological trade feed. Do not dump raw JSON.
|
||||
|
||||
```
|
||||
{timestamp} {side} {base_token.symbol} ${amount_usd} by {maker_info.name or short address}
|
||||
[{tags}] Price: ${price_usd} | Price now: ${price_now} ({price_change}x since trade)
|
||||
```
|
||||
|
||||
Group by token if multiple trades hit the same token. Highlight tokens where several followed wallets traded in the same direction within a short window (cluster signal).
|
||||
|
||||
For `follow-wallet`, also show `is_open_or_close`: flag full position opens/closes distinctly from partial adds/reduces.
|
||||
|
||||
### Cluster Signal Summary
|
||||
|
||||
After presenting the trade feed, check for convergence signals. If ≥ 2 distinct wallets traded the same token in the same direction, display a summary block:
|
||||
|
||||
```
|
||||
⚡ Convergence Signals
|
||||
──────────────────────────────────────────
|
||||
TOKEN_X ({short_address})
|
||||
5 smart money wallets — all BUY — $42,300 total — within 15 min
|
||||
Signal strength: STRONG
|
||||
|
||||
TOKEN_Y ({short_address})
|
||||
2 KOL wallets — BUY (full open) — $8,100 total
|
||||
Signal strength: MEDIUM
|
||||
```
|
||||
|
||||
For STRONG signals: proceed to full token research before acting — see [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md)
|
||||
For MEDIUM signals: monitor and wait for more wallets to confirm before acting.
|
||||
|
||||
If no convergence signals are detected: output "No cluster signals detected in this result set."
|
||||
|
||||
To research any token surfaced by smart money activity, follow [`docs/workflow-token-research.md`](../../docs/workflow-token-research.md)
|
||||
|
||||
**Smart money leaderboard / wallet profiling:** When the user asks "which smart money wallets are best to follow", "rank wallets by win rate", or wants to compare wallet performance — use `track smartmoney` to collect active wallet addresses, then batch-query their stats via `gmgn-portfolio stats`. Full workflow: [`docs/workflow-smart-money-profile.md`](../../docs/workflow-smart-money-profile.md)
|
||||
|
||||
**Daily brief:** When the user asks for a market overview ("what's the market like today", "what is smart money buying today", "give me a daily brief") — combine `track smartmoney` + `track kol` with `gmgn-market trending`. Full workflow: [`docs/workflow-daily-brief.md`](../../docs/workflow-daily-brief.md)
|
||||
|
||||
## Safety Constraints
|
||||
|
||||
- **`follow-wallet` reveals your following list** — results expose which wallets you have followed on GMGN. Do not share raw output in public channels.
|
||||
- **`track kol` / `track smartmoney` expose no personal data** — these use API Key auth only and return platform-tagged public wallet activity. Safe to share raw output.
|
||||
|
||||
## Notes
|
||||
|
||||
- `track follow-wallet` uses signed auth (API Key + private key signature); `track kol` and `track smartmoney` use exist auth (API Key only)
|
||||
- `track follow-wallet` returns trades from wallets followed on the GMGN platform; the follow list is resolved automatically from the GMGN user account bound to the API Key — `--wallet` is optional
|
||||
- Use `--raw` to get single-line JSON for further processing
|
||||
- `track kol` / `track smartmoney` `--side` is a **client-side filter** — the CLI fetches all results then filters locally; it is NOT sent to the API
|
||||
@@ -2,12 +2,63 @@
|
||||
* OpenApiClient — GMGN OpenAPI external client
|
||||
*
|
||||
* Auth modes:
|
||||
* Normal (market/token/portfolio): X-APIKEY + timestamp + client_id
|
||||
* Critical (swap/order): normal auth + X-Signature (private key signature)
|
||||
* Exist (market/token/portfolio): X-APIKEY + timestamp + client_id
|
||||
* Signed (swap and order routes): X-APIKEY + timestamp + client_id + X-Signature (private key signature)
|
||||
*/
|
||||
|
||||
import { buildAuthQuery, buildMessage, detectAlgorithm, sign } from "./signer.js";
|
||||
|
||||
const RATE_LIMIT_RETRY_BUFFER_MS = 1000;
|
||||
const DEFAULT_RATE_LIMIT_AUTO_RETRY_MAX_WAIT_MS = 5000;
|
||||
|
||||
interface PreparedRequest {
|
||||
method: string;
|
||||
subPath: string;
|
||||
url: string;
|
||||
headers: Record<string, string>;
|
||||
body: string | null;
|
||||
curlStr: string;
|
||||
}
|
||||
|
||||
interface ResponseEnvelope {
|
||||
code: number | string;
|
||||
data?: unknown;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface OpenApiErrorParams {
|
||||
method: string;
|
||||
path: string;
|
||||
status: number;
|
||||
apiCode?: number | string;
|
||||
apiError?: string;
|
||||
apiMessage?: string;
|
||||
resetAtUnix?: number;
|
||||
}
|
||||
|
||||
class OpenApiError extends Error {
|
||||
readonly method: string;
|
||||
readonly path: string;
|
||||
readonly status: number;
|
||||
readonly apiCode?: number | string;
|
||||
readonly apiError?: string;
|
||||
readonly apiMessage?: string;
|
||||
readonly resetAtUnix?: number;
|
||||
|
||||
constructor(params: OpenApiErrorParams) {
|
||||
super(buildOpenApiErrorMessage(params));
|
||||
this.name = "OpenApiError";
|
||||
this.method = params.method;
|
||||
this.path = params.path;
|
||||
this.status = params.status;
|
||||
this.apiCode = params.apiCode;
|
||||
this.apiError = params.apiError;
|
||||
this.apiMessage = params.apiMessage;
|
||||
this.resetAtUnix = params.resetAtUnix;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
apiKey: string;
|
||||
privateKeyPem?: string;
|
||||
@@ -29,11 +80,239 @@ export interface SwapParams {
|
||||
is_anti_mev?: boolean;
|
||||
priority_fee?: string;
|
||||
tip_fee?: string;
|
||||
auto_tip_fee?: boolean;
|
||||
max_auto_fee?: string;
|
||||
gas_price?: string;
|
||||
gas_level?: string;
|
||||
auto_fee?: boolean;
|
||||
max_fee_per_gas?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
condition_orders?: StrategyConditionOrder[];
|
||||
sell_ratio_type?: string;
|
||||
}
|
||||
|
||||
export interface StrategyConditionOrder {
|
||||
order_type: string; // "profit_stop" | "loss_stop" | "profit_stop_trace" | "loss_stop_trace"
|
||||
side: string; // "sell"
|
||||
price_scale?: string;
|
||||
sell_ratio: string;
|
||||
drawdown_rate?: string;
|
||||
}
|
||||
|
||||
export interface MultiSwapParams {
|
||||
chain: string;
|
||||
accounts: string[];
|
||||
input_token: string;
|
||||
output_token: string;
|
||||
input_amount?: Record<string, string>;
|
||||
input_amount_bps?: Record<string, string>;
|
||||
output_amount?: Record<string, string>;
|
||||
swap_mode?: string;
|
||||
slippage?: number;
|
||||
auto_slippage?: boolean;
|
||||
is_anti_mev?: boolean;
|
||||
priority_fee?: string;
|
||||
tip_fee?: string;
|
||||
gas_price?: string;
|
||||
gas_level?: string;
|
||||
auto_fee?: boolean;
|
||||
max_fee_per_gas?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
condition_orders?: StrategyConditionOrder[];
|
||||
sell_ratio_type?: string;
|
||||
}
|
||||
|
||||
export interface StrategyCreateParams {
|
||||
chain: string;
|
||||
from_address: string;
|
||||
base_token: string;
|
||||
quote_token: string;
|
||||
order_type: string;
|
||||
sub_order_type: string;
|
||||
check_price?: string;
|
||||
open_price?: string;
|
||||
amount_in?: string;
|
||||
amount_in_percent?: string;
|
||||
limit_price_mode?: string;
|
||||
price_gap_ratio?: string;
|
||||
expire_in?: number;
|
||||
sell_ratio_type?: string;
|
||||
slippage?: number;
|
||||
auto_slippage?: boolean;
|
||||
fee?: string;
|
||||
auto_fee?: boolean;
|
||||
gas_price?: string;
|
||||
gas_level?: string;
|
||||
max_fee_per_gas?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
is_anti_mev?: boolean;
|
||||
anti_mev_mode?: string;
|
||||
priority_fee?: string;
|
||||
tip_fee?: string;
|
||||
custom_rpc?: string;
|
||||
condition_orders?: StrategyConditionOrder[];
|
||||
quote_investment?: string;
|
||||
}
|
||||
|
||||
export interface StrategyCancelParams {
|
||||
chain: string;
|
||||
from_address: string;
|
||||
order_id: string;
|
||||
order_type?: string;
|
||||
close_sell_model?: string;
|
||||
}
|
||||
|
||||
export interface TokenSignalGroup {
|
||||
signal_type?: number[];
|
||||
mc_min?: number;
|
||||
mc_max?: number;
|
||||
trigger_mc_min?: number;
|
||||
trigger_mc_max?: number;
|
||||
total_fee_min?: number;
|
||||
total_fee_max?: number;
|
||||
min_create_or_open_ts?: string;
|
||||
max_create_or_open_ts?: string;
|
||||
}
|
||||
|
||||
export interface PumpFeeShareInfo {
|
||||
provider: string; // "solana" | "twitter" | "github"
|
||||
username: string; // platform username; a SOL address when provider = "solana"
|
||||
basic_points: number;
|
||||
}
|
||||
|
||||
export interface BAGSFeeShareInfo {
|
||||
provider: string; // "twitter" | "solana" | "kick" | "github"
|
||||
username: string;
|
||||
basic_points: number;
|
||||
}
|
||||
|
||||
export interface FlapRateConf {
|
||||
tax_rate?: number; // V5 unified tax rate, e.g. 5% -> 500
|
||||
buy_tax_rate?: number; // V6 separate buy tax rate
|
||||
sell_tax_rate?: number; // V6 separate sell tax rate
|
||||
mkt_bps?: number;
|
||||
deflation_bps?: number;
|
||||
dividend_bps?: number;
|
||||
lp_bps?: number;
|
||||
minimum_share_balance?: number;
|
||||
recipient_type?: string;
|
||||
beneficiary?: string;
|
||||
twitter_account?: string;
|
||||
split_conf?: Array<{ recipient: string; bps: number }>;
|
||||
}
|
||||
|
||||
export interface FourmemeRateConf {
|
||||
fee_plan?: boolean;
|
||||
fee_rate?: number;
|
||||
burn_rate?: number;
|
||||
divide_rate?: number;
|
||||
liquidity_rate?: number;
|
||||
recipient_rate?: number;
|
||||
recipient_address?: string;
|
||||
min_sharing?: number;
|
||||
}
|
||||
|
||||
export interface BuyWalletInfo {
|
||||
from_address: string;
|
||||
buy_amt: string;
|
||||
}
|
||||
|
||||
// Buy/sell execution config for CondMarket orders (snipe buy, auto-sell, pending_sell).
|
||||
// Does NOT affect the main creation tx. Falls back to outer-level fields when omitted.
|
||||
export interface TradeParam {
|
||||
slippage?: number;
|
||||
auto_slippage?: boolean;
|
||||
fee?: string;
|
||||
priority_fee?: string;
|
||||
tip_fee?: string;
|
||||
gas_price?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
max_fee_per_gas?: string;
|
||||
is_anti_mev?: boolean; // backend currently forces true; passing has no effect
|
||||
anti_mev_mode?: string; // backend currently forces "secure"; passing has no effect
|
||||
}
|
||||
|
||||
export interface CookingSellConfig {
|
||||
sell_type: string; // "delay_sell" | "limit_order"
|
||||
delay_sec?: number; // required when sell_type = "delay_sell"
|
||||
delay_mili_sec?: number; // optional; takes precedence over delay_sec
|
||||
sell_ratio: string; // "1" = 100%, "0.5" = 50%
|
||||
check_price?: string; // trigger market cap in USD; required when sell_type = "limit_order"
|
||||
wallet_addresses: string[]; // empty array means the strategy is inert
|
||||
}
|
||||
|
||||
export interface CreateTokenParams {
|
||||
// Required
|
||||
chain: string;
|
||||
dex: string;
|
||||
from_address: string;
|
||||
name: string;
|
||||
symbol: string;
|
||||
buy_amt: string;
|
||||
|
||||
// Image (one required)
|
||||
image?: string;
|
||||
image_url?: string;
|
||||
|
||||
// Social
|
||||
description?: string;
|
||||
website?: string;
|
||||
twitter?: string;
|
||||
telegram?: string;
|
||||
|
||||
// Transaction
|
||||
slippage?: number;
|
||||
auto_slippage?: boolean;
|
||||
|
||||
// Fees
|
||||
fee?: string;
|
||||
priority_fee?: string;
|
||||
tip_fee?: string;
|
||||
gas_price?: string;
|
||||
max_priority_fee_per_gas?: string;
|
||||
max_fee_per_gas?: string;
|
||||
|
||||
// Anti-MEV (SOL only)
|
||||
is_anti_mev?: boolean;
|
||||
anti_mev_mode?: string;
|
||||
|
||||
// Advanced
|
||||
raised_token?: string;
|
||||
dev_gas?: string;
|
||||
dev_priority?: string;
|
||||
dev_tip?: string;
|
||||
dev_max_fee_per_gas?: string;
|
||||
approve_vision?: string;
|
||||
source?: string;
|
||||
dev_wallet_bps?: number;
|
||||
|
||||
// CondMarket buy/sell execution config (snipe / bundle / auto-sell)
|
||||
buy_trade_config?: TradeParam;
|
||||
sell_trade_config?: TradeParam;
|
||||
|
||||
// Auto-sell strategies created after a successful launch
|
||||
sell_configs?: CookingSellConfig[];
|
||||
|
||||
// Pump.fun specific
|
||||
is_mayhem?: boolean;
|
||||
is_cashback?: boolean;
|
||||
is_buy_back?: boolean;
|
||||
pump_fee_share_list?: PumpFeeShareInfo[];
|
||||
|
||||
// Flap specific
|
||||
flap_rate_conf?: FlapRateConf;
|
||||
|
||||
// FourMeme specific
|
||||
fourmeme_rate_conf?: FourmemeRateConf;
|
||||
|
||||
// BAGS specific
|
||||
bags_fee_share_list?: BAGSFeeShareInfo[];
|
||||
|
||||
// Bonk specific
|
||||
bonk_model?: string;
|
||||
|
||||
// Multi-wallet buy
|
||||
buy_wallets?: BuyWalletInfo[];
|
||||
snip_buy_wallets?: BuyWalletInfo[];
|
||||
interval_seconds?: number;
|
||||
}
|
||||
|
||||
export class OpenApiClient {
|
||||
@@ -47,52 +326,55 @@ export class OpenApiClient {
|
||||
this.host = config.host.replace(/\/$/, "");
|
||||
}
|
||||
|
||||
// ---- Token endpoints (normal auth) ----
|
||||
// ---- Token endpoints (exist auth) ----
|
||||
|
||||
async getTokenInfo(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/info", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/info", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenSecurity(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/security", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/security", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenPoolInfo(chain: string, address: string): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/token/pool_info", { chain, address });
|
||||
return this.authExistRequest("GET", "/v1/token/pool_info", { chain, address });
|
||||
}
|
||||
|
||||
async getTokenTopHolders(chain: string, address: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_top_holders", { chain, address, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/token_top_holders", { chain, address, ...extra });
|
||||
}
|
||||
|
||||
async getTokenTopTraders(chain: string, address: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_top_traders", { chain, address, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/token_top_traders", { chain, address, ...extra });
|
||||
}
|
||||
|
||||
// ---- Market endpoints (normal auth) ----
|
||||
// ---- Market endpoints (exist auth) ----
|
||||
|
||||
async getTokenKline(
|
||||
chain: string,
|
||||
address: string,
|
||||
resolution: string,
|
||||
from: number,
|
||||
to: number
|
||||
from?: number,
|
||||
to?: number
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/token_kline", { chain, address, resolution, from, to });
|
||||
const query: Record<string, string | number> = { chain, address, resolution };
|
||||
if (from != null) query["from"] = from;
|
||||
if (to != null) query["to"] = to;
|
||||
return this.authExistRequest("GET", "/v1/market/token_kline", query);
|
||||
}
|
||||
|
||||
// ---- Portfolio endpoints (normal auth) ----
|
||||
// ---- Portfolio endpoints ----
|
||||
|
||||
async getWalletHoldings(
|
||||
chain: string,
|
||||
walletAddress: string,
|
||||
extra: Record<string, string | number> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_holdings", {
|
||||
return this.authSignedRequest("GET", "/v1/user/wallet_holdings", {
|
||||
chain,
|
||||
wallet_address: walletAddress,
|
||||
...extra,
|
||||
});
|
||||
}, null);
|
||||
}
|
||||
|
||||
async getWalletActivity(
|
||||
@@ -100,7 +382,7 @@ export class OpenApiClient {
|
||||
walletAddress: string,
|
||||
extra: Record<string, string | number | string[]> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_activity", {
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_activity", {
|
||||
chain,
|
||||
wallet_address: walletAddress,
|
||||
...extra,
|
||||
@@ -108,7 +390,7 @@ export class OpenApiClient {
|
||||
}
|
||||
|
||||
async getWalletStats(chain: string, walletAddresses: string[], period = "7d"): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_stats", {
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_stats", {
|
||||
chain,
|
||||
wallet_address: walletAddresses,
|
||||
period,
|
||||
@@ -120,83 +402,207 @@ export class OpenApiClient {
|
||||
walletAddress: string,
|
||||
tokenAddress: string
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/wallet_token_balance", { chain, wallet_address: walletAddress, token_address: tokenAddress });
|
||||
return this.authExistRequest("GET", "/v1/user/wallet_token_balance", { chain, wallet_address: walletAddress, token_address: tokenAddress });
|
||||
}
|
||||
|
||||
// ---- Market trending endpoints (normal auth) ----
|
||||
async getTrenches(chain: string, types?: string[], platforms?: string[], limit?: number, filters?: Record<string, number | string>): Promise<unknown> {
|
||||
const body = buildTrenchesBody(chain, types, platforms, limit, filters);
|
||||
return this.authExistRequest("POST", "/v1/trenches", { chain }, body);
|
||||
}
|
||||
|
||||
// ---- Market trending endpoints (exist auth) ----
|
||||
|
||||
async getTrendingSwaps(
|
||||
chain: string,
|
||||
interval: string,
|
||||
extra: Record<string, string | number | string[]> = {}
|
||||
): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/market/rank", { chain, interval, ...extra });
|
||||
return this.authExistRequest("GET", "/v1/market/rank", { chain, interval, ...extra });
|
||||
}
|
||||
|
||||
// ---- User endpoints (normal auth) ----
|
||||
async getTokenSignalV2(chain: string, groups: TokenSignalGroup[]): Promise<unknown> {
|
||||
return this.authExistRequest("POST", "/v1/market/token_signal", {}, { chain, groups });
|
||||
}
|
||||
|
||||
// ---- User endpoints (exist auth) ----
|
||||
|
||||
async getUserInfo(): Promise<unknown> {
|
||||
return this.normalRequest("GET", "/v1/user/info", {});
|
||||
return this.authExistRequest("GET", "/v1/user/info", {});
|
||||
}
|
||||
|
||||
// ---- Swap endpoints (critical auth) ----
|
||||
async getFollowWallet(chain: string, extra: Record<string, string | number | string[]> = {}): Promise<unknown> {
|
||||
return this.authSignedRequest("GET", "/v1/trade/follow_wallet", { chain, ...extra }, null);
|
||||
}
|
||||
|
||||
async getKol(chain?: string, limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (chain) query["chain"] = chain;
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.authExistRequest("GET", "/v1/user/kol", query);
|
||||
}
|
||||
|
||||
async getSmartMoney(chain?: string, limit?: number): Promise<unknown> {
|
||||
const query: Record<string, string | number> = {};
|
||||
if (chain) query["chain"] = chain;
|
||||
if (limit != null) query["limit"] = limit;
|
||||
return this.authExistRequest("GET", "/v1/user/smartmoney", query);
|
||||
}
|
||||
|
||||
async getCreatedTokens(chain: string, walletAddress: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.authExistRequest("GET", "/v1/user/created_tokens", { chain, wallet_address: walletAddress, ...extra });
|
||||
}
|
||||
|
||||
async quoteOrder(
|
||||
chain: string,
|
||||
from_address: string,
|
||||
input_token: string,
|
||||
output_token: string,
|
||||
input_amount: string,
|
||||
slippage: number
|
||||
): Promise<unknown> {
|
||||
const query = { chain, from_address, input_token, output_token, input_amount, slippage };
|
||||
return this.authSignedRequest("GET", "/v1/trade/quote", query, null);
|
||||
}
|
||||
|
||||
// ---- Swap endpoints (signed auth) ----
|
||||
|
||||
async swap(params: SwapParams): Promise<unknown> {
|
||||
return this.criticalRequest("POST", "/v1/trade/swap", {}, params);
|
||||
return this.authSignedRequest("POST", "/v1/trade/swap", {}, params);
|
||||
}
|
||||
|
||||
async multiSwap(params: MultiSwapParams): Promise<unknown> {
|
||||
return this.authSignedRequest("POST", "/v1/trade/multi_swap", {}, params);
|
||||
}
|
||||
|
||||
async queryOrder(orderId: string, chain: string): Promise<unknown> {
|
||||
return this.criticalRequest("GET", "/v1/trade/query_order", { order_id: orderId, chain }, null);
|
||||
return this.authSignedRequest("GET", "/v1/trade/query_order", { order_id: orderId, chain }, null);
|
||||
}
|
||||
|
||||
async getGasPrice(chain: string): Promise<unknown> {
|
||||
return this.authExistRequest("GET", "/v1/trade/gas_price", { chain });
|
||||
}
|
||||
|
||||
// ---- Strategy order endpoints (signed auth) ----
|
||||
|
||||
async createStrategyOrder(params: StrategyCreateParams): Promise<unknown> {
|
||||
return this.authSignedRequest("POST", "/v1/trade/strategy/create", {}, params);
|
||||
}
|
||||
|
||||
async getStrategyOrders(chain: string, extra: Record<string, string | number> = {}): Promise<unknown> {
|
||||
return this.authSignedRequest("GET", "/v1/trade/strategy/orders", { chain, ...extra }, null);
|
||||
}
|
||||
|
||||
async cancelStrategyOrder(params: StrategyCancelParams): Promise<unknown> {
|
||||
return this.authSignedRequest("POST", "/v1/trade/strategy/cancel", {}, params);
|
||||
}
|
||||
|
||||
// ---- Cooking endpoints ----
|
||||
|
||||
async getCookingStatistics(): Promise<unknown> {
|
||||
return this.authExistRequest("GET", "/v1/cooking/statistics", {});
|
||||
}
|
||||
|
||||
async createToken(params: CreateTokenParams): Promise<unknown> {
|
||||
return this.authSignedRequest("POST", "/v1/cooking/create_token", {}, params);
|
||||
}
|
||||
|
||||
// ---- Internal methods ----
|
||||
|
||||
private async normalRequest(
|
||||
private async authExistRequest(
|
||||
method: string,
|
||||
subPath: string,
|
||||
queryExtra: Record<string, string | number | string[]>,
|
||||
body: unknown = null
|
||||
): Promise<unknown> {
|
||||
const { timestamp, client_id } = buildAuthQuery();
|
||||
const query: Record<string, string | number | string[]> = { ...queryExtra, timestamp, client_id };
|
||||
|
||||
const url = buildUrl(`${this.host}${subPath}`, query);
|
||||
const headers: Record<string, string> = {
|
||||
"X-APIKEY": this.apiKey,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const bodyStr = body !== null ? JSON.stringify(body) : null;
|
||||
const curlStr = formatCurl(method, url, headers, bodyStr);
|
||||
const res = await this.doFetch(method, subPath, url, headers, bodyStr, curlStr);
|
||||
return this.parseResponse(method, subPath, res, curlStr);
|
||||
return this.executePreparedRequest(() => {
|
||||
const { timestamp, client_id } = buildAuthQuery();
|
||||
const query: Record<string, string | number | string[]> = { ...queryExtra, timestamp, client_id };
|
||||
const url = buildUrl(`${this.host}${subPath}`, query);
|
||||
const headers: Record<string, string> = {
|
||||
"X-APIKEY": this.apiKey,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const bodyStr = body !== null ? JSON.stringify(body) : null;
|
||||
return {
|
||||
method,
|
||||
subPath,
|
||||
url,
|
||||
headers,
|
||||
body: bodyStr,
|
||||
curlStr: formatCurl(method, url, headers, bodyStr),
|
||||
};
|
||||
}, true);
|
||||
}
|
||||
|
||||
private async criticalRequest(
|
||||
private async authSignedRequest(
|
||||
method: string,
|
||||
subPath: string,
|
||||
queryExtra: Record<string, string | number>,
|
||||
queryExtra: Record<string, string | number | string[]>,
|
||||
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, order, follow-wallet, and portfolio holdings commands)");
|
||||
}
|
||||
|
||||
const { timestamp, client_id } = buildAuthQuery();
|
||||
const query: Record<string, string | number> = { ...queryExtra, timestamp, client_id };
|
||||
return this.executePreparedRequest(() => {
|
||||
const { timestamp, client_id } = buildAuthQuery();
|
||||
const query: Record<string, string | number | string[]> = { ...queryExtra, timestamp, client_id };
|
||||
const bodyStr = body !== null ? JSON.stringify(body) : "";
|
||||
const message = buildMessage(subPath, query, bodyStr, timestamp);
|
||||
const signature = sign(message, this.privateKeyPem!, detectAlgorithm(this.privateKeyPem!));
|
||||
|
||||
const bodyStr = body !== null ? JSON.stringify(body) : "";
|
||||
const message = buildMessage(subPath, query, bodyStr, timestamp);
|
||||
const signature = sign(message, this.privateKeyPem, detectAlgorithm(this.privateKeyPem));
|
||||
const url = buildUrl(`${this.host}${subPath}`, query);
|
||||
const headers: Record<string, string> = {
|
||||
"X-APIKEY": this.apiKey,
|
||||
"X-Signature": signature,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
return {
|
||||
method,
|
||||
subPath,
|
||||
url,
|
||||
headers,
|
||||
body: bodyStr || null,
|
||||
curlStr: formatCurl(method, url, headers, bodyStr || null),
|
||||
};
|
||||
}, method !== "POST");
|
||||
}
|
||||
|
||||
const url = buildUrl(`${this.host}${subPath}`, query);
|
||||
const headers: Record<string, string> = {
|
||||
"X-APIKEY": this.apiKey,
|
||||
"X-Signature": signature,
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const curlStr = formatCurl(method, url, headers, bodyStr || null);
|
||||
const res = await this.doFetch(method, subPath, url, headers, bodyStr || null, curlStr);
|
||||
return this.parseResponse(method, subPath, res, curlStr);
|
||||
private async executePreparedRequest(
|
||||
prepare: () => PreparedRequest,
|
||||
autoRetryOnRateLimit: boolean
|
||||
): Promise<unknown> {
|
||||
const maxAttempts = autoRetryOnRateLimit ? 2 : 1;
|
||||
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
||||
const request = prepare();
|
||||
const res = await this.doFetch(
|
||||
request.method,
|
||||
request.subPath,
|
||||
request.url,
|
||||
request.headers,
|
||||
request.body,
|
||||
request.curlStr
|
||||
);
|
||||
|
||||
try {
|
||||
return this.parseResponse(request.method, request.subPath, res, request.curlStr);
|
||||
} catch (err) {
|
||||
const retryDelayMs = getRateLimitRetryDelayMs(err, attempt, maxAttempts, autoRetryOnRateLimit);
|
||||
if (retryDelayMs == null) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (process.env.GMGN_DEBUG) {
|
||||
console.error(
|
||||
`[gmgn-cli] ${request.method} ${request.subPath} hit rate limit, retrying once in ${Math.ceil(retryDelayMs / 1000)}s`
|
||||
);
|
||||
}
|
||||
await sleep(retryDelayMs);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Unexpected retry loop exit");
|
||||
}
|
||||
|
||||
private async doFetch(
|
||||
@@ -210,7 +616,17 @@ export class OpenApiClient {
|
||||
try {
|
||||
return await fetch(url, { method, headers, body: body ?? undefined });
|
||||
} catch (err: unknown) {
|
||||
const cause = err instanceof Error ? (err.cause ?? err) : err;
|
||||
const cause = extractRootCause(err);
|
||||
const errorCode = (cause as NodeJS.ErrnoException).code;
|
||||
|
||||
// Detect IPv4 unavailability errors
|
||||
if (errorCode === "EADDRNOTAVAIL" || errorCode === "ENETUNREACH") {
|
||||
throw new Error(
|
||||
`Network unreachable (${errorCode}): Your system may not support IPv4. ` +
|
||||
`Please check your network configuration or contact support.`
|
||||
);
|
||||
}
|
||||
|
||||
if (process.env.GMGN_DEBUG) console.error(`${curlStr}\n[error] fetch failed: ${cause}`);
|
||||
throw new Error(`${method} ${subPath} fetch failed: ${cause}`);
|
||||
}
|
||||
@@ -229,6 +645,8 @@ export class OpenApiClient {
|
||||
throw new Error(msg);
|
||||
};
|
||||
|
||||
const resetAtUnix = parseRateLimitReset(res.headers.get("x-ratelimit-reset"));
|
||||
|
||||
let text!: string;
|
||||
try {
|
||||
text = await res.text();
|
||||
@@ -236,7 +654,7 @@ export class OpenApiClient {
|
||||
fail(`${method} ${path} failed: HTTP ${res.status} (failed to read response body: ${err})`);
|
||||
}
|
||||
|
||||
let json!: { code: number | string; data?: unknown; message?: string; error?: string };
|
||||
let json!: ResponseEnvelope;
|
||||
try {
|
||||
json = JSON.parse(text);
|
||||
} catch {
|
||||
@@ -244,16 +662,116 @@ export class OpenApiClient {
|
||||
}
|
||||
|
||||
if (json.code !== 0) {
|
||||
fail(
|
||||
`${method} ${path} failed: HTTP ${res.status} code=${json.code} error=${json.error ?? ""} message=${json.message ?? ""}`,
|
||||
text
|
||||
);
|
||||
if (process.env.GMGN_DEBUG) {
|
||||
console.error(`${curlStr}\n${formatResponse(res, text)}`);
|
||||
}
|
||||
throw new OpenApiError({
|
||||
method,
|
||||
path,
|
||||
status: res.status,
|
||||
apiCode: json.code,
|
||||
apiError: json.error,
|
||||
apiMessage: json.message,
|
||||
resetAtUnix,
|
||||
});
|
||||
}
|
||||
|
||||
return json.data;
|
||||
}
|
||||
}
|
||||
|
||||
function getRateLimitRetryDelayMs(
|
||||
err: unknown,
|
||||
attempt: number,
|
||||
maxAttempts: number,
|
||||
autoRetryOnRateLimit: boolean
|
||||
): number | null {
|
||||
if (!autoRetryOnRateLimit || attempt >= maxAttempts) {
|
||||
return null;
|
||||
}
|
||||
if (!(err instanceof OpenApiError)) {
|
||||
return null;
|
||||
}
|
||||
if (err.apiError !== "RATE_LIMIT_EXCEEDED" && err.apiError !== "RATE_LIMIT_BANNED") {
|
||||
return null;
|
||||
}
|
||||
if (err.resetAtUnix == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const waitMs = Math.max(err.resetAtUnix * 1000 - Date.now(), 0) + RATE_LIMIT_RETRY_BUFFER_MS;
|
||||
return waitMs <= getAutoRetryMaxWaitMs() ? waitMs : null;
|
||||
}
|
||||
|
||||
function parseRateLimitReset(raw: string | null): number | undefined {
|
||||
if (raw == null || raw.trim() === "") {
|
||||
return undefined;
|
||||
}
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
||||
}
|
||||
|
||||
function getAutoRetryMaxWaitMs(): number {
|
||||
const raw = process.env.GMGN_RATE_LIMIT_AUTO_RETRY_MAX_WAIT_MS;
|
||||
if (!raw) {
|
||||
return DEFAULT_RATE_LIMIT_AUTO_RETRY_MAX_WAIT_MS;
|
||||
}
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_RATE_LIMIT_AUTO_RETRY_MAX_WAIT_MS;
|
||||
}
|
||||
|
||||
function buildOpenApiErrorMessage(params: OpenApiErrorParams): string {
|
||||
const parts = [`${params.method} ${params.path} failed: HTTP ${params.status}`];
|
||||
if (params.apiCode != null) parts.push(`code=${params.apiCode}`);
|
||||
if (params.apiError) parts.push(`error=${params.apiError}`);
|
||||
if (params.apiMessage) parts.push(`message=${params.apiMessage}`);
|
||||
|
||||
let message = parts.join(" ");
|
||||
|
||||
if (params.status !== 429) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const resetText = params.resetAtUnix != null
|
||||
? formatRateLimitReset(params.resetAtUnix)
|
||||
: "an unknown time";
|
||||
|
||||
if (params.apiError === "ERROR_RATE_LIMIT_BLOCKED") {
|
||||
return `${message}. Repeated business errors triggered a temporary block until ${resetText}. Fix the underlying request before retrying.`;
|
||||
}
|
||||
|
||||
if (params.apiError === "RATE_LIMIT_EXCEEDED" || params.apiError === "RATE_LIMIT_BANNED") {
|
||||
return `${message}. Rate limit resets at ${resetText}. Stop sending requests before then; repeated requests can extend the ban by 5s up to 5 minutes.`;
|
||||
}
|
||||
|
||||
return `${message}. Received HTTP 429; retry after ${resetText}.`;
|
||||
}
|
||||
|
||||
function formatRateLimitReset(resetAtUnix: number): string {
|
||||
const resetAt = new Date(resetAtUnix * 1000);
|
||||
const remainingSeconds = Math.max(Math.ceil((resetAt.getTime() - Date.now()) / 1000), 0);
|
||||
return `${formatLocalTimestamp(resetAt)} (~${remainingSeconds}s remaining)`;
|
||||
}
|
||||
|
||||
function formatLocalTimestamp(date: Date): string {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||||
const offsetMinutes = -date.getTimezoneOffset();
|
||||
const sign = offsetMinutes >= 0 ? "+" : "-";
|
||||
const absOffsetMinutes = Math.abs(offsetMinutes);
|
||||
const offsetHours = String(Math.floor(absOffsetMinutes / 60)).padStart(2, "0");
|
||||
const offsetMins = String(absOffsetMinutes % 60).padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds} GMT${sign}${offsetHours}:${offsetMins}`;
|
||||
}
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function formatResponse(res: Response, body: string | null): string {
|
||||
const headerLines = [...res.headers.entries()].map(([k, v]) => ` ${k}: ${v}`).join("\n");
|
||||
return `[response] HTTP ${res.status}\n${headerLines}\n\n${body ?? "(no body)"}`;
|
||||
@@ -269,6 +787,50 @@ function formatCurl(method: string, url: string, headers: Record<string, string>
|
||||
return `\n[curl]\ncurl -X ${method} '${url}' \\\n${headerArgs}${bodyArg}\n`;
|
||||
}
|
||||
|
||||
const TRENCHES_PLATFORMS: Record<string, string[]> = {
|
||||
sol: [
|
||||
"Pump.fun", "pump_mayhem", "pump_mayhem_agent", "pump_agent",
|
||||
"letsbonk", "bonkers", "bags", "memoo", "liquid", "bankr", "zora",
|
||||
"surge", "anoncoin", "moonshot_app", "wendotdev", "heaven", "sugar",
|
||||
"token_mill", "believe", "trendsfun", "trends_fun", "jup_studio",
|
||||
"Moonshot", "boop", "ray_launchpad", "meteora_virtual_curve", "xstocks",
|
||||
],
|
||||
bsc: [
|
||||
"fourmeme", "fourmeme_agent", "bn_fourmeme", "four_xmode_agent",
|
||||
"flap", "clanker", "lunafun",
|
||||
],
|
||||
base: [
|
||||
"clanker", "bankr", "flaunch", "zora", "zora_creator",
|
||||
"baseapp", "basememe", "virtuals_v2", "klik",
|
||||
],
|
||||
};
|
||||
|
||||
const TRENCHES_QUOTE_ADDRESS_TYPES: Record<string, number[]> = {
|
||||
sol: [4, 5, 3, 1, 13, 0],
|
||||
bsc: [6, 7, 1, 16, 8, 3, 9, 10, 2, 17, 18, 0],
|
||||
base: [11, 3, 12, 13, 0],
|
||||
};
|
||||
|
||||
function buildTrenchesBody(chain: string, types?: string[], platforms?: string[], limit?: number, filters?: Record<string, number | string>): Record<string, unknown> {
|
||||
const selectedTypes = types?.length ? types : ["new_creation", "near_completion", "completed"];
|
||||
const launchpad_platform = platforms?.length ? platforms : (TRENCHES_PLATFORMS[chain] ?? []);
|
||||
const quote_address_type = TRENCHES_QUOTE_ADDRESS_TYPES[chain] ?? [];
|
||||
const actualLimit = limit ?? 80;
|
||||
const section: Record<string, unknown> = {
|
||||
filters: ["offchain", "onchain"],
|
||||
launchpad_platform,
|
||||
quote_address_type,
|
||||
launchpad_platform_v2: true,
|
||||
limit: actualLimit,
|
||||
...filters,
|
||||
};
|
||||
const body: Record<string, unknown> = { version: "v2" };
|
||||
for (const type of selectedTypes) {
|
||||
body[type] = { ...section };
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
function buildUrl(base: string, query: Record<string, string | number | string[]>): string {
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of Object.entries(query)) {
|
||||
@@ -280,3 +842,11 @@ function buildUrl(base: string, query: Record<string, string | number | string[]
|
||||
}
|
||||
return `${base}?${params.toString()}`;
|
||||
}
|
||||
|
||||
// Recursively extract the root cause from nested Error.cause chain
|
||||
function extractRootCause(err: unknown): unknown {
|
||||
if (err instanceof Error && err.cause) {
|
||||
return extractRootCause(err.cause);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -30,19 +30,27 @@ export function buildAuthQuery(): { timestamp: number; client_id: string } {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the signature message (critical auth)
|
||||
* Build the signature message (signed auth)
|
||||
* Format: {sub_path}:{sorted_query_string}:{request_body}:{timestamp}
|
||||
* sorted_query_string: all query params (including timestamp, client_id) sorted alphabetically by key
|
||||
* sorted_query_string: all query params (including timestamp, client_id) sorted alphabetically by key.
|
||||
* Array values are serialized as repeated k=v pairs (same as buildUrl / URLSearchParams), sorted by value.
|
||||
*/
|
||||
export function buildMessage(
|
||||
subPath: string,
|
||||
queryParams: Record<string, string | number>,
|
||||
queryParams: Record<string, string | number | string[]>,
|
||||
body: string,
|
||||
timestamp: number
|
||||
): string {
|
||||
const sortedQs = Object.keys(queryParams)
|
||||
.sort()
|
||||
.map((k) => `${k}=${queryParams[k]}`)
|
||||
.flatMap((k) => {
|
||||
const ek = encodeURIComponent(k);
|
||||
const v = queryParams[k];
|
||||
if (Array.isArray(v)) {
|
||||
return [...v].sort().map((item) => `${ek}=${encodeURIComponent(item)}`);
|
||||
}
|
||||
return [`${ek}=${encodeURIComponent(String(v))}`];
|
||||
})
|
||||
.join("&");
|
||||
return `${subPath}:${sortedQs}:${body}:${timestamp}`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
import { Command } from "commander";
|
||||
import { OpenApiClient, CreateTokenParams } from "../client/OpenApiClient.js";
|
||||
import { getConfig } from "../config.js";
|
||||
import { exitOnError, printResult } from "../output.js";
|
||||
import { validateChain } from "../validate.js";
|
||||
|
||||
export function registerCookingCommands(program: Command): void {
|
||||
const cooking = program.command("cooking").description("Token creation and launchpad commands");
|
||||
|
||||
cooking
|
||||
.command("stats")
|
||||
.description("Get token creation statistics by launchpad (exist auth)")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getCookingStatistics().catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
cooking
|
||||
.command("create")
|
||||
.description("Create a token on a launchpad platform (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--dex <dex>", "Launchpad: pump / bonk / bags (sol) / fourmeme / flap (bsc) / klik / clanker (base)")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--name <name>", "Token name")
|
||||
.requiredOption("--symbol <symbol>", "Token symbol")
|
||||
.requiredOption("--buy-amt <amount>", "Initial buy amount in native token (e.g. 0.01 SOL)")
|
||||
.option("--image <base64>", "Token logo as base64-encoded data (max 2MB decoded)")
|
||||
.option("--image-url <url>", "Token logo URL")
|
||||
.option("--description <text>", "Token description / project pitch")
|
||||
.option("--website <url>", "Website URL")
|
||||
.option("--twitter <url>", "Twitter link")
|
||||
.option("--telegram <url>", "Telegram link")
|
||||
.option("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--auto-slippage", "Enable automatic slippage")
|
||||
.option("--fee <amount>", "Base gas / fee")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (SOL only)")
|
||||
.option("--tip-fee <amount>", "Tip fee")
|
||||
.option("--gas-price <amount>", "Gas price in wei (EVM chains)")
|
||||
.option("--max-fee-per-gas <amount>", "Max fee per gas in wei (EVM only)")
|
||||
.option("--max-priority-fee-per-gas <amount>", "Max priority fee per gas in wei (EVM only)")
|
||||
.option("--anti-mev", "Enable anti-MEV protection (SOL only)")
|
||||
.option("--anti-mev-mode <mode>", "Anti-MEV mode: off / normal / secure (SOL only)")
|
||||
.option("--raised-token <symbol>", "Raise token symbol: pump→USDC; bonk→USD1; fourmeme→USDT/USD1; leave empty for native")
|
||||
.option("--dev-wallet-bps <n>", "Dev wallet fee in basis points (100 = 1%)", parseInt)
|
||||
.option("--dev-gas <amount>", "Dev gas amount")
|
||||
.option("--dev-priority <amount>", "Dev priority fee")
|
||||
.option("--dev-tip <amount>", "Dev tip fee")
|
||||
.option("--dev-max-fee-per-gas <amount>", "Dev tx feeCap in wei (EVM EIP-1559)")
|
||||
.option("--approve-vision <version>", "Approve vision version: v1 / v2 (default: v2)")
|
||||
.option("--source <source>", "Traffic source identifier")
|
||||
// Pump.fun specific
|
||||
.option("--is-mayhem", "Enable Mayhem mode (Pump.fun only)")
|
||||
.option("--is-cashback", "Enable Cashback (Pump.fun only)")
|
||||
.option("--is-buy-back", "Enable Agent Auto Buyback (Pump.fun only)")
|
||||
.option("--pump-fee-share-list <json>", "Pump.fun fee share list as JSON array (Pump.fun only)")
|
||||
// Flap specific
|
||||
.option("--flap-rate-conf <json>", "Flap rate config as JSON object (Flap only)")
|
||||
// FourMeme specific
|
||||
.option("--fourmeme-rate-conf <json>", "FourMeme rate config as JSON object (FourMeme only)")
|
||||
// BAGS specific
|
||||
.option("--bags-fee-share-list <json>", "BAGS fee share list as JSON array (BAGS only)")
|
||||
// Bonk specific
|
||||
.option("--bonk-model <model>", "Bonk model identifier (bonk DEX only)")
|
||||
// Multi-wallet buy
|
||||
.option("--buy-wallets <json>", "Multi-wallet buy config as JSON array [{from_address, buy_amt}]")
|
||||
.option("--snip-buy-wallets <json>", "Snipe-buy wallet config as JSON array [{from_address, buy_amt}]")
|
||||
.option("--interval-seconds <n>", "Interval between multi-wallet buys in seconds", parseInt)
|
||||
// CondMarket execution config + auto-sell (JSON)
|
||||
.option("--buy-trade-config <json>", "Buy-side trade config for CondMarket orders as JSON (TradeParam)")
|
||||
.option("--sell-trade-config <json>", "Sell-side trade config for auto-sell / pending_sell as JSON (TradeParam)")
|
||||
.option("--sell-configs <json>", "Auto-sell strategy list as JSON array (CookingSellConfig[])")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (!opts.image && !opts.imageUrl) {
|
||||
console.error("[gmgn-cli] Either --image or --image-url must be provided");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!opts.slippage && !opts.autoSlippage) {
|
||||
console.error("[gmgn-cli] Either --slippage or --auto-slippage must be provided");
|
||||
process.exit(1);
|
||||
}
|
||||
validateChain(opts.chain);
|
||||
const params: CreateTokenParams = {
|
||||
chain: opts.chain,
|
||||
dex: opts.dex,
|
||||
from_address: opts.from,
|
||||
name: opts.name,
|
||||
symbol: opts.symbol,
|
||||
buy_amt: opts.buyAmt,
|
||||
};
|
||||
if (opts.image) params.image = opts.image;
|
||||
if (opts.imageUrl) params.image_url = opts.imageUrl;
|
||||
if (opts.description) params.description = opts.description;
|
||||
if (opts.website) params.website = opts.website;
|
||||
if (opts.twitter) params.twitter = opts.twitter;
|
||||
if (opts.telegram) params.telegram = opts.telegram;
|
||||
if (opts.slippage != null) params.slippage = opts.slippage;
|
||||
if (opts.autoSlippage) params.auto_slippage = true;
|
||||
if (opts.fee) params.fee = opts.fee;
|
||||
if (opts.priorityFee) params.priority_fee = opts.priorityFee;
|
||||
if (opts.tipFee) params.tip_fee = opts.tipFee;
|
||||
if (opts.gasPrice) params.gas_price = opts.gasPrice;
|
||||
if (opts.maxFeePerGas) params.max_fee_per_gas = opts.maxFeePerGas;
|
||||
if (opts.maxPriorityFeePerGas) params.max_priority_fee_per_gas = opts.maxPriorityFeePerGas;
|
||||
if (opts.antiMev) params.is_anti_mev = true;
|
||||
if (opts.antiMevMode) params.anti_mev_mode = opts.antiMevMode;
|
||||
if (opts.raisedToken != null) params.raised_token = opts.raisedToken;
|
||||
if (opts.devWalletBps != null) params.dev_wallet_bps = opts.devWalletBps;
|
||||
if (opts.devGas) params.dev_gas = opts.devGas;
|
||||
if (opts.devPriority) params.dev_priority = opts.devPriority;
|
||||
if (opts.devTip) params.dev_tip = opts.devTip;
|
||||
if (opts.devMaxFeePerGas) params.dev_max_fee_per_gas = opts.devMaxFeePerGas;
|
||||
if (opts.approveVision) params.approve_vision = opts.approveVision;
|
||||
if (opts.source) params.source = opts.source;
|
||||
if (opts.isMayhem) params.is_mayhem = true;
|
||||
if (opts.isCashback) params.is_cashback = true;
|
||||
if (opts.isBuyBack) params.is_buy_back = true;
|
||||
if (opts.pumpFeeShareList) params.pump_fee_share_list = JSON.parse(opts.pumpFeeShareList);
|
||||
if (opts.flapRateConf) params.flap_rate_conf = JSON.parse(opts.flapRateConf);
|
||||
if (opts.fourmemeRateConf) params.fourmeme_rate_conf = JSON.parse(opts.fourmemeRateConf);
|
||||
if (opts.bagsFeeShareList) params.bags_fee_share_list = JSON.parse(opts.bagsFeeShareList);
|
||||
if (opts.bonkModel) params.bonk_model = opts.bonkModel;
|
||||
if (opts.buyWallets) params.buy_wallets = JSON.parse(opts.buyWallets);
|
||||
if (opts.snipBuyWallets) params.snip_buy_wallets = JSON.parse(opts.snipBuyWallets);
|
||||
if (opts.intervalSeconds != null) params.interval_seconds = opts.intervalSeconds;
|
||||
if (opts.buyTradeConfig) params.buy_trade_config = JSON.parse(opts.buyTradeConfig);
|
||||
if (opts.sellTradeConfig) params.sell_trade_config = JSON.parse(opts.sellTradeConfig);
|
||||
if (opts.sellConfigs) params.sell_configs = JSON.parse(opts.sellConfigs);
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.createToken(params).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
@@ -1,27 +1,49 @@
|
||||
import { Command } from "commander";
|
||||
import { OpenApiClient } from "../client/OpenApiClient.js";
|
||||
import { OpenApiClient, TokenSignalGroup } from "../client/OpenApiClient.js";
|
||||
import { getConfig } from "../config.js";
|
||||
import { exitOnError, printResult } from "../output.js";
|
||||
import { validateAddress, validateChain } from "../validate.js";
|
||||
|
||||
// Parse token age string. If a unit suffix is present (s/m), use it as-is.
|
||||
// Bare numbers (no unit) are treated as minutes with a warning.
|
||||
function parseDuration(value: string): string {
|
||||
if (/^\d+(\.\d+)?[sm]$/.test(value)) return value;
|
||||
if (/^\d+(\.\d+)?$/.test(value)) {
|
||||
console.warn(
|
||||
`[gmgn-cli] Warning: no unit specified for duration "${value}" — treating as minutes (${value}m). Use a suffix to be explicit: ${value}s for seconds or ${value}m for minutes.`
|
||||
);
|
||||
return `${value}m`;
|
||||
}
|
||||
console.error(
|
||||
`[gmgn-cli] Invalid duration "${value}". Use seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m).`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
export function registerMarketCommands(program: Command): void {
|
||||
const market = program.command("market").description("Market data commands");
|
||||
|
||||
market
|
||||
.command("kline")
|
||||
.description("Get token K-line (candlestick) data")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.requiredOption("--resolution <resolution>", "Candlestick resolution: 1m / 5m / 15m / 1h / 4h / 1d")
|
||||
.requiredOption("--from <timestamp>", "Start time (Unix seconds)", parseInt)
|
||||
.requiredOption("--to <timestamp>", "End time (Unix seconds)", parseInt)
|
||||
.option("--from <timestamp>", "Start time (Unix seconds)", parseInt)
|
||||
.option("--to <timestamp>", "End time (Unix seconds)", parseInt)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.address, opts.chain, "--address");
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client
|
||||
.getTokenKline(opts.chain, opts.address, opts.resolution, opts.from * 1000, opts.to * 1000)
|
||||
.getTokenKline(
|
||||
opts.chain,
|
||||
opts.address,
|
||||
opts.resolution,
|
||||
opts.from != null ? opts.from * 1000 : undefined,
|
||||
opts.to != null ? opts.to * 1000 : undefined
|
||||
)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
@@ -29,8 +51,8 @@ export function registerMarketCommands(program: Command): void {
|
||||
market
|
||||
.command("trending")
|
||||
.description("Get trending token swap data")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--interval <interval>", "Time interval: 1h / 3h / 6h / 24h")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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)")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc")
|
||||
@@ -50,5 +72,259 @@ export function registerMarketCommands(program: Command): void {
|
||||
const data = await client.getTrendingSwaps(opts.chain, opts.interval, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const trenchesCmd = market
|
||||
.command("trenches")
|
||||
.description("Get Trenches token data (new creation, near completion, completed)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.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)
|
||||
.option("--filter-preset <preset>", "Apply a named filter preset: safe / smart-money / strict")
|
||||
.option("--sort-by <field>", "Client-side sort per category: smart_degen_count / renowned_count / volume_24h / volume_1h / swaps_24h / swaps_1h / rug_ratio / holder_count / usd_market_cap / created_timestamp")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc (default: desc; asc for rug_ratio)")
|
||||
.option("--raw", "Output raw JSON");
|
||||
|
||||
// Dynamically register all server-side filter flags
|
||||
for (const def of TRENCHES_FILTER_FIELDS) {
|
||||
const flag = def.api.replace(/_/g, '-');
|
||||
if (def.type === "int") {
|
||||
trenchesCmd.option(`--${flag} <${def.type}>`, def.desc, parseInt);
|
||||
} else if (def.type === "float") {
|
||||
trenchesCmd.option(`--${flag} <${def.type}>`, def.desc, parseFloat);
|
||||
} else if (def.type === "duration") {
|
||||
trenchesCmd.option(`--${flag} <duration>`, def.desc, parseDuration);
|
||||
} else {
|
||||
trenchesCmd.option(`--${flag} <value>`, def.desc);
|
||||
}
|
||||
}
|
||||
|
||||
trenchesCmd.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const client = new OpenApiClient(getConfig());
|
||||
|
||||
// Build server-side filter object
|
||||
const filters: Record<string, number | string> = {};
|
||||
|
||||
// Apply preset values first
|
||||
if (opts.filterPreset != null) {
|
||||
const preset = TRENCHES_FILTER_PRESETS[opts.filterPreset as string];
|
||||
if (!preset) {
|
||||
console.error(`Unknown --filter-preset "${opts.filterPreset}". Valid options: ${Object.keys(TRENCHES_FILTER_PRESETS).join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
Object.assign(filters, preset);
|
||||
}
|
||||
|
||||
// Apply individual filter flags (override preset values)
|
||||
const optsMap = opts as Record<string, unknown>;
|
||||
for (const def of TRENCHES_FILTER_FIELDS) {
|
||||
const key = apiFieldToCliKey(def.api);
|
||||
const val = optsMap[key];
|
||||
if (val != null) filters[def.api] = val as number | string;
|
||||
}
|
||||
|
||||
const data = await client
|
||||
.getTrenches(opts.chain, opts.type, opts.launchpadPlatform, opts.limit, Object.keys(filters).length ? filters : undefined)
|
||||
.catch(exitOnError);
|
||||
|
||||
const result = opts.sortBy
|
||||
? sortTrenchesResult(data as Record<string, unknown>, opts.sortBy as string, (opts.direction as string) ?? "")
|
||||
: data;
|
||||
printResult(result, opts.raw);
|
||||
});
|
||||
|
||||
market
|
||||
.command("signal")
|
||||
.description("Query token signals (price spikes, smart money buys, large buys, etc.) — max 50 results per group")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc")
|
||||
.option("--signal-type <n...>", "Signal type(s), repeatable: 1–18 (default: all types)", (v: string, acc: number[]) => { acc.push(parseInt(v, 10)); return acc; }, [] as number[])
|
||||
.option("--mc-min <usd>", "Min market cap at trigger time (USD)", parseFloat)
|
||||
.option("--mc-max <usd>", "Max market cap at trigger time (USD)", parseFloat)
|
||||
.option("--trigger-mc-min <usd>", "Min market cap at signal trigger (USD)", parseFloat)
|
||||
.option("--trigger-mc-max <usd>", "Max market cap at signal trigger (USD)", parseFloat)
|
||||
.option("--total-fee-min <usd>", "Min total fees paid (USD)", parseFloat)
|
||||
.option("--total-fee-max <usd>", "Max total fees paid (USD)", parseFloat)
|
||||
.option("--min-create-or-open-ts <ts>", "Min token creation or open timestamp (Unix seconds string)")
|
||||
.option("--max-create-or-open-ts <ts>", "Max token creation or open timestamp (Unix seconds string)")
|
||||
.option("--groups <json>", "Multi-group override: JSON array of group objects — overrides all individual flags when provided")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts: Record<string, unknown>) => {
|
||||
validateChain(opts["chain"] as string);
|
||||
if (!["sol", "bsc"].includes(opts["chain"] as string)) {
|
||||
console.error(`[gmgn-cli] market signal only supports sol and bsc, got "${opts["chain"]}"`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let groups: TokenSignalGroup[];
|
||||
if (opts["groups"] != null) {
|
||||
try {
|
||||
groups = JSON.parse(opts["groups"] as string) as TokenSignalGroup[];
|
||||
} catch {
|
||||
console.error(`[gmgn-cli] --groups must be a valid JSON array, e.g. '[{"signal_type":[12,14]},{"signal_type":[6,7],"mc_min":50000}]'`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
const group: TokenSignalGroup = {};
|
||||
const signalType = opts["signalType"] as number[] | undefined;
|
||||
if (signalType?.length) group.signal_type = signalType;
|
||||
if (opts["mcMin"] != null) group.mc_min = opts["mcMin"] as number;
|
||||
if (opts["mcMax"] != null) group.mc_max = opts["mcMax"] as number;
|
||||
if (opts["triggerMcMin"] != null) group.trigger_mc_min = opts["triggerMcMin"] as number;
|
||||
if (opts["triggerMcMax"] != null) group.trigger_mc_max = opts["triggerMcMax"] as number;
|
||||
if (opts["totalFeeMin"] != null) group.total_fee_min = opts["totalFeeMin"] as number;
|
||||
if (opts["totalFeeMax"] != null) group.total_fee_max = opts["totalFeeMax"] as number;
|
||||
if (opts["minCreateOrOpenTs"] != null) group.min_create_or_open_ts = opts["minCreateOrOpenTs"] as string;
|
||||
if (opts["maxCreateOrOpenTs"] != null) group.max_create_or_open_ts = opts["maxCreateOrOpenTs"] as string;
|
||||
groups = [group];
|
||||
}
|
||||
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getTokenSignalV2(opts["chain"] as string, groups).catch(exitOnError);
|
||||
printResult(data, opts["raw"] as boolean | undefined);
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Trenches filter field definitions ----
|
||||
|
||||
type TrenchesFieldType = "int" | "float" | "string" | "duration";
|
||||
|
||||
interface TrenchesFilterField {
|
||||
api: string;
|
||||
type: TrenchesFieldType;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
// All server-side filter fields for market trenches
|
||||
// API field names map to CLI flags by replacing _ with - (e.g. min_volume_24h → --min-volume-24h)
|
||||
const TRENCHES_FILTER_FIELDS: TrenchesFilterField[] = [
|
||||
// Trading activity (24h)
|
||||
{ api: "min_volume_24h", type: "float", desc: "Min 24h trading volume (USD)" },
|
||||
{ api: "max_volume_24h", type: "float", desc: "Max 24h trading volume (USD)" },
|
||||
{ api: "min_net_buy_24h", type: "float", desc: "Min 24h net buy volume (USD)" },
|
||||
{ api: "max_net_buy_24h", type: "float", desc: "Max 24h net buy volume (USD)" },
|
||||
{ api: "min_swaps_24h", type: "int", desc: "Min 24h total swap count" },
|
||||
{ api: "max_swaps_24h", type: "int", desc: "Max 24h total swap count" },
|
||||
{ api: "min_buys_24h", type: "int", desc: "Min 24h buy count" },
|
||||
{ api: "max_buys_24h", type: "int", desc: "Max 24h buy count" },
|
||||
{ api: "min_sells_24h", type: "int", desc: "Min 24h sell count" },
|
||||
{ api: "max_sells_24h", type: "int", desc: "Max 24h sell count" },
|
||||
{ api: "min_visiting_count", type: "int", desc: "Min visitor count" },
|
||||
{ api: "max_visiting_count", type: "int", desc: "Max visitor count" },
|
||||
// Market & liquidity
|
||||
{ api: "min_progress", type: "float", desc: "Min bonding curve progress (0–1)" },
|
||||
{ api: "max_progress", type: "float", desc: "Max bonding curve progress (0–1, 1 = completed)" },
|
||||
{ api: "min_marketcap", type: "float", desc: "Min market cap (USD)" },
|
||||
{ api: "max_marketcap", type: "float", desc: "Max market cap (USD)" },
|
||||
{ api: "min_liquidity", type: "float", desc: "Min liquidity (USD)" },
|
||||
{ api: "max_liquidity", type: "float", desc: "Max liquidity (USD)" },
|
||||
// Token age
|
||||
{ api: "min_created", type: "duration", desc: "Min token age — unit recommended: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m). Bare numbers treated as minutes." },
|
||||
{ api: "max_created", type: "duration", desc: "Max token age — unit recommended: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m). Bare numbers treated as minutes." },
|
||||
// Holders
|
||||
{ api: "min_holder_count", type: "int", desc: "Min holder count" },
|
||||
{ api: "max_holder_count", type: "int", desc: "Max holder count" },
|
||||
{ api: "min_top_holder_rate", type: "float", desc: "Min top-10 holder concentration (0–1)" },
|
||||
{ api: "max_top_holder_rate", type: "float", desc: "Max top-10 holder concentration (0–1)" },
|
||||
// Risk signals
|
||||
{ api: "min_rug_ratio", type: "float", desc: "Min rug pull risk score (0–1)" },
|
||||
{ api: "max_rug_ratio", type: "float", desc: "Max rug pull risk score (0–1, e.g. 0.3 to exclude rugs)" },
|
||||
{ api: "min_bundler_rate", type: "float", desc: "Min bundle-bot trading ratio (0–1)" },
|
||||
{ api: "max_bundler_rate", type: "float", desc: "Max bundle-bot trading ratio (0–1)" },
|
||||
{ api: "min_insider_ratio", type: "float", desc: "Min insider trading ratio (0–1)" },
|
||||
{ api: "max_insider_ratio", type: "float", desc: "Max insider trading ratio (0–1)" },
|
||||
{ api: "min_entrapment_ratio", type: "float", desc: "Min entrapment trading ratio (0–1)" },
|
||||
{ api: "max_entrapment_ratio", type: "float", desc: "Max entrapment trading ratio (0–1)" },
|
||||
{ api: "min_private_vault_hold_rate", type: "float", desc: "Min private vault holding ratio (0–1)" },
|
||||
{ api: "max_private_vault_hold_rate", type: "float", desc: "Max private vault holding ratio (0–1)" },
|
||||
{ api: "min_top70_sniper_hold_rate", type: "float", desc: "Min top-70 sniper holding ratio (0–1)" },
|
||||
{ api: "max_top70_sniper_hold_rate", type: "float", desc: "Max top-70 sniper holding ratio (0–1)" },
|
||||
{ api: "min_bot_count", type: "int", desc: "Min bot wallet count" },
|
||||
{ api: "max_bot_count", type: "int", desc: "Max bot wallet count" },
|
||||
{ api: "min_bot_degen_rate", type: "float", desc: "Min bot-degen wallet ratio (0–1)" },
|
||||
{ api: "max_bot_degen_rate", type: "float", desc: "Max bot-degen wallet ratio (0–1)" },
|
||||
{ api: "min_fresh_wallet_rate", type: "float", desc: "Min fresh wallet ratio (0–1)" },
|
||||
{ api: "max_fresh_wallet_rate", type: "float", desc: "Max fresh wallet ratio (0–1)" },
|
||||
{ api: "min_total_fee", type: "float", desc: "Min total fee" },
|
||||
{ api: "max_total_fee", type: "float", desc: "Max total fee" },
|
||||
// Smart money
|
||||
{ api: "min_smart_degen_count", type: "int", desc: "Min smart-money holder count" },
|
||||
{ api: "max_smart_degen_count", type: "int", desc: "Max smart-money holder count" },
|
||||
{ api: "min_renowned_count", type: "int", desc: "Min KOL / renowned wallet count" },
|
||||
{ api: "max_renowned_count", type: "int", desc: "Max KOL / renowned wallet count" },
|
||||
// Dev / creator
|
||||
{ api: "min_creator_balance_rate", type: "float", desc: "Min creator holding ratio (0–1)" },
|
||||
{ api: "max_creator_balance_rate", type: "float", desc: "Max creator holding ratio (0–1)" },
|
||||
{ api: "min_creator_created_count", type: "int", desc: "Min creator total token creation count" },
|
||||
{ api: "max_creator_created_count", type: "int", desc: "Max creator total token creation count" },
|
||||
{ api: "min_creator_created_open_count", type: "int", desc: "Min creator graduated token count" },
|
||||
{ api: "max_creator_created_open_count", type: "int", desc: "Max creator graduated token count" },
|
||||
{ api: "min_creator_created_open_ratio", type: "float", desc: "Min creator graduation ratio (0–1)" },
|
||||
{ api: "max_creator_created_open_ratio", type: "float", desc: "Max creator graduation ratio (0–1)" },
|
||||
// Social
|
||||
{ api: "min_x_follower", type: "int", desc: "Min Twitter / X follower count" },
|
||||
{ api: "max_x_follower", type: "int", desc: "Max Twitter / X follower count" },
|
||||
{ api: "min_twitter_rename_count", type: "int", desc: "Min Twitter rename count (high = suspicious)" },
|
||||
{ api: "max_twitter_rename_count", type: "int", desc: "Max Twitter rename count" },
|
||||
{ api: "min_tg_call_count", type: "int", desc: "Min Telegram call count" },
|
||||
{ api: "max_tg_call_count", type: "int", desc: "Max Telegram call count" },
|
||||
];
|
||||
|
||||
// Named filter presets using actual server-side API field names
|
||||
const TRENCHES_FILTER_PRESETS: Record<string, Record<string, number | string>> = {
|
||||
safe: {
|
||||
max_rug_ratio: 0.3,
|
||||
max_bundler_rate: 0.3,
|
||||
max_insider_ratio: 0.3,
|
||||
},
|
||||
"smart-money": {
|
||||
min_smart_degen_count: 1,
|
||||
},
|
||||
strict: {
|
||||
max_rug_ratio: 0.3,
|
||||
max_bundler_rate: 0.3,
|
||||
max_insider_ratio: 0.3,
|
||||
min_smart_degen_count: 1,
|
||||
min_volume_24h: 1000,
|
||||
},
|
||||
};
|
||||
|
||||
// Convert API snake_case field to Commander.js opts key
|
||||
// Commander.js camelCase: converts -[a-z] to uppercase, and removes hyphen before digits
|
||||
// e.g. min_volume_24h → min-volume-24h → minVolume-24h → minVolume24h
|
||||
// e.g. min_smart_degen_count → min-smart-degen-count → minSmartDegenCount
|
||||
function apiFieldToCliKey(apiField: string): string {
|
||||
return apiField
|
||||
.replace(/_/g, '-')
|
||||
.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())
|
||||
.replace(/-(\d)/g, '$1');
|
||||
}
|
||||
|
||||
// Client-side sort helpers (API does not support server-side sort for trenches)
|
||||
interface TrenchesCategory {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
const TRENCHES_SORT_ASC_DEFAULTS = new Set(["rug_ratio"]);
|
||||
const TRENCHES_STRING_NUMERIC_FIELDS = new Set(["usd_market_cap", "liquidity", "volume_1h", "volume_24h"]);
|
||||
|
||||
function sortTrenchesCategory(items: TrenchesCategory[], sortBy: string, direction: string): TrenchesCategory[] {
|
||||
const dir = direction || (TRENCHES_SORT_ASC_DEFAULTS.has(sortBy) ? "asc" : "desc");
|
||||
return [...items].sort((a, b) => {
|
||||
const aVal = TRENCHES_STRING_NUMERIC_FIELDS.has(sortBy)
|
||||
? parseFloat(String(a[sortBy] ?? 0))
|
||||
: Number(a[sortBy] ?? 0);
|
||||
const bVal = TRENCHES_STRING_NUMERIC_FIELDS.has(sortBy)
|
||||
? parseFloat(String(b[sortBy] ?? 0))
|
||||
: Number(b[sortBy] ?? 0);
|
||||
return dir === "asc" ? aVal - bVal : bVal - aVal;
|
||||
});
|
||||
}
|
||||
|
||||
function sortTrenchesResult(data: Record<string, unknown>, sortBy: string, direction: string): Record<string, unknown> {
|
||||
const result: Record<string, unknown> = {};
|
||||
for (const [key, val] of Object.entries(data)) {
|
||||
result[key] = Array.isArray(val) ? sortTrenchesCategory(val as TrenchesCategory[], sortBy, direction) : val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -10,18 +10,16 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("holdings")
|
||||
.description("Get wallet token holdings")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--limit <n>", "Page size (default 20, max 50)", parseInt, 20)
|
||||
.option("--cursor <cursor>", "Pagination cursor")
|
||||
.option("--order-by <field>", "Sort field: usd_value / last_active_timestamp / realized_profit / unrealized_profit / total_profit / history_bought_cost / history_sold_income", "usd_value")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc", "desc")
|
||||
.option("--interval <interval>", "Stats interval (default 24h)")
|
||||
.option("--sell-out", "Include sold-out positions")
|
||||
.option("--show-small", "Include small-value positions")
|
||||
.option("--hide-abnormal", "Hide abnormal positions")
|
||||
.option("--hide-airdrop", "Hide airdrop positions")
|
||||
.option("--hide-closed", "Hide closed positions")
|
||||
.option("--hide-abnormal <bool>", "Hide abnormal positions (default: false)", "false")
|
||||
.option("--hide-airdrop <bool>", "Hide airdrop positions (default: true)", "true")
|
||||
.option("--hide-closed <bool>", "Hide closed positions (default: true)", "true")
|
||||
.option("--hide-open", "Hide open positions")
|
||||
.option("--tx30d", "Only show positions with trades in last 30 days")
|
||||
.option("--raw", "Output raw JSON")
|
||||
@@ -34,11 +32,9 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
if (opts.orderBy) extra["order_by"] = opts.orderBy;
|
||||
if (opts.direction) extra["direction"] = opts.direction;
|
||||
if (opts.interval) extra["interval"] = opts.interval;
|
||||
if (opts.sellOut) extra["sell_out"] = "true";
|
||||
if (opts.showSmall) extra["show_small"] = "true";
|
||||
if (opts.hideAbnormal) extra["hide_abnormal"] = "true";
|
||||
if (opts.hideAirdrop) extra["hide_airdrop"] = "true";
|
||||
if (opts.hideClosed) extra["hide_closed"] = "true";
|
||||
extra["hide_abnormal"] = opts.hideAbnormal;
|
||||
extra["hide_airdrop"] = opts.hideAirdrop;
|
||||
extra["hide_closed"] = opts.hideClosed;
|
||||
if (opts.hideOpen) extra["hide_open"] = "true";
|
||||
if (opts.tx30d) extra["tx30d"] = "true";
|
||||
|
||||
@@ -50,19 +46,19 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
portfolio
|
||||
.command("activity")
|
||||
.description("Get wallet transaction activity")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.option("--token <address>", "Filter by token contract address")
|
||||
.option("--limit <n>", "Page size", parseInt)
|
||||
.option("--cursor <cursor>", "Pagination cursor")
|
||||
.option("--type <type...>", "Activity type filter, repeatable: buy / sell / add / remove / transfer")
|
||||
.option("--type <type...>", "Activity type filter, repeatable: buy / sell / transferIn / transferOut / add / remove")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.wallet, opts.chain, "--wallet");
|
||||
if (opts.token) validateAddress(opts.token, opts.chain, "--token");
|
||||
const extra: Record<string, string | number | string[]> = {};
|
||||
if (opts.token) extra["token"] = opts.token;
|
||||
if (opts.token) extra["token_address"] = opts.token;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
if (opts.cursor) extra["cursor"] = opts.cursor;
|
||||
if (opts.type?.length) extra["type"] = opts.type;
|
||||
@@ -75,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")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--wallet <address...>", "Wallet address(es), repeatable")
|
||||
.option("--period <period>", "Stats period: 7d / 30d", "7d")
|
||||
.option("--raw", "Output raw JSON")
|
||||
@@ -100,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")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--wallet <address>", "Wallet address")
|
||||
.requiredOption("--token <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
@@ -112,5 +108,27 @@ export function registerPortfolioCommands(program: Command): void {
|
||||
const data = await client.getWalletTokenBalance(opts.chain, opts.wallet, opts.token).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
portfolio
|
||||
.command("created-tokens")
|
||||
.description("Get tokens created by a developer wallet")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--wallet <address>", "Developer wallet address")
|
||||
.option("--order-by <field>", "Sort field: market_cap / token_ath_mc")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc")
|
||||
.option("--migrate-state <state>", "Filter: migrated / non_migrated")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.wallet, opts.chain, "--wallet");
|
||||
const extra: Record<string, string | number> = {};
|
||||
if (opts.orderBy) extra["order_by"] = opts.orderBy;
|
||||
if (opts.direction) extra["direction"] = opts.direction;
|
||||
if (opts.migrateState) extra["migrate_state"] = opts.migrateState;
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getCreatedTokens(opts.chain, opts.wallet, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Command } from "commander";
|
||||
import { OpenApiClient, SwapParams } from "../client/OpenApiClient.js";
|
||||
import { OpenApiClient, SwapParams, MultiSwapParams, StrategyCreateParams, StrategyCancelParams } from "../client/OpenApiClient.js";
|
||||
import { getConfig } from "../config.js";
|
||||
import { exitOnError, printResult } from "../output.js";
|
||||
import { validateAddress, validateChain, validatePercent, validatePositiveInt } from "../validate.js";
|
||||
@@ -8,21 +8,25 @@ 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")
|
||||
.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")
|
||||
.option("--amount <amount>", "Input raw amount (smallest unit)")
|
||||
.option("--percent <pct>", "Input amount as a percentage, e.g. 50 = 50%, 1 = 1%; only valid when input_token is NOT a currency", parseFloat)
|
||||
.option("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--auto-slippage", "Enable automatic slippage")
|
||||
.option("--min-output <amount>", "Minimum output amount")
|
||||
.option("--anti-mev", "Enable anti-MEV protection, default true")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (≥ 0.00001, SOL only)")
|
||||
.option("--tip-fee <amount>", "Tip fee (SOL ≥ 0.00001 SOL / BSC ≥ 0.000001 BNB)")
|
||||
.option("--max-auto-fee <amount>", "Max auto fee cap")
|
||||
.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("--gas-price <gwei>", "Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01); mutually exclusive with --gas-level")
|
||||
.option("--gas-level <level>", "Gas price tier (eth only): low / average / high; mutually exclusive with --gas-price")
|
||||
.option("--auto-fee", "Auto fee mode (eth only); delegates fee selection to trading bot for condition_orders strategy")
|
||||
.option("--max-fee-per-gas <amount>", "EIP-1559 max fee per gas (BSC / BASE / ETH)")
|
||||
.option("--max-priority-fee-per-gas <amount>", "EIP-1559 max priority fee per gas (BSC / BASE / ETH)")
|
||||
.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) => {
|
||||
if (opts.percent == null && !opts.amount) {
|
||||
@@ -37,29 +41,135 @@ export function registerSwapCommands(program: Command): void {
|
||||
if (opts.percent != null) validatePercent(opts.percent);
|
||||
const params: SwapParams = {
|
||||
chain: opts.chain,
|
||||
from_address: opts.from,
|
||||
from_address: opts.chain === "sol" ? opts.from : opts.from.toLowerCase(),
|
||||
input_token: opts.inputToken,
|
||||
output_token: opts.outputToken,
|
||||
input_amount: opts.percent != null ? (opts.amount ?? "0") : opts.amount,
|
||||
};
|
||||
if (opts.percent != null) params.input_amount_bps = String(Math.round(opts.percent * 100));
|
||||
if (opts.slippage != null) params.slippage = opts.slippage;
|
||||
if (opts.autoSlippage) params.auto_slippage = true;
|
||||
if (opts.minOutput) params.min_output_amount = opts.minOutput;
|
||||
if (opts.antiMev) params.is_anti_mev = true;
|
||||
if (opts.priorityFee) params.priority_fee = opts.priorityFee;
|
||||
if (opts.tipFee) params.tip_fee = opts.tipFee;
|
||||
if (opts.maxAutoFee) params.max_auto_fee = opts.maxAutoFee;
|
||||
if (opts.autoFee) params.auto_fee = true;
|
||||
if (opts.gasPrice) params.gas_price = String(Math.round(parseFloat(opts.gasPrice) * 1e9));
|
||||
if (opts.gasLevel) params.gas_level = opts.gasLevel;
|
||||
if (opts.maxFeePerGas) params.max_fee_per_gas = opts.maxFeePerGas;
|
||||
if (opts.maxPriorityFeePerGas) params.max_priority_fee_per_gas = opts.maxPriorityFeePerGas;
|
||||
if (opts.conditionOrders) {
|
||||
try {
|
||||
params.condition_orders = JSON.parse(opts.conditionOrders);
|
||||
} catch {
|
||||
console.error("[gmgn-cli] --condition-orders must be valid JSON");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
if (opts.sellRatioType) params.sell_ratio_type = opts.sellRatioType;
|
||||
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.swap(params).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
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("--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")
|
||||
.option("--input-amount <json>", 'JSON map of wallet→amount (smallest unit), e.g. \'{"addr1":"1000000","addr2":"2000000"}\'')
|
||||
.option("--input-amount-bps <json>", 'JSON map of wallet→percent in bps (1–10000, e.g. 5000=50%), e.g. \'{"addr1":"5000"}\'')
|
||||
.option("--output-amount <json>", "JSON map of wallet→target output amount")
|
||||
.option("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--auto-slippage", "Enable automatic slippage")
|
||||
.option("--anti-mev", "Enable anti-MEV protection")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (SOL only, ≥ 0.00001)")
|
||||
.option("--tip-fee <amount>", "Tip fee (SOL ≥ 0.00001 / BSC ≥ 0.000001 BNB)")
|
||||
.option("--gas-price <gwei>", "Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01); mutually exclusive with --gas-level")
|
||||
.option("--gas-level <level>", "Gas price tier (eth only): low / average / high; mutually exclusive with --gas-price")
|
||||
.option("--auto-fee", "Auto fee mode (eth only); delegates fee selection to trading bot for condition_orders strategy")
|
||||
.option("--max-fee-per-gas <amount>", "EIP-1559 max fee per gas (BSC / BASE / ETH)")
|
||||
.option("--max-priority-fee-per-gas <amount>", "EIP-1559 max priority fee per gas (BSC / BASE / ETH)")
|
||||
.option("--condition-orders <json>", "JSON array of take-profit/stop-loss conditions attached to each successful wallet's swap")
|
||||
.option("--sell-ratio-type <type>", "Sell ratio base: buy_amount (default) / hold_amount; only used with --condition-orders")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (!opts.inputAmount && !opts.inputAmountBps && !opts.outputAmount) {
|
||||
console.error("[gmgn-cli] At least one of --input-amount, --input-amount-bps, or --output-amount must be provided");
|
||||
process.exit(1);
|
||||
}
|
||||
validateChain(opts.chain);
|
||||
const accounts = (opts.accounts as string).split(",").map((a: string) => a.trim()).filter(Boolean);
|
||||
if (accounts.length === 0 || accounts.length > 100) {
|
||||
console.error("[gmgn-cli] --accounts must be 1–100 comma-separated wallet addresses");
|
||||
process.exit(1);
|
||||
}
|
||||
const params: MultiSwapParams = {
|
||||
chain: opts.chain,
|
||||
accounts: opts.chain === "sol" ? accounts : accounts.map((a: string) => a.toLowerCase()),
|
||||
input_token: opts.inputToken,
|
||||
output_token: opts.outputToken,
|
||||
};
|
||||
if (opts.inputAmount) {
|
||||
try { params.input_amount = JSON.parse(opts.inputAmount); }
|
||||
catch { console.error("[gmgn-cli] --input-amount must be valid JSON"); process.exit(1); }
|
||||
}
|
||||
if (opts.inputAmountBps) {
|
||||
try { params.input_amount_bps = JSON.parse(opts.inputAmountBps); }
|
||||
catch { console.error("[gmgn-cli] --input-amount-bps must be valid JSON"); process.exit(1); }
|
||||
}
|
||||
if (opts.outputAmount) {
|
||||
try { params.output_amount = JSON.parse(opts.outputAmount); }
|
||||
catch { console.error("[gmgn-cli] --output-amount must be valid JSON"); process.exit(1); }
|
||||
}
|
||||
if (opts.slippage != null) params.slippage = opts.slippage;
|
||||
if (opts.autoSlippage) params.auto_slippage = true;
|
||||
if (opts.antiMev) params.is_anti_mev = true;
|
||||
if (opts.priorityFee) params.priority_fee = opts.priorityFee;
|
||||
if (opts.tipFee) params.tip_fee = opts.tipFee;
|
||||
if (opts.autoFee) params.auto_fee = true;
|
||||
if (opts.gasPrice) params.gas_price = String(Math.round(parseFloat(opts.gasPrice) * 1e9));
|
||||
if (opts.gasLevel) params.gas_level = opts.gasLevel;
|
||||
if (opts.maxFeePerGas) params.max_fee_per_gas = opts.maxFeePerGas;
|
||||
if (opts.maxPriorityFeePerGas) params.max_priority_fee_per_gas = opts.maxPriorityFeePerGas;
|
||||
if (opts.conditionOrders) {
|
||||
try { params.condition_orders = JSON.parse(opts.conditionOrders); }
|
||||
catch { console.error("[gmgn-cli] --condition-orders must be valid JSON"); process.exit(1); }
|
||||
}
|
||||
if (opts.sellRatioType) params.sell_ratio_type = opts.sellRatioType;
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.multiSwap(params).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const order = program.command("order").description("Order management commands");
|
||||
|
||||
order
|
||||
.command("quote")
|
||||
.description("Get a swap quote without submitting a transaction (signed auth — requires GMGN_PRIVATE_KEY)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth (requires GMGN_PRIVATE_KEY)")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--input-token <address>", "Input token contract address")
|
||||
.requiredOption("--output-token <address>", "Output token contract address")
|
||||
.requiredOption("--amount <amount>", "Input amount (smallest unit)")
|
||||
.requiredOption("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
validateAddress(opts.from, opts.chain, "--from");
|
||||
validateAddress(opts.inputToken, opts.chain, "--input-token");
|
||||
validateAddress(opts.outputToken, opts.chain, "--output-token");
|
||||
validatePositiveInt(opts.amount, "--amount");
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client
|
||||
.quoteOrder(opts.chain, opts.from, opts.inputToken, opts.outputToken, opts.amount, opts.slippage)
|
||||
.catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
order
|
||||
.command("get")
|
||||
.description("Query order status (requires private key)")
|
||||
@@ -72,5 +182,139 @@ export function registerSwapCommands(program: Command): void {
|
||||
const data = await client.queryOrder(opts.orderId, opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
|
||||
program
|
||||
.command("gas-price")
|
||||
.description("Query recommended gas price tiers for any chain (exist auth — API Key only; eth / bsc / base / sol)")
|
||||
.requiredOption("--chain <chain>", "Chain: eth / bsc / base / sol")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
const client = new OpenApiClient(getConfig(false));
|
||||
const data = await client.getGasPrice(opts.chain).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
const strategy = order.command("strategy").description("Limit/strategy order management");
|
||||
|
||||
strategy
|
||||
.command("create")
|
||||
.description("Create a limit/strategy order (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--base-token <address>", "Base token contract address")
|
||||
.requiredOption("--quote-token <address>", "Quote token contract address")
|
||||
.requiredOption("--order-type <type>", "Order type: limit_order / smart_trade")
|
||||
.requiredOption("--sub-order-type <type>", "Sub-order type: buy_low / buy_high / stop_loss / take_profit (limit_order); mix_trade (smart_trade with condition_orders)")
|
||||
.option("--check-price <price>", "Trigger check price (required for limit_order; omit for smart_trade)")
|
||||
.option("--open-price <price>", "Open price of the position")
|
||||
.option("--amount-in <amount>", "Input amount (smallest unit)")
|
||||
.option("--amount-in-percent <pct>", "Input amount as a percentage (e.g. 50 = 50%)")
|
||||
.option("--limit-price-mode <mode>", "Price mode: exact / slippage (default: slippage)")
|
||||
.option("--expire-in <seconds>", "Order expiry in seconds", parseInt)
|
||||
.option("--sell-ratio-type <type>", "Sell ratio basis: buy_amount (default) / hold_amount")
|
||||
.option("--quote-investment <amount>", "Quote token investment amount (smart_trade)")
|
||||
.option("--slippage <n>", "Slippage tolerance (e.g. 0.01 = 1%)", parseFloat)
|
||||
.option("--auto-slippage", "Enable automatic slippage")
|
||||
.option("--priority-fee <sol>", "Priority fee in SOL (required for SOL chain)")
|
||||
.option("--tip-fee <amount>", "Tip fee (required for SOL chain)")
|
||||
.option("--auto-fee", "Auto fee mode (eth only); delegates fee selection to trading bot")
|
||||
.option("--gas-price <gwei>", "Gas price in gwei (BSC ≥ 0.05 / BASE/ETH ≥ 0.01 gwei); mutually exclusive with --gas-level")
|
||||
.option("--gas-level <level>", "Gas price tier (eth only): low / average / high; mutually exclusive with --gas-price")
|
||||
.option("--max-fee-per-gas <amount>", "EIP-1559 max fee per gas (BSC / BASE / ETH)")
|
||||
.option("--max-priority-fee-per-gas <amount>", "EIP-1559 max priority fee per gas (BSC / BASE / ETH)")
|
||||
.option("--anti-mev", "Enable anti-MEV protection")
|
||||
.option("--condition-orders <json>", "JSON array of condition sub-orders for smart_trade (must include a buy_low entry + TP/SL entries)")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (!opts.amountIn && !opts.amountInPercent) {
|
||||
console.error("[gmgn-cli] Either --amount-in or --amount-in-percent must be provided");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!opts.slippage && !opts.autoSlippage) {
|
||||
console.error("[gmgn-cli] Either --slippage or --auto-slippage must be provided");
|
||||
process.exit(1);
|
||||
}
|
||||
validateChain(opts.chain);
|
||||
const params: StrategyCreateParams = {
|
||||
chain: opts.chain,
|
||||
from_address: opts.from,
|
||||
base_token: opts.baseToken,
|
||||
quote_token: opts.quoteToken,
|
||||
order_type: opts.orderType,
|
||||
sub_order_type: opts.subOrderType,
|
||||
};
|
||||
if (opts.checkPrice) params.check_price = opts.checkPrice;
|
||||
if (opts.openPrice) params.open_price = opts.openPrice;
|
||||
if (opts.amountIn) params.amount_in = opts.amountIn;
|
||||
if (opts.amountInPercent) params.amount_in_percent = opts.amountInPercent;
|
||||
if (opts.limitPriceMode) params.limit_price_mode = opts.limitPriceMode;
|
||||
if (opts.expireIn != null) params.expire_in = opts.expireIn;
|
||||
if (opts.sellRatioType) params.sell_ratio_type = opts.sellRatioType;
|
||||
if (opts.quoteInvestment) params.quote_investment = opts.quoteInvestment;
|
||||
if (opts.slippage != null) params.slippage = opts.slippage;
|
||||
if (opts.autoSlippage) params.auto_slippage = true;
|
||||
if (opts.priorityFee) params.priority_fee = opts.priorityFee;
|
||||
if (opts.tipFee) params.tip_fee = opts.tipFee;
|
||||
if (opts.autoFee) params.auto_fee = true;
|
||||
if (opts.gasPrice) params.gas_price = String(Math.round(parseFloat(opts.gasPrice) * 1e9));
|
||||
if (opts.gasLevel) params.gas_level = opts.gasLevel;
|
||||
if (opts.maxFeePerGas) params.max_fee_per_gas = opts.maxFeePerGas;
|
||||
if (opts.maxPriorityFeePerGas) params.max_priority_fee_per_gas = opts.maxPriorityFeePerGas;
|
||||
if (opts.antiMev) params.is_anti_mev = true;
|
||||
if (opts.conditionOrders) {
|
||||
try { params.condition_orders = JSON.parse(opts.conditionOrders); }
|
||||
catch { console.error("[gmgn-cli] --condition-orders must be valid JSON"); process.exit(1); }
|
||||
}
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.createStrategyOrder(params).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
strategy
|
||||
.command("list")
|
||||
.description("List strategy orders (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.option("--type <type>", "open (default) / history")
|
||||
.option("--from <address>", "Filter by wallet address")
|
||||
.option("--group-tag <tag>", "Filter by group: LimitOrder / STMix")
|
||||
.option("--base-token <address>", "Filter by token address")
|
||||
.option("--page-token <token>", "Pagination cursor from previous response")
|
||||
.option("--limit <n>", "Results per page", parseInt)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const extra: Record<string, string | number> = {};
|
||||
if (opts.type) extra["type"] = opts.type;
|
||||
if (opts.from) extra["from_address"] = opts.from;
|
||||
if (opts.groupTag) extra["group_tag"] = opts.groupTag;
|
||||
if (opts.baseToken) extra["base_token"] = opts.baseToken;
|
||||
if (opts.pageToken) extra["page_token"] = opts.pageToken;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.getStrategyOrders(opts.chain, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
strategy
|
||||
.command("cancel")
|
||||
.description("Cancel a strategy order (requires private key)")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--from <address>", "Wallet address (must match API Key binding)")
|
||||
.requiredOption("--order-id <id>", "Order ID to cancel")
|
||||
.option("--order-type <type>", "Order type: limit_order / smart_trade")
|
||||
.option("--close-sell-model <model>", "Sell model when closing")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const params: StrategyCancelParams = {
|
||||
chain: opts.chain,
|
||||
from_address: opts.from,
|
||||
order_id: opts.orderId,
|
||||
};
|
||||
if (opts.orderType) params.order_type = opts.orderType;
|
||||
if (opts.closeSellModel) params.close_sell_model = opts.closeSellModel;
|
||||
const client = new OpenApiClient(getConfig(true));
|
||||
const data = await client.cancelStrategyOrder(params).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.requiredOption("--address <address>", "Token contract address")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
@@ -52,12 +52,12 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("holders")
|
||||
.description("Get top token holders")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc", "desc")
|
||||
.option("--tag <tag>", "Wallet tag filter: renowned / smart_degen", "renowned")
|
||||
.option("--tag <tag>", "Wallet tag filter: smart_degen / renowned / fresh_wallet / dev / sniper / rat_trader / bundler / transfer_in / dex_bot / bluechip_owner")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
@@ -75,12 +75,12 @@ export function registerTokenCommands(program: Command): void {
|
||||
token
|
||||
.command("traders")
|
||||
.description("Get top token traders")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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")
|
||||
.option("--direction <dir>", "Sort direction: asc / desc", "desc")
|
||||
.option("--tag <tag>", "Wallet tag filter: renowned / smart_degen", "renowned")
|
||||
.option("--tag <tag>", "Wallet tag filter: smart_degen / renowned / fresh_wallet / dev / sniper / rat_trader / bundler / transfer_in / dex_bot / bluechip_owner")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Command } from "commander";
|
||||
import { OpenApiClient } from "../client/OpenApiClient.js";
|
||||
import { getConfig } from "../config.js";
|
||||
import { exitOnError, printResult } from "../output.js";
|
||||
import { validateChain } from "../validate.js";
|
||||
|
||||
export function registerTrackCommands(program: Command): void {
|
||||
const track = program.command("track").description("On-chain tracking commands: follow-wallet trades, KOL trades, Smart Money trades");
|
||||
|
||||
track
|
||||
.command("follow-wallet")
|
||||
.description("Get follow-wallet trade records")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.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")
|
||||
.option("--filter <tag...>", "Filter conditions, repeatable")
|
||||
.option("--min-amount-usd <n>", "Minimum trade amount (USD)", parseFloat)
|
||||
.option("--max-amount-usd <n>", "Maximum trade amount (USD)", parseFloat)
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
validateChain(opts.chain);
|
||||
const extra: Record<string, string | number | string[]> = {};
|
||||
if (opts.wallet) extra["wallet_address"] = opts.wallet;
|
||||
if (opts.limit != null) extra["limit"] = opts.limit;
|
||||
if (opts.side) extra["side"] = opts.side;
|
||||
if (opts.filter?.length) extra["filters"] = opts.filter;
|
||||
if (opts.minAmountUsd != null) extra["min_amount_usd"] = opts.minAmountUsd;
|
||||
if (opts.maxAmountUsd != null) extra["max_amount_usd"] = opts.maxAmountUsd;
|
||||
const client = new OpenApiClient(getConfig());
|
||||
const data = await client.getFollowWallet(opts.chain, extra).catch(exitOnError);
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
track
|
||||
.command("kol")
|
||||
.description("Get KOL trade records")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.option("--limit <n>", "Page size (1–200, default 100)", parseInt)
|
||||
.option("--side <side>", "Filter by trade direction: buy / sell (client-side filter)")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (opts.chain) validateChain(opts.chain);
|
||||
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) {
|
||||
data.list = data.list.filter((item) => item.side === opts.side);
|
||||
}
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
|
||||
track
|
||||
.command("smartmoney")
|
||||
.description("Get Smart Money trade records")
|
||||
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
|
||||
.option("--limit <n>", "Page size (1–200, default 100)", parseInt)
|
||||
.option("--side <side>", "Filter by trade direction: buy / sell (client-side filter)")
|
||||
.option("--raw", "Output raw JSON")
|
||||
.action(async (opts) => {
|
||||
if (opts.chain) validateChain(opts.chain);
|
||||
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) {
|
||||
data.list = data.list.filter((item) => item.side === opts.side);
|
||||
}
|
||||
printResult(data, opts.raw);
|
||||
});
|
||||
}
|
||||
@@ -3,9 +3,9 @@ import { homedir } from "os";
|
||||
import { join } from "path";
|
||||
|
||||
|
||||
// Load global config first (~/.config/gmgn/.env), then project .env (project takes precedence)
|
||||
loadDotenv({ path: join(homedir(), ".config", "gmgn", ".env") });
|
||||
loadDotenv({ override: true });
|
||||
// Load global config first (~/.config/gmgn/.env, takes precedence), then project .env (supplements only)
|
||||
loadDotenv({ path: join(homedir(), ".config", "gmgn", ".env"), override: true });
|
||||
loadDotenv();
|
||||
|
||||
export interface Config {
|
||||
apiKey: string;
|
||||
@@ -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, order, and follow-wallet 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,10 +36,10 @@ 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";
|
||||
const host = "https://openapi.gmgn.ai";
|
||||
_config = { apiKey: apiKey!, privateKeyPem, host };
|
||||
return _config;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
import { createRequire } from "module";
|
||||
const { version } = createRequire(import.meta.url)("../package.json") as { version: string };
|
||||
import { setGlobalDispatcher, ProxyAgent, Agent } from "undici";
|
||||
import { setGlobalDispatcher, ProxyAgent, Agent, buildConnector } from "undici";
|
||||
import { SocksClient } from "socks";
|
||||
import * as tls from "tls";
|
||||
import { Command } from "commander";
|
||||
import { registerTokenCommands } from "./commands/token.js";
|
||||
import { registerMarketCommands } from "./commands/market.js";
|
||||
import { registerPortfolioCommands } from "./commands/portfolio.js";
|
||||
import { registerTrackCommands } from "./commands/track.js";
|
||||
import { registerSwapCommands } from "./commands/swap.js";
|
||||
import { registerCookingCommands } from "./commands/cooking.js";
|
||||
|
||||
const proxy = process.env.HTTPS_PROXY ?? process.env.https_proxy
|
||||
?? process.env.HTTP_PROXY ?? process.env.http_proxy;
|
||||
@@ -24,6 +26,7 @@ if (proxy) {
|
||||
proxy: { host: u.hostname, port: parseInt(u.port || "1080"), type },
|
||||
command: "connect",
|
||||
destination: { host: options.hostname!, port: +options.port! },
|
||||
socket_options: { family: 4 } as any,
|
||||
});
|
||||
if (options.protocol === "https:") {
|
||||
callback(null, tls.connect({ socket, servername: options.hostname, rejectUnauthorized: options.rejectUnauthorized !== false }));
|
||||
@@ -38,6 +41,10 @@ if (proxy) {
|
||||
} else {
|
||||
setGlobalDispatcher(new ProxyAgent(proxy));
|
||||
}
|
||||
} else {
|
||||
// Force IPv4 for all connections (no proxy mode)
|
||||
const connector = buildConnector({ family: 4 } as any);
|
||||
setGlobalDispatcher(new Agent({ connect: connector }));
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
@@ -45,12 +52,14 @@ const program = new Command();
|
||||
program
|
||||
.name("gmgn-cli")
|
||||
.version(version)
|
||||
.description("GMGN OpenAPI CLI — market data, token info, portfolio and swap");
|
||||
.description("GMGN OpenAPI CLI — market data, token info, portfolio, track KOL/smart money trades, and swap");
|
||||
|
||||
registerTokenCommands(program);
|
||||
registerMarketCommands(program);
|
||||
registerPortfolioCommands(program);
|
||||
registerTrackCommands(program);
|
||||
registerSwapCommands(program);
|
||||
registerCookingCommands(program);
|
||||
|
||||
program.parseAsync().catch((err) => {
|
||||
console.error(`[gmgn-cli] ${err.message}`);
|
||||
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 367 KiB |
|
After Width: | Height: | Size: 418 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 407 KiB |
|
After Width: | Height: | Size: 451 KiB |
|
After Width: | Height: | Size: 225 KiB |