diff --git a/skills/gmgn-cooking/SKILL.md b/skills/gmgn-cooking/SKILL.md index 1e5eb31..ac133fd 100644 --- a/skills/gmgn-cooking/SKILL.md +++ b/skills/gmgn-cooking/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli cooking --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.env +``` + **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.** diff --git a/skills/gmgn-market/SKILL.md b/skills/gmgn-market/SKILL.md index 89b04cb..abcf4f5 100644 --- a/skills/gmgn-market/SKILL.md +++ b/skills/gmgn-market/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli market --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.env +``` + **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.** diff --git a/skills/gmgn-portfolio/SKILL.md b/skills/gmgn-portfolio/SKILL.md index a9e2cef..a2fa8fd 100644 --- a/skills/gmgn-portfolio/SKILL.md +++ b/skills/gmgn-portfolio/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli portfolio --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.env +``` + **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."** diff --git a/skills/gmgn-swap/SKILL.md b/skills/gmgn-swap/SKILL.md index eef9832..53ebb03 100644 --- a/skills/gmgn-swap/SKILL.md +++ b/skills/gmgn-swap/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli swap --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.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.** diff --git a/skills/gmgn-token/SKILL.md b/skills/gmgn-token/SKILL.md index 3ab13e0..57c61f5 100644 --- a/skills/gmgn-token/SKILL.md +++ b/skills/gmgn-token/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli token --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.env +``` + **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."** diff --git a/skills/gmgn-track/SKILL.md b/skills/gmgn-track/SKILL.md index 2c18c99..5f32903 100644 --- a/skills/gmgn-track/SKILL.md +++ b/skills/gmgn-track/SKILL.md @@ -6,6 +6,17 @@ metadata: cliHelp: "gmgn-cli track --help" --- +**BEFORE RUNNING ANY COMMAND: Check whether `GMGN_API_KEY` exists in `/.env` or `~/.config/gmgn/.env`. If found in either location, proceed normally. If not found in either location, stop and run `gmgn-cli config` first — this generates an Ed25519 key pair and outputs a pre-filled link. Show the link to the user and ask them to create their API Key. Once the user sends back the API Key, write `GMGN_API_KEY` and `GMGN_PRIVATE_KEY` together into `~/.config/gmgn/.env` using the following commands, then proceed:** + +```bash +PRIVATE_KEY=$(awk '/-----BEGIN PRIVATE KEY-----/{p=1} p{printf "%s\\n", $0} /-----END PRIVATE KEY-----/{p=0}' ~/.config/gmgn/keypair.pem) +grep -v "^GMGN_API_KEY=\|^GMGN_PRIVATE_KEY=" ~/.config/gmgn/.env 2>/dev/null > /tmp/gmgn_env_tmp +echo "GMGN_API_KEY=" >> /tmp/gmgn_env_tmp +echo "GMGN_PRIVATE_KEY=$PRIVATE_KEY" >> /tmp/gmgn_env_tmp +mv /tmp/gmgn_env_tmp ~/.config/gmgn/.env +chmod 600 ~/.config/gmgn/.env +``` + **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.** diff --git a/src/commands/config.ts b/src/commands/config.ts new file mode 100644 index 0000000..f9acbd4 --- /dev/null +++ b/src/commands/config.ts @@ -0,0 +1,56 @@ +import { Command } from "commander"; +import * as crypto from "crypto"; +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; + +const GMGN_CONFIG_DIR = path.join(os.homedir(), ".config", "gmgn"); +const KEYPAIR_FILE = path.join(GMGN_CONFIG_DIR, "keypair.pem"); +const GMGN_API_URL = "https://gmgn.ai/ai/generateapi"; + +export function registerConfigCommands(program: Command): void { + program + .command("config") + .description("Generate an Ed25519 key pair and output a pre-filled GMGN API Key creation link") + .action(async () => { + fs.mkdirSync(GMGN_CONFIG_DIR, { recursive: true }); + + let publicPem: string; + + if (fs.existsSync(KEYPAIR_FILE)) { + // Reuse existing key pair + const content = fs.readFileSync(KEYPAIR_FILE, "utf-8"); + const match = content.match(/(-----BEGIN PUBLIC KEY-----[\s\S]+?-----END PUBLIC KEY-----)/); + if (!match) { + console.error("Error: keypair.pem exists but public key could not be parsed. Delete ~/.config/gmgn/keypair.pem and try again."); + process.exit(1); + } + publicPem = match[1] + "\n"; + } else { + // Generate new Ed25519 key pair + const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519"); + const privatePem = privateKey.export({ type: "pkcs8", format: "pem" }) as string; + publicPem = publicKey.export({ type: "spki", format: "pem" }) as string; + + const entry = `# Private Key\n${privatePem}\n# Public Key\n${publicPem}\n`; + fs.writeFileSync(KEYPAIR_FILE, entry, { mode: 0o600 }); + } + + const link = `${GMGN_API_URL}?pbk=${encodeURIComponent(publicPem)}`; + + const locale = (process.env.LANG ?? process.env.LC_ALL ?? process.env.LC_MESSAGES ?? "").toLowerCase(); + let message: string; + if (locale.startsWith("zh_tw") || locale.startsWith("zh_hk")) { + message = "請點擊連結建立你的 GMGN API Key,完成後將 Key 發給我,我來幫你完成配置:"; + } else if (locale.startsWith("zh")) { + message = "请点击链接创建你的 GMGN API Key,完成后将 Key 发给我,我来帮你完成配置:"; + } else { + message = "Please click the link below to create your GMGN API Key. Once created, send me the API Key and I will finish the configuration:"; + } + + console.log(""); + console.log(message); + console.log(link); + console.log(""); + }); +} diff --git a/src/index.ts b/src/index.ts index b3897f2..9e7d736 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import { registerPortfolioCommands } from "./commands/portfolio.js"; import { registerTrackCommands } from "./commands/track.js"; import { registerSwapCommands } from "./commands/swap.js"; import { registerCookingCommands } from "./commands/cooking.js"; +import { registerConfigCommands } from "./commands/config.js"; const proxy = process.env.HTTPS_PROXY ?? process.env.https_proxy ?? process.env.HTTP_PROXY ?? process.env.http_proxy; @@ -60,6 +61,7 @@ registerPortfolioCommands(program); registerTrackCommands(program); registerSwapCommands(program); registerCookingCommands(program); +registerConfigCommands(program); program.parseAsync().catch((err) => { console.error(`[gmgn-cli] ${err.message}`);