@tokenomist-ai/tokenomist-cli 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/token.ts","../src/api/errors.ts","../src/api/retry.ts","../src/api/cache.ts","../src/api/client.ts","../src/api/token.ts","../src/output/table.ts","../src/output/csv.ts","../src/output/formatter.ts","../src/config/config.ts","../src/config/store.ts","../src/commands/unlock.ts","../src/api/unlock.ts","../src/commands/investor.ts","../src/api/investor.ts","../src/commands/fundraising.ts","../src/api/fundraising.ts","../src/commands/burn.ts","../src/api/burn.ts","../src/commands/buyback.ts","../src/api/buyback.ts","../src/commands/emission.ts","../src/api/emission.ts","../src/commands/allocation.ts","../src/api/allocation.ts","../src/commands/auth.ts","../src/commands/schema.ts","../src/schema.json"],"sourcesContent":["import { Command } from \"commander\";\nimport { tokenCommand } from \"./commands/token.js\";\nimport { unlockCommand } from \"./commands/unlock.js\";\nimport { investorCommand } from \"./commands/investor.js\";\nimport { fundraisingCommand } from \"./commands/fundraising.js\";\nimport { burnCommand } from \"./commands/burn.js\";\nimport { buybackCommand } from \"./commands/buyback.js\";\nimport { emissionCommand } from \"./commands/emission.js\";\nimport { allocationCommand } from \"./commands/allocation.js\";\nimport { authCommand } from \"./commands/auth.js\";\nimport { schemaCommand } from \"./commands/schema.js\";\nimport { ApiError } from \"./api/errors.js\";\nimport { spawn } from \"node:child_process\";\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { fileURLToPath } from \"node:url\";\n\nconst ONE_DAY = 24 * 60 * 60 * 1000;\n\nfunction showUpdateNotification() {\n if (process.env.NO_UPDATE_NOTIFIER === \"1\" || process.env.CI === \"1\") return;\n try {\n const raw = readFileSync(join(homedir(), \".tokenomist\", \"update-check.json\"), \"utf-8\");\n const data = JSON.parse(raw);\n if (data.latest !== data.current && Date.now() - data.checkedAt < ONE_DAY) {\n process.stderr.write(\n `\\nUpdate available: ${data.current} → ${data.latest} (npm i -g @tokenomist-ai/tokenomist-cli)\\n\\n`,\n );\n }\n } catch {\n // No cache file or invalid — skip silently\n }\n}\n\nfunction spawnUpdateCheck() {\n if (process.env.NO_UPDATE_NOTIFIER === \"1\" || process.env.CI === \"1\") return;\n try {\n const script = fileURLToPath(new URL(\"./update-check.js\", import.meta.url));\n spawn(\"node\", [script], { detached: true, stdio: \"ignore\" }).unref();\n } catch {\n // Spawn failure — skip silently\n }\n}\n\nconst program = new Command();\n\nprogram\n .name(\"tokenomist\")\n .description(\n \"CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, and buybacks\",\n )\n .version(\"0.1.0\")\n .option(\"-k, --api-key <key>\", \"API key (overrides env/config)\")\n .option(\"-o, --output <format>\", \"Output format: table, json, csv\", \"table\")\n .option(\"--base-url <url>\", \"API base URL\")\n .option(\"--no-cache\", \"Bypass response cache\");\n\nprogram.addCommand(tokenCommand);\nprogram.addCommand(unlockCommand);\nprogram.addCommand(investorCommand);\nprogram.addCommand(fundraisingCommand);\nprogram.addCommand(burnCommand);\nprogram.addCommand(buybackCommand);\nprogram.addCommand(emissionCommand);\nprogram.addCommand(allocationCommand);\nprogram.addCommand(authCommand);\nprogram.addCommand(schemaCommand);\n\nshowUpdateNotification();\n\nprogram\n .parseAsync(process.argv)\n .then(() => {\n spawnUpdateCheck();\n })\n .catch((err) => {\n if (err instanceof ApiError) {\n if (err.retriesExhausted) {\n // Retry log lines already printed to stderr; just show detail if present\n if (err.detail) console.error(`Detail: ${err.detail}`);\n } else {\n console.error(`${err.code}: ${err.message}`);\n if (err.detail) console.error(`Detail: ${err.detail}`);\n }\n } else {\n console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);\n }\n spawnUpdateCheck();\n process.exit(1);\n });\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { listTokens, searchTokens } from \"../api/token.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst columns: Column[] = [\n { key: \"id\", header: \"ID\" },\n { key: \"name\", header: \"Name\" },\n { key: \"symbol\", header: \"Symbol\" },\n { key: \"marketCap\", header: \"Market Cap\", align: \"right\" },\n { key: \"circulatingSupply\", header: \"Circ. Supply\", align: \"right\" },\n { key: \"totalLockedAmount\", header: \"Locked\", align: \"right\" },\n { key: \"unlockedAmount\", header: \"Unlocked\", align: \"right\" },\n { key: \"lastUpdatedDate\", header: \"Updated\" },\n];\n\nconst searchColumns: Column[] = [\n { key: \"tokenId\", header: \"ID\" },\n { key: \"tokenName\", header: \"Name\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n];\n\nexport const tokenCommand = new Command(\"token\").description(\"Token commands\");\n\ntokenCommand\n .command(\"list\")\n .description(\"List all tokens with summary data\")\n .option(\"--token-id <ids>\", \"Filter by token IDs (comma-separated)\")\n .action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listTokens(client, {\n tokenId: opts.tokenId,\n });\n output(data as unknown as Record<string, unknown>[], columns, globalOpts.output || \"table\");\n });\n\ntokenCommand\n .command(\"search <query>\")\n .description(\"Search for tokens by name, symbol, or slug\")\n .action(async (query: string, _opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await searchTokens(client, query);\n output(data as unknown as Record<string, unknown>[], searchColumns, globalOpts.output || \"table\");\n });\n","export enum ErrorCode {\n UNAUTHORIZED = \"UNAUTHORIZED\",\n FORBIDDEN = \"FORBIDDEN\",\n NOT_FOUND = \"NOT_FOUND\",\n RATE_LIMITED = \"RATE_LIMITED\",\n SERVER_ERROR = \"SERVER_ERROR\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n UNKNOWN = \"UNKNOWN\",\n}\n\nfunction classifyStatus(status: number): ErrorCode {\n if (status === 401) return ErrorCode.UNAUTHORIZED;\n if (status === 403) return ErrorCode.FORBIDDEN;\n if (status === 404) return ErrorCode.NOT_FOUND;\n if (status === 429) return ErrorCode.RATE_LIMITED;\n if (status >= 500 && status < 600) return ErrorCode.SERVER_ERROR;\n return ErrorCode.UNKNOWN;\n}\n\nfunction parseRetryAfter(value?: string): number | undefined {\n if (!value) return undefined;\n const seconds = Number(value);\n return Number.isFinite(seconds) && seconds > 0 ? seconds : undefined;\n}\n\nexport class ApiError extends Error {\n public retriesExhausted = false;\n\n constructor(\n message: string,\n public code: ErrorCode,\n public detail?: string,\n public statusCode?: number,\n public retryAfter?: number,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n\n get retryable(): boolean {\n return (\n this.code === ErrorCode.RATE_LIMITED ||\n this.code === ErrorCode.SERVER_ERROR ||\n this.code === ErrorCode.NETWORK_ERROR\n );\n }\n\n static fromResponse(status: number, body: unknown, retryAfterHeader?: string): ApiError {\n const b = body && typeof body === \"object\" ? (body as Record<string, unknown>) : {};\n const errorMessage = typeof b.errorMessage === \"string\" ? b.errorMessage : undefined;\n const errorDetail = typeof b.errorDetail === \"string\" ? b.errorDetail : undefined;\n\n // API-level error: HTTP 200 but body.status === false\n if (status === 200 && b.status === false) {\n const bodyStatus = typeof b.statusCode === \"number\" ? b.statusCode : 0;\n const code = bodyStatus > 0 ? classifyStatus(bodyStatus) : ErrorCode.UNKNOWN;\n return new ApiError(\n errorMessage || \"API request failed\",\n code,\n errorDetail,\n bodyStatus || undefined,\n );\n }\n\n // HTTP-level error\n const code = classifyStatus(status);\n return new ApiError(\n errorMessage || `HTTP ${status}`,\n code,\n errorDetail,\n status,\n parseRetryAfter(retryAfterHeader),\n );\n }\n\n static fromNetworkError(error: unknown): ApiError {\n const message = error instanceof Error ? error.message : String(error);\n return new ApiError(message, ErrorCode.NETWORK_ERROR);\n }\n}\n","import { ApiError } from \"./errors.js\";\n\ninterface RetryOptions {\n maxAttempts?: number;\n baseDelay?: number;\n maxDelay?: number;\n}\n\nconst DEFAULTS = {\n maxAttempts: 3,\n baseDelay: 1000,\n maxDelay: 30_000,\n} as const;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> {\n const maxAttempts = options?.maxAttempts ?? DEFAULTS.maxAttempts;\n const baseDelay = options?.baseDelay ?? DEFAULTS.baseDelay;\n const maxDelay = options?.maxDelay ?? DEFAULTS.maxDelay;\n\n let lastError: ApiError | undefined;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (!(err instanceof ApiError) || !err.retryable) {\n throw err;\n }\n\n lastError = err;\n\n if (attempt === maxAttempts) {\n break;\n }\n\n const jitter = Math.random() * 500;\n const calculated = baseDelay * Math.pow(2, attempt - 1) + jitter;\n const delay = err.retryAfter\n ? Math.min(err.retryAfter * 1000, maxDelay)\n : Math.min(calculated, maxDelay);\n\n process.stderr.write(\n `${err.code}: ${err.message}. Retrying in ${Math.round(delay / 1000)}s... (attempt ${attempt + 1}/${maxAttempts})\\n`,\n );\n\n await sleep(delay);\n }\n }\n\n lastError!.retriesExhausted = true;\n throw lastError;\n}\n","import { createHash } from \"node:crypto\";\nimport { readFileSync, writeFileSync, mkdirSync, unlinkSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\ninterface CacheEntry {\n url: string;\n timestamp: number;\n ttl: number;\n data: unknown;\n}\n\nconst DEFAULT_CACHE_DIR = join(homedir(), \".tokenomist\", \"cache\");\nconst MAX_CACHE_FILES = 500;\n\nexport class ResponseCache {\n private writeCount = 0;\n\n constructor(\n private ttl: number = 600_000,\n private cacheDir: string = DEFAULT_CACHE_DIR,\n ) {}\n\n buildKey(url: string, apiKey?: string): string {\n const parsed = new URL(url);\n parsed.searchParams.sort();\n const prefix = apiKey ? createHash(\"md5\").update(apiKey).digest(\"hex\").slice(0, 8) : \"\";\n const normalized = `${prefix}:GET:${parsed.toString()}`;\n return createHash(\"md5\").update(normalized).digest(\"hex\");\n }\n\n get<T>(key: string): T | null {\n try {\n const filePath = join(this.cacheDir, `${key}.json`);\n const raw = readFileSync(filePath, \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry;\n\n if (Date.now() - entry.timestamp > entry.ttl) {\n try {\n unlinkSync(filePath);\n } catch {\n /* ignore */\n }\n return null;\n }\n\n return entry.data as T;\n } catch {\n return null;\n }\n }\n\n set(key: string, url: string, data: unknown): void {\n try {\n mkdirSync(this.cacheDir, { recursive: true, mode: 0o700 });\n const entry: CacheEntry = {\n url,\n timestamp: Date.now(),\n ttl: this.ttl,\n data,\n };\n const filePath = join(this.cacheDir, `${key}.json`);\n writeFileSync(filePath, JSON.stringify(entry), { encoding: \"utf-8\", mode: 0o600 });\n\n this.writeCount++;\n if (this.writeCount % 20 === 0) this.sweep();\n } catch {\n // Cache is best-effort — silently ignore write failures\n }\n }\n\n private sweep(): void {\n try {\n const files = readdirSync(this.cacheDir).filter((f) => f.endsWith(\".json\"));\n\n // Remove expired entries\n const now = Date.now();\n for (const file of files) {\n try {\n const filePath = join(this.cacheDir, file);\n const raw = readFileSync(filePath, \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry;\n if (now - entry.timestamp > entry.ttl) {\n unlinkSync(filePath);\n }\n } catch {\n /* ignore individual file errors */\n }\n }\n\n // If still over limit, remove oldest entries\n const remaining = readdirSync(this.cacheDir).filter((f) => f.endsWith(\".json\"));\n if (remaining.length > MAX_CACHE_FILES) {\n const entries = remaining.map((file) => {\n try {\n const filePath = join(this.cacheDir, file);\n const raw = readFileSync(filePath, \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry;\n return { file, timestamp: entry.timestamp };\n } catch {\n return { file, timestamp: 0 };\n }\n });\n entries.sort((a, b) => a.timestamp - b.timestamp);\n const toRemove = entries.slice(0, entries.length - MAX_CACHE_FILES);\n for (const { file } of toRemove) {\n try {\n unlinkSync(join(this.cacheDir, file));\n } catch {\n /* ignore */\n }\n }\n }\n } catch {\n /* sweep is best-effort */\n }\n }\n}\n","import type { ApiResponse } from \"../types/response.js\";\nimport { ApiError } from \"./errors.js\";\nimport { withRetry } from \"./retry.js\";\nimport { ResponseCache } from \"./cache.js\";\n\nexport { ApiError } from \"./errors.js\";\n\nconst HEADER_API_KEY = \"x-api-key\";\nconst HEADER_CLIENT_SOURCE = \"x-client-source\";\nconst CLIENT_SOURCE_CLI = \"cli\";\n\nexport class TokenomistClient {\n private cache: ResponseCache;\n\n constructor(\n private apiKey: string,\n private baseUrl: string,\n private options?: { noCache?: boolean },\n ) {\n this.cache = new ResponseCache();\n }\n\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = this.buildUrl(path, params);\n const urlStr = url.toString();\n const cacheKey = this.cache.buildKey(urlStr, this.apiKey);\n const useCache = this.options?.noCache !== true;\n\n if (useCache) {\n const cached = this.cache.get<T>(cacheKey);\n if (cached) return cached;\n }\n\n const data = await withRetry(() => this.fetchFromApi<T>(url));\n\n if (useCache) {\n this.cache.set(cacheKey, urlStr, data);\n }\n\n return data;\n }\n\n private buildUrl(path: string, params?: Record<string, string>): URL {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== \"\") {\n url.searchParams.set(key, value);\n }\n }\n }\n return url;\n }\n\n private async fetchFromApi<T>(url: URL): Promise<T> {\n let res: Response;\n try {\n res = await fetch(url.toString(), {\n headers: {\n [HEADER_API_KEY]: this.apiKey,\n [HEADER_CLIENT_SOURCE]: CLIENT_SOURCE_CLI,\n },\n });\n } catch (err) {\n throw ApiError.fromNetworkError(err);\n }\n\n if (!res.ok) {\n let body: unknown = {};\n try {\n body = await res.json();\n } catch {\n // Response may not be JSON\n }\n const retryAfter = res.headers.get(\"retry-after\") ?? undefined;\n throw ApiError.fromResponse(res.status, body, retryAfter);\n }\n\n const body = (await res.json()) as ApiResponse<T>;\n\n if (!body.status) {\n throw ApiError.fromResponse(200, body);\n }\n\n return body.data as T;\n }\n}\n","import type { TokenomistClient } from \"./client.js\";\nimport type { TokenV4, SearchTokenV5 } from \"../types/token.js\";\n\nexport async function listTokens(\n client: TokenomistClient,\n params?: { tokenId?: string },\n): Promise<TokenV4[]> {\n return client.get<TokenV4[]>(\"/v5/token/list\", params as Record<string, string>);\n}\n\nexport async function searchTokens(\n client: TokenomistClient,\n query: string,\n): Promise<SearchTokenV5[]> {\n return client.get<SearchTokenV5[]>(\"/v5/search-token\", { query });\n}\n","import Table from \"cli-table3\";\n\nexport interface Column {\n key: string;\n header: string;\n align?: \"left\" | \"right\" | \"center\";\n}\n\nexport function renderTable(data: Record<string, unknown>[], columns: Column[]): string {\n const table = new Table({\n head: columns.map((c) => c.header),\n style: { head: [\"cyan\"] },\n colAligns: columns.map((c) => c.align || \"left\"),\n });\n\n for (const row of data) {\n table.push(columns.map((c) => formatValue(row[c.key])));\n }\n\n return table.toString();\n}\n\nfunction formatValue(value: unknown): string {\n if (value === null || value === undefined) return \"\\u2014\";\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) return value.toLocaleString();\n return value.toLocaleString(undefined, { maximumFractionDigits: 4 });\n }\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n if (Array.isArray(value)) return value.join(\", \");\n return String(value);\n}\n","import type { Column } from \"./table.js\";\n\nexport function renderCsv(data: Record<string, unknown>[], columns: Column[]): string {\n const header = columns.map((c) => escapeCsv(c.header)).join(\",\");\n const rows = data.map((row) =>\n columns.map((c) => escapeCsv(formatCsvValue(row[c.key]))).join(\",\"),\n );\n return [header, ...rows].join(\"\\n\");\n}\n\nfunction escapeCsv(value: string): string {\n if (value.includes(\",\") || value.includes('\"') || value.includes(\"\\n\")) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\nfunction formatCsvValue(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (Array.isArray(value)) return value.join(\"; \");\n return String(value);\n}\n","import type { Column } from \"./table.js\";\nimport { renderTable } from \"./table.js\";\nimport { renderCsv } from \"./csv.js\";\n\nexport type OutputMode = \"table\" | \"json\" | \"csv\";\n\nexport function format(\n data: Record<string, unknown>[],\n columns: Column[],\n mode: OutputMode,\n): string {\n switch (mode) {\n case \"json\":\n return JSON.stringify(data, null, 2);\n case \"csv\":\n return renderCsv(data, columns);\n case \"table\":\n default:\n return renderTable(data, columns);\n }\n}\n\nexport function output(data: Record<string, unknown>[], columns: Column[], mode: OutputMode): void {\n console.log(format(data, columns, mode));\n}\n","import { config as loadDotenv } from \"dotenv\";\nimport { loadConfigFile } from \"./store.js\";\n\nloadDotenv();\n\nexport interface Config {\n apiKey: string;\n baseUrl: string;\n noCache: boolean;\n}\n\nexport function resolveConfig(opts: {\n apiKey?: string;\n baseUrl?: string;\n cache?: boolean;\n}): Config {\n const file = loadConfigFile();\n\n const apiKey = opts.apiKey || process.env.TOKENOMIST_API_KEY || file.apiKey || \"\";\n const baseUrl =\n opts.baseUrl || process.env.TOKENOMIST_BASE_URL || file.baseUrl || \"https://api.tokenomist.ai\";\n\n if (!apiKey) {\n console.error(\n 'Error: API key is required. Run \"tokenomist auth login\" or provide via --api-key / TOKENOMIST_API_KEY env var.',\n );\n process.exit(1);\n }\n\n return { apiKey, baseUrl, noCache: opts.cache === false };\n}\n","import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst CONFIG_DIR = join(homedir(), \".tokenomist\");\nconst CONFIG_PATH = join(CONFIG_DIR, \"config.json\");\n\nexport interface ConfigFile {\n apiKey?: string;\n baseUrl?: string;\n}\n\nexport function getConfigPath(): string {\n return CONFIG_PATH;\n}\n\nexport function loadConfigFile(): ConfigFile {\n try {\n const raw = readFileSync(CONFIG_PATH, \"utf-8\");\n return JSON.parse(raw) as ConfigFile;\n } catch {\n return {};\n }\n}\n\nexport function saveConfigFile(config: ConfigFile): void {\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\", {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n}\n\nexport function deleteConfigFile(): void {\n try {\n unlinkSync(CONFIG_PATH);\n } catch {\n // file doesn't exist, that's fine\n }\n}\n\nexport function maskApiKey(key: string): string {\n if (key.length <= 8) return \"****\";\n return key.slice(0, 4) + \"****\" + key.slice(-4);\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { listUnlockEvents, listUpcomingUnlockEvents, getUnlockEvents } from \"../api/unlock.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst listColumns: Column[] = [\n { key: \"tokenName\", header: \"Token\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"marketCap\", header: \"Market Cap\", align: \"right\" },\n { key: \"releasedPercentage\", header: \"Released %\", align: \"right\" },\n { key: \"eventCount\", header: \"Events\", align: \"right\" },\n];\n\nconst upcomingColumns: Column[] = [\n { key: \"tokenName\", header: \"Token\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"marketCap\", header: \"Market Cap\", align: \"right\" },\n { key: \"unlockDate\", header: \"Unlock Date\" },\n { key: \"totalCliffAmount\", header: \"Cliff Amount\", align: \"right\" },\n { key: \"totalCliffValue\", header: \"Cliff Value\", align: \"right\" },\n];\n\nconst eventsColumns: Column[] = [\n { key: \"unlockDate\", header: \"Date\" },\n { key: \"tokenName\", header: \"Token\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"cliffAmount\", header: \"Amount\", align: \"right\" },\n { key: \"cliffValue\", header: \"Value\", align: \"right\" },\n { key: \"valueToMarketCap\", header: \"Val/MCap\", align: \"right\" },\n];\n\nfunction addPaginationOptions(cmd: Command): Command {\n return cmd\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\");\n}\n\nfunction addListFilterOptions(cmd: Command): Command {\n return addPaginationOptions(\n cmd\n .option(\"--min-market-cap <value>\", \"Minimum market cap\")\n .option(\"--min-released-percentage <value>\", \"Minimum released percentage\")\n .option(\"--min-unlock-date <date>\", \"Min unlock date (YYYY-MM-DD)\")\n .option(\"--max-unlock-date <date>\", \"Max unlock date (YYYY-MM-DD)\")\n .option(\"--min-total-unlock-amount <value>\", \"Minimum total unlock amount\")\n .option(\"--min-value-to-market-cap <value>\", \"Min value-to-market-cap ratio\")\n .option(\"--standard-allocation <names>\", \"Filter by allocation (comma-separated)\"),\n );\n}\n\nfunction addUpcomingFilterOptions(cmd: Command): Command {\n return addPaginationOptions(\n cmd\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .option(\"--standard-allocation <names>\", \"Filter by allocation (comma-separated)\")\n .option(\"--min-market-cap <value>\", \"Minimum market cap\")\n .option(\"--min-released-percentage <value>\", \"Minimum released percentage\")\n .option(\"--min-total-unlock-amount <value>\", \"Minimum total unlock amount\")\n .option(\"--min-value-to-market-cap <value>\", \"Min value-to-market-cap ratio\"),\n );\n}\n\nexport const unlockCommand = new Command(\"unlock\").description(\"Token unlock event commands\");\n\naddListFilterOptions(\n unlockCommand.command(\"list\").description(\"List unlock events grouped by token\"),\n).action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listUnlockEvents(client, {\n minMarketCap: opts.minMarketCap,\n minReleasedPercentage: opts.minReleasedPercentage,\n minUnlockDate: opts.minUnlockDate,\n maxUnlockDate: opts.maxUnlockDate,\n minTotalUnlockAmount: opts.minTotalUnlockAmount,\n minValueToMarketCap: opts.minValueToMarketCap,\n standardAllocation: opts.standardAllocation,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n const rows = data.map((d) => ({\n ...d,\n eventCount: d.events.length,\n }));\n output(rows as unknown as Record<string, unknown>[], listColumns, globalOpts.output || \"table\");\n});\n\naddUpcomingFilterOptions(\n unlockCommand.command(\"upcoming\").description(\"List next upcoming unlock event per token\"),\n).action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listUpcomingUnlockEvents(client, {\n start: opts.start,\n end: opts.end,\n standardAllocation: opts.standardAllocation,\n minMarketCap: opts.minMarketCap,\n minReleasedPercentage: opts.minReleasedPercentage,\n minTotalUnlockAmount: opts.minTotalUnlockAmount,\n minValueToMarketCap: opts.minValueToMarketCap,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n const rows = data.map((d) => ({\n ...d,\n unlockDate: d.upcomingEvent.unlockDate,\n totalCliffAmount: d.upcomingEvent.cliffUnlocks.totalCliffAmount,\n totalCliffValue: d.upcomingEvent.cliffUnlocks.totalCliffValue,\n }));\n output(\n rows as unknown as Record<string, unknown>[],\n upcomingColumns,\n globalOpts.output || \"table\",\n );\n});\n\naddPaginationOptions(\n unlockCommand\n .command(\"events <tokenSlug>\")\n .description(\"Get unlock events for a specific token\")\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .option(\"--standard-allocation <names>\", \"Filter by allocation (comma-separated)\"),\n).action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getUnlockEvents(client, tokenSlug, {\n start: opts.start,\n end: opts.end,\n standardAllocation: opts.standardAllocation,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n const rows = data.map((d) => ({\n ...d,\n cliffAmount: d.cliffUnlocks.cliffAmount,\n cliffValue: d.cliffUnlocks.cliffValue,\n valueToMarketCap: d.cliffUnlocks.valueToMarketCap,\n }));\n output(\n rows as unknown as Record<string, unknown>[],\n eventsColumns,\n globalOpts.output || \"table\",\n );\n});\n","import type { TokenomistClient } from \"./client.js\";\nimport type { UnlockEventList, UnlockEventListUpcoming, UnlockEventV4 } from \"../types/unlock.js\";\n\nexport interface UnlockListParams {\n minMarketCap?: string;\n minReleasedPercentage?: string;\n minUnlockDate?: string;\n maxUnlockDate?: string;\n minTotalUnlockAmount?: string;\n minValueToMarketCap?: string;\n standardAllocation?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport interface UnlockUpcomingParams {\n start?: string;\n end?: string;\n standardAllocation?: string;\n minMarketCap?: string;\n minReleasedPercentage?: string;\n minTotalUnlockAmount?: string;\n minValueToMarketCap?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport interface UnlockEventsParams {\n standardAllocation?: string;\n start?: string;\n end?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport async function listUnlockEvents(\n client: TokenomistClient,\n params?: UnlockListParams,\n): Promise<UnlockEventList[]> {\n return client.get<UnlockEventList[]>(\"/v5/unlock/events/list\", params as Record<string, string>);\n}\n\nexport async function listUpcomingUnlockEvents(\n client: TokenomistClient,\n params?: UnlockUpcomingParams,\n): Promise<UnlockEventListUpcoming[]> {\n return client.get<UnlockEventListUpcoming[]>(\n \"/v5/unlock/events/upcoming\",\n params as Record<string, string>,\n );\n}\n\nexport async function getUnlockEvents(\n client: TokenomistClient,\n tokenSlug: string,\n params?: UnlockEventsParams,\n): Promise<UnlockEventV4[]> {\n return client.get<UnlockEventV4[]>(\n `/v5/unlock/events/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { listInvestors, getInvestorDetail } from \"../api/investor.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst listColumns: Column[] = [\n { key: \"investorId\", header: \"ID\" },\n { key: \"investorName\", header: \"Name\" },\n { key: \"website\", header: \"Website\" },\n { key: \"latestFundingDate\", header: \"Latest Funding\" },\n { key: \"latestFundingRound\", header: \"Latest Round\" },\n { key: \"roundCount\", header: \"Rounds\", align: \"right\" },\n];\n\nconst detailColumns: Column[] = [\n { key: \"tokenId\", header: \"Token ID\" },\n { key: \"roundName\", header: \"Round\" },\n { key: \"isLeadInvestor\", header: \"Lead?\" },\n { key: \"fundingDate\", header: \"Date\" },\n { key: \"totalAmountRaisedinThatRound\", header: \"Raised\", align: \"right\" },\n { key: \"valuation\", header: \"Valuation\", align: \"right\" },\n { key: \"pricePerToken\", header: \"Price/Token\", align: \"right\" },\n];\n\nexport const investorCommand = new Command(\"investor\").description(\"Investor commands\");\n\ninvestorCommand\n .command(\"list\")\n .description(\"List all investors with their funding rounds\")\n .option(\"--start-latest-funding-date <date>\", \"Start date filter for latest funding (YYYY-MM-DD)\")\n .option(\"--end-latest-funding-date <date>\", \"End date filter for latest funding (YYYY-MM-DD)\")\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\")\n .action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listInvestors(client, {\n startLatestFundingDate: opts.startLatestFundingDate,\n endLatestFundingDate: opts.endLatestFundingDate,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n const rows = data.map((d) => ({\n ...d,\n roundCount: d.fundingRounds?.length || 0,\n }));\n output(rows as unknown as Record<string, unknown>[], listColumns, globalOpts.output || \"table\");\n });\n\ninvestorCommand\n .command(\"detail <investorId>\")\n .description(\"Get investor detail with funding rounds\")\n .option(\"--is-lead-investor\", \"Filter by lead investor status\")\n .option(\"--funding-date-min <date>\", \"Min funding date (YYYY-MM-DD)\")\n .option(\"--funding-date-max <date>\", \"Max funding date (YYYY-MM-DD)\")\n .option(\"--raised-amount-min <value>\", \"Min raised amount\")\n .option(\"--raised-amount-max <value>\", \"Max raised amount\")\n .action(async (investorId: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getInvestorDetail(client, investorId, {\n isLeadInvestor: opts.isLeadInvestor ? \"true\" : undefined,\n fundingDateMin: opts.fundingDateMin,\n fundingDateMax: opts.fundingDateMax,\n raisedAmountMin: opts.raisedAmountMin,\n raisedAmountMax: opts.raisedAmountMax,\n });\n const outputMode = globalOpts.output || \"table\";\n if (outputMode === \"json\") {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(`Investor: ${data.investorName}`);\n console.log(`Website: ${data.website}`);\n console.log(`Latest Funding: ${data.latestFundingDate}`);\n console.log();\n output(data.fundingRounds as unknown as Record<string, unknown>[], detailColumns, outputMode);\n }\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { FundraisingInvestors, FundraisingInvestorsAggregated } from \"../types/investor.js\";\n\nexport interface InvestorListParams {\n startLatestFundingDate?: string;\n endLatestFundingDate?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport async function listInvestors(\n client: TokenomistClient,\n params?: InvestorListParams,\n): Promise<FundraisingInvestors[]> {\n return client.get<FundraisingInvestors[]>(\n \"/v5/fundraising/investors/list\",\n params as Record<string, string>,\n );\n}\n\nexport interface InvestorDetailParams {\n isLeadInvestor?: string;\n fundingDateMin?: string;\n fundingDateMax?: string;\n raisedAmountMin?: string;\n raisedAmountMax?: string;\n}\n\nexport async function getInvestorDetail(\n client: TokenomistClient,\n investorId: string,\n params?: InvestorDetailParams,\n): Promise<FundraisingInvestorsAggregated> {\n return client.get<FundraisingInvestorsAggregated>(\n `/v5/fundraising/investors/${encodeURIComponent(investorId)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { getFundraising } from \"../api/fundraising.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst columns: Column[] = [\n { key: \"fundingRound\", header: \"Round\" },\n { key: \"fundingDate\", header: \"Date\" },\n { key: \"raiseType\", header: \"Type\" },\n { key: \"amountRaised\", header: \"Raised\", align: \"right\" },\n { key: \"valuation\", header: \"Valuation\", align: \"right\" },\n { key: \"pricePerToken\", header: \"Price/Token\", align: \"right\" },\n { key: \"numberOfInvestors\", header: \"Investors\", align: \"right\" },\n];\n\nexport const fundraisingCommand = new Command(\"fundraising\")\n .description(\"Get fundraising data for a token\")\n .argument(\"<tokenSlug>\", \"Token slug\")\n .option(\"--funding-date-min <date>\", \"Min funding date (YYYY-MM-DD)\")\n .option(\"--funding-date-max <date>\", \"Max funding date (YYYY-MM-DD)\")\n .option(\"--raised-amount-min <value>\", \"Min raised amount\")\n .option(\"--raised-amount-max <value>\", \"Max raised amount\")\n .action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getFundraising(client, tokenSlug, {\n fundingDateMin: opts.fundingDateMin,\n fundingDateMax: opts.fundingDateMax,\n raisedAmountMin: opts.raisedAmountMin,\n raisedAmountMax: opts.raisedAmountMax,\n });\n const outputMode = globalOpts.output || \"table\";\n if (outputMode === \"json\") {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(`Token: ${data.tokenName} (${data.tokenSymbol})`);\n console.log(`Total Raised: ${data.totalAmountRaised ?? \"\\u2014\"}`);\n console.log(`Investor Released: ${data.investorReleasedPercentage ?? \"\\u2014\"}%`);\n console.log();\n output(data.fundingRounds as unknown as Record<string, unknown>[], columns, outputMode);\n }\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { FundraisingToken } from \"../types/fundraising.js\";\n\nexport interface FundraisingParams {\n fundingDateMin?: string;\n fundingDateMax?: string;\n raisedAmountMin?: string;\n raisedAmountMax?: string;\n}\n\nexport async function getFundraising(\n client: TokenomistClient,\n tokenSlug: string,\n params?: FundraisingParams,\n): Promise<FundraisingToken> {\n return client.get<FundraisingToken>(\n `/v5/fundraising/token/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { listBurns, getBurnDetail } from \"../api/burn.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst listColumns: Column[] = [\n { key: \"tokenId\", header: \"ID\" },\n { key: \"tokenName\", header: \"Name\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"totalBurnAmount\", header: \"Total Burned\", align: \"right\" },\n];\n\nconst detailColumns: Column[] = [\n { key: \"burnEventLabel\", header: \"Label\" },\n { key: \"burnType\", header: \"Type\" },\n { key: \"burnDate\", header: \"Date\" },\n { key: \"amount\", header: \"Amount\", align: \"right\" },\n];\n\nexport const burnCommand = new Command(\"burn\").description(\"Token burn commands\");\n\nburnCommand\n .command(\"list\")\n .description(\"List all tokens with burn events\")\n .option(\"--token-id <ids>\", \"Filter by token IDs (comma-separated)\")\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\")\n .action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listBurns(client, {\n tokenId: opts.tokenId,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n output(data as unknown as Record<string, unknown>[], listColumns, globalOpts.output || \"table\");\n });\n\nburnCommand\n .command(\"detail <tokenSlug>\")\n .description(\"Get burn events for a specific token\")\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getBurnDetail(client, tokenSlug, {\n start: opts.start,\n end: opts.end,\n });\n const outputMode = globalOpts.output || \"table\";\n if (outputMode === \"json\") {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(`Token: ${data.tokenName} (${data.tokenSymbol})`);\n console.log(`Total Burned: ${data.totalBurnAmount.toLocaleString()}`);\n console.log();\n output(data.burns as unknown as Record<string, unknown>[], detailColumns, outputMode);\n }\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { BurnTokenList, BurnToken } from \"../types/burn.js\";\n\nexport interface BurnListParams {\n tokenId?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport async function listBurns(\n client: TokenomistClient,\n params?: BurnListParams,\n): Promise<BurnTokenList[]> {\n return client.get<BurnTokenList[]>(\"/v5/burn/list\", params as Record<string, string>);\n}\n\nexport async function getBurnDetail(\n client: TokenomistClient,\n tokenSlug: string,\n params?: { start?: string; end?: string },\n): Promise<BurnToken> {\n return client.get<BurnToken>(\n `/v5/burn/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { listBuybacks, getBuybackDetail } from \"../api/buyback.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst listColumns: Column[] = [\n { key: \"tokenId\", header: \"ID\" },\n { key: \"tokenName\", header: \"Name\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"totalBuybackAmount\", header: \"Total Buyback\", align: \"right\" },\n];\n\nconst detailColumns: Column[] = [\n { key: \"buybackEventLabel\", header: \"Label\" },\n { key: \"buybackType\", header: \"Type\" },\n { key: \"buybackDate\", header: \"Date\" },\n { key: \"tokenAmount\", header: \"Amount\", align: \"right\" },\n { key: \"value\", header: \"Value\", align: \"right\" },\n { key: \"spentAmount\", header: \"Spent\", align: \"right\" },\n { key: \"spentUnit\", header: \"Unit\" },\n];\n\nexport const buybackCommand = new Command(\"buyback\").description(\"Token buyback commands\");\n\nbuybackCommand\n .command(\"list\")\n .description(\"List all tokens with buyback events\")\n .option(\"--token-id <ids>\", \"Filter by token IDs (comma-separated)\")\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\")\n .action(async (opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await listBuybacks(client, {\n tokenId: opts.tokenId,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n output(data as unknown as Record<string, unknown>[], listColumns, globalOpts.output || \"table\");\n });\n\nbuybackCommand\n .command(\"detail <tokenSlug>\")\n .description(\"Get buyback events for a specific token\")\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getBuybackDetail(client, tokenSlug, {\n start: opts.start,\n end: opts.end,\n });\n const outputMode = globalOpts.output || \"table\";\n if (outputMode === \"json\") {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(`Token: ${data.tokenName} (${data.tokenSymbol})`);\n console.log(`Total Buyback: ${data.totalBuybackAmount.toLocaleString()}`);\n console.log();\n output(data.buybacks as unknown as Record<string, unknown>[], detailColumns, outputMode);\n }\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { BuybackTokenList, BuybackToken } from \"../types/buyback.js\";\n\nexport interface BuybackListParams {\n tokenId?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport async function listBuybacks(\n client: TokenomistClient,\n params?: BuybackListParams,\n): Promise<BuybackTokenList[]> {\n return client.get<BuybackTokenList[]>(\"/v5/buyback/list\", params as Record<string, string>);\n}\n\nexport async function getBuybackDetail(\n client: TokenomistClient,\n tokenSlug: string,\n params?: { start?: string; end?: string },\n): Promise<BuybackToken> {\n return client.get<BuybackToken>(\n `/v5/buyback/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { getDailyEmission, getWeeklyEmission } from \"../api/emission.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst columns: Column[] = [\n { key: \"startDate\", header: \"Start\" },\n { key: \"endDate\", header: \"End\" },\n { key: \"tokenName\", header: \"Token\" },\n { key: \"tokenSymbol\", header: \"Symbol\" },\n { key: \"unlockAmount\", header: \"Unlock Amt\", align: \"right\" },\n { key: \"unlockValue\", header: \"Unlock Val\", align: \"right\" },\n { key: \"referencePrice\", header: \"Ref Price\", align: \"right\" },\n { key: \"totalCumulativeUnlockedAmount\", header: \"Cumulative\", align: \"right\" },\n];\n\nexport const emissionCommand = new Command(\"emission\").description(\"Token emission commands\");\n\nemissionCommand\n .command(\"daily <tokenSlug>\")\n .description(\"Get daily emission breakdown for a token\")\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .option(\"--standard-allocation <names>\", \"Filter by allocation (comma-separated)\")\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\")\n .action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getDailyEmission(client, tokenSlug, {\n start: opts.start,\n end: opts.end,\n standardAllocation: opts.standardAllocation,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n output(data as unknown as Record<string, unknown>[], columns, globalOpts.output || \"table\");\n });\n\nemissionCommand\n .command(\"weekly <tokenSlug>\")\n .description(\"Get weekly emission breakdown for a token\")\n .option(\"--start <date>\", \"Start date (YYYY-MM-DD)\")\n .option(\"--end <date>\", \"End date (YYYY-MM-DD)\")\n .option(\"--standard-allocation <names>\", \"Filter by allocation (comma-separated)\")\n .option(\"--page <number>\", \"Page number\")\n .option(\"--page-size <number>\", \"Items per page\")\n .action(async (tokenSlug: string, opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getWeeklyEmission(client, tokenSlug, {\n start: opts.start,\n end: opts.end,\n standardAllocation: opts.standardAllocation,\n page: opts.page,\n pageSize: opts.pageSize,\n });\n output(data as unknown as Record<string, unknown>[], columns, globalOpts.output || \"table\");\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { EmissionBreakdown } from \"../types/emission.js\";\n\nexport interface EmissionParams {\n standardAllocation?: string;\n start?: string;\n end?: string;\n page?: string;\n pageSize?: string;\n}\n\nexport async function getDailyEmission(\n client: TokenomistClient,\n tokenSlug: string,\n params?: EmissionParams,\n): Promise<EmissionBreakdown[]> {\n return client.get<EmissionBreakdown[]>(\n `/v5/daily-emission/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n\nexport async function getWeeklyEmission(\n client: TokenomistClient,\n tokenSlug: string,\n params?: EmissionParams,\n): Promise<EmissionBreakdown[]> {\n return client.get<EmissionBreakdown[]>(\n `/v5/emission/${encodeURIComponent(tokenSlug)}`,\n params as Record<string, string>,\n );\n}\n","import { Command } from \"commander\";\nimport { TokenomistClient } from \"../api/client.js\";\nimport { getAllocation } from \"../api/allocation.js\";\nimport { output } from \"../output/formatter.js\";\nimport type { Column } from \"../output/table.js\";\nimport { resolveConfig } from \"../config/config.js\";\n\nconst columns: Column[] = [\n { key: \"allocationName\", header: \"Allocation\" },\n { key: \"allocationType\", header: \"Type\" },\n { key: \"standardAllocationName\", header: \"Std. Allocation\" },\n { key: \"allocationAmount\", header: \"Amount\", align: \"right\" },\n { key: \"allocationUnlockedAmount\", header: \"Unlocked\", align: \"right\" },\n { key: \"allocationLockedAmount\", header: \"Locked\", align: \"right\" },\n { key: \"trackedAllocationPercentage\", header: \"Tracked %\", align: \"right\" },\n];\n\nexport const allocationCommand = new Command(\"allocation\")\n .description(\"Get standard allocation data for a token\")\n .argument(\"<tokenSlug>\", \"Token slug\")\n .action(async (tokenSlug: string, _opts, cmd) => {\n const globalOpts = cmd.optsWithGlobals();\n const config = resolveConfig(globalOpts);\n const client = new TokenomistClient(config.apiKey, config.baseUrl, {\n noCache: config.noCache,\n });\n const data = await getAllocation(client, tokenSlug);\n const outputMode = globalOpts.output || \"table\";\n if (outputMode === \"json\") {\n console.log(JSON.stringify(data, null, 2));\n } else {\n console.log(`Token: ${data.name} (${data.symbol})`);\n console.log(`Max Supply: ${data.maxSupply?.toLocaleString() ?? \"\\u2014\"}`);\n console.log(`Total Unlocked: ${data.totalUnlockedAmount.toLocaleString()}`);\n console.log(`Total Locked: ${data.totalLockedAmount.toLocaleString()}`);\n console.log(`Last Updated: ${data.lastUpdatedDate}`);\n console.log();\n output(data.allocations as unknown as Record<string, unknown>[], columns, outputMode);\n }\n });\n","import type { TokenomistClient } from \"./client.js\";\nimport type { StandardAllocation } from \"../types/allocation.js\";\n\nexport async function getAllocation(\n client: TokenomistClient,\n tokenSlug: string,\n): Promise<StandardAllocation> {\n return client.get<StandardAllocation>(\n `/v5/allocations/${encodeURIComponent(tokenSlug)}`,\n );\n}\n","import { Command } from \"commander\";\nimport { createInterface } from \"node:readline\";\nimport {\n loadConfigFile,\n saveConfigFile,\n deleteConfigFile,\n maskApiKey,\n getConfigPath,\n} from \"../config/store.js\";\n\nfunction readInput(prompt: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stderr });\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport const authCommand = new Command(\"auth\").description(\"Manage API key authentication\");\n\nauthCommand\n .command(\"login\")\n .description(\"Store your API key securely in ~/.tokenomist/config.json\")\n .option(\"--api-key <key>\", \"API key (will prompt if not provided)\")\n .action(async (opts) => {\n let apiKey = opts.apiKey;\n\n if (!apiKey) {\n apiKey = await readInput(\"Enter your Tokenomist API key: \");\n }\n\n if (!apiKey) {\n console.error(\"Error: API key cannot be empty.\");\n process.exit(1);\n }\n\n const config = loadConfigFile();\n config.apiKey = apiKey;\n saveConfigFile(config);\n\n console.log(`API key saved to ${getConfigPath()}`);\n console.log(`Key: ${maskApiKey(apiKey)}`);\n });\n\nauthCommand\n .command(\"logout\")\n .description(\"Remove stored API key\")\n .action(() => {\n const config = loadConfigFile();\n if (!config.apiKey) {\n console.log(\"No API key stored.\");\n return;\n }\n\n delete config.apiKey;\n\n if (Object.keys(config).length === 0) {\n deleteConfigFile();\n console.log(`Removed ${getConfigPath()}`);\n } else {\n saveConfigFile(config);\n console.log(\"API key removed from config.\");\n }\n });\n\nauthCommand\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(() => {\n const envKey = process.env.TOKENOMIST_API_KEY;\n const config = loadConfigFile();\n const fileKey = config.apiKey;\n\n if (envKey) {\n console.log(`Source: TOKENOMIST_API_KEY env var`);\n console.log(`Key: ${maskApiKey(envKey)}`);\n } else if (fileKey) {\n console.log(`Source: ${getConfigPath()}`);\n console.log(`Key: ${maskApiKey(fileKey)}`);\n } else {\n console.log(\"Not authenticated.\");\n console.log(`Run \"tokenomist auth login\" to store your API key.`);\n }\n });\n","import { Command } from \"commander\";\nimport schema from \"../schema.json\" with { type: \"json\" };\n\nexport const schemaCommand = new Command(\"schema\")\n .description(\"Print full command schema as JSON\")\n .option(\"--pretty\", \"Pretty-print with 2-space indent\")\n .action((opts) => {\n const indent = opts.pretty ? 2 : undefined;\n console.log(JSON.stringify(schema, null, indent));\n });\n","{\n \"name\": \"tokenomist\",\n \"version\": \"0.1.0\",\n \"description\": \"CLI tool for the Tokenomist API\",\n \"globalOptions\": {\n \"api-key\": { \"flags\": \"-k, --api-key <key>\", \"description\": \"API key (overrides env/config)\" },\n \"output\": { \"flags\": \"-o, --output <format>\", \"description\": \"Output format: table, json, csv\", \"default\": \"table\" },\n \"base-url\": { \"flags\": \"--base-url <url>\", \"description\": \"API base URL\" },\n \"no-cache\": { \"flags\": \"--no-cache\", \"description\": \"Bypass response cache\" }\n },\n \"commands\": {\n \"token list\": {\n \"description\": \"List all tracked tokens with market data\",\n \"options\": {\n \"token-id\": { \"flags\": \"--token-id <ids>\", \"description\": \"Filter by token IDs (comma-separated)\" }\n },\n \"example\": \"tokenomist token list --output json\"\n },\n \"token search <query>\": {\n \"description\": \"Search for tokens by name, symbol, or slug\",\n \"arguments\": { \"query\": { \"required\": true, \"description\": \"Search query string\" } },\n \"example\": \"tokenomist token search bitcoin --output json\"\n },\n \"unlock list\": {\n \"description\": \"List unlock events grouped by token\",\n \"options\": {\n \"min-market-cap\": { \"flags\": \"--min-market-cap <value>\", \"description\": \"Minimum market cap\" },\n \"min-released-percentage\": { \"flags\": \"--min-released-percentage <value>\", \"description\": \"Minimum released percentage\" },\n \"min-unlock-date\": { \"flags\": \"--min-unlock-date <date>\", \"description\": \"Min unlock date (YYYY-MM-DD)\" },\n \"max-unlock-date\": { \"flags\": \"--max-unlock-date <date>\", \"description\": \"Max unlock date (YYYY-MM-DD)\" },\n \"min-total-unlock-amount\": { \"flags\": \"--min-total-unlock-amount <value>\", \"description\": \"Minimum total unlock amount\" },\n \"min-value-to-market-cap\": { \"flags\": \"--min-value-to-market-cap <value>\", \"description\": \"Min value-to-market-cap ratio\" },\n \"standard-allocation\": { \"flags\": \"--standard-allocation <names>\", \"description\": \"Filter by allocation (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist unlock list --min-market-cap 1000000\"\n },\n \"unlock upcoming\": {\n \"description\": \"List next upcoming unlock event per token\",\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date (YYYY-MM-DD)\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date (YYYY-MM-DD)\" },\n \"standard-allocation\": { \"flags\": \"--standard-allocation <names>\", \"description\": \"Filter by allocation (comma-separated)\" },\n \"min-market-cap\": { \"flags\": \"--min-market-cap <value>\", \"description\": \"Minimum market cap\" },\n \"min-released-percentage\": { \"flags\": \"--min-released-percentage <value>\", \"description\": \"Minimum released percentage\" },\n \"min-total-unlock-amount\": { \"flags\": \"--min-total-unlock-amount <value>\", \"description\": \"Minimum total unlock amount\" },\n \"min-value-to-market-cap\": { \"flags\": \"--min-value-to-market-cap <value>\", \"description\": \"Min value-to-market-cap ratio\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist unlock upcoming --output json\"\n },\n \"unlock events <tokenSlug>\": {\n \"description\": \"Get unlock events for a specific token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug (e.g. solana)\" } },\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date (YYYY-MM-DD)\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date (YYYY-MM-DD)\" },\n \"standard-allocation\": { \"flags\": \"--standard-allocation <names>\", \"description\": \"Filter by allocation (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist unlock events solana --start 2024-01-01 --end 2024-12-31\"\n },\n \"investor list\": {\n \"description\": \"List all investors\",\n \"options\": {\n \"start-latest-funding-date\": { \"flags\": \"--start-latest-funding-date <date>\", \"description\": \"Start date filter for latest funding (YYYY-MM-DD)\" },\n \"end-latest-funding-date\": { \"flags\": \"--end-latest-funding-date <date>\", \"description\": \"End date filter for latest funding (YYYY-MM-DD)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist investor list --output json\"\n },\n \"investor detail <investorId>\": {\n \"description\": \"Get investor portfolio and funding rounds\",\n \"arguments\": { \"investorId\": { \"required\": true, \"description\": \"Investor ID\" } },\n \"options\": {\n \"is-lead-investor\": { \"flags\": \"--is-lead-investor\", \"description\": \"Filter to rounds where investor was lead\" },\n \"funding-date-min\": { \"flags\": \"--funding-date-min <date>\", \"description\": \"Minimum funding date\" },\n \"funding-date-max\": { \"flags\": \"--funding-date-max <date>\", \"description\": \"Maximum funding date\" },\n \"raised-amount-min\": { \"flags\": \"--raised-amount-min <amount>\", \"description\": \"Minimum raised amount\" },\n \"raised-amount-max\": { \"flags\": \"--raised-amount-max <amount>\", \"description\": \"Maximum raised amount\" }\n },\n \"example\": \"tokenomist investor detail 123 --is-lead-investor\"\n },\n \"fundraising <tokenSlug>\": {\n \"description\": \"Get fundraising data for a token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"options\": {\n \"funding-date-min\": { \"flags\": \"--funding-date-min <date>\", \"description\": \"Minimum funding date\" },\n \"funding-date-max\": { \"flags\": \"--funding-date-max <date>\", \"description\": \"Maximum funding date\" },\n \"raised-amount-min\": { \"flags\": \"--raised-amount-min <amount>\", \"description\": \"Minimum raised amount\" },\n \"raised-amount-max\": { \"flags\": \"--raised-amount-max <amount>\", \"description\": \"Maximum raised amount\" }\n },\n \"example\": \"tokenomist fundraising uniswap --output json\"\n },\n \"burn list\": {\n \"description\": \"List all tokens with burn data\",\n \"options\": {\n \"token-id\": { \"flags\": \"--token-id <ids>\", \"description\": \"Filter by token IDs (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist burn list --output json\"\n },\n \"burn detail <tokenSlug>\": {\n \"description\": \"Get burn events for a specific token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date\" }\n },\n \"example\": \"tokenomist burn detail solana --start 2024-01-01\"\n },\n \"buyback list\": {\n \"description\": \"List all tokens with buyback data\",\n \"options\": {\n \"token-id\": { \"flags\": \"--token-id <ids>\", \"description\": \"Filter by token IDs (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist buyback list --output json\"\n },\n \"buyback detail <tokenSlug>\": {\n \"description\": \"Get buyback events for a specific token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date\" }\n },\n \"example\": \"tokenomist buyback detail solana --output json\"\n },\n \"emission daily <tokenSlug>\": {\n \"description\": \"Get daily emission data for a token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date\" },\n \"standard-allocation\": { \"flags\": \"--standard-allocation <names>\", \"description\": \"Filter by allocation (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist emission daily arbitrum --start 2024-08-01 --end 2024-08-31\"\n },\n \"emission weekly <tokenSlug>\": {\n \"description\": \"Get weekly emission data for a token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"options\": {\n \"start\": { \"flags\": \"--start <date>\", \"description\": \"Start date\" },\n \"end\": { \"flags\": \"--end <date>\", \"description\": \"End date\" },\n \"standard-allocation\": { \"flags\": \"--standard-allocation <names>\", \"description\": \"Filter by allocation (comma-separated)\" },\n \"page\": { \"flags\": \"--page <number>\", \"description\": \"Page number\" },\n \"page-size\": { \"flags\": \"--page-size <number>\", \"description\": \"Items per page\" }\n },\n \"example\": \"tokenomist emission weekly arbitrum --start 2024-01-01 --end 2024-06-30\"\n },\n \"allocation <tokenSlug>\": {\n \"description\": \"Get standard allocation distribution for a token\",\n \"arguments\": { \"tokenSlug\": { \"required\": true, \"description\": \"Token slug\" } },\n \"example\": \"tokenomist allocation solana --output json\"\n },\n \"auth login\": {\n \"description\": \"Store API key\",\n \"options\": {\n \"api-key\": { \"flags\": \"--api-key <key>\", \"description\": \"API key (prompts if not provided)\" }\n },\n \"example\": \"tokenomist auth login\"\n },\n \"auth logout\": {\n \"description\": \"Remove stored API key\",\n \"example\": \"tokenomist auth logout\"\n },\n \"auth status\": {\n \"description\": \"Show current auth status\",\n \"example\": \"tokenomist auth status\"\n },\n \"schema\": {\n \"description\": \"Print full command schema as JSON\",\n \"options\": {\n \"pretty\": { \"flags\": \"--pretty\", \"description\": \"Pretty-print with 2-space indent\" }\n },\n \"example\": \"tokenomist schema --pretty\"\n }\n }\n}\n"],"mappings":"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","names":["Command","code","body","columns","columns","columns","readFileSync","writeFileSync","mkdirSync","unlinkSync","join","homedir","Command","Command","Command","listColumns","Command","Command","columns","Command","Command","listColumns","detailColumns","Command","Command","listColumns","detailColumns","Command","Command","columns","Command","Command","columns","Command","Command","Command","Command","Command","readFileSync","join","homedir","Command"]}
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/update-check.ts
4
+ import { readFileSync, writeFileSync, mkdirSync } from "fs";
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+
8
+ // package.json
9
+ var package_default = {
10
+ name: "@tokenomist-ai/tokenomist-cli",
11
+ version: "0.1.0",
12
+ description: "CLI tool for the Tokenomist API \u2014 query token unlocks, emissions, fundraising, burns, and buybacks from the terminal",
13
+ type: "module",
14
+ main: "dist/index.js",
15
+ bin: {
16
+ tokenomist: "dist/index.js"
17
+ },
18
+ scripts: {
19
+ postinstall: "node scripts/postinstall.js",
20
+ build: "tsup",
21
+ dev: "tsup --watch",
22
+ start: "node dist/index.js",
23
+ test: "vitest run",
24
+ "test:watch": "vitest",
25
+ lint: "eslint src/ tests/",
26
+ "lint:fix": "eslint src/ tests/ --fix",
27
+ format: "prettier --write 'src/**/*.ts' 'tests/**/*.ts'",
28
+ "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts'",
29
+ prepublishOnly: "npm run build"
30
+ },
31
+ keywords: [
32
+ "tokenomist",
33
+ "crypto",
34
+ "token",
35
+ "unlock",
36
+ "emission",
37
+ "fundraising",
38
+ "burn",
39
+ "buyback",
40
+ "cli",
41
+ "api"
42
+ ],
43
+ author: {
44
+ name: "tokenomist-ai",
45
+ email: "support@tokenomist.ai",
46
+ url: "https://tokenomist.ai"
47
+ },
48
+ license: "MIT",
49
+ repository: {
50
+ type: "git",
51
+ url: "git+https://github.com/tokenomist-ai/tokenomist-cli.git"
52
+ },
53
+ homepage: "https://github.com/tokenomist-ai/tokenomist-cli#readme",
54
+ bugs: {
55
+ url: "https://github.com/tokenomist-ai/tokenomist-cli/issues"
56
+ },
57
+ engines: {
58
+ node: ">=18.0.0"
59
+ },
60
+ publishConfig: {
61
+ access: "public"
62
+ },
63
+ files: [
64
+ "dist",
65
+ "skills/**",
66
+ "scripts/postinstall.js",
67
+ "LICENSE",
68
+ "README.md"
69
+ ],
70
+ dependencies: {
71
+ "cli-table3": "^0.6.5",
72
+ commander: "^12.1.0",
73
+ dotenv: "^16.4.7"
74
+ },
75
+ devDependencies: {
76
+ "@types/node": "^22.10.0",
77
+ eslint: "^9.16.0",
78
+ prettier: "^3.4.2",
79
+ tsup: "^8.3.5",
80
+ typescript: "^5.7.2",
81
+ "typescript-eslint": "^8.57.0",
82
+ vitest: "^2.1.8"
83
+ }
84
+ };
85
+
86
+ // src/update-check.ts
87
+ var CONFIG_DIR = join(homedir(), ".tokenomist");
88
+ var CACHE_PATH = join(CONFIG_DIR, "update-check.json");
89
+ var ONE_DAY = 24 * 60 * 60 * 1e3;
90
+ var REGISTRY_URL = "https://registry.npmjs.org/@tokenomist-ai%2Ftokenomist-cli/latest";
91
+ async function main() {
92
+ try {
93
+ const raw = readFileSync(CACHE_PATH, "utf-8");
94
+ const cache2 = JSON.parse(raw);
95
+ if (Date.now() - cache2.checkedAt < ONE_DAY) {
96
+ return;
97
+ }
98
+ } catch {
99
+ }
100
+ const current = package_default.version;
101
+ const res = await fetch(REGISTRY_URL, {
102
+ signal: AbortSignal.timeout(5e3)
103
+ });
104
+ if (!res.ok) return;
105
+ const data = await res.json();
106
+ const latest = data.version;
107
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
108
+ const cache = { latest, current, checkedAt: Date.now() };
109
+ writeFileSync(CACHE_PATH, JSON.stringify(cache), { encoding: "utf-8", mode: 384 });
110
+ }
111
+ main().catch(() => {
112
+ });
113
+ //# sourceMappingURL=update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/update-check.ts","../package.json"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport pkg from \"../package.json\" with { type: \"json\" };\n\nconst CONFIG_DIR = join(homedir(), \".tokenomist\");\nconst CACHE_PATH = join(CONFIG_DIR, \"update-check.json\");\nconst ONE_DAY = 24 * 60 * 60 * 1000;\nconst REGISTRY_URL = \"https://registry.npmjs.org/@tokenomist-ai%2Ftokenomist-cli/latest\";\n\ninterface UpdateCache {\n latest: string;\n current: string;\n checkedAt: number;\n}\n\nasync function main() {\n // Check if cache is fresh\n try {\n const raw = readFileSync(CACHE_PATH, \"utf-8\");\n const cache = JSON.parse(raw) as UpdateCache;\n if (Date.now() - cache.checkedAt < ONE_DAY) {\n return; // Already checked recently\n }\n } catch {\n // No cache or invalid — proceed with check\n }\n\n const current: string = pkg.version;\n\n const res = await fetch(REGISTRY_URL, {\n signal: AbortSignal.timeout(5000),\n });\n\n if (!res.ok) return;\n\n const data = (await res.json()) as { version: string };\n const latest = data.version;\n\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n\n const cache: UpdateCache = { latest, current, checkedAt: Date.now() };\n writeFileSync(CACHE_PATH, JSON.stringify(cache), { encoding: \"utf-8\", mode: 0o600 });\n}\n\nmain().catch(() => {});\n","{\n \"name\": \"@tokenomist-ai/tokenomist-cli\",\n \"version\": \"0.1.0\",\n \"description\": \"CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, and buybacks from the terminal\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"tokenomist\": \"dist/index.js\"\n },\n \"scripts\": {\n \"postinstall\": \"node scripts/postinstall.js\",\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.js\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint src/ tests/\",\n \"lint:fix\": \"eslint src/ tests/ --fix\",\n \"format\": \"prettier --write 'src/**/*.ts' 'tests/**/*.ts'\",\n \"format:check\": \"prettier --check 'src/**/*.ts' 'tests/**/*.ts'\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"tokenomist\",\n \"crypto\",\n \"token\",\n \"unlock\",\n \"emission\",\n \"fundraising\",\n \"burn\",\n \"buyback\",\n \"cli\",\n \"api\"\n ],\n \"author\": {\n \"name\": \"tokenomist-ai\",\n \"email\": \"support@tokenomist.ai\",\n \"url\": \"https://tokenomist.ai\"\n },\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/tokenomist-ai/tokenomist-cli.git\"\n },\n \"homepage\": \"https://github.com/tokenomist-ai/tokenomist-cli#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/tokenomist-ai/tokenomist-cli/issues\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\",\n \"skills/**\",\n \"scripts/postinstall.js\",\n \"LICENSE\",\n \"README.md\"\n ],\n \"dependencies\": {\n \"cli-table3\": \"^0.6.5\",\n \"commander\": \"^12.1.0\",\n \"dotenv\": \"^16.4.7\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.10.0\",\n \"eslint\": \"^9.16.0\",\n \"prettier\": \"^3.4.2\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"typescript-eslint\": \"^8.57.0\",\n \"vitest\": \"^2.1.8\"\n }\n}\n"],"mappings":";;;AAAA,SAAS,cAAc,eAAe,iBAAiB;AACvD,SAAS,YAAY;AACrB,SAAS,eAAe;;;ACFxB;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,YAAc;AAAA,EAChB;AAAA,EACA,SAAW;AAAA,IACT,aAAe;AAAA,IACf,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,cAAc;AAAA,IACd,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,QAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,gBAAkB;AAAA,EACpB;AAAA,EACA,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAU;AAAA,IACR,MAAQ;AAAA,IACR,OAAS;AAAA,IACT,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,EACX,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,MAAQ;AAAA,IACN,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,cAAc;AAAA,IACd,WAAa;AAAA,IACb,QAAU;AAAA,EACZ;AAAA,EACA,iBAAmB;AAAA,IACjB,eAAe;AAAA,IACf,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,EACZ;AACF;;;ADtEA,IAAM,aAAa,KAAK,QAAQ,GAAG,aAAa;AAChD,IAAM,aAAa,KAAK,YAAY,mBAAmB;AACvD,IAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,IAAM,eAAe;AAQrB,eAAe,OAAO;AAEpB,MAAI;AACF,UAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,UAAMA,SAAQ,KAAK,MAAM,GAAG;AAC5B,QAAI,KAAK,IAAI,IAAIA,OAAM,YAAY,SAAS;AAC1C;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,UAAkB,gBAAI;AAE5B,QAAM,MAAM,MAAM,MAAM,cAAc;AAAA,IACpC,QAAQ,YAAY,QAAQ,GAAI;AAAA,EAClC,CAAC;AAED,MAAI,CAAC,IAAI,GAAI;AAEb,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,SAAS,KAAK;AAEpB,YAAU,YAAY,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAEtD,QAAM,QAAqB,EAAE,QAAQ,SAAS,WAAW,KAAK,IAAI,EAAE;AACpE,gBAAc,YAAY,KAAK,UAAU,KAAK,GAAG,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AACrF;AAEA,KAAK,EAAE,MAAM,MAAM;AAAC,CAAC;","names":["cache"]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@tokenomist-ai/tokenomist-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool for the Tokenomist API — query token unlocks, emissions, fundraising, burns, and buybacks from the terminal",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "tokenomist": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "postinstall": "node scripts/postinstall.js",
12
+ "build": "tsup",
13
+ "dev": "tsup --watch",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "lint": "eslint src/ tests/",
18
+ "lint:fix": "eslint src/ tests/ --fix",
19
+ "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'",
20
+ "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts'",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "tokenomist",
25
+ "crypto",
26
+ "token",
27
+ "unlock",
28
+ "emission",
29
+ "fundraising",
30
+ "burn",
31
+ "buyback",
32
+ "cli",
33
+ "api"
34
+ ],
35
+ "author": {
36
+ "name": "tokenomist-ai",
37
+ "email": "support@tokenomist.ai",
38
+ "url": "https://tokenomist.ai"
39
+ },
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/tokenomist-ai/tokenomist-cli.git"
44
+ },
45
+ "homepage": "https://github.com/tokenomist-ai/tokenomist-cli#readme",
46
+ "bugs": {
47
+ "url": "https://github.com/tokenomist-ai/tokenomist-cli/issues"
48
+ },
49
+ "engines": {
50
+ "node": ">=18.0.0"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "files": [
56
+ "dist",
57
+ "skills/**",
58
+ "scripts/postinstall.js",
59
+ "LICENSE",
60
+ "README.md"
61
+ ],
62
+ "dependencies": {
63
+ "cli-table3": "^0.6.5",
64
+ "commander": "^12.1.0",
65
+ "dotenv": "^16.4.7"
66
+ },
67
+ "devDependencies": {
68
+ "@types/node": "^22.10.0",
69
+ "eslint": "^9.16.0",
70
+ "prettier": "^3.4.2",
71
+ "tsup": "^8.3.5",
72
+ "typescript": "^5.7.2",
73
+ "typescript-eslint": "^8.57.0",
74
+ "vitest": "^2.1.8"
75
+ }
76
+ }
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install onboarding for tokenomist-cli.
5
+ *
6
+ * Runs after `npm install -g @tokenomist-ai/tokenomist-cli` and offers to install
7
+ * AI coding skills via `npx skills add tokenomist-ai/tokenomist-cli`.
8
+ *
9
+ * Non-interactive environments (CI, piped stdin) get a one-liner tip instead.
10
+ * Always exits 0 — onboarding failures must never break installation.
11
+ */
12
+
13
+ import { execFileSync, spawn } from "child_process";
14
+ import { existsSync } from "fs";
15
+ import { join } from "path";
16
+ import { homedir } from "os";
17
+ import { createInterface } from "readline";
18
+ import { fileURLToPath } from "url";
19
+
20
+ const BOLD = "\x1b[1m";
21
+ const DIM = "\x1b[2m";
22
+ const GREEN = "\x1b[32m";
23
+ const YELLOW = "\x1b[33m";
24
+ const CYAN = "\x1b[36m";
25
+ const RESET = "\x1b[0m";
26
+
27
+ const SKILL_REPO = "tokenomist-ai/tokenomist-cli";
28
+
29
+ function log(msg = "") {
30
+ process.stderr.write(` ${msg}\n`);
31
+ }
32
+
33
+ export function hasTTY() {
34
+ return !!(process.stdin.isTTY && process.stderr.isTTY);
35
+ }
36
+
37
+ export function hasNpx() {
38
+ try {
39
+ execFileSync("npx", ["--version"], {
40
+ stdio: "ignore",
41
+ shell: process.platform === "win32",
42
+ });
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+
49
+ export function isSkillInstalled() {
50
+ const home = homedir();
51
+ const locations = [
52
+ join(home, ".claude", "skills", "tokenomist-cli"),
53
+ join(home, ".claude", "skills", "tokenomist-ai--tokenomist-cli"),
54
+ ];
55
+ return locations.some((loc) => existsSync(loc));
56
+ }
57
+
58
+ function prompt(question) {
59
+ return new Promise((resolve) => {
60
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
61
+ let answered = false;
62
+ rl.on("close", () => {
63
+ if (!answered) resolve("");
64
+ });
65
+ rl.question(question, (answer) => {
66
+ answered = true;
67
+ rl.close();
68
+ resolve(answer.trim());
69
+ });
70
+ });
71
+ }
72
+
73
+ function runCommand(cmd, args) {
74
+ return new Promise((resolve) => {
75
+ const child = spawn(cmd, args, {
76
+ stdio: "inherit",
77
+ shell: process.platform === "win32",
78
+ });
79
+ child.on("close", (code) => resolve(code === 0));
80
+ child.on("error", () => resolve(false));
81
+ });
82
+ }
83
+
84
+ async function installSkill() {
85
+ if (isSkillInstalled()) {
86
+ log(`${GREEN}✓${RESET} Tokenomist skills already installed.`);
87
+ return;
88
+ }
89
+
90
+ if (!hasNpx()) {
91
+ log(
92
+ `${DIM}Tip: Run 'npx skills add ${SKILL_REPO}' to install Tokenomist AI coding skills.${RESET}`,
93
+ );
94
+ return;
95
+ }
96
+
97
+ log(`Tokenomist skills let AI coding agents (Claude Code, Cursor, etc.) query`);
98
+ log(`token unlocks, emissions, fundraising, burns, and allocations on your behalf.`);
99
+ const answer = await prompt(
100
+ ` Install Tokenomist skills for your AI coding agent? [Y/n] `,
101
+ );
102
+
103
+ if (/^n/i.test(answer)) {
104
+ log(
105
+ `Skipped. You can install later with: ${CYAN}npx skills add ${SKILL_REPO}${RESET}`,
106
+ );
107
+ return;
108
+ }
109
+
110
+ log(`Installing Tokenomist skills...`);
111
+ const ok = await runCommand("npx", ["-y", "skills", "add", SKILL_REPO]);
112
+ if (!ok) {
113
+ log(
114
+ `${YELLOW}Skill installation failed. You can retry with: npx skills add ${SKILL_REPO}${RESET}`,
115
+ );
116
+ }
117
+ }
118
+
119
+ async function main() {
120
+ // Only run for global installs. When npm runs this as a postinstall hook
121
+ // during local `npm install` or `npm ci`, skip to avoid breaking CI.
122
+ // When invoked directly (`node scripts/postinstall.js`), npm_lifecycle_event
123
+ // is undefined, so the guard does not trigger — allowing manual execution.
124
+ if (
125
+ process.env.npm_lifecycle_event === "postinstall" &&
126
+ process.env.npm_config_global !== "true"
127
+ ) {
128
+ return;
129
+ }
130
+
131
+ log();
132
+
133
+ if (!hasTTY()) {
134
+ log(`${BOLD}Tokenomist CLI installed!${RESET}`);
135
+ log();
136
+ log(
137
+ `Tip: Run '${CYAN}npx skills add ${SKILL_REPO}${RESET}' to install AI coding skills.`,
138
+ );
139
+ log(
140
+ `Tip: Run '${CYAN}tokenomist auth login${RESET}' to authenticate.`,
141
+ );
142
+ return;
143
+ }
144
+
145
+ log(`${BOLD}Tokenomist CLI installed!${RESET}`);
146
+ log();
147
+
148
+ await installSkill();
149
+
150
+ log();
151
+ }
152
+
153
+ // Only auto-run when executed as the entry point, not when imported for testing
154
+ const isEntryPoint =
155
+ process.argv[1] &&
156
+ fileURLToPath(import.meta.url) === process.argv[1];
157
+
158
+ if (isEntryPoint) {
159
+ main().catch(() => {
160
+ // Never fail installation due to onboarding errors
161
+ });
162
+ }