From 981600f1709422a750173887d04216c8c6b052a3 Mon Sep 17 00:00:00 2001 From: wuyanling Date: Wed, 22 Apr 2026 11:37:44 +0800 Subject: [PATCH 1/3] fix(trenches): require unit suffix for --min-created / --max-created Bare numbers like 0.5 were silently accepted but caused inconsistent server-side filtering. This change: - Adds a parseDuration() validator that rejects values without a unit - Accepts seconds (e.g. 30s) and minutes (e.g. 0.5m / 1m / 5m) - Prints a clear error message when a bare number is passed - Updates desc strings to document the required unit format - Adds a new TrenchesFieldType 'duration' to distinguish these fields --- src/commands/market.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/commands/market.ts b/src/commands/market.ts index df7d7c5..020080b 100644 --- a/src/commands/market.ts +++ b/src/commands/market.ts @@ -4,6 +4,16 @@ import { getConfig } from "../config.js"; import { exitOnError, printResult } from "../output.js"; import { validateAddress, validateChain } from "../validate.js"; +// Parse token age string — must include a unit suffix: s (seconds) or m (minutes). +// e.g. "30s" → "30s", "0.5m" → "0.5m". Bare numbers without a unit are rejected. +function parseDuration(value: string): string { + if (/^\d+(\.\d+)?[sm]$/.test(value)) return value; + console.error( + `[gmgn-cli] Invalid duration "${value}". A unit is required — 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"); @@ -76,6 +86,8 @@ export function registerMarketCommands(program: Command): void { 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} `, def.desc, parseDuration); } else { trenchesCmd.option(`--${flag} `, def.desc); } @@ -169,7 +181,7 @@ export function registerMarketCommands(program: Command): void { // ---- Trenches filter field definitions ---- -type TrenchesFieldType = "int" | "float" | "string"; +type TrenchesFieldType = "int" | "float" | "string" | "duration"; interface TrenchesFilterField { api: string; @@ -201,8 +213,8 @@ const TRENCHES_FILTER_FIELDS: TrenchesFilterField[] = [ { api: "min_liquidity", type: "float", desc: "Min liquidity (USD)" }, { api: "max_liquidity", type: "float", desc: "Max liquidity (USD)" }, // Token age - { api: "min_created", type: "string", desc: "Min token age (e.g. 1m / 5m / 30m / 1h / 6h / 24h)" }, - { api: "max_created", type: "string", desc: "Max token age (e.g. 1m / 5m / 30m / 1h / 6h / 24h)" }, + { api: "min_created", type: "duration", desc: "Min token age — unit required: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m / 1h)" }, + { api: "max_created", type: "duration", desc: "Max token age — unit required: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m / 1h)" }, // Holders { api: "min_holder_count", type: "int", desc: "Min holder count" }, { api: "max_holder_count", type: "int", desc: "Max holder count" }, From cc1cb48db97e58a8a76f87cc2c0bb1a909590c2c Mon Sep 17 00:00:00 2001 From: wuyanling Date: Wed, 22 Apr 2026 11:52:01 +0800 Subject: [PATCH 2/3] fix(trenches): treat bare duration numbers as minutes with warning, update skill docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - parseDuration: bare numbers now default to minutes (e.g. "5" → "5m") instead of hard error - Print a warning to stderr so users know the implicit conversion is happening - Update SKILL.md: document unit suffix recommendation and bare-number fallback behavior Co-Authored-By: Claude Sonnet 4.6 --- skills/gmgn-market/SKILL.md | 2 +- src/commands/market.ts | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/skills/gmgn-market/SKILL.md b/skills/gmgn-market/SKILL.md index a29c0a8..6bf7718 100644 --- a/skills/gmgn-market/SKILL.md +++ b/skills/gmgn-market/SKILL.md @@ -507,7 +507,7 @@ All filter flags are sent as part of the API request body — the server filters | `--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` | string | Token age (e.g. `1m` / `5m` / `1h` / `24h`) | +| `--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) | diff --git a/src/commands/market.ts b/src/commands/market.ts index 020080b..c126b5f 100644 --- a/src/commands/market.ts +++ b/src/commands/market.ts @@ -4,12 +4,18 @@ import { getConfig } from "../config.js"; import { exitOnError, printResult } from "../output.js"; import { validateAddress, validateChain } from "../validate.js"; -// Parse token age string — must include a unit suffix: s (seconds) or m (minutes). -// e.g. "30s" → "30s", "0.5m" → "0.5m". Bare numbers without a unit are rejected. +// 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}". A unit is required — use seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m).` + `[gmgn-cli] Invalid duration "${value}". Use seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m).` ); process.exit(1); } From b83422769f10e29e995460f52b6997aaabfa9dff Mon Sep 17 00:00:00 2001 From: wuyanling Date: Wed, 22 Apr 2026 15:22:44 +0800 Subject: [PATCH 3/3] fix(trenches): remove 1h example from min/max-created desc, align with s/m only Co-Authored-By: Claude Sonnet 4.6 --- src/commands/market.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/market.ts b/src/commands/market.ts index c126b5f..7cede05 100644 --- a/src/commands/market.ts +++ b/src/commands/market.ts @@ -219,8 +219,8 @@ const TRENCHES_FILTER_FIELDS: TrenchesFilterField[] = [ { 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 required: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m / 1h)" }, - { api: "max_created", type: "duration", desc: "Max token age — unit required: seconds (e.g. 30s) or minutes (e.g. 0.5m / 1m / 5m / 30m / 1h)" }, + { 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" },