gmgn-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +45 -0
- package/.claude-plugin/plugin.json +13 -0
- package/.cursor-plugin/plugin.json +23 -0
- package/LICENSE +21 -0
- package/Readme.md +236 -0
- package/Readme.zh.md +236 -0
- package/dist/client/OpenApiClient.d.ts +58 -0
- package/dist/client/OpenApiClient.d.ts.map +1 -0
- package/dist/client/OpenApiClient.js +174 -0
- package/dist/client/OpenApiClient.js.map +1 -0
- package/dist/client/signer.d.ts +32 -0
- package/dist/client/signer.d.ts.map +1 -0
- package/dist/client/signer.js +66 -0
- package/dist/client/signer.js.map +1 -0
- package/dist/commands/market.d.ts +3 -0
- package/dist/commands/market.d.ts.map +1 -0
- package/dist/commands/market.js +50 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/portfolio.d.ts +3 -0
- package/dist/commands/portfolio.d.ts.map +1 -0
- package/dist/commands/portfolio.js +112 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/swap.d.ts +3 -0
- package/dist/commands/swap.d.ts.map +1 -0
- package/dist/commands/swap.js +73 -0
- package/dist/commands/swap.js.map +1 -0
- package/dist/commands/token.d.ts +3 -0
- package/dist/commands/token.d.ts.map +1 -0
- package/dist/commands/token.js +62 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +3 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +22 -0
- package/dist/output.js.map +1 -0
- package/package.json +51 -0
- package/skills/gmgn-market/SKILL.md +144 -0
- package/skills/gmgn-portfolio/SKILL.md +105 -0
- package/skills/gmgn-swap/SKILL.md +142 -0
- package/skills/gmgn-token/SKILL.md +55 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { OpenApiClient } from "../client/OpenApiClient.js";
|
|
2
|
+
import { getConfig } from "../config.js";
|
|
3
|
+
import { exitOnError, printResult } from "../output.js";
|
|
4
|
+
export function registerTokenCommands(program) {
|
|
5
|
+
const token = program.command("token").description("Token information commands");
|
|
6
|
+
token
|
|
7
|
+
.command("info")
|
|
8
|
+
.description("Get token basic information and realtime price")
|
|
9
|
+
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
|
10
|
+
.requiredOption("--address <address>", "Token contract address")
|
|
11
|
+
.option("--raw", "Output raw JSON")
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const client = new OpenApiClient(getConfig());
|
|
14
|
+
const data = await client.getTokenInfo(opts.chain, opts.address).catch(exitOnError);
|
|
15
|
+
printResult(data, opts.raw);
|
|
16
|
+
});
|
|
17
|
+
token
|
|
18
|
+
.command("security")
|
|
19
|
+
.description("Get token security metrics")
|
|
20
|
+
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
|
21
|
+
.requiredOption("--address <address>", "Token contract address")
|
|
22
|
+
.option("--raw", "Output raw JSON")
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
const client = new OpenApiClient(getConfig());
|
|
25
|
+
const data = await client.getTokenSecurity(opts.chain, opts.address).catch(exitOnError);
|
|
26
|
+
printResult(data, opts.raw);
|
|
27
|
+
});
|
|
28
|
+
token
|
|
29
|
+
.command("pool")
|
|
30
|
+
.description("Get token liquidity pool information")
|
|
31
|
+
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
|
32
|
+
.requiredOption("--address <address>", "Token contract address")
|
|
33
|
+
.option("--raw", "Output raw JSON")
|
|
34
|
+
.action(async (opts) => {
|
|
35
|
+
const client = new OpenApiClient(getConfig());
|
|
36
|
+
const data = await client.getTokenPoolInfo(opts.chain, opts.address).catch(exitOnError);
|
|
37
|
+
printResult(data, opts.raw);
|
|
38
|
+
});
|
|
39
|
+
token
|
|
40
|
+
.command("holders")
|
|
41
|
+
.description("Get top token holders")
|
|
42
|
+
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
|
43
|
+
.requiredOption("--address <address>", "Token contract address")
|
|
44
|
+
.option("--raw", "Output raw JSON")
|
|
45
|
+
.action(async (opts) => {
|
|
46
|
+
const client = new OpenApiClient(getConfig());
|
|
47
|
+
const data = await client.getTokenTopHolders(opts.chain, opts.address).catch(exitOnError);
|
|
48
|
+
printResult(data, opts.raw);
|
|
49
|
+
});
|
|
50
|
+
token
|
|
51
|
+
.command("traders")
|
|
52
|
+
.description("Get top token traders")
|
|
53
|
+
.requiredOption("--chain <chain>", "Chain: sol / bsc / base")
|
|
54
|
+
.requiredOption("--address <address>", "Token contract address")
|
|
55
|
+
.option("--raw", "Output raw JSON")
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
const client = new OpenApiClient(getConfig());
|
|
58
|
+
const data = await client.getTokenTopTraders(opts.chain, opts.address).catch(exitOnError);
|
|
59
|
+
printResult(data, opts.raw);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/commands/token.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAID,wBAAgB,SAAS,CAAC,iBAAiB,UAAQ,GAAG,MAAM,CAyB3D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { config as loadDotenv } from "dotenv";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
// Load global config first (~/.config/gmgn/.env), then project .env (project takes precedence)
|
|
5
|
+
loadDotenv({ path: join(homedir(), ".config", "gmgn", ".env") });
|
|
6
|
+
loadDotenv({ override: true });
|
|
7
|
+
let _config = null;
|
|
8
|
+
export function getConfig(requirePrivateKey = false) {
|
|
9
|
+
if (_config) {
|
|
10
|
+
if (requirePrivateKey && !_config.privateKeyPem) {
|
|
11
|
+
die("GMGN_PRIVATE_KEY is required for swap/order commands");
|
|
12
|
+
}
|
|
13
|
+
return _config;
|
|
14
|
+
}
|
|
15
|
+
const apiKey = process.env.GMGN_API_KEY;
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
die("GMGN_API_KEY is required. Set it in your .env file or environment.");
|
|
18
|
+
}
|
|
19
|
+
let privateKeyPem;
|
|
20
|
+
const privateKey = process.env.GMGN_PRIVATE_KEY;
|
|
21
|
+
if (privateKey) {
|
|
22
|
+
// Support escaped newlines (e.g. from single-line .env values)
|
|
23
|
+
privateKeyPem = privateKey.replace(/\\n/g, "\n");
|
|
24
|
+
}
|
|
25
|
+
else if (requirePrivateKey) {
|
|
26
|
+
die("GMGN_PRIVATE_KEY is required for swap/order commands");
|
|
27
|
+
}
|
|
28
|
+
const host = process.env.GMGN_HOST ?? "https://openapi.gmgn.ai";
|
|
29
|
+
_config = { apiKey: apiKey, privateKeyPem, host };
|
|
30
|
+
return _config;
|
|
31
|
+
}
|
|
32
|
+
function die(msg) {
|
|
33
|
+
console.error(`[gmgn-cli] Error: ${msg}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,+FAA+F;AAC/F,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AACjE,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAQ/B,IAAI,OAAO,GAAkB,IAAI,CAAC;AAElC,MAAM,UAAU,SAAS,CAAC,iBAAiB,GAAG,KAAK;IACjD,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,iBAAiB,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAChD,GAAG,CAAC,sDAAsD,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,oEAAoE,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,aAAiC,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAChD,IAAI,UAAU,EAAE,CAAC;QACf,+DAA+D;QAC/D,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;SAAM,IAAI,iBAAiB,EAAE,CAAC;QAC7B,GAAG,CAAC,sDAAsD,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,yBAAyB,CAAC;IAChE,OAAO,GAAG,EAAE,MAAM,EAAE,MAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IACnD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { setGlobalDispatcher, ProxyAgent, Agent } from "undici";
|
|
3
|
+
import { SocksClient } from "socks";
|
|
4
|
+
import * as tls from "tls";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { registerTokenCommands } from "./commands/token.js";
|
|
7
|
+
import { registerMarketCommands } from "./commands/market.js";
|
|
8
|
+
import { registerPortfolioCommands } from "./commands/portfolio.js";
|
|
9
|
+
import { registerSwapCommands } from "./commands/swap.js";
|
|
10
|
+
const proxy = process.env.HTTPS_PROXY ?? process.env.https_proxy
|
|
11
|
+
?? process.env.HTTP_PROXY ?? process.env.http_proxy;
|
|
12
|
+
if (proxy) {
|
|
13
|
+
const u = new URL(proxy);
|
|
14
|
+
if (u.protocol === "socks5:" || u.protocol === "socks4:") {
|
|
15
|
+
const type = u.protocol === "socks5:" ? 5 : 4;
|
|
16
|
+
setGlobalDispatcher(new Agent({
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
connect: async (options, callback) => {
|
|
19
|
+
try {
|
|
20
|
+
const { socket } = await SocksClient.createConnection({
|
|
21
|
+
proxy: { host: u.hostname, port: parseInt(u.port || "1080"), type },
|
|
22
|
+
command: "connect",
|
|
23
|
+
destination: { host: options.hostname, port: +options.port },
|
|
24
|
+
});
|
|
25
|
+
if (options.protocol === "https:") {
|
|
26
|
+
callback(null, tls.connect({ socket, servername: options.hostname, rejectUnauthorized: options.rejectUnauthorized !== false }));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
callback(null, socket);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
callback(err, null);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
setGlobalDispatcher(new ProxyAgent(proxy));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const program = new Command();
|
|
43
|
+
program
|
|
44
|
+
.name("gmgn-cli")
|
|
45
|
+
.version("1.0.0")
|
|
46
|
+
.description("GMGN OpenAPI CLI — market data, token info, portfolio and swap");
|
|
47
|
+
registerTokenCommands(program);
|
|
48
|
+
registerMarketCommands(program);
|
|
49
|
+
registerPortfolioCommands(program);
|
|
50
|
+
registerSwapCommands(program);
|
|
51
|
+
program.parseAsync().catch((err) => {
|
|
52
|
+
console.error(`[gmgn-cli] ${err.message}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,CAM9D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,KAAK,GAAG,KAAK,CAY7C"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function printResult(data, raw) {
|
|
2
|
+
if (raw) {
|
|
3
|
+
console.log(JSON.stringify(data));
|
|
4
|
+
}
|
|
5
|
+
else {
|
|
6
|
+
console.log(JSON.stringify(data, null, 2));
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function exitOnError(err) {
|
|
10
|
+
console.error(`[gmgn-cli] ${err.message}`);
|
|
11
|
+
if (process.env.GMGN_DEBUG) {
|
|
12
|
+
if (err.code) {
|
|
13
|
+
console.error(`[gmgn-cli] code: ${err.code}`);
|
|
14
|
+
}
|
|
15
|
+
if (err.cause) {
|
|
16
|
+
console.error(`[gmgn-cli] cause: ${err.cause}`);
|
|
17
|
+
}
|
|
18
|
+
console.error(err.stack ?? "");
|
|
19
|
+
}
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,IAAa,EAAE,GAAa;IACtD,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAU;IACpC,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3B,IAAK,GAA6B,CAAC,IAAI,EAAE,CAAC;YACxC,OAAO,CAAC,KAAK,CAAC,oBAAqB,GAA6B,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,IAAK,GAA2B,CAAC,KAAK,EAAE,CAAC;YACvC,OAAO,CAAC,KAAK,CAAC,qBAAsB,GAA2B,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gmgn-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "GMGN OpenAPI CLI — call GMGN market, token, portfolio and swap APIs from the command line",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gmgn-cli": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"skills",
|
|
13
|
+
".claude-plugin",
|
|
14
|
+
".cursor-plugin"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsx src/index.ts",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"commander": "^12.1.0",
|
|
23
|
+
"dotenv": "^16.4.5",
|
|
24
|
+
"socks": "^2.8.7",
|
|
25
|
+
"undici": "^7.24.1"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"tsx": "^4.19.0",
|
|
30
|
+
"typescript": "^5.5.0"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/gmgn-ai/gmgn-skills"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"gmgn",
|
|
42
|
+
"crypto",
|
|
43
|
+
"solana",
|
|
44
|
+
"token",
|
|
45
|
+
"defi",
|
|
46
|
+
"swap",
|
|
47
|
+
"portfolio",
|
|
48
|
+
"market",
|
|
49
|
+
"claude-skill"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gmgn-market
|
|
3
|
+
description: Query GMGN market data — token K-line (candlestick) and trending token swap data. Supports sol / bsc / base.
|
|
4
|
+
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>"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the `gmgn-cli` tool to query K-line data for a token or browse trending tokens.
|
|
8
|
+
|
|
9
|
+
## Sub-commands
|
|
10
|
+
|
|
11
|
+
| Sub-command | Description |
|
|
12
|
+
|-------------|-------------|
|
|
13
|
+
| `market kline` | Token candlestick data |
|
|
14
|
+
| `market trending` | Trending token swap data |
|
|
15
|
+
|
|
16
|
+
## Supported Chains
|
|
17
|
+
|
|
18
|
+
`sol` / `bsc` / `base`
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- `.env` file with `GMGN_API_KEY` set
|
|
23
|
+
- Run from the directory where your `.env` file is located, or set `GMGN_HOST` in your environment
|
|
24
|
+
|
|
25
|
+
## Kline Parameters
|
|
26
|
+
|
|
27
|
+
| Parameter | Required | Description |
|
|
28
|
+
|-----------|----------|-------------|
|
|
29
|
+
| `--chain` | Yes | `sol` / `bsc` / `base` |
|
|
30
|
+
| `--address` | Yes | Token contract address |
|
|
31
|
+
| `--resolution` | Yes | Candlestick resolution |
|
|
32
|
+
| `--from` | No | Start time (Unix seconds) |
|
|
33
|
+
| `--to` | No | End time (Unix seconds) |
|
|
34
|
+
|
|
35
|
+
## Resolutions
|
|
36
|
+
|
|
37
|
+
`1m` / `5m` / `15m` / `1h` / `4h` / `1d`
|
|
38
|
+
|
|
39
|
+
## Trending Options
|
|
40
|
+
|
|
41
|
+
| Option | Description |
|
|
42
|
+
|--------|-------------|
|
|
43
|
+
| `--chain` | Required. `sol` / `bsc` / `base` |
|
|
44
|
+
| `--interval` | Required. `1h` / `3h` / `6h` / `24h` |
|
|
45
|
+
| `--limit <n>` | Number of results (default 100, max 100) |
|
|
46
|
+
| `--orderby <field>` | Sort field: `score` / `volume` / `swaps` / `liquidity` / `marketcap` / `holders` / `price` / `change` / `change1m` / `change5m` / `change1h` / `renowned_count` / `smart_degen_count` / `bluechip_owner_percentage` / `rank` / `creation_timestamp` / `square_mentions` / `history_highest_market_cap` / `gas_fee` |
|
|
47
|
+
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
|
48
|
+
| `--filter <tag...>` | Repeatable filter tags: `has_social` / `not_risk` / `not_honeypot` / `verified` / `locked` / `renounced` / `distributed` / `frozen` / `burn` / `token_burnt` / `creator_hold` / `creator_close` / `creator_add_liquidity` / `creator_remove_liquidity` / `creator_sell` / `creator_buy` / `not_wash_trading` / `not_social_dup` / `not_image_dup` / `is_internal_market` / `is_out_market` |
|
|
49
|
+
| `--platform <name...>` | Repeatable platform filter: `pump` / `moonshot` / `launchlab` |
|
|
50
|
+
|
|
51
|
+
## Usage Examples
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Last 1 hour of 1-minute candles
|
|
55
|
+
# macOS:
|
|
56
|
+
npx gmgn-cli market kline \
|
|
57
|
+
--chain sol \
|
|
58
|
+
--address <token_address> \
|
|
59
|
+
--resolution 1m \
|
|
60
|
+
--from $(date -v-1H +%s) \
|
|
61
|
+
--to $(date +%s)
|
|
62
|
+
# Linux: use $(date -d '1 hour ago' +%s) instead of $(date -v-1H +%s)
|
|
63
|
+
|
|
64
|
+
# Last 24 hours of 1-hour candles
|
|
65
|
+
# macOS:
|
|
66
|
+
npx gmgn-cli market kline \
|
|
67
|
+
--chain sol \
|
|
68
|
+
--address <token_address> \
|
|
69
|
+
--resolution 1h \
|
|
70
|
+
--from $(date -v-24H +%s) \
|
|
71
|
+
--to $(date +%s)
|
|
72
|
+
# Linux: use $(date -d '24 hours ago' +%s) instead of $(date -v-24H +%s)
|
|
73
|
+
|
|
74
|
+
# Top 20 hot tokens on SOL in the last 1 hour, sorted by volume
|
|
75
|
+
npx gmgn-cli market trending --chain sol --interval 1h --orderby volume --limit 20
|
|
76
|
+
|
|
77
|
+
# Hot tokens with social links only, not risky, on BSC over 24h
|
|
78
|
+
npx gmgn-cli market trending \
|
|
79
|
+
--chain bsc --interval 24h \
|
|
80
|
+
--filter has_social --filter not_risk
|
|
81
|
+
|
|
82
|
+
# Pump platform tokens on SOL, last 6 hours
|
|
83
|
+
npx gmgn-cli market trending --chain sol --interval 6h --platform pump
|
|
84
|
+
|
|
85
|
+
# Raw output for further processing
|
|
86
|
+
npx gmgn-cli market kline --chain sol --address <addr> \
|
|
87
|
+
--resolution 5m --from <ts> --to <ts> --raw | jq '.[]'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Workflow: Discover Trading Opportunities via Trending
|
|
91
|
+
|
|
92
|
+
### Step 1 — Fetch trending data
|
|
93
|
+
|
|
94
|
+
Fetch a broad pool with safe filters, sorted by GMGN's composite score:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx gmgn-cli market trending \
|
|
98
|
+
--chain <chain> --interval 1h \
|
|
99
|
+
--orderby score --limit 50 \
|
|
100
|
+
--filter not_risk --filter not_honeypot --filter has_social --raw
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Step 2 — AI multi-factor analysis
|
|
104
|
+
|
|
105
|
+
Analyze each record in the response using the following signals (apply judgment, not rigid rules):
|
|
106
|
+
|
|
107
|
+
| Signal | Field(s) | Weight | Notes |
|
|
108
|
+
|--------|----------|--------|-------|
|
|
109
|
+
| GMGN quality score | `score` | High | Primary ranking signal from GMGN |
|
|
110
|
+
| Smart money interest | `smart_degen_count`, `renowned_count` | High | Key conviction indicator |
|
|
111
|
+
| Bluechip ownership | `bluechip_owner_percentage` | Medium | Quality of holder base |
|
|
112
|
+
| Real trading activity | `volume`, `swaps` | Medium | Distinguishes genuine interest from wash trading |
|
|
113
|
+
| Price momentum | `change1h`, `change5m` | Medium | Prefer positive, non-parabolic moves |
|
|
114
|
+
| Pool safety | `liquidity` | Medium | Low liquidity = high slippage risk |
|
|
115
|
+
| Token maturity | `creation_timestamp` | Low | Avoid tokens less than ~1h old unless other signals are very strong |
|
|
116
|
+
|
|
117
|
+
Select the **top 5** tokens with the best composite profile. Prefer tokens that score well across multiple signals rather than excelling in just one.
|
|
118
|
+
|
|
119
|
+
### Step 3 — Present top 5 to user
|
|
120
|
+
|
|
121
|
+
Present results as a concise table, then give a one-line rationale for each pick:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
Top 5 Trending Tokens — SOL / 1h
|
|
125
|
+
|
|
126
|
+
# | Symbol | Address (short) | Score | Smart Degens | Volume | 1h Chg | Reasoning
|
|
127
|
+
1 | ... | ... | ... | ... | ... | ... | High score + smart money accumulating
|
|
128
|
+
2 | ...
|
|
129
|
+
...
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Step 4 — Follow-up actions
|
|
133
|
+
|
|
134
|
+
For each token, offer:
|
|
135
|
+
- **Deep dive**: `token info` + `token security` for full due diligence
|
|
136
|
+
- **Swap**: execute directly if the user is satisfied with the trending data alone
|
|
137
|
+
|
|
138
|
+
## Notes
|
|
139
|
+
|
|
140
|
+
- `market kline`: `--from` and `--to` are Unix timestamps in **seconds** — CLI converts to milliseconds automatically
|
|
141
|
+
- `market trending`: `--filter` and `--platform` are repeatable flags
|
|
142
|
+
- All commands use normal auth (API Key only, no signature)
|
|
143
|
+
- If the user doesn't provide kline timestamps, calculate them from the current time based on their desired time range
|
|
144
|
+
- Use `--raw` to get single-line JSON for further processing
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gmgn-portfolio
|
|
3
|
+
description: Query GMGN wallet portfolio — API Key wallet info, holdings, transaction activity, trading stats, and token balance. Supports sol / bsc / base.
|
|
4
|
+
argument-hint: "<info|holdings|activity|stats|token-balance> [--chain <sol|bsc|base>] [--wallet <wallet_address>]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use the `gmgn-cli` tool to query wallet portfolio data based on the user's request.
|
|
8
|
+
|
|
9
|
+
## Sub-commands
|
|
10
|
+
|
|
11
|
+
| Sub-command | Description |
|
|
12
|
+
|-------------|-------------|
|
|
13
|
+
| `portfolio info` | Wallets and main currency balances bound to the API Key |
|
|
14
|
+
| `portfolio holdings` | Wallet token holdings with P&L |
|
|
15
|
+
| `portfolio activity` | Transaction history |
|
|
16
|
+
| `portfolio stats` | Trading statistics (supports batch) |
|
|
17
|
+
| `portfolio token-balance` | Token balance for a specific token |
|
|
18
|
+
|
|
19
|
+
## Supported Chains
|
|
20
|
+
|
|
21
|
+
`sol` / `bsc` / `base`
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
- `.env` file with `GMGN_API_KEY` set
|
|
26
|
+
- Run from the directory where your `.env` file is located, or set `GMGN_HOST` in your environment
|
|
27
|
+
|
|
28
|
+
## Usage Examples
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# API Key wallet info (no --chain or --wallet needed)
|
|
32
|
+
npx gmgn-cli portfolio info
|
|
33
|
+
|
|
34
|
+
# Wallet holdings (default sort)
|
|
35
|
+
npx gmgn-cli portfolio holdings --chain sol --wallet <wallet_address>
|
|
36
|
+
|
|
37
|
+
# Holdings sorted by USD value, descending
|
|
38
|
+
npx gmgn-cli portfolio holdings \
|
|
39
|
+
--chain sol --wallet <wallet_address> \
|
|
40
|
+
--order-by usd_value --direction desc --limit 20
|
|
41
|
+
|
|
42
|
+
# Include sold-out positions
|
|
43
|
+
npx gmgn-cli portfolio holdings --chain sol --wallet <wallet_address> --sell-out
|
|
44
|
+
|
|
45
|
+
# Transaction activity
|
|
46
|
+
npx gmgn-cli portfolio activity --chain sol --wallet <wallet_address>
|
|
47
|
+
|
|
48
|
+
# Activity filtered by type
|
|
49
|
+
npx gmgn-cli portfolio activity --chain sol --wallet <wallet_address> \
|
|
50
|
+
--type buy --type sell
|
|
51
|
+
|
|
52
|
+
# Activity for a specific token
|
|
53
|
+
npx gmgn-cli portfolio activity --chain sol --wallet <wallet_address> \
|
|
54
|
+
--token <token_address>
|
|
55
|
+
|
|
56
|
+
# Trading stats (default 7d)
|
|
57
|
+
npx gmgn-cli portfolio stats --chain sol --wallet <wallet_address>
|
|
58
|
+
|
|
59
|
+
# Trading stats for 30 days
|
|
60
|
+
npx gmgn-cli portfolio stats --chain sol --wallet <wallet_address> --period 30d
|
|
61
|
+
|
|
62
|
+
# Batch stats for multiple wallets
|
|
63
|
+
npx gmgn-cli portfolio stats --chain sol \
|
|
64
|
+
--wallet <wallet_1> --wallet <wallet_2>
|
|
65
|
+
|
|
66
|
+
# Token balance
|
|
67
|
+
npx gmgn-cli portfolio token-balance \
|
|
68
|
+
--chain sol --wallet <wallet_address> --token <token_address>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Holdings Options
|
|
72
|
+
|
|
73
|
+
| Option | Description |
|
|
74
|
+
|--------|-------------|
|
|
75
|
+
| `--limit <n>` | Page size (default `20`, max 50) |
|
|
76
|
+
| `--cursor <cursor>` | Pagination cursor |
|
|
77
|
+
| `--order-by <field>` | Sort field: `usd_value` / `price` / `unrealized_profit` / `realized_profit` / `total_profit` / `history_bought_cost` / `history_sold_income` (default `usd_value`) |
|
|
78
|
+
| `--direction <asc\|desc>` | Sort direction (default `desc`) |
|
|
79
|
+
| `--sell-out` | Include sold-out positions |
|
|
80
|
+
| `--show-small` | Include small-value positions |
|
|
81
|
+
| `--hide-abnormal` | Hide abnormal positions |
|
|
82
|
+
| `--hide-airdrop` | Hide airdrop positions |
|
|
83
|
+
| `--hide-closed` | Hide closed positions |
|
|
84
|
+
| `--hide-open` | Hide open positions |
|
|
85
|
+
|
|
86
|
+
## Activity Options
|
|
87
|
+
|
|
88
|
+
| Option | Description |
|
|
89
|
+
|--------|-------------|
|
|
90
|
+
| `--token <address>` | Filter by token |
|
|
91
|
+
| `--limit <n>` | Page size |
|
|
92
|
+
| `--cursor <cursor>` | Pagination cursor |
|
|
93
|
+
| `--type <type>` | Repeatable: `buy` / `sell` / `add` / `remove` / `transfer` |
|
|
94
|
+
|
|
95
|
+
## Stats Options
|
|
96
|
+
|
|
97
|
+
| Option | Description |
|
|
98
|
+
|--------|-------------|
|
|
99
|
+
| `--period <period>` | Stats period: `7d` / `30d` (default `7d`) |
|
|
100
|
+
|
|
101
|
+
## Notes
|
|
102
|
+
|
|
103
|
+
- All portfolio commands use normal auth (API Key only, no signature required)
|
|
104
|
+
- `portfolio stats` supports multiple `--wallet` flags for batch queries
|
|
105
|
+
- Use `--raw` to get single-line JSON for further processing
|