Files
gmgn-skills/src/commands/token.ts
T
David LauandClaude Sonnet 4.6 1012cfffb8 feat(eth): add Ethereum mainnet chain support (P0 commands)
Add ETH chain support to all P0 commands across CLI and SKILL.md docs:

Commands with ETH support added:
- token info/security/pool/holders/traders
- market kline/trending
- portfolio info/holdings/activity/stats/token-balance
- track follow-wallet
- swap, order quote/get

P1/P2 commands remain sol/bsc/base only:
- track kol/smartmoney (P1)
- multi-swap, order strategy create/list/cancel (P1)
- portfolio created-tokens (P2)

Also adds ETH chain currencies, explorer links, and gas price bounds
to gmgn-swap SKILL.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 16:08:36 +08:00

99 lines
4.7 KiB
TypeScript

import { Command } from "commander";
import { OpenApiClient } from "../client/OpenApiClient.js";
import { getConfig } from "../config.js";
import { exitOnError, printResult } from "../output.js";
import { validateAddress, validateChain } from "../validate.js";
export function registerTokenCommands(program: Command): void {
const token = program.command("token").description("Token information commands");
token
.command("info")
.description("Get token basic information and realtime price")
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
.requiredOption("--address <address>", "Token contract address")
.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.getTokenInfo(opts.chain, opts.address).catch(exitOnError);
printResult(data, opts.raw);
});
token
.command("security")
.description("Get token security metrics")
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
.requiredOption("--address <address>", "Token contract address")
.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.getTokenSecurity(opts.chain, opts.address).catch(exitOnError);
printResult(data, opts.raw);
});
token
.command("pool")
.description("Get token liquidity pool information")
.requiredOption("--chain <chain>", "Chain: sol / bsc / base / eth")
.requiredOption("--address <address>", "Token contract address")
.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.getTokenPoolInfo(opts.chain, opts.address).catch(exitOnError);
printResult(data, opts.raw);
});
token
.command("holders")
.description("Get top token holders")
.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: 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);
validateAddress(opts.address, opts.chain, "--address");
const extra: Record<string, string | number> = {};
if (opts.limit != null) extra["limit"] = opts.limit;
if (opts.orderBy) extra["order_by"] = opts.orderBy;
if (opts.direction) extra["direction"] = opts.direction;
if (opts.tag) extra["tag"] = opts.tag;
const client = new OpenApiClient(getConfig());
const data = await client.getTokenTopHolders(opts.chain, opts.address, extra).catch(exitOnError);
printResult(data, opts.raw);
});
token
.command("traders")
.description("Get top token traders")
.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: 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);
validateAddress(opts.address, opts.chain, "--address");
const extra: Record<string, string | number> = {};
if (opts.limit != null) extra["limit"] = opts.limit;
if (opts.orderBy) extra["order_by"] = opts.orderBy;
if (opts.direction) extra["direction"] = opts.direction;
if (opts.tag) extra["tag"] = opts.tag;
const client = new OpenApiClient(getConfig());
const data = await client.getTokenTopTraders(opts.chain, opts.address, extra).catch(exitOnError);
printResult(data, opts.raw);
});
}