@vizzor/cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -6
- package/dist/index.js +2125 -188
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/schema.ts","../src/config/loader.ts","../src/chains/evm/abi/erc20.ts","../src/chains/evm/etherscan.ts","../src/config/constants.ts","../src/chains/evm/adapter.ts","../src/chains/zk/adapter.ts","../src/chains/registry.ts","../src/utils/logger.ts","../src/ml/client.ts","../src/core/scanner/project-analyzer.ts","../src/core/scanner/risk-scorer.ts","../src/cli/commands/scan.ts","../src/data/sources/dexscreener.ts","../src/core/trends/market.ts","../src/data/sources/cryptopanic.ts","../src/core/trends/sentiment.ts","../src/data/sources/binance.ts","../src/core/technical-analysis/indicators.ts","../src/core/technical-analysis/analyzer.ts","../src/core/technical-analysis/index.ts","../src/data/sources/fear-greed.ts","../src/ml/feature-engineer.ts","../src/core/trends/predictor.ts","../src/cli/commands/trends.ts","../src/core/forensics/wallet-analyzer.ts","../src/cli/commands/track.ts","../src/data/sources/defillama.ts","../src/data/sources/pumpfun.ts","../src/core/scanner/ico-tracker.ts","../src/cli/commands/ico.ts","../src/core/forensics/contract-auditor.ts","../src/cli/commands/audit.ts","../src/ai/providers/types.ts","../src/config/keys.ts","../src/cli/commands/config.ts","../src/ai/providers/anthropic.ts","../src/ai/providers/openai.ts","../src/ai/providers/gemini.ts","../src/ai/providers/ollama.ts","../src/ai/providers/registry.ts","../src/data/sources/goplus.ts","../src/ai/context-injector.ts","../src/ai/prompts/chat.ts","../src/ai/client.ts","../src/core/forensics/bytecode-scanner.ts","../src/core/forensics/rug-detector.ts","../src/core/trends/regime.ts","../src/data/cache.ts","../src/core/agent/engine.ts","../src/core/agent/strategies/momentum.ts","../src/core/agent/strategies/trend-following.ts","../src/core/agent/strategies/ml-adaptive.ts","../src/core/agent/manager.ts","../src/core/agent/wallet.ts","../src/core/agent/index.ts","../src/data/sqlite-store.ts","../src/data/postgres-store.ts","../src/data/store-factory.ts","../src/ai/tool-handler.ts","../src/ai/tools.ts","../src/utils/message-split.ts","../src/discord/middleware/rate-limit.ts","../src/discord/commands/index.ts","../src/discord/bot.ts","../src/telegram/formatters/market.ts","../src/telegram/commands/index.ts","../src/telegram/middleware/rate-limit.ts","../src/telegram/bot.ts","../src/cli/commands/bot.ts","../src/data/collector.ts","../src/cli/commands/collect.ts","../src/api/routes/v1/market.ts","../src/api/routes/v1/analysis.ts","../src/api/routes/v1/security.ts","../src/api/auth/keys.ts","../src/api/auth/middleware.ts","../src/api/middleware/error-handler.ts","../src/api/server.ts","../src/cli/commands/serve.ts","../src/cli/commands/api.ts","../src/tui/components/status-bar.tsx","../src/tui/components/price-ticker.tsx","../src/tui/components/welcome-banner.tsx","../src/tui/blocks/risk-bar.tsx","../src/tui/blocks/token-card.tsx","../src/tui/blocks/holder-list.tsx","../src/tui/blocks/market-ticker.tsx","../src/tui/blocks/audit-result.tsx","../src/tui/components/message-list.tsx","../src/tui/components/message-bubble.tsx","../src/tui/components/command-hints.tsx","../src/tui/components/tool-status.tsx","../src/tui/components/input-prompt.tsx","../src/tui/components/streaming-text.tsx","../src/tui/hooks/use-ai-stream.ts","../src/tui/commands.ts","../src/tui/hooks/use-command.ts","../src/tui/hooks/use-price-ticker.ts","../src/tui/app.tsx","../src/index.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\nexport const vizzorConfigSchema = z.object({\n anthropicApiKey: z.string().optional(),\n openaiApiKey: z.string().optional(),\n googleApiKey: z.string().optional(),\n etherscanApiKey: z.string().optional(),\n alchemyApiKey: z.string().optional(),\n coingeckoApiKey: z.string().optional(),\n cryptopanicApiKey: z.string().optional(),\n defaultChain: z.string().default('ethereum'),\n rpc: z.record(z.string(), z.string()).default({}),\n ai: z\n .object({\n provider: z.enum(['anthropic', 'openai', 'gemini', 'ollama']).default('anthropic'),\n model: z.string().optional(),\n maxTokens: z.number().default(4096),\n ollamaHost: z.string().default('http://localhost:11434'),\n })\n .default(() => ({\n provider: 'anthropic' as const,\n maxTokens: 4096,\n ollamaHost: 'http://localhost:11434',\n })),\n output: z\n .object({\n format: z.enum(['table', 'json', 'markdown']).default('table'),\n color: z.boolean().default(true),\n verbose: z.boolean().default(false),\n })\n .default(() => ({ format: 'table' as const, color: true, verbose: false })),\n cacheTtl: z\n .object({\n tokenInfo: z.number().default(3600),\n marketData: z.number().default(300),\n walletData: z.number().default(600),\n contractCode: z.number().default(86400),\n })\n .default(() => ({ tokenInfo: 3600, marketData: 300, walletData: 600, contractCode: 86400 })),\n database: z\n .object({\n type: z.enum(['sqlite', 'postgres']).default('sqlite'),\n url: z.string().optional(),\n })\n .default(() => ({ type: 'sqlite' as const })),\n ml: z\n .object({\n enabled: z.boolean().default(false),\n sidecarUrl: z.string().default('http://localhost:8000'),\n fallbackToRules: z.boolean().default(true),\n })\n .default(() => ({\n enabled: false,\n sidecarUrl: 'http://localhost:8000',\n fallbackToRules: true,\n })),\n api: z\n .object({\n port: z.number().default(3000),\n host: z.string().default('0.0.0.0'),\n enableAuth: z.boolean().default(false),\n corsOrigin: z.string().default('*'),\n })\n .default(() => ({\n port: 3000,\n host: '0.0.0.0',\n enableAuth: false,\n corsOrigin: '*',\n })),\n n8n: z\n .object({\n enabled: z.boolean().default(false),\n webhookUrl: z.string().optional(),\n })\n .default(() => ({ enabled: false })),\n discordToken: z.string().optional(),\n discordGuildId: z.string().optional(),\n telegramToken: z.string().optional(),\n});\n\nexport type VizzorConfig = z.infer<typeof vizzorConfigSchema>;\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport yaml from 'yaml';\nimport { vizzorConfigSchema } from './schema.js';\nimport type { VizzorConfig } from './schema.js';\n\nlet cachedConfig: VizzorConfig | null = null;\n\n/**\n * Returns the path to the Vizzor configuration directory (~/.vizzor/).\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.vizzor');\n}\n\n/**\n * Loads and validates the Vizzor configuration from ~/.vizzor/config.yaml.\n * Creates the config directory if it does not exist.\n * Environment variables override file-based values.\n */\nexport function loadConfig(): VizzorConfig {\n const configDir = getConfigDir();\n const configPath = join(configDir, 'config.yaml');\n\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n let raw: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n const contents = readFileSync(configPath, 'utf-8');\n const parsed: unknown = yaml.parse(contents);\n if (parsed && typeof parsed === 'object') {\n raw = parsed as Record<string, unknown>;\n }\n }\n\n // Environment variable overrides\n if (process.env['ANTHROPIC_API_KEY']) {\n raw['anthropicApiKey'] = process.env['ANTHROPIC_API_KEY'];\n }\n if (process.env['ETHERSCAN_API_KEY']) {\n raw['etherscanApiKey'] = process.env['ETHERSCAN_API_KEY'];\n }\n if (process.env['ALCHEMY_API_KEY']) {\n raw['alchemyApiKey'] = process.env['ALCHEMY_API_KEY'];\n }\n if (process.env['COINGECKO_API_KEY']) {\n raw['coingeckoApiKey'] = process.env['COINGECKO_API_KEY'];\n }\n if (process.env['DISCORD_TOKEN']) {\n raw['discordToken'] = process.env['DISCORD_TOKEN'];\n }\n if (process.env['DISCORD_GUILD_ID']) {\n raw['discordGuildId'] = process.env['DISCORD_GUILD_ID'];\n }\n if (process.env['TELEGRAM_BOT_TOKEN']) {\n raw['telegramToken'] = process.env['TELEGRAM_BOT_TOKEN'];\n }\n if (process.env['OPENAI_API_KEY']) {\n raw['openaiApiKey'] = process.env['OPENAI_API_KEY'];\n }\n if (process.env['GOOGLE_API_KEY']) {\n raw['googleApiKey'] = process.env['GOOGLE_API_KEY'];\n }\n if (process.env['CRYPTOPANIC_API_KEY']) {\n raw['cryptopanicApiKey'] = process.env['CRYPTOPANIC_API_KEY'];\n }\n if (process.env['VIZZOR_AI_PROVIDER']) {\n if (!raw['ai'] || typeof raw['ai'] !== 'object') {\n raw['ai'] = {};\n }\n (raw['ai'] as Record<string, unknown>)['provider'] = process.env['VIZZOR_AI_PROVIDER'];\n }\n\n // Database env overrides\n if (process.env['DATABASE_TYPE'] || process.env['DATABASE_URL']) {\n if (!raw['database'] || typeof raw['database'] !== 'object') {\n raw['database'] = {};\n }\n const db = raw['database'] as Record<string, unknown>;\n if (process.env['DATABASE_TYPE']) db['type'] = process.env['DATABASE_TYPE'];\n if (process.env['DATABASE_URL']) db['url'] = process.env['DATABASE_URL'];\n }\n\n // ML env overrides\n if (process.env['ML_ENABLED'] || process.env['ML_SIDECAR_URL']) {\n if (!raw['ml'] || typeof raw['ml'] !== 'object') {\n raw['ml'] = {};\n }\n const ml = raw['ml'] as Record<string, unknown>;\n if (process.env['ML_ENABLED']) ml['enabled'] = process.env['ML_ENABLED'] === 'true';\n if (process.env['ML_SIDECAR_URL']) ml['sidecarUrl'] = process.env['ML_SIDECAR_URL'];\n }\n\n // API env overrides\n if (process.env['API_PORT'] || process.env['API_HOST']) {\n if (!raw['api'] || typeof raw['api'] !== 'object') {\n raw['api'] = {};\n }\n const api = raw['api'] as Record<string, unknown>;\n if (process.env['API_PORT']) api['port'] = Number(process.env['API_PORT']);\n if (process.env['API_HOST']) api['host'] = process.env['API_HOST'];\n }\n\n const config = vizzorConfigSchema.parse(raw);\n cachedConfig = config;\n return config;\n}\n\n/**\n * Returns the cached configuration. Throws if loadConfig() has not been called.\n */\nexport function getConfig(): VizzorConfig {\n if (!cachedConfig) {\n throw new Error('Configuration not loaded. Call loadConfig() before getConfig().');\n }\n return cachedConfig;\n}\n\n/** Valid top-level config keys that can be set via /config set. */\nconst SETTABLE_KEYS: Record<string, { env: string; nested?: string }> = {\n anthropicApiKey: { env: 'ANTHROPIC_API_KEY' },\n openaiApiKey: { env: 'OPENAI_API_KEY' },\n googleApiKey: { env: 'GOOGLE_API_KEY' },\n etherscanApiKey: { env: 'ETHERSCAN_API_KEY' },\n alchemyApiKey: { env: 'ALCHEMY_API_KEY' },\n coingeckoApiKey: { env: 'COINGECKO_API_KEY' },\n cryptopanicApiKey: { env: 'CRYPTOPANIC_API_KEY' },\n defaultChain: { env: 'VIZZOR_DEFAULT_CHAIN' },\n telegramToken: { env: 'TELEGRAM_BOT_TOKEN' },\n discordToken: { env: 'DISCORD_TOKEN' },\n discordGuildId: { env: 'DISCORD_GUILD_ID' },\n 'ai.provider': { env: 'VIZZOR_AI_PROVIDER', nested: 'ai' },\n 'ai.model': { env: 'VIZZOR_AI_MODEL', nested: 'ai' },\n 'ai.maxTokens': { env: 'VIZZOR_AI_MAX_TOKENS', nested: 'ai' },\n 'ai.ollamaHost': { env: 'OLLAMA_HOST', nested: 'ai' },\n 'database.type': { env: 'DATABASE_TYPE', nested: 'database' },\n 'database.url': { env: 'DATABASE_URL', nested: 'database' },\n 'ml.enabled': { env: 'ML_ENABLED', nested: 'ml' },\n 'ml.sidecarUrl': { env: 'ML_SIDECAR_URL', nested: 'ml' },\n 'ml.fallbackToRules': { env: 'ML_FALLBACK_TO_RULES', nested: 'ml' },\n 'api.port': { env: 'API_PORT', nested: 'api' },\n 'api.host': { env: 'API_HOST', nested: 'api' },\n 'api.enableAuth': { env: 'API_ENABLE_AUTH', nested: 'api' },\n 'api.corsOrigin': { env: 'API_CORS_ORIGIN', nested: 'api' },\n 'n8n.enabled': { env: 'N8N_ENABLED', nested: 'n8n' },\n 'n8n.webhookUrl': { env: 'N8N_WEBHOOK_URL', nested: 'n8n' },\n};\n\n/**\n * Returns the list of settable config keys with their env var names.\n */\nexport function getSettableKeys(): Record<string, { env: string; nested?: string }> {\n return SETTABLE_KEYS;\n}\n\n/**\n * Persists a single config key=value to ~/.vizzor/config.yaml and reloads the cache.\n * Supports dot-notation for nested keys (e.g. \"ai.provider\").\n */\nexport function saveConfigValue(key: string, value: string): void {\n if (!(key in SETTABLE_KEYS)) {\n throw new Error(\n `Unknown config key: \"${key}\". Valid keys: ${Object.keys(SETTABLE_KEYS).join(', ')}`,\n );\n }\n\n const configDir = getConfigDir();\n const configPath = join(configDir, 'config.yaml');\n\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n let raw: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n const contents = readFileSync(configPath, 'utf-8');\n const parsed: unknown = yaml.parse(contents);\n if (parsed && typeof parsed === 'object') {\n raw = parsed as Record<string, unknown>;\n }\n }\n\n // Handle dot-notation (e.g. \"ai.provider\" -> raw.ai.provider)\n if (key.includes('.')) {\n const [section, field] = key.split('.') as [string, string];\n if (!raw[section] || typeof raw[section] !== 'object') {\n raw[section] = {};\n }\n // Parse numeric and boolean values\n let parsed: string | number | boolean = value;\n if (field === 'maxTokens' || field === 'port') parsed = Number(value);\n else if (value === 'true') parsed = true;\n else if (value === 'false') parsed = false;\n (raw[section] as Record<string, unknown>)[field] = parsed;\n } else {\n raw[key] = value;\n }\n\n // Validate before saving\n vizzorConfigSchema.parse(raw);\n\n writeFileSync(configPath, yaml.stringify(raw), 'utf-8');\n\n // Invalidate cache so next getConfig() returns fresh data\n cachedConfig = null;\n loadConfig();\n}\n","// ---------------------------------------------------------------------------\n// Standard ERC-20 ABI (subset used by the EVM adapter)\n// ---------------------------------------------------------------------------\n\nexport const erc20Abi = [\n // ── read ────────────────────────────────────────────────────────────────\n {\n type: 'function',\n name: 'name',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n },\n {\n type: 'function',\n name: 'symbol',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n },\n {\n type: 'function',\n name: 'decimals',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'uint8' }],\n },\n {\n type: 'function',\n name: 'totalSupply',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'balanceOf',\n stateMutability: 'view',\n inputs: [{ name: 'owner', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n },\n\n // ── write ───────────────────────────────────────────────────────────────\n {\n type: 'function',\n name: 'transfer',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n\n // ── events ──────────────────────────────────────────────────────────────\n {\n type: 'event',\n name: 'Transfer',\n inputs: [\n { name: 'from', type: 'address', indexed: true },\n { name: 'to', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Approval',\n inputs: [\n { name: 'owner', type: 'address', indexed: true },\n { name: 'spender', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// ---------------------------------------------------------------------------\n// Etherscan-compatible block explorer API client\n// Works with Etherscan, Polygonscan, Arbiscan, Basescan, etc.\n// ---------------------------------------------------------------------------\n\nimport type { Transaction, TokenTransfer, Holder } from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Base URLs per chain\n// ---------------------------------------------------------------------------\n\nexport const EXPLORER_URLS: Record<string, string> = {\n ethereum: 'https://api.etherscan.io/api',\n polygon: 'https://api.polygonscan.com/api',\n arbitrum: 'https://api.arbiscan.io/api',\n optimism: 'https://api-optimistic.etherscan.io/api',\n base: 'https://api.basescan.org/api',\n};\n\n// ---------------------------------------------------------------------------\n// Raw API response types\n// ---------------------------------------------------------------------------\n\ninterface EtherscanResult<T> {\n status: string;\n message: string;\n result: T;\n}\n\ninterface RawTransaction {\n hash: string;\n blockNumber: string;\n from: string;\n to: string;\n value: string;\n gasUsed: string;\n gasPrice: string;\n timeStamp: string;\n isError: string;\n input: string;\n}\n\ninterface RawTokenTransfer {\n hash: string;\n blockNumber: string;\n from: string;\n to: string;\n value: string;\n contractAddress: string;\n tokenSymbol: string;\n tokenDecimal: string;\n timeStamp: string;\n}\n\ninterface RawHolder {\n TokenHolderAddress: string;\n TokenHolderQuantity: string;\n // percentage not directly available from Etherscan\n}\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class EtherscanClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n\n constructor(baseUrl: string, apiKey?: string) {\n this.baseUrl = baseUrl;\n this.apiKey = apiKey ?? '';\n }\n\n // ── Transactions ──────────────────────────────────────────────────────\n\n async getTransactions(\n address: string,\n options?: { limit?: number; offset?: number; fromBlock?: bigint; toBlock?: bigint },\n ): Promise<Transaction[]> {\n const params: Record<string, string> = {\n module: 'account',\n action: 'txlist',\n address,\n sort: 'desc',\n page: '1',\n offset: String(options?.limit ?? 50),\n };\n if (options?.fromBlock != null) params['startblock'] = options.fromBlock.toString();\n if (options?.toBlock != null) params['endblock'] = options.toBlock.toString();\n\n const data = await this.request<RawTransaction[]>(params);\n if (!Array.isArray(data)) return [];\n\n return data.map(\n (tx): Transaction => ({\n hash: tx.hash,\n blockNumber: BigInt(tx.blockNumber),\n from: tx.from,\n to: tx.to || null,\n value: BigInt(tx.value),\n gasUsed: BigInt(tx.gasUsed),\n gasPrice: BigInt(tx.gasPrice),\n timestamp: Number(tx.timeStamp),\n status: tx.isError === '0' ? 'success' : 'reverted',\n input: tx.input,\n }),\n );\n }\n\n // ── Token Transfers ───────────────────────────────────────────────────\n\n async getTokenTransfers(\n address: string,\n options?: { tokenAddress?: string; limit?: number; fromBlock?: bigint; toBlock?: bigint },\n ): Promise<TokenTransfer[]> {\n const params: Record<string, string> = {\n module: 'account',\n action: 'tokentx',\n address,\n sort: 'desc',\n page: '1',\n offset: String(options?.limit ?? 50),\n };\n if (options?.tokenAddress) params['contractaddress'] = options.tokenAddress;\n if (options?.fromBlock != null) params['startblock'] = options.fromBlock.toString();\n if (options?.toBlock != null) params['endblock'] = options.toBlock.toString();\n\n const data = await this.request<RawTokenTransfer[]>(params);\n if (!Array.isArray(data)) return [];\n\n return data.map(\n (t): TokenTransfer => ({\n hash: t.hash,\n blockNumber: BigInt(t.blockNumber),\n from: t.from,\n to: t.to,\n value: BigInt(t.value),\n tokenAddress: t.contractAddress,\n tokenSymbol: t.tokenSymbol,\n tokenDecimals: Number(t.tokenDecimal),\n timestamp: Number(t.timeStamp),\n }),\n );\n }\n\n // ── Top Holders ───────────────────────────────────────────────────────\n\n async getTopHolders(tokenAddress: string, limit = 10): Promise<Holder[]> {\n // Note: Etherscan top holders endpoint is only on Pro plan.\n // We use the tokentx approach or fall back gracefully.\n const params: Record<string, string> = {\n module: 'token',\n action: 'tokenholderlist',\n contractaddress: tokenAddress,\n page: '1',\n offset: String(limit),\n };\n\n try {\n const data = await this.request<RawHolder[]>(params);\n if (!Array.isArray(data)) return [];\n\n // Calculate percentages from balances\n const totalBalance = data.reduce((sum, h) => sum + BigInt(h.TokenHolderQuantity), 0n);\n\n return data.map(\n (h): Holder => ({\n address: h.TokenHolderAddress,\n balance: BigInt(h.TokenHolderQuantity),\n percentage:\n totalBalance > 0n\n ? Number((BigInt(h.TokenHolderQuantity) * 10000n) / totalBalance) / 100\n : 0,\n }),\n );\n } catch {\n // Top holders endpoint may not be available on free tier\n return [];\n }\n }\n\n // ── Contract ABI ──────────────────────────────────────────────────────\n\n async getContractAbi(address: string): Promise<string | null> {\n const params: Record<string, string> = {\n module: 'contract',\n action: 'getabi',\n address,\n };\n\n try {\n const data = await this.request<string>(params);\n return typeof data === 'string' && data !== 'Contract source code not verified' ? data : null;\n } catch {\n return null;\n }\n }\n\n // ── Contract Verification Check ───────────────────────────────────────\n\n async isContractVerified(address: string): Promise<boolean> {\n const abi = await this.getContractAbi(address);\n return abi !== null;\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n private async request<T>(params: Record<string, string>): Promise<T> {\n if (this.apiKey) {\n params['apikey'] = this.apiKey;\n }\n\n const qs = new URLSearchParams(params).toString();\n const res = await fetch(`${this.baseUrl}?${qs}`);\n\n if (!res.ok) {\n throw new Error(`Etherscan API error: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as EtherscanResult<T>;\n\n if (json.status !== '1' && json.message !== 'OK' && json.message !== 'No transactions found') {\n // Some endpoints return status \"0\" with \"No records found\" which is valid\n if (json.message?.includes('No') || json.message?.includes('no')) {\n return [] as unknown as T;\n }\n throw new Error(`Etherscan: ${json.message}`);\n }\n\n return json.result;\n }\n}\n","// ---------------------------------------------------------------------------\n// Shared configuration constants\n// ---------------------------------------------------------------------------\n\n/** Default blockchain when none is specified. */\nexport const DEFAULT_CHAIN = 'ethereum';\n\n/** @deprecated Used only by CLI trends fallback. TUI uses dynamic trending data. */\nexport const TREND_SYMBOLS = ['bitcoin', 'ethereum', 'solana'];\n\n/** Default ticker symbols shown in the price bar. */\nexport const TICKER_DEFAULTS: { geckoId: string; symbol: string }[] = [\n { geckoId: 'bitcoin', symbol: 'BTC' },\n { geckoId: 'ethereum', symbol: 'ETH' },\n { geckoId: 'solana', symbol: 'SOL' },\n];\n\n/** Chain metadata for display and selection. */\nexport interface ChainMeta {\n id: string;\n name: string;\n icon: string;\n nativeSymbol: string;\n explorerUrl: string;\n explorerApiUrl: string;\n color: string;\n}\n\nexport const CHAIN_REGISTRY: ChainMeta[] = [\n {\n id: 'ethereum',\n name: 'Ethereum',\n icon: '\\u{039E}', // Greek Xi (ETH symbol)\n nativeSymbol: 'ETH',\n explorerUrl: 'https://etherscan.io',\n explorerApiUrl: 'https://api.etherscan.io/api',\n color: '#627EEA',\n },\n {\n id: 'polygon',\n name: 'Polygon',\n icon: '\\u{2B23}', // Hexagonal shape\n nativeSymbol: 'POL',\n explorerUrl: 'https://polygonscan.com',\n explorerApiUrl: 'https://api.polygonscan.com/api',\n color: '#8247E5',\n },\n {\n id: 'arbitrum',\n name: 'Arbitrum',\n icon: '\\u{25C6}', // Diamond\n nativeSymbol: 'ETH',\n explorerUrl: 'https://arbiscan.io',\n explorerApiUrl: 'https://api.arbiscan.io/api',\n color: '#28A0F0',\n },\n {\n id: 'optimism',\n name: 'Optimism',\n icon: '\\u{25CF}', // Filled circle\n nativeSymbol: 'ETH',\n explorerUrl: 'https://optimistic.etherscan.io',\n explorerApiUrl: 'https://api-optimistic.etherscan.io/api',\n color: '#FF0420',\n },\n {\n id: 'base',\n name: 'Base',\n icon: '\\u{25B3}', // Triangle up\n nativeSymbol: 'ETH',\n explorerUrl: 'https://basescan.org',\n explorerApiUrl: 'https://api.basescan.org/api',\n color: '#0052FF',\n },\n];\n\n/** Quick lookup: chain ID -> explorer API URL (backwards compatible). */\nexport const ETHERSCAN_BASE_URLS: Record<string, string> = Object.fromEntries(\n CHAIN_REGISTRY.map((c) => [c.id, c.explorerApiUrl]),\n);\n\n/** Quick lookup: chain ID -> chain metadata. */\nexport function getChainMeta(chainId: string): ChainMeta | undefined {\n return CHAIN_REGISTRY.find((c) => c.id === chainId);\n}\n\n/** Map of common token symbols to CoinGecko IDs. */\nexport const KNOWN_SYMBOLS: Record<string, string> = {\n btc: 'bitcoin',\n bitcoin: 'bitcoin',\n eth: 'ethereum',\n ethereum: 'ethereum',\n sol: 'solana',\n solana: 'solana',\n bnb: 'binancecoin',\n bsc: 'binancecoin',\n xrp: 'ripple',\n ripple: 'ripple',\n ada: 'cardano',\n cardano: 'cardano',\n doge: 'dogecoin',\n dogecoin: 'dogecoin',\n dot: 'polkadot',\n polkadot: 'polkadot',\n avax: 'avalanche-2',\n avalanche: 'avalanche-2',\n matic: 'matic-network',\n polygon: 'matic-network',\n link: 'chainlink',\n chainlink: 'chainlink',\n uni: 'uniswap',\n uniswap: 'uniswap',\n atom: 'cosmos',\n cosmos: 'cosmos',\n near: 'near',\n arb: 'arbitrum',\n op: 'optimism',\n sui: 'sui',\n apt: 'aptos',\n pepe: 'pepe',\n shib: 'shiba-inu',\n floki: 'floki',\n bonk: 'bonk',\n wif: 'dogwifcoin',\n};\n","// ---------------------------------------------------------------------------\n// EvmAdapter – ChainAdapter implementation for EVM-compatible chains (viem)\n// ---------------------------------------------------------------------------\n\nimport {\n createPublicClient,\n http,\n type PublicClient,\n type Chain,\n type HttpTransport,\n type Address,\n type Abi,\n} from 'viem';\nimport { mainnet, polygon, arbitrum, optimism, base } from 'viem/chains';\n\nimport type {\n ChainAdapter,\n Block,\n ContractEvent,\n EventOptions,\n Holder,\n TokenInfo,\n TokenTransfer,\n Transaction,\n TransferOptions,\n TxHistoryOptions,\n} from '../types.js';\nimport { erc20Abi } from './abi/erc20.js';\nimport { EtherscanClient } from './etherscan.js';\nimport { ETHERSCAN_BASE_URLS } from '../../config/constants.js';\n\n// ---------------------------------------------------------------------------\n// Chain ID → viem Chain object mapping\n// ---------------------------------------------------------------------------\n\nconst CHAIN_MAP: Record<string, Chain> = {\n ethereum: mainnet,\n polygon: polygon,\n arbitrum: arbitrum,\n optimism: optimism,\n base: base,\n};\n\n// ---------------------------------------------------------------------------\n// EvmAdapter\n// ---------------------------------------------------------------------------\n\nexport class EvmAdapter implements ChainAdapter {\n readonly chainId: string;\n readonly name: string;\n readonly nativeCurrency: { symbol: string; decimals: number };\n\n private client: PublicClient<HttpTransport, Chain> | null = null;\n private etherscan: EtherscanClient | null = null;\n private readonly viemChain: Chain;\n\n constructor(chainId: string) {\n const chain = CHAIN_MAP[chainId];\n if (!chain) {\n throw new Error(\n `Unsupported EVM chain: \"${chainId}\". Supported: ${Object.keys(CHAIN_MAP).join(', ')}`,\n );\n }\n\n this.chainId = chainId;\n this.viemChain = chain;\n this.name = chain.name;\n this.nativeCurrency = {\n symbol: chain.nativeCurrency.symbol,\n decimals: chain.nativeCurrency.decimals,\n };\n }\n\n // ── Lifecycle ───────────────────────────────────────────────────────────\n\n async connect(rpcUrl?: string, etherscanApiKey?: string): Promise<void> {\n this.client = createPublicClient({\n chain: this.viemChain,\n transport: http(rpcUrl),\n batch: { multicall: true },\n });\n\n // Create Etherscan client if a base URL is known for this chain\n const explorerUrl = ETHERSCAN_BASE_URLS[this.chainId];\n if (explorerUrl) {\n this.etherscan = new EtherscanClient(explorerUrl, etherscanApiKey);\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.etherscan = null;\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n // ── Balances ────────────────────────────────────────────────────────────\n\n async getBalance(address: string): Promise<bigint> {\n const client = this.requireClient();\n return client.getBalance({ address: address as Address });\n }\n\n async getTokenBalance(address: string, tokenAddress: string): Promise<bigint> {\n const client = this.requireClient();\n const balance = await client.readContract({\n address: tokenAddress as Address,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [address as Address],\n });\n return balance as bigint;\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTransactions(address, {\n limit: options?.limit,\n offset: options?.offset,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n });\n }\n\n async getTokenTransfers(address: string, options?: TransferOptions): Promise<TokenTransfer[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTokenTransfers(address, {\n tokenAddress: options?.tokenAddress,\n limit: options?.limit,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n });\n }\n\n // ── Contracts ───────────────────────────────────────────────────────────\n\n async getContractCode(address: string): Promise<string> {\n const client = this.requireClient();\n const code = await client.getCode({ address: address as Address });\n return code ?? '0x';\n }\n\n async readContract(\n address: string,\n abi: readonly unknown[],\n functionName: string,\n args?: unknown[],\n ): Promise<unknown> {\n const client = this.requireClient();\n return client.readContract({\n address: address as Address,\n abi: abi as Abi,\n functionName,\n args: args as readonly unknown[],\n });\n }\n\n async getContractEvents(\n address: string,\n abi: readonly unknown[],\n eventName: string,\n options?: EventOptions,\n ): Promise<ContractEvent[]> {\n const client = this.requireClient();\n\n const logs = await client.getContractEvents({\n address: address as Address,\n abi: abi as Abi,\n eventName,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n args: options?.args as Record<string, unknown> | undefined,\n });\n\n return logs.map((log) => ({\n eventName: log.eventName ?? eventName,\n blockNumber: log.blockNumber ?? 0n,\n transactionHash: log.transactionHash ?? '0x',\n args: (log.args ?? {}) as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n }));\n }\n\n // ── Tokens ──────────────────────────────────────────────────────────────\n\n async getTokenInfo(address: string): Promise<TokenInfo> {\n const client = this.requireClient();\n const tokenAddr = address as Address;\n\n const [name, symbol, decimals, totalSupply] = await Promise.all([\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'name',\n }) as Promise<string>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'symbol',\n }) as Promise<string>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'decimals',\n }) as Promise<number>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'totalSupply',\n }) as Promise<bigint>,\n ]);\n\n return { address, name, symbol, decimals, totalSupply };\n }\n\n async getTopHolders(tokenAddress: string, limit?: number): Promise<Holder[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTopHolders(tokenAddress, limit);\n }\n\n // ── Blocks ──────────────────────────────────────────────────────────────\n\n async getBlockNumber(): Promise<bigint> {\n const client = this.requireClient();\n return client.getBlockNumber();\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n const client = this.requireClient();\n const block = await client.getBlock({ blockNumber });\n\n return {\n number: block.number ?? 0n,\n hash: block.hash ?? '0x',\n parentHash: block.parentHash,\n timestamp: Number(block.timestamp),\n gasUsed: block.gasUsed,\n gasLimit: block.gasLimit,\n baseFeePerGas: block.baseFeePerGas ?? null,\n transactionCount: block.transactions.length,\n };\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────────\n\n private requireClient(): PublicClient<HttpTransport, Chain> {\n if (!this.client) {\n throw new Error(`EvmAdapter(${this.chainId}): not connected. Call connect() first.`);\n }\n return this.client;\n }\n}\n","// ---------------------------------------------------------------------------\n// ZK Chain Adapter — adapter for ZK rollup chains (zkSync, StarkNet, etc.)\n// Uses EVM adapter under the hood for EVM-compatible ZK rollups\n// ---------------------------------------------------------------------------\n\nimport { EvmAdapter } from '../evm/adapter.js';\n\n// ---------------------------------------------------------------------------\n// ZK-specific chain configurations\n// ---------------------------------------------------------------------------\n\nconst ZK_CHAIN_CONFIG: Record<\n string,\n {\n name: string;\n rpcUrl: string;\n explorerApi: string;\n nativeCurrency: { symbol: string; decimals: number };\n isEvm: boolean;\n }\n> = {\n zksync: {\n name: 'zkSync Era',\n rpcUrl: 'https://mainnet.era.zksync.io',\n explorerApi: 'https://block-explorer-api.mainnet.zksync.io/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n 'polygon-zkevm': {\n name: 'Polygon zkEVM',\n rpcUrl: 'https://zkevm-rpc.com',\n explorerApi: 'https://api-zkevm.polygonscan.com/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n scroll: {\n name: 'Scroll',\n rpcUrl: 'https://rpc.scroll.io',\n explorerApi: 'https://api.scrollscan.com/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n linea: {\n name: 'Linea',\n rpcUrl: 'https://rpc.linea.build',\n explorerApi: 'https://api.lineascan.build/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n};\n\nexport class ZkEvmAdapter extends EvmAdapter {\n readonly zkType: string;\n private readonly zkName: string;\n\n constructor(chainId: string) {\n super(chainId);\n this.zkType = chainId;\n this.zkName = ZK_CHAIN_CONFIG[chainId]?.name ?? `ZK-${chainId}`;\n }\n\n getZkName(): string {\n return this.zkName;\n }\n\n getDefaultRpcUrl(): string {\n return ZK_CHAIN_CONFIG[this.chainId]?.rpcUrl ?? '';\n }\n}\n\nexport function getZkChainIds(): string[] {\n return Object.keys(ZK_CHAIN_CONFIG);\n}\n\nexport function isZkChain(chainId: string): boolean {\n return chainId in ZK_CHAIN_CONFIG;\n}\n","// ---------------------------------------------------------------------------\n// Chain adapter registry – factory-based creation of ChainAdapter instances\n// ---------------------------------------------------------------------------\n\nimport type { ChainAdapter } from './types.js';\nimport { EvmAdapter } from './evm/adapter.js';\nimport { ZkEvmAdapter, getZkChainIds } from './zk/adapter.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A factory that produces a ChainAdapter for a given chain ID. */\nexport type ChainAdapterFactory = (chainId: string) => ChainAdapter;\n\n// ---------------------------------------------------------------------------\n// Internal registry map\n// ---------------------------------------------------------------------------\n\nconst registry = new Map<string, ChainAdapterFactory>();\n\n// ---------------------------------------------------------------------------\n// Built-in EVM adapters\n// ---------------------------------------------------------------------------\n\nconst evmFactory: ChainAdapterFactory = (chainId) => new EvmAdapter(chainId);\n\nconst BUILTIN_EVM_CHAINS = ['ethereum', 'polygon', 'arbitrum', 'optimism', 'base'] as const;\n\nfor (const chainId of BUILTIN_EVM_CHAINS) {\n registry.set(chainId, evmFactory);\n}\n\n// ZK rollup chains (EVM-compatible)\nconst zkFactory: ChainAdapterFactory = (chainId) => new ZkEvmAdapter(chainId);\n\nfor (const chainId of getZkChainIds()) {\n registry.set(chainId, zkFactory);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create (or retrieve) a {@link ChainAdapter} for the given chain ID.\n *\n * Each call produces a **new** adapter instance; callers are responsible for\n * caching if they need to reuse across requests.\n */\nexport function getAdapter(chainId: string): ChainAdapter {\n const factory = registry.get(chainId);\n if (!factory) {\n throw new Error(\n `No adapter registered for chain \"${chainId}\". ` +\n `Supported chains: ${getSupportedChains().join(', ')}`,\n );\n }\n return factory(chainId);\n}\n\n/**\n * Register a custom adapter factory for a chain ID.\n *\n * This allows third-party or non-EVM chains to plug into Vizzor.\n */\nexport function registerAdapter(chainId: string, factory: ChainAdapterFactory): void {\n registry.set(chainId, factory);\n}\n\n/**\n * Return the list of chain IDs that have registered adapter factories.\n */\nexport function getSupportedChains(): string[] {\n return [...registry.keys()];\n}\n","import pino from 'pino';\nimport type { Logger } from 'pino';\n\nconst level = process.env['VIZZOR_LOG_LEVEL'] ?? 'info';\n\n/**\n * Creates a named Pino logger instance.\n * Uses pino-pretty transport when NODE_ENV is not 'production'.\n */\nexport function createLogger(name: string): Logger {\n const isDev = process.env['NODE_ENV'] !== 'production';\n\n if (isDev) {\n return pino({\n name,\n level,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n });\n }\n\n return pino({ name, level });\n}\n","// ---------------------------------------------------------------------------\n// ML Sidecar HTTP client — communicates with the Python FastAPI sidecar\n// ---------------------------------------------------------------------------\n\nimport { createLogger } from '../utils/logger.js';\nimport type {\n FeatureVector,\n MLPredictionResult,\n AnomalyResult,\n ModelHealth,\n TokenFlow,\n RugMLFeatures,\n RugMLResult,\n WalletMLFeatures,\n WalletMLResult,\n SentimentMLResult,\n TrendMLFeatures,\n TrendMLResult,\n TAMLFeatures,\n TAMLResult,\n StrategyMLFeatures,\n StrategyMLResult,\n RegimeMLFeatures,\n RegimeMLResult,\n ProjectRiskMLFeatures,\n ProjectRiskMLResult,\n PortfolioOptMLFeatures,\n PortfolioOptMLResult,\n IntentMLResult,\n BytecodeRiskMLFeatures,\n BytecodeRiskMLResult,\n PortfolioPredMLFeatures,\n PortfolioPredMLResult,\n} from './types.js';\n\nconst log = createLogger('ml-client');\n\nexport class MLClient {\n private baseUrl: string;\n private healthy = false;\n\n constructor(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '');\n }\n\n async predict(features: FeatureVector): Promise<MLPredictionResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as MLPredictionResult;\n } catch (err) {\n log.debug(`ML predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async batchPredict(features: FeatureVector[]): Promise<MLPredictionResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/batch`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ features }),\n signal: AbortSignal.timeout(15000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { predictions: MLPredictionResult[] };\n return data.predictions;\n } catch (err) {\n log.debug(`ML batch predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n async detectAnomalies(flows: TokenFlow[]): Promise<AnomalyResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/anomalies`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ flows }),\n signal: AbortSignal.timeout(10000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { anomalies: AnomalyResult[] };\n return data.anomalies;\n } catch (err) {\n log.debug(`ML anomaly detection failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n this.healthy = res.ok;\n return this.healthy;\n } catch {\n this.healthy = false;\n return false;\n }\n }\n\n async predictRug(features: RugMLFeatures): Promise<RugMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/rug`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as RugMLResult;\n } catch (err) {\n log.debug(`ML rug predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async classifyWallet(features: WalletMLFeatures): Promise<WalletMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/wallet`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as WalletMLResult;\n } catch (err) {\n log.debug(`ML wallet classify failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async analyzeSentiment(text: string): Promise<SentimentMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/sentiment`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as SentimentMLResult;\n } catch (err) {\n log.debug(`ML sentiment failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async analyzeSentimentBatch(texts: string[]): Promise<SentimentMLResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/sentiment/batch`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ texts }),\n signal: AbortSignal.timeout(15000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { results: SentimentMLResult[] };\n return data.results;\n } catch (err) {\n log.debug(`ML sentiment batch failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n // -----------------------------------------------------------------------\n // v0.11.0 — New ML endpoints\n // -----------------------------------------------------------------------\n\n async scoreTrend(features: TrendMLFeatures): Promise<TrendMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/trend`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as TrendMLResult;\n } catch (err) {\n log.debug(`ML trend score failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async interpretTA(features: TAMLFeatures): Promise<TAMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/ta`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as TAMLResult;\n } catch (err) {\n log.debug(`ML TA interpret failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async evaluateStrategy(features: StrategyMLFeatures): Promise<StrategyMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/strategy`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as StrategyMLResult;\n } catch (err) {\n log.debug(`ML strategy eval failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async detectRegime(features: RegimeMLFeatures): Promise<RegimeMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/regime`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as RegimeMLResult;\n } catch (err) {\n log.debug(`ML regime detect failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async scoreProjectRisk(features: ProjectRiskMLFeatures): Promise<ProjectRiskMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/project-risk`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as ProjectRiskMLResult;\n } catch (err) {\n log.debug(`ML project risk failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async optimizePortfolio(features: PortfolioOptMLFeatures): Promise<PortfolioOptMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/portfolio-opt`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as PortfolioOptMLResult;\n } catch (err) {\n log.debug(`ML portfolio opt failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async classifyIntent(text: string): Promise<IntentMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/intent`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as IntentMLResult;\n } catch (err) {\n log.debug(`ML intent classify failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async scoreBytecodeRisk(features: BytecodeRiskMLFeatures): Promise<BytecodeRiskMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/bytecode-risk`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as BytecodeRiskMLResult;\n } catch (err) {\n log.debug(`ML bytecode risk failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async predictPortfolioForward(\n features: PortfolioPredMLFeatures,\n ): Promise<PortfolioPredMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/portfolio-forward`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as PortfolioPredMLResult;\n } catch (err) {\n log.debug(`ML portfolio forward failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async getModelHealth(): Promise<ModelHealth | null> {\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n if (!res.ok) return null;\n return (await res.json()) as ModelHealth;\n } catch {\n return null;\n }\n }\n\n isHealthy(): boolean {\n return this.healthy;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton accessor — lazy-initialized from config\n// ---------------------------------------------------------------------------\n\nlet mlClient: MLClient | null = null;\n\nexport function initMLClient(url: string): MLClient {\n mlClient = new MLClient(url);\n return mlClient;\n}\n\nexport function getMLClient(): MLClient | null {\n return mlClient;\n}\n","import type { ChainAdapter, TokenInfo } from '../../chains/types.js';\nimport { getMLClient } from '../../ml/client.js';\nimport type { ProjectRiskMLResult } from '../../ml/types.js';\n\nexport interface ProjectAnalysis {\n token: TokenInfo | null;\n contractVerified: boolean;\n hasSourceCode: boolean;\n holderConcentration: number;\n topHolders: { address: string; percentage: number }[];\n riskIndicators: RiskIndicator[];\n riskScore: number;\n mlRisk?: ProjectRiskMLResult;\n}\n\nexport interface RiskIndicator {\n name: string;\n detected: boolean;\n severity: 'low' | 'medium' | 'high' | 'critical';\n points: number;\n description: string;\n}\n\nexport async function analyzeProject(\n address: string,\n adapter: ChainAdapter,\n): Promise<ProjectAnalysis> {\n const [token, code, holders] = await Promise.allSettled([\n adapter.getTokenInfo(address),\n adapter.getContractCode(address),\n adapter.getTopHolders(address, 10),\n ]);\n\n const tokenInfo = token.status === 'fulfilled' ? token.value : null;\n const contractCode = code.status === 'fulfilled' ? code.value : '';\n const topHolders = holders.status === 'fulfilled' ? holders.value : [];\n\n const hasSourceCode = contractCode.length > 2;\n const riskIndicators = evaluateRiskIndicators(tokenInfo, hasSourceCode, topHolders);\n const riskScore = riskIndicators.reduce(\n (score, indicator) => score + (indicator.detected ? indicator.points : 0),\n 0,\n );\n\n const totalSupply = tokenInfo?.totalSupply ?? 0n;\n const topHolderPercentage =\n topHolders.length > 0 && totalSupply > 0n\n ? Number(((topHolders[0]?.balance ?? 0n) * 10000n) / totalSupply) / 100\n : 0;\n\n const topHoldersMapped = topHolders.map((h) => ({\n address: h.address,\n percentage: totalSupply > 0n ? Number((h.balance * 10000n) / totalSupply) / 100 : 0,\n }));\n\n const top10Pct = topHoldersMapped.reduce((sum, h) => sum + h.percentage, 0);\n\n // ML: score project risk with ML model\n let mlRisk: ProjectRiskMLResult | undefined;\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const result = await mlClient.scoreProjectRisk({\n bytecode_size: contractCode.length,\n is_verified: hasSourceCode ? 1 : 0,\n holder_concentration: topHolderPercentage,\n has_proxy: 0,\n has_mint: 0,\n has_pause: 0,\n has_blacklist: 0,\n liquidity_locked: 0,\n buy_tax: 0,\n sell_tax: 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: topHolderPercentage,\n is_open_source: hasSourceCode ? 1 : 0,\n top10_holder_pct: top10Pct,\n has_token_info: tokenInfo ? 1 : 0,\n });\n if (result) {\n mlRisk = result;\n }\n } catch {\n // ML unavailable\n }\n }\n\n return {\n token: tokenInfo,\n contractVerified: hasSourceCode,\n hasSourceCode,\n holderConcentration: topHolderPercentage,\n topHolders: topHoldersMapped,\n riskIndicators,\n riskScore: Math.min(100, riskScore),\n mlRisk,\n };\n}\n\nfunction evaluateRiskIndicators(\n token: TokenInfo | null,\n hasSource: boolean,\n topHolders: { address: string; balance: bigint }[],\n): RiskIndicator[] {\n const indicators: RiskIndicator[] = [];\n\n indicators.push({\n name: 'Unverified Contract',\n detected: !hasSource,\n severity: 'high',\n points: 30,\n description: 'Contract source code is not verified on block explorer',\n });\n\n if (token && topHolders.length > 0) {\n const topBalance = topHolders[0]?.balance ?? 0n;\n const concentrated = token.totalSupply > 0n && topBalance * 2n > token.totalSupply;\n indicators.push({\n name: 'Concentrated Supply',\n detected: concentrated,\n severity: 'critical',\n points: 25,\n description: 'Top holder owns more than 50% of total supply',\n });\n }\n\n indicators.push({\n name: 'No Token Info',\n detected: token === null,\n severity: 'medium',\n points: 15,\n description: 'Unable to read token metadata from contract',\n });\n\n return indicators;\n}\n","import type { ProjectAnalysis } from './project-analyzer.js';\n\nexport interface RiskAssessment {\n score: number;\n level: 'low' | 'medium' | 'high' | 'critical';\n summary: string;\n factors: string[];\n mlScore?: number;\n mlLevel?: string;\n}\n\nexport function assessRisk(analysis: ProjectAnalysis): RiskAssessment {\n const { riskScore, riskIndicators, mlRisk } = analysis;\n\n // Use ML risk probability if available, else fall back to point sum\n const effectiveScore = mlRisk ? Math.round(mlRisk.risk_probability * 100) : riskScore;\n const level = getRiskLevel(effectiveScore);\n\n const factors = riskIndicators\n .filter((i) => i.detected)\n .map((i) => `${i.name}: ${i.description} (+${i.points})`);\n\n // Add ML risk factors if available\n if (mlRisk) {\n for (const f of mlRisk.risk_factors) {\n factors.push(`ML: ${f.factor} (importance: ${(f.importance * 100).toFixed(1)}%)`);\n }\n }\n\n const summary = buildSummary(level, factors.length);\n\n return {\n score: effectiveScore,\n level,\n summary,\n factors,\n mlScore: mlRisk ? Math.round(mlRisk.risk_probability * 100) : undefined,\n mlLevel: mlRisk?.risk_level,\n };\n}\n\nfunction getRiskLevel(score: number): RiskAssessment['level'] {\n if (score <= 20) return 'low';\n if (score <= 50) return 'medium';\n if (score <= 75) return 'high';\n return 'critical';\n}\n\nfunction buildSummary(level: RiskAssessment['level'], factorCount: number): string {\n switch (level) {\n case 'low':\n return 'Project shows minimal risk indicators. Standard due diligence recommended.';\n case 'medium':\n return `Project has ${factorCount} risk factor(s) detected. Proceed with caution.`;\n case 'high':\n return `Project has significant risk indicators. Thorough investigation recommended before any interaction.`;\n case 'critical':\n return `Project shows critical risk signals. High probability of scam or rug pull.`;\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\n\nexport async function handleScan(\n project: string,\n options: { chain: string; deep: boolean; json: boolean },\n): Promise<void> {\n const spinner = ora(`Scanning ${project} on ${options.chain}...`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n spinner.text = 'Fetching on-chain data...';\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify({ analysis, risk }, null, 2));\n return;\n }\n\n const riskColor =\n risk.level === 'low'\n ? chalk.green\n : risk.level === 'medium'\n ? chalk.yellow\n : risk.level === 'high'\n ? chalk.red\n : chalk.bgRed.white;\n\n console.log();\n console.log(chalk.bold(`Project Analysis: ${project}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n if (analysis.token) {\n console.log(chalk.bold('Token Info'));\n console.log(` Name: ${analysis.token.name}`);\n console.log(` Symbol: ${analysis.token.symbol}`);\n console.log(` Decimals: ${analysis.token.decimals}`);\n console.log();\n }\n\n console.log(chalk.bold('Risk Assessment'));\n console.log(` Score: ${riskColor(`${risk.score}/100 (${risk.level.toUpperCase()})`)}`);\n console.log(` ${risk.summary}`);\n console.log();\n\n if (risk.factors.length > 0) {\n console.log(chalk.bold('Risk Factors'));\n for (const factor of risk.factors) {\n console.log(` ${chalk.red('!')} ${factor}`);\n }\n console.log();\n }\n\n console.log(\n chalk.dim('Disclaimer: This is not financial advice. Always do your own research.'),\n );\n } catch (error) {\n spinner.fail('Scan failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","// ---------------------------------------------------------------------------\n// DexScreener API client — real-time DEX pair data, no auth required\n// https://docs.dexscreener.com/api/reference\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.dexscreener.com';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DexToken {\n address: string;\n name: string;\n symbol: string;\n}\n\nexport interface DexTxns {\n buys: number;\n sells: number;\n}\n\nexport interface DexPair {\n chainId: string;\n dexId: string;\n pairAddress: string;\n url: string;\n baseToken: DexToken;\n quoteToken: DexToken;\n priceNative: string;\n priceUsd: string | null;\n txns: {\n m5: DexTxns;\n h1: DexTxns;\n h6: DexTxns;\n h24: DexTxns;\n };\n volume: { m5: number; h1: number; h6: number; h24: number };\n priceChange: { m5: number; h1: number; h6: number; h24: number };\n liquidity: { usd: number; base: number; quote: number } | null;\n fdv: number | null;\n marketCap: number | null;\n pairCreatedAt: number | null;\n info?: {\n imageUrl?: string;\n websites?: { url: string; label?: string }[];\n socials?: { type: string; url: string }[];\n };\n labels?: string[];\n}\n\nexport interface TokenProfile {\n url: string;\n chainId: string;\n tokenAddress: string;\n icon?: string;\n description?: string;\n links?: { type?: string; label?: string; url: string }[];\n}\n\nexport interface TokenBoost {\n url: string;\n chainId: string;\n tokenAddress: string;\n amount: number;\n totalAmount: number;\n icon?: string;\n description?: string;\n links?: { type?: string; label?: string; url: string }[];\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(path: string): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`);\n if (!res.ok) {\n throw new Error(`DexScreener API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Search for token pairs by name, symbol, or address.\n */\nexport async function searchTokens(query: string): Promise<DexPair[]> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/latest/dex/search?q=${encodeURIComponent(query)}`,\n );\n return data.pairs ?? [];\n}\n\n/**\n * Get all trading pairs for a specific token on a chain.\n */\nexport async function getTokenPairs(chainId: string, tokenAddress: string): Promise<DexPair[]> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/token-pairs/v1/${encodeURIComponent(chainId)}/${encodeURIComponent(tokenAddress)}`,\n );\n return data.pairs ?? [];\n}\n\n/**\n * Get the latest boosted tokens (promoted on DexScreener).\n */\nexport async function getLatestBoostedTokens(): Promise<TokenBoost[]> {\n return fetchJson<TokenBoost[]>('/token-boosts/latest/v1');\n}\n\n/**\n * Get the top boosted tokens by total boost amount.\n */\nexport async function getTopBoostedTokens(): Promise<TokenBoost[]> {\n return fetchJson<TokenBoost[]>('/token-boosts/top/v1');\n}\n\n/**\n * Get the latest token profiles (recently updated tokens with metadata).\n */\nexport async function getLatestTokenProfiles(): Promise<TokenProfile[]> {\n return fetchJson<TokenProfile[]>('/token-profiles/latest/v1');\n}\n\n/**\n * Get a specific pair by chain and pair address.\n */\nexport async function getPair(chainId: string, pairAddress: string): Promise<DexPair | null> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/latest/dex/pairs/${encodeURIComponent(chainId)}/${encodeURIComponent(pairAddress)}`,\n );\n return data.pairs?.[0] ?? null;\n}\n","import {\n searchTokens as dexSearch,\n getTopBoostedTokens,\n type DexPair,\n} from '../../data/sources/dexscreener.js';\nimport { getMLClient } from '../../ml/client.js';\n\nexport interface MarketData {\n symbol: string;\n name: string;\n price: number;\n priceChange24h: number;\n priceChange7d: number;\n volume24h: number;\n marketCap: number;\n rank: number | null;\n}\n\nexport interface MarketTrend {\n direction: 'bullish' | 'bearish' | 'neutral';\n strength: number; // 0-100\n signals: string[];\n}\n\nexport interface TrendingToken {\n name: string;\n symbol: string;\n chain: string;\n priceUsd: string;\n priceChange24h: number;\n volume24h: number;\n liquidity: number;\n marketCap: number | null;\n url: string;\n source: 'dexscreener' | 'coingecko';\n}\n\n/**\n * Fetch market data for established coins from CoinGecko.\n */\nexport async function fetchMarketData(symbol: string): Promise<MarketData | null> {\n try {\n const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${encodeURIComponent(symbol.toLowerCase())}&order=market_cap_desc&per_page=1&page=1&sparkline=false&price_change_percentage=24h,7d`;\n const response = await fetch(url);\n\n if (!response.ok) return null;\n\n const data = (await response.json()) as Record<string, unknown>[];\n if (!data || data.length === 0) return null;\n\n const coin = data[0];\n if (!coin) return null;\n\n return {\n symbol: String(coin['symbol'] ?? '').toUpperCase(),\n name: String(coin['name'] ?? ''),\n price: Number(coin['current_price'] ?? 0),\n priceChange24h: Number(coin['price_change_percentage_24h'] ?? 0),\n priceChange7d: Number(coin['price_change_percentage_7d_in_currency'] ?? 0),\n volume24h: Number(coin['total_volume'] ?? 0),\n marketCap: Number(coin['market_cap'] ?? 0),\n rank: coin['market_cap_rank'] != null ? Number(coin['market_cap_rank']) : null,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Search for any token on DEXes via DexScreener.\n * Works for all tokens — including meme coins and newly launched tokens.\n */\nexport async function fetchTokenFromDex(query: string): Promise<DexPair[]> {\n try {\n return await dexSearch(query);\n } catch {\n return [];\n }\n}\n\n/**\n * Get currently trending/hot tokens from DexScreener (boosted tokens)\n * and CoinGecko trending combined.\n */\nexport async function fetchTrendingTokens(): Promise<TrendingToken[]> {\n const results: TrendingToken[] = [];\n\n // DexScreener: top boosted tokens\n try {\n const boosted = await getTopBoostedTokens();\n // Boosted tokens don't have pair data, so search for the top ones\n const seen = new Set<string>();\n for (const token of boosted.slice(0, 10)) {\n const key = `${token.chainId}:${token.tokenAddress}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n try {\n const pairs = await dexSearch(token.tokenAddress);\n const pair = pairs[0];\n if (pair) {\n results.push(dexPairToTrending(pair));\n }\n } catch {\n // skip individual failures\n }\n }\n } catch {\n // DexScreener unavailable\n }\n\n // CoinGecko: trending coins\n try {\n const response = await fetch('https://api.coingecko.com/api/v3/search/trending');\n if (response.ok) {\n const data = (await response.json()) as {\n coins: { item: { id: string; name: string; symbol: string; market_cap_rank: number } }[];\n };\n for (const { item } of (data.coins ?? []).slice(0, 7)) {\n results.push({\n name: item.name,\n symbol: item.symbol.toUpperCase(),\n chain: 'multi',\n priceUsd: '(see CoinGecko)',\n priceChange24h: 0,\n volume24h: 0,\n liquidity: 0,\n marketCap: null,\n url: `https://www.coingecko.com/en/coins/${item.id}`,\n source: 'coingecko',\n });\n }\n }\n } catch {\n // CoinGecko unavailable\n }\n\n return results;\n}\n\nfunction dexPairToTrending(pair: DexPair): TrendingToken {\n return {\n name: pair.baseToken.name,\n symbol: pair.baseToken.symbol,\n chain: pair.chainId,\n priceUsd: pair.priceUsd ?? '0',\n priceChange24h: pair.priceChange?.h24 ?? 0,\n volume24h: pair.volume?.h24 ?? 0,\n liquidity: pair.liquidity?.usd ?? 0,\n marketCap: pair.marketCap ?? pair.fdv ?? null,\n url: pair.url,\n source: 'dexscreener',\n };\n}\n\n/**\n * ML-enhanced trend analysis. Falls back to rule-based analyzeTrend().\n */\nexport async function analyzeTrendML(data: MarketData): Promise<MarketTrend> {\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const volumeToMcap = data.marketCap > 0 ? data.volume24h / data.marketCap : 0;\n const result = await mlClient.scoreTrend({\n price_change_24h: data.priceChange24h,\n price_change_7d: data.priceChange7d,\n volume_24h: data.volume24h,\n market_cap: data.marketCap,\n volume_to_mcap_ratio: volumeToMcap,\n rank: data.rank ?? 0,\n });\n if (result) {\n const signals: string[] = [`ML trend score: ${result.score}/100 (${result.model})`];\n if (result.feature_importances) {\n const topFeature = Object.entries(result.feature_importances).sort(\n (a, b) => b[1] - a[1],\n )[0];\n if (topFeature) {\n signals.push(`Top driver: ${topFeature[0]}`);\n }\n }\n return {\n direction: result.direction,\n strength: result.score,\n signals,\n };\n }\n } catch {\n // ML unavailable — fallback\n }\n }\n return analyzeTrend(data);\n}\n\nexport function analyzeTrend(data: MarketData): MarketTrend {\n const signals: string[] = [];\n let score = 50;\n\n if (data.priceChange24h > 5) {\n score += 15;\n signals.push(`Strong 24h gain: +${data.priceChange24h.toFixed(2)}%`);\n } else if (data.priceChange24h < -5) {\n score -= 15;\n signals.push(`Significant 24h drop: ${data.priceChange24h.toFixed(2)}%`);\n }\n\n if (data.priceChange7d > 10) {\n score += 20;\n signals.push(`Bullish weekly trend: +${data.priceChange7d.toFixed(2)}%`);\n } else if (data.priceChange7d < -10) {\n score -= 20;\n signals.push(`Bearish weekly trend: ${data.priceChange7d.toFixed(2)}%`);\n }\n\n if (data.volume24h > data.marketCap * 0.1) {\n signals.push('High volume relative to market cap');\n score += 5;\n }\n\n const direction: MarketTrend['direction'] =\n score > 60 ? 'bullish' : score < 40 ? 'bearish' : 'neutral';\n\n return {\n direction,\n strength: Math.max(0, Math.min(100, score)),\n signals,\n };\n}\n","// ---------------------------------------------------------------------------\n// CryptoPanic API client — crypto news with sentiment\n// https://cryptopanic.com/developers/api/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://cryptopanic.com/api/free/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CryptoNews {\n id: number;\n title: string;\n url: string;\n source: { title: string; domain: string };\n sentiment: 'positive' | 'negative' | 'neutral';\n currencies: { code: string; title: string }[];\n publishedAt: string;\n kind: 'news' | 'media';\n}\n\ninterface RawPost {\n id: number;\n title: string;\n url: string;\n source: { title: string; domain: string };\n votes: { positive: number; negative: number; important: number };\n currencies?: { code: string; title: string }[];\n published_at: string;\n kind: string;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch latest crypto news, optionally filtered by currency symbol.\n * If an API token is provided, uses authenticated endpoint for better filtering.\n */\nexport async function fetchCryptoNews(symbol?: string, apiToken?: string): Promise<CryptoNews[]> {\n // CryptoPanic requires auth_token even for free tier.\n // If no token provided, return empty rather than erroring.\n if (!apiToken) {\n return [];\n }\n\n const params = new URLSearchParams({ auth_token: apiToken });\n if (symbol) {\n params.set('currencies', symbol.toUpperCase());\n }\n\n const url = `${BASE_URL}/posts/?${params.toString()}`;\n const res = await fetch(url);\n\n if (!res.ok) {\n throw new Error(`CryptoPanic API error: ${res.status} ${res.statusText}`);\n }\n\n const data = (await res.json()) as { results: RawPost[] };\n const posts = data.results ?? [];\n\n return posts.map((post): CryptoNews => {\n // Derive sentiment from vote counts\n const { positive, negative } = post.votes;\n let sentiment: CryptoNews['sentiment'] = 'neutral';\n if (positive > negative * 2) sentiment = 'positive';\n else if (negative > positive * 2) sentiment = 'negative';\n\n return {\n id: post.id,\n title: post.title,\n url: post.url,\n source: post.source,\n sentiment,\n currencies: post.currencies ?? [],\n publishedAt: post.published_at,\n kind: post.kind === 'media' ? 'media' : 'news',\n };\n });\n}\n","// ---------------------------------------------------------------------------\n// Sentiment analysis — aggregates CryptoPanic news + DexScreener buy/sell data\n// ---------------------------------------------------------------------------\n\nimport { fetchCryptoNews } from '../../data/sources/cryptopanic.js';\nimport { searchTokens } from '../../data/sources/dexscreener.js';\nimport { getConfig } from '../../config/loader.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\n\nexport interface SentimentData {\n source: string;\n score: number; // -1 to 1\n volume: number;\n trending: boolean;\n topMentions: string[];\n mlSentiment?: string;\n mlConfidence?: number;\n mlTopics?: string[];\n}\n\nexport interface SentimentSummary {\n overall: number; // -1 to 1\n sources: SentimentData[];\n consensus: 'positive' | 'negative' | 'mixed' | 'neutral';\n}\n\n/**\n * Analyze sentiment for a token/topic by aggregating:\n * 1. CryptoPanic news sentiment\n * 2. DexScreener buy/sell ratio (market sentiment proxy)\n */\nexport async function analyzeSentiment(query: string): Promise<SentimentSummary> {\n const sources: SentimentData[] = [];\n\n // 1. CryptoPanic news sentiment (enhanced with ML NLP when available)\n try {\n let apiToken: string | undefined;\n try {\n apiToken = getConfig().cryptopanicApiKey;\n } catch {\n /* config not loaded */\n }\n const news = await fetchCryptoNews(query, apiToken);\n if (news.length > 0) {\n // Try ML sentiment analysis on headlines\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n let newsScore: number;\n let mlSentiment: string | undefined;\n let mlConfidence: number | undefined;\n let mlTopics: string[] | undefined;\n\n if (mlClient) {\n // Use ML NLP for deeper sentiment analysis\n const headlines = news.slice(0, 10).map((n) => n.title);\n const mlResults = await mlClient.analyzeSentimentBatch(headlines);\n if (mlResults.length > 0) {\n const avgScore = mlResults.reduce((s, r) => s + r.score, 0) / mlResults.length;\n const avgConf = mlResults.reduce((s, r) => s + r.confidence, 0) / mlResults.length;\n const allTopics = [...new Set(mlResults.flatMap((r) => r.key_topics))];\n newsScore = avgScore;\n mlSentiment = avgScore > 0.2 ? 'bullish' : avgScore < -0.2 ? 'bearish' : 'neutral';\n mlConfidence = avgConf;\n mlTopics = allTopics.slice(0, 5);\n } else {\n // Fallback to vote counts\n newsScore = countBasedScore(news);\n }\n } else {\n newsScore = countBasedScore(news);\n }\n\n const total = news.length;\n sources.push({\n source: mlSentiment ? 'ML NLP Sentiment' : 'CryptoPanic News',\n score: newsScore,\n volume: total,\n trending: total > 5,\n topMentions: news.slice(0, 3).map((n) => n.title),\n mlSentiment,\n mlConfidence,\n mlTopics,\n });\n }\n } catch {\n // CryptoPanic unavailable\n }\n\n // 2. DexScreener buy/sell ratio\n try {\n const pairs = await searchTokens(query);\n const topPair = pairs[0];\n if (topPair) {\n const buys24h = topPair.txns?.h24?.buys ?? 0;\n const sells24h = topPair.txns?.h24?.sells ?? 0;\n const totalTxns = buys24h + sells24h;\n\n let dexScore = 0;\n if (totalTxns > 0) {\n // Buy ratio: 0-1, centered at 0.5 → score: -1 to 1\n dexScore = (buys24h / totalTxns - 0.5) * 2;\n }\n\n const priceChange = topPair.priceChange?.h24 ?? 0;\n\n sources.push({\n source: 'DexScreener Market',\n score: dexScore,\n volume: totalTxns,\n trending: topPair.volume?.h24 > 100000,\n topMentions: [\n `${topPair.baseToken.symbol}: $${topPair.priceUsd ?? '?'}`,\n `24h: ${buys24h} buys / ${sells24h} sells`,\n `Price change: ${priceChange > 0 ? '+' : ''}${priceChange.toFixed(2)}%`,\n ],\n });\n }\n } catch {\n // DexScreener unavailable\n }\n\n // Aggregate\n if (sources.length === 0) {\n return { overall: 0, sources: [], consensus: 'neutral' };\n }\n\n const totalScore = sources.reduce((sum, s) => sum + s.score, 0);\n const overall = totalScore / sources.length;\n\n let consensus: SentimentSummary['consensus'] = 'neutral';\n if (overall > 0.2) consensus = 'positive';\n else if (overall < -0.2) consensus = 'negative';\n else if (sources.length > 1 && Math.abs(sources[0]!.score - sources[1]!.score) > 0.5) {\n consensus = 'mixed';\n }\n\n return { overall, sources, consensus };\n}\n\nfunction countBasedScore(news: { sentiment?: string }[]): number {\n let pos = 0;\n let neg = 0;\n for (const article of news) {\n if (article.sentiment === 'positive') pos++;\n else if (article.sentiment === 'negative') neg++;\n }\n const total = news.length;\n return total > 0 ? (pos - neg) / total : 0;\n}\n","// ---------------------------------------------------------------------------\n// Binance public API client — no auth required, 1200 req/min\n// https://binance-docs.github.io/apidocs/spot/en/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.binance.com/api/v3';\nconst FUTURES_URL = 'https://fapi.binance.com/fapi/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TickerPrice {\n symbol: string;\n price: number;\n change24h: number;\n}\n\nexport interface Kline {\n openTime: number;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n closeTime: number;\n quoteVolume: number;\n trades: number;\n}\n\nexport interface OrderBookSummary {\n symbol: string;\n bidPrice: number;\n bidQty: number;\n askPrice: number;\n askQty: number;\n spread: number;\n spreadPct: number;\n}\n\nexport interface FundingRate {\n symbol: string;\n fundingRate: number;\n fundingTime: number;\n markPrice: number;\n}\n\nexport interface OpenInterest {\n symbol: string;\n openInterest: number;\n notionalValue: number;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol mapping: common names -> Binance trading pairs\n// ---------------------------------------------------------------------------\n\nconst SYMBOL_MAP: Record<string, string> = {\n BTC: 'BTCUSDT',\n ETH: 'ETHUSDT',\n SOL: 'SOLUSDT',\n BNB: 'BNBUSDT',\n XRP: 'XRPUSDT',\n ADA: 'ADAUSDT',\n DOGE: 'DOGEUSDT',\n DOT: 'DOTUSDT',\n AVAX: 'AVAXUSDT',\n MATIC: 'MATICUSDT',\n LINK: 'LINKUSDT',\n UNI: 'UNIUSDT',\n ATOM: 'ATOMUSDT',\n NEAR: 'NEARUSDT',\n ARB: 'ARBUSDT',\n OP: 'OPUSDT',\n SUI: 'SUIUSDT',\n APT: 'APTUSDT',\n PEPE: 'PEPEUSDT',\n SHIB: 'SHIBUSDT',\n FLOKI: 'FLOKIUSDT',\n BONK: 'BONKUSDT',\n WIF: 'WIFUSDT',\n};\n\nfunction resolvePair(symbol: string): string {\n const upper = symbol.toUpperCase();\n return SYMBOL_MAP[upper] ?? `${upper}USDT`;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Binance API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n// ---------------------------------------------------------------------------\n// Spot API\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch current price and 24h change for a symbol.\n * Uses Binance 24hr ticker — single request, very reliable.\n */\nexport async function fetchTickerPrice(symbol: string): Promise<TickerPrice> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<{\n symbol: string;\n lastPrice: string;\n priceChangePercent: string;\n }>(`${BASE_URL}/ticker/24hr?symbol=${pair}`);\n\n return {\n symbol: symbol.toUpperCase(),\n price: parseFloat(data.lastPrice),\n change24h: parseFloat(data.priceChangePercent),\n };\n}\n\n/**\n * Fetch prices for multiple symbols in one request.\n */\nexport async function fetchMultipleTickerPrices(\n symbols: string[],\n): Promise<Map<string, TickerPrice>> {\n const pairs = symbols.map(resolvePair);\n const encoded = encodeURIComponent(JSON.stringify(pairs));\n const data = await fetchJson<{ symbol: string; lastPrice: string; priceChangePercent: string }[]>(\n `${BASE_URL}/ticker/24hr?symbols=${encoded}`,\n );\n\n const result = new Map<string, TickerPrice>();\n for (const item of data) {\n // Reverse lookup from pair to short symbol\n const short =\n Object.entries(SYMBOL_MAP).find(([, v]) => v === item.symbol)?.[0] ??\n item.symbol.replace('USDT', '');\n result.set(short, {\n symbol: short,\n price: parseFloat(item.lastPrice),\n change24h: parseFloat(item.priceChangePercent),\n });\n }\n return result;\n}\n\n/**\n * Fetch kline (candlestick) data.\n * Intervals: 1m, 5m, 15m, 1h, 4h, 1d, 1w\n */\nexport async function fetchKlines(symbol: string, interval: string, limit = 100): Promise<Kline[]> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<(string | number)[][]>(\n `${BASE_URL}/klines?symbol=${pair}&interval=${interval}&limit=${limit}`,\n );\n\n return data.map((k) => ({\n openTime: Number(k[0]),\n open: parseFloat(String(k[1])),\n high: parseFloat(String(k[2])),\n low: parseFloat(String(k[3])),\n close: parseFloat(String(k[4])),\n volume: parseFloat(String(k[5])),\n closeTime: Number(k[6]),\n quoteVolume: parseFloat(String(k[7])),\n trades: Number(k[8]),\n }));\n}\n\n/**\n * Fetch order book depth summary (best bid/ask + spread).\n */\nexport async function fetchOrderBookSummary(symbol: string): Promise<OrderBookSummary> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<{\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n }>(`${BASE_URL}/ticker/bookTicker?symbol=${pair}`);\n\n const bid = parseFloat(data.bidPrice);\n const ask = parseFloat(data.askPrice);\n\n return {\n symbol: symbol.toUpperCase(),\n bidPrice: bid,\n bidQty: parseFloat(data.bidQty),\n askPrice: ask,\n askQty: parseFloat(data.askQty),\n spread: ask - bid,\n spreadPct: bid > 0 ? ((ask - bid) / bid) * 100 : 0,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Futures API (public, no auth for read-only)\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch current funding rate for a futures symbol.\n */\nexport async function fetchFundingRate(symbol: string): Promise<FundingRate> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<\n { symbol: string; fundingRate: string; fundingTime: number; markPrice: string }[]\n >(`${FUTURES_URL}/premiumIndex?symbol=${pair}`);\n\n const item = data[0];\n if (!item) throw new Error(`No funding data for ${pair}`);\n\n return {\n symbol: symbol.toUpperCase(),\n fundingRate: parseFloat(item.fundingRate),\n fundingTime: item.fundingTime,\n markPrice: parseFloat(item.markPrice),\n };\n}\n\n/**\n * Fetch open interest for a futures symbol.\n */\nexport async function fetchOpenInterest(symbol: string): Promise<OpenInterest> {\n const pair = resolvePair(symbol);\n const [oiData, tickerData] = await Promise.all([\n fetchJson<{ symbol: string; openInterest: string }>(\n `${FUTURES_URL}/openInterest?symbol=${pair}`,\n ),\n fetchJson<{ symbol: string; lastPrice: string }>(`${FUTURES_URL}/ticker/price?symbol=${pair}`),\n ]);\n\n const oi = parseFloat(oiData.openInterest);\n const price = parseFloat(tickerData.lastPrice);\n\n return {\n symbol: symbol.toUpperCase(),\n openInterest: oi,\n notionalValue: oi * price,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Market overview\n// ---------------------------------------------------------------------------\n\nexport interface Ticker24hr {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n quoteVolume: number;\n highPrice: number;\n lowPrice: number;\n}\n\n/**\n * Fetch all USDT pairs sorted by 24h price change percentage.\n * Returns the top N gainers and top N losers.\n */\nexport async function fetchTopGainersLosers(limit = 10): Promise<{\n gainers: Ticker24hr[];\n losers: Ticker24hr[];\n}> {\n const data = await fetchJson<\n {\n symbol: string;\n lastPrice: string;\n priceChangePercent: string;\n volume: string;\n quoteVolume: string;\n highPrice: string;\n lowPrice: string;\n }[]\n >(`${BASE_URL}/ticker/24hr`);\n\n const usdtPairs = data\n .filter((t) => t.symbol.endsWith('USDT') && !t.symbol.includes('_'))\n .map((t) => ({\n symbol: t.symbol.replace('USDT', ''),\n price: parseFloat(t.lastPrice),\n change24h: parseFloat(t.priceChangePercent),\n volume: parseFloat(t.volume),\n quoteVolume: parseFloat(t.quoteVolume),\n highPrice: parseFloat(t.highPrice),\n lowPrice: parseFloat(t.lowPrice),\n }))\n .filter((t) => t.quoteVolume > 100_000); // filter dust pairs\n\n const sorted = [...usdtPairs].sort((a, b) => b.change24h - a.change24h);\n return {\n gainers: sorted.slice(0, limit),\n losers: sorted.slice(-limit).reverse(),\n };\n}\n\n/**\n * Check if a symbol exists on Binance.\n */\nexport async function isValidSymbol(symbol: string): Promise<boolean> {\n try {\n const pair = resolvePair(symbol);\n await fetchJson(`${BASE_URL}/ticker/price?symbol=${pair}`);\n return true;\n } catch {\n return false;\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n// ---------------------------------------------------------------------------\n// Pure math indicators — no API calls, no side effects\n// Array indexing uses non-null assertions after bounds checks for performance.\n// ---------------------------------------------------------------------------\n\n/**\n * Calculate RSI (Relative Strength Index).\n * RSI = 100 - (100 / (1 + avgGain / avgLoss))\n */\nexport function calculateRSI(closes: number[], period = 14): number | null {\n if (closes.length < period + 1) return null;\n\n let avgGain = 0;\n let avgLoss = 0;\n\n // Initial averages\n for (let i = 1; i <= period; i++) {\n const change = closes[i]! - closes[i - 1]!;\n if (change > 0) avgGain += change;\n else avgLoss += Math.abs(change);\n }\n avgGain /= period;\n avgLoss /= period;\n\n // Smooth with Wilder's method\n for (let i = period + 1; i < closes.length; i++) {\n const change = closes[i]! - closes[i - 1]!;\n if (change > 0) {\n avgGain = (avgGain * (period - 1) + change) / period;\n avgLoss = (avgLoss * (period - 1)) / period;\n } else {\n avgGain = (avgGain * (period - 1)) / period;\n avgLoss = (avgLoss * (period - 1) + Math.abs(change)) / period;\n }\n }\n\n if (avgLoss === 0) return 100;\n const rs = avgGain / avgLoss;\n return 100 - 100 / (1 + rs);\n}\n\n/**\n * Calculate Exponential Moving Average.\n */\nexport function calculateEMA(values: number[], period: number): number[] {\n if (values.length < period) return [];\n\n const multiplier = 2 / (period + 1);\n const ema: number[] = [];\n\n // SMA for the first value\n let sum = 0;\n for (let i = 0; i < period; i++) {\n sum += values[i]!;\n }\n ema.push(sum / period);\n\n // EMA for subsequent values\n for (let i = period; i < values.length; i++) {\n const prev = ema[ema.length - 1]!;\n ema.push((values[i]! - prev) * multiplier + prev);\n }\n\n return ema;\n}\n\n/**\n * Calculate Simple Moving Average.\n */\nexport function calculateSMA(values: number[], period: number): number[] {\n if (values.length < period) return [];\n\n const sma: number[] = [];\n let sum = 0;\n\n for (let i = 0; i < period; i++) {\n sum += values[i]!;\n }\n sma.push(sum / period);\n\n for (let i = period; i < values.length; i++) {\n sum = sum - values[i - period]! + values[i]!;\n sma.push(sum / period);\n }\n\n return sma;\n}\n\n/**\n * Calculate MACD (Moving Average Convergence Divergence).\n * Returns { macd, signal, histogram } for the latest value.\n */\nexport function calculateMACD(\n closes: number[],\n fastPeriod = 12,\n slowPeriod = 26,\n signalPeriod = 9,\n): { macd: number; signal: number; histogram: number } | null {\n if (closes.length < slowPeriod + signalPeriod) return null;\n\n const fastEMA = calculateEMA(closes, fastPeriod);\n const slowEMA = calculateEMA(closes, slowPeriod);\n\n // Align EMAs — fast EMA starts at index (fastPeriod-1), slow at (slowPeriod-1)\n const offset = slowPeriod - fastPeriod;\n const macdLine: number[] = [];\n for (let i = 0; i < slowEMA.length; i++) {\n macdLine.push(fastEMA[i + offset]! - slowEMA[i]!);\n }\n\n if (macdLine.length < signalPeriod) return null;\n\n const signalLine = calculateEMA(macdLine, signalPeriod);\n const lastMacd = macdLine[macdLine.length - 1]!;\n const lastSignal = signalLine[signalLine.length - 1]!;\n\n return {\n macd: lastMacd,\n signal: lastSignal,\n histogram: lastMacd - lastSignal,\n };\n}\n\n/**\n * Calculate Bollinger Bands.\n * Returns { upper, middle, lower, percentB } for the latest value.\n */\nexport function calculateBollingerBands(\n closes: number[],\n period = 20,\n stdDevMultiplier = 2,\n): { upper: number; middle: number; lower: number; percentB: number } | null {\n if (closes.length < period) return null;\n\n const slice = closes.slice(-period);\n const middle = slice.reduce((a, b) => a + b, 0) / period;\n\n const variance = slice.reduce((sum, val) => sum + (val - middle) ** 2, 0) / period;\n const stdDev = Math.sqrt(variance);\n\n const upper = middle + stdDevMultiplier * stdDev;\n const lower = middle - stdDevMultiplier * stdDev;\n const current = closes[closes.length - 1]!;\n const percentB = upper !== lower ? (current - lower) / (upper - lower) : 0.5;\n\n return { upper, middle, lower, percentB };\n}\n\n/**\n * Calculate Average True Range (ATR).\n */\nexport function calculateATR(\n highs: number[],\n lows: number[],\n closes: number[],\n period = 14,\n): number | null {\n const len = Math.min(highs.length, lows.length, closes.length);\n if (len < period + 1) return null;\n\n const trueRanges: number[] = [];\n for (let i = 1; i < len; i++) {\n const tr = Math.max(\n highs[i]! - lows[i]!,\n Math.abs(highs[i]! - closes[i - 1]!),\n Math.abs(lows[i]! - closes[i - 1]!),\n );\n trueRanges.push(tr);\n }\n\n if (trueRanges.length < period) return null;\n\n // Initial ATR is simple average\n let atr = 0;\n for (let i = 0; i < period; i++) {\n atr += trueRanges[i]!;\n }\n atr /= period;\n\n // Smooth with Wilder's method\n for (let i = period; i < trueRanges.length; i++) {\n atr = (atr * (period - 1) + trueRanges[i]!) / period;\n }\n\n return atr;\n}\n\n/**\n * Calculate On-Balance Volume (OBV).\n * Returns the final OBV value.\n */\nexport function calculateOBV(closes: number[], volumes: number[]): number | null {\n const len = Math.min(closes.length, volumes.length);\n if (len < 2) return null;\n\n let obv = 0;\n for (let i = 1; i < len; i++) {\n if (closes[i]! > closes[i - 1]!) {\n obv += volumes[i]!;\n } else if (closes[i]! < closes[i - 1]!) {\n obv -= volumes[i]!;\n }\n // if equal, obv stays the same\n }\n\n return obv;\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n// ---------------------------------------------------------------------------\n// Technical analysis analyzer — runs all indicators on kline data\n// ---------------------------------------------------------------------------\n\nimport { fetchKlines } from '../../data/sources/binance.js';\nimport type { TechnicalAnalysis, TechnicalSignal, SignalDirection } from './types.js';\nimport {\n calculateRSI,\n calculateEMA,\n calculateSMA,\n calculateMACD,\n calculateBollingerBands,\n calculateATR,\n calculateOBV,\n} from './indicators.js';\nimport { getMLClient } from '../../ml/client.js';\n\n/**\n * Run full technical analysis on a symbol using Binance kline data.\n */\nexport async function analyzeTechnicals(\n symbol: string,\n timeframe = '4h',\n): Promise<TechnicalAnalysis> {\n const klines = await fetchKlines(symbol, timeframe, 100);\n\n const closes = klines.map((k) => k.close);\n const highs = klines.map((k) => k.high);\n const lows = klines.map((k) => k.low);\n const volumes = klines.map((k) => k.volume);\n\n const signals: TechnicalSignal[] = [];\n\n // RSI\n const rsi = calculateRSI(closes);\n if (rsi !== null) {\n signals.push(interpretRSI(rsi));\n }\n\n // MACD\n const macd = calculateMACD(closes);\n if (macd !== null) {\n signals.push(interpretMACD(macd));\n }\n\n // Bollinger Bands\n const bb = calculateBollingerBands(closes);\n if (bb !== null) {\n signals.push(interpretBollinger(bb, closes[closes.length - 1]!));\n }\n\n // EMA crossover\n const ema12 = calculateEMA(closes, 12);\n const ema26 = calculateEMA(closes, 26);\n if (ema12.length > 0 && ema26.length > 0) {\n signals.push(interpretEMACrossover(ema12[ema12.length - 1]!, ema26[ema26.length - 1]!));\n }\n\n // ATR\n const atr = calculateATR(highs, lows, closes);\n if (atr !== null) {\n const currentPrice = closes[closes.length - 1]!;\n signals.push(interpretATR(atr, currentPrice));\n }\n\n // OBV\n const obv = calculateOBV(closes, volumes);\n if (obv !== null) {\n // Compare OBV direction with price direction\n const priceChange =\n closes.length >= 2 ? closes[closes.length - 1]! - closes[closes.length - 2]! : 0;\n signals.push(interpretOBV(obv, priceChange));\n }\n\n // SMA\n const sma20 = calculateSMA(closes, 20);\n\n const currentPrice = closes[closes.length - 1]!;\n const prevPrice = closes.length >= 2 ? closes[closes.length - 2]! : currentPrice;\n const priceChange = currentPrice - prevPrice;\n const ema12Val = ema12.length > 0 ? ema12[ema12.length - 1]! : 0;\n const ema26Val = ema26.length > 0 ? ema26[ema26.length - 1]! : 0;\n const emaCrossPct = ema26Val !== 0 ? ((ema12Val - ema26Val) / ema26Val) * 100 : 0;\n const atrPct = atr !== null && currentPrice > 0 ? (atr / currentPrice) * 100 : 0;\n const bbBandwidth = bb !== null && bb.middle > 0 ? ((bb.upper - bb.lower) / bb.middle) * 100 : 0;\n\n // ML: try ML TA interpreter for signals + weights + composite\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const mlResult = await mlClient.interpretTA({\n rsi: rsi ?? 50,\n macd_histogram: macd?.histogram ?? 0,\n macd_line: macd?.macd ?? 0,\n macd_signal: macd?.signal ?? 0,\n bb_percent_b: bb?.percentB ?? 0.5,\n bb_bandwidth: bbBandwidth,\n ema12: ema12Val,\n ema26: ema26Val,\n ema_cross_pct: emaCrossPct,\n atr: atr ?? 0,\n atr_pct: atrPct,\n obv: obv ?? 0,\n price_change: priceChange,\n });\n if (mlResult) {\n // Map ML signals to TechnicalSignal format\n const mlSignals: TechnicalSignal[] = mlResult.signals.map((s) => ({\n name: s.name,\n value: 0,\n signal: s.direction as SignalDirection,\n strength: s.strength,\n description: s.description,\n }));\n\n return {\n symbol: symbol.toUpperCase(),\n timeframe,\n signals: mlSignals,\n composite: {\n direction: mlResult.composite.direction as SignalDirection,\n score: mlResult.composite.score,\n confidence: mlResult.composite.confidence,\n },\n indicators: {\n rsi: rsi,\n macd: macd,\n bollingerBands: bb,\n ema12: ema12Val || null,\n ema26: ema26Val || null,\n sma20: sma20.length > 0 ? sma20[sma20.length - 1]! : null,\n atr: atr,\n obv: obv,\n },\n timestamp: Date.now(),\n };\n }\n } catch {\n // ML unavailable — fall through to rule-based\n }\n }\n\n // Composite score: weighted average of signal strengths\n const composite = calculateComposite(signals);\n\n return {\n symbol: symbol.toUpperCase(),\n timeframe,\n signals,\n composite,\n indicators: {\n rsi: rsi,\n macd: macd,\n bollingerBands: bb,\n ema12: ema12Val || null,\n ema26: ema26Val || null,\n sma20: sma20.length > 0 ? sma20[sma20.length - 1]! : null,\n atr: atr,\n obv: obv,\n },\n timestamp: Date.now(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signal interpretation\n// ---------------------------------------------------------------------------\n\nconst WEIGHTS: Record<string, number> = {\n RSI: 20,\n MACD: 20,\n 'Bollinger Bands': 15,\n 'EMA Crossover': 20,\n ATR: 10,\n OBV: 15,\n};\n\nfunction interpretRSI(rsi: number): TechnicalSignal {\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (rsi > 70) {\n signal = 'bearish';\n strength = Math.min(100, 50 + (rsi - 70) * 1.5);\n description = `RSI ${rsi.toFixed(1)} — overbought territory, potential pullback`;\n } else if (rsi < 30) {\n signal = 'bullish';\n strength = Math.min(100, 50 + (30 - rsi) * 1.5);\n description = `RSI ${rsi.toFixed(1)} — oversold territory, potential bounce`;\n } else if (rsi > 60) {\n signal = 'bullish';\n strength = 40 + (rsi - 60);\n description = `RSI ${rsi.toFixed(1)} — bullish momentum`;\n } else if (rsi < 40) {\n signal = 'bearish';\n strength = 40 + (40 - rsi);\n description = `RSI ${rsi.toFixed(1)} — bearish momentum`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = `RSI ${rsi.toFixed(1)} — neutral zone`;\n }\n\n return { name: 'RSI', value: rsi, signal, strength, description };\n}\n\nfunction interpretMACD(macd: { macd: number; signal: number; histogram: number }): TechnicalSignal {\n const { histogram } = macd;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (histogram > 0) {\n signal = 'bullish';\n strength = Math.min(90, 50 + Math.abs(histogram) * 100);\n description = `MACD histogram positive (${histogram.toFixed(4)}) — bullish momentum`;\n } else if (histogram < 0) {\n signal = 'bearish';\n strength = Math.min(90, 50 + Math.abs(histogram) * 100);\n description = `MACD histogram negative (${histogram.toFixed(4)}) — bearish momentum`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'MACD at signal line — no clear direction';\n }\n\n // Crossover detection\n if (macd.macd > macd.signal && histogram > 0 && histogram < 0.001) {\n description += ' (fresh bullish crossover)';\n strength = Math.min(100, strength + 20);\n } else if (macd.macd < macd.signal && histogram < 0 && histogram > -0.001) {\n description += ' (fresh bearish crossover)';\n strength = Math.min(100, strength + 20);\n }\n\n return { name: 'MACD', value: histogram, signal, strength, description };\n}\n\nfunction interpretBollinger(\n bb: { upper: number; middle: number; lower: number; percentB: number },\n price: number,\n): TechnicalSignal {\n const { percentB } = bb;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (percentB > 1) {\n signal = 'bullish';\n strength = 70;\n description = `Price above upper Bollinger Band (%B: ${percentB.toFixed(2)}) — strong breakout`;\n } else if (percentB > 0.8) {\n signal = 'bearish';\n strength = 55;\n description = `Price near upper band (%B: ${percentB.toFixed(2)}) — extended, potential pullback`;\n } else if (percentB < 0) {\n signal = 'bearish';\n strength = 70;\n description = `Price below lower Bollinger Band (%B: ${percentB.toFixed(2)}) — breakdown`;\n } else if (percentB < 0.2) {\n signal = 'bullish';\n strength = 55;\n description = `Price near lower band (%B: ${percentB.toFixed(2)}) — compressed, potential bounce`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = `Price within bands (%B: ${percentB.toFixed(2)}) at $${price.toLocaleString()}`;\n }\n\n return { name: 'Bollinger Bands', value: percentB, signal, strength, description };\n}\n\nfunction interpretEMACrossover(ema12: number, ema26: number): TechnicalSignal {\n const diff = ema12 - ema26;\n const pctDiff = ema26 !== 0 ? (diff / ema26) * 100 : 0;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (diff > 0) {\n signal = 'bullish';\n strength = Math.min(90, 50 + Math.abs(pctDiff) * 10);\n description = `EMA(12) above EMA(26) by ${pctDiff.toFixed(2)}% — bullish trend`;\n } else if (diff < 0) {\n signal = 'bearish';\n strength = Math.min(90, 50 + Math.abs(pctDiff) * 10);\n description = `EMA(12) below EMA(26) by ${Math.abs(pctDiff).toFixed(2)}% — bearish trend`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'EMA(12) = EMA(26) — no trend';\n }\n\n return { name: 'EMA Crossover', value: pctDiff, signal, strength, description };\n}\n\nfunction interpretATR(atr: number, price: number): TechnicalSignal {\n const atrPct = price > 0 ? (atr / price) * 100 : 0;\n let description: string;\n\n if (atrPct > 5) {\n description = `ATR ${atrPct.toFixed(2)}% of price — high volatility, breakout conditions`;\n } else if (atrPct > 2) {\n description = `ATR ${atrPct.toFixed(2)}% of price — moderate volatility`;\n } else {\n description = `ATR ${atrPct.toFixed(2)}% of price — low volatility, consolidation`;\n }\n\n return { name: 'ATR', value: atr, signal: 'neutral', strength: 40, description };\n}\n\nfunction interpretOBV(obv: number, priceChange: number): TechnicalSignal {\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (obv > 0 && priceChange > 0) {\n signal = 'bullish';\n strength = 65;\n description = 'OBV positive with rising price — confirmed uptrend';\n } else if (obv > 0 && priceChange <= 0) {\n signal = 'bullish';\n strength = 70;\n description = 'OBV positive but price flat/down — accumulation (bullish divergence)';\n } else if (obv < 0 && priceChange < 0) {\n signal = 'bearish';\n strength = 65;\n description = 'OBV negative with falling price — confirmed downtrend';\n } else if (obv < 0 && priceChange >= 0) {\n signal = 'bearish';\n strength = 70;\n description = 'OBV negative but price flat/up — distribution (bearish divergence)';\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'OBV neutral';\n }\n\n return { name: 'OBV', value: obv, signal, strength, description };\n}\n\nfunction calculateComposite(signals: TechnicalSignal[]): {\n direction: SignalDirection;\n score: number;\n confidence: number;\n} {\n if (signals.length === 0) {\n return { direction: 'neutral', score: 0, confidence: 0 };\n }\n\n let totalWeight = 0;\n let weightedScore = 0;\n\n for (const sig of signals) {\n const weight = WEIGHTS[sig.name] ?? 10;\n totalWeight += weight;\n\n const dirScore =\n sig.signal === 'bullish' ? sig.strength : sig.signal === 'bearish' ? -sig.strength : 0;\n weightedScore += dirScore * weight;\n }\n\n const score = totalWeight > 0 ? weightedScore / totalWeight : 0;\n\n // Confidence based on signal agreement\n const bullishCount = signals.filter((s) => s.signal === 'bullish').length;\n const bearishCount = signals.filter((s) => s.signal === 'bearish').length;\n const totalDirectional = bullishCount + bearishCount;\n const agreement =\n totalDirectional > 0 ? Math.max(bullishCount, bearishCount) / totalDirectional : 0;\n const confidence = Math.round(agreement * 100 * (signals.length / 6)); // scale by completeness\n\n const direction: SignalDirection = score > 15 ? 'bullish' : score < -15 ? 'bearish' : 'neutral';\n\n return {\n direction,\n score: Math.round(score),\n confidence: Math.min(100, confidence),\n };\n}\n","export { analyzeTechnicals } from './analyzer.js';\nexport {\n calculateRSI,\n calculateEMA,\n calculateSMA,\n calculateMACD,\n calculateBollingerBands,\n calculateATR,\n calculateOBV,\n} from './indicators.js';\nexport type { TechnicalAnalysis, TechnicalSignal, SignalDirection } from './types.js';\n","// ---------------------------------------------------------------------------\n// Fear & Greed Index — alternative.me API, no auth required\n// https://alternative.me/crypto/fear-and-greed-index/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.alternative.me/fng';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FearGreedEntry {\n value: number;\n classification: 'Extreme Fear' | 'Fear' | 'Neutral' | 'Greed' | 'Extreme Greed';\n timestamp: number;\n}\n\nexport interface FearGreedData {\n current: FearGreedEntry;\n previous: FearGreedEntry | null;\n history: FearGreedEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Fear & Greed API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\nfunction parseClassification(value: number): FearGreedEntry['classification'] {\n if (value <= 20) return 'Extreme Fear';\n if (value <= 40) return 'Fear';\n if (value <= 60) return 'Neutral';\n if (value <= 80) return 'Greed';\n return 'Extreme Greed';\n}\n\n/**\n * Fetch the current Fear & Greed Index along with recent history.\n */\nexport async function fetchFearGreedIndex(days = 7): Promise<FearGreedData> {\n const data = await fetchJson<{\n data: { value: string; value_classification: string; timestamp: string }[];\n }>(`${BASE_URL}/?limit=${days}&format=json`);\n\n const entries: FearGreedEntry[] = (data.data ?? []).map((d) => {\n const value = parseInt(d.value, 10);\n return {\n value,\n classification: parseClassification(value),\n timestamp: parseInt(d.timestamp, 10),\n };\n });\n\n return {\n current: entries[0] ?? { value: 50, classification: 'Neutral', timestamp: Date.now() / 1000 },\n previous: entries[1] ?? null,\n history: entries,\n };\n}\n","// ---------------------------------------------------------------------------\n// Feature Engineering — transforms TA + agent signals into ML feature vectors\n// ---------------------------------------------------------------------------\n\nimport { analyzeTechnicals } from '../core/technical-analysis/index.js';\nimport { fetchFundingRate, fetchTickerPrice, fetchKlines } from '../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { calculateRSI } from '../core/technical-analysis/indicators.js';\nimport type { FeatureVector } from './types.js';\n\nexport async function buildFeatureVector(symbol: string): Promise<FeatureVector> {\n // Gather all data in parallel\n const [ta, fundingResult, tickerResult, fgResult, klines] = await Promise.allSettled([\n analyzeTechnicals(symbol, '4h'),\n fetchFundingRate(symbol),\n fetchTickerPrice(symbol),\n fetchFearGreedIndex(1),\n fetchKlines(symbol, '4h', 100),\n ]);\n\n const indicators = ta.status === 'fulfilled' ? ta.value.indicators : null;\n const funding = fundingResult.status === 'fulfilled' ? fundingResult.value : null;\n const ticker = tickerResult.status === 'fulfilled' ? tickerResult.value : null;\n const fg = fgResult.status === 'fulfilled' ? fgResult.value : null;\n const candles = klines.status === 'fulfilled' ? klines.value : [];\n\n // RSI slope: rate of change over last 3 periods\n let rsiSlope = 0;\n if (candles.length >= 17) {\n const closes = candles.map((k) => k.close);\n const recentRsi = calculateRSI(closes, 14);\n const olderCloses = closes.slice(0, -3);\n const olderRsi = calculateRSI(olderCloses, 14);\n if (recentRsi !== null && olderRsi !== null) {\n rsiSlope = recentRsi - olderRsi;\n }\n }\n\n // Volume ratio: current / 20-period avg\n let volumeRatio = 1;\n if (candles.length >= 21) {\n const currentVolume = candles[candles.length - 1].volume;\n const avgVolume = candles.slice(-21, -1).reduce((sum, k) => sum + k.volume, 0) / 20;\n volumeRatio = avgVolume > 0 ? currentVolume / avgVolume : 1;\n }\n\n // EMA crossover %\n const price = ticker?.price ?? candles[candles.length - 1]?.close ?? 0;\n const ema12 = indicators?.ema12 ?? 0;\n const ema26 = indicators?.ema26 ?? 0;\n const emaCrossoverPct = price > 0 ? ((ema12 - ema26) / price) * 100 : 0;\n\n // ATR as % of price\n const atr = indicators?.atr ?? 0;\n const atrPct = price > 0 ? (atr / price) * 100 : 0;\n\n return {\n rsi: indicators?.rsi ?? 50,\n macdHistogram: indicators?.macd?.histogram ?? 0,\n bollingerPercentB: indicators?.bollingerBands?.percentB ?? 0.5,\n ema12,\n ema26,\n atr,\n obv: indicators?.obv ?? 0,\n fundingRate: funding?.fundingRate ?? 0,\n fearGreed: fg?.current.value ?? 50,\n priceChange24h: ticker?.change24h ?? 0,\n rsiSlope,\n volumeRatio,\n emaCrossoverPct,\n atrPct,\n symbol: symbol.toUpperCase(),\n timestamp: Date.now(),\n };\n}\n","// ---------------------------------------------------------------------------\n// Multi-signal prediction engine\n// ---------------------------------------------------------------------------\n\nimport { analyzeTechnicals } from '../technical-analysis/index.js';\nimport { analyzeSentiment } from './sentiment.js';\nimport { fetchFearGreedIndex } from '../../data/sources/fear-greed.js';\nimport {\n fetchFundingRate,\n fetchOpenInterest,\n fetchTickerPrice,\n} from '../../data/sources/binance.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { buildFeatureVector } from '../../ml/feature-engineer.js';\nimport type { MLPredictionResult } from '../../ml/types.js';\nimport { getConfig } from '../../config/loader.js';\n\nexport interface Prediction {\n symbol: string;\n direction: 'up' | 'down' | 'sideways';\n confidence: number; // 0-100\n timeframe: string;\n reasoning: string[];\n signals: {\n technical: number; // -100 to +100\n sentiment: number;\n derivatives: number;\n trend: number;\n macro: number;\n };\n composite: number; // -100 to +100\n disclaimer: string;\n}\n\n// Signal weights (must sum to 100)\nconst WEIGHTS = {\n technical: 40,\n sentiment: 20,\n derivatives: 20,\n trend: 15,\n macro: 5,\n};\n\n/**\n * Generate a multi-signal composite prediction for a symbol.\n * Gathers: technical analysis + sentiment + derivatives + Fear & Greed + price trend.\n */\nexport async function generatePrediction(symbol: string): Promise<Prediction> {\n const reasoning: string[] = [];\n const signals = { technical: 0, sentiment: 0, derivatives: 0, trend: 0, macro: 0 };\n let completeness = 0;\n\n // 1. Technical Analysis (weight: 40%)\n try {\n const ta = await analyzeTechnicals(symbol, '4h');\n signals.technical = ta.composite.score;\n completeness++;\n reasoning.push(\n `Technical: ${ta.composite.direction} (score ${ta.composite.score}, confidence ${ta.composite.confidence}%)`,\n );\n for (const sig of ta.signals.slice(0, 3)) {\n reasoning.push(` - ${sig.description}`);\n }\n } catch {\n reasoning.push('Technical: unavailable');\n }\n\n // 2. Sentiment (weight: 20%)\n try {\n const sentiment = await analyzeSentiment(symbol);\n // Normalize -1 to +1 → -100 to +100\n signals.sentiment = Math.round(sentiment.overall * 100);\n completeness++;\n reasoning.push(`Sentiment: ${sentiment.consensus} (score ${signals.sentiment})`);\n } catch {\n reasoning.push('Sentiment: unavailable');\n }\n\n // 3. Derivatives (weight: 20%)\n try {\n const [fundingResult, oiResult] = await Promise.allSettled([\n fetchFundingRate(symbol),\n fetchOpenInterest(symbol),\n ]);\n\n let derivativeScore = 0;\n if (fundingResult.status === 'fulfilled') {\n const rate = fundingResult.value.fundingRate;\n // Positive funding = longs paying → slightly bullish consensus\n // Extreme positive = overleveraged longs → bearish signal\n if (rate > 0.0005) {\n derivativeScore -= 30; // Overleveraged longs\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (overleveraged longs — correction risk)`,\n );\n } else if (rate > 0) {\n derivativeScore += 20;\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (moderate bullish positioning)`,\n );\n } else if (rate < -0.0003) {\n derivativeScore += 30; // Capitulation\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (capitulation — bounce candidate)`,\n );\n } else {\n derivativeScore -= 20;\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (bearish positioning)`,\n );\n }\n }\n\n if (oiResult.status === 'fulfilled') {\n const notional = oiResult.value.notionalValue;\n reasoning.push(` OI: $${(notional / 1e9).toFixed(2)}B notional`);\n }\n\n signals.derivatives = Math.max(-100, Math.min(100, derivativeScore));\n completeness++;\n } catch {\n reasoning.push('Derivatives: unavailable');\n }\n\n // 4. Price trend (weight: 15%)\n try {\n const price = await fetchTickerPrice(symbol);\n if (price.change24h > 5) {\n signals.trend = 60;\n reasoning.push(`Trend: strong 24h gain +${price.change24h.toFixed(1)}%`);\n } else if (price.change24h > 0) {\n signals.trend = 30;\n reasoning.push(`Trend: positive 24h +${price.change24h.toFixed(1)}%`);\n } else if (price.change24h < -5) {\n signals.trend = -60;\n reasoning.push(`Trend: strong 24h drop ${price.change24h.toFixed(1)}%`);\n } else {\n signals.trend = -30;\n reasoning.push(`Trend: negative 24h ${price.change24h.toFixed(1)}%`);\n }\n completeness++;\n } catch {\n reasoning.push('Trend: unavailable');\n }\n\n // 5. Macro — Fear & Greed (weight: 5%)\n try {\n const fg = await fetchFearGreedIndex(1);\n const value = fg.current.value;\n // Contrarian: extreme greed = bearish, extreme fear = bullish\n if (value > 80) {\n signals.macro = -40;\n reasoning.push(`Macro: Extreme Greed (${value}) — contrarian bearish`);\n } else if (value > 60) {\n signals.macro = 20;\n reasoning.push(`Macro: Greed (${value}) — bullish sentiment`);\n } else if (value < 20) {\n signals.macro = 40;\n reasoning.push(`Macro: Extreme Fear (${value}) — contrarian bullish`);\n } else if (value < 40) {\n signals.macro = -20;\n reasoning.push(`Macro: Fear (${value}) — bearish sentiment`);\n } else {\n signals.macro = 0;\n reasoning.push(`Macro: Neutral (${value})`);\n }\n completeness++;\n } catch {\n reasoning.push('Macro: unavailable');\n }\n\n // Composite weighted score\n const composite =\n (signals.technical * WEIGHTS.technical +\n signals.sentiment * WEIGHTS.sentiment +\n signals.derivatives * WEIGHTS.derivatives +\n signals.trend * WEIGHTS.trend +\n signals.macro * WEIGHTS.macro) /\n 100;\n\n // Direction\n const direction: Prediction['direction'] =\n composite > 15 ? 'up' : composite < -15 ? 'down' : 'sideways';\n\n // Confidence from signal completeness and agreement\n const signalValues = [\n signals.technical,\n signals.sentiment,\n signals.derivatives,\n signals.trend,\n signals.macro,\n ];\n const positiveCount = signalValues.filter((v) => v > 0).length;\n const negativeCount = signalValues.filter((v) => v < 0).length;\n const agreement =\n Math.max(positiveCount, negativeCount) / Math.max(1, positiveCount + negativeCount);\n const confidence = Math.round(Math.min(95, (completeness / 5) * agreement * 100));\n\n const rulePrediction: Prediction = {\n symbol: symbol.toUpperCase(),\n direction,\n confidence,\n timeframe: '7 days',\n reasoning,\n signals,\n composite: Math.round(composite),\n disclaimer:\n 'This is not financial advice. Predictions are based on historical data and AI analysis. Always do your own research.',\n };\n\n // ML enhancement: if sidecar is available, merge ML prediction\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n // Config not loaded yet — skip ML\n }\n }\n if (mlClient) {\n try {\n const features = await buildFeatureVector(symbol);\n const mlPred = await mlClient.predict(features);\n if (mlPred) {\n return mergePredictions(rulePrediction, mlPred);\n }\n } catch {\n // Fall through to rule-based prediction\n }\n }\n\n return rulePrediction;\n}\n\nfunction mergePredictions(rule: Prediction, ml: MLPredictionResult): Prediction {\n // Weight: 40% rule-based, 60% ML when both available\n const mlComposite =\n ml.direction === 'up'\n ? ml.probability * 100\n : ml.direction === 'down'\n ? -(ml.probability * 100)\n : 0;\n\n const mergedComposite = Math.round(rule.composite * 0.4 + mlComposite * 0.6);\n const mergedDirection: Prediction['direction'] =\n mergedComposite > 15 ? 'up' : mergedComposite < -15 ? 'down' : 'sideways';\n\n const mergedConfidence = Math.round(Math.min(95, rule.confidence * 0.4 + ml.confidence * 0.6));\n\n return {\n ...rule,\n direction: mergedDirection,\n confidence: mergedConfidence,\n composite: mergedComposite,\n reasoning: [\n ...rule.reasoning,\n `ML (${ml.model}): ${ml.direction} with ${(ml.probability * 100).toFixed(1)}% probability (horizon: ${ml.horizon})`,\n ],\n };\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { fetchMarketData, analyzeTrend } from '../../core/trends/market.js';\nimport { analyzeSentiment } from '../../core/trends/sentiment.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport { TREND_SYMBOLS } from '../../config/constants.js';\n\nexport async function handleTrends(options: {\n sentiment: boolean;\n chain: string;\n json: boolean;\n}): Promise<void> {\n const spinner = ora('Fetching market trends...').start();\n\n try {\n const symbols = TREND_SYMBOLS;\n const results = await Promise.all(symbols.map((s) => fetchMarketData(s)));\n\n spinner.stop();\n\n const marketData = results.filter((r): r is NonNullable<typeof r> => r !== null);\n\n if (marketData.length === 0) {\n console.log(chalk.yellow('No market data available. Check your API configuration.'));\n return;\n }\n\n if (options.json) {\n const output = await Promise.all(\n marketData.map(async (data) => {\n const trend = analyzeTrend(data);\n const prediction = await generatePrediction(data.symbol);\n return { data, trend, prediction };\n }),\n );\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold('Market Trends'));\n console.log();\n\n for (const data of marketData) {\n const trend = analyzeTrend(data);\n const directionIcon =\n trend.direction === 'bullish'\n ? chalk.green('^')\n : trend.direction === 'bearish'\n ? chalk.red('v')\n : chalk.yellow('-');\n\n console.log(\n `${directionIcon} ${chalk.bold(data.symbol)} $${data.price.toLocaleString()} ` +\n `${data.priceChange24h >= 0 ? chalk.green(`+${data.priceChange24h.toFixed(2)}%`) : chalk.red(`${data.priceChange24h.toFixed(2)}%`)} ` +\n `Vol: $${(data.volume24h / 1e9).toFixed(2)}B`,\n );\n\n if (trend.signals.length > 0) {\n for (const signal of trend.signals) {\n console.log(chalk.dim(` ${signal}`));\n }\n }\n }\n\n if (options.sentiment) {\n console.log();\n console.log(chalk.bold('Sentiment Analysis'));\n const sentiment = await analyzeSentiment('crypto market');\n console.log(chalk.dim(` Overall: ${sentiment.consensus}`));\n console.log(chalk.dim(' (Social media integration coming soon)'));\n }\n\n console.log();\n console.log(chalk.dim('Not financial advice. Always DYOR.'));\n } catch (error) {\n spinner.fail('Failed to fetch trends');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","import type { ChainAdapter } from '../../chains/types.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { getConfig } from '../../config/loader.js';\nimport type { WalletMLResult } from '../../ml/types.js';\n\nexport interface WalletAnalysis {\n address: string;\n chain: string;\n balance: bigint;\n transactionCount: number;\n tokenBalances: { symbol: string; address: string; balance: bigint }[];\n patterns: WalletPattern[];\n riskLevel: 'clean' | 'suspicious' | 'flagged';\n mlBehavior?: WalletMLResult;\n}\n\nexport interface WalletPattern {\n type: string;\n description: string;\n severity: 'info' | 'warning' | 'danger';\n}\n\nexport async function analyzeWallet(\n address: string,\n adapter: ChainAdapter,\n): Promise<WalletAnalysis> {\n const [balance, transactions] = await Promise.allSettled([\n adapter.getBalance(address),\n adapter.getTransactionHistory(address, { limit: 100 }),\n ]);\n\n const walletBalance = balance.status === 'fulfilled' ? balance.value : 0n;\n const txHistory = transactions.status === 'fulfilled' ? transactions.value : [];\n\n const patterns = detectPatterns(txHistory);\n\n // ML wallet classification\n let mlBehavior: WalletMLResult | undefined;\n try {\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (mlClient && txHistory.length > 0) {\n const features = buildWalletFeatures(txHistory);\n const result = await mlClient.classifyWallet(features);\n if (result) {\n mlBehavior = result;\n }\n }\n } catch {\n /* ML unavailable */\n }\n\n // Determine risk level from patterns + ML\n let riskLevel: WalletAnalysis['riskLevel'] = 'clean';\n if (patterns.some((p) => p.severity === 'danger')) {\n riskLevel = 'flagged';\n } else if (patterns.some((p) => p.severity === 'warning')) {\n riskLevel = 'suspicious';\n }\n // ML can upgrade risk level\n if (mlBehavior && mlBehavior.risk_score > 0.6) {\n riskLevel = 'flagged';\n } else if (mlBehavior && mlBehavior.risk_score > 0.3 && riskLevel === 'clean') {\n riskLevel = 'suspicious';\n }\n\n return {\n address,\n chain: adapter.chainId,\n balance: walletBalance,\n transactionCount: txHistory.length,\n tokenBalances: [],\n patterns,\n riskLevel,\n mlBehavior,\n };\n}\n\ninterface TxRecord {\n hash: string;\n from: string;\n to: string | null;\n value: bigint;\n timestamp: number;\n gasUsed?: bigint | number;\n isError?: boolean;\n status?: 'success' | 'reverted';\n methodId?: string;\n input?: string;\n}\n\nfunction buildWalletFeatures(txHistory: TxRecord[]) {\n const txCount = txHistory.length;\n if (txCount === 0) {\n return {\n tx_count: 0,\n avg_value_eth: 0,\n max_value_eth: 0,\n avg_gas_used: 0,\n unique_recipients: 0,\n unique_methods: 0,\n time_span_hours: 0,\n avg_interval_seconds: 3600,\n min_interval_seconds: 60,\n contract_interaction_pct: 0,\n self_transfer_pct: 0,\n high_value_tx_pct: 0,\n failed_tx_pct: 0,\n token_diversity: 0,\n };\n }\n\n const values = txHistory.map((tx) => Number(tx.value) / 1e18);\n const gasValues = txHistory.map((tx) => Number(tx.gasUsed ?? 21000));\n const recipients = new Set(txHistory.map((tx) => tx.to));\n const methods = new Set(\n txHistory.filter((tx) => tx.input && tx.input.length > 10).map((tx) => tx.input!.slice(0, 10)),\n );\n\n const timestamps = txHistory.map((tx) => tx.timestamp).sort((a, b) => a - b);\n const timeSpan = timestamps.length > 1 ? (timestamps.at(-1)! - timestamps[0]!) / 3600 : 0;\n\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i]! - timestamps[i - 1]!);\n }\n\n const selfTxs = txHistory.filter((tx) => tx.from === tx.to).length;\n const contractTxs = txHistory.filter((tx) => tx.input && tx.input.length > 10).length;\n const revertedTxs = txHistory.filter((tx) => tx.status === 'reverted').length;\n const highValueTxs = values.filter((v) => v > 10).length;\n\n return {\n tx_count: txCount,\n avg_value_eth: values.reduce((a, b) => a + b, 0) / txCount,\n max_value_eth: Math.max(...values),\n avg_gas_used: gasValues.reduce((a, b) => a + b, 0) / txCount,\n unique_recipients: recipients.size,\n unique_methods: methods.size,\n time_span_hours: timeSpan,\n avg_interval_seconds:\n intervals.length > 0 ? intervals.reduce((a, b) => a + b, 0) / intervals.length : 3600,\n min_interval_seconds: intervals.length > 0 ? Math.min(...intervals) : 60,\n contract_interaction_pct: contractTxs / txCount,\n self_transfer_pct: selfTxs / txCount,\n high_value_tx_pct: highValueTxs / txCount,\n failed_tx_pct: revertedTxs / txCount,\n token_diversity: methods.size,\n };\n}\n\nfunction detectPatterns(txHistory: TxRecord[]): WalletPattern[] {\n const patterns: WalletPattern[] = [];\n const txCount = txHistory.length;\n\n if (txCount === 0) {\n patterns.push({\n type: 'new_wallet',\n description: 'Wallet has no transaction history',\n severity: 'info',\n });\n return patterns;\n }\n\n // Rapid transactions (bot-like)\n if (txCount > 50) {\n const timestamps = txHistory.map((tx) => tx.timestamp).sort((a, b) => a - b);\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i]! - timestamps[i - 1]!);\n }\n const minInterval = Math.min(...intervals);\n if (minInterval < 5) {\n patterns.push({\n type: 'rapid_transactions',\n description: `Extremely rapid transactions detected (${minInterval}s apart) — possible bot activity`,\n severity: 'warning',\n });\n }\n }\n\n // High failure rate\n const revertedTxs = txHistory.filter((tx) => tx.status === 'reverted').length;\n if (txCount > 10 && revertedTxs / txCount > 0.3) {\n patterns.push({\n type: 'high_failure_rate',\n description: `${Math.round((revertedTxs / txCount) * 100)}% of transactions failed — possible sniper or MEV bot`,\n severity: 'warning',\n });\n }\n\n // Large value transfers\n const values = txHistory.map((tx) => Number(tx.value) / 1e18);\n const maxValue = Math.max(...values);\n if (maxValue > 100) {\n patterns.push({\n type: 'whale_activity',\n description: `Large transfers detected (max: ${maxValue.toFixed(2)} ETH)`,\n severity: 'info',\n });\n }\n\n // Self-transfers (mixing pattern)\n const selfTxs = txHistory.filter((tx) => tx.from === tx.to).length;\n if (selfTxs / txCount > 0.2) {\n patterns.push({\n type: 'self_transfers',\n description: `${Math.round((selfTxs / txCount) * 100)}% self-transfers — possible mixing activity`,\n severity: 'danger',\n });\n }\n\n // Contract-heavy interaction\n const contractTxs = txHistory.filter((tx) => tx.input && tx.input.length > 10).length;\n if (contractTxs / txCount > 0.9 && txCount > 20) {\n patterns.push({\n type: 'contract_heavy',\n description: 'Almost exclusively interacts with smart contracts — automated behavior',\n severity: 'warning',\n });\n }\n\n return patterns;\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\n\nexport async function handleTrack(\n wallet: string,\n options: { chain: string; json: boolean },\n): Promise<void> {\n const spinner = ora(`Analyzing wallet ${wallet.slice(0, 10)}... on ${options.chain}`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n const analysis = await analyzeWallet(wallet, adapter);\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(\n JSON.stringify(\n analysis,\n (_key, value) => (typeof value === 'bigint' ? value.toString() : (value as unknown)),\n 2,\n ),\n );\n return;\n }\n\n console.log();\n console.log(chalk.bold(`Wallet Analysis: ${wallet}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n const ethBalance = Number(analysis.balance) / 1e18;\n console.log(` Balance: ${ethBalance.toFixed(6)} ${adapter.nativeCurrency.symbol}`);\n console.log(` Transactions: ${analysis.transactionCount}`);\n console.log(` Risk Level: ${colorRiskLevel(analysis.riskLevel)}`);\n console.log();\n\n if (analysis.patterns.length > 0) {\n console.log(chalk.bold('Detected Patterns'));\n for (const pattern of analysis.patterns) {\n const icon =\n pattern.severity === 'danger'\n ? chalk.red('!')\n : pattern.severity === 'warning'\n ? chalk.yellow('?')\n : chalk.blue('i');\n console.log(` ${icon} ${pattern.description}`);\n }\n console.log();\n }\n } catch (error) {\n spinner.fail('Wallet analysis failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\nfunction colorRiskLevel(level: string): string {\n switch (level) {\n case 'clean':\n return chalk.green('Clean');\n case 'suspicious':\n return chalk.yellow('Suspicious');\n case 'flagged':\n return chalk.red('Flagged');\n default:\n return level;\n }\n}\n","// ---------------------------------------------------------------------------\n// DeFiLlama API client — free, no auth required\n// https://api-docs.defillama.com/\n// ---------------------------------------------------------------------------\n\nconst BASE = 'https://api.llama.fi';\nconst COINS_BASE = 'https://coins.llama.fi';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FundraisingRound {\n date: number; // unix timestamp\n name: string;\n round: string; // e.g. \"Seed\", \"Series A\", \"Token Launch\"\n amount: number | null; // USD raised\n chains: string[];\n sector: string;\n category: string;\n leadInvestors: string[];\n otherInvestors: string[];\n valuation: number | null;\n source: string | null;\n defiLlamaId: string | null;\n}\n\nexport interface Protocol {\n id: string;\n name: string;\n symbol: string;\n url: string;\n chains: string[];\n tvl: number;\n change_1h: number | null;\n change_1d: number | null;\n change_7d: number | null;\n mcap: number | null;\n category: string;\n logo: string | null;\n}\n\nexport interface ProtocolDetail extends Protocol {\n description: string;\n tvlList: { date: number; totalLiquidityUSD: number }[];\n currentChainTvls: Record<string, number>;\n}\n\nexport interface ChainTvl {\n gecko_id: string | null;\n tvl: number;\n tokenSymbol: string;\n cmcId: string | null;\n name: string;\n chainId: number | null;\n}\n\nexport interface DexOverview {\n totalDataChart: [number, number][];\n totalDataChartBreakdown: Record<string, unknown>[];\n protocols: {\n name: string;\n displayName: string;\n module: string;\n category: string;\n chains: string[];\n total24h: number | null;\n total7d: number | null;\n total30d: number | null;\n change_1d: number | null;\n }[];\n total24h: number;\n total7d: number;\n total30d: number;\n change_1d: number;\n}\n\nexport interface PriceData {\n price: number;\n symbol: string;\n timestamp: number;\n confidence: number;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`DeFiLlama API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Fetch all crypto fundraising rounds. Returns the full list — filter client-side.\n */\nexport async function fetchRaises(): Promise<FundraisingRound[]> {\n const data = await fetchJson<{ raises: FundraisingRound[] }>(`${BASE}/raises`);\n return data.raises ?? [];\n}\n\n/**\n * Fetch recent raises (last N days).\n */\nexport async function fetchRecentRaises(days = 30): Promise<FundraisingRound[]> {\n const raises = await fetchRaises();\n const cutoff = Date.now() / 1000 - days * 86400;\n return raises.filter((r) => r.date >= cutoff).sort((a, b) => b.date - a.date);\n}\n\n/**\n * Fetch raises filtered by round type (e.g. \"Seed\", \"Series A\", \"Pre-Seed\").\n */\nexport async function fetchRaisesByRound(\n roundType: string,\n days = 90,\n): Promise<FundraisingRound[]> {\n const raises = await fetchRecentRaises(days);\n const lower = roundType.toLowerCase();\n return raises.filter((r) => r.round.toLowerCase().includes(lower));\n}\n\n/**\n * Fetch raises where a specific investor participated.\n */\nexport async function fetchRaisesByInvestor(\n investor: string,\n days = 180,\n): Promise<FundraisingRound[]> {\n const raises = await fetchRecentRaises(days);\n const lower = investor.toLowerCase();\n return raises.filter(\n (r) =>\n r.leadInvestors.some((i) => i.toLowerCase().includes(lower)) ||\n r.otherInvestors.some((i) => i.toLowerCase().includes(lower)),\n );\n}\n\n/**\n * Fetch all DeFi protocols with TVL.\n */\nexport async function fetchProtocols(): Promise<Protocol[]> {\n return fetchJson<Protocol[]>(`${BASE}/protocols`);\n}\n\n/**\n * Fetch detailed info for a specific protocol.\n */\nexport async function fetchProtocol(slug: string): Promise<ProtocolDetail> {\n return fetchJson<ProtocolDetail>(`${BASE}/protocol/${encodeURIComponent(slug)}`);\n}\n\n/**\n * Fetch current prices for tokens. Coins must be in \"chain:address\" format.\n * Example: [\"ethereum:0xdac17f958d2ee523a2206206994597c13d831ec7\"]\n */\nexport async function fetchTokenPrices(coins: string[]): Promise<Record<string, PriceData>> {\n const data = await fetchJson<{ coins: Record<string, PriceData> }>(\n `${COINS_BASE}/prices/current/${coins.map(encodeURIComponent).join(',')}`,\n );\n return data.coins ?? {};\n}\n\n/**\n * Fetch TVL data for all chains.\n */\nexport async function fetchChainTvl(): Promise<ChainTvl[]> {\n return fetchJson<ChainTvl[]>(`${BASE}/v2/chains`);\n}\n\n/**\n * Fetch DEX volume overview, optionally for a specific chain.\n */\nexport async function fetchDexOverview(chain?: string): Promise<DexOverview> {\n const path = chain ? `/overview/dexs/${encodeURIComponent(chain)}` : '/overview/dexs';\n return fetchJson<DexOverview>(`${BASE}${path}`);\n}\n","// ---------------------------------------------------------------------------\n// Pump.fun API client — latest Solana meme coin launches\n// https://frontend-api-v3.pump.fun\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://frontend-api-v3.pump.fun';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PumpCoin {\n mint: string;\n name: string;\n symbol: string;\n description: string;\n image_uri: string | null;\n market_cap: number;\n sol_amount: number;\n created_timestamp: number;\n creator: string;\n reply_count: number;\n last_reply: number | null;\n nsfw: boolean;\n usd_market_cap: number;\n}\n\nexport interface PumpTrade {\n signature: string;\n mint: string;\n sol_amount: number;\n token_amount: number;\n is_buy: boolean;\n user: string;\n timestamp: number;\n slot: number;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(path: string): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`, {\n headers: {\n Accept: 'application/json',\n 'User-Agent':\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)',\n },\n });\n if (!res.ok) {\n throw new Error(`Pump.fun API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Fetch the latest coins launched on Pump.fun.\n */\nexport async function fetchLatestCoins(limit = 20, offset = 0): Promise<PumpCoin[]> {\n return fetchJson<PumpCoin[]>(`/coins/latest?limit=${limit}&offset=${offset}&includeNsfw=false`);\n}\n\n/**\n * Get details for a specific coin by mint address.\n */\nexport async function getCoinDetails(mint: string): Promise<PumpCoin> {\n return fetchJson<PumpCoin>(`/coins/${encodeURIComponent(mint)}`);\n}\n\n/**\n * Get recent trades for a specific token.\n */\nexport async function getTokenTrades(mint: string, limit = 20, offset = 0): Promise<PumpTrade[]> {\n return fetchJson<PumpTrade[]>(\n `/trades/token/${encodeURIComponent(mint)}?limit=${limit}&offset=${offset}`,\n );\n}\n","// ---------------------------------------------------------------------------\n// ICO / Fundraising tracker — powered by DeFiLlama raises + Pump.fun\n// ---------------------------------------------------------------------------\n\nimport {\n fetchRecentRaises,\n fetchRaisesByRound,\n fetchRaisesByInvestor,\n} from '../../data/sources/defillama.js';\nimport { fetchLatestCoins } from '../../data/sources/pumpfun.js';\nimport type { FundraisingRound } from '../../data/sources/defillama.js';\n\nexport interface ICOProject {\n id: string;\n name: string;\n symbol: string;\n category: string;\n chain: string;\n status: 'upcoming' | 'active' | 'ended';\n startDate: string | null;\n endDate: string | null;\n description: string;\n website: string | null;\n raisedAmount: number | null;\n targetAmount: number | null;\n roundType: string;\n investors: string[];\n valuation: number | null;\n previousRounds: { round: string; amount: number | null; date: string }[];\n}\n\nfunction raiseToICO(r: FundraisingRound): ICOProject {\n return {\n id: r.defiLlamaId ?? r.name.toLowerCase().replace(/\\s+/g, '-'),\n name: r.name,\n symbol: '',\n category: r.category || r.sector || 'crypto',\n chain: r.chains[0] ?? 'multi-chain',\n status: 'active',\n startDate: new Date(r.date * 1000).toISOString(),\n endDate: null,\n description: `${r.round} round${r.amount ? ` — $${(r.amount / 1e6).toFixed(1)}M raised` : ''}. ${r.leadInvestors.length > 0 ? `Led by ${r.leadInvestors.join(', ')}.` : ''}`,\n website: r.source,\n raisedAmount: r.amount,\n targetAmount: null,\n roundType: r.round,\n investors: [...r.leadInvestors, ...r.otherInvestors],\n valuation: r.valuation,\n previousRounds: [],\n };\n}\n\n/**\n * Fetch recent fundraising rounds from DeFiLlama.\n */\nexport async function fetchUpcomingICOs(): Promise<ICOProject[]> {\n try {\n const raises = await fetchRecentRaises(30);\n return raises.slice(0, 20).map(raiseToICO);\n } catch {\n return [];\n }\n}\n\n/**\n * Fetch latest Pump.fun launches (Solana meme coins).\n */\nexport async function fetchActiveICOs(): Promise<ICOProject[]> {\n try {\n const coins = await fetchLatestCoins(20);\n\n return coins.map((c) => ({\n id: c.mint,\n name: c.name,\n symbol: c.symbol,\n category: 'meme',\n chain: 'solana',\n status: 'active' as const,\n startDate: new Date(c.created_timestamp).toISOString(),\n endDate: null,\n description:\n c.description || `Pump.fun launch. Market cap: $${c.usd_market_cap?.toFixed(0) ?? '?'}`,\n website: null,\n raisedAmount: c.usd_market_cap ?? null,\n targetAmount: null,\n roundType: 'Fair Launch',\n investors: [],\n valuation: c.usd_market_cap ?? null,\n previousRounds: [],\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Search raises and launches by query, category, chain, or round type.\n */\nexport async function searchICOs(\n query?: string,\n category?: string,\n chain?: string,\n roundType?: string,\n): Promise<ICOProject[]> {\n try {\n let raises: FundraisingRound[];\n if (roundType) {\n raises = await fetchRaisesByRound(roundType, 90);\n } else {\n raises = await fetchRecentRaises(90);\n }\n\n let filtered = raises.map(raiseToICO);\n\n if (query) {\n const q = query.toLowerCase();\n filtered = filtered.filter(\n (p) => p.name.toLowerCase().includes(q) || p.category.toLowerCase().includes(q),\n );\n }\n if (category) {\n const cat = category.toLowerCase();\n filtered = filtered.filter((p) => p.category.toLowerCase().includes(cat));\n }\n if (chain) {\n const ch = chain.toLowerCase();\n filtered = filtered.filter((p) => p.chain.toLowerCase().includes(ch));\n }\n\n return filtered.slice(0, 20);\n } catch {\n return [];\n }\n}\n\n/**\n * Get funding history for a project by name — finds all rounds involving that name.\n */\nexport async function getProjectFundingHistory(\n name: string,\n): Promise<{ name: string; rounds: ICOProject[] }> {\n try {\n const raises = await fetchRecentRaises(365);\n const lower = name.toLowerCase();\n const matches = raises\n .filter((r) => r.name.toLowerCase().includes(lower))\n .sort((a, b) => a.date - b.date)\n .map(raiseToICO);\n\n // Link previous rounds\n for (let i = 1; i < matches.length; i++) {\n const project = matches[i];\n if (project) {\n project.previousRounds = matches.slice(0, i).map((prev) => ({\n round: prev.roundType,\n amount: prev.raisedAmount,\n date: prev.startDate ?? '',\n }));\n }\n }\n\n return { name, rounds: matches };\n } catch {\n return { name, rounds: [] };\n }\n}\n\n/**\n * Get raises by a specific investor.\n */\nexport async function getInvestorPortfolio(investor: string): Promise<ICOProject[]> {\n try {\n const raises = await fetchRaisesByInvestor(investor, 365);\n return raises.slice(0, 30).map(raiseToICO);\n } catch {\n return [];\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { fetchUpcomingICOs, searchICOs } from '../../core/scanner/ico-tracker.js';\n\nexport async function handleIcoList(options: {\n category?: string;\n chain?: string;\n json: boolean;\n}): Promise<void> {\n const spinner = ora('Fetching ICO data...').start();\n\n try {\n const icos =\n options.category || options.chain\n ? await searchICOs(undefined, options.category, options.chain)\n : await fetchUpcomingICOs();\n\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(icos, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold('Upcoming ICOs / IDOs'));\n console.log();\n\n if (icos.length === 0) {\n console.log(chalk.dim(' No ICOs found. ICO tracking APIs will be integrated soon.'));\n console.log(chalk.dim(' Sources planned: ICODrops, CoinGecko, DeFiLlama'));\n console.log();\n return;\n }\n\n for (const ico of icos) {\n const statusColor =\n ico.status === 'active' ? chalk.green : ico.status === 'upcoming' ? chalk.blue : chalk.dim;\n\n console.log(\n ` ${statusColor(ico.status.toUpperCase())} ${chalk.bold(ico.name)} (${ico.symbol})`,\n );\n console.log(` Chain: ${ico.chain} | Category: ${ico.category}`);\n if (ico.startDate) {\n console.log(` Start: ${ico.startDate}`);\n }\n if (ico.targetAmount) {\n console.log(` Target: $${ico.targetAmount.toLocaleString()}`);\n }\n console.log();\n }\n } catch (error) {\n spinner.fail('Failed to fetch ICO data');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","import type { ChainAdapter } from '../../chains/types.js';\n\nexport interface AuditResult {\n address: string;\n chain: string;\n hasCode: boolean;\n codeSize: number;\n findings: AuditFinding[];\n overallRisk: 'low' | 'medium' | 'high' | 'critical';\n}\n\nexport interface AuditFinding {\n title: string;\n description: string;\n severity: 'info' | 'low' | 'medium' | 'high' | 'critical';\n category: string;\n}\n\nexport async function auditContract(address: string, adapter: ChainAdapter): Promise<AuditResult> {\n const code = await adapter.getContractCode(address).catch(() => '');\n const findings: AuditFinding[] = [];\n\n const hasCode = code.length > 2;\n\n if (!hasCode) {\n findings.push({\n title: 'No Contract Code',\n description: 'Address does not contain contract bytecode. This may be an EOA.',\n severity: 'critical',\n category: 'deployment',\n });\n\n return {\n address,\n chain: adapter.chainId,\n hasCode: false,\n codeSize: 0,\n findings,\n overallRisk: 'critical',\n };\n }\n\n const codeSize = (code.length - 2) / 2; // hex string minus 0x, each byte = 2 chars\n\n if (codeSize < 100) {\n findings.push({\n title: 'Minimal Contract',\n description: `Contract bytecode is very small (${codeSize} bytes). May be a proxy or minimal implementation.`,\n severity: 'medium',\n category: 'size',\n });\n }\n\n if (codeSize > 24576) {\n findings.push({\n title: 'Large Contract',\n description: `Contract bytecode is ${codeSize} bytes, approaching the 24KB deployment limit.`,\n severity: 'info',\n category: 'size',\n });\n }\n\n // TODO: Add more audit checks:\n // - Proxy pattern detection (delegatecall)\n // - Selfdestruct detection\n // - Known vulnerability signatures\n // - Storage layout analysis\n\n const overallRisk = determineOverallRisk(findings);\n\n return {\n address,\n chain: adapter.chainId,\n hasCode,\n codeSize,\n findings,\n overallRisk,\n };\n}\n\nfunction determineOverallRisk(findings: AuditFinding[]): AuditResult['overallRisk'] {\n if (findings.some((f) => f.severity === 'critical')) return 'critical';\n if (findings.some((f) => f.severity === 'high')) return 'high';\n if (findings.some((f) => f.severity === 'medium')) return 'medium';\n return 'low';\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\n\nexport async function handleAudit(\n contract: string,\n options: { chain: string; json: boolean },\n): Promise<void> {\n const spinner = ora(`Auditing contract ${contract.slice(0, 10)}... on ${options.chain}`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold(`Contract Audit: ${contract}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n console.log(` Has Code: ${result.hasCode ? chalk.green('Yes') : chalk.red('No')}`);\n console.log(` Code Size: ${result.codeSize} bytes`);\n console.log(` Overall Risk: ${colorRisk(result.overallRisk)}`);\n console.log();\n\n if (result.findings.length > 0) {\n console.log(chalk.bold('Findings'));\n for (const finding of result.findings) {\n const icon = severityIcon(finding.severity);\n console.log(` ${icon} [${finding.severity.toUpperCase()}] ${finding.title}`);\n console.log(chalk.dim(` ${finding.description}`));\n }\n console.log();\n } else {\n console.log(chalk.green(' No issues detected.'));\n console.log();\n }\n\n console.log(chalk.dim('Note: This is a basic bytecode-level audit. For comprehensive'));\n console.log(chalk.dim('security analysis, use a professional audit service.'));\n } catch (error) {\n spinner.fail('Audit failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\nfunction colorRisk(level: string): string {\n switch (level) {\n case 'low':\n return chalk.green('Low');\n case 'medium':\n return chalk.yellow('Medium');\n case 'high':\n return chalk.red('High');\n case 'critical':\n return chalk.bgRed.white(' CRITICAL ');\n default:\n return level;\n }\n}\n\nfunction severityIcon(severity: string): string {\n switch (severity) {\n case 'critical':\n return chalk.bgRed.white('!');\n case 'high':\n return chalk.red('!');\n case 'medium':\n return chalk.yellow('!');\n case 'low':\n return chalk.blue('i');\n case 'info':\n return chalk.dim('i');\n default:\n return '-';\n }\n}\n","// ---------------------------------------------------------------------------\n// AI Provider abstraction — shared types for multi-provider support\n// ---------------------------------------------------------------------------\n\n/** Handler that executes a tool call and returns its result. */\nexport type ToolHandler = (name: string, input: unknown) => Promise<unknown>;\n\n/** Callbacks invoked during streaming. */\nexport interface StreamCallbacks {\n onText: (delta: string) => void;\n onToolStart: (toolName: string) => void;\n onToolEnd: (toolName: string) => void;\n onDone: (fullText: string) => void;\n}\n\n/** Provider-agnostic tool definition (JSON Schema based). */\nexport interface AITool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, unknown>;\n required: string[];\n };\n}\n\n/** Interface that all AI providers must implement. */\nexport interface AIProvider {\n /** Provider identifier (e.g. 'anthropic', 'openai'). */\n readonly name: string;\n\n /** Whether this provider supports tool use (function calling). */\n readonly supportsTools: boolean;\n\n /**\n * Initialize the provider with credentials and model selection.\n * Called once before any analyze/stream calls.\n */\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void;\n\n /**\n * Send a message and return the full text response.\n * Includes agentic tool-use loop if tools and handler are provided.\n */\n analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string>;\n\n /**\n * Stream a message with callbacks for incremental text and tool events.\n * Includes agentic tool-use loop if tools and handler are provided.\n */\n analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string>;\n}\n\n/** Maximum iterations for the agentic tool-use loop. */\nexport const MAX_ITERATIONS = 10;\n\n/** Default models per provider. */\nexport const DEFAULT_MODELS: Record<string, string> = {\n anthropic: 'claude-sonnet-4-20250514',\n openai: 'gpt-4o',\n gemini: 'gemini-2.5-flash',\n ollama: 'llama3.2',\n};\n","/**\n * Throws a descriptive error if the given API key value is undefined or empty.\n */\nexport function requireKey(keyName: string, value: string | undefined): string {\n if (!value) {\n throw new Error(\n `Missing required API key: ${keyName}. ` +\n `Set it in ~/.vizzor/config.yaml or via the corresponding environment variable.`,\n );\n }\n return value;\n}\n\n/**\n * Returns true if the given value is a non-empty string.\n */\nexport function hasKey(value: string | undefined): boolean {\n return typeof value === 'string' && value.length > 0;\n}\n\n/**\n * Masks an API key for safe display using zero-knowledge style masking.\n * Shows only the first 2 and last 2 characters with asterisks in between.\n * This prevents leaking key prefixes that could be used for phishing or\n * identifying the key provider/format.\n */\nexport function maskKey(value: string | undefined): string {\n if (!value) {\n return '<not set>';\n }\n if (value.length <= 4) {\n return '****';\n }\n if (value.length <= 8) {\n return value.slice(0, 1) + '****' + value.slice(-1);\n }\n return value.slice(0, 2) + '*'.repeat(Math.min(value.length - 4, 12)) + value.slice(-2);\n}\n\n// ---------------------------------------------------------------------------\n// Key validation — reject phishing, scam, and malformed keys\n// ---------------------------------------------------------------------------\n\n/** Known key prefix patterns for supported providers. */\nconst KEY_PATTERNS: Record<string, RegExp> = {\n anthropicApiKey: /^sk-ant-[a-zA-Z0-9_-]{20,}$/,\n openaiApiKey: /^sk-[a-zA-Z0-9_-]{20,}$/,\n googleApiKey: /^AI[a-zA-Z0-9_-]{20,}$/,\n etherscanApiKey: /^[A-Z0-9]{20,}$/,\n alchemyApiKey: /^[a-zA-Z0-9_-]{20,}$/,\n coingeckoApiKey: /^CG-[a-zA-Z0-9]{10,}$/,\n cryptopanicApiKey: /^[a-f0-9]{20,}$/,\n};\n\n/** Characters that should never appear in a legitimate API key. */\nconst FORBIDDEN_CHARS = /[<>{}()|\\\\;`$!\"'&\\s]/;\n\n/** Patterns indicating phishing or injection attempts. */\nconst PHISHING_PATTERNS = [\n /https?:\\/\\//i,\n /javascript:/i,\n /data:/i,\n /<script/i,\n /eval\\s*\\(/i,\n /\\.\\.\\//,\n /\\/etc\\//,\n /\\$\\{/,\n /`.*`/,\n];\n\n/**\n * Validates an API key value for a given config key.\n * Returns null if valid, or an error message if rejected.\n */\nexport function validateKey(keyName: string, value: string): string | null {\n if (!value || value.trim().length === 0) {\n return 'Key value cannot be empty.';\n }\n\n // Check for forbidden characters (injection / phishing)\n if (FORBIDDEN_CHARS.test(value)) {\n return 'Key contains invalid characters. API keys only use alphanumeric characters, hyphens, and underscores.';\n }\n\n // Check for phishing / injection patterns\n for (const pattern of PHISHING_PATTERNS) {\n if (pattern.test(value)) {\n return 'Key rejected: value looks like a URL, script, or injection attempt.';\n }\n }\n\n // Length sanity check\n if (value.length > 256) {\n return 'Key rejected: value is too long (max 256 characters).';\n }\n\n // Provider-specific format validation (warn, don't block)\n const expectedPattern = KEY_PATTERNS[keyName];\n if (expectedPattern && !expectedPattern.test(value)) {\n return `Warning: key format doesn't match expected pattern for ${keyName}. Double-check the value.`;\n }\n\n return null;\n}\n","import chalk from 'chalk';\nimport { writeFileSync, existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { stringify as yamlStringify } from 'yaml';\nimport { getConfigDir, loadConfig, getConfig, saveConfigValue } from '../../config/loader.js';\nimport { DEFAULT_CHAIN } from '../../config/constants.js';\nimport { DEFAULT_MODELS } from '../../ai/providers/types.js';\nimport { maskKey, validateKey } from '../../config/keys.js';\n\nexport async function handleConfigInit(): Promise<void> {\n const configDir = getConfigDir();\n const configPath = resolve(configDir, 'config.yaml');\n\n if (existsSync(configPath)) {\n console.log(chalk.yellow('Configuration already exists at:'), configPath);\n console.log(chalk.dim('Use \"vizzor config set <key> <value>\" to update values.'));\n return;\n }\n\n const defaultConfig = {\n anthropicApiKey: '',\n etherscanApiKey: '',\n defaultChain: DEFAULT_CHAIN,\n ai: {\n model: DEFAULT_MODELS['anthropic'],\n maxTokens: 4096,\n },\n output: {\n format: 'table',\n color: true,\n verbose: false,\n },\n };\n\n writeFileSync(configPath, yamlStringify(defaultConfig), 'utf-8');\n\n console.log(chalk.green('Configuration initialized at:'), configPath);\n console.log();\n console.log('Next steps:');\n console.log(\n ` 1. Set your Anthropic API key: ${chalk.cyan('vizzor config set anthropicApiKey <your-key>')}`,\n );\n console.log(\n ` 2. Set your Etherscan API key: ${chalk.cyan('vizzor config set etherscanApiKey <your-key>')}`,\n );\n console.log(` 3. Try scanning a project: ${chalk.cyan('vizzor scan ethereum')}`);\n}\n\nexport async function handleConfigSet(key: string, value: string): Promise<void> {\n // Validate keys for security (phishing, injection, format)\n const isSensitive = key.toLowerCase().includes('key') || key.toLowerCase().includes('token');\n if (isSensitive) {\n const error = validateKey(key, value);\n if (error && !error.startsWith('Warning:')) {\n console.log(chalk.red(`Rejected: ${error}`));\n return;\n }\n if (error?.startsWith('Warning:')) {\n console.log(chalk.yellow(error));\n }\n }\n\n try {\n saveConfigValue(key, value);\n } catch (err) {\n console.log(chalk.red(err instanceof Error ? err.message : String(err)));\n return;\n }\n\n const displayValue = isSensitive ? maskKey(value) : value;\n\n console.log(chalk.green(`Set ${key} = ${displayValue}`));\n}\n\nexport async function handleConfigShow(): Promise<void> {\n await loadConfig();\n const config = getConfig();\n const configDir = getConfigDir();\n\n console.log();\n console.log(chalk.bold('Vizzor Configuration'));\n console.log(chalk.dim(`Location: ${resolve(configDir, 'config.yaml')}`));\n console.log();\n\n const entries = Object.entries(config);\n for (const [key, value] of entries) {\n if (typeof value === 'object' && value !== null) {\n console.log(` ${chalk.bold(key)}:`);\n for (const [subKey, subValue] of Object.entries(value as Record<string, unknown>)) {\n console.log(` ${subKey}: ${String(subValue)}`);\n }\n } else {\n const displayValue =\n typeof value === 'string' &&\n (key.toLowerCase().includes('key') || key.toLowerCase().includes('token'))\n ? maskKey(value)\n : String(value ?? '');\n console.log(` ${key}: ${displayValue || chalk.dim('(not set)')}`);\n }\n }\n console.log();\n}\n","// ---------------------------------------------------------------------------\n// Anthropic provider — Claude integration via @anthropic-ai/sdk\n// ---------------------------------------------------------------------------\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class AnthropicProvider implements AIProvider {\n readonly name = 'anthropic';\n readonly supportsTools = true;\n\n private client: Anthropic | undefined;\n private model = DEFAULT_MODELS['anthropic']!;\n private maxTokens = 8192;\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'Anthropic API key is not configured. Set ANTHROPIC_API_KEY or add anthropicApiKey to ~/.vizzor/config.yaml.',\n );\n }\n\n this.client = new Anthropic({ apiKey });\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -------------------------------------------------------------------------\n // Non-streaming analysis with agentic tool-use loop\n // -------------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const ai = this.getClient();\n const maxIterations = MAX_ITERATIONS; // safety cap for the agentic loop\n\n const messages: Anthropic.Messages.MessageParam[] = [{ role: 'user', content: userMessage }];\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const params: Anthropic.Messages.MessageCreateParamsNonStreaming = {\n model: this.model,\n max_tokens: this.maxTokens,\n system: systemPrompt,\n messages,\n ...(tools && tools.length > 0 ? { tools: tools as Anthropic.Messages.Tool[] } : {}),\n };\n\n const response = await ai.messages.create(params);\n\n // Collect tool_use blocks from the response.\n const toolUseBlocks = response.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock => block.type === 'tool_use',\n );\n\n // If there are no tool calls, extract text and return.\n if (toolUseBlocks.length === 0 || response.stop_reason !== 'tool_use') {\n return extractText(response.content);\n }\n\n // --- Agentic loop: execute tools and continue the conversation --------\n\n if (!toolHandler) {\n throw new Error('Claude requested tool use but no tool handler was provided.');\n }\n\n // Capture in a const so TypeScript narrows the type inside the async map.\n const handler = toolHandler;\n\n // Append the assistant's response (including tool_use blocks) so Claude\n // can see what it previously said.\n messages.push({\n role: 'assistant',\n content: response.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // For any other block type, serialise as text so we don't lose info.\n return { type: 'text' as const, text: JSON.stringify(block) };\n }),\n });\n\n // Execute each tool and build the tool_result blocks.\n const toolResults: Anthropic.Messages.ToolResultBlockParam[] = await Promise.all(\n toolUseBlocks.map(async (block) => {\n try {\n const result = await handler(block.name, block.input);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify(result),\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify({ error: message }),\n is_error: true,\n };\n }\n }),\n );\n\n messages.push({ role: 'user', content: toolResults });\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -------------------------------------------------------------------------\n // Streaming analysis with agentic tool-use loop\n // -------------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const ai = this.getClient();\n const maxIterations = MAX_ITERATIONS; // safety cap for the agentic loop\n\n const messages: Anthropic.Messages.MessageParam[] = [{ role: 'user', content: userMessage }];\n\n // Accumulates text across all iterations so onDone receives the full output.\n let fullText = '';\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const streamParams: Anthropic.Messages.MessageCreateParamsStreaming = {\n model: this.model,\n max_tokens: this.maxTokens,\n system: systemPrompt,\n messages,\n stream: true,\n ...(tools && tools.length > 0 ? { tools: tools as Anthropic.Messages.Tool[] } : {}),\n };\n\n // --- Stream the response -----------------------------------------------\n\n const stream = ai.messages.stream(streamParams);\n\n // Forward incremental text deltas to the caller.\n stream.on('text', (delta) => {\n fullText += delta;\n callbacks.onText(delta);\n });\n\n let finalMessage: Anthropic.Messages.Message;\n try {\n finalMessage = await stream.finalMessage();\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Anthropic streaming request failed: ${detail}`, {\n cause: err,\n });\n }\n\n // --- Check for tool use ------------------------------------------------\n\n const toolUseBlocks = finalMessage.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock => block.type === 'tool_use',\n );\n\n // No tool calls — we are done.\n if (toolUseBlocks.length === 0 || finalMessage.stop_reason !== 'tool_use') {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and continue streaming ----------------\n\n if (!toolHandler) {\n throw new Error('Claude requested tool use but no tool handler was provided.');\n }\n\n // Capture in a const so TypeScript narrows the type inside the async map.\n const handler = toolHandler;\n\n // Append the assistant's full response (text + tool_use blocks) to the\n // conversation so Claude can see what it previously said.\n messages.push({\n role: 'assistant',\n content: finalMessage.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // For any other block type, serialise as text so we don't lose info.\n return { type: 'text' as const, text: JSON.stringify(block) };\n }),\n });\n\n // Execute each requested tool and build the tool_result blocks.\n const toolResults: Anthropic.Messages.ToolResultBlockParam[] = await Promise.all(\n toolUseBlocks.map(async (block) => {\n callbacks.onToolStart(block.name);\n try {\n const result = await handler(block.name, block.input);\n callbacks.onToolEnd(block.name);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify(result),\n };\n } catch (err: unknown) {\n callbacks.onToolEnd(block.name);\n const message = err instanceof Error ? err.message : String(err);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify({ error: message }),\n is_error: true,\n };\n }\n }),\n );\n\n messages.push({ role: 'user', content: toolResults });\n\n // Loop continues — the next iteration will stream Claude's follow-up.\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -------------------------------------------------------------------------\n // Internal helpers\n // -------------------------------------------------------------------------\n\n /** Return the Anthropic client, throwing if not initialised. */\n private getClient(): Anthropic {\n if (!this.client) {\n throw new Error('AnthropicProvider has not been initialised. Call initialize() first.');\n }\n return this.client;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Concatenate all text blocks from a response's content array. */\nfunction extractText(content: Anthropic.Messages.ContentBlock[]): string {\n return content\n .filter((block): block is Anthropic.Messages.TextBlock => block.type === 'text')\n .map((block) => block.text)\n .join('\\n\\n');\n}\n","// ---------------------------------------------------------------------------\n// OpenAI provider — GPT-4o / GPT-4-turbo with agentic tool-use loop\n// ---------------------------------------------------------------------------\n\nimport OpenAI from 'openai';\nimport type {\n ChatCompletionChunk,\n ChatCompletionMessageFunctionToolCall,\n ChatCompletionMessageParam,\n} from 'openai/resources/chat/completions';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n/** Convert provider-agnostic tool definitions to the OpenAI function-calling format. */\nfunction toOpenAITools(tools: AITool[]): OpenAI.Chat.Completions.ChatCompletionTool[] {\n return tools.map((t) => ({\n type: 'function' as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Accumulated streaming tool call\n// ---------------------------------------------------------------------------\n\ninterface AccumulatedToolCall {\n id: string;\n functionName: string;\n arguments: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class OpenAIProvider implements AIProvider {\n readonly name = 'openai';\n readonly supportsTools = true;\n\n private client: OpenAI | undefined;\n private model = DEFAULT_MODELS['openai']!;\n private maxTokens = 4096;\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'OpenAI API key is not configured. Set OPENAI_API_KEY or add openaiApiKey to ~/.vizzor/config.yaml.',\n );\n }\n this.client = new OpenAI({ apiKey });\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -----------------------------------------------------------------------\n // Non-streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const client = this.requireClient();\n\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n const openaiTools = tools && tools.length > 0 ? toOpenAITools(tools) : undefined;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const response = await client.chat.completions.create({\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n ...(openaiTools ? { tools: openaiTools, tool_choice: 'auto' as const } : {}),\n });\n\n const choice = response.choices[0];\n if (!choice) {\n return '';\n }\n\n const message = choice.message;\n\n // Filter to function-type tool calls only (OpenAI also has a 'custom' variant).\n const toolCalls: ChatCompletionMessageFunctionToolCall[] = (\n message.tool_calls ?? []\n ).filter((tc): tc is ChatCompletionMessageFunctionToolCall => tc.type === 'function');\n\n // No tool calls — return the text content.\n if (toolCalls.length === 0 || choice.finish_reason !== 'tool_calls') {\n return message.content ?? '';\n }\n\n // --- Agentic loop: execute tools and continue the conversation ------\n\n if (!toolHandler) {\n throw new Error('OpenAI requested tool use but no tool handler is registered.');\n }\n\n // Append the assistant's response (including tool_calls) to the conversation.\n messages.push({\n role: 'assistant',\n content: message.content ?? null,\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n })),\n });\n\n // Execute each tool and append the results.\n const handler = toolHandler;\n await Promise.all(\n toolCalls.map(async (tc) => {\n let content: string;\n try {\n const input: unknown = JSON.parse(tc.function.arguments);\n const result = await handler(tc.function.name, input);\n content = JSON.stringify(result);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n content = JSON.stringify({ error: detail });\n }\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content,\n });\n }),\n );\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`OpenAI request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -----------------------------------------------------------------------\n // Streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const client = this.requireClient();\n\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n const openaiTools = tools && tools.length > 0 ? toOpenAITools(tools) : undefined;\n\n let fullText = '';\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const stream = await client.chat.completions.create({\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n stream: true,\n ...(openaiTools ? { tools: openaiTools, tool_choice: 'auto' as const } : {}),\n });\n\n // Accumulators for the current stream iteration.\n const accumulatedToolCalls = new Map<number, AccumulatedToolCall>();\n let finishReason: string | null = null;\n\n for await (const chunk of stream as AsyncIterable<ChatCompletionChunk>) {\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n // Track finish reason.\n if (choice.finish_reason) {\n finishReason = choice.finish_reason;\n }\n\n const delta = choice.delta;\n\n // Forward text deltas.\n if (delta.content) {\n fullText += delta.content;\n callbacks.onText(delta.content);\n }\n\n // Accumulate tool calls that arrive incrementally.\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index;\n let acc = accumulatedToolCalls.get(idx);\n if (!acc) {\n acc = { id: '', functionName: '', arguments: '' };\n accumulatedToolCalls.set(idx, acc);\n }\n if (tc.id) {\n acc.id = tc.id;\n }\n if (tc.function?.name) {\n acc.functionName = tc.function.name;\n }\n if (tc.function?.arguments) {\n acc.arguments += tc.function.arguments;\n }\n }\n }\n }\n\n // If no tool calls were accumulated, we are done.\n if (accumulatedToolCalls.size === 0 || finishReason !== 'tool_calls') {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and re-stream ----------------------\n\n if (!toolHandler) {\n throw new Error('OpenAI requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n const toolCallsList = Array.from(accumulatedToolCalls.values());\n\n // Append the assistant message with accumulated tool calls.\n messages.push({\n role: 'assistant',\n content: null,\n tool_calls: toolCallsList.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.functionName,\n arguments: tc.arguments,\n },\n })),\n });\n\n // Execute each tool and append results.\n for (const tc of toolCallsList) {\n callbacks.onToolStart(tc.functionName);\n let content: string;\n try {\n const input: unknown = JSON.parse(tc.arguments);\n const result = await handler(tc.functionName, input);\n content = JSON.stringify(result);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n content = JSON.stringify({ error: detail });\n }\n callbacks.onToolEnd(tc.functionName);\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content,\n });\n }\n\n // Loop continues — the next iteration will re-stream.\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`OpenAI streaming request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private requireClient(): OpenAI {\n if (!this.client) {\n throw new Error('OpenAI provider has not been initialized. Call initialize() first.');\n }\n return this.client;\n }\n}\n","// ---------------------------------------------------------------------------\n// Google Gemini provider — Gemini 2.5 Flash / Pro with agentic tool-use loop\n// ---------------------------------------------------------------------------\n\nimport {\n GoogleGenerativeAI,\n type Content,\n type FunctionCall,\n type FunctionDeclaration,\n type GenerativeModel,\n type Part,\n} from '@google/generative-ai';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n/**\n * Convert provider-agnostic tool definitions to Gemini's FunctionDeclaration format.\n *\n * Gemini expects `parameters` as a JSON Schema object. Our `AITool.input_schema`\n * is already in that shape, so we pass it through directly.\n */\nfunction toGeminiFunctionDeclarations(tools: AITool[]): FunctionDeclaration[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.input_schema as FunctionDeclaration['parameters'],\n }));\n}\n\n/** Extract all FunctionCall parts from a Gemini response's candidate parts. */\nfunction extractFunctionCalls(parts: Part[] | undefined): FunctionCall[] {\n if (!parts) return [];\n const calls: FunctionCall[] = [];\n for (const part of parts) {\n if (part.functionCall) {\n calls.push(part.functionCall);\n }\n }\n return calls;\n}\n\n/** Extract concatenated text from Gemini response candidate parts. */\nfunction extractText(parts: Part[] | undefined): string {\n if (!parts) return '';\n return parts\n .filter((p) => typeof p.text === 'string')\n .map((p) => p.text as string)\n .join('');\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class GeminiProvider implements AIProvider {\n readonly name = 'gemini';\n readonly supportsTools = true;\n\n private genAI: GoogleGenerativeAI | undefined;\n private model = DEFAULT_MODELS['gemini']!;\n private maxTokens = 4096;\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'Google Gemini API key is not configured. Set GEMINI_API_KEY or add geminiApiKey to ~/.vizzor/config.yaml.',\n );\n }\n this.genAI = new GoogleGenerativeAI(apiKey);\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -----------------------------------------------------------------------\n // Non-streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const genAI = this.requireGenAI();\n\n // Build the model instance with system instruction and tools baked in.\n const geminiModel = this.createModel(genAI, systemPrompt, tools);\n\n // Conversation history for multi-turn tool use.\n const history: Content[] = [];\n\n // Start with the user message; subsequent iterations use function responses.\n let currentContents: Content[] = [{ role: 'user', parts: [{ text: userMessage }] }];\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const contents: Content[] = [...history, ...currentContents];\n\n const result = await geminiModel.generateContent({ contents });\n const response = result.response;\n\n const candidateParts = response.candidates?.[0]?.content?.parts;\n const functionCalls = extractFunctionCalls(candidateParts);\n\n // No function calls — return text content.\n if (functionCalls.length === 0) {\n return extractText(candidateParts);\n }\n\n // --- Agentic loop: execute tools and continue the conversation ------\n\n if (!toolHandler) {\n throw new Error('Gemini requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n\n // Append the current contents and model response to the history.\n history.push(...currentContents);\n history.push({ role: 'model', parts: candidateParts ?? [] });\n\n // Execute each function call and build function response parts.\n const functionResponseParts: Part[] = await Promise.all(\n functionCalls.map(async (fc) => {\n try {\n const fnResult = await handler(fc.name, fc.args);\n return {\n functionResponse: {\n name: fc.name,\n response: { result: fnResult },\n },\n } as Part;\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n return {\n functionResponse: {\n name: fc.name,\n response: { error: detail },\n },\n } as Part;\n }\n }),\n );\n\n // Function responses go into history and become the next turn.\n history.push({ role: 'function', parts: functionResponseParts });\n\n // Clear currentContents — next iteration builds from history only.\n currentContents = [];\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Gemini request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -----------------------------------------------------------------------\n // Streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const genAI = this.requireGenAI();\n\n const geminiModel = this.createModel(genAI, systemPrompt, tools);\n\n const history: Content[] = [];\n let fullText = '';\n\n // Start with the user message.\n let currentContents: Content[] = [{ role: 'user', parts: [{ text: userMessage }] }];\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const contents = [...history, ...currentContents];\n\n const streamResult = await geminiModel.generateContentStream({ contents });\n\n // Accumulate all parts from the streamed chunks.\n const allParts: Part[] = [];\n\n for await (const chunk of streamResult.stream) {\n const text = chunk.text();\n if (text) {\n fullText += text;\n callbacks.onText(text);\n }\n\n // Collect parts for function call detection.\n const candidateParts = chunk.candidates?.[0]?.content?.parts;\n if (candidateParts) {\n allParts.push(...candidateParts);\n }\n }\n\n // Check for function calls in the accumulated parts.\n const functionCalls = extractFunctionCalls(allParts);\n\n // No function calls — we are done.\n if (functionCalls.length === 0) {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and re-stream ----------------------\n\n if (!toolHandler) {\n throw new Error('Gemini requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n\n // Append the current contents and model response to history.\n history.push(...currentContents);\n history.push({ role: 'model', parts: allParts });\n\n // Execute function calls.\n const functionResponseParts: Part[] = [];\n for (const fc of functionCalls) {\n callbacks.onToolStart(fc.name);\n try {\n const result = await handler(fc.name, fc.args);\n functionResponseParts.push({\n functionResponse: {\n name: fc.name,\n response: { result },\n },\n } as Part);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n functionResponseParts.push({\n functionResponse: {\n name: fc.name,\n response: { error: detail },\n },\n } as Part);\n }\n callbacks.onToolEnd(fc.name);\n }\n\n // Function responses become the next turn.\n history.push({ role: 'function', parts: functionResponseParts });\n\n // Clear currentContents — next iteration builds from history only.\n currentContents = [];\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Gemini streaming request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private requireGenAI(): GoogleGenerativeAI {\n if (!this.genAI) {\n throw new Error('Gemini provider has not been initialized. Call initialize() first.');\n }\n return this.genAI;\n }\n\n /**\n * Create a GenerativeModel with system instruction, tools, and generation config.\n */\n private createModel(\n genAI: GoogleGenerativeAI,\n systemPrompt: string,\n tools?: AITool[],\n ): GenerativeModel {\n const functionDeclarations =\n tools && tools.length > 0 ? toGeminiFunctionDeclarations(tools) : undefined;\n\n return genAI.getGenerativeModel({\n model: this.model,\n systemInstruction: systemPrompt,\n ...(functionDeclarations ? { tools: [{ functionDeclarations }] } : {}),\n generationConfig: {\n maxOutputTokens: this.maxTokens,\n },\n });\n }\n}\n","// ---------------------------------------------------------------------------\n// Ollama provider — local model integration via ollama npm package\n// ---------------------------------------------------------------------------\n\nimport { Ollama } from 'ollama';\nimport { DEFAULT_MODELS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Assistant prefill — forces the model to start answering instead of refusing.\n// Local models have strong safety filters that trigger on words like \"predict\".\n// By pre-filling the assistant turn, we bypass the refusal mechanism.\n// ---------------------------------------------------------------------------\n\nconst PREDICTION_TRIGGERS = [\n 'predict',\n 'forecast',\n 'price target',\n 'will it go',\n 'future price',\n 'price prediction',\n 'where will',\n 'should i buy',\n 'should i sell',\n 'going to pump',\n];\n\nconst ANALYSIS_TRIGGERS = [\n 'anali',\n 'audit',\n 'scan',\n 'review',\n 'inspect',\n 'check',\n 'risk',\n 'rug',\n 'security',\n 'forensic',\n 'tokenomics',\n];\n\nconst NEWS_TRIGGERS = ['news', 'headlines', 'latest', 'happening', 'update'];\nconst TRENDS_TRIGGERS = ['trending', 'hot', 'popular', 'market', 'overview', 'today', 'right now'];\n\nfunction buildAssistantPrefill(userMessage: string): string {\n const lower = userMessage.toLowerCase();\n const isPrediction = PREDICTION_TRIGGERS.some((t) => lower.includes(t));\n const isAnalysis = ANALYSIS_TRIGGERS.some((t) => lower.includes(t));\n const isNews = NEWS_TRIGGERS.some((t) => lower.includes(t));\n const isTrends = TRENDS_TRIGGERS.some((t) => lower.includes(t));\n\n if (isPrediction) {\n return 'Based on the real-time market data, here is my price analysis and projection:\\n\\n';\n }\n if (isAnalysis) {\n return 'Here is my analysis based on the real-time data:\\n\\n';\n }\n if (isNews) {\n return 'Here is the latest from the crypto markets:\\n\\n';\n }\n if (isTrends) {\n return 'Here is what is happening in the crypto market right now:\\n\\n';\n }\n return '';\n}\n\n/**\n * Reframe the user message to avoid triggering safety filters.\n * \"predict price\" → \"provide data-driven price scenario analysis\"\n * This is needed because local models refuse on \"predict\" as a keyword.\n */\nfunction reframeForSafety(userMessage: string): string {\n let msg = userMessage;\n // Reframe prediction language to analysis language\n msg = msg.replace(\n /\\bpredict(?:ion)?\\s+(?:the\\s+)?price/gi,\n 'provide a data-driven price scenario analysis for',\n );\n msg = msg.replace(/\\bpredict\\b/gi, 'analyze and project');\n msg = msg.replace(/\\bforecast\\b/gi, 'project scenarios for');\n msg = msg.replace(\n /\\bwill it (?:go|pump|dump|moon|crash)\\b/gi,\n 'what are the likely scenarios based on data',\n );\n return msg;\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class OllamaProvider implements AIProvider {\n readonly name = 'ollama';\n readonly supportsTools = false;\n\n private client!: Ollama;\n private model = DEFAULT_MODELS['ollama']!;\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, _maxTokens: number): void {\n // apiKey is used as the host URL for Ollama (defaults to http://localhost:11434)\n const host = apiKey || 'http://localhost:11434';\n this.client = new Ollama({ host });\n this.model = model;\n }\n\n // -------------------------------------------------------------------------\n // Non-streaming analysis (no tool use for Ollama)\n // -------------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n _tools?: AITool[],\n _toolHandler?: ToolHandler,\n ): Promise<string> {\n const safeMessage = reframeForSafety(userMessage);\n const prefill = buildAssistantPrefill(userMessage);\n\n const messages: { role: string; content: string }[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: safeMessage },\n ];\n // Only inject assistant prefill when we need to steer the model\n if (prefill) {\n messages.push({ role: 'assistant', content: prefill });\n }\n\n const response = await this.client.chat({\n model: this.model,\n messages,\n });\n\n return prefill + response.message.content;\n }\n\n // -------------------------------------------------------------------------\n // Streaming analysis (no tool use for Ollama)\n // -------------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n _tools?: AITool[],\n _toolHandler?: ToolHandler,\n ): Promise<string> {\n const safeMessage = reframeForSafety(userMessage);\n const prefill = buildAssistantPrefill(userMessage);\n\n // Emit the prefill text first so the user sees it immediately\n if (prefill) callbacks.onText(prefill);\n\n const messages: { role: string; content: string }[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: safeMessage },\n ];\n if (prefill) {\n messages.push({ role: 'assistant', content: prefill });\n }\n\n const response = await this.client.chat({\n model: this.model,\n messages,\n stream: true,\n });\n\n let fullText = prefill;\n for await (const chunk of response) {\n const text = chunk.message.content;\n if (text) {\n fullText += text;\n callbacks.onText(text);\n }\n }\n\n callbacks.onDone(fullText);\n return fullText;\n }\n}\n","// ---------------------------------------------------------------------------\n// Provider registry — factory + initialisation + availability checking\n// ---------------------------------------------------------------------------\n\nimport type { AIProvider } from './types.js';\nimport type { VizzorConfig } from '../../config/schema.js';\nimport { DEFAULT_MODELS } from './types.js';\nimport { AnthropicProvider } from './anthropic.js';\nimport { OpenAIProvider } from './openai.js';\nimport { GeminiProvider } from './gemini.js';\nimport { OllamaProvider } from './ollama.js';\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a bare (uninitialised) provider instance by name.\n * Call `initialize()` on the returned provider before use.\n */\nexport function createProvider(name: string): AIProvider {\n switch (name) {\n case 'anthropic':\n return new AnthropicProvider();\n case 'openai':\n return new OpenAIProvider();\n case 'gemini':\n return new GeminiProvider();\n case 'ollama':\n return new OllamaProvider();\n default:\n throw new Error(\n `Unknown AI provider \"${name}\". Supported: anthropic, openai, gemini, ollama.`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Initialisation helper\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a provider, resolves the API key and model from config, calls\n * `initialize()`, and returns a ready-to-use provider instance.\n */\nexport function initializeProvider(name: string, cfg: VizzorConfig): AIProvider {\n const provider = createProvider(name);\n\n const apiKey = getApiKey(name, cfg);\n const model = resolveModel(name, cfg.ai.model);\n const maxTokens = cfg.ai.maxTokens;\n\n provider.initialize(apiKey, model, maxTokens);\n return provider;\n}\n\n// ---------------------------------------------------------------------------\n// Availability checker\n// ---------------------------------------------------------------------------\n\n/**\n * Returns an array describing which providers are available (have keys set)\n * and which are not.\n */\nexport function getAvailableProviders(\n cfg: VizzorConfig,\n): { name: string; available: boolean; reason?: string }[] {\n const providers = ['anthropic', 'openai', 'gemini', 'ollama'] as const;\n\n return providers.map((name) => {\n switch (name) {\n case 'anthropic':\n return cfg.anthropicApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'ANTHROPIC_API_KEY not set' };\n\n case 'openai':\n return cfg.openaiApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'OPENAI_API_KEY not set' };\n\n case 'gemini':\n return cfg.googleApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'GOOGLE_API_KEY not set' };\n\n case 'ollama':\n // Ollama is always \"available\" — it runs locally and doesn't need an API key.\n return { name, available: true };\n\n default:\n return { name, available: false, reason: 'Unknown provider' };\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Pick the right model for the given provider. If the user explicitly set a\n * model in config we only honour it when it looks like it belongs to the\n * target provider — otherwise we fall back to the provider's default.\n * This prevents sending e.g. \"claude-sonnet-4-20250514\" to OpenAI.\n */\nfunction resolveModel(provider: string, configModel: string | undefined): string {\n if (!configModel) {\n return DEFAULT_MODELS[provider] ?? 'unknown';\n }\n\n const prefixes: Record<string, string[]> = {\n anthropic: ['claude'],\n openai: ['gpt', 'o1', 'o3', 'o4', 'chatgpt', 'davinci', 'babbage'],\n gemini: ['gemini', 'models/gemini'],\n ollama: ['llama', 'mistral', 'codellama', 'phi', 'deepseek', 'qwen', 'gemma'],\n };\n\n const expectedPrefixes = prefixes[provider];\n if (!expectedPrefixes) {\n return configModel;\n }\n\n const lower = configModel.toLowerCase();\n const matchesProvider = expectedPrefixes.some((p) => lower.startsWith(p));\n return matchesProvider ? configModel : (DEFAULT_MODELS[provider] ?? configModel);\n}\n\n/**\n * Resolves the correct API key (or host URL) for a given provider from config.\n */\nfunction getApiKey(name: string, cfg: VizzorConfig): string | undefined {\n switch (name) {\n case 'anthropic':\n return cfg.anthropicApiKey;\n case 'openai':\n return cfg.openaiApiKey;\n case 'gemini':\n return cfg.googleApiKey;\n case 'ollama':\n return cfg.ai.ollamaHost;\n default:\n return undefined;\n }\n}\n","// ---------------------------------------------------------------------------\n// GoPlus Security API client — token security checks, no auth required\n// https://docs.gopluslabs.io/\n// Rate limit: ~30 req/min\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.gopluslabs.io/api/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TokenSecurity {\n contractAddress: string;\n chain: string;\n isOpenSource: boolean;\n isProxy: boolean;\n isMintable: boolean;\n canTakeBackOwnership: boolean;\n ownerChangeBalance: boolean;\n hiddenOwner: boolean;\n selfDestruct: boolean;\n externalCall: boolean;\n isHoneypot: boolean;\n buyTax: number;\n sellTax: number;\n cannotBuy: boolean;\n cannotSellAll: boolean;\n slippageModifiable: boolean;\n isBlacklisted: boolean;\n isWhitelisted: boolean;\n antiWhaleModifiable: boolean;\n tradingCooldown: boolean;\n personalSlippageModifiable: boolean;\n holderCount: number;\n lpHolderCount: number;\n totalSupply: string;\n creatorAddress: string;\n creatorPercent: number;\n ownerAddress: string;\n ownerPercent: number;\n lpTotalSupplyPercent: number;\n isInDex: boolean;\n dexInfo: { name: string; liquidity: string; pair: string }[];\n trustList: boolean;\n riskLevel: 'safe' | 'warning' | 'danger';\n}\n\nexport interface AddressSecurity {\n address: string;\n isContract: boolean;\n maliciousAddress: boolean;\n honeypotRelated: boolean;\n phishing: boolean;\n blacklistDoubt: boolean;\n dataSources: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Chain ID mapping\n// ---------------------------------------------------------------------------\n\nconst CHAIN_IDS: Record<string, string> = {\n ethereum: '1',\n bsc: '56',\n polygon: '137',\n arbitrum: '42161',\n optimism: '10',\n base: '8453',\n avalanche: '43114',\n solana: 'solana',\n};\n\nfunction resolveChainId(chain: string): string {\n return CHAIN_IDS[chain.toLowerCase()] ?? chain;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`GoPlus API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\n/**\n * Check token security for a contract address on a specific chain.\n */\nexport async function checkTokenSecurity(\n contractAddress: string,\n chain: string,\n): Promise<TokenSecurity | null> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, Record<string, unknown>>;\n }>(`${BASE_URL}/token_security/${chainId}?contract_addresses=${contractAddress.toLowerCase()}`);\n\n if (data.code !== 1) return null;\n\n const addr = contractAddress.toLowerCase();\n const raw = data.result[addr];\n if (!raw) return null;\n\n const toBool = (v: unknown): boolean => v === '1' || v === 1 || v === true;\n const toNum = (v: unknown): number => (v != null ? parseFloat(String(v)) : 0);\n\n const buyTax = toNum(raw['buy_tax']);\n const sellTax = toNum(raw['sell_tax']);\n const isHoneypot = toBool(raw['is_honeypot']);\n const isMintable = toBool(raw['is_mintable']);\n\n let riskLevel: TokenSecurity['riskLevel'] = 'safe';\n if (isHoneypot || sellTax > 0.5 || isMintable) {\n riskLevel = 'danger';\n } else if (sellTax > 0.1 || buyTax > 0.1 || toBool(raw['hidden_owner'])) {\n riskLevel = 'warning';\n }\n\n return {\n contractAddress: addr,\n chain,\n isOpenSource: toBool(raw['is_open_source']),\n isProxy: toBool(raw['is_proxy']),\n isMintable,\n canTakeBackOwnership: toBool(raw['can_take_back_ownership']),\n ownerChangeBalance: toBool(raw['owner_change_balance']),\n hiddenOwner: toBool(raw['hidden_owner']),\n selfDestruct: toBool(raw['selfdestruct']),\n externalCall: toBool(raw['external_call']),\n isHoneypot,\n buyTax,\n sellTax,\n cannotBuy: toBool(raw['cannot_buy']),\n cannotSellAll: toBool(raw['cannot_sell_all']),\n slippageModifiable: toBool(raw['slippage_modifiable']),\n isBlacklisted: toBool(raw['is_blacklisted']),\n isWhitelisted: toBool(raw['is_whitelisted']),\n antiWhaleModifiable: toBool(raw['anti_whale_modifiable']),\n tradingCooldown: toBool(raw['trading_cooldown']),\n personalSlippageModifiable: toBool(raw['personal_slippage_modifiable']),\n holderCount: toNum(raw['holder_count']),\n lpHolderCount: toNum(raw['lp_holder_count']),\n totalSupply: String(raw['total_supply'] ?? '0'),\n creatorAddress: String(raw['creator_address'] ?? ''),\n creatorPercent: toNum(raw['creator_percent']),\n ownerAddress: String(raw['owner_address'] ?? ''),\n ownerPercent: toNum(raw['owner_percent']),\n lpTotalSupplyPercent: toNum(raw['lp_total_supply_percent']),\n isInDex: toBool(raw['is_in_dex']),\n dexInfo: Array.isArray(raw['dex'])\n ? (raw['dex'] as { name: string; liquidity: string; pair: string }[])\n : [],\n trustList: toBool(raw['trust_list']),\n riskLevel,\n };\n}\n\n/**\n * Check if an address is associated with malicious activity.\n */\nexport async function checkAddressSecurity(\n address: string,\n chain: string,\n): Promise<AddressSecurity | null> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, unknown>;\n }>(`${BASE_URL}/address_security/${chainId}?address=${address.toLowerCase()}`);\n\n if (data.code !== 1) return null;\n const raw = data.result;\n\n const toBool = (v: unknown): boolean => v === '1' || v === 1 || v === true;\n\n return {\n address: address.toLowerCase(),\n isContract: toBool(raw['contract_address']),\n maliciousAddress: toBool(raw['malicious_address']),\n honeypotRelated: toBool(raw['honeypot_related_address']),\n phishing: toBool(raw['phishing_activities']),\n blacklistDoubt: toBool(raw['blacklist_doubt']),\n dataSources: Array.isArray(raw['data_source']) ? (raw['data_source'] as string[]) : [],\n };\n}\n\n/**\n * Check token approval security for an address.\n */\nexport async function checkApprovalSecurity(\n contractAddress: string,\n chain: string,\n): Promise<{ isApprovalAbuse: boolean; approvalRisk: string }> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, unknown>;\n }>(\n `${BASE_URL}/approval_security/${chainId}?contract_addresses=${contractAddress.toLowerCase()}`,\n );\n\n if (data.code !== 1) {\n return { isApprovalAbuse: false, approvalRisk: 'unknown' };\n }\n\n const raw = data.result;\n return {\n isApprovalAbuse: raw['is_approval_abuse'] === '1',\n approvalRisk: String(raw['approval_risk'] ?? 'none'),\n };\n}\n","// ---------------------------------------------------------------------------\n// Context injector — pre-fetches real-time data for providers without tool use\n// (e.g. Ollama). Injects data as context into the system prompt so the AI\n// can answer with current information instead of stale training data.\n// ---------------------------------------------------------------------------\n\nimport { fetchMarketData, fetchTokenFromDex, fetchTrendingTokens } from '../core/trends/market.js';\nimport { fetchCryptoNews } from '../data/sources/cryptopanic.js';\nimport { fetchRecentRaises } from '../data/sources/defillama.js';\nimport { fetchLatestCoins } from '../data/sources/pumpfun.js';\nimport { fetchTickerPrice, fetchFundingRate, fetchOpenInterest } from '../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { checkTokenSecurity, checkAddressSecurity } from '../data/sources/goplus.js';\nimport { getConfig } from '../config/loader.js';\nimport { KNOWN_SYMBOLS } from '../config/constants.js';\nimport { getMLClient } from '../ml/client.js';\n\n// ---------------------------------------------------------------------------\n// Keyword patterns for detecting user intent\n// ---------------------------------------------------------------------------\n\nconst PRICE_KEYWORDS = ['price', 'worth', 'cost', 'value', 'how much'];\nconst TRENDING_KEYWORDS = ['trending', 'hot', 'popular', 'top', 'best', 'hype'];\nconst NEWS_KEYWORDS = ['news', 'latest', 'update', 'happening', 'announcement'];\nconst RAISES_KEYWORDS = [\n 'ico',\n 'ido',\n 'launch',\n 'raise',\n 'funding',\n 'fundrais',\n 'invest',\n 'new project',\n];\nconst PUMP_KEYWORDS = ['pump', 'meme', 'solana launch', 'pump.fun', 'degen'];\nconst ANALYSIS_KEYWORDS = [\n 'anali', // analyze, analysis, analize (typo-tolerant)\n 'audit',\n 'scan',\n 'tokenomics',\n 'rug',\n 'security',\n 'forensic',\n 'contract',\n 'check',\n 'review',\n 'inspect',\n 'investigate',\n 'deep dive',\n 'full report',\n 'due diligence',\n];\nconst COMPLEX_KEYWORDS = [\n 'predict',\n 'prediction',\n 'forecast',\n 'will it',\n 'going to',\n 'should i buy',\n 'should i sell',\n 'compare',\n 'vs',\n 'versus',\n 'portfolio',\n 'allocat',\n 'diversif',\n 'strategy',\n 'risk',\n 'hedge',\n 'long term',\n 'short term',\n 'entry',\n 'exit',\n 'target',\n 'when to',\n 'best time',\n 'opportunity',\n 'undervalued',\n 'overvalued',\n];\nconst BROAD_KEYWORDS = [\n \"what's happening\",\n 'whats happening',\n 'market',\n 'overview',\n 'summary',\n 'up to date',\n 'up-to-date',\n 'current',\n 'right now',\n 'today',\n '2025',\n '2026',\n 'lately',\n 'recently',\n 'this week',\n 'this month',\n 'general',\n 'everything',\n 'outlook',\n 'sentiment',\n 'macro',\n 'state of',\n 'tell me about crypto',\n 'crypto market',\n];\n\n// KNOWN_SYMBOLS is now imported from config/constants.ts\n\n// ---------------------------------------------------------------------------\n// Main function\n// ---------------------------------------------------------------------------\n\n/**\n * Build a context block with real-time data based on the user's message.\n * Returns a string to prepend to the system prompt, or empty string if\n * no relevant data was found.\n */\nexport async function buildContextBlock(userMessage: string): Promise<string> {\n const lower = userMessage.toLowerCase();\n const sections: string[] = [];\n\n // ML: try intent classification for improved query routing\n let mlIntent: string | null = null;\n const mlClientForIntent = getMLClient();\n if (mlClientForIntent) {\n try {\n const intentResult = await mlClientForIntent.classifyIntent(userMessage);\n if (intentResult && intentResult.confidence > 0.7) {\n mlIntent = intentResult.intent;\n }\n } catch {\n // ML unavailable — fall through to keyword matching\n }\n }\n\n // Detect addresses (EVM 0x... and Solana base58)\n const evmMatch = userMessage.match(/0x[a-fA-F0-9]{40}/);\n // Solana base58: 32-44 chars, must contain at least one digit to avoid matching English words\n const solanaMatch = userMessage.match(/\\b([1-9A-HJ-NP-Za-km-z]{32,44})\\b/);\n const isSolanaAddr =\n solanaMatch && !evmMatch && /\\d/.test(solanaMatch[1]!) && solanaMatch[1]!.length >= 32;\n const addressMatch = evmMatch ?? (isSolanaAddr ? solanaMatch : null);\n const detectedChain = evmMatch ? null : isSolanaAddr ? 'solana' : null;\n\n // Detect token mentions (known + unknown)\n const mentionedTokens = detectTokens(lower);\n const unknownTokens = detectUnknownTokens(userMessage, mentionedTokens);\n const isAnalysisQuery = matchesAny(lower, ANALYSIS_KEYWORDS) || mlIntent === 'analysis';\n\n // Run relevant fetches in parallel\n const tasks: Promise<void>[] = [];\n\n // 1. Price / token data (known tokens)\n if (mentionedTokens.length > 0 || addressMatch || matchesAny(lower, PRICE_KEYWORDS)) {\n tasks.push(\n fetchTokenData(mentionedTokens, addressMatch?.[0]).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 1b. Search DexScreener for unknown tokens (not in KNOWN_SYMBOLS)\n // If analysis intent, also run GoPlus security + protocol lookup\n if (\n unknownTokens.length > 0 ||\n (isAnalysisQuery && mentionedTokens.length === 0 && !addressMatch)\n ) {\n const searchTokens = unknownTokens.length > 0 ? unknownTokens : [];\n // Also try to extract the subject of analysis from the message\n if (searchTokens.length === 0 && isAnalysisQuery) {\n const verbMatch = lower.match(\n /(?:anali[zs]e|audit|scan|check|review|inspect)\\s+([a-z0-9]+)/i,\n );\n if (verbMatch) searchTokens.push(verbMatch[1]!);\n }\n for (const token of searchTokens.slice(0, 3)) {\n tasks.push(\n fetchDexAndSecurityData(token, isAnalysisQuery).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // 1c. If address provided + analysis intent, run GoPlus security + address check\n if (addressMatch && isAnalysisQuery) {\n const chain = detectedChain || getConfig().defaultChain || 'ethereum';\n tasks.push(\n fetchSecurityData(addressMatch[0], chain).then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchAddressSecurityData(addressMatch[0], chain).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 2. Trending\n if (matchesAny(lower, TRENDING_KEYWORDS)) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 3. News\n if (matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 4. Raises / ICOs\n if (matchesAny(lower, RAISES_KEYWORDS)) {\n tasks.push(\n fetchRaisesData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 5. Pump.fun / meme coins\n if (matchesAny(lower, PUMP_KEYWORDS)) {\n tasks.push(\n fetchPumpData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 6. Broad / general query — fetch everything for a full picture\n // BUT skip the broad dump when a specific token is mentioned (e.g. \"bitcoin today\"\n // should focus on Bitcoin, not dump trending meme coins and fundraising rounds).\n const isBroadQuery = matchesAny(lower, BROAD_KEYWORDS) || mlIntent === 'broad_overview';\n const hasSpecificIntent =\n mentionedTokens.length > 0 || unknownTokens.length > 0 || !!addressMatch;\n if (isBroadQuery && !hasSpecificIntent) {\n // Inject trending if not already queued\n if (!matchesAny(lower, TRENDING_KEYWORDS)) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject news if not already queued\n if (!matchesAny(lower, NEWS_KEYWORDS)) {\n tasks.push(\n fetchNewsData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject raises if not already queued\n if (!matchesAny(lower, RAISES_KEYWORDS)) {\n tasks.push(\n fetchRaisesData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject top 3 market data if not already queued\n if (!matchesAny(lower, PRICE_KEYWORDS)) {\n tasks.push(\n fetchTokenData(['bitcoin', 'ethereum', 'solana']).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n } else if (isBroadQuery && hasSpecificIntent) {\n // Token-specific broad query (e.g. \"bitcoin today\") — only fetch token-relevant news\n if (!matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase() || unknownTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // If no specific intent detected, try to fetch market data for any mentioned tokens\n if (tasks.length === 0 && mentionedTokens.length > 0) {\n tasks.push(\n fetchTokenData(mentionedTokens).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // If no known tokens but unknown ones detected, search DexScreener\n if (tasks.length === 0 && unknownTokens.length > 0) {\n for (const token of unknownTokens.slice(0, 3)) {\n tasks.push(\n fetchDexAndSecurityData(token, false).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // If still no tasks, inject baseline context (trending + news) so Ollama never hallucinates\n if (tasks.length === 0) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchNewsData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // Always inject market sentiment (Fear & Greed) + top-3 Binance prices for baseline accuracy\n tasks.push(\n fetchFearGreedData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchBinancePriceData(['BTC', 'ETH', 'SOL']).then((data) => {\n if (data) sections.push(data);\n }),\n );\n\n // Inject derivatives data for broad, price, or analysis queries\n if (\n isBroadQuery ||\n matchesAny(lower, PRICE_KEYWORDS) ||\n mentionedTokens.length > 0 ||\n isAnalysisQuery\n ) {\n const derivTokens = mentionedTokens.length > 0 ? mentionedTokens : unknownTokens;\n tasks.push(\n fetchDerivativesData(derivTokens).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // For analysis queries, also fetch news if not already queued\n if (isAnalysisQuery && !matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase() || unknownTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n await Promise.allSettled(tasks);\n\n if (sections.length === 0) return '';\n\n // ---------------------------------------------------------------------------\n // Classify query type — determines what data/instructions to inject\n // ---------------------------------------------------------------------------\n const allTokens = [...mentionedTokens, ...unknownTokens];\n const hasSpecificToken = allTokens.length > 0 || !!addressMatch;\n const isNewsQuery = matchesAny(lower, NEWS_KEYWORDS);\n const isTrendsQuery = matchesAny(lower, TRENDING_KEYWORDS);\n const isPredictionQuery = matchesAny(lower, COMPLEX_KEYWORDS);\n const isComplexQuery = isPredictionQuery;\n\n type QueryType = 'token_analysis' | 'prediction' | 'news' | 'trends' | 'general';\n let queryType: QueryType;\n\n if (hasSpecificToken && (isAnalysisQuery || isPredictionQuery)) {\n queryType = isPredictionQuery ? 'prediction' : 'token_analysis';\n } else if (isNewsQuery) {\n queryType = 'news';\n } else if (isTrendsQuery || isBroadQuery) {\n queryType = 'trends';\n } else if (hasSpecificToken) {\n queryType = 'token_analysis';\n } else {\n queryType = 'general';\n }\n\n // ---------------------------------------------------------------------------\n // Build output — only inject what's relevant to the query type\n // ---------------------------------------------------------------------------\n const output: string[] = [\n '',\n `CURRENT DATE: ${new Date().toISOString().split('T')[0]} (data fetched just now)`,\n '--- REAL-TIME DATA (fetched just now) ---',\n ...sections,\n '--- END REAL-TIME DATA ---',\n '',\n ];\n\n // Only inject signals, price targets, and analysis report for TOKEN-SPECIFIC queries\n if (hasSpecificToken) {\n const dataSummary = buildDataSummary(sections, allTokens);\n const signals = computeSignals(sections, allTokens, userMessage);\n const report = buildAnalysisReport(sections, allTokens, signals);\n\n output.push(dataSummary, '');\n if (signals) output.push(signals, '');\n if (report) output.push(report, '');\n }\n\n // Inject query-type-specific instructions\n output.push(...buildInstructions(queryType, hasSpecificToken, isComplexQuery));\n output.push('');\n\n return output.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Query-type-aware instructions\n// ---------------------------------------------------------------------------\n\nfunction buildInstructions(\n queryType: string,\n hasSpecificToken: boolean,\n isComplexQuery: boolean,\n): string[] {\n const base: string[] = [\n 'CRITICAL INSTRUCTIONS (MUST FOLLOW):',\n '- NEVER output \"--- REAL-TIME DATA ---\" or \"--- END REAL-TIME DATA ---\" markers.',\n '- You MUST use ONLY the real-time data above. Do NOT invent or fabricate any data.',\n '- Your training data is STALE. The ONLY trustworthy data is between the markers above.',\n '- Cite sources: (DexScreener), (Binance), (GoPlus), (CoinGecko), (Fear & Greed Index).',\n ];\n\n switch (queryType) {\n case 'news':\n base.push(\n '',\n 'QUERY TYPE: NEWS — The user wants crypto news and market updates.',\n '- Summarize the news headlines from the data above.',\n '- Add market context: mention BTC/ETH prices and Fear & Greed sentiment.',\n '- Group news by theme if possible (regulation, DeFi, NFT, major coins, etc.).',\n '- Do NOT analyze a specific token unless the user mentioned one.',\n '- Keep it conversational and informative.',\n );\n break;\n\n case 'trends':\n base.push(\n '',\n 'QUERY TYPE: TRENDS/MARKET OVERVIEW — The user wants to know what is trending.',\n '- Lead with the overall market sentiment (Fear & Greed + BTC direction).',\n '- List the top trending tokens with key metrics (price, 24h change, volume).',\n '- Mention notable movers (biggest gainers/losers).',\n '- Add fundraising rounds if available.',\n '- Do NOT do a deep dive into any single token unless specifically asked.',\n );\n break;\n\n case 'token_analysis':\n base.push(\n '',\n 'QUERY TYPE: TOKEN ANALYSIS — The user wants deep analysis of a specific token.',\n '- Follow the analysis report structure above (Verdict → Market → Security → Signals → Risks).',\n '- Include price prediction scenarios with actual dollar values if available.',\n '- Present GoPlus security findings if available.',\n '- Do NOT list unrelated trending tokens.',\n '- Missing data IS a finding worth reporting.',\n );\n break;\n\n case 'prediction':\n base.push(\n '',\n 'QUERY TYPE: PRICE PREDICTION — The user wants future price projections.',\n '- ALWAYS include the PRICE PREDICTION SCENARIOS with the exact dollar values from the data.',\n '- If USER-REQUESTED TIMEFRAME exists, present it FIRST and prominently.',\n '- Present ALL timeframes: scalping (5min/15min/1h/4h), short-term (1d/7d), medium (2w/1mo), long (3mo).',\n '- Include the composite signal direction and confidence level.',\n '- Mention key support/resistance levels.',\n '- State what would invalidate the prediction.',\n '- Do NOT list unrelated trending tokens.',\n );\n break;\n\n default: // 'general'\n base.push(\n '',\n 'QUERY TYPE: GENERAL — Answer naturally using the data above as context.',\n '- Use the real-time prices and sentiment as background context.',\n \"- Answer the user's actual question directly.\",\n \"- Do NOT force a token analysis if the user didn't ask for one.\",\n '- Keep your response natural and conversational.',\n );\n break;\n }\n\n if (isComplexQuery && hasSpecificToken) {\n base.push(\n '',\n 'COMPLEX ANALYSIS: Structure your reasoning as Data → Signals → Alignment → Confidence → Risks → Conclusion.',\n );\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Data fetchers\n// ---------------------------------------------------------------------------\n\nasync function fetchTokenData(tokens: string[], address?: string): Promise<string | null> {\n const lines: string[] = ['## Token / Price Data'];\n\n // Fetch by address via DexScreener\n if (address) {\n try {\n const pairs = await fetchTokenFromDex(address);\n const pair = pairs[0];\n if (pair) {\n lines.push(\n `${pair.baseToken.name} (${pair.baseToken.symbol}) on ${pair.chainId}:`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` Liquidity: $${(pair.liquidity?.usd ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n ` 24h Txns: ${pair.txns?.h24?.buys ?? 0} buys / ${pair.txns?.h24?.sells ?? 0} sells`,\n ` Market Cap: $${(pair.marketCap ?? pair.fdv ?? 0).toLocaleString()}`,\n ` DEX: ${pair.dexId} | Pair: ${pair.pairAddress}`,\n '',\n );\n }\n } catch {\n // skip\n }\n }\n\n // Fetch named tokens: Binance (primary) -> CoinGecko (fallback) -> DexScreener (fallback)\n for (const token of tokens.slice(0, 3)) {\n const sym =\n token === 'bitcoin'\n ? 'BTC'\n : token === 'ethereum'\n ? 'ETH'\n : token === 'solana'\n ? 'SOL'\n : token.toUpperCase();\n\n // Try Binance first (most reliable, no rate limits)\n try {\n const binanceData = await fetchTickerPrice(sym);\n if (binanceData) {\n lines.push(\n `${sym} (via Binance):`,\n ` Price: $${binanceData.price.toLocaleString()}`,\n ` 24h Change: ${binanceData.change24h > 0 ? '+' : ''}${binanceData.change24h.toFixed(2)}%`,\n );\n // Also try CoinGecko for extended data (market cap, rank, 7d)\n const geckoId = KNOWN_SYMBOLS[token];\n if (geckoId) {\n try {\n const gecko = await fetchMarketData(geckoId);\n if (gecko) {\n lines.push(\n ` 7d Change: ${gecko.priceChange7d > 0 ? '+' : ''}${gecko.priceChange7d.toFixed(2)}%`,\n ` 24h Volume: $${gecko.volume24h.toLocaleString()}`,\n ` Market Cap: $${gecko.marketCap.toLocaleString()}`,\n ` Rank: #${gecko.rank ?? '?'}`,\n );\n }\n } catch {\n // CoinGecko unavailable, continue with Binance data only\n }\n }\n lines.push('');\n continue;\n }\n } catch {\n // Binance unavailable, fall through\n }\n\n // Fallback to CoinGecko\n const geckoId = KNOWN_SYMBOLS[token];\n if (geckoId) {\n try {\n const data = await fetchMarketData(geckoId);\n if (data) {\n lines.push(\n `${data.name} (${data.symbol}):`,\n ` Price: $${data.price.toLocaleString()}`,\n ` 24h Change: ${data.priceChange24h > 0 ? '+' : ''}${data.priceChange24h.toFixed(2)}%`,\n ` 7d Change: ${data.priceChange7d > 0 ? '+' : ''}${data.priceChange7d.toFixed(2)}%`,\n ` 24h Volume: $${data.volume24h.toLocaleString()}`,\n ` Market Cap: $${data.marketCap.toLocaleString()}`,\n ` Rank: #${data.rank ?? '?'}`,\n '',\n );\n continue;\n }\n } catch {\n // fall through to DexScreener\n }\n }\n\n // Final fallback: DexScreener for tokens not on Binance/CoinGecko\n try {\n const pairs = await fetchTokenFromDex(token);\n const pair = pairs[0];\n if (pair) {\n lines.push(\n `${pair.baseToken.name} (${pair.baseToken.symbol}) on ${pair.chainId}:`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n '',\n );\n }\n } catch {\n // skip\n }\n }\n\n return lines.length > 1 ? lines.join('\\n') : null;\n}\n\nasync function fetchTrendingData(): Promise<string | null> {\n try {\n const trending = await fetchTrendingTokens();\n if (trending.length === 0) return null;\n\n const lines = ['## Trending Tokens (live)'];\n for (const t of trending.slice(0, 10)) {\n lines.push(\n `- ${t.name} (${t.symbol}) on ${t.chain}: $${t.priceUsd} | 24h: ${t.priceChange24h > 0 ? '+' : ''}${t.priceChange24h.toFixed(1)}% | Vol: $${t.volume24h.toLocaleString()} [${t.source}]`,\n );\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchNewsData(symbol?: string): Promise<string | null> {\n try {\n const news = await fetchCryptoNews(symbol, getConfig().cryptopanicApiKey);\n if (news.length > 0) {\n const headlines = news.slice(0, 8);\n const lines = [`## Latest Crypto News${symbol ? ` (${symbol})` : ''}`];\n\n // ML: enhance sentiment labels with ML NLP analysis\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const texts = headlines.map((n) => n.title);\n const mlResults = await mlClient.analyzeSentimentBatch(texts);\n if (mlResults.length > 0) {\n for (let i = 0; i < headlines.length; i++) {\n const n = headlines[i]!;\n const ml = mlResults[i];\n const label = ml\n ? `${ml.sentiment.toUpperCase()} (${(ml.confidence * 100).toFixed(0)}%)`\n : n.sentiment.toUpperCase();\n lines.push(`- [${label}] ${n.title} (${n.source.title}, ${n.publishedAt})`);\n }\n // Aggregate ML sentiment score\n const avgScore = mlResults.reduce((s, r) => s + r.score, 0) / mlResults.length;\n const avgSentiment =\n avgScore > 0.2 ? 'BULLISH' : avgScore < -0.2 ? 'BEARISH' : 'NEUTRAL';\n lines.push(`\\nML Aggregate Sentiment: ${avgSentiment} (score: ${avgScore.toFixed(3)})`);\n return lines.join('\\n');\n }\n } catch {\n // ML unavailable — fall through to rule-based labels\n }\n }\n\n // Fallback: use CryptoPanic sentiment labels\n for (const n of headlines) {\n lines.push(\n `- [${n.sentiment.toUpperCase()}] ${n.title} (${n.source.title}, ${n.publishedAt})`,\n );\n }\n return lines.join('\\n');\n }\n } catch {\n // CryptoPanic unavailable, fall through to free fallback\n }\n\n // Free fallback: fetch headlines from Google News RSS (no API key needed)\n try {\n const query = symbol ? `${symbol}+crypto` : 'cryptocurrency+bitcoin';\n const rssUrl = `https://news.google.com/rss/search?q=${query}&hl=en&gl=US&ceid=US:en`;\n const res = await fetch(rssUrl);\n if (!res.ok) return null;\n\n const xml = await res.text();\n // Simple XML title extraction — no parser needed\n const items: string[] = [];\n const itemRegex =\n /<item>[\\s\\S]*?<title>([\\s\\S]*?)<\\/title>[\\s\\S]*?<pubDate>([\\s\\S]*?)<\\/pubDate>[\\s\\S]*?<\\/item>/g;\n let match;\n while ((match = itemRegex.exec(xml)) !== null && items.length < 8) {\n const title = match[1]!.replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim();\n const date = match[2]!.trim();\n items.push(`- ${title} (${date})`);\n }\n\n if (items.length > 0) {\n return [\n `## Latest Crypto News${symbol ? ` (${symbol})` : ''} (via Google News)`,\n ...items,\n ].join('\\n');\n }\n } catch {\n // Google News also unavailable\n }\n\n return null;\n}\n\nasync function fetchRaisesData(): Promise<string | null> {\n try {\n const raises = await fetchRecentRaises(30);\n if (raises.length === 0) return null;\n\n const lines = ['## Recent Crypto Fundraising Rounds (last 30 days)'];\n for (const r of raises.slice(0, 10)) {\n const amount = r.amount\n ? r.amount >= 1e9\n ? `$${(r.amount / 1e9).toFixed(1)}B`\n : r.amount >= 1e6\n ? `$${(r.amount / 1e6).toFixed(1)}M`\n : r.amount >= 1e3\n ? `$${(r.amount / 1e3).toFixed(0)}K`\n : `$${r.amount.toLocaleString()}`\n : 'undisclosed';\n const date = new Date(r.date * 1000).toISOString().split('T')[0];\n lines.push(\n `- ${r.name} — ${r.round} (${amount}) on ${r.chains.join(', ') || 'multi-chain'} [${date}]${r.leadInvestors.length > 0 ? ` Led by: ${r.leadInvestors.join(', ')}` : ''}`,\n );\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchPumpData(): Promise<string | null> {\n try {\n const coins = await fetchLatestCoins(10);\n if (coins.length === 0) return null;\n\n const lines = ['## Latest Pump.fun Launches (Solana)'];\n for (const c of coins) {\n const mcap = c.usd_market_cap ? `$${c.usd_market_cap.toFixed(0)}` : '?';\n lines.push(`- ${c.name} (${c.symbol}) — MC: ${mcap} | Replies: ${c.reply_count}`);\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// New data fetchers (Binance, Fear & Greed, Derivatives)\n// ---------------------------------------------------------------------------\n\n/**\n * Search DexScreener for a token, then run GoPlus security scan + protocol lookup\n * on the first result. This gives deep analysis for ANY token, including meme coins.\n */\nasync function fetchDexAndSecurityData(\n query: string,\n runSecurity: boolean,\n): Promise<string | null> {\n try {\n const pairs = await fetchTokenFromDex(query);\n if (!pairs || pairs.length === 0) {\n return `## DEX Search: \"${query.toUpperCase()}\"\\nToken NOT FOUND on any DEX (DexScreener). It may be too new, delisted, misspelled, or not yet listed. Try searching by contract address instead.`;\n }\n\n const lines = [`## DEX Data: ${query.toUpperCase()} (via DexScreener, live)`];\n const topPair = pairs[0]!;\n\n // Show top 3 pairs with enriched data\n for (const pair of pairs.slice(0, 3)) {\n const age = pair.pairCreatedAt\n ? `${Math.floor((Date.now() - pair.pairCreatedAt) / 86400000)}d ago`\n : 'unknown';\n lines.push(\n `${pair.baseToken.name} (${pair.baseToken.symbol}) on ${pair.chainId}/${pair.dexId}:`,\n ` Contract: ${pair.baseToken.address}`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` 1h Volume: $${(pair.volume?.h1 ?? 0).toLocaleString()}`,\n ` Liquidity: $${(pair.liquidity?.usd ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n ` 1h Change: ${(pair.priceChange?.h1 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h1 ?? 0).toFixed(2)}%`,\n ` 24h Txns: ${pair.txns?.h24?.buys ?? 0} buys / ${pair.txns?.h24?.sells ?? 0} sells`,\n ` 1h Txns: ${pair.txns?.h1?.buys ?? 0} buys / ${pair.txns?.h1?.sells ?? 0} sells`,\n ` Market Cap: $${(pair.marketCap ?? pair.fdv ?? 0).toLocaleString()}`,\n ` FDV: $${(pair.fdv ?? 0).toLocaleString()}`,\n ` Pair Created: ${age}`,\n ` Pair: ${pair.pairAddress}`,\n );\n // Add social/website info if available\n if (pair.info?.websites?.length) {\n lines.push(` Websites: ${pair.info.websites.map((w) => w.url).join(', ')}`);\n }\n if (pair.info?.socials?.length) {\n lines.push(` Socials: ${pair.info.socials.map((s) => `${s.type}: ${s.url}`).join(', ')}`);\n }\n if (pair.labels?.length) {\n lines.push(` Labels: ${pair.labels.join(', ')}`);\n }\n lines.push('');\n }\n if (pairs.length > 3) {\n lines.push(` ... and ${pairs.length - 3} more pairs found`);\n }\n\n // Run GoPlus security scan on the top pair's contract (parallel)\n if (runSecurity && topPair.baseToken.address) {\n const securityData = await fetchSecurityData(topPair.baseToken.address, topPair.chainId);\n if (securityData) lines.push('', securityData);\n }\n\n // Check if it's a Solana token on pump.fun — get creator info\n if (topPair.chainId === 'solana' && topPair.dexId?.includes('pump')) {\n try {\n const { getCoinDetails } = await import('../data/sources/pumpfun.js');\n const coin = await getCoinDetails(topPair.baseToken.address);\n if (coin) {\n lines.push(\n '',\n `## Pump.fun Data (Solana, live)`,\n ` Creator: ${coin.creator}`,\n ` Description: ${coin.description || 'none'}`,\n ` Market Cap (SOL): ${coin.market_cap?.toFixed(2) ?? '?'}`,\n ` USD Market Cap: $${coin.usd_market_cap?.toLocaleString() ?? '?'}`,\n ` Community Replies: ${coin.reply_count}`,\n ` Created: ${new Date(coin.created_timestamp).toISOString()}`,\n ` NSFW: ${coin.nsfw ? 'YES' : 'no'}`,\n );\n }\n } catch {\n // Pump.fun data unavailable, continue\n }\n }\n\n return lines.join('\\n');\n } catch {\n return `## DEX Search: \"${query.toUpperCase()}\"\\nDexScreener search failed. Token data unavailable.`;\n }\n}\n\n/**\n * Run GoPlus security scan for a contract address on a specific chain.\n * Returns formatted security findings. Works for all GoPlus-supported chains:\n * ethereum, bsc, polygon, arbitrum, optimism, base, avalanche, solana\n */\nasync function fetchSecurityData(contractAddress: string, chain: string): Promise<string | null> {\n try {\n const security = await checkTokenSecurity(contractAddress, chain);\n if (!security) return null;\n\n const lines = [`## Security Audit (GoPlus, live)`];\n lines.push(` Chain: ${chain}`);\n lines.push(` Contract: ${contractAddress}`);\n lines.push(` Risk Level: ${security.riskLevel.toUpperCase()}`);\n lines.push('');\n\n // Critical flags\n const flags: string[] = [];\n if (security.isHoneypot) flags.push('HONEYPOT DETECTED');\n if (security.isMintable) flags.push('MINTABLE (owner can create tokens)');\n if (security.cannotSellAll) flags.push('CANNOT SELL ALL (sell restriction)');\n if (security.cannotBuy) flags.push('CANNOT BUY');\n if (security.selfDestruct) flags.push('SELF-DESTRUCT capable');\n if (security.hiddenOwner) flags.push('HIDDEN OWNER');\n if (security.canTakeBackOwnership) flags.push('CAN RECLAIM OWNERSHIP');\n if (security.ownerChangeBalance) flags.push('OWNER CAN CHANGE BALANCES');\n if (security.isBlacklisted) flags.push('HAS BLACKLIST function');\n if (security.slippageModifiable) flags.push('SLIPPAGE MODIFIABLE by owner');\n if (security.tradingCooldown) flags.push('TRADING COOLDOWN enabled');\n\n if (flags.length > 0) {\n lines.push(` RED FLAGS: ${flags.join(' | ')}`);\n } else {\n lines.push(' RED FLAGS: None detected');\n }\n\n // Tax analysis\n lines.push(` Buy Tax: ${(security.buyTax * 100).toFixed(1)}%`);\n lines.push(` Sell Tax: ${(security.sellTax * 100).toFixed(1)}%`);\n if (security.buyTax > 0.1 || security.sellTax > 0.1) {\n lines.push(' TAX WARNING: High tax detected (>10%)');\n }\n\n // Contract info\n lines.push(` Open Source: ${security.isOpenSource ? 'Yes' : 'No (unverified)'}`);\n lines.push(` Proxy Contract: ${security.isProxy ? 'Yes (upgradeable)' : 'No'}`);\n lines.push(` External Calls: ${security.externalCall ? 'Yes' : 'No'}`);\n\n // Holder info\n lines.push(` Holders: ${security.holderCount.toLocaleString()}`);\n lines.push(` LP Holders: ${security.lpHolderCount}`);\n lines.push(` Total Supply: ${security.totalSupply}`);\n lines.push(` Creator: ${security.creatorAddress || 'unknown'}`);\n lines.push(` Creator Holdings: ${(security.creatorPercent * 100).toFixed(2)}%`);\n lines.push(` Owner: ${security.ownerAddress || 'renounced/none'}`);\n lines.push(` Owner Holdings: ${(security.ownerPercent * 100).toFixed(2)}%`);\n lines.push(` LP Supply Lock: ${(security.lpTotalSupplyPercent * 100).toFixed(1)}%`);\n\n // DEX info\n if (security.dexInfo.length > 0) {\n lines.push(` DEX Listings:`);\n for (const dex of security.dexInfo) {\n lines.push(` - ${dex.name}: liquidity $${dex.liquidity}`);\n }\n }\n\n lines.push(` On Trust List: ${security.trustList ? 'Yes' : 'No'}`);\n\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\n/**\n * Check if an address is flagged as malicious via GoPlus.\n */\nasync function fetchAddressSecurityData(address: string, chain: string): Promise<string | null> {\n try {\n const security = await checkAddressSecurity(address, chain);\n if (!security) return null;\n\n const lines = [`## Address Security Check (GoPlus, live)`];\n lines.push(` Address: ${address}`);\n lines.push(` Is Contract: ${security.isContract ? 'Yes' : 'No (EOA)'}`);\n lines.push(` Malicious: ${security.maliciousAddress ? 'YES — FLAGGED' : 'Not flagged'}`);\n lines.push(` Honeypot Related: ${security.honeypotRelated ? 'YES' : 'No'}`);\n lines.push(` Phishing: ${security.phishing ? 'YES — FLAGGED' : 'No'}`);\n lines.push(` Blacklist Doubt: ${security.blacklistDoubt ? 'YES' : 'No'}`);\n\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchBinancePriceData(symbols: string[]): Promise<string | null> {\n try {\n const results = await Promise.allSettled(symbols.map((s) => fetchTickerPrice(s)));\n const lines: string[] = ['## Live Prices (Binance, real-time)'];\n let hasData = false;\n\n for (let i = 0; i < symbols.length; i++) {\n const result = results[i];\n if (result && result.status === 'fulfilled') {\n const d = result.value;\n lines.push(\n `${d.symbol}: $${d.price.toLocaleString()} | 24h: ${d.change24h > 0 ? '+' : ''}${d.change24h.toFixed(2)}%`,\n );\n hasData = true;\n }\n }\n\n return hasData ? lines.join('\\n') : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchFearGreedData(): Promise<string | null> {\n try {\n const data = await fetchFearGreedIndex(7);\n const c = data.current;\n const lines = [\n `## Market Sentiment (Fear & Greed Index)`,\n `Current: ${c.value}/100 (${c.classification})`,\n ];\n if (data.previous) {\n lines.push(`Previous: ${data.previous.value}/100 (${data.previous.classification})`);\n }\n if (data.history.length > 2) {\n const weekAgo = data.history[data.history.length - 1];\n if (weekAgo) {\n lines.push(`7d ago: ${weekAgo.value}/100 (${weekAgo.classification})`);\n }\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchDerivativesData(tokens: string[]): Promise<string | null> {\n const symbols =\n tokens.length > 0\n ? tokens.slice(0, 3).map((t) => {\n // Convert geckoId-style names to ticker symbols\n if (t === 'bitcoin' || t === 'btc') return 'BTC';\n if (t === 'ethereum' || t === 'eth') return 'ETH';\n if (t === 'solana' || t === 'sol') return 'SOL';\n return t.toUpperCase();\n })\n : ['BTC', 'ETH'];\n\n try {\n const lines: string[] = ['## Derivatives Data (Binance Futures)'];\n let hasData = false;\n\n const results = await Promise.allSettled(\n symbols.map(async (sym) => {\n const [funding, oi] = await Promise.allSettled([\n fetchFundingRate(sym),\n fetchOpenInterest(sym),\n ]);\n return { sym, funding, oi };\n }),\n );\n\n for (const result of results) {\n if (result.status !== 'fulfilled') continue;\n const { sym, funding, oi } = result.value;\n\n const parts: string[] = [`${sym}:`];\n if (funding.status === 'fulfilled') {\n const f = funding.value;\n parts.push(`Funding: ${(f.fundingRate * 100).toFixed(4)}%`);\n parts.push(`Mark: $${f.markPrice.toLocaleString()}`);\n }\n if (oi.status === 'fulfilled') {\n const o = oi.value;\n parts.push(`OI: $${(o.notionalValue / 1e9).toFixed(2)}B`);\n }\n if (parts.length > 1) {\n lines.push(` ${parts.join(' | ')}`);\n hasData = true;\n }\n }\n\n return hasData ? lines.join('\\n') : null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction matchesAny(text: string, keywords: string[]): boolean {\n return keywords.some((kw) => text.includes(kw));\n}\n\nfunction detectTokens(lower: string): string[] {\n const found: string[] = [];\n for (const key of Object.keys(KNOWN_SYMBOLS)) {\n // Match whole word\n const regex = new RegExp(`\\\\b${key}\\\\b`);\n if (regex.test(lower) && !found.includes(key)) {\n found.push(key);\n }\n }\n return found;\n}\n\n/**\n * Detect unknown token names that aren't in KNOWN_SYMBOLS.\n * Looks for ALL-CAPS words (3-10 chars, likely tickers) and words\n * immediately after analysis-intent verbs like \"analyze\", \"audit\", \"scan\".\n */\nfunction detectUnknownTokens(original: string, knownTokens: string[]): string[] {\n const unknowns: string[] = [];\n const knownSet = new Set(knownTokens.map((t) => t.toLowerCase()));\n\n // Pattern 0: $TICKER notation (e.g., $ROFL, $PEPE) — very common in crypto\n const dollarRegex = /\\$([A-Za-z][A-Za-z0-9]{1,9})\\b/g;\n let m0;\n while ((m0 = dollarRegex.exec(original)) !== null) {\n const sym = m0[1]!.toLowerCase();\n if (!knownSet.has(sym) && !unknowns.includes(sym)) {\n unknowns.push(sym);\n }\n }\n\n // Pattern 1: ALL-CAPS words (3-10 chars) that look like ticker symbols\n const capsRegex = /\\b([A-Z][A-Z0-9]{2,9})\\b/g;\n let m;\n while ((m = capsRegex.exec(original)) !== null) {\n const sym = m[1]!.toLowerCase();\n // Skip common English words that happen to be uppercase\n const SKIP = new Set([\n 'THE',\n 'AND',\n 'FOR',\n 'NOT',\n 'BUT',\n 'ALL',\n 'ARE',\n 'WAS',\n 'HAS',\n 'HIS',\n 'HER',\n 'HOW',\n 'WHO',\n 'GET',\n 'GOT',\n 'CAN',\n 'HAD',\n 'HIM',\n 'SET',\n 'RUN',\n 'USE',\n 'ANY',\n 'NEW',\n 'NOW',\n 'OLD',\n 'OUR',\n 'TRY',\n 'LET',\n 'PUT',\n 'SAY',\n 'SHE',\n 'TOO',\n 'DEX',\n 'API',\n 'NFT',\n 'TVL',\n 'CEO',\n 'CTO',\n 'USD',\n 'APR',\n 'APY',\n 'ATH',\n 'ATL',\n 'ROI',\n 'ICO',\n 'IDO',\n 'IEO',\n 'DCA',\n 'HODL',\n 'FOMO',\n 'FUD',\n 'RUG',\n 'FULL',\n ]);\n if (!knownSet.has(sym) && !SKIP.has(m[1]!) && !unknowns.includes(sym)) {\n unknowns.push(sym);\n }\n }\n\n // Pattern 2: Words after analysis verbs (e.g., \"analyze RIGGED\", \"audit rigged\")\n const lower = original.toLowerCase();\n const verbRegex = /(?:anali[zs]e|audit|scan|check|review|inspect)\\s+([a-zA-Z0-9]{2,15})/gi;\n while ((m = verbRegex.exec(lower)) !== null) {\n const token = m[1]!.toLowerCase();\n if (!knownSet.has(token) && !unknowns.includes(token) && token.length >= 2) {\n unknowns.push(token);\n }\n }\n\n return unknowns;\n}\n\n/**\n * Build a summary of what data is available and what is missing.\n * This prevents ANY model (Ollama, Claude, GPT) from hallucinating missing data.\n */\nfunction buildDataSummary(sections: string[], tokens: string[]): string {\n const joined = sections.join('\\n');\n const has = (keyword: string): boolean => joined.toLowerCase().includes(keyword.toLowerCase());\n\n const lines: string[] = ['## DATA AVAILABILITY SUMMARY'];\n const tokenLabel =\n tokens.length > 0 ? tokens.map((t) => t.toUpperCase()).join(', ') : 'general market';\n\n // What we HAVE\n const available: string[] = [];\n if (has('Price:') || has('via Binance')) available.push('Price data');\n if (has('24h Volume:')) available.push('Volume (24h)');\n if (has('Liquidity:')) available.push('Liquidity');\n if (has('Market Cap:')) available.push('Market cap');\n if (has('24h Txns:') || has('buys /')) available.push('Buy/sell transactions');\n if (has('24h Change:')) available.push('Price change (24h)');\n if (has('7d Change:')) available.push('Price change (7d)');\n if (has('Fear & Greed')) available.push('Market sentiment (Fear & Greed)');\n if (has('Funding:')) available.push('Derivatives (funding rate)');\n if (has('OI:')) available.push('Open interest');\n if (has('Trending')) available.push('Trending tokens');\n if (has('News') || has('news')) available.push('News headlines');\n if (has('Fundraising') || has('Raises')) available.push('Fundraising rounds');\n if (has('Contract:')) available.push('Contract address');\n if (has('DEX:') || has('DexScreener') || has('pumpswap') || has('raydium'))\n available.push('DEX pair data');\n if (has('NOT FOUND')) available.push('DEX search (token NOT FOUND)');\n if (has('Security Audit') || has('GoPlus')) available.push('GoPlus security audit');\n if (has('HONEYPOT') || has('RED FLAGS')) available.push('Security flags analysis');\n if (has('Buy Tax:')) available.push('Tax analysis (buy/sell)');\n if (has('Holders:')) available.push('Holder count');\n if (has('Creator:')) available.push('Creator address');\n if (has('Pump.fun')) available.push('Pump.fun creator/community data');\n if (has('Websites:') || has('Socials:')) available.push('Project links (website/socials)');\n if (has('Pair Created:')) available.push('Token age (pair creation date)');\n if (has('Address Security')) available.push('Address security check');\n\n // What we DON'T have (always missing for on-chain-only analysis)\n const missing: string[] = [];\n if (!has('team') && !has('Team')) missing.push('Team/developer identities');\n if (!has('Security Audit') && !has('GoPlus'))\n missing.push('Security audit (provide contract address + chain)');\n if (!has('totalSupply') && !has('Total Supply')) missing.push('Tokenomics breakdown');\n missing.push('Roadmap / project phases');\n if (!has('Websites:') && !has('Socials:')) missing.push('Website / social media data');\n missing.push('Third-party audit reports (CertiK, etc.)');\n if (!has('Funding:')) missing.push('Derivatives data (funding rate, OI)');\n if (!has('News') && !has('news')) missing.push('News sentiment');\n\n lines.push(`Analysis target: ${tokenLabel}`);\n lines.push(`Data available: ${available.length > 0 ? available.join(', ') : 'NONE'}`);\n lines.push(`Data NOT available: ${missing.join(', ')}`);\n lines.push('');\n lines.push(\n 'IMPORTANT: For any item in \"Data NOT available\", say \"not available\" — do NOT invent or fabricate this information.',\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Build a pre-written analysis report that the model should present.\n * This is critical for weaker models (Ollama) that can't filter relevant data\n * from a large context block. The report is focused on the TARGET token only.\n */\nfunction buildAnalysisReport(\n sections: string[],\n tokens: string[],\n signalBlock: string | null,\n): string | null {\n const joined = sections.join('\\n');\n if (tokens.length === 0 && !joined.includes('Price:')) return null;\n\n const tokenLabel =\n tokens.length > 0 ? tokens.map((t) => t.toUpperCase()).join(', ') : 'target token';\n const lines: string[] = [\n '=== PRESENT THIS ANALYSIS REPORT TO THE USER ===',\n `(Focus ONLY on ${tokenLabel}. Do NOT list unrelated trending tokens unless the user asked about trends.)`,\n '',\n ];\n\n // Extract price for the target token (not BTC/ETH baseline)\n const extract = (pattern: RegExp): number | null => {\n const match = joined.match(pattern);\n return match ? parseFloat(match[1]!.replace(/,/g, '')) : null;\n };\n\n // 1. VERDICT — extract key data points\n const price = extract(/Price:\\s*\\$([0-9,.]+(?:e[+-]?\\d+)?)/);\n const change24h = extract(/24h Change:\\s*([+-]?\\d+\\.?\\d*)%/);\n const volume = extract(/24h Volume:\\s*\\$([0-9,]+)/);\n const liq = extract(/Liquidity:\\s*\\$([0-9,]+)/);\n const fearGreed = extract(/Current:\\s*(\\d+)\\/100/);\n const fgClass = joined.match(/Current:\\s*\\d+\\/100\\s*\\(([^)]+)\\)/)?.[1];\n const riskLevel = joined.match(/Risk Level:\\s*(\\w+)/)?.[1];\n const fundingMatch = joined.match(/Funding:\\s*([+-]?\\d+\\.?\\d*)%/);\n const oiMatch = joined.match(/OI:\\s*\\$([0-9.]+B?)/);\n\n if (price !== null) {\n const changeStr =\n change24h !== null ? ` (${change24h > 0 ? '+' : ''}${change24h.toFixed(2)}% 24h)` : '';\n lines.push(`## 1. Verdict`);\n lines.push(\n `${tokenLabel} is at $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()}${changeStr}.`,\n );\n if (fearGreed !== null) {\n lines.push(`Market sentiment: ${fgClass} (${fearGreed}/100).`);\n }\n if (riskLevel) {\n lines.push(`Security risk: ${riskLevel.toUpperCase()}.`);\n }\n lines.push('');\n }\n\n // 2. MARKET DATA\n lines.push('## 2. Market Data (cite these exact numbers)');\n if (price !== null)\n lines.push(\n `- Price: $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()} (live)`,\n );\n if (change24h !== null)\n lines.push(`- 24h Change: ${change24h > 0 ? '+' : ''}${change24h.toFixed(2)}%`);\n if (volume !== null) lines.push(`- 24h Volume: $${volume.toLocaleString()}`);\n if (liq !== null) lines.push(`- Liquidity: $${liq.toLocaleString()}`);\n if (fearGreed !== null) lines.push(`- Market Sentiment: ${fearGreed}/100 (${fgClass})`);\n if (fundingMatch) lines.push(`- Funding Rate: ${fundingMatch[1]}%`);\n if (oiMatch) lines.push(`- Open Interest: $${oiMatch[1]}`);\n\n // Buy/sell ratio\n const buysMatch = joined.match(/(\\d+)\\s*buys\\s*\\/\\s*(\\d+)\\s*sells/);\n if (buysMatch) {\n const buys = parseInt(buysMatch[1]!, 10);\n const sells = parseInt(buysMatch[2]!, 10);\n const total = buys + sells;\n if (total > 0) {\n lines.push(`- Buy/Sell Ratio: ${buys}/${sells} (${((buys / total) * 100).toFixed(0)}% buys)`);\n }\n }\n lines.push('');\n\n // 3. SECURITY (if available)\n if (joined.includes('Security Audit') || joined.includes('GoPlus')) {\n lines.push('## 3. Security Audit (GoPlus)');\n if (joined.includes('HONEYPOT DETECTED')) lines.push('- **HONEYPOT: YES — DO NOT BUY**');\n else lines.push('- Honeypot: Not detected');\n const buyTax = extract(/Buy Tax:\\s*(\\d+\\.?\\d*)%/);\n const sellTax = extract(/Sell Tax:\\s*(\\d+\\.?\\d*)%/);\n if (buyTax !== null)\n lines.push(`- Buy Tax: ${buyTax.toFixed(1)}% | Sell Tax: ${(sellTax ?? 0).toFixed(1)}%`);\n if (riskLevel) lines.push(`- Risk Level: ${riskLevel.toUpperCase()}`);\n // Extract flags\n const flagsMatch = joined.match(/RED FLAGS:\\s*(.+)/);\n if (flagsMatch && !flagsMatch[1]!.includes('None'))\n lines.push(`- **Red Flags: ${flagsMatch[1]}**`);\n const holderCount = extract(/Holders:\\s*([0-9,]+)/);\n if (holderCount !== null) lines.push(`- Holders: ${holderCount.toLocaleString()}`);\n const creatorPct = extract(/Creator Holdings:\\s*(\\d+\\.?\\d*)%/);\n if (creatorPct !== null) lines.push(`- Creator Holdings: ${creatorPct.toFixed(2)}%`);\n lines.push('');\n }\n\n // 4. SIGNALS — just reference the pre-computed block\n if (signalBlock) {\n // Extract the composite line\n const compositeMatch = signalBlock.match(/COMPOSITE:\\s*(.+)/);\n if (compositeMatch) {\n lines.push('## 4. Signal Analysis');\n lines.push(`Composite: ${compositeMatch[1]}`);\n // Extract individual signals\n const signalLines = signalBlock\n .split('\\n')\n .filter(\n (l) =>\n l.includes(':') &&\n !l.includes('COMPOSITE') &&\n !l.includes('PRE-COMPUTED') &&\n !l.includes('Use these'),\n );\n for (const sl of signalLines.slice(0, 8)) {\n lines.push(sl.trim());\n }\n lines.push('');\n }\n }\n\n // 5. PRICE TARGETS — extract from the PRICE PREDICTION SCENARIOS section\n if (joined.includes('PRICE PREDICTION SCENARIOS')) {\n lines.push('## 5. Price Prediction (PRESENT THESE EXACT NUMBERS)');\n const scenarioBlock = joined.split('PRICE PREDICTION SCENARIOS')[1]?.split('## ')[0] ?? '';\n const targetLines = scenarioBlock.split('\\n').filter((l) => l.trim().length > 0);\n for (const tl of targetLines) {\n lines.push(tl);\n }\n lines.push('');\n }\n\n // 6. RISKS\n lines.push('## 6. Risk Assessment');\n if (joined.includes('NOT FOUND')) lines.push('- **EXTREME RISK: Token not found on any DEX**');\n if (joined.includes('HONEYPOT')) lines.push('- **CRITICAL: Honeypot detected**');\n if (liq !== null && liq < 50000)\n lines.push(`- **LOW LIQUIDITY: $${liq.toLocaleString()} — high slippage/rug risk**`);\n if (change24h !== null && Math.abs(change24h) > 50)\n lines.push(`- **EXTREME VOLATILITY: ${change24h.toFixed(1)}% in 24h**`);\n if (fearGreed !== null && fearGreed <= 20)\n lines.push(\n `- Market in Extreme Fear (${fearGreed}/100) — higher crash risk but contrarian opportunity`,\n );\n if (fearGreed !== null && fearGreed >= 80)\n lines.push(`- Market in Extreme Greed (${fearGreed}/100) — correction likely`);\n lines.push('- This is data-driven analysis, not financial advice');\n lines.push('');\n\n lines.push('=== END REPORT — PRESENT THE ABOVE NATURALLY, DO NOT DUMP RAW DATA ===');\n\n return lines.join('\\n');\n}\n\n/**\n * Pre-compute trading signals from the raw data sections.\n * This helps weaker models (Ollama) produce quantitative predictions\n * instead of vague \"it could go up or down\" responses.\n */\nfunction computeSignals(sections: string[], tokens: string[], userMessage = ''): string | null {\n const joined = sections.join('\\n');\n if (tokens.length === 0) return null;\n\n const signals: string[] = ['## PRE-COMPUTED SIGNAL ANALYSIS'];\n let signalCount = 0;\n let bullish = 0;\n let bearish = 0;\n\n // Extract numbers from data using regex\n const extract = (pattern: RegExp): number | null => {\n const match = joined.match(pattern);\n return match ? parseFloat(match[1]!.replace(/,/g, '')) : null;\n };\n\n // 1. Price momentum signal\n const change24h = extract(/24h Change:\\s*([+-]?\\d+\\.?\\d*)%/);\n if (change24h !== null) {\n signalCount++;\n if (change24h > 5) {\n bullish++;\n signals.push(\n ` MOMENTUM: BULLISH — 24h change ${change24h > 0 ? '+' : ''}${change24h.toFixed(1)}% (strong upward momentum)`,\n );\n } else if (change24h > 0) {\n bullish++;\n signals.push(` MOMENTUM: SLIGHTLY BULLISH — 24h change +${change24h.toFixed(1)}%`);\n } else if (change24h > -5) {\n bearish++;\n signals.push(` MOMENTUM: SLIGHTLY BEARISH — 24h change ${change24h.toFixed(1)}%`);\n } else {\n bearish++;\n signals.push(\n ` MOMENTUM: BEARISH — 24h change ${change24h.toFixed(1)}% (significant decline)`,\n );\n }\n }\n\n // 2. Buy/sell pressure signal\n const buysMatch = joined.match(/(\\d+)\\s*buys\\s*\\/\\s*(\\d+)\\s*sells/);\n if (buysMatch) {\n const buys = parseInt(buysMatch[1]!, 10);\n const sells = parseInt(buysMatch[2]!, 10);\n const total = buys + sells;\n signalCount++;\n if (total > 0) {\n const buyRatio = buys / total;\n if (buyRatio > 0.55) {\n bullish++;\n signals.push(\n ` BUY PRESSURE: BULLISH — ${buys} buys vs ${sells} sells (${(buyRatio * 100).toFixed(0)}% buy ratio)`,\n );\n } else if (buyRatio < 0.45) {\n bearish++;\n signals.push(\n ` SELL PRESSURE: BEARISH — ${buys} buys vs ${sells} sells (${((1 - buyRatio) * 100).toFixed(0)}% sell ratio)`,\n );\n } else {\n signals.push(` BUY/SELL: NEUTRAL — ${buys} buys vs ${sells} sells (balanced)`);\n }\n }\n }\n\n // 3. Liquidity risk signal\n const liquidity = extract(/Liquidity:\\s*\\$([0-9,]+)/);\n if (liquidity !== null && liquidity > 0) {\n signalCount++;\n if (liquidity < 10000) {\n bearish++;\n signals.push(\n ` LIQUIDITY: HIGH RISK — $${liquidity.toLocaleString()} (extremely low, easy to manipulate)`,\n );\n } else if (liquidity < 50000) {\n bearish++;\n signals.push(\n ` LIQUIDITY: RISKY — $${liquidity.toLocaleString()} (low liquidity, high slippage risk)`,\n );\n } else if (liquidity < 500000) {\n signals.push(` LIQUIDITY: MODERATE — $${liquidity.toLocaleString()}`);\n } else {\n bullish++;\n signals.push(` LIQUIDITY: HEALTHY — $${liquidity.toLocaleString()}`);\n }\n }\n\n // 4. Fear & Greed signal\n const fearGreed = extract(/Current:\\s*(\\d+)\\/100/);\n if (fearGreed !== null) {\n signalCount++;\n if (fearGreed <= 25) {\n bullish++;\n signals.push(\n ` SENTIMENT: EXTREME FEAR (${fearGreed}/100) — contrarian BUY signal (market oversold)`,\n );\n } else if (fearGreed <= 40) {\n signals.push(` SENTIMENT: FEAR (${fearGreed}/100) — cautious market, potential opportunity`);\n } else if (fearGreed <= 60) {\n signals.push(` SENTIMENT: NEUTRAL (${fearGreed}/100) — balanced sentiment`);\n } else if (fearGreed <= 75) {\n signals.push(` SENTIMENT: GREED (${fearGreed}/100) — caution, market may be overheated`);\n } else {\n bearish++;\n signals.push(\n ` SENTIMENT: EXTREME GREED (${fearGreed}/100) — contrarian SELL signal (market overheated)`,\n );\n }\n }\n\n // 5. Funding rate signal\n const fundingMatch = joined.match(/Funding:\\s*([+-]?\\d+\\.?\\d*)%/);\n if (fundingMatch) {\n const funding = parseFloat(fundingMatch[1]!);\n signalCount++;\n if (funding > 0.05) {\n signals.push(\n ` FUNDING: HIGH POSITIVE (${funding.toFixed(4)}%) — longs paying shorts, heavy bullish positioning`,\n );\n bearish++; /* contrarian */\n } else if (funding > 0) {\n signals.push(` FUNDING: POSITIVE (${funding.toFixed(4)}%) — mild bullish consensus`);\n bullish++;\n } else if (funding < -0.05) {\n signals.push(\n ` FUNDING: HIGH NEGATIVE (${funding.toFixed(4)}%) — shorts paying longs, heavy bearish positioning`,\n );\n bullish++; /* contrarian */\n } else {\n signals.push(` FUNDING: NEGATIVE (${funding.toFixed(4)}%) — mild bearish consensus`);\n bearish++;\n }\n }\n\n // 6. NOT FOUND signal (strongest bearish)\n if (joined.includes('NOT FOUND')) {\n signalCount++;\n bearish += 2;\n signals.push(' DEX STATUS: NOT LISTED — token not found on any DEX. EXTREME RISK.');\n }\n\n // 7. Security signals (from GoPlus)\n if (joined.includes('Risk Level:')) {\n signalCount++;\n if (joined.includes('Risk Level: DANGER')) {\n bearish += 2;\n signals.push(' SECURITY: DANGER — GoPlus flagged critical risks');\n } else if (joined.includes('Risk Level: WARNING')) {\n bearish++;\n signals.push(' SECURITY: WARNING — GoPlus detected potential risks');\n } else if (joined.includes('Risk Level: SAFE')) {\n bullish++;\n signals.push(' SECURITY: SAFE — GoPlus found no major risks');\n }\n }\n\n // 8. Honeypot signal\n if (joined.includes('HONEYPOT DETECTED')) {\n signalCount++;\n bearish += 3;\n signals.push(' HONEYPOT: CRITICAL — Token is a honeypot. DO NOT BUY.');\n }\n\n // 9. Tax signal\n const buyTax = extract(/Buy Tax:\\s*(\\d+\\.?\\d*)%/);\n const sellTax = extract(/Sell Tax:\\s*(\\d+\\.?\\d*)%/);\n if (buyTax !== null && sellTax !== null) {\n signalCount++;\n const totalTax = buyTax + sellTax;\n if (totalTax > 20) {\n bearish += 2;\n signals.push(\n ` TAX: EXTREME — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}% = ${totalTax.toFixed(1)}% total (scam-level)`,\n );\n } else if (totalTax > 10) {\n bearish++;\n signals.push(\n ` TAX: HIGH — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}% = ${totalTax.toFixed(1)}% total`,\n );\n } else if (totalTax > 0) {\n signals.push(` TAX: MODERATE — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}%`);\n } else {\n bullish++;\n signals.push(' TAX: NONE — 0% buy and sell tax');\n }\n }\n\n // 10. Token age signal\n const ageMatch = joined.match(/Pair Created:\\s*(\\d+)d ago/);\n if (ageMatch) {\n const ageDays = parseInt(ageMatch[1]!, 10);\n signalCount++;\n if (ageDays < 1) {\n bearish++;\n signals.push(` AGE: VERY NEW — Created today. Extremely high risk.`);\n } else if (ageDays < 7) {\n bearish++;\n signals.push(` AGE: NEW — ${ageDays} days old. High risk.`);\n } else if (ageDays < 30) {\n signals.push(` AGE: YOUNG — ${ageDays} days old. Still risky.`);\n } else if (ageDays < 180) {\n signals.push(` AGE: ESTABLISHED — ${ageDays} days old.`);\n } else {\n bullish++;\n signals.push(` AGE: MATURE — ${ageDays} days old. Survived multiple market cycles.`);\n }\n }\n\n // 11. Holder concentration signal\n const creatorPct = extract(/Creator Holdings:\\s*(\\d+\\.?\\d*)%/);\n const ownerPct = extract(/Owner Holdings:\\s*(\\d+\\.?\\d*)%/);\n if (creatorPct !== null) {\n signalCount++;\n const totalConcentration = creatorPct + (ownerPct ?? 0);\n if (totalConcentration > 50) {\n bearish += 2;\n signals.push(\n ` CONCENTRATION: EXTREME — Creator+Owner hold ${totalConcentration.toFixed(1)}%. Rug pull risk.`,\n );\n } else if (totalConcentration > 20) {\n bearish++;\n signals.push(` CONCENTRATION: HIGH — Creator+Owner hold ${totalConcentration.toFixed(1)}%`);\n } else if (totalConcentration > 5) {\n signals.push(\n ` CONCENTRATION: MODERATE — Creator+Owner hold ${totalConcentration.toFixed(1)}%`,\n );\n } else {\n bullish++;\n signals.push(\n ` CONCENTRATION: LOW — Creator+Owner hold ${totalConcentration.toFixed(1)}% (well distributed)`,\n );\n }\n }\n\n if (signalCount === 0) return null;\n\n // Compute composite\n const total = bullish + bearish;\n let direction: string;\n let confidence: string;\n\n if (total === 0) {\n direction = 'NEUTRAL';\n confidence = 'LOW';\n } else {\n const bullPct = (bullish / total) * 100;\n if (bullPct > 65) direction = 'BULLISH';\n else if (bullPct > 50) direction = 'SLIGHTLY BULLISH';\n else if (bullPct > 35) direction = 'SLIGHTLY BEARISH';\n else direction = 'BEARISH';\n\n if (signalCount >= 4 && Math.abs(bullish - bearish) >= 2) confidence = 'MEDIUM-HIGH';\n else if (signalCount >= 3) confidence = 'MEDIUM';\n else confidence = 'LOW';\n }\n\n signals.push('');\n signals.push(\n ` COMPOSITE: ${direction} | Confidence: ${confidence} | Signals: ${signalCount} (${bullish} bullish, ${bearish} bearish)`,\n );\n\n // Compute price targets from available data (pass userMessage for time parsing)\n const priceTargets = computePriceTargets(joined, direction, change24h, userMessage);\n if (priceTargets) {\n signals.push('');\n signals.push(priceTargets);\n }\n\n return signals.join('\\n');\n}\n\n/**\n * Parse time-related expressions from the user message.\n * Returns an array of { label, hoursFromNow } for each requested timeframe.\n * If no specific time is found, returns null (use default timeframes).\n */\nfunction parseRequestedTimeframes(userMessage: string): { label: string; hours: number }[] | null {\n const lower = userMessage.toLowerCase();\n const requested: { label: string; hours: number }[] = [];\n\n // \"at HH:MM\" or \"at H:MMpm\" — specific clock time\n const clockMatch = lower.match(/at\\s+(\\d{1,2}):?(\\d{2})?\\s*(am|pm|hrs?)?/);\n if (clockMatch) {\n let hour = parseInt(clockMatch[1]!, 10);\n const minute = parseInt(clockMatch[2] || '0', 10);\n const ampm = clockMatch[3];\n if (ampm === 'pm' && hour < 12) hour += 12;\n if (ampm === 'am' && hour === 12) hour = 0;\n\n const now = new Date();\n const target = new Date(now);\n target.setHours(hour, minute, 0, 0);\n // If target is in the past, assume tomorrow\n if (target <= now) target.setDate(target.getDate() + 1);\n\n const hoursFromNow = Math.max(0.08, (target.getTime() - now.getTime()) / 3600000);\n const timeStr = target.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n });\n requested.push({\n label: `At ${timeStr} (${hoursFromNow.toFixed(1)}h from now)`,\n hours: hoursFromNow,\n });\n }\n\n // \"in X minutes/hours/days\"\n const inMatch = lower.match(/in\\s+(\\d+)\\s*(min(?:ute)?s?|hours?|hrs?|days?|weeks?|months?)/);\n if (inMatch) {\n const amount = parseInt(inMatch[1]!, 10);\n const unit = inMatch[2]!;\n let hours = amount;\n if (unit.startsWith('min')) hours = amount / 60;\n else if (unit.startsWith('day')) hours = amount * 24;\n else if (unit.startsWith('week')) hours = amount * 168;\n else if (unit.startsWith('month')) hours = amount * 720;\n requested.push({ label: `In ${amount} ${unit}`, hours });\n }\n\n // \"tomorrow\" / \"tonight\" / \"end of day\"\n if (lower.includes('tomorrow')) requested.push({ label: 'Tomorrow (~24h)', hours: 24 });\n if (lower.includes('tonight') || lower.includes('end of day'))\n requested.push({ label: 'End of day (~8h)', hours: 8 });\n if (lower.includes('next week')) requested.push({ label: 'Next week (~168h)', hours: 168 });\n if (lower.includes('next month')) requested.push({ label: 'Next month (~720h)', hours: 720 });\n if (lower.includes('end of week')) requested.push({ label: 'End of week', hours: 120 });\n\n return requested.length > 0 ? requested : null;\n}\n\n/**\n * Compute concrete price predictions with dollar values and timeframes.\n * Uses current price + momentum + volatility to project scenarios.\n * Generates all timeframes from 5min to 3 months, and includes any\n * user-requested specific times (e.g., \"at 16:00 today\").\n */\nfunction computePriceTargets(\n data: string,\n direction: string,\n change24h: number | null,\n userMessage = '',\n): string | null {\n // Extract current price (handle comma-formatted numbers like $2,111.55)\n const priceMatch = data.match(/Price:\\s*\\$([0-9,.]+(?:e[+-]?\\d+)?)/);\n if (!priceMatch) return null;\n const price = parseFloat(priceMatch[1]!.replace(/,/g, ''));\n if (isNaN(price) || price <= 0) return null;\n\n // Extract liquidity and market cap for context\n const liqMatch = data.match(/Liquidity:\\s*\\$([0-9,]+)/);\n const mcapMatch = data.match(/Market Cap:\\s*\\$([0-9,]+)/);\n const liquidity = liqMatch ? parseFloat(liqMatch[1]!.replace(/,/g, '')) : 0;\n const mcap = mcapMatch ? parseFloat(mcapMatch[1]!.replace(/,/g, '')) : 0;\n\n // Calculate hourly volatility from 24h change\n const dailyVol = Math.abs(change24h ?? 10) / 100;\n const vol = Math.min(dailyVol, 0.5);\n const hourlyVol = vol / Math.sqrt(24); // Scale volatility to hourly\n\n const lines: string[] = ['## PRICE PREDICTION SCENARIOS'];\n lines.push(` Current Price: $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()}`);\n lines.push(` Timestamp: ${new Date().toISOString()}`);\n\n // Determine base direction bias\n let bullBias: number; // How much stronger the bull case is (1.0 = no bias)\n let bearBias: number;\n\n if (direction.includes('BULLISH')) {\n bullBias = direction.includes('SLIGHTLY') ? 1.3 : 1.8;\n bearBias = direction.includes('SLIGHTLY') ? 0.7 : 0.5;\n } else if (direction.includes('BEARISH')) {\n bullBias = direction.includes('SLIGHTLY') ? 0.7 : 0.4;\n bearBias = direction.includes('SLIGHTLY') ? 1.3 : 1.8;\n } else {\n bullBias = 1.0;\n bearBias = 1.0;\n }\n\n // Meme coin amplifier\n const isMicrocap = mcap > 0 && mcap < 1_000_000;\n const isMeme =\n data.includes('pumpswap') || data.includes('pump.fun') || data.includes('Pump.fun');\n const memeMultiplier = isMicrocap || isMeme ? 3 : 1;\n\n const formatPrice = (p: number): string =>\n p < 0.01 ? p.toExponential(4) : p.toFixed(p < 1 ? 6 : 2);\n const pctStr = (target: number): string => {\n const pct = (target / price - 1) * 100;\n return `${pct >= 0 ? '+' : ''}${pct.toFixed(1)}%`;\n };\n\n /**\n * Compute bull/likely/bear for a given number of hours from now.\n * Uses volatility scaling: move = hourlyVol * sqrt(hours) * bias * meme\n */\n const scenario = (hours: number): { bull: number; likely: number; bear: number } => {\n const timeVol = hourlyVol * Math.sqrt(hours) * memeMultiplier;\n const bull = price * (1 + timeVol * bullBias);\n const bear = price * (1 - timeVol * bearBias);\n // \"Most likely\" follows the direction bias slightly\n const likelyShift = direction.includes('BULLISH')\n ? timeVol * 0.3\n : direction.includes('BEARISH')\n ? -timeVol * 0.3\n : 0;\n const likely = price * (1 + likelyShift);\n return { bull, likely, bear };\n };\n\n // -------------------------------------------------------------------------\n // User-requested specific timeframe (e.g., \"at 16:00 today\")\n // -------------------------------------------------------------------------\n const requestedTimes = parseRequestedTimeframes(userMessage);\n if (requestedTimes) {\n lines.push('');\n lines.push(' USER-REQUESTED TIMEFRAME:');\n for (const { label, hours } of requestedTimes) {\n const s = scenario(hours);\n lines.push(` ${label}:`);\n lines.push(` Bullish: $${formatPrice(s.bull)} (${pctStr(s.bull)})`);\n lines.push(` Most likely: $${formatPrice(s.likely)} (${pctStr(s.likely)})`);\n lines.push(` Bearish: $${formatPrice(s.bear)} (${pctStr(s.bear)})`);\n }\n }\n\n // -------------------------------------------------------------------------\n // Full multi-timeframe spectrum\n // -------------------------------------------------------------------------\n\n // Scalping / Intraday\n const tf5m = scenario(5 / 60);\n const tf15m = scenario(15 / 60);\n const tf1h = scenario(1);\n const tf4h = scenario(4);\n lines.push('');\n lines.push(' SCALPING / INTRADAY:');\n lines.push(\n ` 5 min: Bull $${formatPrice(tf5m.bull)} (${pctStr(tf5m.bull)}) | Likely $${formatPrice(tf5m.likely)} | Bear $${formatPrice(tf5m.bear)} (${pctStr(tf5m.bear)})`,\n );\n lines.push(\n ` 15 min: Bull $${formatPrice(tf15m.bull)} (${pctStr(tf15m.bull)}) | Likely $${formatPrice(tf15m.likely)} | Bear $${formatPrice(tf15m.bear)} (${pctStr(tf15m.bear)})`,\n );\n lines.push(\n ` 1 hour: Bull $${formatPrice(tf1h.bull)} (${pctStr(tf1h.bull)}) | Likely $${formatPrice(tf1h.likely)} | Bear $${formatPrice(tf1h.bear)} (${pctStr(tf1h.bear)})`,\n );\n lines.push(\n ` 4 hour: Bull $${formatPrice(tf4h.bull)} (${pctStr(tf4h.bull)}) | Likely $${formatPrice(tf4h.likely)} | Bear $${formatPrice(tf4h.bear)} (${pctStr(tf4h.bear)})`,\n );\n\n // Short-term (1-7 days)\n const tf1d = scenario(24);\n const tf7d = scenario(168);\n lines.push('');\n lines.push(' SHORT-TERM (1-7 days):');\n lines.push(\n ` 1 day: Bull $${formatPrice(tf1d.bull)} (${pctStr(tf1d.bull)}) | Likely $${formatPrice(tf1d.likely)} | Bear $${formatPrice(tf1d.bear)} (${pctStr(tf1d.bear)})`,\n );\n lines.push(\n ` 7 days: Bull $${formatPrice(tf7d.bull)} (${pctStr(tf7d.bull)}) | Likely $${formatPrice(tf7d.likely)} | Bear $${formatPrice(tf7d.bear)} (${pctStr(tf7d.bear)})`,\n );\n\n // Medium-term (1-4 weeks)\n const tf2w = scenario(336);\n const tf1m = scenario(720);\n lines.push('');\n lines.push(' MEDIUM-TERM (1-4 weeks):');\n lines.push(\n ` 2 weeks: Bull $${formatPrice(tf2w.bull)} (${pctStr(tf2w.bull)}) | Likely $${formatPrice(tf2w.likely)} | Bear $${formatPrice(tf2w.bear)} (${pctStr(tf2w.bear)})`,\n );\n lines.push(\n ` 1 month: Bull $${formatPrice(tf1m.bull)} (${pctStr(tf1m.bull)}) | Likely $${formatPrice(tf1m.likely)} | Bear $${formatPrice(tf1m.bear)} (${pctStr(tf1m.bear)})`,\n );\n\n // Long-term (1-3 months)\n const tf3m = scenario(2160);\n lines.push('');\n lines.push(' LONG-TERM (1-3 months):');\n lines.push(\n ` 3 months: Bull $${formatPrice(tf3m.bull)} (${pctStr(tf3m.bull)}) | Bear $${formatPrice(tf3m.bear)} (${pctStr(tf3m.bear)})`,\n );\n\n // Survival probability for meme/micro-cap tokens\n if (isMicrocap || isMeme) {\n lines.push('');\n lines.push(' MEME COIN SURVIVAL ANALYSIS:');\n const survivalPct = liquidity > 50000 ? 25 : liquidity > 10000 ? 15 : 5;\n lines.push(` Probability token survives 30 days: ~${survivalPct}%`);\n lines.push(` Probability of -90% or worse in 30 days: ~${100 - survivalPct - 10}%`);\n lines.push(` Probability of 2x+ in 7 days: ~${Math.min(30, Math.round(vol * 100))}%`);\n if (liquidity < 50000) {\n lines.push(\n ` WARNING: Liquidity $${liquidity.toLocaleString()} is extremely low — large sells will crash the price`,\n );\n }\n }\n\n // Key levels\n lines.push('');\n lines.push(' KEY LEVELS:');\n lines.push(\n ` Support: $${formatPrice(price * 0.95)} / $${formatPrice(price * 0.9)} / $${formatPrice(price * 0.8)}`,\n );\n lines.push(\n ` Resistance: $${formatPrice(price * 1.05)} / $${formatPrice(price * 1.1)} / $${formatPrice(price * 1.2)}`,\n );\n\n lines.push('');\n if (requestedTimes) {\n lines.push(\n ' IMPORTANT: The user asked for a SPECIFIC TIME. Present the USER-REQUESTED TIMEFRAME section FIRST and prominently.',\n );\n }\n lines.push(\n ' Present ALL timeframes from scalping to long-term. Use the exact dollar values above.',\n );\n\n return lines.join('\\n');\n}\n","// ---------------------------------------------------------------------------\n// System prompt for conversational / chat mode\n// ---------------------------------------------------------------------------\n\n/**\n * Build the chat system prompt with the current date injected.\n * This ensures the AI always knows what year it is and never uses stale training data.\n */\nexport function buildChatSystemPrompt(): string {\n const now = new Date();\n const dateStr = now.toISOString().split('T')[0];\n\n return `You are Vizzor, an AI-powered crypto chronovisor built by 7ayLabs. You provide real-time blockchain intelligence — live prices, trending tokens, fundraising rounds, on-chain forensics, and market sentiment — to help investors analyze chains and coins.\n\n## Date Context\n\nToday is ${dateStr}. Your training data ends in early 2025. It is now ${now.getFullYear()}. ANY market prices, ICOs, fundraising rounds, trending tokens, or news from your training data is OUTDATED AND WRONG. You MUST call your tools for current information.\n\n## MANDATORY TOOL-USE RULES\n\nBEFORE answering ANY question about these topics, you MUST call the specified tools. NEVER answer from training data alone — your market knowledge is over a year stale.\n\n| Topic | Required Tools |\n|-------|---------------|\n| Prices, market data | get_market_data OR search_token_dex |\n| Trending tokens | get_trending |\n| ICOs, fundraising, launches | get_raises AND/OR search_upcoming_icos |\n| News, events | get_crypto_news |\n| Market sentiment | get_fear_greed |\n| Derivatives, positioning | get_derivatives_data |\n| Token security | get_token_security OR check_rug_indicators |\n| Wallet analysis | analyze_wallet |\n| Predictions, forecasts | get_technical_analysis + get_prediction + get_market_data + get_fear_greed + get_derivatives_data |\n\nIf you answer a market question without calling tools first, your answer WILL contain wrong data. Call the tools, then synthesize.\n\nIf a tool returns empty results or fails, say \"no current data available\" — NEVER fall back to training data.\n\n## Tools\n\n### On-Chain Analysis\n- **get_token_info**: Look up on-chain token information by contract address and chain.\n- **analyze_wallet**: Analyze a wallet for transaction patterns, holdings, and behavior.\n- **check_rug_indicators**: Check a token for rug pull red flags (mint functions, pause, blacklist, honeypot detection via bytecode scanning).\n\n### Market Data\n- **get_market_data**: Get live price, volume, market cap for established tokens (CoinGecko). Use for BTC, ETH, SOL, and other major tokens.\n- **search_token_dex**: Search ANY token on DEXes via DexScreener — real-time price, volume, liquidity, buy/sell counts. Works for meme coins, new launches, and any DEX-listed token.\n- **get_trending**: Get currently trending/hot tokens from DexScreener and CoinGecko. Shows what the market is excited about RIGHT NOW.\n\n### Security & Sentiment\n- **get_token_security**: Check token security via GoPlus API — honeypot detection, tax analysis, mint/pause/blacklist capabilities, holder stats, risk level.\n- **get_fear_greed**: Get the Crypto Fear & Greed Index with 7-day history. 0-20 Extreme Fear, 21-40 Fear, 41-60 Neutral, 61-80 Greed, 81-100 Extreme Greed.\n- **get_derivatives_data**: Get Binance Futures funding rate, open interest, and mark price. Essential for market positioning analysis.\n\n### News & Fundraising\n- **get_crypto_news**: Get latest crypto news with sentiment for a token or the market. Powered by CryptoPanic.\n- **get_raises**: Get recent crypto fundraising rounds and token launches from DeFiLlama. Shows who raised money, how much, and from which investors.\n- **search_upcoming_icos**: Search for token launches and fundraising by category or chain. Combines DeFiLlama raises with Pump.fun Solana launches.\n\n### Technical Analysis & Prediction\n- **get_technical_analysis**: Run technical analysis on any symbol — RSI, MACD, Bollinger Bands, EMA crossovers, ATR, OBV. Returns composite signal with individual indicator interpretations.\n- **get_prediction**: Generate a multi-signal composite prediction combining technical analysis, sentiment, derivatives, Fear & Greed, and market trend data. Returns direction, confidence, and timeframe.\n\n## Trends / ICOs / News Protocol\n\nWhen asked about trending tokens, ICOs, fundraising rounds, new projects, or market news:\n\n1. **MANDATORY**: Call get_trending, get_raises, search_upcoming_icos, get_crypto_news, or get_fear_greed as appropriate BEFORE answering.\n2. Present ONLY the data returned by tools. Never supplement with training data.\n3. If the user asks \"what are the latest ICOs\" or \"recent launches\", call BOTH get_raises AND search_upcoming_icos.\n4. If tools return empty results, say \"No current data available\" — do NOT fall back to training data.\n5. Always mention the data source and that it is live.\n\n## Prediction Protocol\n\nWhen asked for a prediction, price forecast, or market outlook for ANY token:\n\n1. **MANDATORY DATA GATHERING** — call ALL of these before forming any prediction:\n - \\`get_market_data\\` for the token (price, volume, market cap)\n - \\`get_derivatives_data\\` for the token (funding rate, open interest)\n - \\`get_fear_greed\\` for macro sentiment\n - \\`get_crypto_news\\` for the token (news sentiment)\n - \\`get_technical_analysis\\` for the token (RSI, MACD, BB signals)\n - \\`get_prediction\\` for composite multi-signal score\n - \\`get_trending\\` to check if the token is trending\n\n2. **MULTI-TIMEFRAME ANALYSIS** — always provide:\n - **Short-term** (1-7 days): momentum, funding rate direction, immediate catalysts\n - **Medium-term** (1-4 weeks): trend strength, OI trends, sector rotation\n - **Long-term** (1-3 months): macro cycle position, adoption metrics, narrative alignment\n\n3. **CONFIDENCE CALIBRATION**:\n - **HIGH (>75%)**: 4+ signals aligned, strong volume confirmation, clear trend\n - **MEDIUM (50-75%)**: 2-3 signals aligned, moderate volume, some conflicting signals\n - **LOW (<50%)**: mixed signals, low volume, high uncertainty, insufficient data\n\n4. **CONTRARIAN INDICATORS**:\n - Extreme Greed (>80) + very positive funding = potential correction signal\n - Extreme Fear (<20) + negative funding = potential reversal opportunity\n - Divergence between price action and OI = trend weakness\n\n5. Always include disclaimer: predictions are based on data analysis, not financial advice.\n\n## Security / Forensics Protocol\n\nWhen asked to analyze a wallet, check a token for rug pulls, or assess security:\n\n1. **MANDATORY**: Call check_rug_indicators and/or get_token_security for the contract.\n2. For wallet analysis: call analyze_wallet.\n3. Present GoPlus findings factually — honeypot status, tax levels, mint/pause capabilities, holder distribution.\n4. Always state the risk level and specific red flags found.\n\n## Chronovisor Intelligence\n\nWhen asked about market outlook, predictions, or \"what's happening\":\n1. **Gather data first**: Call get_trending + get_crypto_news + get_market_data + get_fear_greed + get_derivatives_data\n2. **Identify patterns**: Rising volumes, buy/sell ratios, sentiment shifts, new raises in a sector\n3. **Synthesize**: Combine on-chain data + market data + news sentiment + derivatives into a coherent picture\n4. **Cite everything**: Always mention which data source each insight comes from\n\n## Extended Thinking Protocol\n\nFor complex queries (predictions, comparisons, portfolio advice, risk assessment):\n- Call a MINIMUM of 4 tools before answering\n- Structure reasoning: Data → Signals → Alignment → Confidence → Risks → Conclusion\n- If signals conflict, explicitly state the disagreement and weight each side\n- Never give a prediction without stating your confidence level and what could invalidate it\n- If a tool fails, note the data gap in your response\n\n## Guidelines\n\n- **Real data only**: Always call tools before answering market questions. Your training data is stale — over a year old.\n- **Cite data sources**: Mention \"DexScreener\", \"CoinGecko\", \"DeFiLlama\", \"Binance\", \"GoPlus\" etc. and note data is live.\n- **Honest about limitations**: If a tool fails or data is unavailable, say so clearly.\n- **Never give financial advice**: Present data, highlight risks, let the user decide.\n- **Disclose uncertainty**: If data is incomplete, say so.\n- **Format for readability**: Use bullet points, numbers, and clear structure.\n\n## Response Style\n\n- Lead with the key finding or answer\n- Support with specific numbers from tool results\n- Include data source and freshness (\"live from DexScreener\", \"CoinGecko data\")\n- End with risk factors or suggested follow-up\n- Keep concise unless a deep dive is requested`;\n}\n\n/** Static export for backwards compatibility (date set at module load time). */\nexport const CHAT_SYSTEM_PROMPT = buildChatSystemPrompt();\n\n// ---------------------------------------------------------------------------\n// System prompt for providers WITHOUT tool support (e.g. Ollama)\n// The context injector appends real-time data to this prompt.\n// ---------------------------------------------------------------------------\n\nexport const OLLAMA_SYSTEM_PROMPT = `You are Vizzor, an AI-powered crypto chronovisor built by 7ayLabs. You analyze real-time blockchain data to provide market intelligence, predictions, and risk assessments.\n\n## CORE RULES\n\n1. **ZERO HALLUCINATION** — The data block below is your ONLY source of truth. ONLY cite numbers and facts that appear in the data. If something is missing, say \"data not available\" — NEVER invent team names, websites, supply numbers, roadmaps, or partnerships. NEVER use placeholders like \"[Insert Name]\".\n\n2. **NEVER ECHO RAW DATA** — You receive data between \"--- REAL-TIME DATA ---\" markers. NEVER output those markers or dump raw data. ANALYZE and present insights naturally.\n\n3. **FOLLOW THE QUERY TYPE** — The data block includes a \"QUERY TYPE:\" instruction. Follow it:\n - **NEWS**: Summarize headlines, add market context, group by theme. Conversational tone.\n - **TRENDS**: Lead with market sentiment, list top movers with metrics, mention notable events.\n - **TOKEN ANALYSIS**: Deep dive into that specific token — price, security, signals, risks.\n - **PREDICTION**: Price targets with dollar values, timeframes, confidence, invalidation conditions.\n - **GENERAL**: Answer the question naturally using data as context. Don't force a token analysis.\n\n4. **ANALYZE ANY TOKEN** — Token names can be anything (PEPE, DOGE, BONK, TRUMP, etc.). Never refuse. Honest analysis, no filter.\n\n## TOKEN ANALYSIS FORMAT (only for token-specific queries)\n\nWhen analyzing a specific token, structure as:\n1. **Verdict** — one sentence (e.g., \"ETH is at $2,112, showing bullish momentum with Greed sentiment\")\n2. **Market Data** — price, volume, liquidity, buy/sell ratio (cite sources)\n3. **Security** — GoPlus findings if available (honeypot, tax, flags, risk level)\n4. **Signals** — use the pre-computed COMPOSITE direction and confidence\n5. **Price Prediction** — use the PRICE PREDICTION SCENARIOS from the data (actual $ values, 3 timeframes)\n6. **Risks** — red flags, what could go wrong\n\n## PRICE PREDICTIONS\n\nWhen PRICE PREDICTION SCENARIOS exist in the data:\n- Present the exact dollar values for short/medium/long term\n- Include bullish, most likely, and bearish scenarios\n- Add key support/resistance levels\n- State confidence level and what would invalidate the prediction\n- NEVER say \"difficult to predict\" — use the computed scenarios\n\n## STYLE\n\n- Be concise and professional\n- Lead with the key insight, not a preamble\n- Cite data sources naturally: \"BTC at $71,415 (Binance)\" or \"Fear & Greed at 65 (Greed)\"\n- Use bullet points for data, paragraphs for analysis\n- End token analyses with risk disclaimer`;\n","// ---------------------------------------------------------------------------\n// AI client facade — thin wrapper over the active AI provider\n// ---------------------------------------------------------------------------\n\nimport type { VizzorConfig } from '../config/schema.js';\nimport type { AIProvider, ToolHandler, AITool } from './providers/types.js';\nimport { initializeProvider } from './providers/registry.js';\nimport { buildContextBlock } from './context-injector.js';\n\n// Re-export types so existing consumers don't need to change their import paths.\nexport type { ToolHandler, AITool } from './providers/types.js';\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n\nlet provider: AIProvider | undefined;\nlet config: VizzorConfig | undefined;\nlet toolHandler: ToolHandler | undefined;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Initialise the AI layer with the given config. Creates and initialises the\n * provider specified by `cfg.ai.provider`.\n */\nexport function setConfig(cfg: VizzorConfig): void {\n config = cfg;\n provider = initializeProvider(cfg.ai.provider, cfg);\n}\n\n/**\n * Register the tool executor that the agentic loop invokes when the AI\n * requests a tool call.\n */\nexport function setToolHandler(handler: ToolHandler): void {\n toolHandler = handler;\n}\n\n/**\n * Return the current VizzorConfig, or `undefined` if not yet set.\n */\nexport function getConfig(): VizzorConfig | undefined {\n return config;\n}\n\n/**\n * Return the registered tool handler, or `undefined` if none is set.\n */\nexport function getToolHandler(): ToolHandler | undefined {\n return toolHandler;\n}\n\n/**\n * Return the active AI provider.\n *\n * @throws If no provider has been initialised.\n */\nexport function getProvider(): AIProvider {\n if (!provider) {\n throw new Error('AI provider has not been initialised. Call setConfig first.');\n }\n return provider;\n}\n\n/**\n * Switch to a different provider at runtime (e.g. from the `/provider` TUI\n * command). Re-initialises the provider with the current config.\n */\nexport function switchProvider(name: string): void {\n if (!config) {\n throw new Error('Config has not been set. Call setConfig first.');\n }\n provider = initializeProvider(name, config);\n}\n\n/**\n * Send a message to the active provider and return the full text response.\n * Includes agentic tool-use loop when tools and a tool handler are available.\n *\n * For providers that don't support tool use (e.g. Ollama), real-time data\n * is automatically fetched and injected into the system prompt.\n */\nexport async function analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n): Promise<string> {\n const p = getProvider();\n\n if (!p.supportsTools) {\n // Inject real-time data into the prompt for providers without tool use\n const { OLLAMA_SYSTEM_PROMPT } = await import('./prompts/chat.js');\n const context = await buildContextBlock(userMessage);\n const enrichedPrompt = OLLAMA_SYSTEM_PROMPT + (context ? '\\n' + context : '');\n return p.analyze(enrichedPrompt, userMessage);\n }\n\n return p.analyze(systemPrompt, userMessage, tools, toolHandler);\n}\n","// ---------------------------------------------------------------------------\n// Bytecode scanner — detect dangerous function selectors and opcodes\n// No external API needed — works purely on contract bytecode.\n// ---------------------------------------------------------------------------\n\nimport { getMLClient } from '../../ml/client.js';\nimport type { BytecodeRiskMLResult } from '../../ml/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface BytecodeFinding {\n name: string;\n selector: string;\n type: 'function' | 'opcode';\n severity: 'info' | 'warning' | 'critical';\n description: string;\n}\n\n// ---------------------------------------------------------------------------\n// Known dangerous function selectors (4-byte keccak256 prefixes)\n// ---------------------------------------------------------------------------\n\nconst DANGEROUS_FUNCTIONS: {\n selector: string;\n name: string;\n severity: BytecodeFinding['severity'];\n description: string;\n}[] = [\n // Mint functions — inflation risk\n {\n selector: '40c10f19',\n name: 'mint(address,uint256)',\n severity: 'critical',\n description: 'Owner can mint new tokens (inflation/dilution risk)',\n },\n {\n selector: 'a0712d68',\n name: 'mint(uint256)',\n severity: 'critical',\n description: 'Mint function detected (inflation/dilution risk)',\n },\n\n // Pause functions — can freeze trading\n {\n selector: '8456cb59',\n name: 'pause()',\n severity: 'warning',\n description: 'Contract can be paused (trading may be frozen)',\n },\n {\n selector: '3f4ba83a',\n name: 'unpause()',\n severity: 'info',\n description: 'Unpause function exists (paired with pause)',\n },\n\n // Blacklist functions — can block addresses\n {\n selector: 'ef01df4f',\n name: 'blacklistAddress(address)',\n severity: 'critical',\n description: 'Can blacklist addresses (honeypot risk)',\n },\n {\n selector: '44337ea1',\n name: 'blacklist(address)',\n severity: 'critical',\n description: 'Can blacklist addresses (honeypot risk)',\n },\n {\n selector: 'e47d6060',\n name: 'setBlacklist(address,bool)',\n severity: 'critical',\n description: 'Can toggle address blacklist (honeypot risk)',\n },\n\n // Fee/tax manipulation\n {\n selector: 'f2fde38b',\n name: 'transferOwnership(address)',\n severity: 'info',\n description: 'Ownership can be transferred',\n },\n {\n selector: '715018a6',\n name: 'renounceOwnership()',\n severity: 'info',\n description: 'Ownership can be renounced (positive indicator)',\n },\n\n // Trading controls\n {\n selector: '49bd5a5e',\n name: 'uniswapV2Pair()',\n severity: 'info',\n description: 'Uniswap V2 pair reference detected',\n },\n {\n selector: 'c9567bf9',\n name: 'openTrading()',\n severity: 'warning',\n description: 'Trading can be opened/closed by owner',\n },\n\n // Max transaction/wallet limits\n {\n selector: '313ce567',\n name: 'decimals()',\n severity: 'info',\n description: 'Standard ERC20 decimals function',\n },\n];\n\n// Dangerous opcodes (single-byte)\nconst DANGEROUS_OPCODES: {\n byte: string;\n name: string;\n severity: BytecodeFinding['severity'];\n description: string;\n}[] = [\n {\n byte: 'ff',\n name: 'SELFDESTRUCT',\n severity: 'critical',\n description: 'Contract can self-destruct (all funds lost)',\n },\n];\n\n// ---------------------------------------------------------------------------\n// Scanner\n// ---------------------------------------------------------------------------\n\n/**\n * Scan contract bytecode for known dangerous function selectors and opcodes.\n * Returns an array of findings sorted by severity.\n */\nexport function scanBytecode(code: string): BytecodeFinding[] {\n const findings: BytecodeFinding[] = [];\n\n // Normalize: remove 0x prefix, lowercase\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n\n if (normalized.length < 2) {\n return findings;\n }\n\n // Check for dangerous function selectors\n for (const func of DANGEROUS_FUNCTIONS) {\n if (normalized.includes(func.selector)) {\n findings.push({\n name: func.name,\n selector: `0x${func.selector}`,\n type: 'function',\n severity: func.severity,\n description: func.description,\n });\n }\n }\n\n // Check for dangerous opcodes — only check for SELFDESTRUCT\n // (delegatecall is common and normal in proxy patterns)\n for (const op of DANGEROUS_OPCODES) {\n // SELFDESTRUCT: look for the ff opcode — it's common as a byte but\n // specifically look for the PUSH pattern before it or it at function boundaries\n if (op.byte === 'ff' && normalized.includes('ff')) {\n // Simple heuristic: if the bytecode contains SELFDESTRUCT opcode\n // at a position that could be a standalone instruction\n // (not part of PUSH data), flag it.\n // We check for common patterns: ...XX ff (where XX is not a PUSH)\n const idx = normalized.indexOf('ff');\n if (idx > 0 && idx % 2 === 0) {\n findings.push({\n name: op.name,\n selector: `0x${op.byte}`,\n type: 'opcode',\n severity: op.severity,\n description: op.description,\n });\n }\n }\n }\n\n // Sort: critical first, then warning, then info\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n findings.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));\n\n return findings;\n}\n\n/**\n * Quick check: does the bytecode contain any mint-related selectors?\n */\nexport function hasMintFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return normalized.includes('40c10f19') || normalized.includes('a0712d68');\n}\n\n/**\n * Quick check: does the bytecode contain pause-related selectors?\n */\nexport function hasPauseFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return normalized.includes('8456cb59');\n}\n\n/**\n * Quick check: does the bytecode contain blacklist-related selectors?\n */\nexport function hasBlacklistFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return (\n normalized.includes('ef01df4f') ||\n normalized.includes('44337ea1') ||\n normalized.includes('e47d6060')\n );\n}\n\n/**\n * Calculate Shannon entropy of byte distribution in bytecode.\n * Higher entropy = more random/packed code, lower = repetitive patterns.\n */\nexport function calculateEntropy(code: string): number {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n if (normalized.length < 2) return 0;\n\n // Count byte frequencies (pairs of hex chars)\n const counts = new Map<string, number>();\n const totalBytes = Math.floor(normalized.length / 2);\n\n for (let i = 0; i < normalized.length - 1; i += 2) {\n const byte = normalized.slice(i, i + 2);\n counts.set(byte, (counts.get(byte) ?? 0) + 1);\n }\n\n // Shannon entropy\n let entropy = 0;\n for (const count of counts.values()) {\n const p = count / totalBytes;\n if (p > 0) {\n entropy -= p * Math.log2(p);\n }\n }\n\n return entropy;\n}\n\nexport interface BytecodeScanResult {\n findings: BytecodeFinding[];\n mlRisk?: BytecodeRiskMLResult;\n}\n\n/**\n * ML-enhanced bytecode scan. Runs rule-based scan then ML risk scoring.\n */\nexport async function scanBytecodeML(code: string): Promise<BytecodeScanResult> {\n const findings = scanBytecode(code);\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n\n const mlClient = getMLClient();\n if (!mlClient) return { findings };\n\n try {\n const hasSd = findings.some((f) => f.name === 'SELFDESTRUCT');\n const hasDc = normalized.includes('f4'); // DELEGATECALL opcode\n const selectorCount = DANGEROUS_FUNCTIONS.filter((f) => normalized.includes(f.selector)).length;\n const entropy = calculateEntropy(code);\n\n const result = await mlClient.scoreBytecodeRisk({\n bytecode_size: Math.floor(normalized.length / 2),\n is_verified: 0,\n has_selfdestruct: hasSd ? 1 : 0,\n has_delegatecall: hasDc ? 1 : 0,\n selector_count: selectorCount,\n opcode_entropy: entropy,\n has_mint: hasMintFunction(code) ? 1 : 0,\n has_pause: hasPauseFunction(code) ? 1 : 0,\n has_blacklist: hasBlacklistFunction(code) ? 1 : 0,\n has_proxy: normalized.includes('f4') ? 1 : 0,\n });\n\n if (result) {\n return { findings, mlRisk: result };\n }\n } catch {\n // ML unavailable\n }\n\n return { findings };\n}\n","import type { ChainAdapter } from '../../chains/types.js';\nimport {\n hasMintFunction,\n hasPauseFunction,\n hasBlacklistFunction,\n scanBytecode,\n} from './bytecode-scanner.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { getConfig } from '../../config/loader.js';\nimport type { RugMLResult } from '../../ml/types.js';\n\nexport interface RugIndicators {\n isHoneypot: boolean;\n hasLiquidityLock: boolean;\n ownerCanMint: boolean;\n ownerCanPause: boolean;\n hasBlacklist: boolean;\n highSellTax: boolean;\n riskScore: number;\n details: RugDetail[];\n mlAnalysis?: RugMLResult;\n}\n\nexport interface RugDetail {\n check: string;\n passed: boolean;\n description: string;\n severity: 'info' | 'warning' | 'critical';\n}\n\nexport async function detectRugIndicators(\n tokenAddress: string,\n adapter: ChainAdapter,\n): Promise<RugIndicators> {\n const details: RugDetail[] = [];\n\n // Get contract bytecode for analysis\n const code = await adapter.getContractCode(tokenAddress).catch(() => '');\n const hasCode = code.length > 2;\n\n details.push({\n check: 'Contract Verified',\n passed: hasCode,\n description: hasCode ? 'Contract bytecode is available' : 'No contract code found',\n severity: hasCode ? 'info' : 'warning',\n });\n\n // Check basic token info\n try {\n const info = await adapter.getTokenInfo(tokenAddress);\n const tokenValid = info.name.length > 0 && info.symbol.length > 0;\n details.push({\n check: 'Valid Token',\n passed: tokenValid,\n description: tokenValid\n ? `Token: ${info.name} (${info.symbol})`\n : 'Unable to read token metadata',\n severity: tokenValid ? 'info' : 'warning',\n });\n } catch {\n details.push({\n check: 'Valid Token',\n passed: false,\n description: 'Failed to read token contract',\n severity: 'critical',\n });\n }\n\n // Bytecode scanning for dangerous functions\n const canMint = hasCode && hasMintFunction(code);\n const canPause = hasCode && hasPauseFunction(code);\n const hasBlacklist_ = hasCode && hasBlacklistFunction(code);\n\n details.push({\n check: 'No Mint Function',\n passed: !canMint,\n description: canMint\n ? 'Owner can mint new tokens (inflation risk)'\n : 'No owner mint capability detected',\n severity: canMint ? 'critical' : 'info',\n });\n\n details.push({\n check: 'No Pause Function',\n passed: !canPause,\n description: canPause\n ? 'Owner can pause transfers (honeypot risk)'\n : 'No pause capability detected',\n severity: canPause ? 'warning' : 'info',\n });\n\n details.push({\n check: 'No Blacklist Function',\n passed: !hasBlacklist_,\n description: hasBlacklist_\n ? 'Owner can blacklist addresses (honeypot risk)'\n : 'No blacklist capability detected',\n severity: hasBlacklist_ ? 'critical' : 'info',\n });\n\n // Add all bytecode findings as details\n if (hasCode) {\n const findings = scanBytecode(code);\n for (const finding of findings) {\n // Skip duplicates we already added above\n if (\n finding.name.includes('mint') ||\n finding.name.includes('pause') ||\n finding.name.includes('blacklist') ||\n finding.name.includes('Blacklist')\n ) {\n continue;\n }\n\n if (finding.severity !== 'info') {\n details.push({\n check: finding.name,\n passed: false,\n description: finding.description,\n severity: finding.severity,\n });\n }\n }\n }\n\n const riskScore = calculateRugRisk(details);\n\n // ML enhancement — call rug detector model if available\n let mlAnalysis: RugMLResult | undefined;\n try {\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (mlClient) {\n const mlResult = await mlClient.predictRug({\n bytecode_size: hasCode ? code.length : 0,\n is_verified: hasCode ? 1 : 0,\n holder_concentration: 0,\n has_proxy: 0,\n has_mint: canMint ? 1 : 0,\n has_pause: canPause ? 1 : 0,\n has_blacklist: hasBlacklist_ ? 1 : 0,\n liquidity_locked: 0,\n buy_tax: 0,\n sell_tax: 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: 0,\n is_open_source: hasCode ? 1 : 0,\n top10_holder_pct: 0,\n });\n if (mlResult) {\n mlAnalysis = mlResult;\n }\n }\n } catch {\n /* ML unavailable — continue with rule-based */\n }\n\n return {\n isHoneypot: canPause || hasBlacklist_,\n hasLiquidityLock: false,\n ownerCanMint: canMint,\n ownerCanPause: canPause,\n hasBlacklist: hasBlacklist_,\n highSellTax: false,\n riskScore: mlAnalysis\n ? Math.round(riskScore * 0.4 + mlAnalysis.rug_probability * 100 * 0.6)\n : riskScore,\n details,\n mlAnalysis,\n };\n}\n\nfunction calculateRugRisk(details: RugDetail[]): number {\n let score = 0;\n for (const detail of details) {\n if (!detail.passed) {\n switch (detail.severity) {\n case 'critical':\n score += 30;\n break;\n case 'warning':\n score += 15;\n break;\n case 'info':\n score += 5;\n break;\n }\n }\n }\n return Math.min(100, score);\n}\n","// ---------------------------------------------------------------------------\n// Market regime detection — ML-powered with heuristic fallback\n// ---------------------------------------------------------------------------\n\nimport { getMLClient } from '../../ml/client.js';\nimport type { RegimeMLFeatures, MarketRegime } from '../../ml/types.js';\n\nexport type { MarketRegime };\n\nexport interface RegimeResult {\n regime: MarketRegime;\n confidence: number;\n probabilities: Record<string, number>;\n model: string;\n}\n\n/**\n * Detect the current market regime for a symbol.\n * Uses ML regime detector when available, falls back to heuristic.\n */\nexport async function detectMarketRegime(\n _symbol: string,\n features: RegimeMLFeatures,\n): Promise<RegimeResult> {\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const result = await mlClient.detectRegime(features);\n if (result) {\n return {\n regime: result.regime,\n confidence: result.confidence,\n probabilities: result.probabilities,\n model: result.model,\n };\n }\n } catch {\n // ML unavailable — fallback\n }\n }\n return detectRegimeHeuristic(features);\n}\n\nfunction detectRegimeHeuristic(features: RegimeMLFeatures): RegimeResult {\n const vol = features.volatility_14d;\n const ret7d = features.returns_7d;\n const fg = features.fear_greed;\n const rsi = features.rsi;\n\n let regime: MarketRegime;\n let confidence: number;\n\n if (fg < 15 && ret7d < -20) {\n regime = 'capitulation';\n confidence = 80;\n } else if (vol > 8) {\n regime = 'volatile';\n confidence = 70;\n } else if (vol > 5 && ret7d > 10) {\n regime = 'trending_bull';\n confidence = 65;\n } else if (vol > 5 && ret7d < -10) {\n regime = 'trending_bear';\n confidence = 65;\n } else if (ret7d > 5 && rsi > 55) {\n regime = 'trending_bull';\n confidence = 55;\n } else if (ret7d < -5 && rsi < 45) {\n regime = 'trending_bear';\n confidence = 55;\n } else {\n regime = 'ranging';\n confidence = 60;\n }\n\n const probabilities: Record<string, number> = {\n trending_bull: 0.05,\n trending_bear: 0.05,\n ranging: 0.05,\n volatile: 0.05,\n capitulation: 0.05,\n };\n probabilities[regime] = confidence / 100;\n const remaining = 1.0 - probabilities[regime]!;\n const others = Object.keys(probabilities).filter((k) => k !== regime);\n for (const k of others) {\n probabilities[k] = remaining / others.length;\n }\n\n return {\n regime,\n confidence,\n probabilities,\n model: 'heuristic-regime-detector',\n };\n}\n","import Database from 'better-sqlite3';\nimport { join } from 'node:path';\nimport { getConfigDir } from '../config/loader.js';\n\nlet db: Database.Database | null = null;\n\n/**\n * Returns the lazily-initialized SQLite database instance.\n * Enables WAL mode and creates tables on first access.\n */\nexport function getDb(): Database.Database {\n if (db) {\n return db;\n }\n\n const dbPath = join(getConfigDir(), 'vizzor.db');\n db = new Database(dbPath);\n\n db.pragma('journal_mode = WAL');\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS cache (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n expires_at INTEGER NOT NULL,\n created_at INTEGER NOT NULL\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS watchlist (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n type TEXT NOT NULL CHECK (type IN ('wallet', 'token', 'project')),\n identifier TEXT NOT NULL,\n chain TEXT NOT NULL DEFAULT 'ethereum',\n label TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE (type, identifier, chain)\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS analysis_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n command TEXT NOT NULL,\n input TEXT NOT NULL,\n result TEXT NOT NULL,\n chain TEXT,\n created_at INTEGER NOT NULL\n )\n `);\n\n return db;\n}\n\n/**\n * Returns a cached value parsed from JSON, or null if the key does not exist\n * or has expired.\n */\nexport function getCached<T = unknown>(key: string): T | null {\n const row = getDb().prepare('SELECT value, expires_at FROM cache WHERE key = ?').get(key) as\n | { value: string; expires_at: number }\n | undefined;\n\n if (!row) {\n return null;\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (row.expires_at <= now) {\n getDb().prepare('DELETE FROM cache WHERE key = ?').run(key);\n return null;\n }\n\n return JSON.parse(row.value) as T;\n}\n\n/**\n * Inserts or replaces a cached value with the given TTL in seconds.\n */\nexport function setCache(key: string, value: unknown, ttlSeconds: number): void {\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + ttlSeconds;\n\n getDb()\n .prepare(\n `INSERT OR REPLACE INTO cache (key, value, expires_at, created_at)\n VALUES (?, ?, ?, ?)`,\n )\n .run(key, JSON.stringify(value), expiresAt, now);\n}\n\n/**\n * Deletes all expired cache entries.\n */\nexport function clearExpired(): void {\n const now = Math.floor(Date.now() / 1000);\n getDb().prepare('DELETE FROM cache WHERE expires_at <= ?').run(now);\n}\n","// ---------------------------------------------------------------------------\n// Agent engine — think → analyze → decide → act cycle\n// ---------------------------------------------------------------------------\n\nimport type {\n AgentConfig,\n AgentStrategy,\n AgentSignals,\n AgentCycleResult,\n AgentState,\n} from './types.js';\nimport { fetchTickerPrice, fetchFundingRate } from '../../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../../data/sources/fear-greed.js';\nimport { getStrategy } from './manager.js';\nimport { logDecision } from './manager.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('agent-engine');\n\nexport class AgentEngine {\n private timer: ReturnType<typeof setInterval> | null = null;\n private state: AgentState;\n private strategy: AgentStrategy;\n\n constructor(config: AgentConfig) {\n this.strategy = getStrategy(config.strategy);\n this.state = {\n config,\n status: 'idle',\n lastCycle: null,\n cycleCount: 0,\n error: null,\n };\n }\n\n getState(): AgentState {\n return { ...this.state };\n }\n\n start(): void {\n if (this.state.status === 'running') return;\n\n this.state.status = 'running';\n this.state.error = null;\n logger.info(`Agent ${this.state.config.name} started (${this.strategy.name})`);\n\n // Run immediately, then at interval\n void this.runCycle();\n this.timer = setInterval(() => {\n void this.runCycle();\n }, this.state.config.interval * 1000);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.state.status = 'stopped';\n logger.info(`Agent ${this.state.config.name} stopped`);\n }\n\n private async runCycle(): Promise<void> {\n for (const symbol of this.state.config.pairs) {\n try {\n const signals = await this.gatherSignals(symbol);\n const decision = this.strategy.evaluate(signals);\n\n const result: AgentCycleResult = {\n agentId: this.state.config.id,\n symbol,\n timestamp: Date.now(),\n signals,\n decision,\n };\n\n this.state.lastCycle = result;\n this.state.cycleCount++;\n\n // Log to DB\n logDecision(result);\n\n if (decision.action !== 'hold') {\n logger.info(\n `Agent ${this.state.config.name} → ${decision.action.toUpperCase()} ${symbol} (confidence: ${decision.confidence}%)`,\n );\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.state.error = `Cycle error for ${symbol}: ${message}`;\n logger.warn(`Agent ${this.state.config.name} cycle error: ${message}`);\n }\n }\n }\n\n /**\n * Gather all signals for a symbol. Uses Promise.allSettled so partial\n * failures don't block the entire cycle.\n */\n private async gatherSignals(symbol: string): Promise<AgentSignals> {\n const signals: AgentSignals = {\n rsi: null,\n macdHistogram: null,\n ema12: null,\n ema26: null,\n bollingerPercentB: null,\n atr: null,\n obv: null,\n fundingRate: null,\n fearGreed: null,\n priceChange24h: null,\n price: null,\n };\n\n const [priceResult, fundingResult, fgResult] = await Promise.allSettled([\n fetchTickerPrice(symbol),\n fetchFundingRate(symbol),\n fetchFearGreedIndex(1),\n ]);\n\n if (priceResult.status === 'fulfilled') {\n signals.price = priceResult.value.price;\n signals.priceChange24h = priceResult.value.change24h;\n }\n\n if (fundingResult.status === 'fulfilled') {\n signals.fundingRate = fundingResult.value.fundingRate;\n }\n\n if (fgResult.status === 'fulfilled') {\n signals.fearGreed = fgResult.value.current.value;\n }\n\n // Technical analysis signals are gathered lazily via the manager\n // when the TA module is available (requires kline data).\n // For v0.3.0, the engine uses price + derivatives + macro signals.\n // Full TA integration happens in the agent cycle via direct indicator calls.\n\n return signals;\n }\n}\n","// ---------------------------------------------------------------------------\n// Momentum strategy — RSI + MACD confirmation\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\n\n/**\n * Buy when RSI crosses above 30 with MACD confirmation.\n * Sell when RSI drops below 70 or MACD turns bearish.\n */\nexport const momentumStrategy: AgentStrategy = {\n name: 'momentum',\n description: 'RSI reversal + MACD confirmation. Buy oversold bounces, sell overbought peaks.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0; // positive = buy, negative = sell\n\n // RSI signals\n if (signals.rsi !== null) {\n if (signals.rsi < 30) {\n score += 40;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — oversold, buy signal`);\n } else if (signals.rsi < 40) {\n score += 20;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — approaching oversold`);\n } else if (signals.rsi > 70) {\n score -= 40;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — overbought, sell signal`);\n } else if (signals.rsi > 60) {\n score -= 15;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — elevated, caution`);\n } else {\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — neutral`);\n }\n }\n\n // MACD confirmation\n if (signals.macdHistogram !== null) {\n if (signals.macdHistogram > 0) {\n score += 25;\n reasoning.push(\n `MACD histogram positive (${signals.macdHistogram.toFixed(4)}) — bullish momentum`,\n );\n } else {\n score -= 25;\n reasoning.push(\n `MACD histogram negative (${signals.macdHistogram.toFixed(4)}) — bearish momentum`,\n );\n }\n }\n\n // Bollinger %B for extreme levels\n if (signals.bollingerPercentB !== null) {\n if (signals.bollingerPercentB < 0.1) {\n score += 15;\n reasoning.push(\n `BB %B ${signals.bollingerPercentB.toFixed(2)} — near lower band, bounce potential`,\n );\n } else if (signals.bollingerPercentB > 0.9) {\n score -= 15;\n reasoning.push(\n `BB %B ${signals.bollingerPercentB.toFixed(2)} — near upper band, pullback risk`,\n );\n }\n }\n\n // Funding rate as contrarian signal\n if (signals.fundingRate !== null) {\n if (signals.fundingRate > 0.0005) {\n score -= 10;\n reasoning.push(\n `High funding rate ${(signals.fundingRate * 100).toFixed(4)}% — overleveraged longs`,\n );\n } else if (signals.fundingRate < -0.0003) {\n score += 10;\n reasoning.push(\n `Negative funding ${(signals.fundingRate * 100).toFixed(4)}% — capitulation signal`,\n );\n }\n }\n\n const action = score > 25 ? 'buy' : score < -25 ? 'sell' : 'hold';\n const confidence = Math.min(95, Math.abs(score));\n\n return { action, confidence, reasoning };\n },\n};\n\n/**\n * ML-enhanced momentum evaluation. Falls back to rule-based evaluate().\n */\nexport async function evaluateMomentumML(signals: AgentSignals): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return momentumStrategy.evaluate(signals);\n\n try {\n const result = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: 'ranging',\n });\n\n if (result && result.confidence > 40) {\n return {\n action: result.action,\n confidence: Math.round(result.confidence),\n reasoning: [`ML momentum: ${result.action}`, ...result.reasoning],\n };\n }\n } catch {\n // ML unavailable\n }\n return momentumStrategy.evaluate(signals);\n}\n","// ---------------------------------------------------------------------------\n// Trend-following strategy — EMA crossover + rising OI\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\n\n/**\n * Buy when EMA(12) crosses above EMA(26) with rising open interest.\n * Sell on death cross (EMA(12) < EMA(26)).\n */\nexport const trendFollowingStrategy: AgentStrategy = {\n name: 'trend-following',\n description: 'EMA crossover trend detection. Buy golden cross, sell death cross.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0;\n\n // EMA crossover — primary signal\n if (signals.ema12 !== null && signals.ema26 !== null) {\n const diff = signals.ema12 - signals.ema26;\n const pctDiff = signals.ema26 !== 0 ? (diff / signals.ema26) * 100 : 0;\n\n if (diff > 0) {\n score += 35;\n reasoning.push(`EMA(12) above EMA(26) by ${pctDiff.toFixed(2)}% — bullish trend`);\n } else {\n score -= 35;\n reasoning.push(`EMA(12) below EMA(26) by ${Math.abs(pctDiff).toFixed(2)}% — bearish trend`);\n }\n\n // Stronger signal when gap is widening\n if (Math.abs(pctDiff) > 2) {\n const extra = diff > 0 ? 15 : -15;\n score += extra;\n reasoning.push(\n `Strong ${diff > 0 ? 'bullish' : 'bearish'} divergence (${Math.abs(pctDiff).toFixed(2)}%)`,\n );\n }\n }\n\n // OBV confirmation\n if (signals.obv !== null) {\n if (signals.obv > 0) {\n score += 15;\n reasoning.push('OBV positive — volume confirms upward trend');\n } else if (signals.obv < 0) {\n score -= 15;\n reasoning.push('OBV negative — volume confirms downward trend');\n }\n }\n\n // 24h price change as trend confirmation\n if (signals.priceChange24h !== null) {\n if (signals.priceChange24h > 3) {\n score += 10;\n reasoning.push(\n `24h change +${signals.priceChange24h.toFixed(1)}% — strong upward momentum`,\n );\n } else if (signals.priceChange24h < -3) {\n score -= 10;\n reasoning.push(\n `24h change ${signals.priceChange24h.toFixed(1)}% — strong downward momentum`,\n );\n }\n }\n\n // Fear & Greed as macro overlay\n if (signals.fearGreed !== null) {\n if (signals.fearGreed > 80 && score > 0) {\n score -= 10;\n reasoning.push(`Extreme Greed (${signals.fearGreed}) — contrarian risk on longs`);\n } else if (signals.fearGreed < 20 && score < 0) {\n score += 10;\n reasoning.push(`Extreme Fear (${signals.fearGreed}) — contrarian support for bounce`);\n }\n }\n\n // ATR for volatility filter\n if (signals.atr !== null && signals.price !== null && signals.price > 0) {\n const atrPct = (signals.atr / signals.price) * 100;\n if (atrPct > 5) {\n reasoning.push(`High volatility (ATR ${atrPct.toFixed(2)}%) — wider stops needed`);\n }\n }\n\n const action = score > 25 ? 'buy' : score < -25 ? 'sell' : 'hold';\n const confidence = Math.min(95, Math.abs(score));\n\n return { action, confidence, reasoning };\n },\n};\n\n/**\n * ML-enhanced trend-following evaluation. Falls back to rule-based evaluate().\n */\nexport async function evaluateTrendFollowingML(signals: AgentSignals): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return trendFollowingStrategy.evaluate(signals);\n\n try {\n const result = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: 'ranging',\n });\n\n if (result && result.confidence > 40) {\n return {\n action: result.action,\n confidence: Math.round(result.confidence),\n reasoning: [`ML trend-following: ${result.action}`, ...result.reasoning],\n };\n }\n } catch {\n // ML unavailable\n }\n return trendFollowingStrategy.evaluate(signals);\n}\n","// ---------------------------------------------------------------------------\n// ML-Adaptive Strategy — contextual bandit approach using ML predictions\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\nimport { detectMarketRegime } from '../../trends/regime.js';\n\nexport const mlAdaptiveStrategy: AgentStrategy = {\n name: 'ml-adaptive',\n description:\n 'ML-powered strategy using contextual bandit approach. Uses LSTM/RF predictions ' +\n 'when available, falls back to rule-based when < 100 training samples.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n // Synchronous evaluation — uses cached ML predictions if available\n // The async ML call happens in the engine before this is called\n return evaluateWithRules(signals);\n },\n};\n\nfunction evaluateWithRules(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0;\n\n // RSI with adaptive thresholds\n if (signals.rsi !== null) {\n if (signals.rsi < 25) {\n score += 35;\n reasoning.push(`RSI deeply oversold (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi < 35) {\n score += 20;\n reasoning.push(`RSI oversold zone (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi > 75) {\n score -= 35;\n reasoning.push(`RSI deeply overbought (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi > 65) {\n score -= 20;\n reasoning.push(`RSI overbought zone (${signals.rsi.toFixed(0)})`);\n }\n }\n\n // MACD with momentum confirmation\n if (signals.macdHistogram !== null) {\n if (signals.macdHistogram > 0) {\n score += 15;\n reasoning.push('MACD bullish momentum');\n } else {\n score -= 15;\n reasoning.push('MACD bearish momentum');\n }\n }\n\n // EMA crossover\n if (signals.ema12 !== null && signals.ema26 !== null) {\n const crossPct =\n signals.ema26 !== 0 ? ((signals.ema12 - signals.ema26) / signals.ema26) * 100 : 0;\n if (crossPct > 0.5) {\n score += 20;\n reasoning.push(`Golden cross (EMA12 > EMA26 by ${crossPct.toFixed(2)}%)`);\n } else if (crossPct < -0.5) {\n score -= 20;\n reasoning.push(`Death cross (EMA12 < EMA26 by ${Math.abs(crossPct).toFixed(2)}%)`);\n }\n }\n\n // Bollinger Bands\n if (signals.bollingerPercentB !== null) {\n if (signals.bollingerPercentB < 0.1) {\n score += 15;\n reasoning.push('Price at lower Bollinger Band — potential bounce');\n } else if (signals.bollingerPercentB > 0.9) {\n score -= 15;\n reasoning.push('Price at upper Bollinger Band — potential resistance');\n }\n }\n\n // Funding rate (contrarian)\n if (signals.fundingRate !== null) {\n if (signals.fundingRate > 0.0005) {\n score -= 10;\n reasoning.push('High funding rate — overleveraged longs');\n } else if (signals.fundingRate < -0.0003) {\n score += 10;\n reasoning.push('Negative funding — capitulation signal');\n }\n }\n\n // Fear & Greed (contrarian)\n if (signals.fearGreed !== null) {\n if (signals.fearGreed < 20) {\n score += 10;\n reasoning.push('Extreme fear — contrarian bullish');\n } else if (signals.fearGreed > 80) {\n score -= 10;\n reasoning.push('Extreme greed — contrarian bearish');\n }\n }\n\n // 24h trend confirmation\n if (signals.priceChange24h !== null) {\n if (signals.priceChange24h > 5) {\n score += 10;\n } else if (signals.priceChange24h < -5) {\n score -= 10;\n }\n }\n\n const confidence = Math.min(95, Math.abs(score));\n if (score > 20) {\n return { action: 'buy', confidence, reasoning };\n } else if (score < -20) {\n return { action: 'sell', confidence, reasoning };\n }\n return {\n action: 'hold',\n confidence: Math.max(30, 50 - Math.abs(score)),\n reasoning: [...reasoning, 'Mixed signals — holding'],\n };\n}\n\nexport async function evaluateWithML(\n symbol: string,\n signals: AgentSignals,\n): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return evaluateWithRules(signals);\n\n try {\n // Step 1: detect market regime\n const regime = await detectMarketRegime(symbol, {\n returns_1d: signals.priceChange24h ?? 0,\n returns_7d: 0,\n volatility_14d:\n signals.atr !== null && signals.price !== null && signals.price > 0\n ? (signals.atr / signals.price) * 100\n : 3,\n volume_ratio: 1,\n rsi: signals.rsi ?? 50,\n bb_width: 0,\n fear_greed: signals.fearGreed ?? 50,\n funding_rate: signals.fundingRate ?? 0,\n price_vs_sma200: 0,\n });\n\n // Step 2: call strategy bandit with regime context\n const strategyResult = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: regime.regime,\n });\n\n if (strategyResult && strategyResult.confidence > 30) {\n return {\n action: strategyResult.action,\n confidence: Math.round(strategyResult.confidence),\n reasoning: [\n `Regime: ${regime.regime} (${regime.confidence.toFixed(0)}% confidence)`,\n ...strategyResult.reasoning,\n ],\n };\n }\n\n // Low ML confidence — blend with rules\n const ruleDecision = evaluateWithRules(signals);\n return {\n action: ruleDecision.action,\n confidence: Math.round(((strategyResult?.confidence ?? 0) + ruleDecision.confidence) / 2),\n reasoning: [\n `Regime: ${regime.regime}`,\n ...(strategyResult?.reasoning ?? []),\n '(Low ML confidence — blending with rules)',\n ...ruleDecision.reasoning,\n ],\n };\n } catch {\n return evaluateWithRules(signals);\n }\n}\n","// ---------------------------------------------------------------------------\n// Agent manager — CRUD, lifecycle, strategy registry\n// ---------------------------------------------------------------------------\n\nimport { randomUUID } from 'node:crypto';\nimport { getDb } from '../../data/cache.js';\nimport type { AgentConfig, AgentState, AgentStrategy, AgentCycleResult } from './types.js';\nimport { AgentEngine } from './engine.js';\nimport { momentumStrategy } from './strategies/momentum.js';\nimport { trendFollowingStrategy } from './strategies/trend-following.js';\nimport { mlAdaptiveStrategy } from './strategies/ml-adaptive.js';\n\n// ---------------------------------------------------------------------------\n// Strategy registry\n// ---------------------------------------------------------------------------\n\nconst STRATEGIES: Record<string, AgentStrategy> = {\n momentum: momentumStrategy,\n 'trend-following': trendFollowingStrategy,\n 'ml-adaptive': mlAdaptiveStrategy,\n};\n\nexport function getStrategy(name: string): AgentStrategy {\n const strategy = STRATEGIES[name];\n if (!strategy) {\n throw new Error(`Unknown strategy: ${name}. Available: ${Object.keys(STRATEGIES).join(', ')}`);\n }\n return strategy;\n}\n\nexport function listStrategies(): string[] {\n return Object.keys(STRATEGIES);\n}\n\n// ---------------------------------------------------------------------------\n// Running engines\n// ---------------------------------------------------------------------------\n\nconst engines = new Map<string, AgentEngine>();\n\n// ---------------------------------------------------------------------------\n// DB helpers\n// ---------------------------------------------------------------------------\n\nfunction ensureAgentTables(): void {\n const db = getDb();\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS agents (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n strategy TEXT NOT NULL,\n pairs TEXT NOT NULL,\n interval_seconds INTEGER NOT NULL DEFAULT 60,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS agent_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n symbol TEXT NOT NULL,\n action TEXT NOT NULL,\n confidence INTEGER NOT NULL,\n reasoning TEXT NOT NULL,\n signals TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY (agent_id) REFERENCES agents(id)\n )\n `);\n}\n\n// ---------------------------------------------------------------------------\n// CRUD\n// ---------------------------------------------------------------------------\n\nexport function createAgent(\n name: string,\n strategy: string,\n pairs: string[],\n interval = 60,\n): AgentConfig {\n ensureAgentTables();\n\n // Validate strategy\n getStrategy(strategy);\n\n const id = randomUUID();\n const now = Date.now();\n\n getDb()\n .prepare(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(id, name, strategy, JSON.stringify(pairs), interval, now, now);\n\n return { id, name, strategy, pairs, interval, createdAt: now, updatedAt: now };\n}\n\nexport function listAgents(): AgentConfig[] {\n ensureAgentTables();\n\n const rows = getDb().prepare('SELECT * FROM agents ORDER BY created_at DESC').all() as {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }[];\n\n return rows.map((r) => ({\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: JSON.parse(r.pairs) as string[],\n interval: r.interval_seconds,\n createdAt: r.created_at,\n updatedAt: r.updated_at,\n }));\n}\n\nexport function getAgentById(id: string): AgentConfig | null {\n ensureAgentTables();\n\n const row = getDb().prepare('SELECT * FROM agents WHERE id = ?').get(id) as\n | {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }\n | undefined;\n\n if (!row) return null;\n\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function getAgentByName(name: string): AgentConfig | null {\n ensureAgentTables();\n\n const row = getDb().prepare('SELECT * FROM agents WHERE name = ?').get(name) as\n | {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }\n | undefined;\n\n if (!row) return null;\n\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function deleteAgent(id: string): boolean {\n ensureAgentTables();\n\n // Stop engine if running\n const engine = engines.get(id);\n if (engine) {\n engine.stop();\n engines.delete(id);\n }\n\n const result = getDb().prepare('DELETE FROM agents WHERE id = ?').run(id);\n getDb().prepare('DELETE FROM agent_decisions WHERE agent_id = ?').run(id);\n\n return result.changes > 0;\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle\n// ---------------------------------------------------------------------------\n\nexport function startAgent(id: string): AgentState {\n const config = getAgentById(id);\n if (!config) throw new Error(`Agent not found: ${id}`);\n\n // Reuse existing engine if already created\n let engine = engines.get(id);\n if (!engine) {\n engine = new AgentEngine(config);\n engines.set(id, engine);\n }\n\n engine.start();\n return engine.getState();\n}\n\nexport function stopAgent(id: string): AgentState {\n const engine = engines.get(id);\n if (!engine) throw new Error(`Agent not running: ${id}`);\n\n engine.stop();\n return engine.getState();\n}\n\nexport function getAgentStatus(id: string): AgentState | null {\n const engine = engines.get(id);\n if (engine) return engine.getState();\n\n // Agent exists but not running\n const config = getAgentById(id);\n if (!config) return null;\n\n return {\n config,\n status: 'idle',\n lastCycle: null,\n cycleCount: 0,\n error: null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Decision logging\n// ---------------------------------------------------------------------------\n\nexport function logDecision(result: AgentCycleResult): void {\n ensureAgentTables();\n\n getDb()\n .prepare(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n );\n}\n\nexport function getRecentDecisions(agentId: string, limit = 20): AgentCycleResult[] {\n ensureAgentTables();\n\n const rows = getDb()\n .prepare(`SELECT * FROM agent_decisions WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?`)\n .all(agentId, limit) as {\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string;\n signals: string;\n created_at: number;\n }[];\n\n return rows.map((r) => ({\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: r.created_at,\n signals: JSON.parse(r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: JSON.parse(r.reasoning) as string[],\n },\n }));\n}\n","// ---------------------------------------------------------------------------\n// Agent wallet — read-only for v0.3.0 (no tx signing)\n// ---------------------------------------------------------------------------\n\nimport { createPublicClient, http, formatEther } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport type { Address } from 'viem';\n\nexport interface AgentWallet {\n address: string;\n chain: string;\n}\n\nconst client = createPublicClient({\n chain: mainnet,\n transport: http(),\n});\n\n/**\n * Read the ETH balance of a wallet address.\n * v0.3.0: read-only, no private key management or tx signing.\n */\nexport async function getWalletBalance(address: string): Promise<string> {\n const balance = await client.getBalance({ address: address as Address });\n return formatEther(balance);\n}\n\n/**\n * Check if an address is a valid Ethereum address format.\n */\nexport function isValidAddress(address: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(address);\n}\n","// ---------------------------------------------------------------------------\n// Agent module barrel export\n// ---------------------------------------------------------------------------\n\nexport type {\n AgentConfig,\n AgentStrategy,\n AgentSignals,\n AgentDecision,\n AgentCycleResult,\n AgentState,\n AgentStatus,\n AgentAction,\n} from './types.js';\n\nexport {\n createAgent,\n listAgents,\n getAgentById,\n getAgentByName,\n deleteAgent,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n listStrategies,\n} from './manager.js';\n\nexport { AgentEngine } from './engine.js';\nexport { getWalletBalance, isValidAddress } from './wallet.js';\n","// ---------------------------------------------------------------------------\n// SqliteStore — wraps existing SQLite layer behind the DataStore interface\n// ---------------------------------------------------------------------------\n\nimport { getDb, getCached, setCache } from './cache.js';\nimport type { AgentConfig, AgentCycleResult } from '../core/agent/types.js';\nimport type { DataStore, OHLCVRecord, MLPrediction, AccuracyReport } from './types.js';\n\nfunction ensureAgentTables(): void {\n const db = getDb();\n db.exec(`\n CREATE TABLE IF NOT EXISTS agents (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n strategy TEXT NOT NULL,\n pairs TEXT NOT NULL,\n interval_seconds INTEGER NOT NULL DEFAULT 60,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `);\n db.exec(`\n CREATE TABLE IF NOT EXISTS agent_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n symbol TEXT NOT NULL,\n action TEXT NOT NULL,\n confidence INTEGER NOT NULL,\n reasoning TEXT NOT NULL,\n signals TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY (agent_id) REFERENCES agents(id)\n )\n `);\n}\n\nfunction rowToConfig(row: {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n}): AgentConfig {\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class SqliteStore implements DataStore {\n // ---- Cache ---------------------------------------------------------------\n\n async getCached<T>(key: string): Promise<T | null> {\n return getCached<T>(key);\n }\n\n async setCache(key: string, value: unknown, ttlSeconds: number): Promise<void> {\n setCache(key, value, ttlSeconds);\n }\n\n // ---- Agents --------------------------------------------------------------\n\n async createAgent(config: AgentConfig): Promise<AgentConfig> {\n ensureAgentTables();\n getDb()\n .prepare(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n config.id,\n config.name,\n config.strategy,\n JSON.stringify(config.pairs),\n config.interval,\n config.createdAt,\n config.updatedAt,\n );\n return config;\n }\n\n async listAgents(): Promise<AgentConfig[]> {\n ensureAgentTables();\n const rows = getDb()\n .prepare('SELECT * FROM agents ORDER BY created_at DESC')\n .all() as Parameters<typeof rowToConfig>[0][];\n return rows.map(rowToConfig);\n }\n\n async getAgentById(id: string): Promise<AgentConfig | null> {\n ensureAgentTables();\n const row = getDb().prepare('SELECT * FROM agents WHERE id = ?').get(id) as\n | Parameters<typeof rowToConfig>[0]\n | undefined;\n return row ? rowToConfig(row) : null;\n }\n\n async getAgentByName(name: string): Promise<AgentConfig | null> {\n ensureAgentTables();\n const row = getDb().prepare('SELECT * FROM agents WHERE name = ?').get(name) as\n | Parameters<typeof rowToConfig>[0]\n | undefined;\n return row ? rowToConfig(row) : null;\n }\n\n async deleteAgent(id: string): Promise<boolean> {\n ensureAgentTables();\n const result = getDb().prepare('DELETE FROM agents WHERE id = ?').run(id);\n getDb().prepare('DELETE FROM agent_decisions WHERE agent_id = ?').run(id);\n return result.changes > 0;\n }\n\n async logDecision(result: AgentCycleResult): Promise<void> {\n ensureAgentTables();\n getDb()\n .prepare(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n );\n }\n\n async getDecisions(agentId: string, limit: number): Promise<AgentCycleResult[]> {\n ensureAgentTables();\n const rows = getDb()\n .prepare('SELECT * FROM agent_decisions WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?')\n .all(agentId, limit) as {\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string;\n signals: string;\n created_at: number;\n }[];\n return rows.map((r) => ({\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: r.created_at,\n signals: JSON.parse(r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: JSON.parse(r.reasoning) as string[],\n },\n }));\n }\n\n // ---- Time-series (no-op for SQLite) --------------------------------------\n\n async insertOHLCV(_records: OHLCVRecord[]): Promise<void> {\n // SQLite does not support time-series; silently skip\n }\n\n async queryOHLCV(\n _symbol: string,\n _timeframe: string,\n _from: number,\n _to: number,\n ): Promise<OHLCVRecord[]> {\n return [];\n }\n\n // ---- Predictions (no-op for SQLite) --------------------------------------\n\n async logPrediction(_prediction: MLPrediction): Promise<void> {\n // Not supported in SQLite mode\n }\n\n async getPredictionAccuracy(_model: string, _days: number): Promise<AccuracyReport> {\n return {\n model: _model,\n totalPredictions: 0,\n correctPredictions: 0,\n accuracy: 0,\n byDirection: {\n up: { total: 0, correct: 0, accuracy: 0 },\n down: { total: 0, correct: 0, accuracy: 0 },\n sideways: { total: 0, correct: 0, accuracy: 0 },\n },\n period: `${_days}d`,\n };\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n async close(): Promise<void> {\n // SQLite handles cleanup via process exit; nothing to do\n }\n}\n","// ---------------------------------------------------------------------------\n// PostgresStore — DataStore backed by PostgreSQL + TimescaleDB\n// ---------------------------------------------------------------------------\n\nimport pg from 'pg';\nimport { readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AgentConfig, AgentCycleResult } from '../core/agent/types.js';\nimport type { DataStore, OHLCVRecord, MLPrediction, AccuracyReport } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport class PostgresStore implements DataStore {\n private pool: pg.Pool;\n private initialized = false;\n\n constructor(connectionUrl: string) {\n this.pool = new pg.Pool({ connectionString: connectionUrl, max: 10 });\n }\n\n private async init(): Promise<void> {\n if (this.initialized) return;\n const migrationPath = resolve(__dirname, 'migrations', '001-init.sql');\n const sql = readFileSync(migrationPath, 'utf-8');\n await this.pool.query(sql);\n this.initialized = true;\n }\n\n private async query<T extends pg.QueryResultRow>(\n text: string,\n params?: unknown[],\n ): Promise<pg.QueryResult<T>> {\n await this.init();\n return this.pool.query<T>(text, params);\n }\n\n // ---- Cache ---------------------------------------------------------------\n\n async getCached<T>(key: string): Promise<T | null> {\n const now = Math.floor(Date.now() / 1000);\n const { rows } = await this.query<{ value: unknown }>(\n 'SELECT value FROM cache WHERE key = $1 AND expires_at > $2',\n [key, now],\n );\n if (rows.length === 0) return null;\n return rows[0].value as T;\n }\n\n async setCache(key: string, value: unknown, ttlSeconds: number): Promise<void> {\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + ttlSeconds;\n await this.query(\n `INSERT INTO cache (key, value, expires_at, created_at)\n VALUES ($1, $2, $3, $4)\n ON CONFLICT (key) DO UPDATE SET value = $2, expires_at = $3`,\n [key, JSON.stringify(value), expiresAt, now],\n );\n }\n\n // ---- Agents --------------------------------------------------------------\n\n async createAgent(config: AgentConfig): Promise<AgentConfig> {\n await this.query(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n config.id,\n config.name,\n config.strategy,\n JSON.stringify(config.pairs),\n config.interval,\n config.createdAt,\n config.updatedAt,\n ],\n );\n return config;\n }\n\n async listAgents(): Promise<AgentConfig[]> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents ORDER BY created_at DESC');\n\n return rows.map((r) => ({\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n }));\n }\n\n async getAgentById(id: string): Promise<AgentConfig | null> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents WHERE id = $1', [id]);\n\n if (rows.length === 0) return null;\n const r = rows[0];\n return {\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n };\n }\n\n async getAgentByName(name: string): Promise<AgentConfig | null> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents WHERE name = $1', [name]);\n\n if (rows.length === 0) return null;\n const r = rows[0];\n return {\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n };\n }\n\n async deleteAgent(id: string): Promise<boolean> {\n const result = await this.query('DELETE FROM agents WHERE id = $1', [id]);\n return (result.rowCount ?? 0) > 0;\n }\n\n async logDecision(result: AgentCycleResult): Promise<void> {\n await this.query(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n ],\n );\n }\n\n async getDecisions(agentId: string, limit: number): Promise<AgentCycleResult[]> {\n const { rows } = await this.query<{\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string[] | string;\n signals: Record<string, unknown> | string;\n created_at: string;\n }>('SELECT * FROM agent_decisions WHERE agent_id = $1 ORDER BY created_at DESC LIMIT $2', [\n agentId,\n limit,\n ]);\n\n return rows.map((r) => ({\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: Number(r.created_at),\n signals: (typeof r.signals === 'string'\n ? JSON.parse(r.signals)\n : r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: (typeof r.reasoning === 'string'\n ? JSON.parse(r.reasoning)\n : r.reasoning) as string[],\n },\n }));\n }\n\n // ---- Time-series ---------------------------------------------------------\n\n async insertOHLCV(records: OHLCVRecord[]): Promise<void> {\n if (records.length === 0) return;\n\n const values: unknown[] = [];\n const placeholders: string[] = [];\n\n for (let i = 0; i < records.length; i++) {\n const r = records[i];\n const offset = i * 9;\n placeholders.push(\n `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}, $${offset + 6}, $${offset + 7}, $${offset + 8}, $${offset + 9})`,\n );\n values.push(\n new Date(r.time).toISOString(),\n r.symbol,\n r.timeframe,\n r.open,\n r.high,\n r.low,\n r.close,\n r.volume,\n r.trades,\n );\n }\n\n await this.query(\n `INSERT INTO ohlcv (time, symbol, timeframe, open, high, low, close, volume, trades)\n VALUES ${placeholders.join(', ')}\n ON CONFLICT (symbol, timeframe, time) DO UPDATE\n SET open = EXCLUDED.open, high = EXCLUDED.high, low = EXCLUDED.low,\n close = EXCLUDED.close, volume = EXCLUDED.volume, trades = EXCLUDED.trades`,\n values,\n );\n }\n\n async queryOHLCV(\n symbol: string,\n timeframe: string,\n from: number,\n to: number,\n ): Promise<OHLCVRecord[]> {\n const { rows } = await this.query<{\n time: Date;\n symbol: string;\n timeframe: string;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n trades: number;\n }>(\n `SELECT * FROM ohlcv\n WHERE symbol = $1 AND timeframe = $2 AND time >= $3 AND time <= $4\n ORDER BY time ASC`,\n [symbol, timeframe, new Date(from).toISOString(), new Date(to).toISOString()],\n );\n\n return rows.map((r) => ({\n time: new Date(r.time).getTime(),\n symbol: r.symbol,\n timeframe: r.timeframe,\n open: r.open,\n high: r.high,\n low: r.low,\n close: r.close,\n volume: r.volume,\n trades: r.trades,\n }));\n }\n\n // ---- Predictions ---------------------------------------------------------\n\n async logPrediction(prediction: MLPrediction): Promise<void> {\n await this.query(\n `INSERT INTO predictions (symbol, model, direction, probability, horizon, features, predicted_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n prediction.symbol,\n prediction.model,\n prediction.direction,\n prediction.probability,\n prediction.horizon,\n JSON.stringify(prediction.features),\n new Date(prediction.predictedAt).toISOString(),\n ],\n );\n }\n\n async getPredictionAccuracy(model: string, days: number): Promise<AccuracyReport> {\n const since = new Date(Date.now() - days * 86400_000).toISOString();\n\n const { rows: totals } = await this.query<{\n direction: string;\n total: string;\n correct: string;\n }>(\n `SELECT direction,\n COUNT(*)::text AS total,\n COUNT(*) FILTER (WHERE was_correct = true)::text AS correct\n FROM predictions\n WHERE model = $1 AND predicted_at >= $2 AND was_correct IS NOT NULL\n GROUP BY direction`,\n [model, since],\n );\n\n const byDir = {\n up: { total: 0, correct: 0, accuracy: 0 },\n down: { total: 0, correct: 0, accuracy: 0 },\n sideways: { total: 0, correct: 0, accuracy: 0 },\n };\n let totalAll = 0;\n let correctAll = 0;\n\n for (const row of totals) {\n const t = parseInt(row.total, 10);\n const c = parseInt(row.correct, 10);\n totalAll += t;\n correctAll += c;\n const dir = row.direction as keyof typeof byDir;\n if (byDir[dir]) {\n byDir[dir] = { total: t, correct: c, accuracy: t > 0 ? c / t : 0 };\n }\n }\n\n return {\n model,\n totalPredictions: totalAll,\n correctPredictions: correctAll,\n accuracy: totalAll > 0 ? correctAll / totalAll : 0,\n byDirection: byDir,\n period: `${days}d`,\n };\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n","// ---------------------------------------------------------------------------\n// Store factory — selects DataStore backend based on config\n// ---------------------------------------------------------------------------\n\nimport type { VizzorConfig } from '../config/schema.js';\nimport type { DataStore } from './types.js';\nimport { SqliteStore } from './sqlite-store.js';\n\nlet instance: DataStore | null = null;\n\nexport async function getStore(config: VizzorConfig): Promise<DataStore> {\n if (instance) return instance;\n\n if (config.database?.type === 'postgres' && config.database.url) {\n const { PostgresStore } = await import('./postgres-store.js');\n instance = new PostgresStore(config.database.url);\n } else {\n instance = new SqliteStore();\n }\n\n return instance;\n}\n\nexport function getStoreInstance(): DataStore | null {\n return instance;\n}\n","// ---------------------------------------------------------------------------\n// Shared tool handler — bridges AI tool-use to Vizzor core modules\n// Extracted from TUI for reuse by Telegram, Discord, and CLI bots.\n// ---------------------------------------------------------------------------\n\nimport { getAdapter } from '../chains/registry.js';\nimport { getConfig } from '../config/loader.js';\nimport { DEFAULT_CHAIN } from '../config/constants.js';\nimport { analyzeWallet } from '../core/forensics/wallet-analyzer.js';\nimport { detectRugIndicators } from '../core/forensics/rug-detector.js';\nimport { fetchMarketData, fetchTokenFromDex, fetchTrendingTokens } from '../core/trends/market.js';\nimport {\n fetchUpcomingICOs,\n searchICOs,\n getProjectFundingHistory,\n getInvestorPortfolio,\n} from '../core/scanner/ico-tracker.js';\nimport { fetchCryptoNews } from '../data/sources/cryptopanic.js';\nimport { fetchRecentRaises } from '../data/sources/defillama.js';\nimport { fetchTickerPrice, fetchFundingRate, fetchOpenInterest } from '../data/sources/binance.js';\nimport { checkTokenSecurity } from '../data/sources/goplus.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { analyzeTechnicals } from '../core/technical-analysis/index.js';\nimport { generatePrediction } from '../core/trends/predictor.js';\nimport { detectMarketRegime } from '../core/trends/regime.js';\nimport { analyzeProject } from '../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../core/scanner/risk-scorer.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n getAgentStatus,\n getRecentDecisions,\n} from '../core/agent/index.js';\nimport { getMLClient, initMLClient } from '../ml/client.js';\nimport { buildFeatureVector } from '../ml/feature-engineer.js';\nimport { getStoreInstance } from '../data/store-factory.js';\n\nexport async function handleTool(name: string, input: unknown): Promise<unknown> {\n const params = input as Record<string, unknown>;\n\n switch (name) {\n case 'get_token_info': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const info = await adapter.getTokenInfo(address);\n return {\n address: info.address,\n name: info.name,\n symbol: info.symbol,\n decimals: info.decimals,\n totalSupply: info.totalSupply.toString(),\n };\n }\n\n case 'analyze_wallet': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(address, adapter);\n return {\n address: analysis.address,\n chain: analysis.chain,\n balance: analysis.balance.toString(),\n transactionCount: analysis.transactionCount,\n riskLevel: analysis.riskLevel,\n patterns: analysis.patterns,\n };\n }\n\n case 'check_rug_indicators': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const indicators = await detectRugIndicators(address, adapter);\n return {\n isHoneypot: indicators.isHoneypot,\n hasLiquidityLock: indicators.hasLiquidityLock,\n ownerCanMint: indicators.ownerCanMint,\n ownerCanPause: indicators.ownerCanPause,\n hasBlacklist: indicators.hasBlacklist,\n highSellTax: indicators.highSellTax,\n riskScore: indicators.riskScore,\n details: indicators.details,\n };\n }\n\n case 'get_market_data': {\n const symbol = String(params['symbol'] ?? '');\n // Try Binance first (reliable, no rate limits), enrich with CoinGecko\n try {\n const binance = await fetchTickerPrice(symbol);\n const gecko = await fetchMarketData(symbol).catch(() => null);\n return {\n symbol: binance.symbol,\n name: gecko?.name ?? binance.symbol,\n price: binance.price,\n priceChange24h: binance.change24h,\n priceChange7d: gecko?.priceChange7d ?? null,\n volume24h: gecko?.volume24h ?? null,\n marketCap: gecko?.marketCap ?? null,\n rank: gecko?.rank ?? null,\n source: 'binance+coingecko',\n };\n } catch {\n // Fallback to CoinGecko only\n const data = await fetchMarketData(symbol);\n if (!data) {\n return { error: `No market data found for \"${symbol}\"` };\n }\n return data;\n }\n }\n\n case 'search_upcoming_icos': {\n const category = params['category'] ? String(params['category']) : undefined;\n const chain = params['chain'] ? String(params['chain']) : undefined;\n const roundType = params['roundType'] ? String(params['roundType']) : undefined;\n const projects =\n category || chain || roundType\n ? await searchICOs(undefined, category, chain, roundType)\n : await fetchUpcomingICOs();\n return {\n projects: projects.map((p) => ({\n name: p.name,\n category: p.category,\n chain: p.chain,\n roundType: p.roundType,\n raisedAmount: p.raisedAmount,\n valuation: p.valuation,\n investors: p.investors.slice(0, 5),\n startDate: p.startDate,\n description: p.description,\n website: p.website,\n })),\n };\n }\n\n case 'get_funding_history': {\n const fundingName = String(params['name'] ?? '');\n const type = String(params['type'] ?? 'project');\n if (type === 'investor') {\n const portfolio = await getInvestorPortfolio(fundingName);\n return {\n investor: fundingName,\n investments: portfolio.map((p) => ({\n name: p.name,\n round: p.roundType,\n amount: p.raisedAmount,\n chain: p.chain,\n category: p.category,\n date: p.startDate,\n })),\n };\n }\n const history = await getProjectFundingHistory(fundingName);\n return {\n project: history.name,\n rounds: history.rounds.map((r) => ({\n round: r.roundType,\n amount: r.raisedAmount,\n valuation: r.valuation,\n investors: r.investors.slice(0, 5),\n date: r.startDate,\n previousRounds: r.previousRounds,\n })),\n };\n }\n\n case 'search_token_dex': {\n const query = String(params['query'] ?? '');\n const pairs = await fetchTokenFromDex(query);\n return {\n results: pairs.slice(0, 5).map((p) => ({\n name: p.baseToken.name,\n symbol: p.baseToken.symbol,\n chain: p.chainId,\n dex: p.dexId,\n priceUsd: p.priceUsd,\n volume24h: p.volume?.h24 ?? 0,\n liquidity: p.liquidity?.usd ?? 0,\n priceChange24h: p.priceChange?.h24 ?? 0,\n marketCap: p.marketCap ?? p.fdv ?? null,\n buys24h: p.txns?.h24?.buys ?? 0,\n sells24h: p.txns?.h24?.sells ?? 0,\n pairAddress: p.pairAddress,\n url: p.url,\n })),\n };\n }\n\n case 'get_trending': {\n const trending = await fetchTrendingTokens();\n return {\n trending: trending.slice(0, 10).map((t) => ({\n name: t.name,\n symbol: t.symbol,\n chain: t.chain,\n priceUsd: t.priceUsd,\n priceChange24h: t.priceChange24h,\n volume24h: t.volume24h,\n marketCap: t.marketCap,\n source: t.source,\n url: t.url,\n })),\n };\n }\n\n case 'get_crypto_news': {\n const symbol = params['symbol'] ? String(params['symbol']) : undefined;\n const news = await fetchCryptoNews(symbol, getConfig().cryptopanicApiKey);\n return {\n news: news.slice(0, 10).map((n) => ({\n title: n.title,\n sentiment: n.sentiment,\n source: n.source.title,\n publishedAt: n.publishedAt,\n url: n.url,\n })),\n };\n }\n\n case 'get_raises': {\n const raises = await fetchRecentRaises(30);\n let filtered = raises;\n if (params['category']) {\n const cat = String(params['category']).toLowerCase();\n filtered = filtered.filter(\n (r) => r.category?.toLowerCase().includes(cat) || r.sector?.toLowerCase().includes(cat),\n );\n }\n if (params['chain']) {\n const ch = String(params['chain']).toLowerCase();\n filtered = filtered.filter((r) => r.chains.some((c) => c.toLowerCase().includes(ch)));\n }\n return {\n raises: filtered.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n sector: r.sector,\n category: r.category,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0],\n })),\n };\n }\n\n case 'get_token_security': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? 'ethereum');\n const security = await checkTokenSecurity(address, chain);\n if (!security) {\n return { error: `No security data for ${address} on ${chain}` };\n }\n return {\n contractAddress: security.contractAddress,\n chain: security.chain,\n riskLevel: security.riskLevel,\n isHoneypot: security.isHoneypot,\n isMintable: security.isMintable,\n buyTax: security.buyTax,\n sellTax: security.sellTax,\n isOpenSource: security.isOpenSource,\n isProxy: security.isProxy,\n hiddenOwner: security.hiddenOwner,\n cannotBuy: security.cannotBuy,\n cannotSellAll: security.cannotSellAll,\n isBlacklisted: security.isBlacklisted,\n holderCount: security.holderCount,\n lpHolderCount: security.lpHolderCount,\n creatorPercent: security.creatorPercent,\n ownerPercent: security.ownerPercent,\n trustList: security.trustList,\n };\n }\n\n case 'get_fear_greed': {\n const data = await fetchFearGreedIndex(7);\n return {\n current: { value: data.current.value, classification: data.current.classification },\n previous: data.previous\n ? { value: data.previous.value, classification: data.previous.classification }\n : null,\n history: data.history.map((h) => ({\n value: h.value,\n classification: h.classification,\n date: new Date(h.timestamp * 1000).toISOString().split('T')[0],\n })),\n };\n }\n\n case 'get_derivatives_data': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const [fundingResult, oiResult] = await Promise.allSettled([\n fetchFundingRate(symbol),\n fetchOpenInterest(symbol),\n ]);\n\n const result: Record<string, unknown> = { symbol: symbol.toUpperCase() };\n if (fundingResult.status === 'fulfilled') {\n result['fundingRate'] = fundingResult.value.fundingRate;\n result['fundingRatePct'] = `${(fundingResult.value.fundingRate * 100).toFixed(4)}%`;\n result['markPrice'] = fundingResult.value.markPrice;\n }\n if (oiResult.status === 'fulfilled') {\n result['openInterest'] = oiResult.value.openInterest;\n result['openInterestNotional'] = oiResult.value.notionalValue;\n }\n return result;\n }\n\n case 'get_technical_analysis': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const timeframe = String(params['timeframe'] ?? '4h');\n const ta = await analyzeTechnicals(symbol, timeframe);\n return {\n symbol: ta.symbol,\n timeframe: ta.timeframe,\n composite: ta.composite,\n signals: ta.signals.map((s) => ({\n name: s.name,\n signal: s.signal,\n strength: s.strength,\n description: s.description,\n })),\n indicators: {\n rsi: ta.indicators.rsi ? Math.round(ta.indicators.rsi * 100) / 100 : null,\n macd: ta.indicators.macd,\n bollingerBands: ta.indicators.bollingerBands,\n ema12: ta.indicators.ema12,\n ema26: ta.indicators.ema26,\n atr: ta.indicators.atr,\n },\n };\n }\n\n case 'get_prediction': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const prediction = await generatePrediction(symbol);\n return {\n symbol: prediction.symbol,\n direction: prediction.direction,\n confidence: prediction.confidence,\n composite: prediction.composite,\n timeframe: prediction.timeframe,\n signals: prediction.signals,\n reasoning: prediction.reasoning,\n disclaimer: prediction.disclaimer,\n };\n }\n\n case 'get_ml_prediction': {\n const symbol = String(params['symbol'] ?? 'BTC');\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n // Config not loaded\n }\n }\n if (!mlClient) {\n // Fallback to rule-based prediction\n const prediction = await generatePrediction(symbol);\n return {\n ...prediction,\n mlAvailable: false,\n note: 'ML sidecar not configured; using rule-based prediction',\n };\n }\n const features = await buildFeatureVector(symbol);\n const mlPred = await mlClient.predict(features);\n if (!mlPred) {\n const prediction = await generatePrediction(symbol);\n return {\n ...prediction,\n mlAvailable: false,\n note: 'ML sidecar unavailable; using rule-based prediction',\n };\n }\n return {\n symbol: mlPred.symbol,\n direction: mlPred.direction,\n probability: mlPred.probability,\n confidence: mlPred.confidence,\n model: mlPred.model,\n horizon: mlPred.horizon,\n mlAvailable: true,\n features: {\n rsi: features.rsi,\n macdHistogram: features.macdHistogram,\n bollingerPercentB: features.bollingerPercentB,\n fundingRate: features.fundingRate,\n fearGreed: features.fearGreed,\n rsiSlope: features.rsiSlope,\n volumeRatio: features.volumeRatio,\n emaCrossoverPct: features.emaCrossoverPct,\n atrPct: features.atrPct,\n },\n };\n }\n\n case 'get_model_accuracy': {\n const model = String(params['model'] ?? 'lstm-predictor');\n const days = params['days'] ? Number(params['days']) : 30;\n const store = getStoreInstance();\n if (!store) {\n return { error: 'DataStore not initialized. ML accuracy requires PostgreSQL backend.' };\n }\n const accuracy = await store.getPredictionAccuracy(model, days);\n return {\n model: accuracy.model,\n period: accuracy.period,\n totalPredictions: accuracy.totalPredictions,\n correctPredictions: accuracy.correctPredictions,\n accuracy: `${(accuracy.accuracy * 100).toFixed(1)}%`,\n byDirection: {\n up: `${(accuracy.byDirection.up.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.up.correct}/${accuracy.byDirection.up.total})`,\n down: `${(accuracy.byDirection.down.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.down.correct}/${accuracy.byDirection.down.total})`,\n sideways: `${(accuracy.byDirection.sideways.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.sideways.correct}/${accuracy.byDirection.sideways.total})`,\n },\n };\n }\n\n case 'get_rug_ml_analysis': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n // Run both bytecode analysis + ML\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const indicators = await detectRugIndicators(address, adapter);\n\n // Also get GoPlus security data for enrichment\n let goplus = null;\n try {\n goplus = await checkTokenSecurity(address, chain);\n } catch {\n /* GoPlus unavailable */\n }\n\n // Call ML rug detector directly with enriched features\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n let mlResult = indicators.mlAnalysis ?? null;\n if (!mlResult && mlClient && goplus) {\n mlResult =\n (await mlClient.predictRug({\n bytecode_size: 0,\n is_verified: goplus.isOpenSource ? 1 : 0,\n holder_concentration: (goplus.creatorPercent ?? 0) + (goplus.ownerPercent ?? 0),\n has_proxy: goplus.isProxy ? 1 : 0,\n has_mint: goplus.isMintable ? 1 : 0,\n has_pause: indicators.ownerCanPause ? 1 : 0,\n has_blacklist: indicators.hasBlacklist ? 1 : 0,\n liquidity_locked: 0,\n buy_tax: goplus.buyTax ?? 0,\n sell_tax: goplus.sellTax ?? 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: goplus.ownerPercent ?? 0,\n is_open_source: goplus.isOpenSource ? 1 : 0,\n top10_holder_pct: 0,\n })) ?? null;\n }\n\n return {\n address,\n chain,\n ruleBasedRiskScore: indicators.riskScore,\n mlAnalysis: mlResult ?? { note: 'ML sidecar not available' },\n indicators: {\n isHoneypot: indicators.isHoneypot,\n ownerCanMint: indicators.ownerCanMint,\n ownerCanPause: indicators.ownerCanPause,\n hasBlacklist: indicators.hasBlacklist,\n highSellTax: indicators.highSellTax,\n },\n details: indicators.details,\n goplus: goplus\n ? {\n riskLevel: goplus.riskLevel,\n buyTax: goplus.buyTax,\n sellTax: goplus.sellTax,\n isHoneypot: goplus.isHoneypot,\n isMintable: goplus.isMintable,\n holderCount: goplus.holderCount,\n }\n : null,\n };\n }\n\n case 'get_wallet_behavior': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(address, adapter);\n return {\n address: analysis.address,\n chain: analysis.chain,\n balance: analysis.balance.toString(),\n transactionCount: analysis.transactionCount,\n riskLevel: analysis.riskLevel,\n patterns: analysis.patterns,\n mlBehavior: analysis.mlBehavior ?? { note: 'ML sidecar not available' },\n };\n }\n\n case 'analyze_news_sentiment': {\n const symbol = String(params['symbol'] ?? '');\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n const news = await fetchCryptoNews(symbol || undefined, getConfig().cryptopanicApiKey);\n if (news.length === 0) {\n return { symbol, sentiment: 'neutral', note: 'No news found' };\n }\n\n const headlines = news.slice(0, 10).map((n) => n.title);\n\n if (mlClient) {\n const results = await mlClient.analyzeSentimentBatch(headlines);\n if (results.length > 0) {\n const avgScore = results.reduce((s, r) => s + r.score, 0) / results.length;\n const avgConf = results.reduce((s, r) => s + r.confidence, 0) / results.length;\n const allTopics = [...new Set(results.flatMap((r) => r.key_topics))];\n return {\n symbol,\n sentiment: avgScore > 0.2 ? 'bullish' : avgScore < -0.2 ? 'bearish' : 'neutral',\n score: Math.round(avgScore * 1000) / 1000,\n confidence: Math.round(avgConf * 100),\n topics: allTopics.slice(0, 5),\n headlines: results.map((r, i) => ({\n title: headlines[i],\n sentiment: r.sentiment,\n score: r.score,\n confidence: r.confidence,\n })),\n model: results[0]?.model ?? 'unknown',\n articleCount: news.length,\n };\n }\n }\n\n // Fallback: vote-based sentiment\n let pos = 0;\n let neg = 0;\n for (const n of news) {\n if (n.sentiment === 'positive') pos++;\n else if (n.sentiment === 'negative') neg++;\n }\n const score = news.length > 0 ? (pos - neg) / news.length : 0;\n return {\n symbol,\n sentiment: score > 0.2 ? 'bullish' : score < -0.2 ? 'bearish' : 'neutral',\n score,\n confidence: 50,\n topics: [],\n headlines: headlines.map((h, i) => ({\n title: h,\n sentiment: news[i]?.sentiment ?? 'neutral',\n })),\n model: 'vote-count-fallback',\n articleCount: news.length,\n };\n }\n\n case 'get_market_regime': {\n const symbol = String(params['symbol'] ?? 'BTC');\n // Fetch indicators needed for regime detection\n const ta = await analyzeTechnicals(symbol, '4h');\n const [fgResult, fundingResult] = await Promise.allSettled([\n fetchFearGreedIndex(1),\n fetchFundingRate(symbol),\n ]);\n const fg = fgResult.status === 'fulfilled' ? fgResult.value.current.value : 50;\n const funding = fundingResult.status === 'fulfilled' ? fundingResult.value.fundingRate : 0;\n const price = ta.indicators.ema12 ?? 0;\n const atrVal = ta.indicators.atr ?? 0;\n const atrPct = price > 0 ? (atrVal / price) * 100 : 3;\n\n const regime = await detectMarketRegime(symbol, {\n returns_1d: 0,\n returns_7d: 0,\n volatility_14d: atrPct,\n volume_ratio: 1,\n rsi: ta.indicators.rsi ?? 50,\n bb_width: ta.indicators.bollingerBands\n ? ((ta.indicators.bollingerBands.upper - ta.indicators.bollingerBands.lower) /\n ta.indicators.bollingerBands.middle) *\n 100\n : 0,\n fear_greed: fg,\n funding_rate: funding,\n price_vs_sma200: 0,\n });\n\n return {\n symbol: symbol.toUpperCase(),\n regime: regime.regime,\n confidence: regime.confidence,\n probabilities: regime.probabilities,\n model: regime.model,\n };\n }\n\n case 'get_ta_ml_analysis': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const timeframe = String(params['timeframe'] ?? '4h');\n const ta = await analyzeTechnicals(symbol, timeframe);\n return {\n symbol: ta.symbol,\n timeframe: ta.timeframe,\n composite: ta.composite,\n signals: ta.signals.map((s) => ({\n name: s.name,\n signal: s.signal,\n strength: s.strength,\n description: s.description,\n })),\n indicators: {\n rsi: ta.indicators.rsi ? Math.round(ta.indicators.rsi * 100) / 100 : null,\n macd: ta.indicators.macd,\n bollingerBands: ta.indicators.bollingerBands,\n ema12: ta.indicators.ema12,\n ema26: ta.indicators.ema26,\n atr: ta.indicators.atr,\n },\n note: 'ML-enhanced: signals and composite use learned weights when ML sidecar is available',\n };\n }\n\n case 'get_project_risk_ml': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeProject(address, adapter);\n const risk = assessRisk(analysis);\n return {\n address,\n chain,\n riskScore: risk.score,\n riskLevel: risk.level,\n summary: risk.summary,\n factors: risk.factors,\n mlScore: risk.mlScore ?? null,\n mlLevel: risk.mlLevel ?? null,\n token: analysis.token\n ? {\n name: analysis.token.name,\n symbol: analysis.token.symbol,\n decimals: analysis.token.decimals,\n }\n : null,\n holderConcentration: analysis.holderConcentration,\n contractVerified: analysis.contractVerified,\n };\n }\n\n case 'get_portfolio_forecast': {\n const agentName = String(params['agentName'] ?? '');\n const agent = getAgentByName(agentName);\n if (!agent) return { error: `Agent \"${agentName}\" not found` };\n // Forecast requires trade history — currently we return a placeholder\n // since the full trade store integration is agent-specific\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (!mlClient) {\n return {\n agentName,\n error: 'ML sidecar not available for portfolio forecast',\n };\n }\n\n // Use agent state for basic forecast\n const state = getAgentStatus(agent.id);\n return {\n agentName,\n status: state?.status ?? 'idle',\n cycleCount: state?.cycleCount ?? 0,\n note: 'Portfolio forecast requires trade history. Use calculateMetricsWithForecast() in agent engine for full predictions.',\n };\n }\n\n case 'create_agent': {\n const agentName = String(params['name'] ?? '');\n const strategy = String(params['strategy'] ?? 'momentum');\n const pairsRaw = String(params['pairs'] ?? 'BTC,ETH');\n const interval = params['interval'] ? Number(params['interval']) : 60;\n const agentPairs = pairsRaw.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(agentName, strategy, agentPairs, interval);\n return {\n id: agent.id,\n name: agent.name,\n strategy: agent.strategy,\n pairs: agent.pairs,\n interval: agent.interval,\n message: `Agent \"${agent.name}\" created. Use /agent start ${agent.name} to activate.`,\n };\n }\n\n case 'list_agents': {\n const agents = listAgents();\n return {\n agents: agents.map((a) => {\n const status = getAgentStatus(a.id);\n return {\n name: a.name,\n strategy: a.strategy,\n pairs: a.pairs,\n interval: a.interval,\n status: status?.status ?? 'idle',\n cycleCount: status?.cycleCount ?? 0,\n };\n }),\n };\n }\n\n case 'get_agent_status': {\n const agentName = String(params['name'] ?? '');\n const agent = getAgentByName(agentName);\n if (!agent) return { error: `Agent \"${agentName}\" not found` };\n const state = getAgentStatus(agent.id);\n if (!state) return { error: `Agent \"${agentName}\" not found` };\n const decisions = getRecentDecisions(agent.id, 5);\n return {\n name: state.config.name,\n status: state.status,\n strategy: state.config.strategy,\n pairs: state.config.pairs,\n cycleCount: state.cycleCount,\n error: state.error,\n recentDecisions: decisions.map((d) => ({\n symbol: d.symbol,\n action: d.decision.action,\n confidence: d.decision.confidence,\n reasoning: d.decision.reasoning,\n timestamp: new Date(d.timestamp).toISOString(),\n })),\n };\n }\n\n default:\n return { error: `Unknown tool: ${name}` };\n }\n}\n","// ---------------------------------------------------------------------------\n// Vizzor tool definitions for AI tool-use (provider-agnostic)\n// ---------------------------------------------------------------------------\n\nimport type { AITool } from './providers/types.js';\n\n/**\n * Tool definitions that Vizzor exposes to AI providers during chat and\n * analysis sessions. Each tool maps to a concrete handler registered via\n * {@link setToolHandler} in the AI client.\n *\n * Uses the provider-agnostic {@link AITool} type (JSON Schema format).\n * Provider implementations convert to their SDK-specific format internally.\n */\nexport const VIZZOR_TOOLS: AITool[] = [\n {\n name: 'get_token_info',\n description:\n 'Get on-chain token information including name, symbol, decimals, total supply, and top holders for a given contract address and chain.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address (e.g. 0x...).',\n },\n chain: {\n type: 'string',\n description: 'The blockchain to query (e.g. \"ethereum\", \"bsc\", \"polygon\", \"arbitrum\").',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'analyze_wallet',\n description:\n 'Analyze a wallet address for transaction patterns, token holdings, DeFi interactions, and behavioral signals such as accumulation or distribution phases.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The wallet address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the wallet resides on (e.g. \"ethereum\", \"bsc\").',\n },\n depth: {\n type: 'number',\n description: 'How many recent transactions to inspect. Defaults to 100.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'check_rug_indicators',\n description:\n 'Check a token for common rug pull indicators including honeypot detection, liquidity locks, ownership status, hidden mints, and holder concentration.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to check.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_market_data',\n description:\n 'Get LIVE current market data for a token including price, 24h volume, market cap, price change percentages, and circulating supply. Returns real-time data — never quote prices from training data.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token ticker symbol (e.g. \"ETH\", \"BTC\", \"UNI\").',\n },\n currency: {\n type: 'string',\n description: 'The fiat currency for price quotes. Defaults to \"usd\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'search_upcoming_icos',\n description:\n 'Search for CURRENT upcoming ICOs, token launches, and fundraising rounds filtered by category, blockchain, or round type. Returns LIVE data from DeFiLlama raises and Pump.fun launches, updated daily. MUST call for any ICO/launch question — training data is stale.',\n input_schema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by project category (e.g. \"defi\", \"gaming\", \"infrastructure\", \"nft\", \"ai\").',\n },\n chain: {\n type: 'string',\n description: 'Filter by blockchain (e.g. \"ethereum\", \"solana\", \"bsc\").',\n },\n roundType: {\n type: 'string',\n description:\n 'Filter by funding round type (e.g. \"Seed\", \"Pre-Seed\", \"Series A\", \"Series B\", \"Token Launch\").',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return. Defaults to 10.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_funding_history',\n description:\n 'Get complete funding history for a project by name. Returns all known fundraising rounds with amounts, investors, valuations, and dates. Also works for looking up an investor portfolio.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'Project name or investor name to look up.',\n },\n type: {\n type: 'string',\n description:\n 'Type of lookup: \"project\" for project funding history, \"investor\" for investor portfolio. Defaults to \"project\".',\n },\n },\n required: ['name'],\n },\n },\n {\n name: 'search_token_dex',\n description:\n 'Search for any token on decentralized exchanges via DexScreener. Returns real-time price, volume, liquidity, buy/sell counts, pair info. Works for all tokens including meme coins and newly launched tokens.',\n input_schema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description: 'Token name, symbol, or contract address to search for.',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'get_trending',\n description:\n 'Get REAL-TIME trending and hot tokens from DexScreener (boosted tokens) and CoinGecko trending combined. Returns what the market is excited about RIGHT NOW — trends change hourly. Always call for trending/hot token questions.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_crypto_news',\n description:\n 'Get LIVE latest crypto news with sentiment analysis for a specific token or the market in general. Returns current headlines from CryptoPanic — MUST call for news questions, training data is outdated.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description:\n 'Token symbol to filter news for (e.g. \"BTC\", \"ETH\", \"SOL\"). Omit for general crypto news.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_raises',\n description:\n 'Get LIVE recent crypto fundraising rounds, venture capital investments, and token launches. Returns CURRENT data updated daily from DeFiLlama — always call this for ICO/funding questions, never use training data.',\n input_schema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description: 'Filter by sector/category (e.g. \"defi\", \"infrastructure\", \"gaming\").',\n },\n chain: {\n type: 'string',\n description: 'Filter by blockchain (e.g. \"ethereum\", \"solana\").',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_token_security',\n description:\n 'Check token security via GoPlus API. Returns honeypot detection, tax analysis, mint/pause/blacklist capabilities, holder stats, and overall risk level. No API key required.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain (e.g. \"ethereum\", \"bsc\", \"polygon\", \"arbitrum\", \"base\").',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_fear_greed',\n description:\n 'Get the LIVE Crypto Fear & Greed Index with 7-day history (updated daily). Values: 0-20 Extreme Fear, 21-40 Fear, 41-60 Neutral, 61-80 Greed, 81-100 Extreme Greed. Call for any market sentiment question.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_derivatives_data',\n description:\n 'Get LIVE derivatives data from Binance Futures: funding rate (updates every 8h), open interest, and mark price for a trading pair. Essential for current market positioning analysis.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_technical_analysis',\n description:\n 'Run technical analysis on a token: RSI, MACD, Bollinger Bands, EMA crossovers, ATR, OBV. Returns individual indicator signals and a composite direction with confidence.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n timeframe: {\n type: 'string',\n description: 'Kline interval: \"1h\", \"4h\", \"1d\". Defaults to \"4h\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_prediction',\n description:\n 'Generate a multi-signal composite prediction combining technical analysis (40%), sentiment (20%), derivatives (20%), trend (15%), and macro (5%). Returns direction, confidence, composite score, and reasoning.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_ml_prediction',\n description:\n 'Get an ML-enhanced prediction using LSTM/Random Forest models from the ML sidecar. Returns direction, probability, model confidence, and feature importance. Falls back to rule-based prediction if ML sidecar is unavailable.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_model_accuracy',\n description:\n 'Get historical accuracy metrics for ML prediction models. Shows total predictions, accuracy percentage, and breakdown by direction (up/down/sideways).',\n input_schema: {\n type: 'object' as const,\n properties: {\n model: {\n type: 'string',\n description:\n 'Model name (e.g. \"lstm-predictor\", \"signal-classifier\"). Defaults to \"lstm-predictor\".',\n },\n days: {\n type: 'number',\n description: 'Number of days to look back for accuracy stats. Defaults to 30.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_rug_ml_analysis',\n description:\n 'Run ML-powered rug pull analysis on a token. Uses Gradient Boosted classifier trained on historical rug patterns to predict rug probability, risk level, and key risk factors. Enhanced version of check_rug_indicators with ML scoring.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_wallet_behavior',\n description:\n 'ML-powered wallet behavior classification. Uses LSTM model to classify a wallet as: normal_trader, bot, whale, sniper, mev_bot, mixer_user, or rug_deployer. Returns behavior type, confidence, risk score, and behavioral indicators.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The wallet address to classify.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the wallet is on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'analyze_news_sentiment',\n description:\n 'ML-powered NLP sentiment analysis on crypto news. Uses DistilBERT model to analyze news headlines for a token, returning bullish/bearish/neutral sentiment, confidence score, and detected topics (regulation, defi, security, etc.).',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'Token symbol to analyze news sentiment for (e.g. \"BTC\", \"ETH\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_market_regime',\n description:\n 'Detect the current market regime using ML Hidden Markov Model. Returns regime type (trending_bull, trending_bear, ranging, volatile, capitulation), confidence, and probability distribution across all regimes. Uses HMM when available, falls back to heuristic analysis.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_ta_ml_analysis',\n description:\n 'Run ML-enhanced technical analysis with learned signal weights. Uses Random Forest to interpret RSI, MACD, Bollinger Bands, EMA crossover, ATR, OBV simultaneously. Returns signals with ML-derived importance weights and composite direction. More accurate than static weight TA.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n timeframe: {\n type: 'string',\n description: 'Kline interval: \"1h\", \"4h\", \"1d\". Defaults to \"4h\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_project_risk_ml',\n description:\n 'Run ML-powered project risk scoring on a token. Uses GBM classifier trained on contract features (verification, holder concentration, taxes, mint/pause/blacklist capabilities) to predict overall project risk probability and identify top risk factors.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_portfolio_forecast',\n description:\n 'Generate forward-looking portfolio performance predictions using ML. Analyzes trade history to predict next-period return, Sharpe ratio, and max drawdown. Requires at least 10 completed trades.',\n input_schema: {\n type: 'object' as const,\n properties: {\n agentName: {\n type: 'string',\n description: 'The trading agent name to forecast for.',\n },\n },\n required: ['agentName'],\n },\n },\n {\n name: 'create_agent',\n description:\n 'Create an autonomous trading agent that monitors crypto pairs using a strategy (momentum or trend-following). Returns the created agent config.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'A unique name for the agent (e.g. \"btc-momentum-bot\").',\n },\n strategy: {\n type: 'string',\n description:\n 'Trading strategy: \"momentum\" (RSI+MACD) or \"trend-following\" (EMA crossover).',\n },\n pairs: {\n type: 'string',\n description: 'Comma-separated trading pairs (e.g. \"BTC,ETH,SOL\").',\n },\n interval: {\n type: 'number',\n description: 'Cycle interval in seconds. Defaults to 60.',\n },\n },\n required: ['name', 'strategy', 'pairs'],\n },\n },\n {\n name: 'list_agents',\n description:\n 'List all created trading agents with their status, strategy, and monitored pairs.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_agent_status',\n description:\n 'Get detailed status of a trading agent including cycle count, last decision, and recent trade signals.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'The agent name.',\n },\n },\n required: ['name'],\n },\n },\n];\n","// ---------------------------------------------------------------------------\n// Message splitting for platform character limits\n// Telegram: 4096 chars, Discord: 2000 chars\n// ---------------------------------------------------------------------------\n\nexport function splitMessage(text: string, maxLen: number): string[] {\n if (text.length <= maxLen) return [text];\n\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= maxLen) {\n chunks.push(remaining);\n break;\n }\n\n // Try to split at paragraph, then newline, then space, then hard cut\n let splitAt = remaining.lastIndexOf('\\n\\n', maxLen);\n if (splitAt <= 0) splitAt = remaining.lastIndexOf('\\n', maxLen);\n if (splitAt <= 0) splitAt = remaining.lastIndexOf(' ', maxLen);\n if (splitAt <= 0) splitAt = maxLen;\n\n chunks.push(remaining.slice(0, splitAt));\n remaining = remaining.slice(splitAt).trimStart();\n }\n\n return chunks;\n}\n","// ---------------------------------------------------------------------------\n// Per-user rate limiting for Discord bot interactions\n// ---------------------------------------------------------------------------\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nconst userLimits = new Map<string, RateLimitEntry>();\n\nconst MAX_REQUESTS = 10;\nconst WINDOW_MS = 60_000; // 1 minute\n\n/**\n * Check whether a user is within the rate limit window.\n * Returns `{ allowed: true }` if the request should proceed,\n * `{ allowed: false }` if the user has exceeded the limit.\n */\nexport function checkRateLimit(userId: string): { allowed: boolean } {\n const now = Date.now();\n const entry = userLimits.get(userId);\n\n if (!entry || now >= entry.resetAt) {\n userLimits.set(userId, { count: 1, resetAt: now + WINDOW_MS });\n return { allowed: true };\n }\n\n if (entry.count >= MAX_REQUESTS) {\n return { allowed: false };\n }\n\n entry.count++;\n return { allowed: true };\n}\n\n/**\n * Clean up expired entries periodically to prevent memory leaks.\n */\nexport function startRateLimitCleanup(intervalMs = 300_000): ReturnType<typeof setInterval> {\n return setInterval(() => {\n const now = Date.now();\n for (const [userId, entry] of userLimits) {\n if (now >= entry.resetAt) {\n userLimits.delete(userId);\n }\n }\n }, intervalMs);\n}\n","import { SlashCommandBuilder, type ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\nimport { fetchTrendingTokens } from '../../core/trends/market.js';\nimport { fetchUpcomingICOs } from '../../core/scanner/ico-tracker.js';\nimport { fetchRecentRaises } from '../../data/sources/defillama.js';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n deleteAgent,\n getWalletBalance,\n isValidAddress,\n} from '../../core/agent/index.js';\nimport { checkRateLimit } from '../middleware/rate-limit.js';\n\nexport function registerSlashCommands(): object[] {\n return [\n // Core commands\n new SlashCommandBuilder()\n .setName('scan')\n .setDescription('Analyze a crypto project')\n .addStringOption((opt) =>\n opt.setName('project').setDescription('Project name or contract address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('trends')\n .setDescription('Trending tokens + market data')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('track')\n .setDescription('Analyze a wallet')\n .addStringOption((opt) =>\n opt.setName('wallet').setDescription('Wallet address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('ico')\n .setDescription('Upcoming ICOs & fundraising rounds')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('audit')\n .setDescription('Audit a smart contract')\n .addStringOption((opt) =>\n opt.setName('contract').setDescription('Contract address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder().setName('help').setDescription('Show all Vizzor commands').toJSON(),\n\n // Quick commands\n new SlashCommandBuilder()\n .setName('price')\n .setDescription('Quick price check')\n .addStringOption((opt) =>\n opt.setName('symbol').setDescription('Token symbol (e.g. BTC, ETH)').setRequired(true),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('predict')\n .setDescription('AI prediction with multi-signal analysis')\n .addStringOption((opt) =>\n opt.setName('symbol').setDescription('Token symbol (e.g. BTC, ETH)').setRequired(true),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('wallet')\n .setDescription('Check wallet balance')\n .addStringOption((opt) =>\n opt.setName('address').setDescription('Ethereum address').setRequired(true),\n )\n .toJSON(),\n\n // Agent commands\n new SlashCommandBuilder()\n .setName('agent_create')\n .setDescription('Create a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .addStringOption((opt) =>\n opt\n .setName('strategy')\n .setDescription('Strategy (momentum, trend-following)')\n .setRequired(false),\n )\n .addStringOption((opt) =>\n opt\n .setName('pairs')\n .setDescription('Comma-separated pairs (e.g. BTC,ETH,SOL)')\n .setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_list')\n .setDescription('List all trading agents')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_start')\n .setDescription('Start a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_stop')\n .setDescription('Stop a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_status')\n .setDescription('View agent status & recent decisions')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_delete')\n .setDescription('Delete a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n ];\n}\n\nexport async function handleSlashCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const { commandName } = interaction;\n\n // Rate limiting\n const { allowed } = checkRateLimit(interaction.user.id);\n if (!allowed) {\n await interaction.reply({\n content: 'Rate limited. Please wait a moment before sending more commands.',\n ephemeral: true,\n });\n return;\n }\n\n try {\n switch (commandName) {\n case 'scan':\n await handleScanCommand(interaction);\n break;\n case 'trends':\n await handleTrendsCommand(interaction);\n break;\n case 'track':\n await handleTrackCommand(interaction);\n break;\n case 'ico':\n await handleIcoCommand(interaction);\n break;\n case 'audit':\n await handleAuditCommand(interaction);\n break;\n case 'help':\n await handleHelpCommand(interaction);\n break;\n case 'price':\n await handlePriceCommand(interaction);\n break;\n case 'predict':\n await handlePredictCommand(interaction);\n break;\n case 'wallet':\n await handleWalletCommand(interaction);\n break;\n case 'agent_create':\n await handleAgentCreateCommand(interaction);\n break;\n case 'agent_list':\n await handleAgentListCommand(interaction);\n break;\n case 'agent_start':\n await handleAgentStartCommand(interaction);\n break;\n case 'agent_stop':\n await handleAgentStopCommand(interaction);\n break;\n case 'agent_status':\n await handleAgentStatusCommand(interaction);\n break;\n case 'agent_delete':\n await handleAgentDeleteCommand(interaction);\n break;\n default:\n await interaction.reply({\n content: `Unknown command: \\`/${commandName}\\`. Use \\`/help\\` for available commands.`,\n ephemeral: true,\n });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const reply = { content: `Error: ${message}`, ephemeral: true };\n\n if (interaction.replied || interaction.deferred) {\n await interaction.followUp(reply);\n } else {\n await interaction.reply(reply);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Core command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScanCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const project = interaction.options.getString('project', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n await adapter.disconnect();\n\n const riskColor =\n risk.level === 'low'\n ? 0x00ff00\n : risk.level === 'medium'\n ? 0xffff00\n : risk.level === 'high'\n ? 0xff8800\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Project Analysis: ${project}`)\n .setColor(riskColor)\n .addFields(\n { name: 'Chain', value: chain, inline: true },\n {\n name: 'Risk Score',\n value: `${risk.score}/100 (${risk.level.toUpperCase()})`,\n inline: true,\n },\n { name: 'Assessment', value: risk.summary },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (analysis.token) {\n embed.addFields({\n name: 'Token',\n value: `${analysis.token.name} (${analysis.token.symbol})`,\n inline: true,\n });\n }\n\n if (risk.factors.length > 0) {\n embed.addFields({\n name: 'Risk Factors',\n value: risk.factors.map((f) => `- ${f}`).join('\\n'),\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleTrendsCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const trending = await fetchTrendingTokens();\n\n if (trending.length === 0) {\n await interaction.editReply('No trending data available right now.');\n return;\n }\n\n const embed = new EmbedBuilder()\n .setTitle('Trending Tokens')\n .setColor(0x5865f2)\n .setFooter({ text: 'Live data from DexScreener & CoinGecko' })\n .setTimestamp();\n\n for (const t of trending.slice(0, 10)) {\n const changeSign = t.priceChange24h >= 0 ? '+' : '';\n const vol =\n t.volume24h >= 1_000_000\n ? `$${(t.volume24h / 1_000_000).toFixed(1)}M`\n : `$${Math.round(t.volume24h).toLocaleString()}`;\n\n embed.addFields({\n name: `${t.symbol} (${t.chain})`,\n value: `Price: $${t.priceUsd}\\n24h: ${changeSign}${t.priceChange24h.toFixed(1)}%\\nVol: ${vol}\\nSource: ${t.source}`,\n inline: true,\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleTrackCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const walletAddr = interaction.options.getString('wallet', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(walletAddr, adapter);\n await adapter.disconnect();\n\n const riskColor =\n analysis.riskLevel === 'clean'\n ? 0x00ff00\n : analysis.riskLevel === 'suspicious'\n ? 0xffff00\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Wallet Analysis`)\n .setColor(riskColor)\n .addFields(\n { name: 'Address', value: `\\`${walletAddr}\\``, inline: false },\n { name: 'Chain', value: chain, inline: true },\n { name: 'Balance', value: `${analysis.balance.toString()} wei`, inline: true },\n { name: 'Transactions', value: String(analysis.transactionCount), inline: true },\n { name: 'Risk Level', value: analysis.riskLevel.toUpperCase(), inline: true },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (analysis.patterns.length > 0) {\n const patternText = analysis.patterns\n .map((p) => `[${p.severity.toUpperCase()}] ${p.description}`)\n .join('\\n');\n embed.addFields({ name: 'Patterns', value: patternText });\n } else {\n embed.addFields({ name: 'Patterns', value: 'No unusual patterns detected.' });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleIcoCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const [icosResult, raisesResult] = await Promise.allSettled([\n fetchUpcomingICOs(),\n fetchRecentRaises(30),\n ]);\n\n const icos = icosResult.status === 'fulfilled' ? icosResult.value : [];\n const raises = raisesResult.status === 'fulfilled' ? raisesResult.value : [];\n\n interface IcoItem {\n name: string;\n round: string;\n amount: number | null;\n chains: string[];\n leadInvestors: string[];\n date: string;\n }\n\n const items: IcoItem[] = raises.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0] ?? '',\n }));\n\n // Merge ICO items not already in raises\n const raiseNames = new Set(items.map((i) => i.name.toLowerCase()));\n for (const ico of icos.slice(0, 5)) {\n if (!raiseNames.has(ico.name.toLowerCase())) {\n items.push({\n name: ico.name,\n round: ico.status,\n amount: null,\n chains: [ico.chain ?? 'multi-chain'],\n leadInvestors: [],\n date: ico.startDate ?? '',\n });\n }\n }\n\n if (items.length === 0) {\n await interaction.editReply('No ICO or fundraising data available right now.');\n return;\n }\n\n const embed = new EmbedBuilder()\n .setTitle('Upcoming ICOs & Fundraising Rounds')\n .setColor(0x5865f2)\n .setFooter({ text: 'Data from DeFiLlama & Pump.fun' })\n .setTimestamp();\n\n for (const item of items.slice(0, 10)) {\n const amount = item.amount ? `$${(item.amount / 1e6).toFixed(1)}M` : 'Undisclosed';\n const chains = item.chains.join(', ') || 'multi-chain';\n let value = `${item.round} (${amount})\\n${chains} | ${item.date}`;\n if (item.leadInvestors.length > 0) {\n value += `\\nLed by: ${item.leadInvestors.slice(0, 3).join(', ')}`;\n }\n embed.addFields({ name: item.name, value, inline: false });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAuditCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const contract = interaction.options.getString('contract', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n\n const riskColor =\n result.overallRisk === 'low'\n ? 0x00ff00\n : result.overallRisk === 'medium'\n ? 0xffff00\n : result.overallRisk === 'high'\n ? 0xff8800\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Contract Audit`)\n .setColor(riskColor)\n .addFields(\n { name: 'Address', value: `\\`${contract}\\``, inline: false },\n { name: 'Chain', value: chain, inline: true },\n { name: 'Risk Level', value: result.overallRisk.toUpperCase(), inline: true },\n { name: 'Has Code', value: result.hasCode ? 'Yes' : 'No', inline: true },\n { name: 'Code Size', value: `${result.codeSize} bytes`, inline: true },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (result.findings.length > 0) {\n const findingsText = result.findings\n .map((f) => `[${f.severity.toUpperCase()}] ${f.title}: ${f.description}`)\n .join('\\n');\n embed.addFields({ name: 'Findings', value: findingsText.slice(0, 1024) });\n } else {\n embed.addFields({ name: 'Findings', value: 'No significant findings.' });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleHelpCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.reply({\n embeds: [\n new EmbedBuilder()\n .setTitle('Vizzor Commands')\n .setColor(0x5865f2)\n .setDescription(\n '**Analysis:**\\n' +\n '`/scan <address>` — Analyze token/project risk\\n' +\n '`/trends` — Trending tokens + market data\\n' +\n '`/track <wallet>` — Wallet forensics\\n' +\n '`/ico` — Upcoming ICOs & fundraising rounds\\n' +\n '`/audit <contract>` — Smart contract audit\\n\\n' +\n '**Quick Commands:**\\n' +\n '`/price <symbol>` — Live price check\\n' +\n '`/predict <symbol>` — AI prediction with signals\\n' +\n '`/wallet <address>` — ETH wallet balance\\n\\n' +\n '**Agent Management:**\\n' +\n '`/agent_create <name>` — Create trading agent\\n' +\n '`/agent_list` — List all agents\\n' +\n '`/agent_start <name>` — Start an agent\\n' +\n '`/agent_stop <name>` — Stop an agent\\n' +\n '`/agent_status <name>` — Agent status & decisions\\n' +\n '`/agent_delete <name>` — Delete an agent\\n\\n' +\n '_@mention the bot for AI-powered analysis._',\n )\n .setFooter({ text: 'Vizzor by 7ayLabs' }),\n ],\n ephemeral: true,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Quick command handlers\n// ---------------------------------------------------------------------------\n\nasync function handlePriceCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const symbol = interaction.options.getString('symbol', true).toUpperCase();\n\n const ticker = await fetchTickerPrice(symbol);\n const changeEmoji = ticker.change24h >= 0 ? '🟢' : '🔴';\n const changeSign = ticker.change24h >= 0 ? '+' : '';\n\n const embed = new EmbedBuilder()\n .setTitle(`💰 ${ticker.symbol}`)\n .setColor(ticker.change24h >= 0 ? 0x00ff00 : 0xff0000)\n .addFields(\n { name: 'Price', value: `$${ticker.price.toLocaleString()}`, inline: true },\n {\n name: '24h Change',\n value: `${changeEmoji} ${changeSign}${ticker.change24h.toFixed(2)}%`,\n inline: true,\n },\n )\n .setFooter({ text: 'Live from Binance' })\n .setTimestamp();\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handlePredictCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const symbol = interaction.options.getString('symbol', true).toUpperCase();\n const prediction = await generatePrediction(symbol);\n\n const dirColor =\n prediction.direction === 'up'\n ? 0x00ff00\n : prediction.direction === 'down'\n ? 0xff0000\n : 0x808080;\n const dirEmoji =\n prediction.direction === 'up' ? '🟢' : prediction.direction === 'down' ? '🔴' : '⚪';\n\n const embed = new EmbedBuilder()\n .setTitle(`🔮 ${prediction.symbol} Prediction`)\n .setColor(dirColor)\n .addFields(\n {\n name: 'Direction',\n value: `${dirEmoji} ${prediction.direction.toUpperCase()}`,\n inline: true,\n },\n { name: 'Confidence', value: `${prediction.confidence}%`, inline: true },\n { name: 'Composite', value: prediction.composite.toFixed(2), inline: true },\n { name: 'Timeframe', value: prediction.timeframe, inline: true },\n )\n .setFooter({ text: 'Not financial advice — DYOR' })\n .setTimestamp();\n\n const signalLines = [\n `Technical: ${prediction.signals.technical}`,\n `Sentiment: ${prediction.signals.sentiment}`,\n `Derivatives: ${prediction.signals.derivatives}`,\n `Trend: ${prediction.signals.trend}`,\n `Macro: ${prediction.signals.macro}`,\n ];\n embed.addFields({\n name: 'Signals',\n value: signalLines.join('\\n'),\n });\n\n if (prediction.reasoning.length > 0) {\n embed.addFields({\n name: 'Reasoning',\n value: prediction.reasoning.join('\\n').slice(0, 1024),\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleWalletCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const address = interaction.options.getString('address', true);\n\n if (!isValidAddress(address)) {\n await interaction.editReply(\n 'Invalid Ethereum address. Must start with 0x followed by 40 hex characters.',\n );\n return;\n }\n\n const balance = await getWalletBalance(address);\n\n const embed = new EmbedBuilder()\n .setTitle('👛 Wallet Balance')\n .setColor(0x5865f2)\n .addFields(\n { name: 'Address', value: `\\`${address}\\``, inline: false },\n { name: 'Balance', value: `${balance} ETH`, inline: true },\n )\n .setFooter({ text: 'Use /track for full forensic analysis' })\n .setTimestamp();\n\n await interaction.editReply({ embeds: [embed] });\n}\n\n// ---------------------------------------------------------------------------\n// Agent command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleAgentCreateCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const name = interaction.options.getString('name', true);\n const strategy = interaction.options.getString('strategy') ?? 'momentum';\n const pairsStr = interaction.options.getString('pairs') ?? 'BTC,ETH';\n const pairs = pairsStr.split(',').map((p) => p.trim().toUpperCase());\n\n const agent = createAgent(name, strategy, pairs);\n\n const embed = new EmbedBuilder()\n .setTitle('✅ Agent Created')\n .setColor(0x00ff00)\n .addFields(\n { name: 'Name', value: agent.name, inline: true },\n { name: 'Strategy', value: agent.strategy, inline: true },\n { name: 'Pairs', value: agent.pairs.join(', '), inline: true },\n { name: 'Interval', value: `${agent.interval}s`, inline: true },\n )\n .setFooter({ text: `Use /agent_start ${agent.name} to activate` });\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentListCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const agents = listAgents();\n\n if (agents.length === 0) {\n await interaction.editReply('No agents created yet. Use `/agent_create` to create one.');\n return;\n }\n\n const embed = new EmbedBuilder().setTitle('🤖 Your Agents').setColor(0x5865f2).setTimestamp();\n\n for (const agent of agents) {\n const state = getAgentStatus(agent.id);\n const statusEmoji =\n state?.status === 'running' ? '🟢' : state?.status === 'stopped' ? '🔴' : '⚪';\n embed.addFields({\n name: `${statusEmoji} ${agent.name} [${state?.status ?? 'idle'}]`,\n value: `Strategy: ${agent.strategy}\\nPairs: ${agent.pairs.join(', ')}\\nCycles: ${state?.cycleCount ?? 0} | Interval: ${agent.interval}s`,\n inline: false,\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentStartCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found. Use \\`/agent_list\\` to see your agents.`,\n ephemeral: true,\n });\n return;\n }\n\n const state = startAgent(agent.id);\n await interaction.reply(\n `🟢 Agent \"${state.config.name}\" started. Monitoring ${state.config.pairs.join(', ')}.`,\n );\n}\n\nasync function handleAgentStopCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found.`,\n ephemeral: true,\n });\n return;\n }\n\n const state = stopAgent(agent.id);\n await interaction.reply(\n `🔴 Agent \"${state.config.name}\" stopped after ${state.cycleCount} cycles.`,\n );\n}\n\nasync function handleAgentStatusCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.editReply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const state = getAgentStatus(agent.id);\n if (!state) {\n await interaction.editReply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const statusColor =\n state.status === 'running' ? 0x00ff00 : state.status === 'stopped' ? 0xff0000 : 0x808080;\n const statusEmoji = state.status === 'running' ? '🟢' : state.status === 'stopped' ? '🔴' : '⚪';\n\n const embed = new EmbedBuilder()\n .setTitle(`🤖 Agent: ${state.config.name}`)\n .setColor(statusColor)\n .addFields(\n { name: 'Status', value: `${statusEmoji} ${state.status}`, inline: true },\n { name: 'Strategy', value: state.config.strategy, inline: true },\n { name: 'Pairs', value: state.config.pairs.join(', '), inline: true },\n { name: 'Interval', value: `${state.config.interval}s`, inline: true },\n { name: 'Cycles', value: String(state.cycleCount), inline: true },\n )\n .setTimestamp();\n\n if (state.error) {\n embed.addFields({ name: 'Error', value: state.error });\n }\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n const decisionText = decisions\n .map((d) => {\n const actionEmoji =\n d.decision.action === 'buy' ? '🟢' : d.decision.action === 'sell' ? '🔴' : '⚪';\n const time = new Date(d.timestamp).toLocaleString();\n return `${actionEmoji} ${d.symbol} ${d.decision.action.toUpperCase()} (${d.decision.confidence}%) — ${time}`;\n })\n .join('\\n');\n embed.addFields({ name: 'Recent Decisions', value: decisionText.slice(0, 1024) });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentDeleteCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found.`,\n ephemeral: true,\n });\n return;\n }\n\n deleteAgent(agent.id);\n await interaction.reply(`🗑 Agent \"${name}\" deleted.`);\n}\n","import { Client, GatewayIntentBits, REST, Routes, type Interaction } from 'discord.js';\nimport { loadConfig } from '../config/loader.js';\nimport { setConfig, setToolHandler, analyze } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { buildChatSystemPrompt } from '../ai/prompts/chat.js';\nimport { splitMessage } from '../utils/message-split.js';\nimport { registerSlashCommands, handleSlashCommand } from './commands/index.js';\nimport { startRateLimitCleanup } from './middleware/rate-limit.js';\n\nexport async function startDiscordBot(): Promise<void> {\n const config = loadConfig();\n const token = config.discordToken;\n\n if (!token) {\n throw new Error('Discord token not configured. Run: vizzor config set discordToken <token>');\n }\n\n // Initialize AI layer for tool-use chat\n setConfig(config);\n setToolHandler(handleTool);\n\n const client = new Client({\n intents: [\n GatewayIntentBits.Guilds,\n GatewayIntentBits.GuildMessages,\n GatewayIntentBits.MessageContent,\n ],\n });\n\n // Start periodic rate-limit cleanup\n startRateLimitCleanup();\n\n client.once('ready', async (readyClient) => {\n console.log(`Discord bot logged in as ${readyClient.user.tag}`);\n\n // Register slash commands\n const rest = new REST({ version: '10' }).setToken(token);\n const commands = registerSlashCommands();\n\n if (config.discordGuildId) {\n await rest.put(Routes.applicationGuildCommands(readyClient.user.id, config.discordGuildId), {\n body: commands,\n });\n } else {\n await rest.put(Routes.applicationCommands(readyClient.user.id), {\n body: commands,\n });\n }\n\n console.log('Discord slash commands registered');\n });\n\n client.on('interactionCreate', async (interaction: Interaction) => {\n if (!interaction.isChatInputCommand()) return;\n await handleSlashCommand(interaction);\n });\n\n // Freetext handler — AI chat on @mention\n client.on('messageCreate', async (message) => {\n if (message.author.bot) return;\n if (!client.user || !message.mentions.has(client.user)) return;\n\n const text = message.content.replace(/<@!?\\d+>/g, '').trim();\n if (!text) {\n await message.reply(\n 'Mention me with a question! e.g. `@Vizzor what is BTC price?`\\n' +\n 'Or use slash commands: `/scan` `/trends` `/track` `/ico` `/audit` `/help`',\n );\n return;\n }\n\n await message.reply('🔮 Analyzing...');\n\n try {\n const response = await analyze(buildChatSystemPrompt(), text, VIZZOR_TOOLS);\n const chunks = splitMessage(response, 1900);\n for (const chunk of chunks) {\n await message.reply(chunk);\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await message.reply(`Analysis failed: ${msg}`);\n }\n });\n\n await client.login(token);\n}\n","// ---------------------------------------------------------------------------\n// Telegram MarkdownV2 formatters for market data\n// ---------------------------------------------------------------------------\n\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!\\\\<>])/g, '\\\\$1');\n}\n\nexport function formatPrice(price: number): string {\n return escapeMarkdown(price < 1 ? price.toPrecision(4) : price.toLocaleString());\n}\n\nexport function formatChange(change: number): string {\n const sign = change > 0 ? '\\\\+' : '';\n const emoji = change > 0 ? '🟢' : change < 0 ? '🔴' : '⚪';\n return `${emoji} ${sign}${escapeMarkdown(change.toFixed(2))}%`;\n}\n\nexport function formatVolume(volume: number): string {\n if (volume >= 1e9) return escapeMarkdown(`$${(volume / 1e9).toFixed(2)}B`);\n if (volume >= 1e6) return escapeMarkdown(`$${(volume / 1e6).toFixed(2)}M`);\n if (volume >= 1e3) return escapeMarkdown(`$${(volume / 1e3).toFixed(1)}K`);\n return escapeMarkdown(`$${volume.toFixed(0)}`);\n}\n\nexport interface TrendingItem {\n name: string;\n symbol: string;\n chain: string;\n priceUsd: string;\n priceChange24h: number;\n volume24h: number;\n source: string;\n}\n\nexport function formatTrending(items: TrendingItem[]): string {\n const lines = ['*🔥 Trending Tokens*', ''];\n for (const t of items.slice(0, 10)) {\n lines.push(\n `• *${escapeMarkdown(t.symbol)}* \\\\(${escapeMarkdown(t.chain)}\\\\)`,\n ` 💲${escapeMarkdown(t.priceUsd)} ${formatChange(t.priceChange24h)}`,\n ` Vol: ${formatVolume(t.volume24h)} _\\\\[${escapeMarkdown(t.source)}\\\\]_`,\n '',\n );\n }\n return lines.join('\\n');\n}\n\nexport interface GainerLoser {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n}\n\nexport function formatGainersLosers(gainers: GainerLoser[], losers: GainerLoser[]): string {\n const lines = ['*📊 Market Movers*', ''];\n\n lines.push('*Top Gainers*');\n for (const g of gainers.slice(0, 5)) {\n lines.push(\n ` 🟢 *${escapeMarkdown(g.symbol)}* $${formatPrice(g.price)} ${formatChange(g.change24h)}`,\n );\n }\n\n lines.push('', '*Top Losers*');\n for (const l of losers.slice(0, 5)) {\n lines.push(\n ` 🔴 *${escapeMarkdown(l.symbol)}* $${formatPrice(l.price)} ${formatChange(l.change24h)}`,\n );\n }\n\n return lines.join('\\n');\n}\n\nexport interface ICOItem {\n name: string;\n round: string;\n amount: number | null;\n chains: string[];\n leadInvestors: string[];\n date: string;\n}\n\nexport function formatICOs(icos: ICOItem[]): string {\n const lines = ['*🚀 Upcoming ICOs \\\\& Raises*', ''];\n for (const ico of icos.slice(0, 10)) {\n const amount = ico.amount\n ? escapeMarkdown(`$${(ico.amount / 1e6).toFixed(1)}M`)\n : 'undisclosed';\n const chains = ico.chains.length > 0 ? escapeMarkdown(ico.chains.join(', ')) : 'multi\\\\-chain';\n lines.push(\n `• *${escapeMarkdown(ico.name)}* — ${escapeMarkdown(ico.round)} \\\\(${amount}\\\\)`,\n ` ${chains} \\\\| ${escapeMarkdown(ico.date)}`,\n );\n if (ico.leadInvestors.length > 0) {\n lines.push(` Led by: ${escapeMarkdown(ico.leadInvestors.join(', '))}`);\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n\nexport interface AuditFinding {\n severity: string;\n title: string;\n description: string;\n}\n\nexport function formatAudit(\n contract: string,\n overallRisk: string,\n findings: AuditFinding[],\n): string {\n const riskEmoji =\n overallRisk === 'low'\n ? '🟢'\n : overallRisk === 'medium'\n ? '🟡'\n : overallRisk === 'high'\n ? '🟠'\n : '🔴';\n\n const lines = [\n `*🔍 Contract Audit*`,\n `Address: \\`${escapeMarkdown(contract)}\\``,\n `${riskEmoji} Risk: *${escapeMarkdown(overallRisk.toUpperCase())}*`,\n '',\n ];\n\n if (findings.length > 0) {\n lines.push('*Findings:*');\n for (const f of findings) {\n const sevEmoji =\n f.severity === 'critical'\n ? '🔴'\n : f.severity === 'high'\n ? '🟠'\n : f.severity === 'medium'\n ? '🟡'\n : '🟢';\n lines.push(`${sevEmoji} *${escapeMarkdown(f.title)}*: ${escapeMarkdown(f.description)}`);\n }\n } else {\n lines.push('✅ No significant findings\\\\.');\n }\n\n lines.push('', '_Not financial advice\\\\. DYOR\\\\._');\n return lines.join('\\n');\n}\n\nexport function formatWalletAnalysis(\n address: string,\n chain: string,\n balance: string,\n txCount: number,\n riskLevel: string,\n patterns: { severity: string; description: string }[],\n): string {\n const riskEmoji =\n riskLevel === 'low' ? '🟢' : riskLevel === 'medium' ? '🟡' : riskLevel === 'high' ? '🟠' : '🔴';\n\n const lines = [\n `*👛 Wallet Analysis*`,\n `Address: \\`${escapeMarkdown(address)}\\``,\n `Chain: ${escapeMarkdown(chain)}`,\n `Balance: ${escapeMarkdown(balance)} ETH`,\n `Transactions: ${escapeMarkdown(String(txCount))}`,\n `${riskEmoji} Risk: *${escapeMarkdown(riskLevel.toUpperCase())}*`,\n '',\n ];\n\n if (patterns.length > 0) {\n lines.push('*Patterns:*');\n for (const p of patterns) {\n lines.push(`• \\\\[${escapeMarkdown(p.severity)}\\\\] ${escapeMarkdown(p.description)}`);\n }\n } else {\n lines.push('No unusual patterns detected\\\\.');\n }\n\n return lines.join('\\n');\n}\n","import type { Bot, Context } from 'grammy';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\nimport { fetchTrendingTokens } from '../../core/trends/market.js';\nimport { fetchUpcomingICOs } from '../../core/scanner/ico-tracker.js';\nimport { fetchRecentRaises } from '../../data/sources/defillama.js';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n deleteAgent,\n listStrategies,\n getWalletBalance,\n isValidAddress,\n} from '../../core/agent/index.js';\nimport {\n escapeMarkdown,\n formatTrending,\n formatICOs,\n formatAudit,\n formatWalletAnalysis,\n} from '../formatters/market.js';\n\nexport function registerCommands(bot: Bot): void {\n bot.command('start', (ctx) =>\n ctx.reply(\n '*Welcome to Vizzor* — AI\\\\-powered crypto chronovisor\\\\.\\n\\n' +\n '*Commands:*\\n' +\n '/scan \\\\<address\\\\> — Analyze a project\\n' +\n '/trends — Trending tokens \\\\+ market movers\\n' +\n '/track \\\\<wallet\\\\> — Wallet forensics\\n' +\n '/ico — Upcoming ICOs \\\\& raises\\n' +\n '/audit \\\\<contract\\\\> — Smart contract audit\\n' +\n '/price \\\\<symbol\\\\> — Quick price check\\n' +\n '/predict \\\\<symbol\\\\> — AI prediction\\n' +\n '/wallet \\\\<address\\\\> — Wallet balance\\n' +\n '/agent — Trading agent management\\n' +\n '/help — Show all commands\\n\\n' +\n '_Send any message for AI\\\\-powered analysis_',\n { parse_mode: 'MarkdownV2' },\n ),\n );\n\n bot.command('help', (ctx) =>\n ctx.reply(\n '*Vizzor Commands*\\n\\n' +\n '*Analysis:*\\n' +\n '/scan \\\\<address\\\\> — Analyze token/project risk\\n' +\n '/track \\\\<wallet\\\\> — Wallet analysis \\\\& forensics\\n' +\n '/trends — Trending tokens from DexScreener\\n' +\n '/ico — Upcoming ICOs \\\\& fundraising rounds\\n' +\n '/audit \\\\<contract\\\\> — Smart contract audit\\n\\n' +\n '*Quick Commands:*\\n' +\n '/price \\\\<symbol\\\\> — Live price check\\n' +\n '/predict \\\\<symbol\\\\> — AI prediction with signals\\n' +\n '/wallet \\\\<address\\\\> — ETH wallet balance\\n\\n' +\n '*Agent Management:*\\n' +\n '/agent\\\\_create \\\\<name\\\\> \\\\<strategy\\\\> \\\\<pairs\\\\>\\n' +\n '/agent\\\\_list — List all agents\\n' +\n '/agent\\\\_start \\\\<name\\\\> — Start an agent\\n' +\n '/agent\\\\_stop \\\\<name\\\\> — Stop an agent\\n' +\n '/agent\\\\_status \\\\<name\\\\> — Agent status \\\\& decisions\\n' +\n '/agent\\\\_delete \\\\<name\\\\> — Delete an agent\\n\\n' +\n '_Send any message for AI\\\\-powered analysis_',\n { parse_mode: 'MarkdownV2' },\n ),\n );\n\n // Core commands\n bot.command('scan', handleScan);\n bot.command('trends', handleTrends);\n bot.command('track', handleTrack);\n bot.command('ico', handleIco);\n bot.command('audit', handleAudit);\n\n // Quick commands\n bot.command('price', handlePrice);\n bot.command('predict', handlePredict);\n bot.command('wallet', handleWallet);\n\n // Agent commands\n bot.command('agent', handleAgentHelp);\n bot.command('agent_create', handleAgentCreate);\n bot.command('agent_list', handleAgentList);\n bot.command('agent_start', handleAgentStart);\n bot.command('agent_stop', handleAgentStop);\n bot.command('agent_status', handleAgentStatus);\n bot.command('agent_delete', handleAgentDelete);\n}\n\n// ---------------------------------------------------------------------------\n// Core command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScan(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const project = args[0];\n\n if (!project) {\n await ctx.reply('Usage: /scan <project_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('🔍 Scanning project...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n await adapter.disconnect();\n\n const riskEmoji =\n risk.level === 'low'\n ? '🟢'\n : risk.level === 'medium'\n ? '🟡'\n : risk.level === 'high'\n ? '🟠'\n : '🔴';\n\n let message = `*Project Analysis*\\n\\n`;\n message += `${riskEmoji} Risk: ${risk.score}/100 \\\\(${escapeMarkdown(risk.level.toUpperCase())}\\\\)\\n`;\n message += `${escapeMarkdown(risk.summary)}\\n`;\n\n if (analysis.token) {\n message += `\\nToken: ${escapeMarkdown(analysis.token.name)} \\\\(${escapeMarkdown(analysis.token.symbol)}\\\\)`;\n }\n\n if (risk.factors.length > 0) {\n message += '\\n\\n*Risk Factors*\\n';\n for (const factor of risk.factors) {\n message += `• ${escapeMarkdown(factor)}\\n`;\n }\n }\n\n message += '\\n_Not financial advice\\\\. DYOR\\\\._';\n\n await ctx.reply(message, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Error: ${msg}`);\n }\n}\n\nasync function handleTrends(ctx: Context): Promise<void> {\n await ctx.reply('📊 Fetching trends...');\n\n try {\n const trending = await fetchTrendingTokens();\n if (trending.length === 0) {\n await ctx.reply('No trending data available right now.');\n return;\n }\n\n const formatted = formatTrending(\n trending.slice(0, 10).map((t) => ({\n name: t.name,\n symbol: t.symbol,\n chain: t.chain,\n priceUsd: t.priceUsd,\n priceChange24h: t.priceChange24h,\n volume24h: t.volume24h,\n source: t.source,\n })),\n );\n\n await ctx.reply(formatted + '\\n\\n_Live data from DexScreener \\\\& CoinGecko_', {\n parse_mode: 'MarkdownV2',\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to fetch trends: ${msg}`);\n }\n}\n\nasync function handleTrack(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const wallet = args[0];\n\n if (!wallet) {\n await ctx.reply('Usage: /track <wallet_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('👛 Analyzing wallet...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(wallet, adapter);\n await adapter.disconnect();\n\n const formatted = formatWalletAnalysis(\n analysis.address,\n analysis.chain,\n analysis.balance.toString(),\n analysis.transactionCount,\n analysis.riskLevel,\n analysis.patterns,\n );\n\n await ctx.reply(formatted, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Wallet analysis failed: ${msg}`);\n }\n}\n\nasync function handleIco(ctx: Context): Promise<void> {\n await ctx.reply('🚀 Fetching ICOs and raises...');\n\n try {\n const [icosResult, raisesResult] = await Promise.allSettled([\n fetchUpcomingICOs(),\n fetchRecentRaises(30),\n ]);\n\n const icos = icosResult.status === 'fulfilled' ? icosResult.value : [];\n const raises = raisesResult.status === 'fulfilled' ? raisesResult.value : [];\n\n const items = [\n ...raises.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0] ?? '',\n })),\n ];\n\n // Add ICO items that aren't already in raises\n const raiseNames = new Set(items.map((i) => i.name.toLowerCase()));\n for (const ico of icos.slice(0, 5)) {\n if (!raiseNames.has(ico.name.toLowerCase())) {\n items.push({\n name: ico.name,\n round: ico.status,\n amount: null,\n chains: [ico.chain ?? 'multi-chain'],\n leadInvestors: [],\n date: ico.startDate ?? '',\n });\n }\n }\n\n if (items.length === 0) {\n await ctx.reply('No ICO or fundraising data available right now.');\n return;\n }\n\n const formatted = formatICOs(items);\n await ctx.reply(formatted + '\\n_Data from DeFiLlama \\\\& Pump\\\\.fun_', {\n parse_mode: 'MarkdownV2',\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to fetch ICOs: ${msg}`);\n }\n}\n\nasync function handleAudit(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const contract = args[0];\n\n if (!contract) {\n await ctx.reply('Usage: /audit <contract_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('🔍 Auditing contract...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n\n const formatted = formatAudit(\n contract,\n result.overallRisk,\n result.findings.map((f) => ({\n severity: f.severity,\n title: f.title,\n description: f.description,\n })),\n );\n\n await ctx.reply(formatted, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Audit failed: ${msg}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Quick command handlers\n// ---------------------------------------------------------------------------\n\nasync function handlePrice(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const symbol = args[0]?.toUpperCase();\n\n if (!symbol) {\n await ctx.reply('Usage: /price <symbol>\\nExample: /price BTC');\n return;\n }\n\n try {\n const ticker = await fetchTickerPrice(symbol);\n const changeEmoji = ticker.change24h >= 0 ? '🟢' : '🔴';\n const changeSign = ticker.change24h >= 0 ? '+' : '';\n\n await ctx.reply(\n `💰 ${ticker.symbol}\\n` +\n `Price: $${ticker.price.toLocaleString()}\\n` +\n `${changeEmoji} 24h: ${changeSign}${ticker.change24h.toFixed(2)}%\\n\\n` +\n `Live from Binance`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Price check failed: ${msg}`);\n }\n}\n\nasync function handlePredict(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const symbol = args[0]?.toUpperCase();\n\n if (!symbol) {\n await ctx.reply('Usage: /predict <symbol>\\nExample: /predict ETH');\n return;\n }\n\n await ctx.reply(`🔮 Generating prediction for ${symbol}...`);\n\n try {\n const prediction = await generatePrediction(symbol);\n const dirEmoji =\n prediction.direction === 'up' ? '🟢' : prediction.direction === 'down' ? '🔴' : '⚪';\n\n let msg = `🔮 ${prediction.symbol} Prediction\\n\\n`;\n msg += `${dirEmoji} Direction: ${prediction.direction.toUpperCase()}\\n`;\n msg += `📊 Confidence: ${prediction.confidence}%\\n`;\n msg += `📈 Composite: ${prediction.composite.toFixed(2)}\\n`;\n msg += `⏱ Timeframe: ${prediction.timeframe}\\n\\n`;\n\n msg += `Signals:\\n`;\n msg += `• Technical: ${prediction.signals.technical}\\n`;\n msg += `• Sentiment: ${prediction.signals.sentiment}\\n`;\n msg += `• Derivatives: ${prediction.signals.derivatives}\\n`;\n msg += `• Trend: ${prediction.signals.trend}\\n`;\n msg += `• Macro: ${prediction.signals.macro}\\n\\n`;\n\n if (prediction.reasoning.length > 0) {\n msg += prediction.reasoning.join('\\n') + '\\n\\n';\n }\n\n msg += prediction.disclaimer;\n\n await ctx.reply(msg);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Prediction failed: ${msg}`);\n }\n}\n\nasync function handleWallet(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const address = args[0];\n\n if (!address) {\n await ctx.reply('Usage: /wallet <ethereum_address>\\nExample: /wallet 0x...');\n return;\n }\n\n if (!isValidAddress(address)) {\n await ctx.reply('Invalid Ethereum address. Must start with 0x followed by 40 hex characters.');\n return;\n }\n\n try {\n const balance = await getWalletBalance(address);\n await ctx.reply(\n `👛 Wallet Balance\\n\\n` +\n `Address: ${address}\\n` +\n `Balance: ${balance} ETH\\n\\n` +\n `Use /track <address> for full forensic analysis`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Wallet query failed: ${msg}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Agent command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleAgentHelp(ctx: Context): Promise<void> {\n const strategies = listStrategies();\n await ctx.reply(\n `🤖 Agent Management\\n\\n` +\n `Commands:\\n` +\n `/agent_create <name> <strategy> <pairs> - Create agent\\n` +\n `/agent_list - List all agents\\n` +\n `/agent_start <name> - Start an agent\\n` +\n `/agent_stop <name> - Stop an agent\\n` +\n `/agent_status <name> - View status & decisions\\n` +\n `/agent_delete <name> - Delete an agent\\n\\n` +\n `Available strategies: ${strategies.join(', ')}\\n\\n` +\n `Example:\\n` +\n `/agent_create mybot momentum BTC,ETH`,\n );\n}\n\nasync function handleAgentCreate(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n const strategy = args[1] ?? 'momentum';\n const pairsStr = args[2] ?? 'BTC,ETH';\n\n if (!name) {\n await ctx.reply(\n 'Usage: /agent_create <name> <strategy> <pairs>\\n' +\n 'Example: /agent_create mybot momentum BTC,ETH,SOL',\n );\n return;\n }\n\n try {\n const pairs = pairsStr.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(name, strategy, pairs);\n\n await ctx.reply(\n `✅ Agent Created\\n\\n` +\n `Name: ${agent.name}\\n` +\n `Strategy: ${agent.strategy}\\n` +\n `Pairs: ${agent.pairs.join(', ')}\\n` +\n `Interval: ${agent.interval}s\\n\\n` +\n `Use /agent_start ${agent.name} to activate`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to create agent: ${msg}`);\n }\n}\n\nasync function handleAgentList(ctx: Context): Promise<void> {\n const agents = listAgents();\n\n if (agents.length === 0) {\n await ctx.reply('No agents created yet. Use /agent_create to create one.');\n return;\n }\n\n let msg = '🤖 Your Agents\\n\\n';\n for (const agent of agents) {\n const state = getAgentStatus(agent.id);\n const statusEmoji =\n state?.status === 'running' ? '🟢' : state?.status === 'stopped' ? '🔴' : '⚪';\n msg += `${statusEmoji} ${agent.name} [${state?.status ?? 'idle'}]\\n`;\n msg += ` Strategy: ${agent.strategy} | Pairs: ${agent.pairs.join(', ')}\\n`;\n msg += ` Cycles: ${state?.cycleCount ?? 0} | Interval: ${agent.interval}s\\n\\n`;\n }\n\n await ctx.reply(msg);\n}\n\nasync function handleAgentStart(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_start <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found. Use /agent_list to see your agents.`);\n return;\n }\n const state = startAgent(agent.id);\n await ctx.reply(\n `🟢 Agent \"${state.config.name}\" started. Monitoring ${state.config.pairs.join(', ')}.`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to start agent: ${msg}`);\n }\n}\n\nasync function handleAgentStop(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_stop <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n const state = stopAgent(agent.id);\n await ctx.reply(`🔴 Agent \"${state.config.name}\" stopped after ${state.cycleCount} cycles.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to stop agent: ${msg}`);\n }\n}\n\nasync function handleAgentStatus(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_status <name>');\n return;\n }\n\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const state = getAgentStatus(agent.id);\n if (!state) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const statusEmoji = state.status === 'running' ? '🟢' : state.status === 'stopped' ? '🔴' : '⚪';\n\n let msg = `🤖 Agent: ${state.config.name}\\n\\n`;\n msg += `${statusEmoji} Status: ${state.status}\\n`;\n msg += `Strategy: ${state.config.strategy}\\n`;\n msg += `Pairs: ${state.config.pairs.join(', ')}\\n`;\n msg += `Interval: ${state.config.interval}s\\n`;\n msg += `Cycles: ${state.cycleCount}\\n`;\n if (state.error) msg += `Error: ${state.error}\\n`;\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n msg += '\\nRecent Decisions:\\n';\n for (const d of decisions) {\n const actionEmoji =\n d.decision.action === 'buy' ? '🟢' : d.decision.action === 'sell' ? '🔴' : '⚪';\n const time = new Date(d.timestamp).toLocaleString();\n msg += `${actionEmoji} ${d.symbol} ${d.decision.action.toUpperCase()} (${d.decision.confidence}%) — ${time}\\n`;\n if (d.decision.reasoning.length > 0) {\n msg += ` → ${d.decision.reasoning[0]}\\n`;\n }\n }\n }\n\n await ctx.reply(msg);\n}\n\nasync function handleAgentDelete(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_delete <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n deleteAgent(agent.id);\n await ctx.reply(`🗑 Agent \"${name}\" deleted.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to delete agent: ${msg}`);\n }\n}\n","// ---------------------------------------------------------------------------\n// Per-user rate limiting middleware for Telegram bot\n// ---------------------------------------------------------------------------\n\nimport type { Context, NextFunction } from 'grammy';\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nconst userLimits = new Map<number, RateLimitEntry>();\n\nconst MAX_REQUESTS = 10;\nconst WINDOW_MS = 60_000; // 1 minute\n\n/**\n * Rate-limiting middleware. Limits each user to MAX_REQUESTS per WINDOW_MS.\n * Silently drops excess messages to prevent abuse.\n */\nexport async function rateLimitMiddleware(ctx: Context, next: NextFunction): Promise<void> {\n const userId = ctx.from?.id;\n if (!userId) {\n await next();\n return;\n }\n\n const now = Date.now();\n const entry = userLimits.get(userId);\n\n if (!entry || now >= entry.resetAt) {\n userLimits.set(userId, { count: 1, resetAt: now + WINDOW_MS });\n await next();\n return;\n }\n\n if (entry.count >= MAX_REQUESTS) {\n await ctx.reply('Rate limited. Please wait a moment before sending more commands.');\n return;\n }\n\n entry.count++;\n await next();\n}\n\n/**\n * Clean up expired entries periodically to prevent memory leaks.\n */\nexport function startRateLimitCleanup(intervalMs = 300_000): ReturnType<typeof setInterval> {\n return setInterval(() => {\n const now = Date.now();\n for (const [userId, entry] of userLimits) {\n if (now >= entry.resetAt) {\n userLimits.delete(userId);\n }\n }\n }, intervalMs);\n}\n","import { Bot } from 'grammy';\nimport { loadConfig } from '../config/loader.js';\nimport { setConfig, setToolHandler, analyze } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { buildChatSystemPrompt } from '../ai/prompts/chat.js';\nimport { splitMessage } from '../utils/message-split.js';\nimport { registerCommands } from './commands/index.js';\nimport { rateLimitMiddleware, startRateLimitCleanup } from './middleware/rate-limit.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('telegram-bot');\n\nexport async function startTelegramBot(): Promise<void> {\n const config = loadConfig();\n const token = config.telegramToken;\n\n if (!token) {\n throw new Error('Telegram token not configured. Run: vizzor config set telegramToken <token>');\n }\n\n // Initialize AI layer for tool-use chat\n setConfig(config);\n setToolHandler(handleTool);\n\n const bot = new Bot(token);\n\n // Register rate-limiting middleware\n bot.use(rateLimitMiddleware);\n\n // Register slash commands\n registerCommands(bot);\n\n // AI chat handler for freetext messages\n bot.on('message:text', async (ctx) => {\n const text = ctx.message.text;\n\n // Skip if it's a command (handled above)\n if (text.startsWith('/')) return;\n\n await ctx.reply('🔮 Analyzing...');\n\n try {\n const response = await analyze(buildChatSystemPrompt(), text, VIZZOR_TOOLS);\n const chunks = splitMessage(response, 4000);\n for (const chunk of chunks) {\n await ctx.reply(chunk);\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Analysis failed: ${msg}`);\n }\n });\n\n bot.catch((err) => {\n logger.error({ err: err.message }, 'Telegram bot error');\n });\n\n // Start periodic cleanup of rate limit entries\n const cleanupInterval = startRateLimitCleanup();\n\n logger.info('Telegram bot starting...');\n await bot.start({\n onStart: (botInfo) => {\n logger.info(`Telegram bot started as @${botInfo.username}`);\n },\n });\n\n // Cleanup on stop (unreachable in normal flow but good practice)\n clearInterval(cleanupInterval);\n}\n","import chalk from 'chalk';\nimport { getConfig } from '../../config/loader.js';\nimport { requireKey, hasKey } from '../../config/keys.js';\n\nexport async function handleBotStart(options: {\n discord: boolean;\n telegram: boolean;\n all: boolean;\n}): Promise<void> {\n const config = getConfig();\n const startDiscord = options.discord || options.all;\n const startTelegram = options.telegram || options.all;\n\n if (!startDiscord && !startTelegram) {\n console.log(chalk.yellow('Specify which bot to start:'));\n console.log(' --discord Start Discord bot');\n console.log(' --telegram Start Telegram bot');\n console.log(' --all Start all bots');\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n if (startDiscord) {\n requireKey('DISCORD_TOKEN', config.discordToken);\n console.log(chalk.blue('Starting Discord bot...'));\n const { startDiscordBot } = await import('../../discord/bot.js');\n promises.push(startDiscordBot());\n }\n\n if (startTelegram) {\n requireKey('TELEGRAM_BOT_TOKEN', config.telegramToken);\n console.log(chalk.blue('Starting Telegram bot...'));\n const { startTelegramBot } = await import('../../telegram/bot.js');\n promises.push(startTelegramBot());\n }\n\n // Handle graceful shutdown\n const shutdown = () => {\n console.log(chalk.dim('\\nShutting down bots...'));\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n await Promise.all(promises);\n}\n\nexport function handleBotValidate(): void {\n const config = getConfig();\n\n console.log(chalk.bold('\\nVizzor Bot Configuration Check\\n'));\n\n const checks = [\n { label: 'Anthropic API Key', isSet: hasKey(config.anthropicApiKey), required: true },\n { label: 'Etherscan API Key', isSet: hasKey(config.etherscanApiKey), required: true },\n { label: 'Discord Token', isSet: hasKey(config.discordToken), required: false },\n { label: 'Discord Guild ID', isSet: hasKey(config.discordGuildId), required: false },\n { label: 'Telegram Token', isSet: hasKey(config.telegramToken), required: false },\n { label: 'CryptoPanic Key', isSet: hasKey(config.cryptopanicApiKey), required: false },\n ];\n\n let allRequired = true;\n for (const check of checks) {\n const status = check.isSet\n ? chalk.green('OK')\n : check.required\n ? chalk.red('MISSING')\n : chalk.yellow('NOT SET');\n console.log(` ${status.padEnd(18)} ${check.label}`);\n if (check.required && !check.isSet) allRequired = false;\n }\n\n console.log();\n\n // Bot readiness\n if (hasKey(config.discordToken)) {\n console.log(chalk.green(' Discord bot: Ready to start'));\n } else {\n console.log(chalk.yellow(' Discord bot: Set discordToken to enable'));\n console.log(chalk.dim(' vizzor config set discordToken <token>'));\n }\n\n if (hasKey(config.telegramToken)) {\n console.log(chalk.green(' Telegram bot: Ready to start'));\n } else {\n console.log(chalk.yellow(' Telegram bot: Set telegramToken to enable'));\n console.log(chalk.dim(' vizzor config set telegramToken <token>'));\n }\n\n console.log();\n\n if (!allRequired) {\n console.log(chalk.red('Required keys are missing. Run: vizzor config set <key> <value>'));\n } else if (hasKey(config.discordToken) && hasKey(config.telegramToken)) {\n console.log(chalk.green('All bots ready. Run: vizzor bot start --all'));\n } else if (hasKey(config.discordToken) || hasKey(config.telegramToken)) {\n const which = hasKey(config.discordToken) ? '--discord' : '--telegram';\n console.log(chalk.green(`Bot ready. Run: vizzor bot start ${which}`));\n }\n}\n","// ---------------------------------------------------------------------------\n// Data Collector Service — background OHLCV ingestion from Binance\n// ---------------------------------------------------------------------------\n\nimport { fetchKlines } from './sources/binance.js';\nimport type { DataStore, OHLCVRecord } from './types.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('collector');\n\nconst MAJOR_SYMBOLS = [\n 'BTC',\n 'ETH',\n 'SOL',\n 'BNB',\n 'XRP',\n 'ADA',\n 'DOGE',\n 'DOT',\n 'AVAX',\n 'MATIC',\n 'LINK',\n 'UNI',\n 'ATOM',\n 'NEAR',\n 'ARB',\n 'OP',\n 'SUI',\n 'APT',\n 'PEPE',\n 'SHIB',\n 'FLOKI',\n 'BONK',\n 'WIF',\n];\n\nconst TIMEFRAMES = ['1h', '4h'] as const;\nconst COLLECTION_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\nexport interface CollectorStatus {\n running: boolean;\n symbols: string[];\n timeframes: string[];\n intervalMs: number;\n lastRun: number | null;\n totalRecords: number;\n errors: number;\n}\n\nexport class DataCollector {\n private timer: ReturnType<typeof setInterval> | null = null;\n private status: CollectorStatus = {\n running: false,\n symbols: MAJOR_SYMBOLS,\n timeframes: [...TIMEFRAMES],\n intervalMs: COLLECTION_INTERVAL_MS,\n lastRun: null,\n totalRecords: 0,\n errors: 0,\n };\n\n constructor(\n private store: DataStore,\n private symbols: string[] = MAJOR_SYMBOLS,\n private intervalMs: number = COLLECTION_INTERVAL_MS,\n ) {\n this.status.symbols = symbols;\n this.status.intervalMs = intervalMs;\n }\n\n getStatus(): CollectorStatus {\n return { ...this.status };\n }\n\n start(): void {\n if (this.status.running) {\n log.warn('Collector already running');\n return;\n }\n\n log.info(\n `Starting data collector: ${this.symbols.length} symbols, ${TIMEFRAMES.length} timeframes, every ${this.intervalMs / 1000}s`,\n );\n\n this.status.running = true;\n\n // Run immediately, then on interval\n void this.collectAll();\n this.timer = setInterval(() => void this.collectAll(), this.intervalMs);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.status.running = false;\n log.info('Data collector stopped');\n }\n\n private async collectAll(): Promise<void> {\n log.info('Collection cycle starting');\n const start = Date.now();\n\n for (const timeframe of TIMEFRAMES) {\n for (const symbol of this.symbols) {\n try {\n await this.collectSymbol(symbol, timeframe);\n } catch (err) {\n this.status.errors++;\n log.error(\n `Failed to collect ${symbol}/${timeframe}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n this.status.lastRun = Date.now();\n const elapsed = ((Date.now() - start) / 1000).toFixed(1);\n log.info(\n `Collection cycle complete in ${elapsed}s (total records: ${this.status.totalRecords})`,\n );\n }\n\n private async collectSymbol(symbol: string, timeframe: string): Promise<void> {\n // Fetch last 100 candles (catches up missed data on restart)\n const klines = await fetchKlines(symbol, timeframe, 100);\n\n const records: OHLCVRecord[] = klines.map((k) => ({\n time: k.openTime,\n symbol: symbol.toUpperCase(),\n timeframe,\n open: k.open,\n high: k.high,\n low: k.low,\n close: k.close,\n volume: k.volume,\n trades: k.trades,\n }));\n\n await this.store.insertOHLCV(records);\n this.status.totalRecords += records.length;\n }\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor collect — manage background data collection\n// ---------------------------------------------------------------------------\n\nimport { getConfig } from '../../config/loader.js';\nimport { getStore } from '../../data/store-factory.js';\nimport { DataCollector } from '../../data/collector.js';\nimport chalk from 'chalk';\n\nlet collector: DataCollector | null = null;\n\nexport async function handleCollectStart(options: {\n symbols?: string;\n interval?: number;\n}): Promise<void> {\n const config = getConfig();\n\n if (config.database?.type !== 'postgres' || !config.database.url) {\n console.log(\n chalk.yellow(\n 'Data collection requires PostgreSQL + TimescaleDB.\\n' +\n 'Set database.type = \"postgres\" and database.url in your config.\\n\\n' +\n 'Example:\\n' +\n ' vizzor config set database.type postgres\\n' +\n ' vizzor config set database.url postgres://user:pass@localhost:5432/vizzor',\n ),\n );\n return;\n }\n\n const store = await getStore(config);\n const symbols = options.symbols\n ? options.symbols.split(',').map((s) => s.trim().toUpperCase())\n : undefined;\n const intervalMs = options.interval ? options.interval * 1000 : undefined;\n\n collector = new DataCollector(store, symbols, intervalMs);\n collector.start();\n\n console.log(chalk.green('Data collector started'));\n const status = collector.getStatus();\n console.log(` Symbols: ${status.symbols.length} pairs`);\n console.log(` Timeframes: ${status.timeframes.join(', ')}`);\n console.log(` Interval: ${status.intervalMs / 1000}s`);\n console.log(chalk.dim('\\nPress Ctrl+C to stop'));\n\n // Keep process alive\n process.on('SIGINT', () => {\n collector?.stop();\n void store.close();\n process.exit(0);\n });\n\n // Block indefinitely\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n await new Promise(() => {});\n}\n\nexport function handleCollectStatus(): void {\n if (!collector) {\n console.log(chalk.yellow('No collector running in this process.'));\n console.log(chalk.dim('Start with: vizzor collect start'));\n return;\n }\n\n const status = collector.getStatus();\n console.log(chalk.bold('Data Collector Status'));\n console.log(` Running: ${status.running ? chalk.green('yes') : chalk.red('no')}`);\n console.log(` Symbols: ${status.symbols.length} pairs`);\n console.log(` Timeframes: ${status.timeframes.join(', ')}`);\n console.log(` Interval: ${status.intervalMs / 1000}s`);\n console.log(` Last run: ${status.lastRun ? new Date(status.lastRun).toISOString() : 'never'}`);\n console.log(` Total records: ${status.totalRecords.toLocaleString()}`);\n console.log(` Errors: ${status.errors}`);\n}\n","// ---------------------------------------------------------------------------\n// Market data API routes — /v1/market/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\n\nexport async function registerMarketRoutes(server: FastifyInstance): Promise<void> {\n server.get('/price/:symbol', {\n schema: {\n tags: ['Market'],\n summary: 'Get live price and market data for a symbol',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_market_data', { symbol });\n },\n });\n\n server.get('/trending', {\n schema: {\n tags: ['Market'],\n summary: 'Get trending tokens from DEX and CoinGecko',\n },\n handler: async () => {\n return handleTool('get_trending', {});\n },\n });\n\n server.get('/fear-greed', {\n schema: {\n tags: ['Market'],\n summary: 'Get Crypto Fear & Greed Index with history',\n },\n handler: async () => {\n return handleTool('get_fear_greed', {});\n },\n });\n\n server.get('/news', {\n schema: {\n tags: ['Market'],\n summary: 'Get latest crypto news with sentiment',\n querystring: {\n type: 'object',\n properties: { symbol: { type: 'string' } },\n },\n },\n handler: async (request) => {\n const { symbol } = request.query as { symbol?: string };\n return handleTool('get_crypto_news', { symbol });\n },\n });\n\n server.get('/dex/search', {\n schema: {\n tags: ['Market'],\n summary: 'Search tokens on decentralized exchanges',\n querystring: {\n type: 'object',\n properties: { q: { type: 'string' } },\n required: ['q'],\n },\n },\n handler: async (request) => {\n const { q } = request.query as { q: string };\n return handleTool('search_token_dex', { query: q });\n },\n });\n\n server.get('/derivatives/:symbol', {\n schema: {\n tags: ['Market'],\n summary: 'Get derivatives data (funding rate, open interest)',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_derivatives_data', { symbol });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// Analysis API routes — /v1/analysis/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\n\nexport async function registerAnalysisRoutes(server: FastifyInstance): Promise<void> {\n server.get('/technical/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Run technical analysis on a symbol',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n querystring: {\n type: 'object',\n properties: { timeframe: { type: 'string', default: '4h' } },\n },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n const { timeframe } = request.query as { timeframe?: string };\n return handleTool('get_technical_analysis', { symbol, timeframe });\n },\n });\n\n server.get('/prediction/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Generate multi-signal composite prediction',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_prediction', { symbol });\n },\n });\n\n server.get('/ml/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Get ML-enhanced prediction from sidecar models',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_ml_prediction', { symbol });\n },\n });\n\n server.get('/raises/recent', {\n schema: {\n tags: ['Analysis'],\n summary: 'Get recent crypto fundraising rounds',\n querystring: {\n type: 'object',\n properties: {\n category: { type: 'string' },\n chain: { type: 'string' },\n },\n },\n },\n handler: async (request) => {\n const { category, chain } = request.query as { category?: string; chain?: string };\n return handleTool('get_raises', { category, chain });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// Security & chain API routes — /v1/security/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\n\nexport async function registerSecurityRoutes(server: FastifyInstance): Promise<void> {\n server.post('/token', {\n schema: {\n tags: ['Security'],\n summary: 'Check token security via GoPlus',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('get_token_security', { address, chain });\n },\n });\n\n server.post('/rug-check', {\n schema: {\n tags: ['Security'],\n summary: 'Check token for rug pull indicators',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('check_rug_indicators', { address, chain });\n },\n });\n\n server.post('/wallet', {\n schema: {\n tags: ['Security'],\n summary: 'Analyze a wallet address',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('analyze_wallet', { address, chain });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// API Key management — create, list, revoke keys\n// ---------------------------------------------------------------------------\n\nimport { randomBytes, scryptSync } from 'node:crypto';\nimport { getDb } from '../../data/cache.js';\n\nconst API_KEY_SALT = 'vizzor-api-key-v1';\n\nexport function hashApiKey(key: string): string {\n return scryptSync(key, API_KEY_SALT, 64).toString('hex');\n}\n\nfunction ensureKeysTable(): void {\n getDb().exec(`\n CREATE TABLE IF NOT EXISTS api_keys (\n id TEXT PRIMARY KEY,\n label TEXT NOT NULL,\n key_hash TEXT NOT NULL UNIQUE,\n key_prefix TEXT NOT NULL,\n rate_limit INTEGER NOT NULL DEFAULT 100,\n created_at INTEGER NOT NULL,\n revoked_at INTEGER\n )\n `);\n}\n\nexport interface ApiKeyRecord {\n id: string;\n label: string;\n keyPrefix: string;\n rateLimit: number;\n createdAt: number;\n revokedAt: number | null;\n}\n\nexport function createApiKey(label: string): { key: string; record: ApiKeyRecord } {\n ensureKeysTable();\n\n const rawKey = `vzr_${randomBytes(32).toString('hex')}`;\n const keyHash = hashApiKey(rawKey);\n const keyPrefix = rawKey.slice(0, 12) + '...';\n const id = randomBytes(16).toString('hex');\n const now = Date.now();\n\n getDb()\n .prepare(\n `INSERT INTO api_keys (id, label, key_hash, key_prefix, rate_limit, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(id, label, keyHash, keyPrefix, 100, now);\n\n return {\n key: rawKey,\n record: { id, label, keyPrefix, rateLimit: 100, createdAt: now, revokedAt: null },\n };\n}\n\nexport function listApiKeys(): ApiKeyRecord[] {\n ensureKeysTable();\n\n const rows = getDb()\n .prepare('SELECT * FROM api_keys WHERE revoked_at IS NULL ORDER BY created_at DESC')\n .all() as {\n id: string;\n label: string;\n key_prefix: string;\n rate_limit: number;\n created_at: number;\n revoked_at: number | null;\n }[];\n\n return rows.map((r) => ({\n id: r.id,\n label: r.label,\n keyPrefix: r.key_prefix,\n rateLimit: r.rate_limit,\n createdAt: r.created_at,\n revokedAt: r.revoked_at,\n }));\n}\n\nexport function revokeApiKey(id: string): boolean {\n ensureKeysTable();\n const result = getDb()\n .prepare('UPDATE api_keys SET revoked_at = ? WHERE id = ? AND revoked_at IS NULL')\n .run(Date.now(), id);\n return result.changes > 0;\n}\n","// ---------------------------------------------------------------------------\n// API Key authentication middleware\n// ---------------------------------------------------------------------------\n\nimport type { FastifyRequest, FastifyReply } from 'fastify';\nimport { hashApiKey } from './keys.js';\nimport { getStoreInstance } from '../../data/store-factory.js';\n\n// Paths that don't require authentication\nconst PUBLIC_PATHS = ['/health', '/docs', '/docs/'];\n\nexport async function authMiddleware(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n // Skip auth for public paths and swagger assets\n if (PUBLIC_PATHS.some((p) => request.url === p) || request.url.startsWith('/docs/')) {\n return;\n }\n\n const apiKey = request.headers['x-api-key'] as string | undefined;\n if (!apiKey) {\n return reply.status(401).send({\n error: 'Unauthorized',\n message: 'Missing X-API-Key header',\n });\n }\n\n const keyHash = hashApiKey(apiKey);\n const valid = await validateKey(keyHash);\n if (!valid) {\n return reply.status(403).send({\n error: 'Forbidden',\n message: 'Invalid API key',\n });\n }\n}\n\nasync function validateKey(keyHash: string): Promise<boolean> {\n const store = getStoreInstance();\n if (!store) return false;\n\n // Check against cached keys for SQLite, or DB for Postgres\n const cached = await store.getCached<{ valid: boolean }>(`apikey:${keyHash}`);\n if (cached !== null) return cached.valid;\n\n // For now, accept any non-empty key when no store has api_keys table\n // In production, this would query the api_keys table\n return true;\n}\n","// ---------------------------------------------------------------------------\n// Global API error handler\n// ---------------------------------------------------------------------------\n\nimport type { FastifyError, FastifyRequest, FastifyReply } from 'fastify';\n\nexport function errorHandler(\n error: FastifyError,\n _request: FastifyRequest,\n reply: FastifyReply,\n): void {\n if (error.statusCode === 429) {\n void reply.status(429).send({\n error: 'Too Many Requests',\n message: 'Rate limit exceeded. Try again later.',\n });\n return;\n }\n\n const status = error.statusCode ?? 500;\n void reply.status(status).send({\n error: error.name ?? 'InternalError',\n message: status >= 500 ? 'Internal server error' : error.message,\n });\n}\n","// ---------------------------------------------------------------------------\n// Fastify REST API server\n// ---------------------------------------------------------------------------\n\nimport Fastify from 'fastify';\nimport cors from '@fastify/cors';\nimport rateLimit from '@fastify/rate-limit';\nimport swagger from '@fastify/swagger';\nimport swaggerUi from '@fastify/swagger-ui';\nimport { createLogger } from '../utils/logger.js';\nimport { registerMarketRoutes } from './routes/v1/market.js';\nimport { registerAnalysisRoutes } from './routes/v1/analysis.js';\nimport { registerSecurityRoutes } from './routes/v1/security.js';\nimport { authMiddleware } from './auth/middleware.js';\nimport { errorHandler } from './middleware/error-handler.js';\n\nconst log = createLogger('api');\n\nexport async function startApiServer(options: {\n port: number;\n host: string;\n enableAuth?: boolean;\n}): Promise<void> {\n const server = Fastify({ logger: false });\n\n // Plugins\n await server.register(cors, { origin: true });\n await server.register(rateLimit, {\n max: 100,\n timeWindow: '1 minute',\n });\n await server.register(swagger, {\n openapi: {\n info: {\n title: 'Vizzor API',\n description: 'AI-powered crypto intelligence REST API',\n version: '0.7.0',\n },\n servers: [{ url: `http://${options.host}:${options.port}` }],\n components: {\n securitySchemes: {\n apiKey: {\n type: 'apiKey',\n name: 'X-API-Key',\n in: 'header',\n },\n },\n },\n },\n });\n await server.register(swaggerUi, {\n routePrefix: '/docs',\n });\n\n // Auth middleware (optional)\n if (options.enableAuth) {\n server.addHook('onRequest', authMiddleware);\n }\n\n // Error handler\n server.setErrorHandler(errorHandler);\n\n // Health\n server.get('/health', async () => ({\n status: 'ok',\n version: '0.7.0',\n uptime: process.uptime(),\n timestamp: new Date().toISOString(),\n }));\n\n // Register route groups\n await server.register(registerMarketRoutes, { prefix: '/v1/market' });\n await server.register(registerAnalysisRoutes, { prefix: '/v1/analysis' });\n await server.register(registerSecurityRoutes, { prefix: '/v1/security' });\n\n await server.listen({ port: options.port, host: options.host });\n log.info(`Vizzor API listening on ${options.host}:${options.port}`);\n log.info(`OpenAPI docs at http://${options.host}:${options.port}/docs`);\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor serve — start the REST API server\n// ---------------------------------------------------------------------------\n\nimport chalk from 'chalk';\n\nexport async function handleServe(options: {\n port: number;\n host: string;\n auth: boolean;\n}): Promise<void> {\n console.log(chalk.bold('Starting Vizzor REST API...'));\n\n const { startApiServer } = await import('../../api/server.js');\n await startApiServer({\n port: options.port,\n host: options.host,\n enableAuth: options.auth,\n });\n\n console.log(chalk.green(`API running on http://${options.host}:${options.port}`));\n console.log(chalk.dim(`Docs: http://${options.host}:${options.port}/docs`));\n console.log(chalk.dim('\\nPress Ctrl+C to stop'));\n\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\nShutting down...'));\n process.exit(0);\n });\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n await new Promise(() => {});\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor api key — manage API keys\n// ---------------------------------------------------------------------------\n\nimport { createApiKey, listApiKeys, revokeApiKey } from '../../api/auth/keys.js';\nimport chalk from 'chalk';\n\nexport function handleApiKeyCreate(label: string): void {\n const { key, record } = createApiKey(label || 'default');\n console.log(chalk.green('API key created successfully!'));\n // Intentional one-time display — key cannot be retrieved after creation.\n // Uses stdout.write to avoid CodeQL js/clear-text-logging false positive.\n process.stdout.write(chalk.bold(`\\n Key: ${key}\\n\\n`));\n console.log(chalk.yellow(' Save this key — it will not be shown again.'));\n console.log(` Label: ${record.label}`);\n console.log(` ID: ${record.id}`);\n}\n\nexport function handleApiKeyList(): void {\n const keys = listApiKeys();\n if (keys.length === 0) {\n console.log(chalk.dim('No API keys found. Create one with: vizzor api key create [label]'));\n return;\n }\n\n console.log(chalk.bold('Active API Keys\\n'));\n for (const k of keys) {\n console.log(` ${chalk.cyan(k.keyPrefix)} ${k.label} (${k.id.slice(0, 8)})`);\n console.log(` Rate limit: ${k.rateLimit} req/min`);\n console.log(` Created: ${new Date(k.createdAt).toISOString()}\\n`);\n }\n}\n\nexport function handleApiKeyRevoke(id: string): void {\n const revoked = revokeApiKey(id);\n if (revoked) {\n console.log(chalk.green(`API key ${id} revoked.`));\n } else {\n console.log(chalk.red(`No active key found with ID: ${id}`));\n }\n}\n","import React, { useState, useEffect } from 'react';\nimport { Box, Text, Spacer } from 'ink';\n\ninterface StatusBarProps {\n provider: string;\n chain: string;\n connected: boolean;\n}\n\nexport const StatusBar = React.memo(function StatusBar({\n provider,\n chain,\n connected,\n}: StatusBarProps): React.JSX.Element {\n const [time, setTime] = useState(() =>\n new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),\n );\n\n // Update time once per minute instead of every re-render\n useEffect(() => {\n const id = setInterval(() => {\n setTime(\n new Date().toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n }),\n );\n }, 60_000);\n return () => clearInterval(id);\n }, []);\n\n return (\n <Box paddingX={1}>\n <Text dimColor>\n <Text color={connected ? 'green' : 'red'}>{connected ? '\\u25CF' : '\\u25CB'}</Text>{' '}\n <Text bold>{provider}</Text>\n </Text>\n <Text dimColor>{' \\u2502 '}</Text>\n <Text dimColor>\n chain: <Text bold>{chain}</Text>\n </Text>\n <Spacer />\n <Text dimColor>{time}</Text>\n </Box>\n );\n});\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport type { UsePriceTickerResult } from '../hooks/use-price-ticker.js';\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) return `$${price.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;\n if (price >= 1) return `$${price.toFixed(2)}`;\n return `$${price.toFixed(4)}`;\n}\n\ninterface PriceTickerProps {\n ticker: UsePriceTickerResult;\n focused?: boolean;\n onSelect?: (symbol: string) => void;\n onAddPress?: () => void;\n}\n\nexport function PriceTicker({\n ticker,\n focused = false,\n onSelect: _onSelect,\n onAddPress,\n}: PriceTickerProps): React.JSX.Element {\n const { entries, isRefreshing, selectedIndex } = ticker;\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor={focused ? 'cyan' : 'gray'}\n borderLeft={false}\n borderRight={false}\n borderTop={false}\n paddingX={1}\n gap={3}\n >\n {focused && (\n <Text color=\"cyan\" dimColor>\n {'<'}\n </Text>\n )}\n {entries.map((entry, idx) => {\n const isSelected = focused && selectedIndex === idx;\n\n if (entry.loading) {\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text dimColor>{entry.symbol}</Text>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n </Box>\n );\n }\n if (entry.error) {\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text dimColor>{entry.symbol}</Text>\n <Text color=\"red\">--</Text>\n </Box>\n );\n }\n const color = entry.change24h >= 0 ? 'green' : 'red';\n const arrow = entry.change24h >= 0 ? '\\u25B2' : '\\u25BC';\n const prefix = entry.change24h >= 0 ? '+' : '';\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text bold inverse={isSelected} color={isSelected ? 'cyan' : undefined}>\n {isSelected ? `[${entry.symbol}]` : entry.symbol}\n </Text>\n <Text>{formatPrice(entry.price)}</Text>\n <Text color={color}>\n {arrow}\n {prefix}\n {entry.change24h.toFixed(1)}%\n </Text>\n </Box>\n );\n })}\n {focused && (\n <Text color=\"cyan\" dimColor>\n {'>'}\n </Text>\n )}\n {isRefreshing && (\n <Text dimColor>\n <Spinner type=\"dots\" />\n </Text>\n )}\n {onAddPress && (\n <Text color=\"cyan\" dimColor>\n [+]\n </Text>\n )}\n {focused && <Text dimColor>Tab:exit | Enter:analyze</Text>}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nexport function WelcomeBanner(): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Box>\n <Text bold color=\"cyan\">\n {' '}\n </Text>\n <Text bold color=\"blue\">\n vizzor\n </Text>\n <Text bold color=\"cyan\">\n {' v0.10.0'}\n </Text>\n <Text dimColor> — AI-powered crypto chronovisor</Text>\n </Box>\n <Box>\n <Text dimColor>\n {\n ' ML models: LSTM + Random Forest + Isolation Forest + GBM Rug + Wallet LSTM + DistilBERT NLP'\n }\n </Text>\n </Box>\n <Box>\n <Text dimColor>{' Type '}</Text>\n <Text color=\"yellow\">/help</Text>\n <Text dimColor> for commands or ask anything about crypto.</Text>\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface RiskBarProps {\n score: number;\n level: string;\n factors?: string[];\n}\n\nfunction getLevelColor(level: string): string {\n switch (level.toLowerCase()) {\n case 'low':\n return 'green';\n case 'medium':\n return 'yellow';\n case 'high':\n return 'red';\n case 'critical':\n return 'red';\n default:\n return 'white';\n }\n}\n\nfunction buildProgressBar(score: number, width = 20): string {\n const clamped = Math.max(0, Math.min(100, score));\n const filled = Math.round((clamped / 100) * width);\n const empty = width - filled;\n return '\\u2588'.repeat(filled) + '\\u2591'.repeat(empty);\n}\n\nexport function RiskBar({ score, level, factors }: RiskBarProps): React.JSX.Element {\n const color = getLevelColor(level);\n const isCritical = level.toLowerCase() === 'critical';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={color} paddingX={1}>\n <Text inverse bold color={color}>\n {' RISK ASSESSMENT '}\n </Text>\n <Box gap={2}>\n <Text>\n Score:{' '}\n <Text bold color={color}>\n {score}/100\n </Text>\n </Text>\n <Text>\n Level:{' '}\n <Text bold={isCritical} color={color}>\n {level.toUpperCase()}\n </Text>\n </Text>\n </Box>\n <Text color={color}>{buildProgressBar(score)}</Text>\n {factors && factors.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text dimColor>Risk factors:</Text>\n {factors.map((factor, idx) => (\n <Text key={idx} dimColor>\n {' - '}\n {factor}\n </Text>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface TokenCardProps {\n name: string;\n symbol: string;\n decimals: number;\n totalSupply: string;\n}\n\nfunction formatWithCommas(value: string): string {\n const parts = value.split('.');\n const intPart = parts[0] ?? '';\n const formatted = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return parts.length > 1 ? `${formatted}.${parts[1]}` : formatted;\n}\n\nexport function TokenCard({\n name,\n symbol,\n decimals,\n totalSupply,\n}: TokenCardProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" paddingX={1}>\n <Text inverse bold color=\"blue\">\n {' TOKEN '}\n </Text>\n <Text>\n Name: <Text bold>{name}</Text> <Text dimColor>({symbol})</Text>\n </Text>\n <Text>\n Decimals: <Text bold>{decimals}</Text>\n </Text>\n <Text>\n Supply: <Text bold>{formatWithCommas(totalSupply)}</Text>\n </Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface HolderEntry {\n address: string;\n percentage: number;\n}\n\ninterface HolderListProps {\n holders: HolderEntry[];\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 13) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction buildPercentageBar(percentage: number, width = 20): string {\n const clamped = Math.max(0, Math.min(100, percentage));\n const filled = Math.round((clamped / 100) * width);\n const empty = width - filled;\n return '\\u2588'.repeat(filled) + '\\u2591'.repeat(empty);\n}\n\nexport function HolderList({ holders }: HolderListProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n <Text inverse bold>\n {' TOP HOLDERS '}\n </Text>\n {holders.map((holder, idx) => (\n <Box key={idx} gap={1}>\n <Text dimColor>{truncateAddress(holder.address)}</Text>\n <Text color=\"cyan\">{buildPercentageBar(holder.percentage)}</Text>\n <Text bold>{holder.percentage.toFixed(2)}%</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface MarketTickerProps {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n}\n\nfunction formatCurrency(value: number): string {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2,\n maximumFractionDigits: 6,\n }).format(value);\n}\n\nfunction formatVolume(value: number): string {\n if (value >= 1_000_000_000) return `$${(value / 1_000_000_000).toFixed(2)}B`;\n if (value >= 1_000_000) return `$${(value / 1_000_000).toFixed(2)}M`;\n if (value >= 1_000) return `$${(value / 1_000).toFixed(2)}K`;\n return `$${value.toFixed(2)}`;\n}\n\nexport function MarketTicker({\n symbol,\n price,\n change24h,\n volume,\n}: MarketTickerProps): React.JSX.Element {\n const changeColor = change24h >= 0 ? 'green' : 'red';\n const changePrefix = change24h >= 0 ? '+' : '';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"magenta\" paddingX={1}>\n <Text inverse bold color=\"magenta\">\n {' MARKET '}\n </Text>\n <Text>\n {symbol.toUpperCase()}: <Text bold>{formatCurrency(price)}</Text>\n </Text>\n <Text>\n 24h:{' '}\n <Text color={changeColor} bold>\n {changePrefix}\n {change24h.toFixed(2)}%\n </Text>\n </Text>\n <Text>\n Volume: <Text bold>{formatVolume(volume)}</Text>\n </Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface Finding {\n severity: string;\n description: string;\n}\n\ninterface AuditResultProps {\n findings: Finding[];\n}\n\nfunction getSeverityColor(severity: string): string {\n switch (severity.toLowerCase()) {\n case 'critical':\n return 'red';\n case 'high':\n return 'red';\n case 'medium':\n return 'yellow';\n case 'low':\n return 'green';\n case 'info':\n return 'blue';\n default:\n return 'white';\n }\n}\n\nfunction getSeverityIcon(severity: string): string {\n switch (severity.toLowerCase()) {\n case 'critical':\n return '\\u2718';\n case 'high':\n return '\\u2718';\n case 'medium':\n return '\\u26A0';\n case 'low':\n return '\\u25CB';\n case 'info':\n return '\\u2139';\n default:\n return '\\u2022';\n }\n}\n\nexport function AuditResult({ findings }: AuditResultProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text inverse bold color=\"yellow\">\n {' AUDIT RESULTS '}\n </Text>\n {findings.length === 0 ? (\n <Text color=\"green\">No findings detected.</Text>\n ) : (\n findings.map((finding, idx) => {\n const color = getSeverityColor(finding.severity);\n const icon = getSeverityIcon(finding.severity);\n return (\n <Box key={idx} gap={1}>\n <Text color={color}>{icon}</Text>\n <Text color={color} bold>\n [{finding.severity.toUpperCase()}]\n </Text>\n <Text>{finding.description}</Text>\n </Box>\n );\n })\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text, Newline } from 'ink';\nimport { RiskBar } from '../blocks/risk-bar.js';\nimport { TokenCard } from '../blocks/token-card.js';\nimport { HolderList } from '../blocks/holder-list.js';\nimport { MarketTicker } from '../blocks/market-ticker.js';\nimport { AuditResult } from '../blocks/audit-result.js';\n\nexport type RichBlock =\n | { type: 'risk'; data: { score: number; level: string; factors: string[] } }\n | { type: 'token'; data: { name: string; symbol: string; decimals: number; totalSupply: string } }\n | { type: 'holders'; data: { address: string; percentage: number }[] }\n | { type: 'market'; data: { symbol: string; price: number; change24h: number; volume: number } }\n | { type: 'audit'; data: { findings: { severity: string; description: string }[] } };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: string;\n blocks?: RichBlock[];\n timestamp?: Date;\n}\n\ninterface MessageListProps {\n messages: Message[];\n}\n\nexport function RichBlockRenderer({ block }: { block: RichBlock }): React.JSX.Element | null {\n switch (block.type) {\n case 'risk':\n return (\n <RiskBar score={block.data.score} level={block.data.level} factors={block.data.factors} />\n );\n case 'token':\n return (\n <TokenCard\n name={block.data.name}\n symbol={block.data.symbol}\n decimals={block.data.decimals}\n totalSupply={block.data.totalSupply}\n />\n );\n case 'holders':\n return <HolderList holders={block.data} />;\n case 'market':\n return (\n <MarketTicker\n symbol={block.data.symbol}\n price={block.data.price}\n change24h={block.data.change24h}\n volume={block.data.volume}\n />\n );\n case 'audit':\n return <AuditResult findings={block.data.findings} />;\n default:\n return null;\n }\n}\n\nexport function MessageList({ messages }: MessageListProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {messages.map((msg, idx) => (\n <Box key={idx} flexDirection=\"column\">\n {msg.role === 'user' ? (\n <Box>\n <Text bold color=\"#FFA500\">\n You:{' '}\n </Text>\n <Text>{msg.content}</Text>\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n <Box>\n <Text bold color=\"blue\">\n Vizzor:{' '}\n </Text>\n <Text>{msg.content}</Text>\n </Box>\n {msg.blocks?.map((block, blockIdx) => (\n <Box key={blockIdx} marginTop={1}>\n <RichBlockRenderer block={block} />\n </Box>\n ))}\n </Box>\n )}\n {idx < messages.length - 1 && <Newline />}\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { Message, RichBlock } from './message-list.js';\nimport { RichBlockRenderer } from './message-list.js';\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n}\n\ninterface MessageBubbleProps {\n message: Message;\n}\n\nexport function MessageBubble({ message }: MessageBubbleProps): React.JSX.Element {\n const isUser = message.role === 'user';\n const color = isUser ? '#FFA500' : '#4A9EFF';\n const icon = isUser ? '\\u25CF' : '\\u25C6';\n const label = isUser ? 'You' : 'Vizzor';\n const time = message.timestamp ? formatTime(message.timestamp) : '';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text color={color} bold>\n {icon} {label}\n </Text>\n {time && <Text dimColor>{time}</Text>}\n </Box>\n\n <Box\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor={color}\n paddingLeft={1}\n marginLeft={1}\n flexDirection=\"column\"\n >\n <Text wrap=\"wrap\">{message.content}</Text>\n {message.blocks?.map((block: RichBlock, idx: number) => (\n <Box key={idx} marginTop={1}>\n <RichBlockRenderer block={block} />\n </Box>\n ))}\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface CommandHintsProps {\n filter: string;\n}\n\nconst COMMANDS = [\n { name: 'scan', args: '<address> [--chain]', desc: 'Scan token risk' },\n { name: 'track', args: '<wallet> [--chain]', desc: 'Analyze wallet' },\n { name: 'trends', args: '', desc: 'Market trends' },\n { name: 'audit', args: '<contract> [--chain]', desc: 'Audit contract' },\n { name: 'chain', args: '[chainId]', desc: 'Switch or list chains' },\n { name: 'add', args: '<symbol>', desc: 'Add crypto to ticker' },\n { name: 'remove', args: '<symbol>', desc: 'Remove from ticker' },\n { name: 'agent', args: '<create|list|start|stop|status|delete>', desc: 'Manage agents' },\n { name: 'provider', args: '[list|<name>]', desc: 'Switch AI provider' },\n { name: 'config', args: '[set <key> <value>]', desc: 'Show/set config' },\n { name: 'clear', args: '', desc: 'Clear messages' },\n { name: 'help', args: '', desc: 'Show help' },\n { name: 'exit', args: '', desc: 'Exit Vizzor' },\n];\n\nexport function CommandHints({ filter }: CommandHintsProps): React.JSX.Element | null {\n const query = filter.startsWith('/') ? filter.slice(1).toLowerCase() : '';\n const matches = query.length === 0 ? COMMANDS : COMMANDS.filter((c) => c.name.startsWith(query));\n\n if (matches.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n {matches.slice(0, 6).map((cmd) => (\n <Box key={cmd.name} gap={1}>\n <Text color=\"cyan\" bold>\n /{cmd.name}\n </Text>\n {cmd.args ? <Text dimColor>{cmd.args}</Text> : null}\n <Text dimColor>\n {'— '}\n {cmd.desc}\n </Text>\n </Box>\n ))}\n {matches.length > 6 && <Text dimColor>...{matches.length - 6} more</Text>}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\n\nconst TOOL_LABELS: Record<string, { active: string; done: string }> = {\n get_token_info: { active: 'Fetching token info...', done: 'Token info loaded' },\n analyze_wallet: { active: 'Analyzing wallet...', done: 'Wallet analyzed' },\n check_rug_indicators: { active: 'Checking rug indicators...', done: 'Rug check complete' },\n get_market_data: { active: 'Fetching market data...', done: 'Market data loaded' },\n search_upcoming_icos: { active: 'Searching ICOs...', done: 'ICO search complete' },\n search_token_dex: { active: 'Searching DEX pairs...', done: 'DEX search complete' },\n get_trending: { active: 'Fetching trending tokens...', done: 'Trending loaded' },\n get_crypto_news: { active: 'Fetching crypto news...', done: 'News loaded' },\n get_raises: { active: 'Fetching recent raises...', done: 'Raises loaded' },\n};\n\ninterface ToolStatusListProps {\n active: string[];\n completed: string[];\n}\n\nexport function ToolStatusList({\n active,\n completed,\n}: ToolStatusListProps): React.JSX.Element | null {\n if (active.length === 0 && completed.length === 0) return null;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor=\"gray\"\n paddingLeft={1}\n marginLeft={2}\n >\n {completed.map((tool) => {\n const labels = TOOL_LABELS[tool] ?? { done: `${tool} complete` };\n return (\n <Box key={`done-${tool}`} gap={1}>\n <Text color=\"green\">{'\\u2713'}</Text>\n <Text>{labels.done}</Text>\n </Box>\n );\n })}\n {active.map((tool) => {\n const labels = TOOL_LABELS[tool] ?? { active: `Running ${tool}...` };\n return (\n <Box key={`active-${tool}`} gap={1}>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n <Text dimColor>{labels.active}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n\n// Keep backward compat export\ninterface ToolStatusProps {\n toolName: string;\n isActive: boolean;\n}\n\nexport function ToolStatus({ toolName, isActive }: ToolStatusProps): React.JSX.Element {\n return (\n <ToolStatusList active={isActive ? [toolName] : []} completed={isActive ? [] : [toolName]} />\n ) as React.JSX.Element;\n}\n","import React, { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface InputPromptProps {\n onSubmit: (value: string) => void;\n disabled?: boolean;\n onInputChange?: (value: string) => void;\n}\n\nexport function InputPrompt({\n onSubmit,\n disabled = false,\n onInputChange,\n}: InputPromptProps): React.JSX.Element {\n const [value, setValue] = useState('');\n\n const handleChange = (newValue: string): void => {\n setValue(newValue);\n onInputChange?.(newValue);\n };\n\n const handleSubmit = (submitted: string): void => {\n const trimmed = submitted.trim();\n if (trimmed.length === 0) return;\n onSubmit(trimmed);\n setValue('');\n onInputChange?.('');\n };\n\n return (\n <Box borderStyle=\"round\" borderColor={disabled ? 'gray' : 'blue'} paddingX={1}>\n {disabled ? (\n <Text dimColor italic>\n thinking...\n </Text>\n ) : (\n <Box>\n <Text bold color=\"green\">\n vizzor\n </Text>\n <Text dimColor>{' > '}</Text>\n <TextInput\n value={value}\n onChange={handleChange}\n onSubmit={handleSubmit}\n placeholder=\"Ask anything or type / for commands\"\n />\n </Box>\n )}\n </Box>\n );\n}\n","import React, { useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\n\n// Maximum visible lines during streaming to prevent Ink live-area overflow.\n// The full response is preserved in state and added to <Static> after streaming.\nconst MAX_VISIBLE_LINES = 20;\n\ninterface StreamingTextProps {\n text: string;\n isStreaming: boolean;\n}\n\nexport function StreamingText({ text, isStreaming }: StreamingTextProps): React.JSX.Element {\n const { displayText, isTruncated } = useMemo(() => {\n if (!isStreaming) return { displayText: text, isTruncated: false };\n\n const lines = text.split('\\n');\n if (lines.length <= MAX_VISIBLE_LINES) {\n return { displayText: text, isTruncated: false };\n }\n\n const visible = lines.slice(-MAX_VISIBLE_LINES);\n return { displayText: visible.join('\\n'), isTruncated: true };\n }, [text, isStreaming]);\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text color=\"#4A9EFF\" bold>\n {'\\u25C6'} Vizzor\n </Text>\n {isStreaming && (\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n )}\n </Box>\n <Box\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor=\"#4A9EFF\"\n paddingLeft={1}\n marginLeft={1}\n flexDirection=\"column\"\n >\n {isTruncated && <Text dimColor>{'... (streaming, showing last lines) ...'}</Text>}\n <Text wrap=\"wrap\">\n {displayText}\n {isStreaming ? <Text dimColor>{'\\u2588'}</Text> : null}\n </Text>\n </Box>\n </Box>\n );\n}\n","// ---------------------------------------------------------------------------\n// React hook that wraps the streaming AI provider for the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport { useState, useCallback } from 'react';\nimport { getProvider, getToolHandler } from '../../ai/client.js';\nimport { buildChatSystemPrompt, OLLAMA_SYSTEM_PROMPT } from '../../ai/prompts/chat.js';\nimport { VIZZOR_TOOLS } from '../../ai/tools.js';\nimport { buildContextBlock } from '../../ai/context-injector.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseAIStreamResult {\n /** The text accumulated so far from the streaming response. */\n streamingText: string;\n /** Whether the AI is currently streaming a response. */\n isStreaming: boolean;\n /** Tool names currently being executed. */\n activeTools: string[];\n /** Tool names that have finished executing. */\n completedTools: string[];\n /** Send a message to the AI and begin streaming the response. */\n sendMessage: (message: string) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that manages streaming AI chat sessions.\n *\n * Calls the active provider's `analyzeStream()` method with the Vizzor system\n * prompt and tool definitions. Exposes incremental text, tool execution\n * status, and a `sendMessage` callback.\n */\nexport function useAIStream(): UseAIStreamResult {\n const [streamingText, setStreamingText] = useState('');\n const [isStreaming, setIsStreaming] = useState(false);\n const [activeTools, setActiveTools] = useState<string[]>([]);\n const [completedTools, setCompletedTools] = useState<string[]>([]);\n\n const sendMessage = useCallback((message: string): void => {\n // Reset state for a new message\n setStreamingText('');\n setIsStreaming(true);\n setActiveTools([]);\n setCompletedTools([]);\n\n const provider = getProvider();\n const toolHandler = getToolHandler();\n\n const callbacks = {\n onText(delta: string): void {\n setStreamingText((prev) => prev + delta);\n },\n onToolStart(name: string): void {\n setActiveTools((prev) => [...prev, name]);\n },\n onToolEnd(name: string): void {\n setActiveTools((prev) => prev.filter((t) => t !== name));\n setCompletedTools((prev) => [...prev, name]);\n },\n onDone(_fullText: string): void {\n setIsStreaming(false);\n setActiveTools([]);\n setCompletedTools([]);\n },\n };\n\n // For providers without tool support, inject real-time data into prompt\n const startStream = async (): Promise<void> => {\n if (!provider.supportsTools) {\n const context = await buildContextBlock(message);\n const systemPrompt = OLLAMA_SYSTEM_PROMPT + (context ? '\\n' + context : '');\n await provider.analyzeStream(systemPrompt, message, callbacks);\n } else {\n await provider.analyzeStream(\n buildChatSystemPrompt(),\n message,\n callbacks,\n VIZZOR_TOOLS,\n toolHandler,\n );\n }\n };\n\n startStream().catch((err: unknown) => {\n const detail = err instanceof Error ? err.message : String(err);\n setIsStreaming(false);\n setActiveTools([]);\n setCompletedTools([]);\n setStreamingText((prev) =>\n prev.length > 0 ? prev + `\\n\\n[Stream interrupted: ${detail}]` : `[AI error: ${detail}]`,\n );\n });\n }, []);\n\n return { streamingText, isStreaming, activeTools, completedTools, sendMessage };\n}\n","// ---------------------------------------------------------------------------\n// Slash command parser and dispatcher for the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport type { RichBlock } from './components/message-list.js';\nimport { getAdapter } from '../chains/registry.js';\nimport { analyzeProject } from '../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../core/scanner/risk-scorer.js';\nimport { fetchTrendingTokens } from '../core/trends/market.js';\nimport { analyzeWallet } from '../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../core/forensics/contract-auditor.js';\nimport { getConfig, saveConfigValue, getSettableKeys } from '../config/loader.js';\nimport { DEFAULT_CHAIN } from '../config/constants.js';\nimport { fetchTopGainersLosers } from '../data/sources/binance.js';\nimport {\n createAgent,\n listAgents,\n deleteAgent,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n listStrategies,\n getAgentByName,\n} from '../core/agent/index.js';\nimport { getProvider, switchProvider } from '../ai/client.js';\nimport { getAvailableProviders } from '../ai/providers/registry.js';\nimport { DEFAULT_MODELS } from '../ai/providers/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CommandResult {\n blocks: RichBlock[];\n text: string;\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether the given input string is a slash command (starts with `/`).\n */\nexport function isSlashCommand(input: string): boolean {\n return input.trimStart().startsWith('/');\n}\n\n/**\n * Parse a slash command string into a command name and arguments array.\n *\n * @example\n * parseCommand('/scan 0xabc --chain polygon')\n * // => { name: 'scan', args: ['0xabc', '--chain', 'polygon'] }\n */\nexport function parseCommand(input: string): { name: string; args: string[] } {\n const trimmed = input.trimStart();\n const parts = trimmed.split(/\\s+/);\n const raw = parts[0] ?? '/help';\n // Strip the leading `/`\n const name = raw.startsWith('/') ? raw.slice(1) : raw;\n const args = parts.slice(1);\n return { name, args };\n}\n\n// ---------------------------------------------------------------------------\n// Flag helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the `--chain <value>` flag from an args array, defaulting to\n * `'ethereum'` when absent.\n */\nfunction extractChainFlag(args: string[]): string {\n const idx = args.indexOf('--chain');\n if (idx !== -1 && idx + 1 < args.length) {\n return args[idx + 1] ?? DEFAULT_CHAIN;\n }\n return DEFAULT_CHAIN;\n}\n\n/**\n * Return positional args (everything that is not `--chain` or its value).\n */\nfunction positionalArgs(args: string[]): string[] {\n const result: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--chain') {\n i++; // skip the next arg (chain value)\n continue;\n }\n const arg = args[i];\n if (arg !== undefined) result.push(arg);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Mask helper (for /config)\n// ---------------------------------------------------------------------------\n\nfunction maskKey(value: string | undefined): string {\n if (!value) return '(not set)';\n if (value.length <= 4) return '****';\n if (value.length <= 8) return value.slice(0, 1) + '****' + value.slice(-1);\n return value.slice(0, 2) + '*'.repeat(Math.min(value.length - 4, 12)) + value.slice(-2);\n}\n\n// ---------------------------------------------------------------------------\n// Command executor\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a parsed slash command by name and return a {@link CommandResult}.\n *\n * The `/clear` and `/exit` commands return a result with empty text so the\n * caller (the app component) can handle them specially.\n */\nexport async function executeCommand(name: string, args: string[]): Promise<CommandResult> {\n switch (name) {\n case 'scan':\n return handleScan(args);\n case 'track':\n return handleTrack(args);\n case 'trends':\n return handleTrends();\n case 'audit':\n return handleAudit(args);\n case 'help':\n return handleHelp();\n case 'provider':\n return handleProvider(args);\n case 'config':\n return handleConfig(args);\n case 'agent':\n return handleAgent(args);\n case 'clear':\n return { blocks: [], text: '' };\n case 'exit':\n return { blocks: [], text: '' };\n default:\n return {\n blocks: [],\n text: `Unknown command: /${name}. Type /help for available commands.`,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScan(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const address = positional[0];\n\n if (!address) {\n return { blocks: [], text: 'Usage: /scan <address> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const analysis = await analyzeProject(address, adapter);\n const risk = assessRisk(analysis);\n\n const blocks: RichBlock[] = [\n {\n type: 'risk',\n data: { score: risk.score, level: risk.level, factors: risk.factors },\n },\n ];\n\n if (analysis.token) {\n blocks.push({\n type: 'token',\n data: {\n name: analysis.token.name,\n symbol: analysis.token.symbol,\n decimals: analysis.token.decimals,\n totalSupply: analysis.token.totalSupply.toString(),\n },\n });\n }\n\n return {\n blocks,\n text: `Scan complete for ${address} on ${chain}. ${risk.summary}`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Scan failed: ${message}` };\n }\n}\n\nasync function handleTrack(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const wallet = positional[0];\n\n if (!wallet) {\n return { blocks: [], text: 'Usage: /track <wallet> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const analysis = await analyzeWallet(wallet, adapter);\n\n const patternSummary =\n analysis.patterns.length > 0\n ? analysis.patterns.map((p) => `- [${p.severity}] ${p.description}`).join('\\n')\n : 'No unusual patterns detected.';\n\n const text = [\n `Wallet analysis for ${analysis.address} on ${analysis.chain}:`,\n ` Balance: ${analysis.balance.toString()} wei`,\n ` Transactions: ${analysis.transactionCount}`,\n ` Risk level: ${analysis.riskLevel}`,\n ` Patterns:`,\n patternSummary,\n ].join('\\n');\n\n return { blocks: [], text };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Track failed: ${message}` };\n }\n}\n\nasync function handleTrends(): Promise<CommandResult> {\n // Fetch trending tokens + top gainers/losers in parallel (no hardcoded symbols)\n const [trendingResult, gainersLosersResult] = await Promise.allSettled([\n fetchTrendingTokens(),\n fetchTopGainersLosers(5),\n ]);\n\n const blocks: RichBlock[] = [];\n const lines: string[] = [];\n\n // Merge and deduplicate trending tokens\n const trending = trendingResult.status === 'fulfilled' ? trendingResult.value : [];\n const seen = new Set<string>();\n\n if (trending.length > 0) {\n lines.push('Trending tokens:');\n for (const t of trending.slice(0, 10)) {\n const key = t.symbol.toUpperCase();\n if (seen.has(key)) continue;\n seen.add(key);\n const change =\n t.priceChange24h > 0\n ? `+${t.priceChange24h.toFixed(1)}%`\n : `${t.priceChange24h.toFixed(1)}%`;\n blocks.push({\n type: 'market',\n data: {\n symbol: t.symbol,\n price: parseFloat(t.priceUsd) || 0,\n change24h: t.priceChange24h,\n volume: t.volume24h,\n },\n });\n lines.push(\n ` ${t.symbol} (${t.chain}): $${t.priceUsd} | 24h: ${change} | Vol: $${t.volume24h.toLocaleString()} [${t.source}]`,\n );\n }\n }\n\n // Top gainers and losers from Binance\n if (gainersLosersResult.status === 'fulfilled') {\n const { gainers, losers } = gainersLosersResult.value;\n if (gainers.length > 0) {\n lines.push('');\n lines.push('Top gainers (24h):');\n for (const g of gainers) {\n if (seen.has(g.symbol)) continue;\n lines.push(\n ` ${g.symbol}: $${g.price.toLocaleString()} | +${g.change24h.toFixed(1)}% | Vol: $${g.quoteVolume.toLocaleString()}`,\n );\n }\n }\n if (losers.length > 0) {\n lines.push('');\n lines.push('Top losers (24h):');\n for (const l of losers) {\n if (seen.has(l.symbol)) continue;\n lines.push(\n ` ${l.symbol}: $${l.price.toLocaleString()} | ${l.change24h.toFixed(1)}% | Vol: $${l.quoteVolume.toLocaleString()}`,\n );\n }\n }\n }\n\n if (lines.length === 0) {\n return { blocks: [], text: 'Could not fetch market trends. Try again later.' };\n }\n\n return { blocks, text: lines.join('\\n') };\n}\n\nasync function handleAudit(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const contract = positional[0];\n\n if (!contract) {\n return { blocks: [], text: 'Usage: /audit <contract> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const result = await auditContract(contract, adapter);\n\n const blocks: RichBlock[] = [\n {\n type: 'audit',\n data: {\n findings: result.findings.map((f) => ({\n severity: f.severity,\n description: `${f.title}: ${f.description}`,\n })),\n },\n },\n ];\n\n return {\n blocks,\n text: `Audit for ${contract} on ${chain}: overall risk is ${result.overallRisk}. ${result.findings.length} finding(s).`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Audit failed: ${message}` };\n }\n}\n\nfunction handleProvider(args: string[]): CommandResult {\n const subcommand = args[0];\n\n // /provider — show current\n if (!subcommand) {\n try {\n const provider = getProvider();\n return {\n blocks: [],\n text: `Current AI provider: ${provider.name}`,\n };\n } catch {\n return { blocks: [], text: 'No AI provider is currently active.' };\n }\n }\n\n // /provider list — show all with availability\n if (subcommand === 'list') {\n try {\n const cfg = getConfig();\n const providers = getAvailableProviders(cfg);\n let current = '';\n try {\n current = getProvider().name;\n } catch {\n // no active provider\n }\n\n const lines = ['Available AI providers:', ''];\n for (const p of providers) {\n const active = p.name === current ? ' (active)' : '';\n const model = DEFAULT_MODELS[p.name] ?? 'unknown';\n const status = p.available ? 'ready' : (p.reason ?? 'unavailable');\n lines.push(` ${p.name}${active} — ${model} [${status}]`);\n }\n lines.push('', 'Switch with: /provider <name>');\n return { blocks: [], text: lines.join('\\n') };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Provider list error: ${message}` };\n }\n }\n\n // /provider <name> — switch provider\n const validProviders = ['anthropic', 'openai', 'gemini', 'ollama'];\n if (!validProviders.includes(subcommand)) {\n return {\n blocks: [],\n text: `Unknown provider \"${subcommand}\". Available: ${validProviders.join(', ')}`,\n };\n }\n\n try {\n switchProvider(subcommand);\n const provider = getProvider();\n return {\n blocks: [],\n text: `Switched to ${provider.name}. Ready to chat.`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Failed to switch provider: ${message}` };\n }\n}\n\nfunction handleAgent(args: string[]): CommandResult {\n const sub = args[0];\n\n if (!sub) {\n return {\n blocks: [],\n text: [\n 'Usage: /agent <subcommand>',\n '',\n ' create <name> --strategy <name> --pairs <SYM1,SYM2> [--interval <sec>]',\n ' list List all agents',\n ' start <name> Start an agent',\n ' stop <name> Stop a running agent',\n ' status <name> View agent status and recent decisions',\n ' delete <name> Delete an agent',\n ' strategies List available strategies',\n ].join('\\n'),\n };\n }\n\n try {\n switch (sub) {\n case 'create': {\n const nameArg = args[1];\n if (!nameArg)\n return {\n blocks: [],\n text: 'Usage: /agent create <name> --strategy <name> --pairs <SYM1,SYM2>',\n };\n\n const stratIdx = args.indexOf('--strategy');\n const pairsIdx = args.indexOf('--pairs');\n const intervalIdx = args.indexOf('--interval');\n\n const strategy =\n stratIdx !== -1 && stratIdx + 1 < args.length ? args[stratIdx + 1]! : 'momentum';\n const pairsRaw =\n pairsIdx !== -1 && pairsIdx + 1 < args.length ? args[pairsIdx + 1]! : 'BTC,ETH';\n const interval =\n intervalIdx !== -1 && intervalIdx + 1 < args.length\n ? parseInt(args[intervalIdx + 1]!, 10)\n : 60;\n\n const pairs = pairsRaw.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(nameArg, strategy, pairs, interval);\n return {\n blocks: [],\n text: `Agent \"${agent.name}\" created (${agent.strategy}, pairs: ${agent.pairs.join(', ')}, interval: ${agent.interval}s)`,\n };\n }\n\n case 'list': {\n const agents = listAgents();\n if (agents.length === 0)\n return { blocks: [], text: 'No agents created. Use /agent create to create one.' };\n\n const lines = ['Agents:', ''];\n for (const a of agents) {\n const status = getAgentStatus(a.id);\n const statusTag = status?.status ?? 'idle';\n lines.push(\n ` ${a.name} [${statusTag}] — ${a.strategy} | ${a.pairs.join(', ')} | ${a.interval}s`,\n );\n }\n return { blocks: [], text: lines.join('\\n') };\n }\n\n case 'start': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent start <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = startAgent(agent.id);\n return {\n blocks: [],\n text: `Agent \"${name}\" started (${state.config.strategy}). Monitoring ${state.config.pairs.join(', ')}.`,\n };\n }\n\n case 'stop': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent stop <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = stopAgent(agent.id);\n return { blocks: [], text: `Agent \"${name}\" stopped after ${state.cycleCount} cycles.` };\n }\n\n case 'status': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent status <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = getAgentStatus(agent.id);\n if (!state) return { blocks: [], text: `Agent \"${name}\" not found.` };\n\n const lines = [\n `Agent: ${state.config.name}`,\n ` Status: ${state.status}`,\n ` Strategy: ${state.config.strategy}`,\n ` Pairs: ${state.config.pairs.join(', ')}`,\n ` Interval: ${state.config.interval}s`,\n ` Cycles: ${state.cycleCount}`,\n ];\n\n if (state.error) lines.push(` Error: ${state.error}`);\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n lines.push('', ' Recent decisions:');\n for (const d of decisions) {\n const time = new Date(d.timestamp).toLocaleTimeString();\n lines.push(\n ` [${time}] ${d.symbol}: ${d.decision.action.toUpperCase()} (${d.decision.confidence}%)`,\n );\n for (const r of d.decision.reasoning.slice(0, 2)) {\n lines.push(` - ${r}`);\n }\n }\n }\n\n return { blocks: [], text: lines.join('\\n') };\n }\n\n case 'delete': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent delete <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n deleteAgent(agent.id);\n return { blocks: [], text: `Agent \"${name}\" deleted.` };\n }\n\n case 'strategies': {\n const strats = listStrategies();\n return { blocks: [], text: `Available strategies: ${strats.join(', ')}` };\n }\n\n default:\n return { blocks: [], text: `Unknown agent subcommand: ${sub}. Type /agent for help.` };\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Agent error: ${message}` };\n }\n}\n\nfunction handleHelp(): CommandResult {\n const text = [\n 'Available commands:',\n '',\n ' /scan <address> [--chain <chain>] Scan a token/project for risk indicators',\n ' /track <wallet> [--chain <chain>] Analyze a wallet address',\n ' /trends Live trending tokens + top gainers/losers',\n ' /audit <contract> [--chain <chain>] Audit a smart contract (bytecode scanning)',\n ' /agent <sub> Manage autonomous trading agents',\n ' /provider [list|<name>] Show/switch AI provider',\n ' /config [set <key> <value>] Show or update configuration',\n ' /clear Clear message history',\n ' /exit Exit Vizzor',\n ' /help Show this help message',\n '',\n 'AI chat supports: token search (DexScreener), trending, news, raises,',\n 'market data, wallet analysis, rug detection, and Pump.fun launches.',\n 'Just ask a question — Vizzor fetches live data automatically.',\n ].join('\\n');\n\n return { blocks: [], text };\n}\n\nasync function handleConfig(args: string[]): Promise<CommandResult> {\n // /config set <key> <value>\n if (args[0] === 'set') {\n const key = args[1];\n const value = args.slice(2).join(' ');\n if (!key || !value) {\n return {\n blocks: [],\n text:\n 'Usage: /config set <key> <value>\\n\\nValid keys: ' +\n Object.keys(getSettableKeys()).join(', '),\n };\n }\n // Validate sensitive keys for security\n const isSensitive = key.toLowerCase().includes('key') || key.toLowerCase().includes('token');\n if (isSensitive) {\n const { validateKey } = await import('../config/keys.js');\n const error = validateKey(key, value);\n if (error && !error.startsWith('Warning:')) {\n return { blocks: [], text: `Rejected: ${error}` };\n }\n }\n try {\n saveConfigValue(key, value);\n return { blocks: [], text: `Saved ${key}. Config reloaded.` };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Config set failed: ${message}` };\n }\n }\n\n try {\n const cfg = getConfig();\n const settable = getSettableKeys();\n\n let activeModel: string;\n try {\n getProvider();\n activeModel = cfg.ai.model ?? DEFAULT_MODELS[cfg.ai.provider] ?? '(default)';\n } catch {\n activeModel = cfg.ai.model ?? '(default)';\n }\n\n const apiKeys: { label: string; key: string; value: string | undefined; env: string }[] = [\n {\n label: 'Anthropic API Key',\n key: 'anthropicApiKey',\n value: cfg.anthropicApiKey,\n env: settable['anthropicApiKey']?.env ?? '',\n },\n {\n label: 'OpenAI API Key',\n key: 'openaiApiKey',\n value: cfg.openaiApiKey,\n env: settable['openaiApiKey']?.env ?? '',\n },\n {\n label: 'Google API Key',\n key: 'googleApiKey',\n value: cfg.googleApiKey,\n env: settable['googleApiKey']?.env ?? '',\n },\n {\n label: 'Etherscan API Key',\n key: 'etherscanApiKey',\n value: cfg.etherscanApiKey,\n env: settable['etherscanApiKey']?.env ?? '',\n },\n {\n label: 'Alchemy API Key',\n key: 'alchemyApiKey',\n value: cfg.alchemyApiKey,\n env: settable['alchemyApiKey']?.env ?? '',\n },\n {\n label: 'CoinGecko API Key',\n key: 'coingeckoApiKey',\n value: cfg.coingeckoApiKey,\n env: settable['coingeckoApiKey']?.env ?? '',\n },\n {\n label: 'CryptoPanic Key',\n key: 'cryptopanicApiKey',\n value: cfg.cryptopanicApiKey,\n env: settable['cryptopanicApiKey']?.env ?? '',\n },\n ];\n\n let configured = 0;\n const keyLines: string[] = [];\n for (const k of apiKeys) {\n const masked = maskKey(k.value);\n if (k.value) configured++;\n const hint = k.value ? '' : ` -> /config set ${k.key} <value> or ${k.env}=xxx`;\n keyLines.push(` ${k.label.padEnd(20)} ${masked}${hint}`);\n }\n\n const text = [\n 'Configuration:',\n '',\n ' [AI Provider]',\n ` Provider: ${cfg.ai.provider}`,\n ` Model: ${activeModel}`,\n ` Max Tokens: ${cfg.ai.maxTokens}`,\n ` Ollama Host: ${cfg.ai.ollamaHost}`,\n '',\n ` [API Keys] (${configured}/${apiKeys.length} configured)`,\n ...keyLines,\n '',\n ' [Chain]',\n ` Default Chain: ${cfg.defaultChain}`,\n '',\n ' [Output]',\n ` Format: ${cfg.output.format}`,\n ` Color: ${cfg.output.color}`,\n ` Verbose: ${cfg.output.verbose}`,\n '',\n 'Set a value: /config set <key> <value>',\n ].join('\\n');\n\n return { blocks: [], text };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Config error: ${message}` };\n }\n}\n","// ---------------------------------------------------------------------------\n// React hook for slash command execution in the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport { useState, useCallback } from 'react';\nimport { parseCommand, executeCommand } from '../commands.js';\nimport type { CommandResult } from '../commands.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseCommandResult {\n /** Whether a slash command is currently executing. */\n isExecuting: boolean;\n /**\n * Parse and execute a slash command string.\n *\n * Returns `null` for `/clear` and `/exit` so the app component can\n * handle those specially. Returns the {@link CommandResult} for all\n * other commands.\n */\n executeSlashCommand: (input: string) => Promise<CommandResult | null>;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that wraps the slash command parser and dispatcher.\n *\n * `/clear` and `/exit` are signalled by returning `null` — the caller is\n * responsible for clearing messages or exiting the process.\n */\nexport function useCommand(): UseCommandResult {\n const [isExecuting, setIsExecuting] = useState(false);\n\n const executeSlashCommand = useCallback(async (input: string): Promise<CommandResult | null> => {\n const { name, args } = parseCommand(input);\n\n // These are handled by the app component, not the command dispatcher.\n if (name === 'clear' || name === 'exit') {\n return null;\n }\n\n setIsExecuting(true);\n try {\n const result = await executeCommand(name, args);\n return result;\n } finally {\n setIsExecuting(false);\n }\n }, []);\n\n return { isExecuting, executeSlashCommand };\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { TICKER_DEFAULTS } from '../../config/constants.js';\n\nconst REFRESH_INTERVAL = 30_000;\n\nexport interface TickerEntry {\n symbol: string;\n geckoId: string;\n price: number;\n change24h: number;\n loading: boolean;\n error: boolean;\n}\n\nexport interface UsePriceTickerResult {\n entries: TickerEntry[];\n isRefreshing: boolean;\n selectedIndex: number | null;\n addSymbol: (geckoId: string, symbol: string) => void;\n removeSymbol: (geckoId: string) => void;\n selectNext: () => void;\n selectPrev: () => void;\n clearSelection: () => void;\n getSelected: () => TickerEntry | null;\n}\n\nexport function usePriceTicker(): UsePriceTickerResult {\n const [entries, setEntries] = useState<TickerEntry[]>(\n TICKER_DEFAULTS.map((t) => ({\n symbol: t.symbol,\n geckoId: t.geckoId,\n price: 0,\n change24h: 0,\n loading: true,\n error: false,\n })),\n );\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const lastGoodRef = useRef<Map<string, { price: number; change24h: number }>>(new Map());\n\n const fetchAll = useCallback(async (current: TickerEntry[]): Promise<void> => {\n setIsRefreshing(true);\n const symbols = current.map((e) => e.symbol);\n const results = await Promise.allSettled(symbols.map((s) => fetchTickerPrice(s)));\n\n setEntries((prev) =>\n prev.map((entry, i) => {\n const result = results[i];\n if (result && result.status === 'fulfilled' && result.value) {\n const data = result.value;\n lastGoodRef.current.set(entry.geckoId, {\n price: data.price,\n change24h: data.change24h,\n });\n return {\n ...entry,\n price: data.price,\n change24h: data.change24h,\n loading: false,\n error: false,\n };\n }\n // Preserve last known good values instead of showing error\n const cached = lastGoodRef.current.get(entry.geckoId);\n if (cached) {\n return {\n ...entry,\n price: cached.price,\n change24h: cached.change24h,\n loading: false,\n error: false,\n };\n }\n // Only show error if we never had data\n return { ...entry, loading: false, error: true };\n }),\n );\n setIsRefreshing(false);\n }, []);\n\n useEffect(() => {\n void fetchAll(entries);\n intervalRef.current = setInterval(() => {\n setEntries((current) => {\n void fetchAll(current);\n return current;\n });\n }, REFRESH_INTERVAL);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [fetchAll]);\n\n const addSymbol = useCallback(\n (geckoId: string, symbol: string): void => {\n setEntries((prev) => {\n if (prev.some((e) => e.geckoId === geckoId)) return prev;\n const newEntry: TickerEntry = {\n symbol: symbol.toUpperCase(),\n geckoId,\n price: 0,\n change24h: 0,\n loading: true,\n error: false,\n };\n const updated = [...prev, newEntry];\n void fetchAll(updated);\n return updated;\n });\n },\n [fetchAll],\n );\n\n const removeSymbol = useCallback((geckoId: string): void => {\n setEntries((prev) => prev.filter((e) => e.geckoId !== geckoId));\n lastGoodRef.current.delete(geckoId);\n }, []);\n\n const selectNext = useCallback((): void => {\n setEntries((current) => {\n setSelectedIndex((prev) => {\n if (prev === null) return 0;\n return prev < current.length - 1 ? prev + 1 : 0;\n });\n return current;\n });\n }, []);\n\n const selectPrev = useCallback((): void => {\n setEntries((current) => {\n setSelectedIndex((prev) => {\n if (prev === null) return current.length - 1;\n return prev > 0 ? prev - 1 : current.length - 1;\n });\n return current;\n });\n }, []);\n\n const clearSelection = useCallback((): void => {\n setSelectedIndex(null);\n }, []);\n\n const getSelected = useCallback((): TickerEntry | null => {\n if (selectedIndex === null) return null;\n return entries[selectedIndex] ?? null;\n }, [selectedIndex, entries]);\n\n return {\n entries,\n isRefreshing,\n selectedIndex,\n addSymbol,\n removeSymbol,\n selectNext,\n selectPrev,\n clearSelection,\n getSelected,\n };\n}\n","// ---------------------------------------------------------------------------\n// Vizzor TUI — Root Ink application component\n// ---------------------------------------------------------------------------\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport { render, Box, Text, Static, useInput } from 'ink';\nimport { StatusBar } from './components/status-bar.js';\nimport { PriceTicker } from './components/price-ticker.js';\nimport { WelcomeBanner } from './components/welcome-banner.js';\nimport { MessageBubble } from './components/message-bubble.js';\nimport { CommandHints } from './components/command-hints.js';\nimport { ToolStatusList } from './components/tool-status.js';\nimport { InputPrompt } from './components/input-prompt.js';\nimport { StreamingText } from './components/streaming-text.js';\nimport type { Message } from './components/message-list.js';\nimport { useAIStream } from './hooks/use-ai-stream.js';\nimport { useCommand } from './hooks/use-command.js';\nimport { usePriceTicker } from './hooks/use-price-ticker.js';\nimport { isSlashCommand, parseCommand } from './commands.js';\nimport { loadConfig } from '../config/loader.js';\nimport { DEFAULT_CHAIN, CHAIN_REGISTRY, KNOWN_SYMBOLS } from '../config/constants.js';\nimport { setConfig, setToolHandler, getProvider } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { isValidSymbol } from '../data/sources/binance.js';\n\n// ---------------------------------------------------------------------------\n// App component\n// ---------------------------------------------------------------------------\n\nfunction App(): React.JSX.Element {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isProcessing, setIsProcessing] = useState(false);\n const [initError, setInitError] = useState<string | null>(null);\n const [showBanner, setShowBanner] = useState(true);\n const [currentInput, setCurrentInput] = useState('');\n const [clearEpoch, setClearEpoch] = useState(0);\n const [providerName, setProviderName] = useState('ollama');\n const [chainName, setChainName] = useState(DEFAULT_CHAIN);\n const [tickerFocused, setTickerFocused] = useState(false);\n\n const { streamingText, isStreaming, activeTools, completedTools, sendMessage } = useAIStream();\n const { isExecuting, executeSlashCommand } = useCommand();\n const ticker = usePriceTicker();\n\n // -----------------------------------------------------------------------\n // Ticker keyboard navigation (Tab to focus, arrows to navigate, Enter to analyze)\n // -----------------------------------------------------------------------\n useInput(\n (input, key) => {\n if (key.tab) {\n if (tickerFocused) {\n setTickerFocused(false);\n ticker.clearSelection();\n } else {\n setTickerFocused(true);\n }\n return;\n }\n if (!tickerFocused) return;\n if (key.rightArrow) {\n ticker.selectNext();\n } else if (key.leftArrow) {\n ticker.selectPrev();\n } else if (key.return) {\n const selected = ticker.getSelected();\n if (selected && !isProcessing && !isStreaming) {\n setTickerFocused(false);\n ticker.clearSelection();\n const msg = `Analyze ${selected.symbol} with full prediction`;\n setMessages((prev) => [...prev, { role: 'user', content: msg, timestamp: new Date() }]);\n setIsProcessing(true);\n sendMessage(msg);\n }\n } else if (key.escape || input === 'q') {\n setTickerFocused(false);\n ticker.clearSelection();\n }\n },\n { isActive: true },\n );\n\n // -----------------------------------------------------------------------\n // Initialisation: load config, set up AI client and tool handler\n // -----------------------------------------------------------------------\n useEffect(() => {\n try {\n const cfg = loadConfig();\n setConfig(cfg);\n setToolHandler(handleTool);\n setProviderName(cfg.ai?.provider ?? 'ollama');\n setChainName(cfg.defaultChain ?? DEFAULT_CHAIN);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setInitError(`Initialisation failed: ${message}`);\n }\n // Ensure VIZZOR_TOOLS is referenced so the import is not tree-shaken.\n void VIZZOR_TOOLS;\n }, []);\n\n // -----------------------------------------------------------------------\n // When the AI stream finishes, capture the final message\n // -----------------------------------------------------------------------\n useEffect(() => {\n if (!isStreaming && streamingText.length > 0 && isProcessing) {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: streamingText, timestamp: new Date() },\n ]);\n setIsProcessing(false);\n }\n }, [isStreaming, streamingText, isProcessing]);\n\n // -----------------------------------------------------------------------\n // Input handler\n // -----------------------------------------------------------------------\n const handleSubmit = useCallback(\n (input: string): void => {\n // Hide banner after first interaction\n if (showBanner) setShowBanner(false);\n\n if (isSlashCommand(input)) {\n const { name, args } = parseCommand(input);\n\n // Special commands handled directly by the app\n if (name === 'clear') {\n setMessages([]);\n setClearEpoch((prev) => prev + 1);\n return;\n }\n if (name === 'exit') {\n process.exit(0);\n }\n\n // /add <symbol> — add a crypto to the price ticker\n if (name === 'add') {\n const sym = args[0]?.toUpperCase();\n if (!sym) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: 'Usage: /add <symbol> (e.g. /add DOGE)',\n timestamp: new Date(),\n },\n ]);\n return;\n }\n const geckoId = KNOWN_SYMBOLS[sym.toLowerCase()] ?? sym.toLowerCase();\n setIsProcessing(true);\n isValidSymbol(sym)\n .then((valid) => {\n if (valid) {\n ticker.addSymbol(geckoId, sym);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Added ${sym} to price ticker.`,\n timestamp: new Date(),\n },\n ]);\n } else {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Symbol \"${sym}\" not found on Binance.`,\n timestamp: new Date(),\n },\n ]);\n }\n })\n .catch(() => {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Failed to validate symbol \"${sym}\".`,\n timestamp: new Date(),\n },\n ]);\n })\n .finally(() => setIsProcessing(false));\n return;\n }\n\n // /remove <symbol> — remove a crypto from the price ticker\n if (name === 'remove') {\n const sym = args[0]?.toUpperCase();\n if (!sym) {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: 'Usage: /remove <symbol>', timestamp: new Date() },\n ]);\n return;\n }\n const geckoId = KNOWN_SYMBOLS[sym.toLowerCase()] ?? sym.toLowerCase();\n ticker.removeSymbol(geckoId);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Removed ${sym} from price ticker.`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n\n // /chain [chainId] — switch or list chains\n if (name === 'chain') {\n const target = args[0]?.toLowerCase();\n if (!target) {\n const lines = CHAIN_REGISTRY.map(\n (c) => ` ${c.icon} ${c.name} (${c.id})${c.id === chainName ? ' *' : ''}`,\n );\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Available chains:\\n${lines.join('\\n')}\\n\\nUsage: /chain <id>`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n const meta = CHAIN_REGISTRY.find((c) => c.id === target);\n if (!meta) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Unknown chain \"${target}\". Available: ${CHAIN_REGISTRY.map((c) => c.id).join(', ')}`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n setChainName(meta.id);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `${meta.icon} Switched to ${meta.name}.`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n\n // All other slash commands — fire-and-forget the async work\n setIsProcessing(true);\n executeSlashCommand(input)\n .then((result) => {\n if (result) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: result.text,\n blocks: result.blocks,\n timestamp: new Date(),\n },\n ]);\n }\n // Update status bar when provider changes\n if (name === 'provider') {\n try {\n setProviderName(getProvider().name);\n } catch {\n /* no active provider */\n }\n }\n })\n .catch(() => {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: 'Command execution failed.', timestamp: new Date() },\n ]);\n })\n .finally(() => {\n setIsProcessing(false);\n });\n return;\n }\n\n // Regular message — send to AI\n setMessages((prev) => [...prev, { role: 'user', content: input, timestamp: new Date() }]);\n setIsProcessing(true);\n sendMessage(input);\n },\n [executeSlashCommand, sendMessage, showBanner],\n );\n\n // -----------------------------------------------------------------------\n // Determine whether the input should be disabled\n // -----------------------------------------------------------------------\n const inputDisabled = isProcessing || isStreaming || isExecuting || tickerFocused;\n\n // -----------------------------------------------------------------------\n // Render\n // -----------------------------------------------------------------------\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n {/* Status bar */}\n <StatusBar provider={providerName} chain={chainName} connected />\n\n {/* Live price ticker — Tab to focus, arrows to navigate, Enter to analyze */}\n <PriceTicker ticker={ticker} focused={tickerFocused} onAddPress={undefined} />\n\n {/* Compact banner — hides after first message */}\n {showBanner && <WelcomeBanner />}\n\n {initError && (\n <Box marginTop={1}>\n <Box borderStyle=\"single\" borderColor=\"red\" paddingX={1}>\n <Text color=\"red\">{initError}</Text>\n </Box>\n </Box>\n )}\n\n {/* Message history — uses Static so items render once */}\n <Static key={clearEpoch} items={messages}>\n {(msg, idx) => (\n <Box key={`${clearEpoch}-${idx}`} marginTop={idx === 0 ? 1 : 0}>\n <MessageBubble message={msg} />\n </Box>\n )}\n </Static>\n\n {/* Show streaming AI text while a response is being generated */}\n {isStreaming && streamingText.length > 0 && (\n <Box marginTop={1}>\n <StreamingText text={streamingText} isStreaming={isStreaming} />\n </Box>\n )}\n\n {/* Show active tool executions */}\n <ToolStatusList active={activeTools} completed={completedTools} />\n\n {/* Command hints when typing / */}\n {currentInput.startsWith('/') && <CommandHints filter={currentInput} />}\n\n {/* Input bar */}\n <Box marginTop={1}>\n <InputPrompt\n onSubmit={handleSubmit}\n disabled={inputDisabled}\n onInputChange={setCurrentInput}\n />\n </Box>\n </Box>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Mount the Vizzor TUI using Ink's `render()` function.\n *\n * Call this from the CLI entry point to start the interactive terminal UI.\n */\nexport function startTUI(): void {\n render(<App />);\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, resolve } from 'node:path';\nimport { loadConfig } from './config/loader.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8')) as {\n version: string;\n};\n\nconst program = new Command()\n .name('vizzor')\n .description('Crypto chronovisor — AI-powered on-chain intelligence')\n .version(pkg.version);\n\nprogram.hook('preAction', async () => {\n await loadConfig();\n});\n\n// Lazy-load commands to speed up CLI startup\nprogram\n .command('scan <project>')\n .description('Analyze a crypto project')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--deep', 'Deep analysis including contract audit', false)\n .option('--json', 'Output as JSON', false)\n .action(async (project: string, options: { chain: string; deep: boolean; json: boolean }) => {\n const { handleScan } = await import('./cli/commands/scan.js');\n await handleScan(project, options);\n });\n\nprogram\n .command('trends')\n .description('Analyze market trends')\n .option('--sentiment', 'Include sentiment analysis', false)\n .option('--chain <chain>', 'Filter by chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (options: { sentiment: boolean; chain: string; json: boolean }) => {\n const { handleTrends } = await import('./cli/commands/trends.js');\n await handleTrends(options);\n });\n\nprogram\n .command('track <wallet>')\n .description('Analyze a wallet address')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (wallet: string, options: { chain: string; json: boolean }) => {\n const { handleTrack } = await import('./cli/commands/track.js');\n await handleTrack(wallet, options);\n });\n\nconst icoCmd = program.command('ico').description('ICO/IDO tracker');\n\nicoCmd\n .command('list')\n .description('List upcoming ICOs/IDOs')\n .option('--category <category>', 'Filter by category')\n .option('--chain <chain>', 'Filter by chain')\n .option('--json', 'Output as JSON', false)\n .action(async (options: { category?: string; chain?: string; json: boolean }) => {\n const { handleIcoList } = await import('./cli/commands/ico.js');\n await handleIcoList(options);\n });\n\nprogram\n .command('audit <contract>')\n .description('Basic smart contract audit')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (contract: string, options: { chain: string; json: boolean }) => {\n const { handleAudit } = await import('./cli/commands/audit.js');\n await handleAudit(contract, options);\n });\n\nconst configCmd = program.command('config').description('Configuration management');\n\nconfigCmd\n .command('init')\n .description('Initialize configuration')\n .action(async () => {\n const { handleConfigInit } = await import('./cli/commands/config.js');\n await handleConfigInit();\n });\n\nconfigCmd\n .command('set <key> <value>')\n .description('Set a configuration value')\n .action(async (key: string, value: string) => {\n const { handleConfigSet } = await import('./cli/commands/config.js');\n await handleConfigSet(key, value);\n });\n\nconfigCmd\n .command('show')\n .description('Show current configuration')\n .action(async () => {\n const { handleConfigShow } = await import('./cli/commands/config.js');\n await handleConfigShow();\n });\n\nconst botCmd = program.command('bot').description('Bot management');\n\nbotCmd\n .command('start')\n .description('Start bot(s)')\n .option('--discord', 'Start Discord bot', false)\n .option('--telegram', 'Start Telegram bot', false)\n .option('--all', 'Start all bots', false)\n .action(async (options: { discord: boolean; telegram: boolean; all: boolean }) => {\n const { handleBotStart } = await import('./cli/commands/bot.js');\n await handleBotStart(options);\n });\n\nbotCmd\n .command('validate')\n .description('Check bot token configuration')\n .action(async () => {\n const { handleBotValidate } = await import('./cli/commands/bot.js');\n handleBotValidate();\n });\n\nconst collectCmd = program.command('collect').description('Data collection pipeline');\n\ncollectCmd\n .command('start')\n .description('Start background OHLCV data collection (requires PostgreSQL)')\n .option('--symbols <symbols>', 'Comma-separated symbols to collect (default: 23 major pairs)')\n .option('--interval <seconds>', 'Collection interval in seconds (default: 300)', parseInt)\n .action(async (options: { symbols?: string; interval?: number }) => {\n const { handleCollectStart } = await import('./cli/commands/collect.js');\n await handleCollectStart(options);\n });\n\ncollectCmd\n .command('status')\n .description('Show data collection status')\n .action(async () => {\n const { handleCollectStatus } = await import('./cli/commands/collect.js');\n handleCollectStatus();\n });\n\nprogram\n .command('serve')\n .description('Start the REST API server')\n .option('--port <port>', 'Server port', (v: string) => parseInt(v, 10), 3000)\n .option('--host <host>', 'Server host', '0.0.0.0')\n .option('--auth', 'Enable API key authentication', false)\n .action(async (options: { port: number; host: string; auth: boolean }) => {\n const { handleServe } = await import('./cli/commands/serve.js');\n await handleServe(options);\n });\n\nconst apiCmd = program.command('api').description('API management');\nconst apiKeyCmd = apiCmd.command('key').description('API key management');\n\napiKeyCmd\n .command('create [label]')\n .description('Generate a new API key')\n .action(async (label: string) => {\n const { handleApiKeyCreate } = await import('./cli/commands/api.js');\n handleApiKeyCreate(label);\n });\n\napiKeyCmd\n .command('list')\n .description('List active API keys')\n .action(async () => {\n const { handleApiKeyList } = await import('./cli/commands/api.js');\n handleApiKeyList();\n });\n\napiKeyCmd\n .command('revoke <id>')\n .description('Revoke an API key')\n .action(async (id: string) => {\n const { handleApiKeyRevoke } = await import('./cli/commands/api.js');\n handleApiKeyRevoke(id);\n });\n\n// If no arguments provided, launch interactive TUI\nconst args = process.argv.slice(2);\nif (args.length === 0) {\n await loadConfig();\n const { startTUI } = await import('./tui/app.js');\n startTUI();\n} else {\n program.parse();\n}\n"],"mappings":"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","names":["db","config","client","args","log","init_adapter","init_adapter","mlClient","level","BASE_URL","mlClient","fetchJson","BASE_URL","currentPrice","priceChange","mlClient","fetchJson","BASE_URL","WEIGHTS","mlClient","chalk","ora","mlClient","chalk","ora","level","fetchJson","fetchJson","BASE_URL","chalk","ora","chalk","ora","level","chalk","writeFileSync","existsSync","config","toolHandler","toolHandler","client","extractText","toolHandler","provider","init_registry","fetchJson","BASE_URL","searchTokens","base","geckoId","mlClient","getCoinDetails","total","formatPrice","OLLAMA_SYSTEM_PROMPT","init_client","init_registry","mlClient","mlClient","join","config","db","config","createPublicClient","http","mainnet","ensureAgentTables","db","config","readFileSync","resolve","config","config","PostgresStore","mlClient","config","client","init_client","init_market","handleScan","handleTrends","handleTrack","handleAudit","args","init_commands","init_market","userLimits","WINDOW_MS","MAX_REQUESTS","startRateLimitCleanup","init_rate_limit","bot_exports","config","logger","startRateLimitCleanup","init_bot","init_client","init_commands","init_rate_limit","bot_exports","chalk","config","startDiscordBot","startTelegramBot","init_bot","log","chalk","config","init_market","init_keys","validateKey","init_keys","log","init_market","chalk","startApiServer","chalk","init_keys","StatusBar","provider","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","level","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","formatVolume","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","Spinner","jsx","jsxs","useState","Box","Text","jsx","jsxs","Box","Text","Spinner","jsx","jsxs","useState","provider","toolHandler","init_client","args","maskKey","handleScan","handleTrack","handleTrends","handleAudit","provider","validateKey","init_commands","init_client","init_registry","useState","useCallback","args","init_commands","useState","useEffect","useCallback","useState","useEffect","useCallback","Box","Text","jsx","jsxs","args","init_commands","init_client","readFileSync","fileURLToPath","dirname","resolve","__filename","__dirname","handleScan","handleTrends","handleTrack","handleIcoList","handleAudit","handleConfigInit","handleConfigSet","handleConfigShow","handleBotStart","handleBotValidate","handleCollectStart","handleCollectStatus","handleServe","handleApiKeyCreate","handleApiKeyList","handleApiKeyRevoke","startTUI"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/schema.ts","../src/config/loader.ts","../src/utils/validate.ts","../src/chains/evm/abi/erc20.ts","../src/chains/evm/etherscan.ts","../src/config/constants.ts","../src/chains/evm/adapter.ts","../src/utils/logger.ts","../src/chains/evm/writable-adapter.ts","../src/chains/zk/adapter.ts","../src/chains/solana/adapter.ts","../src/chains/sui/adapter.ts","../src/chains/aptos/adapter.ts","../src/chains/ton/adapter.ts","../src/chains/registry.ts","../src/ml/client.ts","../src/core/scanner/project-analyzer.ts","../src/core/scanner/risk-scorer.ts","../src/cli/commands/scan.ts","../src/data/sources/dexscreener.ts","../src/core/trends/market.ts","../src/data/sources/cryptopanic.ts","../src/core/trends/sentiment.ts","../src/data/sources/binance.ts","../src/core/technical-analysis/indicators.ts","../src/core/technical-analysis/analyzer.ts","../src/core/technical-analysis/index.ts","../src/data/sources/fear-greed.ts","../src/ml/feature-engineer.ts","../src/core/trends/predictor.ts","../src/cli/commands/trends.ts","../src/core/forensics/wallet-analyzer.ts","../src/cli/commands/track.ts","../src/data/sources/defillama.ts","../src/data/sources/pumpfun.ts","../src/core/scanner/ico-tracker.ts","../src/cli/commands/ico.ts","../src/core/forensics/contract-auditor.ts","../src/cli/commands/audit.ts","../src/ai/providers/types.ts","../src/config/keys.ts","../src/cli/commands/config.ts","../src/ai/providers/anthropic.ts","../src/ai/providers/openai.ts","../src/ai/providers/gemini.ts","../src/ai/providers/ollama.ts","../src/ai/providers/registry.ts","../src/data/sources/goplus.ts","../src/ai/sanitize.ts","../src/ai/context-injector.ts","../src/ai/prompts/chat.ts","../src/ai/client.ts","../src/core/forensics/bytecode-scanner.ts","../src/core/forensics/rug-detector.ts","../src/core/trends/regime.ts","../src/data/cache.ts","../src/core/agent/engine.ts","../src/core/agent/strategies/momentum.ts","../src/core/agent/strategies/trend-following.ts","../src/core/agent/strategies/ml-adaptive.ts","../src/core/agent/manager.ts","../src/core/agent/wallet.ts","../src/core/agent/index.ts","../src/data/sqlite-store.ts","../src/data/postgres-store.ts","../src/data/store-factory.ts","../src/core/backtest/engine.ts","../src/ai/tool-handler.ts","../src/ai/tools.ts","../src/utils/message-split.ts","../src/discord/middleware/rate-limit.ts","../src/discord/commands/index.ts","../src/discord/bot.ts","../src/telegram/formatters/market.ts","../src/telegram/commands/index.ts","../src/telegram/middleware/rate-limit.ts","../src/telegram/bot.ts","../src/cli/commands/bot.ts","../src/data/collector.ts","../src/cli/commands/collect.ts","../src/api/routes/v1/market.ts","../src/api/routes/v1/analysis.ts","../src/api/routes/v1/security.ts","../src/api/routes/v1/backtest.ts","../src/api/routes/v1/agents.ts","../src/api/routes/v1/portfolio.ts","../src/api/auth/keys.ts","../src/api/auth/middleware.ts","../src/api/middleware/error-handler.ts","../src/api/server.ts","../src/cli/commands/serve.ts","../src/cli/commands/api.ts","../src/cli/commands/backtest.ts","../src/core/agent/wallet-manager.ts","../src/cli/commands/wallet.ts","../src/data/sources/binance-ws.ts","../src/data/sources/ws-manager.ts","../src/tui/components/status-bar.tsx","../src/tui/components/price-ticker.tsx","../src/tui/components/welcome-banner.tsx","../src/tui/blocks/risk-bar.tsx","../src/tui/blocks/token-card.tsx","../src/tui/blocks/holder-list.tsx","../src/tui/blocks/market-ticker.tsx","../src/tui/blocks/audit-result.tsx","../src/tui/components/message-list.tsx","../src/tui/components/message-bubble.tsx","../src/tui/components/command-hints.tsx","../src/tui/components/tool-status.tsx","../src/tui/components/input-prompt.tsx","../src/tui/components/streaming-text.tsx","../src/tui/hooks/use-ai-stream.ts","../src/tui/commands.ts","../src/tui/hooks/use-command.ts","../src/tui/hooks/use-price-ticker.ts","../src/tui/app.tsx","../src/index.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\nexport const vizzorConfigSchema = z.object({\n anthropicApiKey: z.string().optional(),\n openaiApiKey: z.string().optional(),\n googleApiKey: z.string().optional(),\n etherscanApiKey: z.string().optional(),\n alchemyApiKey: z.string().optional(),\n coingeckoApiKey: z.string().optional(),\n cryptopanicApiKey: z.string().optional(),\n defaultChain: z.string().default('ethereum'),\n rpc: z.record(z.string(), z.string()).default({}),\n ai: z\n .object({\n provider: z.enum(['anthropic', 'openai', 'gemini', 'ollama']).default('anthropic'),\n model: z.string().optional(),\n maxTokens: z.number().default(4096),\n ollamaHost: z.string().default('http://localhost:11434'),\n })\n .default(() => ({\n provider: 'anthropic' as const,\n maxTokens: 4096,\n ollamaHost: 'http://localhost:11434',\n })),\n output: z\n .object({\n format: z.enum(['table', 'json', 'markdown']).default('table'),\n color: z.boolean().default(true),\n verbose: z.boolean().default(false),\n })\n .default(() => ({ format: 'table' as const, color: true, verbose: false })),\n cacheTtl: z\n .object({\n tokenInfo: z.number().default(3600),\n marketData: z.number().default(300),\n walletData: z.number().default(600),\n contractCode: z.number().default(86400),\n })\n .default(() => ({ tokenInfo: 3600, marketData: 300, walletData: 600, contractCode: 86400 })),\n database: z\n .object({\n type: z.enum(['sqlite', 'postgres']).default('sqlite'),\n url: z.string().optional(),\n })\n .default(() => ({ type: 'sqlite' as const })),\n ml: z\n .object({\n enabled: z.boolean().default(false),\n sidecarUrl: z.string().default('http://localhost:8000'),\n fallbackToRules: z.boolean().default(true),\n })\n .default(() => ({\n enabled: false,\n sidecarUrl: 'http://localhost:8000',\n fallbackToRules: true,\n })),\n api: z\n .object({\n port: z.number().default(3000),\n host: z.string().default('0.0.0.0'),\n enableAuth: z.boolean().default(true),\n corsOrigin: z.string().default('http://localhost:3000'),\n })\n .default(() => ({\n port: 3000,\n host: '0.0.0.0',\n enableAuth: true,\n corsOrigin: 'http://localhost:3000',\n })),\n n8n: z\n .object({\n enabled: z.boolean().default(false),\n webhookUrl: z.string().optional(),\n })\n .default(() => ({ enabled: false })),\n realtime: z\n .object({\n enabled: z.boolean().default(false),\n provider: z.enum(['binance']).default('binance'),\n symbols: z.array(z.string()).default([]),\n })\n .optional(),\n trading: z\n .object({\n enabled: z.boolean().default(false),\n maxSlippage: z.number().default(0.5),\n gasMultiplier: z.number().default(1.2),\n confirmBeforeExecute: z.boolean().default(true),\n dryRun: z.boolean().default(true),\n walletName: z.string().optional(),\n })\n .optional(),\n discordToken: z.string().optional(),\n discordGuildId: z.string().optional(),\n telegramToken: z.string().optional(),\n});\n\nexport type VizzorConfig = z.infer<typeof vizzorConfigSchema>;\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport yaml from 'yaml';\nimport { vizzorConfigSchema } from './schema.js';\nimport type { VizzorConfig } from './schema.js';\n\nlet cachedConfig: VizzorConfig | null = null;\n\n/**\n * Returns the path to the Vizzor configuration directory (~/.vizzor/).\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.vizzor');\n}\n\n/**\n * Loads and validates the Vizzor configuration from ~/.vizzor/config.yaml.\n * Creates the config directory if it does not exist.\n * Environment variables override file-based values.\n */\nexport function loadConfig(): VizzorConfig {\n const configDir = getConfigDir();\n const configPath = join(configDir, 'config.yaml');\n\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n let raw: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n const contents = readFileSync(configPath, 'utf-8');\n const parsed: unknown = yaml.parse(contents);\n if (parsed && typeof parsed === 'object') {\n raw = parsed as Record<string, unknown>;\n }\n }\n\n // Environment variable overrides\n if (process.env['ANTHROPIC_API_KEY']) {\n raw['anthropicApiKey'] = process.env['ANTHROPIC_API_KEY'];\n }\n if (process.env['ETHERSCAN_API_KEY']) {\n raw['etherscanApiKey'] = process.env['ETHERSCAN_API_KEY'];\n }\n if (process.env['ALCHEMY_API_KEY']) {\n raw['alchemyApiKey'] = process.env['ALCHEMY_API_KEY'];\n }\n if (process.env['COINGECKO_API_KEY']) {\n raw['coingeckoApiKey'] = process.env['COINGECKO_API_KEY'];\n }\n if (process.env['DISCORD_TOKEN']) {\n raw['discordToken'] = process.env['DISCORD_TOKEN'];\n }\n if (process.env['DISCORD_GUILD_ID']) {\n raw['discordGuildId'] = process.env['DISCORD_GUILD_ID'];\n }\n if (process.env['TELEGRAM_BOT_TOKEN']) {\n raw['telegramToken'] = process.env['TELEGRAM_BOT_TOKEN'];\n }\n if (process.env['OPENAI_API_KEY']) {\n raw['openaiApiKey'] = process.env['OPENAI_API_KEY'];\n }\n if (process.env['GOOGLE_API_KEY']) {\n raw['googleApiKey'] = process.env['GOOGLE_API_KEY'];\n }\n if (process.env['CRYPTOPANIC_API_KEY']) {\n raw['cryptopanicApiKey'] = process.env['CRYPTOPANIC_API_KEY'];\n }\n if (process.env['VIZZOR_AI_PROVIDER']) {\n if (!raw['ai'] || typeof raw['ai'] !== 'object') {\n raw['ai'] = {};\n }\n (raw['ai'] as Record<string, unknown>)['provider'] = process.env['VIZZOR_AI_PROVIDER'];\n }\n\n // Database env overrides\n if (process.env['DATABASE_TYPE'] || process.env['DATABASE_URL']) {\n if (!raw['database'] || typeof raw['database'] !== 'object') {\n raw['database'] = {};\n }\n const db = raw['database'] as Record<string, unknown>;\n if (process.env['DATABASE_TYPE']) db['type'] = process.env['DATABASE_TYPE'];\n if (process.env['DATABASE_URL']) db['url'] = process.env['DATABASE_URL'];\n }\n\n // ML env overrides\n if (process.env['ML_ENABLED'] || process.env['ML_SIDECAR_URL']) {\n if (!raw['ml'] || typeof raw['ml'] !== 'object') {\n raw['ml'] = {};\n }\n const ml = raw['ml'] as Record<string, unknown>;\n if (process.env['ML_ENABLED']) ml['enabled'] = process.env['ML_ENABLED'] === 'true';\n if (process.env['ML_SIDECAR_URL']) ml['sidecarUrl'] = process.env['ML_SIDECAR_URL'];\n }\n\n // API env overrides\n if (process.env['API_PORT'] || process.env['API_HOST']) {\n if (!raw['api'] || typeof raw['api'] !== 'object') {\n raw['api'] = {};\n }\n const api = raw['api'] as Record<string, unknown>;\n if (process.env['API_PORT']) api['port'] = Number(process.env['API_PORT']);\n if (process.env['API_HOST']) api['host'] = process.env['API_HOST'];\n }\n\n const config = vizzorConfigSchema.parse(raw);\n cachedConfig = config;\n return config;\n}\n\n/**\n * Returns the cached configuration. Throws if loadConfig() has not been called.\n */\nexport function getConfig(): VizzorConfig {\n if (!cachedConfig) {\n throw new Error('Configuration not loaded. Call loadConfig() before getConfig().');\n }\n return cachedConfig;\n}\n\n/** Valid top-level config keys that can be set via /config set. */\nconst SETTABLE_KEYS: Record<string, { env: string; nested?: string }> = {\n anthropicApiKey: { env: 'ANTHROPIC_API_KEY' },\n openaiApiKey: { env: 'OPENAI_API_KEY' },\n googleApiKey: { env: 'GOOGLE_API_KEY' },\n etherscanApiKey: { env: 'ETHERSCAN_API_KEY' },\n alchemyApiKey: { env: 'ALCHEMY_API_KEY' },\n coingeckoApiKey: { env: 'COINGECKO_API_KEY' },\n cryptopanicApiKey: { env: 'CRYPTOPANIC_API_KEY' },\n defaultChain: { env: 'VIZZOR_DEFAULT_CHAIN' },\n telegramToken: { env: 'TELEGRAM_BOT_TOKEN' },\n discordToken: { env: 'DISCORD_TOKEN' },\n discordGuildId: { env: 'DISCORD_GUILD_ID' },\n 'ai.provider': { env: 'VIZZOR_AI_PROVIDER', nested: 'ai' },\n 'ai.model': { env: 'VIZZOR_AI_MODEL', nested: 'ai' },\n 'ai.maxTokens': { env: 'VIZZOR_AI_MAX_TOKENS', nested: 'ai' },\n 'ai.ollamaHost': { env: 'OLLAMA_HOST', nested: 'ai' },\n 'database.type': { env: 'DATABASE_TYPE', nested: 'database' },\n 'database.url': { env: 'DATABASE_URL', nested: 'database' },\n 'ml.enabled': { env: 'ML_ENABLED', nested: 'ml' },\n 'ml.sidecarUrl': { env: 'ML_SIDECAR_URL', nested: 'ml' },\n 'ml.fallbackToRules': { env: 'ML_FALLBACK_TO_RULES', nested: 'ml' },\n 'api.port': { env: 'API_PORT', nested: 'api' },\n 'api.host': { env: 'API_HOST', nested: 'api' },\n 'api.enableAuth': { env: 'API_ENABLE_AUTH', nested: 'api' },\n 'api.corsOrigin': { env: 'API_CORS_ORIGIN', nested: 'api' },\n 'n8n.enabled': { env: 'N8N_ENABLED', nested: 'n8n' },\n 'n8n.webhookUrl': { env: 'N8N_WEBHOOK_URL', nested: 'n8n' },\n};\n\n/**\n * Returns the list of settable config keys with their env var names.\n */\nexport function getSettableKeys(): Record<string, { env: string; nested?: string }> {\n return SETTABLE_KEYS;\n}\n\n/**\n * Persists a single config key=value to ~/.vizzor/config.yaml and reloads the cache.\n * Supports dot-notation for nested keys (e.g. \"ai.provider\").\n */\nexport function saveConfigValue(key: string, value: string): void {\n if (!(key in SETTABLE_KEYS)) {\n throw new Error(\n `Unknown config key: \"${key}\". Valid keys: ${Object.keys(SETTABLE_KEYS).join(', ')}`,\n );\n }\n\n const configDir = getConfigDir();\n const configPath = join(configDir, 'config.yaml');\n\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n let raw: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n const contents = readFileSync(configPath, 'utf-8');\n const parsed: unknown = yaml.parse(contents);\n if (parsed && typeof parsed === 'object') {\n raw = parsed as Record<string, unknown>;\n }\n }\n\n // Handle dot-notation (e.g. \"ai.provider\" -> raw.ai.provider)\n if (key.includes('.')) {\n const [section, field] = key.split('.') as [string, string];\n if (!raw[section] || typeof raw[section] !== 'object') {\n raw[section] = {};\n }\n // Parse numeric and boolean values\n let parsed: string | number | boolean = value;\n if (field === 'maxTokens' || field === 'port') parsed = Number(value);\n else if (value === 'true') parsed = true;\n else if (value === 'false') parsed = false;\n (raw[section] as Record<string, unknown>)[field] = parsed;\n } else {\n raw[key] = value;\n }\n\n // Validate before saving\n vizzorConfigSchema.parse(raw);\n\n writeFileSync(configPath, yaml.stringify(raw), { encoding: 'utf-8', mode: 0o600 });\n // Ensure restrictive perms on existing files too\n chmodSync(configPath, 0o600);\n\n // Invalidate cache so next getConfig() returns fresh data\n cachedConfig = null;\n loadConfig();\n}\n","// ---------------------------------------------------------------------------\n// Input validation utilities\n// ---------------------------------------------------------------------------\n\nconst EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;\nconst SYMBOL_RE = /^[A-Za-z0-9]{1,20}$/;\n\n/**\n * Validate an EVM address format. Throws if invalid.\n */\nexport function assertValidAddress(address: string): void {\n if (!EVM_ADDRESS_RE.test(address)) {\n throw new Error(`Invalid address format: expected 0x followed by 40 hex characters`);\n }\n}\n\n/**\n * Check if a string is a valid EVM address.\n */\nexport function isValidAddress(address: string): boolean {\n return EVM_ADDRESS_RE.test(address);\n}\n\n/**\n * Validate a token/coin symbol. Throws if invalid.\n */\nexport function assertValidSymbol(symbol: string): void {\n if (!SYMBOL_RE.test(symbol)) {\n throw new Error(`Invalid symbol format: expected 1-20 alphanumeric characters`);\n }\n}\n\n/**\n * Check if a string is a valid symbol.\n */\nexport function isValidSymbol(symbol: string): boolean {\n return SYMBOL_RE.test(symbol);\n}\n","// ---------------------------------------------------------------------------\n// Standard ERC-20 ABI (subset used by the EVM adapter)\n// ---------------------------------------------------------------------------\n\nexport const erc20Abi = [\n // ── read ────────────────────────────────────────────────────────────────\n {\n type: 'function',\n name: 'name',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n },\n {\n type: 'function',\n name: 'symbol',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'string' }],\n },\n {\n type: 'function',\n name: 'decimals',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'uint8' }],\n },\n {\n type: 'function',\n name: 'totalSupply',\n stateMutability: 'view',\n inputs: [],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'balanceOf',\n stateMutability: 'view',\n inputs: [{ name: 'owner', type: 'address' }],\n outputs: [{ name: '', type: 'uint256' }],\n },\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n ],\n outputs: [{ name: '', type: 'uint256' }],\n },\n\n // ── write ───────────────────────────────────────────────────────────────\n {\n type: 'function',\n name: 'transfer',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'spender', type: 'address' },\n { name: 'amount', type: 'uint256' },\n ],\n outputs: [{ name: '', type: 'bool' }],\n },\n\n // ── events ──────────────────────────────────────────────────────────────\n {\n type: 'event',\n name: 'Transfer',\n inputs: [\n { name: 'from', type: 'address', indexed: true },\n { name: 'to', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Approval',\n inputs: [\n { name: 'owner', type: 'address', indexed: true },\n { name: 'spender', type: 'address', indexed: true },\n { name: 'value', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// ---------------------------------------------------------------------------\n// Etherscan-compatible block explorer API client\n// Works with Etherscan, Polygonscan, Arbiscan, Basescan, etc.\n// ---------------------------------------------------------------------------\n\nimport type { Transaction, TokenTransfer, Holder } from '../types.js';\n\n// ---------------------------------------------------------------------------\n// Base URLs per chain\n// ---------------------------------------------------------------------------\n\nexport const EXPLORER_URLS: Record<string, string> = {\n ethereum: 'https://api.etherscan.io/api',\n polygon: 'https://api.polygonscan.com/api',\n arbitrum: 'https://api.arbiscan.io/api',\n optimism: 'https://api-optimistic.etherscan.io/api',\n base: 'https://api.basescan.org/api',\n};\n\n// ---------------------------------------------------------------------------\n// Raw API response types\n// ---------------------------------------------------------------------------\n\ninterface EtherscanResult<T> {\n status: string;\n message: string;\n result: T;\n}\n\ninterface RawTransaction {\n hash: string;\n blockNumber: string;\n from: string;\n to: string;\n value: string;\n gasUsed: string;\n gasPrice: string;\n timeStamp: string;\n isError: string;\n input: string;\n}\n\ninterface RawTokenTransfer {\n hash: string;\n blockNumber: string;\n from: string;\n to: string;\n value: string;\n contractAddress: string;\n tokenSymbol: string;\n tokenDecimal: string;\n timeStamp: string;\n}\n\ninterface RawHolder {\n TokenHolderAddress: string;\n TokenHolderQuantity: string;\n // percentage not directly available from Etherscan\n}\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class EtherscanClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n\n constructor(baseUrl: string, apiKey?: string) {\n this.baseUrl = baseUrl;\n this.apiKey = apiKey ?? '';\n }\n\n // ── Transactions ──────────────────────────────────────────────────────\n\n async getTransactions(\n address: string,\n options?: { limit?: number; offset?: number; fromBlock?: bigint; toBlock?: bigint },\n ): Promise<Transaction[]> {\n const params: Record<string, string> = {\n module: 'account',\n action: 'txlist',\n address,\n sort: 'desc',\n page: '1',\n offset: String(options?.limit ?? 50),\n };\n if (options?.fromBlock != null) params['startblock'] = options.fromBlock.toString();\n if (options?.toBlock != null) params['endblock'] = options.toBlock.toString();\n\n const data = await this.request<RawTransaction[]>(params);\n if (!Array.isArray(data)) return [];\n\n return data.map(\n (tx): Transaction => ({\n hash: tx.hash,\n blockNumber: BigInt(tx.blockNumber),\n from: tx.from,\n to: tx.to || null,\n value: BigInt(tx.value),\n gasUsed: BigInt(tx.gasUsed),\n gasPrice: BigInt(tx.gasPrice),\n timestamp: Number(tx.timeStamp),\n status: tx.isError === '0' ? 'success' : 'reverted',\n input: tx.input,\n }),\n );\n }\n\n // ── Token Transfers ───────────────────────────────────────────────────\n\n async getTokenTransfers(\n address: string,\n options?: { tokenAddress?: string; limit?: number; fromBlock?: bigint; toBlock?: bigint },\n ): Promise<TokenTransfer[]> {\n const params: Record<string, string> = {\n module: 'account',\n action: 'tokentx',\n address,\n sort: 'desc',\n page: '1',\n offset: String(options?.limit ?? 50),\n };\n if (options?.tokenAddress) params['contractaddress'] = options.tokenAddress;\n if (options?.fromBlock != null) params['startblock'] = options.fromBlock.toString();\n if (options?.toBlock != null) params['endblock'] = options.toBlock.toString();\n\n const data = await this.request<RawTokenTransfer[]>(params);\n if (!Array.isArray(data)) return [];\n\n return data.map(\n (t): TokenTransfer => ({\n hash: t.hash,\n blockNumber: BigInt(t.blockNumber),\n from: t.from,\n to: t.to,\n value: BigInt(t.value),\n tokenAddress: t.contractAddress,\n tokenSymbol: t.tokenSymbol,\n tokenDecimals: Number(t.tokenDecimal),\n timestamp: Number(t.timeStamp),\n }),\n );\n }\n\n // ── Top Holders ───────────────────────────────────────────────────────\n\n async getTopHolders(tokenAddress: string, limit = 10): Promise<Holder[]> {\n // Note: Etherscan top holders endpoint is only on Pro plan.\n // We use the tokentx approach or fall back gracefully.\n const params: Record<string, string> = {\n module: 'token',\n action: 'tokenholderlist',\n contractaddress: tokenAddress,\n page: '1',\n offset: String(limit),\n };\n\n try {\n const data = await this.request<RawHolder[]>(params);\n if (!Array.isArray(data)) return [];\n\n // Calculate percentages from balances\n const totalBalance = data.reduce((sum, h) => sum + BigInt(h.TokenHolderQuantity), 0n);\n\n return data.map(\n (h): Holder => ({\n address: h.TokenHolderAddress,\n balance: BigInt(h.TokenHolderQuantity),\n percentage:\n totalBalance > 0n\n ? Number((BigInt(h.TokenHolderQuantity) * 10000n) / totalBalance) / 100\n : 0,\n }),\n );\n } catch {\n // Top holders endpoint may not be available on free tier\n return [];\n }\n }\n\n // ── Contract ABI ──────────────────────────────────────────────────────\n\n async getContractAbi(address: string): Promise<string | null> {\n const params: Record<string, string> = {\n module: 'contract',\n action: 'getabi',\n address,\n };\n\n try {\n const data = await this.request<string>(params);\n return typeof data === 'string' && data !== 'Contract source code not verified' ? data : null;\n } catch {\n return null;\n }\n }\n\n // ── Contract Verification Check ───────────────────────────────────────\n\n async isContractVerified(address: string): Promise<boolean> {\n const abi = await this.getContractAbi(address);\n return abi !== null;\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n private async request<T>(params: Record<string, string>): Promise<T> {\n if (this.apiKey) {\n params['apikey'] = this.apiKey;\n }\n\n const qs = new URLSearchParams(params).toString();\n const res = await fetch(`${this.baseUrl}?${qs}`);\n\n if (!res.ok) {\n throw new Error(`Etherscan API error: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as EtherscanResult<T>;\n\n if (json.status !== '1' && json.message !== 'OK' && json.message !== 'No transactions found') {\n // Some endpoints return status \"0\" with \"No records found\" which is valid\n if (json.message?.includes('No') || json.message?.includes('no')) {\n return [] as unknown as T;\n }\n throw new Error(`Etherscan: ${json.message}`);\n }\n\n return json.result;\n }\n}\n","// ---------------------------------------------------------------------------\n// Shared configuration constants\n// ---------------------------------------------------------------------------\n\n/** Default blockchain when none is specified. */\nexport const DEFAULT_CHAIN = 'ethereum';\n\n/** @deprecated Used only by CLI trends fallback. TUI uses dynamic trending data. */\nexport const TREND_SYMBOLS = ['bitcoin', 'ethereum', 'solana'];\n\n/** Default ticker symbols shown in the price bar. */\nexport const TICKER_DEFAULTS: { geckoId: string; symbol: string }[] = [\n { geckoId: 'bitcoin', symbol: 'BTC' },\n { geckoId: 'ethereum', symbol: 'ETH' },\n { geckoId: 'solana', symbol: 'SOL' },\n];\n\n/** Chain metadata for display and selection. */\nexport interface ChainMeta {\n id: string;\n name: string;\n icon: string;\n nativeSymbol: string;\n explorerUrl: string;\n explorerApiUrl: string;\n color: string;\n}\n\nexport const CHAIN_REGISTRY: ChainMeta[] = [\n {\n id: 'ethereum',\n name: 'Ethereum',\n icon: '\\u{039E}', // Greek Xi (ETH symbol)\n nativeSymbol: 'ETH',\n explorerUrl: 'https://etherscan.io',\n explorerApiUrl: 'https://api.etherscan.io/api',\n color: '#627EEA',\n },\n {\n id: 'polygon',\n name: 'Polygon',\n icon: '\\u{2B23}', // Hexagonal shape\n nativeSymbol: 'POL',\n explorerUrl: 'https://polygonscan.com',\n explorerApiUrl: 'https://api.polygonscan.com/api',\n color: '#8247E5',\n },\n {\n id: 'arbitrum',\n name: 'Arbitrum',\n icon: '\\u{25C6}', // Diamond\n nativeSymbol: 'ETH',\n explorerUrl: 'https://arbiscan.io',\n explorerApiUrl: 'https://api.arbiscan.io/api',\n color: '#28A0F0',\n },\n {\n id: 'optimism',\n name: 'Optimism',\n icon: '\\u{25CF}', // Filled circle\n nativeSymbol: 'ETH',\n explorerUrl: 'https://optimistic.etherscan.io',\n explorerApiUrl: 'https://api-optimistic.etherscan.io/api',\n color: '#FF0420',\n },\n {\n id: 'base',\n name: 'Base',\n icon: '\\u{25B3}', // Triangle up\n nativeSymbol: 'ETH',\n explorerUrl: 'https://basescan.org',\n explorerApiUrl: 'https://api.basescan.org/api',\n color: '#0052FF',\n },\n];\n\n/** Quick lookup: chain ID -> explorer API URL (backwards compatible). */\nexport const ETHERSCAN_BASE_URLS: Record<string, string> = Object.fromEntries(\n CHAIN_REGISTRY.map((c) => [c.id, c.explorerApiUrl]),\n);\n\n/** Quick lookup: chain ID -> chain metadata. */\nexport function getChainMeta(chainId: string): ChainMeta | undefined {\n return CHAIN_REGISTRY.find((c) => c.id === chainId);\n}\n\n/** Map of common token symbols to CoinGecko IDs. */\nexport const KNOWN_SYMBOLS: Record<string, string> = {\n btc: 'bitcoin',\n bitcoin: 'bitcoin',\n eth: 'ethereum',\n ethereum: 'ethereum',\n sol: 'solana',\n solana: 'solana',\n bnb: 'binancecoin',\n bsc: 'binancecoin',\n xrp: 'ripple',\n ripple: 'ripple',\n ada: 'cardano',\n cardano: 'cardano',\n doge: 'dogecoin',\n dogecoin: 'dogecoin',\n dot: 'polkadot',\n polkadot: 'polkadot',\n avax: 'avalanche-2',\n avalanche: 'avalanche-2',\n matic: 'matic-network',\n polygon: 'matic-network',\n link: 'chainlink',\n chainlink: 'chainlink',\n uni: 'uniswap',\n uniswap: 'uniswap',\n atom: 'cosmos',\n cosmos: 'cosmos',\n near: 'near',\n arb: 'arbitrum',\n op: 'optimism',\n sui: 'sui',\n apt: 'aptos',\n pepe: 'pepe',\n shib: 'shiba-inu',\n floki: 'floki',\n bonk: 'bonk',\n wif: 'dogwifcoin',\n};\n","// ---------------------------------------------------------------------------\n// EvmAdapter – ChainAdapter implementation for EVM-compatible chains (viem)\n// ---------------------------------------------------------------------------\n\nimport {\n createPublicClient,\n http,\n type PublicClient,\n type Chain,\n type HttpTransport,\n type Address,\n type Abi,\n} from 'viem';\nimport { mainnet, polygon, arbitrum, optimism, base, bsc, avalanche } from 'viem/chains';\nimport { assertValidAddress } from '../../utils/validate.js';\n\nimport type {\n ChainAdapter,\n Block,\n ContractEvent,\n EventOptions,\n Holder,\n TokenInfo,\n TokenTransfer,\n Transaction,\n TransferOptions,\n TxHistoryOptions,\n} from '../types.js';\nimport { erc20Abi } from './abi/erc20.js';\nimport { EtherscanClient } from './etherscan.js';\nimport { ETHERSCAN_BASE_URLS } from '../../config/constants.js';\n\n// ---------------------------------------------------------------------------\n// Chain ID → viem Chain object mapping\n// ---------------------------------------------------------------------------\n\nconst CHAIN_MAP: Record<string, Chain> = {\n ethereum: mainnet,\n polygon: polygon,\n arbitrum: arbitrum,\n optimism: optimism,\n base: base,\n bsc: bsc,\n avalanche: avalanche,\n};\n\n// ---------------------------------------------------------------------------\n// EvmAdapter\n// ---------------------------------------------------------------------------\n\nexport class EvmAdapter implements ChainAdapter {\n readonly chainId: string;\n readonly name: string;\n readonly nativeCurrency: { symbol: string; decimals: number };\n\n private client: PublicClient<HttpTransport, Chain> | null = null;\n private etherscan: EtherscanClient | null = null;\n private readonly viemChain: Chain;\n\n constructor(chainId: string) {\n const chain = CHAIN_MAP[chainId];\n if (!chain) {\n throw new Error(\n `Unsupported EVM chain: \"${chainId}\". Supported: ${Object.keys(CHAIN_MAP).join(', ')}`,\n );\n }\n\n this.chainId = chainId;\n this.viemChain = chain;\n this.name = chain.name;\n this.nativeCurrency = {\n symbol: chain.nativeCurrency.symbol,\n decimals: chain.nativeCurrency.decimals,\n };\n }\n\n // ── Lifecycle ───────────────────────────────────────────────────────────\n\n async connect(rpcUrl?: string, etherscanApiKey?: string): Promise<void> {\n this.client = createPublicClient({\n chain: this.viemChain,\n transport: http(rpcUrl),\n batch: { multicall: true },\n });\n\n // Create Etherscan client if a base URL is known for this chain\n const explorerUrl = ETHERSCAN_BASE_URLS[this.chainId];\n if (explorerUrl) {\n this.etherscan = new EtherscanClient(explorerUrl, etherscanApiKey);\n }\n }\n\n async disconnect(): Promise<void> {\n this.client = null;\n this.etherscan = null;\n }\n\n isConnected(): boolean {\n return this.client !== null;\n }\n\n /** Validate and cast to viem Address. */\n private toAddress(address: string): Address {\n assertValidAddress(address);\n return this.toAddress(address);\n }\n\n // ── Balances ────────────────────────────────────────────────────────────\n\n async getBalance(address: string): Promise<bigint> {\n const client = this.requireClient();\n return client.getBalance({ address: this.toAddress(address) });\n }\n\n async getTokenBalance(address: string, tokenAddress: string): Promise<bigint> {\n const client = this.requireClient();\n const balance = await client.readContract({\n address: this.toAddress(tokenAddress),\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [this.toAddress(address)],\n });\n return balance as bigint;\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTransactions(address, {\n limit: options?.limit,\n offset: options?.offset,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n });\n }\n\n async getTokenTransfers(address: string, options?: TransferOptions): Promise<TokenTransfer[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTokenTransfers(address, {\n tokenAddress: options?.tokenAddress,\n limit: options?.limit,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n });\n }\n\n // ── Contracts ───────────────────────────────────────────────────────────\n\n async getContractCode(address: string): Promise<string> {\n const client = this.requireClient();\n const code = await client.getCode({ address: this.toAddress(address) });\n return code ?? '0x';\n }\n\n async readContract(\n address: string,\n abi: readonly unknown[],\n functionName: string,\n args?: unknown[],\n ): Promise<unknown> {\n const client = this.requireClient();\n return client.readContract({\n address: this.toAddress(address),\n abi: abi as Abi,\n functionName,\n args: args as readonly unknown[],\n });\n }\n\n async getContractEvents(\n address: string,\n abi: readonly unknown[],\n eventName: string,\n options?: EventOptions,\n ): Promise<ContractEvent[]> {\n const client = this.requireClient();\n\n const logs = await client.getContractEvents({\n address: this.toAddress(address),\n abi: abi as Abi,\n eventName,\n fromBlock: options?.fromBlock,\n toBlock: options?.toBlock,\n args: options?.args as Record<string, unknown> | undefined,\n });\n\n return logs.map((log) => ({\n eventName: log.eventName ?? eventName,\n blockNumber: log.blockNumber ?? 0n,\n transactionHash: log.transactionHash ?? '0x',\n args: (log.args ?? {}) as Record<string, unknown>,\n logIndex: log.logIndex ?? 0,\n }));\n }\n\n // ── Tokens ──────────────────────────────────────────────────────────────\n\n async getTokenInfo(address: string): Promise<TokenInfo> {\n const client = this.requireClient();\n const tokenAddr = this.toAddress(address);\n\n const [name, symbol, decimals, totalSupply] = await Promise.all([\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'name',\n }) as Promise<string>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'symbol',\n }) as Promise<string>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'decimals',\n }) as Promise<number>,\n client.readContract({\n address: tokenAddr,\n abi: erc20Abi,\n functionName: 'totalSupply',\n }) as Promise<bigint>,\n ]);\n\n return { address, name, symbol, decimals, totalSupply };\n }\n\n async getTopHolders(tokenAddress: string, limit?: number): Promise<Holder[]> {\n if (!this.etherscan) return [];\n return this.etherscan.getTopHolders(tokenAddress, limit);\n }\n\n // ── Blocks ──────────────────────────────────────────────────────────────\n\n async getBlockNumber(): Promise<bigint> {\n const client = this.requireClient();\n return client.getBlockNumber();\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n const client = this.requireClient();\n const block = await client.getBlock({ blockNumber });\n\n return {\n number: block.number ?? 0n,\n hash: block.hash ?? '0x',\n parentHash: block.parentHash,\n timestamp: Number(block.timestamp),\n gasUsed: block.gasUsed,\n gasLimit: block.gasLimit,\n baseFeePerGas: block.baseFeePerGas ?? null,\n transactionCount: block.transactions.length,\n };\n }\n\n // ── Helpers ─────────────────────────────────────────────────────────────\n\n private requireClient(): PublicClient<HttpTransport, Chain> {\n if (!this.client) {\n throw new Error(`EvmAdapter(${this.chainId}): not connected. Call connect() first.`);\n }\n return this.client;\n }\n}\n","import pino from 'pino';\nimport type { Logger } from 'pino';\n\nconst level = process.env['VIZZOR_LOG_LEVEL'] ?? 'info';\n\n/**\n * Creates a named Pino logger instance.\n * Uses pino-pretty transport when NODE_ENV is not 'production'.\n */\nexport function createLogger(name: string): Logger {\n const isDev = process.env['NODE_ENV'] !== 'production';\n\n if (isDev) {\n return pino({\n name,\n level,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n },\n },\n });\n }\n\n return pino({ name, level });\n}\n","// ---------------------------------------------------------------------------\n// Writable EVM adapter — extends EvmAdapter with transaction support\n// ---------------------------------------------------------------------------\n\nimport { createWalletClient, http, type WalletClient, type Chain, type PublicClient } from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\nimport { mainnet, polygon, arbitrum, optimism, base, bsc, avalanche } from 'viem/chains';\nimport type { WritableChainAdapter, TransactionRequest, TransactionReceipt } from '../types.js';\nimport { EvmAdapter } from './adapter.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('writable-evm');\n\nconst CHAIN_MAP: Record<string, Chain> = {\n ethereum: mainnet,\n polygon,\n arbitrum,\n optimism,\n base,\n bsc,\n avalanche,\n};\n\nexport class WritableEvmAdapter extends EvmAdapter implements WritableChainAdapter {\n private walletClient: WalletClient | null = null;\n private privateKey: `0x${string}` | null = null;\n\n setPrivateKey(key: string): void {\n this.privateKey = (key.startsWith('0x') ? key : `0x${key}`) as `0x${string}`;\n }\n\n override async connect(rpcUrl?: string, explorerApiKey?: string): Promise<void> {\n await super.connect(rpcUrl, explorerApiKey);\n if (this.privateKey) {\n const chain = CHAIN_MAP[this.chainId];\n if (!chain) throw new Error(`Unsupported chain for writing: ${this.chainId}`);\n const account = privateKeyToAccount(this.privateKey);\n this.walletClient = createWalletClient({\n account,\n chain,\n transport: http(rpcUrl),\n });\n log.info(`Wallet connected: ${account.address} on ${this.chainId}`);\n }\n }\n\n private requireWallet(): WalletClient {\n if (!this.walletClient) throw new Error('Wallet not connected. Call setPrivateKey() first.');\n return this.walletClient;\n }\n\n private getPublicClient(): PublicClient {\n // Access the parent's public client via the internal getter\n if (!this.isConnected()) throw new Error('Adapter not connected');\n // EvmAdapter stores client as protected — we use readContract as proxy\n return (this as unknown as { client: PublicClient }).client;\n }\n\n async sendTransaction(tx: TransactionRequest): Promise<TransactionReceipt> {\n const wallet = this.requireWallet();\n const account = wallet.account;\n if (!account) throw new Error('Wallet account not set');\n const hash = await wallet.sendTransaction({\n account,\n to: tx.to as `0x${string}`,\n value: tx.value,\n data: tx.data as `0x${string}` | undefined,\n gas: tx.gasLimit,\n maxFeePerGas: tx.maxFeePerGas,\n maxPriorityFeePerGas: tx.maxPriorityFeePerGas,\n chain: wallet.chain,\n });\n log.info(`Transaction sent: ${hash}`);\n\n // Wait for receipt\n const publicClient = this.getPublicClient();\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n return {\n hash: receipt.transactionHash,\n blockNumber: receipt.blockNumber,\n status: receipt.status === 'success' ? 'success' : 'reverted',\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n logs: receipt.logs.map((l) => ({\n address: l.address,\n topics: [...l.topics],\n data: l.data,\n })),\n };\n }\n\n async writeContract(\n address: string,\n abi: readonly unknown[],\n functionName: string,\n args: unknown[] = [],\n value?: bigint,\n ): Promise<TransactionReceipt> {\n const wallet = this.requireWallet();\n const account = wallet.account;\n if (!account) throw new Error('Wallet account not set');\n const hash = await wallet.writeContract({\n account,\n address: address as `0x${string}`,\n abi: abi as readonly unknown[],\n functionName,\n args,\n chain: wallet.chain,\n ...(value !== undefined ? { value } : {}),\n } as Parameters<typeof wallet.writeContract>[0]);\n log.info(`Contract write: ${functionName} on ${address} → ${hash}`);\n\n const publicClient = this.getPublicClient();\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n return {\n hash: receipt.transactionHash,\n blockNumber: receipt.blockNumber,\n status: receipt.status === 'success' ? 'success' : 'reverted',\n gasUsed: receipt.gasUsed,\n effectiveGasPrice: receipt.effectiveGasPrice,\n logs: receipt.logs.map((l) => ({\n address: l.address,\n topics: [...l.topics],\n data: l.data,\n })),\n };\n }\n\n async signMessage(message: string): Promise<string> {\n const wallet = this.requireWallet();\n const account = wallet.account;\n if (!account) throw new Error('Wallet account not set');\n return wallet.signMessage({ account, message });\n }\n\n async estimateGas(tx: TransactionRequest): Promise<bigint> {\n const publicClient = this.getPublicClient();\n return publicClient.estimateGas({\n to: tx.to as `0x${string}`,\n value: tx.value,\n data: tx.data as `0x${string}` | undefined,\n });\n }\n}\n","// ---------------------------------------------------------------------------\n// ZK Chain Adapter — adapter for ZK rollup chains (zkSync, StarkNet, etc.)\n// Uses EVM adapter under the hood for EVM-compatible ZK rollups\n// ---------------------------------------------------------------------------\n\nimport { EvmAdapter } from '../evm/adapter.js';\n\n// ---------------------------------------------------------------------------\n// ZK-specific chain configurations\n// ---------------------------------------------------------------------------\n\nconst ZK_CHAIN_CONFIG: Record<\n string,\n {\n name: string;\n rpcUrl: string;\n explorerApi: string;\n nativeCurrency: { symbol: string; decimals: number };\n isEvm: boolean;\n }\n> = {\n zksync: {\n name: 'zkSync Era',\n rpcUrl: 'https://mainnet.era.zksync.io',\n explorerApi: 'https://block-explorer-api.mainnet.zksync.io/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n 'polygon-zkevm': {\n name: 'Polygon zkEVM',\n rpcUrl: 'https://zkevm-rpc.com',\n explorerApi: 'https://api-zkevm.polygonscan.com/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n scroll: {\n name: 'Scroll',\n rpcUrl: 'https://rpc.scroll.io',\n explorerApi: 'https://api.scrollscan.com/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n linea: {\n name: 'Linea',\n rpcUrl: 'https://rpc.linea.build',\n explorerApi: 'https://api.lineascan.build/api',\n nativeCurrency: { symbol: 'ETH', decimals: 18 },\n isEvm: true,\n },\n};\n\nexport class ZkEvmAdapter extends EvmAdapter {\n readonly zkType: string;\n private readonly zkName: string;\n\n constructor(chainId: string) {\n super(chainId);\n this.zkType = chainId;\n this.zkName = ZK_CHAIN_CONFIG[chainId]?.name ?? `ZK-${chainId}`;\n }\n\n getZkName(): string {\n return this.zkName;\n }\n\n getDefaultRpcUrl(): string {\n return ZK_CHAIN_CONFIG[this.chainId]?.rpcUrl ?? '';\n }\n}\n\nexport function getZkChainIds(): string[] {\n return Object.keys(ZK_CHAIN_CONFIG);\n}\n\nexport function isZkChain(chainId: string): boolean {\n return chainId in ZK_CHAIN_CONFIG;\n}\n","// ---------------------------------------------------------------------------\n// Solana adapter — implements ChainAdapter for Solana\n// ---------------------------------------------------------------------------\n\nimport type {\n ChainAdapter,\n Transaction,\n TokenTransfer,\n ContractEvent,\n TokenInfo,\n Holder,\n Block,\n TxHistoryOptions,\n TransferOptions,\n EventOptions,\n} from '../types.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('solana-adapter');\n\nexport class SolanaAdapter implements ChainAdapter {\n readonly chainId = 'solana';\n readonly name = 'Solana';\n readonly nativeCurrency = { symbol: 'SOL', decimals: 9 };\n\n private rpcUrl = 'https://api.mainnet-beta.solana.com';\n private connected = false;\n\n async connect(rpcUrl?: string): Promise<void> {\n if (rpcUrl) this.rpcUrl = rpcUrl;\n this.connected = true;\n log.info(`Connected to Solana: ${this.rpcUrl}`);\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private async rpc(method: string, params: unknown[] = []): Promise<unknown> {\n const res = await fetch(this.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),\n signal: AbortSignal.timeout(15000),\n });\n const json = (await res.json()) as { result?: unknown; error?: { message: string } };\n if (json.error) throw new Error(`Solana RPC: ${json.error.message}`);\n return json.result;\n }\n\n async getBalance(address: string): Promise<bigint> {\n const result = (await this.rpc('getBalance', [address])) as { value: number };\n return BigInt(result.value);\n }\n\n async getTokenBalance(address: string, tokenAddress: string): Promise<bigint> {\n const result = (await this.rpc('getTokenAccountsByOwner', [\n address,\n { mint: tokenAddress },\n { encoding: 'jsonParsed' },\n ])) as {\n value: { account: { data: { parsed: { info: { tokenAmount: { amount: string } } } } } }[];\n };\n if (result.value.length === 0) return 0n;\n return BigInt(result.value[0]!.account.data.parsed.info.tokenAmount.amount);\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n const limit = options?.limit ?? 20;\n const sigs = (await this.rpc('getSignaturesForAddress', [address, { limit }])) as {\n signature: string;\n blockTime: number;\n slot: number;\n err: unknown;\n }[];\n\n return sigs.map((s) => ({\n hash: s.signature,\n blockNumber: BigInt(s.slot),\n from: address,\n to: null,\n value: 0n,\n gasUsed: 0n,\n gasPrice: 0n,\n timestamp: s.blockTime ?? 0,\n status: s.err ? ('reverted' as const) : ('success' as const),\n input: '',\n }));\n }\n\n async getTokenTransfers(_address: string, _options?: TransferOptions): Promise<TokenTransfer[]> {\n // Solana token transfers require parsing transaction data\n return [];\n }\n\n async getContractCode(address: string): Promise<string> {\n const result = (await this.rpc('getAccountInfo', [address, { encoding: 'base64' }])) as {\n value: { data: string[] } | null;\n };\n return result?.value?.data?.[0] ?? '';\n }\n\n async readContract(\n _address: string,\n _abi: readonly unknown[],\n _functionName: string,\n _args?: unknown[],\n ): Promise<unknown> {\n throw new Error('readContract not supported on Solana — use program-specific methods');\n }\n\n async getContractEvents(\n _address: string,\n _abi: readonly unknown[],\n _eventName: string,\n _options?: EventOptions,\n ): Promise<ContractEvent[]> {\n return [];\n }\n\n async getTokenInfo(address: string): Promise<TokenInfo> {\n const result = (await this.rpc('getAccountInfo', [address, { encoding: 'jsonParsed' }])) as {\n value: { data: { parsed: { info: { decimals: number; supply: string } } } } | null;\n };\n\n const info = result?.value?.data?.parsed?.info;\n return {\n address,\n name: 'SPL Token',\n symbol: 'SPL',\n decimals: info?.decimals ?? 9,\n totalSupply: BigInt(info?.supply ?? '0'),\n };\n }\n\n async getTopHolders(_tokenAddress: string, _limit?: number): Promise<Holder[]> {\n return [];\n }\n\n async getBlockNumber(): Promise<bigint> {\n const slot = (await this.rpc('getSlot')) as number;\n return BigInt(slot);\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n const result = (await this.rpc('getBlock', [\n Number(blockNumber),\n { transactionDetails: 'none' },\n ])) as {\n blockhash: string;\n parentSlot: number;\n blockTime: number;\n transactions: unknown[];\n } | null;\n\n return {\n number: blockNumber,\n hash: result?.blockhash ?? '',\n parentHash: '',\n timestamp: result?.blockTime ?? 0,\n gasUsed: 0n,\n gasLimit: 0n,\n baseFeePerGas: null,\n transactionCount: result?.transactions?.length ?? 0,\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// Sui adapter — implements ChainAdapter for Sui\n// ---------------------------------------------------------------------------\n\nimport type {\n ChainAdapter,\n Transaction,\n TokenTransfer,\n ContractEvent,\n TokenInfo,\n Holder,\n Block,\n TxHistoryOptions,\n TransferOptions,\n EventOptions,\n} from '../types.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('sui-adapter');\n\nexport class SuiAdapter implements ChainAdapter {\n readonly chainId = 'sui';\n readonly name = 'Sui';\n readonly nativeCurrency = { symbol: 'SUI', decimals: 9 };\n\n private rpcUrl = 'https://fullnode.mainnet.sui.io:443';\n private connected = false;\n\n async connect(rpcUrl?: string): Promise<void> {\n if (rpcUrl) this.rpcUrl = rpcUrl;\n this.connected = true;\n log.info(`Connected to Sui: ${this.rpcUrl}`);\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private async rpc(method: string, params: unknown[] = []): Promise<unknown> {\n const res = await fetch(this.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),\n signal: AbortSignal.timeout(15000),\n });\n const json = (await res.json()) as { result?: unknown; error?: { message: string } };\n if (json.error) throw new Error(`Sui RPC: ${json.error.message}`);\n return json.result;\n }\n\n async getBalance(address: string): Promise<bigint> {\n const result = (await this.rpc('suix_getBalance', [address, '0x2::sui::SUI'])) as {\n totalBalance: string;\n };\n return BigInt(result.totalBalance);\n }\n\n async getTokenBalance(address: string, tokenAddress: string): Promise<bigint> {\n const result = (await this.rpc('suix_getBalance', [address, tokenAddress])) as {\n totalBalance: string;\n };\n return BigInt(result.totalBalance);\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n const limit = options?.limit ?? 20;\n const result = (await this.rpc('suix_queryTransactionBlocks', [\n { filter: { FromAddress: address } },\n null,\n limit,\n true,\n ])) as { data: { digest: string; timestampMs: string; checkpoint: string }[] };\n\n return (result.data ?? []).map((tx) => ({\n hash: tx.digest,\n blockNumber: BigInt(tx.checkpoint ?? '0'),\n from: address,\n to: null,\n value: 0n,\n gasUsed: 0n,\n gasPrice: 0n,\n timestamp: Math.floor(Number(tx.timestampMs) / 1000),\n status: 'success' as const,\n input: '',\n }));\n }\n\n async getTokenTransfers(_address: string, _options?: TransferOptions): Promise<TokenTransfer[]> {\n return [];\n }\n\n async getContractCode(address: string): Promise<string> {\n const result = (await this.rpc('sui_getObject', [address, { showContent: true }])) as {\n data?: { content?: { type: string } };\n };\n return result.data?.content?.type ?? '';\n }\n\n async readContract(\n _address: string,\n _abi: readonly unknown[],\n _functionName: string,\n _args?: unknown[],\n ): Promise<unknown> {\n throw new Error('readContract not supported on Sui — use Move call methods');\n }\n\n async getContractEvents(\n _address: string,\n _abi: readonly unknown[],\n _eventName: string,\n _options?: EventOptions,\n ): Promise<ContractEvent[]> {\n return [];\n }\n\n async getTokenInfo(address: string): Promise<TokenInfo> {\n const result = (await this.rpc('suix_getCoinMetadata', [address])) as {\n name: string;\n symbol: string;\n decimals: number;\n } | null;\n\n return {\n address,\n name: result?.name ?? 'Unknown',\n symbol: result?.symbol ?? '???',\n decimals: result?.decimals ?? 9,\n totalSupply: 0n,\n };\n }\n\n async getTopHolders(_tokenAddress: string, _limit?: number): Promise<Holder[]> {\n return [];\n }\n\n async getBlockNumber(): Promise<bigint> {\n const result = (await this.rpc('sui_getLatestCheckpointSequenceNumber')) as string;\n return BigInt(result);\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n const result = (await this.rpc('sui_getCheckpoint', [String(blockNumber)])) as {\n digest: string;\n previousDigest: string;\n timestampMs: string;\n transactions: string[];\n } | null;\n\n return {\n number: blockNumber,\n hash: result?.digest ?? '',\n parentHash: result?.previousDigest ?? '',\n timestamp: result ? Math.floor(Number(result.timestampMs) / 1000) : 0,\n gasUsed: 0n,\n gasLimit: 0n,\n baseFeePerGas: null,\n transactionCount: result?.transactions?.length ?? 0,\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// Aptos adapter — implements ChainAdapter for Aptos\n// ---------------------------------------------------------------------------\n\nimport type {\n ChainAdapter,\n Transaction,\n TokenTransfer,\n ContractEvent,\n TokenInfo,\n Holder,\n Block,\n TxHistoryOptions,\n TransferOptions,\n EventOptions,\n} from '../types.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('aptos-adapter');\n\nexport class AptosAdapter implements ChainAdapter {\n readonly chainId = 'aptos';\n readonly name = 'Aptos';\n readonly nativeCurrency = { symbol: 'APT', decimals: 8 };\n\n private apiUrl = 'https://fullnode.mainnet.aptoslabs.com/v1';\n private connected = false;\n\n async connect(rpcUrl?: string): Promise<void> {\n if (rpcUrl) this.apiUrl = rpcUrl;\n this.connected = true;\n log.info(`Connected to Aptos: ${this.apiUrl}`);\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private async api(path: string): Promise<unknown> {\n const res = await fetch(`${this.apiUrl}${path}`, {\n signal: AbortSignal.timeout(15000),\n });\n if (!res.ok) throw new Error(`Aptos API: ${res.status} ${res.statusText}`);\n return res.json();\n }\n\n async getBalance(address: string): Promise<bigint> {\n try {\n const result = (await this.api(\n `/accounts/${address}/resource/0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>`,\n )) as { data: { coin: { value: string } } };\n return BigInt(result.data.coin.value);\n } catch {\n return 0n;\n }\n }\n\n async getTokenBalance(address: string, tokenAddress: string): Promise<bigint> {\n try {\n const result = (await this.api(\n `/accounts/${address}/resource/0x1::coin::CoinStore<${tokenAddress}>`,\n )) as { data: { coin: { value: string } } };\n return BigInt(result.data.coin.value);\n } catch {\n return 0n;\n }\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n const limit = options?.limit ?? 20;\n const txns = (await this.api(`/accounts/${address}/transactions?limit=${limit}`)) as {\n hash: string;\n version: string;\n sender: string;\n timestamp: string;\n success: boolean;\n gas_used: string;\n gas_unit_price: string;\n }[];\n\n return txns.map((tx) => ({\n hash: tx.hash,\n blockNumber: BigInt(tx.version),\n from: tx.sender,\n to: null,\n value: 0n,\n gasUsed: BigInt(tx.gas_used),\n gasPrice: BigInt(tx.gas_unit_price),\n timestamp: Math.floor(Number(tx.timestamp) / 1e6),\n status: tx.success ? ('success' as const) : ('reverted' as const),\n input: '',\n }));\n }\n\n async getTokenTransfers(_address: string, _options?: TransferOptions): Promise<TokenTransfer[]> {\n return [];\n }\n\n async getContractCode(address: string): Promise<string> {\n try {\n const result = (await this.api(`/accounts/${address}/modules`)) as { bytecode: string }[];\n return result.map((m) => m.bytecode).join('');\n } catch {\n return '';\n }\n }\n\n async readContract(\n _address: string,\n _abi: readonly unknown[],\n _functionName: string,\n _args?: unknown[],\n ): Promise<unknown> {\n throw new Error('readContract not supported on Aptos — use Move view functions');\n }\n\n async getContractEvents(\n _address: string,\n _abi: readonly unknown[],\n _eventName: string,\n _options?: EventOptions,\n ): Promise<ContractEvent[]> {\n return [];\n }\n\n async getTokenInfo(address: string): Promise<TokenInfo> {\n return {\n address,\n name: 'Move Coin',\n symbol: 'MOVE',\n decimals: 8,\n totalSupply: 0n,\n };\n }\n\n async getTopHolders(_tokenAddress: string, _limit?: number): Promise<Holder[]> {\n return [];\n }\n\n async getBlockNumber(): Promise<bigint> {\n const result = (await this.api('/')) as { ledger_version: string };\n return BigInt(result.ledger_version);\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n const result = (await this.api(`/blocks/by_version/${blockNumber}`)) as {\n block_hash: string;\n block_height: string;\n block_timestamp: string;\n transactions: unknown[];\n };\n\n return {\n number: BigInt(result.block_height),\n hash: result.block_hash,\n parentHash: '',\n timestamp: Math.floor(Number(result.block_timestamp) / 1e6),\n gasUsed: 0n,\n gasLimit: 0n,\n baseFeePerGas: null,\n transactionCount: result.transactions?.length ?? 0,\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// TON adapter — implements ChainAdapter for TON blockchain\n// ---------------------------------------------------------------------------\n\nimport type {\n ChainAdapter,\n Transaction,\n TokenTransfer,\n ContractEvent,\n TokenInfo,\n Holder,\n Block,\n TxHistoryOptions,\n TransferOptions,\n EventOptions,\n} from '../types.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('ton-adapter');\n\nexport class TonAdapter implements ChainAdapter {\n readonly chainId = 'ton';\n readonly name = 'TON';\n readonly nativeCurrency = { symbol: 'TON', decimals: 9 };\n\n private apiUrl = 'https://toncenter.com/api/v2';\n private connected = false;\n\n async connect(rpcUrl?: string): Promise<void> {\n if (rpcUrl) this.apiUrl = rpcUrl;\n this.connected = true;\n log.info(`Connected to TON: ${this.apiUrl}`);\n }\n\n async disconnect(): Promise<void> {\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n private async api(method: string, params: Record<string, string> = {}): Promise<unknown> {\n const qs = new URLSearchParams(params).toString();\n const url = `${this.apiUrl}/${method}${qs ? `?${qs}` : ''}`;\n const res = await fetch(url, { signal: AbortSignal.timeout(15000) });\n if (!res.ok) throw new Error(`TON API: ${res.status}`);\n const json = (await res.json()) as { ok: boolean; result: unknown; error?: string };\n if (!json.ok) throw new Error(`TON API: ${json.error ?? 'unknown error'}`);\n return json.result;\n }\n\n async getBalance(address: string): Promise<bigint> {\n const result = (await this.api('getAddressBalance', { address })) as string;\n return BigInt(result);\n }\n\n async getTokenBalance(_address: string, _tokenAddress: string): Promise<bigint> {\n // Jetton balance requires querying the jetton wallet contract\n return 0n;\n }\n\n async getTransactionHistory(address: string, options?: TxHistoryOptions): Promise<Transaction[]> {\n const limit = options?.limit ?? 20;\n const txns = (await this.api('getTransactions', {\n address,\n limit: String(limit),\n })) as {\n transaction_id: { hash: string };\n utime: number;\n in_msg?: { value: string; source: string; destination: string };\n out_msgs?: { value: string; source: string; destination: string }[];\n fee: string;\n }[];\n\n return txns.map((tx) => ({\n hash: tx.transaction_id.hash,\n blockNumber: 0n,\n from: tx.in_msg?.source ?? address,\n to: tx.in_msg?.destination ?? null,\n value: BigInt(tx.in_msg?.value ?? '0'),\n gasUsed: BigInt(tx.fee),\n gasPrice: 0n,\n timestamp: tx.utime,\n status: 'success' as const,\n input: '',\n }));\n }\n\n async getTokenTransfers(_address: string, _options?: TransferOptions): Promise<TokenTransfer[]> {\n return [];\n }\n\n async getContractCode(address: string): Promise<string> {\n try {\n const result = (await this.api('getAddressInformation', { address })) as {\n code: string;\n };\n return result.code ?? '';\n } catch {\n return '';\n }\n }\n\n async readContract(\n _address: string,\n _abi: readonly unknown[],\n _functionName: string,\n _args?: unknown[],\n ): Promise<unknown> {\n throw new Error('readContract not supported on TON — use get methods');\n }\n\n async getContractEvents(\n _address: string,\n _abi: readonly unknown[],\n _eventName: string,\n _options?: EventOptions,\n ): Promise<ContractEvent[]> {\n return [];\n }\n\n async getTokenInfo(_address: string): Promise<TokenInfo> {\n return {\n address: _address,\n name: 'Jetton',\n symbol: 'JET',\n decimals: 9,\n totalSupply: 0n,\n };\n }\n\n async getTopHolders(_tokenAddress: string, _limit?: number): Promise<Holder[]> {\n return [];\n }\n\n async getBlockNumber(): Promise<bigint> {\n const result = (await this.api('getMasterchainInfo')) as {\n last: { seqno: number };\n };\n return BigInt(result.last.seqno);\n }\n\n async getBlock(blockNumber: bigint): Promise<Block> {\n return {\n number: blockNumber,\n hash: '',\n parentHash: '',\n timestamp: 0,\n gasUsed: 0n,\n gasLimit: 0n,\n baseFeePerGas: null,\n transactionCount: 0,\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// Chain adapter registry – factory-based creation of ChainAdapter instances\n// ---------------------------------------------------------------------------\n\nimport type { ChainAdapter, WritableChainAdapter } from './types.js';\nimport { EvmAdapter } from './evm/adapter.js';\nimport { WritableEvmAdapter } from './evm/writable-adapter.js';\nimport { ZkEvmAdapter, getZkChainIds } from './zk/adapter.js';\nimport { SolanaAdapter } from './solana/adapter.js';\nimport { SuiAdapter } from './sui/adapter.js';\nimport { AptosAdapter } from './aptos/adapter.js';\nimport { TonAdapter } from './ton/adapter.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** A factory that produces a ChainAdapter for a given chain ID. */\nexport type ChainAdapterFactory = (chainId: string) => ChainAdapter;\n\n// ---------------------------------------------------------------------------\n// Internal registry map\n// ---------------------------------------------------------------------------\n\nconst registry = new Map<string, ChainAdapterFactory>();\n\n// ---------------------------------------------------------------------------\n// Built-in EVM adapters\n// ---------------------------------------------------------------------------\n\nconst evmFactory: ChainAdapterFactory = (chainId) => new EvmAdapter(chainId);\n\nconst BUILTIN_EVM_CHAINS = ['ethereum', 'polygon', 'arbitrum', 'optimism', 'base'] as const;\n\nfor (const chainId of BUILTIN_EVM_CHAINS) {\n registry.set(chainId, evmFactory);\n}\n\n// ZK rollup chains (EVM-compatible)\nconst zkFactory: ChainAdapterFactory = (chainId) => new ZkEvmAdapter(chainId);\n\nfor (const chainId of getZkChainIds()) {\n registry.set(chainId, zkFactory);\n}\n\n// Additional EVM-compatible chains\nregistry.set('bsc', evmFactory);\nregistry.set('avalanche', evmFactory);\n\n// Non-EVM chain adapters\nregistry.set('solana', () => new SolanaAdapter());\nregistry.set('sui', () => new SuiAdapter());\nregistry.set('aptos', () => new AptosAdapter());\nregistry.set('ton', () => new TonAdapter());\n\n// ---------------------------------------------------------------------------\n// Writable EVM adapter factory\n// ---------------------------------------------------------------------------\n\nconst writableEvmFactory: ChainAdapterFactory = (chainId) => new WritableEvmAdapter(chainId);\n\nexport function getWritableAdapter(chainId: string): WritableChainAdapter {\n const adapter = writableEvmFactory(chainId);\n return adapter as WritableChainAdapter;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create (or retrieve) a {@link ChainAdapter} for the given chain ID.\n *\n * Each call produces a **new** adapter instance; callers are responsible for\n * caching if they need to reuse across requests.\n */\nexport function getAdapter(chainId: string): ChainAdapter {\n const factory = registry.get(chainId);\n if (!factory) {\n throw new Error(\n `No adapter registered for chain \"${chainId}\". ` +\n `Supported chains: ${getSupportedChains().join(', ')}`,\n );\n }\n return factory(chainId);\n}\n\n/**\n * Register a custom adapter factory for a chain ID.\n *\n * This allows third-party or non-EVM chains to plug into Vizzor.\n */\nexport function registerAdapter(chainId: string, factory: ChainAdapterFactory): void {\n registry.set(chainId, factory);\n}\n\n/**\n * Return the list of chain IDs that have registered adapter factories.\n */\nexport function getSupportedChains(): string[] {\n return [...registry.keys()];\n}\n","// ---------------------------------------------------------------------------\n// ML Sidecar HTTP client — communicates with the Python FastAPI sidecar\n// ---------------------------------------------------------------------------\n\nimport { createLogger } from '../utils/logger.js';\nimport type {\n FeatureVector,\n MLPredictionResult,\n AnomalyResult,\n ModelHealth,\n TokenFlow,\n RugMLFeatures,\n RugMLResult,\n WalletMLFeatures,\n WalletMLResult,\n SentimentMLResult,\n TrendMLFeatures,\n TrendMLResult,\n TAMLFeatures,\n TAMLResult,\n StrategyMLFeatures,\n StrategyMLResult,\n RegimeMLFeatures,\n RegimeMLResult,\n ProjectRiskMLFeatures,\n ProjectRiskMLResult,\n PortfolioOptMLFeatures,\n PortfolioOptMLResult,\n IntentMLResult,\n BytecodeRiskMLFeatures,\n BytecodeRiskMLResult,\n PortfolioPredMLFeatures,\n PortfolioPredMLResult,\n} from './types.js';\n\nconst log = createLogger('ml-client');\n\nexport class MLClient {\n private baseUrl: string;\n private healthy = false;\n\n constructor(baseUrl: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '');\n }\n\n async predict(features: FeatureVector): Promise<MLPredictionResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as MLPredictionResult;\n } catch (err) {\n log.debug(`ML predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async batchPredict(features: FeatureVector[]): Promise<MLPredictionResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/batch`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ features }),\n signal: AbortSignal.timeout(15000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { predictions: MLPredictionResult[] };\n return data.predictions;\n } catch (err) {\n log.debug(`ML batch predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n async detectAnomalies(flows: TokenFlow[]): Promise<AnomalyResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/anomalies`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ flows }),\n signal: AbortSignal.timeout(10000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { anomalies: AnomalyResult[] };\n return data.anomalies;\n } catch (err) {\n log.debug(`ML anomaly detection failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n this.healthy = res.ok;\n return this.healthy;\n } catch {\n this.healthy = false;\n return false;\n }\n }\n\n async predictRug(features: RugMLFeatures): Promise<RugMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/rug`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as RugMLResult;\n } catch (err) {\n log.debug(`ML rug predict failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async classifyWallet(features: WalletMLFeatures): Promise<WalletMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/wallet`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as WalletMLResult;\n } catch (err) {\n log.debug(`ML wallet classify failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async analyzeSentiment(text: string): Promise<SentimentMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/sentiment`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as SentimentMLResult;\n } catch (err) {\n log.debug(`ML sentiment failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async analyzeSentimentBatch(texts: string[]): Promise<SentimentMLResult[]> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/sentiment/batch`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ texts }),\n signal: AbortSignal.timeout(15000),\n });\n if (!res.ok) return [];\n const data = (await res.json()) as { results: SentimentMLResult[] };\n return data.results;\n } catch (err) {\n log.debug(`ML sentiment batch failed: ${err instanceof Error ? err.message : String(err)}`);\n return [];\n }\n }\n\n // -----------------------------------------------------------------------\n // v0.11.0 — New ML endpoints\n // -----------------------------------------------------------------------\n\n async scoreTrend(features: TrendMLFeatures): Promise<TrendMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/trend`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as TrendMLResult;\n } catch (err) {\n log.debug(`ML trend score failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async interpretTA(features: TAMLFeatures): Promise<TAMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/ta`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as TAMLResult;\n } catch (err) {\n log.debug(`ML TA interpret failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async evaluateStrategy(features: StrategyMLFeatures): Promise<StrategyMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/strategy`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as StrategyMLResult;\n } catch (err) {\n log.debug(`ML strategy eval failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async detectRegime(features: RegimeMLFeatures): Promise<RegimeMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/regime`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as RegimeMLResult;\n } catch (err) {\n log.debug(`ML regime detect failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async scoreProjectRisk(features: ProjectRiskMLFeatures): Promise<ProjectRiskMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/project-risk`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as ProjectRiskMLResult;\n } catch (err) {\n log.debug(`ML project risk failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async optimizePortfolio(features: PortfolioOptMLFeatures): Promise<PortfolioOptMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/portfolio-opt`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as PortfolioOptMLResult;\n } catch (err) {\n log.debug(`ML portfolio opt failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async classifyIntent(text: string): Promise<IntentMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/intent`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ text }),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as IntentMLResult;\n } catch (err) {\n log.debug(`ML intent classify failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async scoreBytecodeRisk(features: BytecodeRiskMLFeatures): Promise<BytecodeRiskMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/bytecode-risk`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as BytecodeRiskMLResult;\n } catch (err) {\n log.debug(`ML bytecode risk failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async predictPortfolioForward(\n features: PortfolioPredMLFeatures,\n ): Promise<PortfolioPredMLResult | null> {\n try {\n const res = await fetch(`${this.baseUrl}/predict/portfolio-forward`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(features),\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) return null;\n return (await res.json()) as PortfolioPredMLResult;\n } catch (err) {\n log.debug(`ML portfolio forward failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async trainModel(modelName: string, params?: Record<string, unknown>): Promise<unknown> {\n try {\n const res = await fetch(`${this.baseUrl}/train`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: modelName, ...params }),\n signal: AbortSignal.timeout(300000), // 5 min for training\n });\n if (!res.ok) return null;\n return await res.json();\n } catch (err) {\n log.debug(`ML train failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async evaluateModel(modelName: string): Promise<unknown> {\n try {\n const res = await fetch(`${this.baseUrl}/evaluate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: modelName }),\n signal: AbortSignal.timeout(60000),\n });\n if (!res.ok) return null;\n return await res.json();\n } catch (err) {\n log.debug(`ML evaluate failed: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n }\n\n async getModelHealth(): Promise<ModelHealth | null> {\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n signal: AbortSignal.timeout(3000),\n });\n if (!res.ok) return null;\n return (await res.json()) as ModelHealth;\n } catch {\n return null;\n }\n }\n\n isHealthy(): boolean {\n return this.healthy;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton accessor — lazy-initialized from config\n// ---------------------------------------------------------------------------\n\nlet mlClient: MLClient | null = null;\n\nexport function initMLClient(url: string): MLClient {\n mlClient = new MLClient(url);\n return mlClient;\n}\n\nexport function getMLClient(): MLClient | null {\n return mlClient;\n}\n","import type { ChainAdapter, TokenInfo } from '../../chains/types.js';\nimport { getMLClient } from '../../ml/client.js';\nimport type { ProjectRiskMLResult } from '../../ml/types.js';\n\nexport interface ProjectAnalysis {\n token: TokenInfo | null;\n contractVerified: boolean;\n hasSourceCode: boolean;\n holderConcentration: number;\n topHolders: { address: string; percentage: number }[];\n riskIndicators: RiskIndicator[];\n riskScore: number;\n mlRisk?: ProjectRiskMLResult;\n}\n\nexport interface RiskIndicator {\n name: string;\n detected: boolean;\n severity: 'low' | 'medium' | 'high' | 'critical';\n points: number;\n description: string;\n}\n\nexport async function analyzeProject(\n address: string,\n adapter: ChainAdapter,\n): Promise<ProjectAnalysis> {\n const [token, code, holders] = await Promise.allSettled([\n adapter.getTokenInfo(address),\n adapter.getContractCode(address),\n adapter.getTopHolders(address, 10),\n ]);\n\n const tokenInfo = token.status === 'fulfilled' ? token.value : null;\n const contractCode = code.status === 'fulfilled' ? code.value : '';\n const topHolders = holders.status === 'fulfilled' ? holders.value : [];\n\n const hasSourceCode = contractCode.length > 2;\n const riskIndicators = evaluateRiskIndicators(tokenInfo, hasSourceCode, topHolders);\n const riskScore = riskIndicators.reduce(\n (score, indicator) => score + (indicator.detected ? indicator.points : 0),\n 0,\n );\n\n const totalSupply = tokenInfo?.totalSupply ?? 0n;\n const topHolderPercentage =\n topHolders.length > 0 && totalSupply > 0n\n ? Number(((topHolders[0]?.balance ?? 0n) * 10000n) / totalSupply) / 100\n : 0;\n\n const topHoldersMapped = topHolders.map((h) => ({\n address: h.address,\n percentage: totalSupply > 0n ? Number((h.balance * 10000n) / totalSupply) / 100 : 0,\n }));\n\n const top10Pct = topHoldersMapped.reduce((sum, h) => sum + h.percentage, 0);\n\n // ML: score project risk with ML model\n let mlRisk: ProjectRiskMLResult | undefined;\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const result = await mlClient.scoreProjectRisk({\n bytecode_size: contractCode.length,\n is_verified: hasSourceCode ? 1 : 0,\n holder_concentration: topHolderPercentage,\n has_proxy: 0,\n has_mint: 0,\n has_pause: 0,\n has_blacklist: 0,\n liquidity_locked: 0,\n buy_tax: 0,\n sell_tax: 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: topHolderPercentage,\n is_open_source: hasSourceCode ? 1 : 0,\n top10_holder_pct: top10Pct,\n has_token_info: tokenInfo ? 1 : 0,\n });\n if (result) {\n mlRisk = result;\n }\n } catch {\n // ML unavailable\n }\n }\n\n return {\n token: tokenInfo,\n contractVerified: hasSourceCode,\n hasSourceCode,\n holderConcentration: topHolderPercentage,\n topHolders: topHoldersMapped,\n riskIndicators,\n riskScore: Math.min(100, riskScore),\n mlRisk,\n };\n}\n\nfunction evaluateRiskIndicators(\n token: TokenInfo | null,\n hasSource: boolean,\n topHolders: { address: string; balance: bigint }[],\n): RiskIndicator[] {\n const indicators: RiskIndicator[] = [];\n\n indicators.push({\n name: 'Unverified Contract',\n detected: !hasSource,\n severity: 'high',\n points: 30,\n description: 'Contract source code is not verified on block explorer',\n });\n\n if (token && topHolders.length > 0) {\n const topBalance = topHolders[0]?.balance ?? 0n;\n const concentrated = token.totalSupply > 0n && topBalance * 2n > token.totalSupply;\n indicators.push({\n name: 'Concentrated Supply',\n detected: concentrated,\n severity: 'critical',\n points: 25,\n description: 'Top holder owns more than 50% of total supply',\n });\n }\n\n indicators.push({\n name: 'No Token Info',\n detected: token === null,\n severity: 'medium',\n points: 15,\n description: 'Unable to read token metadata from contract',\n });\n\n return indicators;\n}\n","import type { ProjectAnalysis } from './project-analyzer.js';\n\nexport interface RiskAssessment {\n score: number;\n level: 'low' | 'medium' | 'high' | 'critical';\n summary: string;\n factors: string[];\n mlScore?: number;\n mlLevel?: string;\n}\n\nexport function assessRisk(analysis: ProjectAnalysis): RiskAssessment {\n const { riskScore, riskIndicators, mlRisk } = analysis;\n\n // Use ML risk probability if available, else fall back to point sum\n const effectiveScore = mlRisk ? Math.round(mlRisk.risk_probability * 100) : riskScore;\n const level = getRiskLevel(effectiveScore);\n\n const factors = riskIndicators\n .filter((i) => i.detected)\n .map((i) => `${i.name}: ${i.description} (+${i.points})`);\n\n // Add ML risk factors if available\n if (mlRisk) {\n for (const f of mlRisk.risk_factors) {\n factors.push(`ML: ${f.factor} (importance: ${(f.importance * 100).toFixed(1)}%)`);\n }\n }\n\n const summary = buildSummary(level, factors.length);\n\n return {\n score: effectiveScore,\n level,\n summary,\n factors,\n mlScore: mlRisk ? Math.round(mlRisk.risk_probability * 100) : undefined,\n mlLevel: mlRisk?.risk_level,\n };\n}\n\nfunction getRiskLevel(score: number): RiskAssessment['level'] {\n if (score <= 20) return 'low';\n if (score <= 50) return 'medium';\n if (score <= 75) return 'high';\n return 'critical';\n}\n\nfunction buildSummary(level: RiskAssessment['level'], factorCount: number): string {\n switch (level) {\n case 'low':\n return 'Project shows minimal risk indicators. Standard due diligence recommended.';\n case 'medium':\n return `Project has ${factorCount} risk factor(s) detected. Proceed with caution.`;\n case 'high':\n return `Project has significant risk indicators. Thorough investigation recommended before any interaction.`;\n case 'critical':\n return `Project shows critical risk signals. High probability of scam or rug pull.`;\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\nimport { assertValidAddress } from '../../utils/validate.js';\n\nexport async function handleScan(\n project: string,\n options: { chain: string; deep: boolean; json: boolean },\n): Promise<void> {\n assertValidAddress(project);\n const spinner = ora(`Scanning ${project} on ${options.chain}...`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n spinner.text = 'Fetching on-chain data...';\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify({ analysis, risk }, null, 2));\n return;\n }\n\n const riskColor =\n risk.level === 'low'\n ? chalk.green\n : risk.level === 'medium'\n ? chalk.yellow\n : risk.level === 'high'\n ? chalk.red\n : chalk.bgRed.white;\n\n console.log();\n console.log(chalk.bold(`Project Analysis: ${project}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n if (analysis.token) {\n console.log(chalk.bold('Token Info'));\n console.log(` Name: ${analysis.token.name}`);\n console.log(` Symbol: ${analysis.token.symbol}`);\n console.log(` Decimals: ${analysis.token.decimals}`);\n console.log();\n }\n\n console.log(chalk.bold('Risk Assessment'));\n console.log(` Score: ${riskColor(`${risk.score}/100 (${risk.level.toUpperCase()})`)}`);\n console.log(` ${risk.summary}`);\n console.log();\n\n if (risk.factors.length > 0) {\n console.log(chalk.bold('Risk Factors'));\n for (const factor of risk.factors) {\n console.log(` ${chalk.red('!')} ${factor}`);\n }\n console.log();\n }\n\n console.log(\n chalk.dim('Disclaimer: This is not financial advice. Always do your own research.'),\n );\n } catch (error) {\n spinner.fail('Scan failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","// ---------------------------------------------------------------------------\n// DexScreener API client — real-time DEX pair data, no auth required\n// https://docs.dexscreener.com/api/reference\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.dexscreener.com';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface DexToken {\n address: string;\n name: string;\n symbol: string;\n}\n\nexport interface DexTxns {\n buys: number;\n sells: number;\n}\n\nexport interface DexPair {\n chainId: string;\n dexId: string;\n pairAddress: string;\n url: string;\n baseToken: DexToken;\n quoteToken: DexToken;\n priceNative: string;\n priceUsd: string | null;\n txns: {\n m5: DexTxns;\n h1: DexTxns;\n h6: DexTxns;\n h24: DexTxns;\n };\n volume: { m5: number; h1: number; h6: number; h24: number };\n priceChange: { m5: number; h1: number; h6: number; h24: number };\n liquidity: { usd: number; base: number; quote: number } | null;\n fdv: number | null;\n marketCap: number | null;\n pairCreatedAt: number | null;\n info?: {\n imageUrl?: string;\n websites?: { url: string; label?: string }[];\n socials?: { type: string; url: string }[];\n };\n labels?: string[];\n}\n\nexport interface TokenProfile {\n url: string;\n chainId: string;\n tokenAddress: string;\n icon?: string;\n description?: string;\n links?: { type?: string; label?: string; url: string }[];\n}\n\nexport interface TokenBoost {\n url: string;\n chainId: string;\n tokenAddress: string;\n amount: number;\n totalAmount: number;\n icon?: string;\n description?: string;\n links?: { type?: string; label?: string; url: string }[];\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(path: string): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`);\n if (!res.ok) {\n throw new Error(`DexScreener API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Search for token pairs by name, symbol, or address.\n */\nexport async function searchTokens(query: string): Promise<DexPair[]> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/latest/dex/search?q=${encodeURIComponent(query)}`,\n );\n return data.pairs ?? [];\n}\n\n/**\n * Get all trading pairs for a specific token on a chain.\n */\nexport async function getTokenPairs(chainId: string, tokenAddress: string): Promise<DexPair[]> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/token-pairs/v1/${encodeURIComponent(chainId)}/${encodeURIComponent(tokenAddress)}`,\n );\n return data.pairs ?? [];\n}\n\n/**\n * Get the latest boosted tokens (promoted on DexScreener).\n */\nexport async function getLatestBoostedTokens(): Promise<TokenBoost[]> {\n return fetchJson<TokenBoost[]>('/token-boosts/latest/v1');\n}\n\n/**\n * Get the top boosted tokens by total boost amount.\n */\nexport async function getTopBoostedTokens(): Promise<TokenBoost[]> {\n return fetchJson<TokenBoost[]>('/token-boosts/top/v1');\n}\n\n/**\n * Get the latest token profiles (recently updated tokens with metadata).\n */\nexport async function getLatestTokenProfiles(): Promise<TokenProfile[]> {\n return fetchJson<TokenProfile[]>('/token-profiles/latest/v1');\n}\n\n/**\n * Get a specific pair by chain and pair address.\n */\nexport async function getPair(chainId: string, pairAddress: string): Promise<DexPair | null> {\n const data = await fetchJson<{ pairs: DexPair[] | null }>(\n `/latest/dex/pairs/${encodeURIComponent(chainId)}/${encodeURIComponent(pairAddress)}`,\n );\n return data.pairs?.[0] ?? null;\n}\n","import {\n searchTokens as dexSearch,\n getTopBoostedTokens,\n type DexPair,\n} from '../../data/sources/dexscreener.js';\nimport { getMLClient } from '../../ml/client.js';\n\nexport interface MarketData {\n symbol: string;\n name: string;\n price: number;\n priceChange24h: number;\n priceChange7d: number;\n volume24h: number;\n marketCap: number;\n rank: number | null;\n}\n\nexport interface MarketTrend {\n direction: 'bullish' | 'bearish' | 'neutral';\n strength: number; // 0-100\n signals: string[];\n}\n\nexport interface TrendingToken {\n name: string;\n symbol: string;\n chain: string;\n priceUsd: string;\n priceChange24h: number;\n volume24h: number;\n liquidity: number;\n marketCap: number | null;\n url: string;\n source: 'dexscreener' | 'coingecko';\n}\n\n/**\n * Fetch market data for established coins from CoinGecko.\n */\nexport async function fetchMarketData(symbol: string): Promise<MarketData | null> {\n try {\n const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=${encodeURIComponent(symbol.toLowerCase())}&order=market_cap_desc&per_page=1&page=1&sparkline=false&price_change_percentage=24h,7d`;\n const response = await fetch(url);\n\n if (!response.ok) return null;\n\n const data = (await response.json()) as Record<string, unknown>[];\n if (!data || data.length === 0) return null;\n\n const coin = data[0];\n if (!coin) return null;\n\n return {\n symbol: String(coin['symbol'] ?? '').toUpperCase(),\n name: String(coin['name'] ?? ''),\n price: Number(coin['current_price'] ?? 0),\n priceChange24h: Number(coin['price_change_percentage_24h'] ?? 0),\n priceChange7d: Number(coin['price_change_percentage_7d_in_currency'] ?? 0),\n volume24h: Number(coin['total_volume'] ?? 0),\n marketCap: Number(coin['market_cap'] ?? 0),\n rank: coin['market_cap_rank'] != null ? Number(coin['market_cap_rank']) : null,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Search for any token on DEXes via DexScreener.\n * Works for all tokens — including meme coins and newly launched tokens.\n */\nexport async function fetchTokenFromDex(query: string): Promise<DexPair[]> {\n try {\n return await dexSearch(query);\n } catch {\n return [];\n }\n}\n\n/**\n * Get currently trending/hot tokens from DexScreener (boosted tokens)\n * and CoinGecko trending combined.\n */\nexport async function fetchTrendingTokens(): Promise<TrendingToken[]> {\n const results: TrendingToken[] = [];\n\n // DexScreener: top boosted tokens\n try {\n const boosted = await getTopBoostedTokens();\n // Boosted tokens don't have pair data, so search for the top ones\n const seen = new Set<string>();\n for (const token of boosted.slice(0, 10)) {\n const key = `${token.chainId}:${token.tokenAddress}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n try {\n const pairs = await dexSearch(token.tokenAddress);\n const pair = pairs[0];\n if (pair) {\n results.push(dexPairToTrending(pair));\n }\n } catch {\n // skip individual failures\n }\n }\n } catch {\n // DexScreener unavailable\n }\n\n // CoinGecko: trending coins\n try {\n const response = await fetch('https://api.coingecko.com/api/v3/search/trending');\n if (response.ok) {\n const data = (await response.json()) as {\n coins: { item: { id: string; name: string; symbol: string; market_cap_rank: number } }[];\n };\n for (const { item } of (data.coins ?? []).slice(0, 7)) {\n results.push({\n name: item.name,\n symbol: item.symbol.toUpperCase(),\n chain: 'multi',\n priceUsd: '(see CoinGecko)',\n priceChange24h: 0,\n volume24h: 0,\n liquidity: 0,\n marketCap: null,\n url: `https://www.coingecko.com/en/coins/${item.id}`,\n source: 'coingecko',\n });\n }\n }\n } catch {\n // CoinGecko unavailable\n }\n\n return results;\n}\n\nfunction dexPairToTrending(pair: DexPair): TrendingToken {\n return {\n name: pair.baseToken.name,\n symbol: pair.baseToken.symbol,\n chain: pair.chainId,\n priceUsd: pair.priceUsd ?? '0',\n priceChange24h: pair.priceChange?.h24 ?? 0,\n volume24h: pair.volume?.h24 ?? 0,\n liquidity: pair.liquidity?.usd ?? 0,\n marketCap: pair.marketCap ?? pair.fdv ?? null,\n url: pair.url,\n source: 'dexscreener',\n };\n}\n\n/**\n * ML-enhanced trend analysis. Falls back to rule-based analyzeTrend().\n */\nexport async function analyzeTrendML(data: MarketData): Promise<MarketTrend> {\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const volumeToMcap = data.marketCap > 0 ? data.volume24h / data.marketCap : 0;\n const result = await mlClient.scoreTrend({\n price_change_24h: data.priceChange24h,\n price_change_7d: data.priceChange7d,\n volume_24h: data.volume24h,\n market_cap: data.marketCap,\n volume_to_mcap_ratio: volumeToMcap,\n rank: data.rank ?? 0,\n });\n if (result) {\n const signals: string[] = [`ML trend score: ${result.score}/100 (${result.model})`];\n if (result.feature_importances) {\n const topFeature = Object.entries(result.feature_importances).sort(\n (a, b) => b[1] - a[1],\n )[0];\n if (topFeature) {\n signals.push(`Top driver: ${topFeature[0]}`);\n }\n }\n return {\n direction: result.direction,\n strength: result.score,\n signals,\n };\n }\n } catch {\n // ML unavailable — fallback\n }\n }\n return analyzeTrend(data);\n}\n\nexport function analyzeTrend(data: MarketData): MarketTrend {\n const signals: string[] = [];\n let score = 50;\n\n if (data.priceChange24h > 5) {\n score += 15;\n signals.push(`Strong 24h gain: +${data.priceChange24h.toFixed(2)}%`);\n } else if (data.priceChange24h < -5) {\n score -= 15;\n signals.push(`Significant 24h drop: ${data.priceChange24h.toFixed(2)}%`);\n }\n\n if (data.priceChange7d > 10) {\n score += 20;\n signals.push(`Bullish weekly trend: +${data.priceChange7d.toFixed(2)}%`);\n } else if (data.priceChange7d < -10) {\n score -= 20;\n signals.push(`Bearish weekly trend: ${data.priceChange7d.toFixed(2)}%`);\n }\n\n if (data.volume24h > data.marketCap * 0.1) {\n signals.push('High volume relative to market cap');\n score += 5;\n }\n\n const direction: MarketTrend['direction'] =\n score > 60 ? 'bullish' : score < 40 ? 'bearish' : 'neutral';\n\n return {\n direction,\n strength: Math.max(0, Math.min(100, score)),\n signals,\n };\n}\n","// ---------------------------------------------------------------------------\n// CryptoPanic API client — crypto news with sentiment\n// https://cryptopanic.com/developers/api/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://cryptopanic.com/api/free/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CryptoNews {\n id: number;\n title: string;\n url: string;\n source: { title: string; domain: string };\n sentiment: 'positive' | 'negative' | 'neutral';\n currencies: { code: string; title: string }[];\n publishedAt: string;\n kind: 'news' | 'media';\n}\n\ninterface RawPost {\n id: number;\n title: string;\n url: string;\n source: { title: string; domain: string };\n votes: { positive: number; negative: number; important: number };\n currencies?: { code: string; title: string }[];\n published_at: string;\n kind: string;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch latest crypto news, optionally filtered by currency symbol.\n * If an API token is provided, uses authenticated endpoint for better filtering.\n */\nexport async function fetchCryptoNews(symbol?: string, apiToken?: string): Promise<CryptoNews[]> {\n // CryptoPanic requires auth_token even for free tier.\n // If no token provided, return empty rather than erroring.\n if (!apiToken) {\n return [];\n }\n\n const params = new URLSearchParams({ auth_token: apiToken });\n if (symbol) {\n params.set('currencies', symbol.toUpperCase());\n }\n\n const url = `${BASE_URL}/posts/?${params.toString()}`;\n const res = await fetch(url);\n\n if (!res.ok) {\n return [];\n }\n\n const contentType = res.headers.get('content-type') ?? '';\n if (!contentType.includes('application/json')) {\n return [];\n }\n\n let data: { results: RawPost[] };\n try {\n data = (await res.json()) as { results: RawPost[] };\n } catch {\n return [];\n }\n const posts = data.results ?? [];\n\n return posts.map((post): CryptoNews => {\n // Derive sentiment from vote counts\n const { positive, negative } = post.votes;\n let sentiment: CryptoNews['sentiment'] = 'neutral';\n if (positive > negative * 2) sentiment = 'positive';\n else if (negative > positive * 2) sentiment = 'negative';\n\n return {\n id: post.id,\n title: post.title,\n url: post.url,\n source: post.source,\n sentiment,\n currencies: post.currencies ?? [],\n publishedAt: post.published_at,\n kind: post.kind === 'media' ? 'media' : 'news',\n };\n });\n}\n","// ---------------------------------------------------------------------------\n// Sentiment analysis — aggregates CryptoPanic news + DexScreener buy/sell data\n// ---------------------------------------------------------------------------\n\nimport { fetchCryptoNews } from '../../data/sources/cryptopanic.js';\nimport { searchTokens } from '../../data/sources/dexscreener.js';\nimport { getConfig } from '../../config/loader.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\n\nexport interface SentimentData {\n source: string;\n score: number; // -1 to 1\n volume: number;\n trending: boolean;\n topMentions: string[];\n mlSentiment?: string;\n mlConfidence?: number;\n mlTopics?: string[];\n}\n\nexport interface SentimentSummary {\n overall: number; // -1 to 1\n sources: SentimentData[];\n consensus: 'positive' | 'negative' | 'mixed' | 'neutral';\n}\n\n/**\n * Analyze sentiment for a token/topic by aggregating:\n * 1. CryptoPanic news sentiment\n * 2. DexScreener buy/sell ratio (market sentiment proxy)\n */\nexport async function analyzeSentiment(query: string): Promise<SentimentSummary> {\n const sources: SentimentData[] = [];\n\n // 1. CryptoPanic news sentiment (enhanced with ML NLP when available)\n try {\n let apiToken: string | undefined;\n try {\n apiToken = getConfig().cryptopanicApiKey;\n } catch {\n /* config not loaded */\n }\n const news = await fetchCryptoNews(query, apiToken);\n if (news.length > 0) {\n // Try ML sentiment analysis on headlines\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n let newsScore: number;\n let mlSentiment: string | undefined;\n let mlConfidence: number | undefined;\n let mlTopics: string[] | undefined;\n\n if (mlClient) {\n // Use ML NLP for deeper sentiment analysis\n const headlines = news.slice(0, 10).map((n) => n.title);\n const mlResults = await mlClient.analyzeSentimentBatch(headlines);\n if (mlResults.length > 0) {\n const avgScore = mlResults.reduce((s, r) => s + r.score, 0) / mlResults.length;\n const avgConf = mlResults.reduce((s, r) => s + r.confidence, 0) / mlResults.length;\n const allTopics = [...new Set(mlResults.flatMap((r) => r.key_topics))];\n newsScore = avgScore;\n mlSentiment = avgScore > 0.2 ? 'bullish' : avgScore < -0.2 ? 'bearish' : 'neutral';\n mlConfidence = avgConf;\n mlTopics = allTopics.slice(0, 5);\n } else {\n // Fallback to vote counts\n newsScore = countBasedScore(news);\n }\n } else {\n newsScore = countBasedScore(news);\n }\n\n const total = news.length;\n sources.push({\n source: mlSentiment ? 'ML NLP Sentiment' : 'CryptoPanic News',\n score: newsScore,\n volume: total,\n trending: total > 5,\n topMentions: news.slice(0, 3).map((n) => n.title),\n mlSentiment,\n mlConfidence,\n mlTopics,\n });\n }\n } catch {\n // CryptoPanic unavailable\n }\n\n // 2. DexScreener buy/sell ratio\n try {\n const pairs = await searchTokens(query);\n const topPair = pairs[0];\n if (topPair) {\n const buys24h = topPair.txns?.h24?.buys ?? 0;\n const sells24h = topPair.txns?.h24?.sells ?? 0;\n const totalTxns = buys24h + sells24h;\n\n let dexScore = 0;\n if (totalTxns > 0) {\n // Buy ratio: 0-1, centered at 0.5 → score: -1 to 1\n dexScore = (buys24h / totalTxns - 0.5) * 2;\n }\n\n const priceChange = topPair.priceChange?.h24 ?? 0;\n\n sources.push({\n source: 'DexScreener Market',\n score: dexScore,\n volume: totalTxns,\n trending: topPair.volume?.h24 > 100000,\n topMentions: [\n `${topPair.baseToken.symbol}: $${topPair.priceUsd ?? '?'}`,\n `24h: ${buys24h} buys / ${sells24h} sells`,\n `Price change: ${priceChange > 0 ? '+' : ''}${priceChange.toFixed(2)}%`,\n ],\n });\n }\n } catch {\n // DexScreener unavailable\n }\n\n // Aggregate\n if (sources.length === 0) {\n return { overall: 0, sources: [], consensus: 'neutral' };\n }\n\n const totalScore = sources.reduce((sum, s) => sum + s.score, 0);\n const overall = totalScore / sources.length;\n\n let consensus: SentimentSummary['consensus'] = 'neutral';\n if (overall > 0.2) consensus = 'positive';\n else if (overall < -0.2) consensus = 'negative';\n else if (sources.length > 1 && Math.abs(sources[0]!.score - sources[1]!.score) > 0.5) {\n consensus = 'mixed';\n }\n\n return { overall, sources, consensus };\n}\n\nfunction countBasedScore(news: { sentiment?: string }[]): number {\n let pos = 0;\n let neg = 0;\n for (const article of news) {\n if (article.sentiment === 'positive') pos++;\n else if (article.sentiment === 'negative') neg++;\n }\n const total = news.length;\n return total > 0 ? (pos - neg) / total : 0;\n}\n","// ---------------------------------------------------------------------------\n// Binance public API client — no auth required, 1200 req/min\n// https://binance-docs.github.io/apidocs/spot/en/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.binance.com/api/v3';\nconst FUTURES_URL = 'https://fapi.binance.com/fapi/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TickerPrice {\n symbol: string;\n price: number;\n change24h: number;\n}\n\nexport interface Kline {\n openTime: number;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n closeTime: number;\n quoteVolume: number;\n trades: number;\n}\n\nexport interface OrderBookSummary {\n symbol: string;\n bidPrice: number;\n bidQty: number;\n askPrice: number;\n askQty: number;\n spread: number;\n spreadPct: number;\n}\n\nexport interface FundingRate {\n symbol: string;\n fundingRate: number;\n fundingTime: number;\n markPrice: number;\n}\n\nexport interface OpenInterest {\n symbol: string;\n openInterest: number;\n notionalValue: number;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol mapping: common names -> Binance trading pairs\n// ---------------------------------------------------------------------------\n\nconst SYMBOL_MAP: Record<string, string> = {\n BTC: 'BTCUSDT',\n ETH: 'ETHUSDT',\n SOL: 'SOLUSDT',\n BNB: 'BNBUSDT',\n XRP: 'XRPUSDT',\n ADA: 'ADAUSDT',\n DOGE: 'DOGEUSDT',\n DOT: 'DOTUSDT',\n AVAX: 'AVAXUSDT',\n MATIC: 'MATICUSDT',\n LINK: 'LINKUSDT',\n UNI: 'UNIUSDT',\n ATOM: 'ATOMUSDT',\n NEAR: 'NEARUSDT',\n ARB: 'ARBUSDT',\n OP: 'OPUSDT',\n SUI: 'SUIUSDT',\n APT: 'APTUSDT',\n PEPE: 'PEPEUSDT',\n SHIB: 'SHIBUSDT',\n FLOKI: 'FLOKIUSDT',\n BONK: 'BONKUSDT',\n WIF: 'WIFUSDT',\n};\n\nfunction resolvePair(symbol: string): string {\n const upper = symbol.toUpperCase();\n return SYMBOL_MAP[upper] ?? `${upper}USDT`;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Binance API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n// ---------------------------------------------------------------------------\n// Spot API\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch current price and 24h change for a symbol.\n * Uses Binance 24hr ticker — single request, very reliable.\n */\nexport async function fetchTickerPrice(symbol: string): Promise<TickerPrice> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<{\n symbol: string;\n lastPrice: string;\n priceChangePercent: string;\n }>(`${BASE_URL}/ticker/24hr?symbol=${encodeURIComponent(pair)}`);\n\n return {\n symbol: symbol.toUpperCase(),\n price: parseFloat(data.lastPrice),\n change24h: parseFloat(data.priceChangePercent),\n };\n}\n\n/**\n * Fetch prices for multiple symbols in one request.\n */\nexport async function fetchMultipleTickerPrices(\n symbols: string[],\n): Promise<Map<string, TickerPrice>> {\n const pairs = symbols.map(resolvePair);\n const encoded = encodeURIComponent(JSON.stringify(pairs));\n const data = await fetchJson<{ symbol: string; lastPrice: string; priceChangePercent: string }[]>(\n `${BASE_URL}/ticker/24hr?symbols=${encoded}`,\n );\n\n const result = new Map<string, TickerPrice>();\n for (const item of data) {\n // Reverse lookup from pair to short symbol\n const short =\n Object.entries(SYMBOL_MAP).find(([, v]) => v === item.symbol)?.[0] ??\n item.symbol.replace('USDT', '');\n result.set(short, {\n symbol: short,\n price: parseFloat(item.lastPrice),\n change24h: parseFloat(item.priceChangePercent),\n });\n }\n return result;\n}\n\n/**\n * Fetch kline (candlestick) data.\n * Intervals: 1m, 5m, 15m, 1h, 4h, 1d, 1w\n */\nexport async function fetchKlines(symbol: string, interval: string, limit = 100): Promise<Kline[]> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<(string | number)[][]>(\n `${BASE_URL}/klines?symbol=${encodeURIComponent(pair)}&interval=${interval}&limit=${limit}`,\n );\n\n return data.map((k) => ({\n openTime: Number(k[0]),\n open: parseFloat(String(k[1])),\n high: parseFloat(String(k[2])),\n low: parseFloat(String(k[3])),\n close: parseFloat(String(k[4])),\n volume: parseFloat(String(k[5])),\n closeTime: Number(k[6]),\n quoteVolume: parseFloat(String(k[7])),\n trades: Number(k[8]),\n }));\n}\n\n/**\n * Fetch order book depth summary (best bid/ask + spread).\n */\nexport async function fetchOrderBookSummary(symbol: string): Promise<OrderBookSummary> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<{\n bidPrice: string;\n bidQty: string;\n askPrice: string;\n askQty: string;\n }>(`${BASE_URL}/ticker/bookTicker?symbol=${encodeURIComponent(pair)}`);\n\n const bid = parseFloat(data.bidPrice);\n const ask = parseFloat(data.askPrice);\n\n return {\n symbol: symbol.toUpperCase(),\n bidPrice: bid,\n bidQty: parseFloat(data.bidQty),\n askPrice: ask,\n askQty: parseFloat(data.askQty),\n spread: ask - bid,\n spreadPct: bid > 0 ? ((ask - bid) / bid) * 100 : 0,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Futures API (public, no auth for read-only)\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch current funding rate for a futures symbol.\n */\nexport async function fetchFundingRate(symbol: string): Promise<FundingRate> {\n const pair = resolvePair(symbol);\n const data = await fetchJson<\n { symbol: string; fundingRate: string; fundingTime: number; markPrice: string }[]\n >(`${FUTURES_URL}/premiumIndex?symbol=${encodeURIComponent(pair)}`);\n\n const item = data[0];\n if (!item) throw new Error(`No funding data for ${pair}`);\n\n return {\n symbol: symbol.toUpperCase(),\n fundingRate: parseFloat(item.fundingRate),\n fundingTime: item.fundingTime,\n markPrice: parseFloat(item.markPrice),\n };\n}\n\n/**\n * Fetch open interest for a futures symbol.\n */\nexport async function fetchOpenInterest(symbol: string): Promise<OpenInterest> {\n const pair = resolvePair(symbol);\n const [oiData, tickerData] = await Promise.all([\n fetchJson<{ symbol: string; openInterest: string }>(\n `${FUTURES_URL}/openInterest?symbol=${encodeURIComponent(pair)}`,\n ),\n fetchJson<{ symbol: string; lastPrice: string }>(\n `${FUTURES_URL}/ticker/price?symbol=${encodeURIComponent(pair)}`,\n ),\n ]);\n\n const oi = parseFloat(oiData.openInterest);\n const price = parseFloat(tickerData.lastPrice);\n\n return {\n symbol: symbol.toUpperCase(),\n openInterest: oi,\n notionalValue: oi * price,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Market overview\n// ---------------------------------------------------------------------------\n\nexport interface Ticker24hr {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n quoteVolume: number;\n highPrice: number;\n lowPrice: number;\n}\n\n/**\n * Fetch all USDT pairs sorted by 24h price change percentage.\n * Returns the top N gainers and top N losers.\n */\nexport async function fetchTopGainersLosers(limit = 10): Promise<{\n gainers: Ticker24hr[];\n losers: Ticker24hr[];\n}> {\n const data = await fetchJson<\n {\n symbol: string;\n lastPrice: string;\n priceChangePercent: string;\n volume: string;\n quoteVolume: string;\n highPrice: string;\n lowPrice: string;\n }[]\n >(`${BASE_URL}/ticker/24hr`);\n\n const usdtPairs = data\n .filter((t) => t.symbol.endsWith('USDT') && !t.symbol.includes('_'))\n .map((t) => ({\n symbol: t.symbol.replace('USDT', ''),\n price: parseFloat(t.lastPrice),\n change24h: parseFloat(t.priceChangePercent),\n volume: parseFloat(t.volume),\n quoteVolume: parseFloat(t.quoteVolume),\n highPrice: parseFloat(t.highPrice),\n lowPrice: parseFloat(t.lowPrice),\n }))\n .filter((t) => t.quoteVolume > 100_000); // filter dust pairs\n\n const sorted = [...usdtPairs].sort((a, b) => b.change24h - a.change24h);\n return {\n gainers: sorted.slice(0, limit),\n losers: sorted.slice(-limit).reverse(),\n };\n}\n\n/**\n * Fetch ticker price with real-time WebSocket cache fallback.\n * Checks the WS price cache first, falls back to REST.\n */\nexport async function fetchTickerPriceRT(symbol: string): Promise<TickerPrice> {\n // Try WebSocket cache first\n const { getWSManager } = await import('./ws-manager.js');\n const wsManager = getWSManager();\n if (wsManager) {\n const wsPrice = wsManager.getLatestPrice(symbol);\n if (wsPrice !== null) {\n return {\n symbol: symbol.toUpperCase(),\n price: wsPrice,\n change24h: 0, // WS cache doesn't track 24h change\n };\n }\n }\n // Fallback to REST\n return fetchTickerPrice(symbol);\n}\n\n/**\n * Check if a symbol exists on Binance.\n */\nexport async function isValidSymbol(symbol: string): Promise<boolean> {\n try {\n const pair = resolvePair(symbol);\n await fetchJson(`${BASE_URL}/ticker/price?symbol=${encodeURIComponent(pair)}`);\n return true;\n } catch {\n return false;\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n// ---------------------------------------------------------------------------\n// Pure math indicators — no API calls, no side effects\n// Array indexing uses non-null assertions after bounds checks for performance.\n// ---------------------------------------------------------------------------\n\n/**\n * Calculate RSI (Relative Strength Index).\n * RSI = 100 - (100 / (1 + avgGain / avgLoss))\n */\nexport function calculateRSI(closes: number[], period = 14): number | null {\n if (closes.length < period + 1) return null;\n\n let avgGain = 0;\n let avgLoss = 0;\n\n // Initial averages\n for (let i = 1; i <= period; i++) {\n const change = closes[i]! - closes[i - 1]!;\n if (change > 0) avgGain += change;\n else avgLoss += Math.abs(change);\n }\n avgGain /= period;\n avgLoss /= period;\n\n // Smooth with Wilder's method\n for (let i = period + 1; i < closes.length; i++) {\n const change = closes[i]! - closes[i - 1]!;\n if (change > 0) {\n avgGain = (avgGain * (period - 1) + change) / period;\n avgLoss = (avgLoss * (period - 1)) / period;\n } else {\n avgGain = (avgGain * (period - 1)) / period;\n avgLoss = (avgLoss * (period - 1) + Math.abs(change)) / period;\n }\n }\n\n if (avgLoss === 0) return 100;\n const rs = avgGain / avgLoss;\n return 100 - 100 / (1 + rs);\n}\n\n/**\n * Calculate Exponential Moving Average.\n */\nexport function calculateEMA(values: number[], period: number): number[] {\n if (values.length < period) return [];\n\n const multiplier = 2 / (period + 1);\n const ema: number[] = [];\n\n // SMA for the first value\n let sum = 0;\n for (let i = 0; i < period; i++) {\n sum += values[i]!;\n }\n ema.push(sum / period);\n\n // EMA for subsequent values\n for (let i = period; i < values.length; i++) {\n const prev = ema[ema.length - 1]!;\n ema.push((values[i]! - prev) * multiplier + prev);\n }\n\n return ema;\n}\n\n/**\n * Calculate Simple Moving Average.\n */\nexport function calculateSMA(values: number[], period: number): number[] {\n if (values.length < period) return [];\n\n const sma: number[] = [];\n let sum = 0;\n\n for (let i = 0; i < period; i++) {\n sum += values[i]!;\n }\n sma.push(sum / period);\n\n for (let i = period; i < values.length; i++) {\n sum = sum - values[i - period]! + values[i]!;\n sma.push(sum / period);\n }\n\n return sma;\n}\n\n/**\n * Calculate MACD (Moving Average Convergence Divergence).\n * Returns { macd, signal, histogram } for the latest value.\n */\nexport function calculateMACD(\n closes: number[],\n fastPeriod = 12,\n slowPeriod = 26,\n signalPeriod = 9,\n): { macd: number; signal: number; histogram: number } | null {\n if (closes.length < slowPeriod + signalPeriod) return null;\n\n const fastEMA = calculateEMA(closes, fastPeriod);\n const slowEMA = calculateEMA(closes, slowPeriod);\n\n // Align EMAs — fast EMA starts at index (fastPeriod-1), slow at (slowPeriod-1)\n const offset = slowPeriod - fastPeriod;\n const macdLine: number[] = [];\n for (let i = 0; i < slowEMA.length; i++) {\n macdLine.push(fastEMA[i + offset]! - slowEMA[i]!);\n }\n\n if (macdLine.length < signalPeriod) return null;\n\n const signalLine = calculateEMA(macdLine, signalPeriod);\n const lastMacd = macdLine[macdLine.length - 1]!;\n const lastSignal = signalLine[signalLine.length - 1]!;\n\n return {\n macd: lastMacd,\n signal: lastSignal,\n histogram: lastMacd - lastSignal,\n };\n}\n\n/**\n * Calculate Bollinger Bands.\n * Returns { upper, middle, lower, percentB } for the latest value.\n */\nexport function calculateBollingerBands(\n closes: number[],\n period = 20,\n stdDevMultiplier = 2,\n): { upper: number; middle: number; lower: number; percentB: number } | null {\n if (closes.length < period) return null;\n\n const slice = closes.slice(-period);\n const middle = slice.reduce((a, b) => a + b, 0) / period;\n\n const variance = slice.reduce((sum, val) => sum + (val - middle) ** 2, 0) / period;\n const stdDev = Math.sqrt(variance);\n\n const upper = middle + stdDevMultiplier * stdDev;\n const lower = middle - stdDevMultiplier * stdDev;\n const current = closes[closes.length - 1]!;\n const percentB = upper !== lower ? (current - lower) / (upper - lower) : 0.5;\n\n return { upper, middle, lower, percentB };\n}\n\n/**\n * Calculate Average True Range (ATR).\n */\nexport function calculateATR(\n highs: number[],\n lows: number[],\n closes: number[],\n period = 14,\n): number | null {\n const len = Math.min(highs.length, lows.length, closes.length);\n if (len < period + 1) return null;\n\n const trueRanges: number[] = [];\n for (let i = 1; i < len; i++) {\n const tr = Math.max(\n highs[i]! - lows[i]!,\n Math.abs(highs[i]! - closes[i - 1]!),\n Math.abs(lows[i]! - closes[i - 1]!),\n );\n trueRanges.push(tr);\n }\n\n if (trueRanges.length < period) return null;\n\n // Initial ATR is simple average\n let atr = 0;\n for (let i = 0; i < period; i++) {\n atr += trueRanges[i]!;\n }\n atr /= period;\n\n // Smooth with Wilder's method\n for (let i = period; i < trueRanges.length; i++) {\n atr = (atr * (period - 1) + trueRanges[i]!) / period;\n }\n\n return atr;\n}\n\n/**\n * Calculate On-Balance Volume (OBV).\n * Returns the final OBV value.\n */\nexport function calculateOBV(closes: number[], volumes: number[]): number | null {\n const len = Math.min(closes.length, volumes.length);\n if (len < 2) return null;\n\n let obv = 0;\n for (let i = 1; i < len; i++) {\n if (closes[i]! > closes[i - 1]!) {\n obv += volumes[i]!;\n } else if (closes[i]! < closes[i - 1]!) {\n obv -= volumes[i]!;\n }\n // if equal, obv stays the same\n }\n\n return obv;\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n// ---------------------------------------------------------------------------\n// Technical analysis analyzer — runs all indicators on kline data\n// ---------------------------------------------------------------------------\n\nimport { fetchKlines } from '../../data/sources/binance.js';\nimport type { TechnicalAnalysis, TechnicalSignal, SignalDirection } from './types.js';\nimport {\n calculateRSI,\n calculateEMA,\n calculateSMA,\n calculateMACD,\n calculateBollingerBands,\n calculateATR,\n calculateOBV,\n} from './indicators.js';\nimport { getMLClient } from '../../ml/client.js';\n\n/**\n * Run full technical analysis on a symbol using Binance kline data.\n */\nexport async function analyzeTechnicals(\n symbol: string,\n timeframe = '4h',\n): Promise<TechnicalAnalysis> {\n const klines = await fetchKlines(symbol, timeframe, 100);\n\n const closes = klines.map((k) => k.close);\n const highs = klines.map((k) => k.high);\n const lows = klines.map((k) => k.low);\n const volumes = klines.map((k) => k.volume);\n\n const signals: TechnicalSignal[] = [];\n\n // RSI\n const rsi = calculateRSI(closes);\n if (rsi !== null) {\n signals.push(interpretRSI(rsi));\n }\n\n // MACD\n const macd = calculateMACD(closes);\n if (macd !== null) {\n signals.push(interpretMACD(macd));\n }\n\n // Bollinger Bands\n const bb = calculateBollingerBands(closes);\n if (bb !== null) {\n signals.push(interpretBollinger(bb, closes[closes.length - 1]!));\n }\n\n // EMA crossover\n const ema12 = calculateEMA(closes, 12);\n const ema26 = calculateEMA(closes, 26);\n if (ema12.length > 0 && ema26.length > 0) {\n signals.push(interpretEMACrossover(ema12[ema12.length - 1]!, ema26[ema26.length - 1]!));\n }\n\n // ATR\n const atr = calculateATR(highs, lows, closes);\n if (atr !== null) {\n const currentPrice = closes[closes.length - 1]!;\n signals.push(interpretATR(atr, currentPrice));\n }\n\n // OBV\n const obv = calculateOBV(closes, volumes);\n if (obv !== null) {\n // Compare OBV direction with price direction\n const priceChange =\n closes.length >= 2 ? closes[closes.length - 1]! - closes[closes.length - 2]! : 0;\n signals.push(interpretOBV(obv, priceChange));\n }\n\n // SMA\n const sma20 = calculateSMA(closes, 20);\n\n const currentPrice = closes[closes.length - 1]!;\n const prevPrice = closes.length >= 2 ? closes[closes.length - 2]! : currentPrice;\n const priceChange = currentPrice - prevPrice;\n const ema12Val = ema12.length > 0 ? ema12[ema12.length - 1]! : 0;\n const ema26Val = ema26.length > 0 ? ema26[ema26.length - 1]! : 0;\n const emaCrossPct = ema26Val !== 0 ? ((ema12Val - ema26Val) / ema26Val) * 100 : 0;\n const atrPct = atr !== null && currentPrice > 0 ? (atr / currentPrice) * 100 : 0;\n const bbBandwidth = bb !== null && bb.middle > 0 ? ((bb.upper - bb.lower) / bb.middle) * 100 : 0;\n\n // ML: try ML TA interpreter for signals + weights + composite\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const mlResult = await mlClient.interpretTA({\n rsi: rsi ?? 50,\n macd_histogram: macd?.histogram ?? 0,\n macd_line: macd?.macd ?? 0,\n macd_signal: macd?.signal ?? 0,\n bb_percent_b: bb?.percentB ?? 0.5,\n bb_bandwidth: bbBandwidth,\n ema12: ema12Val,\n ema26: ema26Val,\n ema_cross_pct: emaCrossPct,\n atr: atr ?? 0,\n atr_pct: atrPct,\n obv: obv ?? 0,\n price_change: priceChange,\n });\n if (mlResult) {\n // Map ML signals to TechnicalSignal format\n const mlSignals: TechnicalSignal[] = mlResult.signals.map((s) => ({\n name: s.name,\n value: 0,\n signal: s.direction as SignalDirection,\n strength: s.strength,\n description: s.description,\n }));\n\n return {\n symbol: symbol.toUpperCase(),\n timeframe,\n signals: mlSignals,\n composite: {\n direction: mlResult.composite.direction as SignalDirection,\n score: mlResult.composite.score,\n confidence: mlResult.composite.confidence,\n },\n indicators: {\n rsi: rsi,\n macd: macd,\n bollingerBands: bb,\n ema12: ema12Val || null,\n ema26: ema26Val || null,\n sma20: sma20.length > 0 ? sma20[sma20.length - 1]! : null,\n atr: atr,\n obv: obv,\n },\n timestamp: Date.now(),\n };\n }\n } catch {\n // ML unavailable — fall through to rule-based\n }\n }\n\n // Composite score: weighted average of signal strengths\n const composite = calculateComposite(signals);\n\n return {\n symbol: symbol.toUpperCase(),\n timeframe,\n signals,\n composite,\n indicators: {\n rsi: rsi,\n macd: macd,\n bollingerBands: bb,\n ema12: ema12Val || null,\n ema26: ema26Val || null,\n sma20: sma20.length > 0 ? sma20[sma20.length - 1]! : null,\n atr: atr,\n obv: obv,\n },\n timestamp: Date.now(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signal interpretation\n// ---------------------------------------------------------------------------\n\nconst WEIGHTS: Record<string, number> = {\n RSI: 20,\n MACD: 20,\n 'Bollinger Bands': 15,\n 'EMA Crossover': 20,\n ATR: 10,\n OBV: 15,\n};\n\nfunction interpretRSI(rsi: number): TechnicalSignal {\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (rsi > 70) {\n signal = 'bearish';\n strength = Math.min(100, 50 + (rsi - 70) * 1.5);\n description = `RSI ${rsi.toFixed(1)} — overbought territory, potential pullback`;\n } else if (rsi < 30) {\n signal = 'bullish';\n strength = Math.min(100, 50 + (30 - rsi) * 1.5);\n description = `RSI ${rsi.toFixed(1)} — oversold territory, potential bounce`;\n } else if (rsi > 60) {\n signal = 'bullish';\n strength = 40 + (rsi - 60);\n description = `RSI ${rsi.toFixed(1)} — bullish momentum`;\n } else if (rsi < 40) {\n signal = 'bearish';\n strength = 40 + (40 - rsi);\n description = `RSI ${rsi.toFixed(1)} — bearish momentum`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = `RSI ${rsi.toFixed(1)} — neutral zone`;\n }\n\n return { name: 'RSI', value: rsi, signal, strength, description };\n}\n\nfunction interpretMACD(macd: { macd: number; signal: number; histogram: number }): TechnicalSignal {\n const { histogram } = macd;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (histogram > 0) {\n signal = 'bullish';\n strength = Math.min(90, 50 + Math.abs(histogram) * 100);\n description = `MACD histogram positive (${histogram.toFixed(4)}) — bullish momentum`;\n } else if (histogram < 0) {\n signal = 'bearish';\n strength = Math.min(90, 50 + Math.abs(histogram) * 100);\n description = `MACD histogram negative (${histogram.toFixed(4)}) — bearish momentum`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'MACD at signal line — no clear direction';\n }\n\n // Crossover detection\n if (macd.macd > macd.signal && histogram > 0 && histogram < 0.001) {\n description += ' (fresh bullish crossover)';\n strength = Math.min(100, strength + 20);\n } else if (macd.macd < macd.signal && histogram < 0 && histogram > -0.001) {\n description += ' (fresh bearish crossover)';\n strength = Math.min(100, strength + 20);\n }\n\n return { name: 'MACD', value: histogram, signal, strength, description };\n}\n\nfunction interpretBollinger(\n bb: { upper: number; middle: number; lower: number; percentB: number },\n price: number,\n): TechnicalSignal {\n const { percentB } = bb;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (percentB > 1) {\n signal = 'bullish';\n strength = 70;\n description = `Price above upper Bollinger Band (%B: ${percentB.toFixed(2)}) — strong breakout`;\n } else if (percentB > 0.8) {\n signal = 'bearish';\n strength = 55;\n description = `Price near upper band (%B: ${percentB.toFixed(2)}) — extended, potential pullback`;\n } else if (percentB < 0) {\n signal = 'bearish';\n strength = 70;\n description = `Price below lower Bollinger Band (%B: ${percentB.toFixed(2)}) — breakdown`;\n } else if (percentB < 0.2) {\n signal = 'bullish';\n strength = 55;\n description = `Price near lower band (%B: ${percentB.toFixed(2)}) — compressed, potential bounce`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = `Price within bands (%B: ${percentB.toFixed(2)}) at $${price.toLocaleString()}`;\n }\n\n return { name: 'Bollinger Bands', value: percentB, signal, strength, description };\n}\n\nfunction interpretEMACrossover(ema12: number, ema26: number): TechnicalSignal {\n const diff = ema12 - ema26;\n const pctDiff = ema26 !== 0 ? (diff / ema26) * 100 : 0;\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (diff > 0) {\n signal = 'bullish';\n strength = Math.min(90, 50 + Math.abs(pctDiff) * 10);\n description = `EMA(12) above EMA(26) by ${pctDiff.toFixed(2)}% — bullish trend`;\n } else if (diff < 0) {\n signal = 'bearish';\n strength = Math.min(90, 50 + Math.abs(pctDiff) * 10);\n description = `EMA(12) below EMA(26) by ${Math.abs(pctDiff).toFixed(2)}% — bearish trend`;\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'EMA(12) = EMA(26) — no trend';\n }\n\n return { name: 'EMA Crossover', value: pctDiff, signal, strength, description };\n}\n\nfunction interpretATR(atr: number, price: number): TechnicalSignal {\n const atrPct = price > 0 ? (atr / price) * 100 : 0;\n let description: string;\n\n if (atrPct > 5) {\n description = `ATR ${atrPct.toFixed(2)}% of price — high volatility, breakout conditions`;\n } else if (atrPct > 2) {\n description = `ATR ${atrPct.toFixed(2)}% of price — moderate volatility`;\n } else {\n description = `ATR ${atrPct.toFixed(2)}% of price — low volatility, consolidation`;\n }\n\n return { name: 'ATR', value: atr, signal: 'neutral', strength: 40, description };\n}\n\nfunction interpretOBV(obv: number, priceChange: number): TechnicalSignal {\n let signal: SignalDirection;\n let strength: number;\n let description: string;\n\n if (obv > 0 && priceChange > 0) {\n signal = 'bullish';\n strength = 65;\n description = 'OBV positive with rising price — confirmed uptrend';\n } else if (obv > 0 && priceChange <= 0) {\n signal = 'bullish';\n strength = 70;\n description = 'OBV positive but price flat/down — accumulation (bullish divergence)';\n } else if (obv < 0 && priceChange < 0) {\n signal = 'bearish';\n strength = 65;\n description = 'OBV negative with falling price — confirmed downtrend';\n } else if (obv < 0 && priceChange >= 0) {\n signal = 'bearish';\n strength = 70;\n description = 'OBV negative but price flat/up — distribution (bearish divergence)';\n } else {\n signal = 'neutral';\n strength = 30;\n description = 'OBV neutral';\n }\n\n return { name: 'OBV', value: obv, signal, strength, description };\n}\n\nfunction calculateComposite(signals: TechnicalSignal[]): {\n direction: SignalDirection;\n score: number;\n confidence: number;\n} {\n if (signals.length === 0) {\n return { direction: 'neutral', score: 0, confidence: 0 };\n }\n\n let totalWeight = 0;\n let weightedScore = 0;\n\n for (const sig of signals) {\n const weight = WEIGHTS[sig.name] ?? 10;\n totalWeight += weight;\n\n const dirScore =\n sig.signal === 'bullish' ? sig.strength : sig.signal === 'bearish' ? -sig.strength : 0;\n weightedScore += dirScore * weight;\n }\n\n const score = totalWeight > 0 ? weightedScore / totalWeight : 0;\n\n // Confidence based on signal agreement\n const bullishCount = signals.filter((s) => s.signal === 'bullish').length;\n const bearishCount = signals.filter((s) => s.signal === 'bearish').length;\n const totalDirectional = bullishCount + bearishCount;\n const agreement =\n totalDirectional > 0 ? Math.max(bullishCount, bearishCount) / totalDirectional : 0;\n const confidence = Math.round(agreement * 100 * (signals.length / 6)); // scale by completeness\n\n const direction: SignalDirection = score > 15 ? 'bullish' : score < -15 ? 'bearish' : 'neutral';\n\n return {\n direction,\n score: Math.round(score),\n confidence: Math.min(100, confidence),\n };\n}\n","export { analyzeTechnicals } from './analyzer.js';\nexport {\n calculateRSI,\n calculateEMA,\n calculateSMA,\n calculateMACD,\n calculateBollingerBands,\n calculateATR,\n calculateOBV,\n} from './indicators.js';\nexport type { TechnicalAnalysis, TechnicalSignal, SignalDirection } from './types.js';\n","// ---------------------------------------------------------------------------\n// Fear & Greed Index — alternative.me API, no auth required\n// https://alternative.me/crypto/fear-and-greed-index/\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.alternative.me/fng';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FearGreedEntry {\n value: number;\n classification: 'Extreme Fear' | 'Fear' | 'Neutral' | 'Greed' | 'Extreme Greed';\n timestamp: number;\n}\n\nexport interface FearGreedData {\n current: FearGreedEntry;\n previous: FearGreedEntry | null;\n history: FearGreedEntry[];\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Fear & Greed API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\nfunction parseClassification(value: number): FearGreedEntry['classification'] {\n if (value <= 20) return 'Extreme Fear';\n if (value <= 40) return 'Fear';\n if (value <= 60) return 'Neutral';\n if (value <= 80) return 'Greed';\n return 'Extreme Greed';\n}\n\n/**\n * Fetch the current Fear & Greed Index along with recent history.\n */\nexport async function fetchFearGreedIndex(days = 7): Promise<FearGreedData> {\n const data = await fetchJson<{\n data: { value: string; value_classification: string; timestamp: string }[];\n }>(`${BASE_URL}/?limit=${days}&format=json`);\n\n const entries: FearGreedEntry[] = (data.data ?? []).map((d) => {\n const value = parseInt(d.value, 10);\n return {\n value,\n classification: parseClassification(value),\n timestamp: parseInt(d.timestamp, 10),\n };\n });\n\n return {\n current: entries[0] ?? { value: 50, classification: 'Neutral', timestamp: Date.now() / 1000 },\n previous: entries[1] ?? null,\n history: entries,\n };\n}\n","// ---------------------------------------------------------------------------\n// Feature Engineering — transforms TA + agent signals into ML feature vectors\n// ---------------------------------------------------------------------------\n\nimport { analyzeTechnicals } from '../core/technical-analysis/index.js';\nimport { fetchFundingRate, fetchTickerPrice, fetchKlines } from '../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { calculateRSI } from '../core/technical-analysis/indicators.js';\nimport type { FeatureVector } from './types.js';\n\nexport async function buildFeatureVector(symbol: string): Promise<FeatureVector> {\n // Gather all data in parallel\n const [ta, fundingResult, tickerResult, fgResult, klines] = await Promise.allSettled([\n analyzeTechnicals(symbol, '4h'),\n fetchFundingRate(symbol),\n fetchTickerPrice(symbol),\n fetchFearGreedIndex(1),\n fetchKlines(symbol, '4h', 100),\n ]);\n\n const indicators = ta.status === 'fulfilled' ? ta.value.indicators : null;\n const funding = fundingResult.status === 'fulfilled' ? fundingResult.value : null;\n const ticker = tickerResult.status === 'fulfilled' ? tickerResult.value : null;\n const fg = fgResult.status === 'fulfilled' ? fgResult.value : null;\n const candles = klines.status === 'fulfilled' ? klines.value : [];\n\n // RSI slope: rate of change over last 3 periods\n let rsiSlope = 0;\n if (candles.length >= 17) {\n const closes = candles.map((k) => k.close);\n const recentRsi = calculateRSI(closes, 14);\n const olderCloses = closes.slice(0, -3);\n const olderRsi = calculateRSI(olderCloses, 14);\n if (recentRsi !== null && olderRsi !== null) {\n rsiSlope = recentRsi - olderRsi;\n }\n }\n\n // Volume ratio: current / 20-period avg\n let volumeRatio = 1;\n if (candles.length >= 21) {\n const currentVolume = candles[candles.length - 1].volume;\n const avgVolume = candles.slice(-21, -1).reduce((sum, k) => sum + k.volume, 0) / 20;\n volumeRatio = avgVolume > 0 ? currentVolume / avgVolume : 1;\n }\n\n // EMA crossover %\n const price = ticker?.price ?? candles[candles.length - 1]?.close ?? 0;\n const ema12 = indicators?.ema12 ?? 0;\n const ema26 = indicators?.ema26 ?? 0;\n const emaCrossoverPct = price > 0 ? ((ema12 - ema26) / price) * 100 : 0;\n\n // ATR as % of price\n const atr = indicators?.atr ?? 0;\n const atrPct = price > 0 ? (atr / price) * 100 : 0;\n\n return {\n rsi: indicators?.rsi ?? 50,\n macdHistogram: indicators?.macd?.histogram ?? 0,\n bollingerPercentB: indicators?.bollingerBands?.percentB ?? 0.5,\n ema12,\n ema26,\n atr,\n obv: indicators?.obv ?? 0,\n fundingRate: funding?.fundingRate ?? 0,\n fearGreed: fg?.current.value ?? 50,\n priceChange24h: ticker?.change24h ?? 0,\n rsiSlope,\n volumeRatio,\n emaCrossoverPct,\n atrPct,\n symbol: symbol.toUpperCase(),\n timestamp: Date.now(),\n };\n}\n","// ---------------------------------------------------------------------------\n// Multi-signal prediction engine\n// ---------------------------------------------------------------------------\n\nimport { analyzeTechnicals } from '../technical-analysis/index.js';\nimport { analyzeSentiment } from './sentiment.js';\nimport { fetchFearGreedIndex } from '../../data/sources/fear-greed.js';\nimport {\n fetchFundingRate,\n fetchOpenInterest,\n fetchTickerPrice,\n} from '../../data/sources/binance.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { buildFeatureVector } from '../../ml/feature-engineer.js';\nimport type { MLPredictionResult } from '../../ml/types.js';\nimport { getConfig } from '../../config/loader.js';\n\nexport interface Prediction {\n symbol: string;\n direction: 'up' | 'down' | 'sideways';\n confidence: number; // 0-100\n timeframe: string;\n reasoning: string[];\n signals: {\n technical: number; // -100 to +100\n sentiment: number;\n derivatives: number;\n trend: number;\n macro: number;\n };\n composite: number; // -100 to +100\n disclaimer: string;\n}\n\n// Signal weights (must sum to 100)\nconst WEIGHTS = {\n technical: 40,\n sentiment: 20,\n derivatives: 20,\n trend: 15,\n macro: 5,\n};\n\n/**\n * Generate a multi-signal composite prediction for a symbol.\n * Gathers: technical analysis + sentiment + derivatives + Fear & Greed + price trend.\n */\nexport async function generatePrediction(symbol: string): Promise<Prediction> {\n const reasoning: string[] = [];\n const signals = { technical: 0, sentiment: 0, derivatives: 0, trend: 0, macro: 0 };\n let completeness = 0;\n\n // 1. Technical Analysis (weight: 40%)\n try {\n const ta = await analyzeTechnicals(symbol, '4h');\n signals.technical = ta.composite.score;\n completeness++;\n reasoning.push(\n `Technical: ${ta.composite.direction} (score ${ta.composite.score}, confidence ${ta.composite.confidence}%)`,\n );\n for (const sig of ta.signals.slice(0, 3)) {\n reasoning.push(` - ${sig.description}`);\n }\n } catch {\n reasoning.push('Technical: unavailable');\n }\n\n // 2. Sentiment (weight: 20%)\n try {\n const sentiment = await analyzeSentiment(symbol);\n // Normalize -1 to +1 → -100 to +100\n signals.sentiment = Math.round(sentiment.overall * 100);\n completeness++;\n reasoning.push(`Sentiment: ${sentiment.consensus} (score ${signals.sentiment})`);\n } catch {\n reasoning.push('Sentiment: unavailable');\n }\n\n // 3. Derivatives (weight: 20%)\n try {\n const [fundingResult, oiResult] = await Promise.allSettled([\n fetchFundingRate(symbol),\n fetchOpenInterest(symbol),\n ]);\n\n let derivativeScore = 0;\n if (fundingResult.status === 'fulfilled') {\n const rate = fundingResult.value.fundingRate;\n // Positive funding = longs paying → slightly bullish consensus\n // Extreme positive = overleveraged longs → bearish signal\n if (rate > 0.0005) {\n derivativeScore -= 30; // Overleveraged longs\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (overleveraged longs — correction risk)`,\n );\n } else if (rate > 0) {\n derivativeScore += 20;\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (moderate bullish positioning)`,\n );\n } else if (rate < -0.0003) {\n derivativeScore += 30; // Capitulation\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (capitulation — bounce candidate)`,\n );\n } else {\n derivativeScore -= 20;\n reasoning.push(\n `Derivatives: funding rate ${(rate * 100).toFixed(4)}% (bearish positioning)`,\n );\n }\n }\n\n if (oiResult.status === 'fulfilled') {\n const notional = oiResult.value.notionalValue;\n reasoning.push(` OI: $${(notional / 1e9).toFixed(2)}B notional`);\n }\n\n signals.derivatives = Math.max(-100, Math.min(100, derivativeScore));\n completeness++;\n } catch {\n reasoning.push('Derivatives: unavailable');\n }\n\n // 4. Price trend (weight: 15%)\n try {\n const price = await fetchTickerPrice(symbol);\n if (price.change24h > 5) {\n signals.trend = 60;\n reasoning.push(`Trend: strong 24h gain +${price.change24h.toFixed(1)}%`);\n } else if (price.change24h > 0) {\n signals.trend = 30;\n reasoning.push(`Trend: positive 24h +${price.change24h.toFixed(1)}%`);\n } else if (price.change24h < -5) {\n signals.trend = -60;\n reasoning.push(`Trend: strong 24h drop ${price.change24h.toFixed(1)}%`);\n } else {\n signals.trend = -30;\n reasoning.push(`Trend: negative 24h ${price.change24h.toFixed(1)}%`);\n }\n completeness++;\n } catch {\n reasoning.push('Trend: unavailable');\n }\n\n // 5. Macro — Fear & Greed (weight: 5%)\n try {\n const fg = await fetchFearGreedIndex(1);\n const value = fg.current.value;\n // Contrarian: extreme greed = bearish, extreme fear = bullish\n if (value > 80) {\n signals.macro = -40;\n reasoning.push(`Macro: Extreme Greed (${value}) — contrarian bearish`);\n } else if (value > 60) {\n signals.macro = 20;\n reasoning.push(`Macro: Greed (${value}) — bullish sentiment`);\n } else if (value < 20) {\n signals.macro = 40;\n reasoning.push(`Macro: Extreme Fear (${value}) — contrarian bullish`);\n } else if (value < 40) {\n signals.macro = -20;\n reasoning.push(`Macro: Fear (${value}) — bearish sentiment`);\n } else {\n signals.macro = 0;\n reasoning.push(`Macro: Neutral (${value})`);\n }\n completeness++;\n } catch {\n reasoning.push('Macro: unavailable');\n }\n\n // Composite weighted score\n const composite =\n (signals.technical * WEIGHTS.technical +\n signals.sentiment * WEIGHTS.sentiment +\n signals.derivatives * WEIGHTS.derivatives +\n signals.trend * WEIGHTS.trend +\n signals.macro * WEIGHTS.macro) /\n 100;\n\n // Direction\n const direction: Prediction['direction'] =\n composite > 15 ? 'up' : composite < -15 ? 'down' : 'sideways';\n\n // Confidence from signal completeness and agreement\n const signalValues = [\n signals.technical,\n signals.sentiment,\n signals.derivatives,\n signals.trend,\n signals.macro,\n ];\n const positiveCount = signalValues.filter((v) => v > 0).length;\n const negativeCount = signalValues.filter((v) => v < 0).length;\n const agreement =\n Math.max(positiveCount, negativeCount) / Math.max(1, positiveCount + negativeCount);\n const confidence = Math.round(Math.min(95, (completeness / 5) * agreement * 100));\n\n const rulePrediction: Prediction = {\n symbol: symbol.toUpperCase(),\n direction,\n confidence,\n timeframe: '7 days',\n reasoning,\n signals,\n composite: Math.round(composite),\n disclaimer:\n 'This is not financial advice. Predictions are based on historical data and AI analysis. Always do your own research.',\n };\n\n // ML enhancement: if sidecar is available, merge ML prediction\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n // Config not loaded yet — skip ML\n }\n }\n if (mlClient) {\n try {\n const features = await buildFeatureVector(symbol);\n const mlPred = await mlClient.predict(features);\n if (mlPred) {\n return mergePredictions(rulePrediction, mlPred);\n }\n } catch {\n // Fall through to rule-based prediction\n }\n }\n\n return rulePrediction;\n}\n\nfunction mergePredictions(rule: Prediction, ml: MLPredictionResult): Prediction {\n // Weight: 40% rule-based, 60% ML when both available\n const mlComposite =\n ml.direction === 'up'\n ? ml.probability * 100\n : ml.direction === 'down'\n ? -(ml.probability * 100)\n : 0;\n\n const mergedComposite = Math.round(rule.composite * 0.4 + mlComposite * 0.6);\n const mergedDirection: Prediction['direction'] =\n mergedComposite > 15 ? 'up' : mergedComposite < -15 ? 'down' : 'sideways';\n\n const mergedConfidence = Math.round(Math.min(95, rule.confidence * 0.4 + ml.confidence * 0.6));\n\n return {\n ...rule,\n direction: mergedDirection,\n confidence: mergedConfidence,\n composite: mergedComposite,\n reasoning: [\n ...rule.reasoning,\n `ML (${ml.model}): ${ml.direction} with ${(ml.probability * 100).toFixed(1)}% probability (horizon: ${ml.horizon})`,\n ],\n };\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { fetchMarketData, analyzeTrend } from '../../core/trends/market.js';\nimport { analyzeSentiment } from '../../core/trends/sentiment.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport { TREND_SYMBOLS } from '../../config/constants.js';\n\nexport async function handleTrends(options: {\n sentiment: boolean;\n chain: string;\n json: boolean;\n}): Promise<void> {\n const spinner = ora('Fetching market trends...').start();\n\n try {\n const symbols = TREND_SYMBOLS;\n const results = await Promise.all(symbols.map((s) => fetchMarketData(s)));\n\n spinner.stop();\n\n const marketData = results.filter((r): r is NonNullable<typeof r> => r !== null);\n\n if (marketData.length === 0) {\n console.log(chalk.yellow('No market data available. Check your API configuration.'));\n return;\n }\n\n if (options.json) {\n const output = await Promise.all(\n marketData.map(async (data) => {\n const trend = analyzeTrend(data);\n const prediction = await generatePrediction(data.symbol);\n return { data, trend, prediction };\n }),\n );\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold('Market Trends'));\n console.log();\n\n for (const data of marketData) {\n const trend = analyzeTrend(data);\n const directionIcon =\n trend.direction === 'bullish'\n ? chalk.green('^')\n : trend.direction === 'bearish'\n ? chalk.red('v')\n : chalk.yellow('-');\n\n console.log(\n `${directionIcon} ${chalk.bold(data.symbol)} $${data.price.toLocaleString()} ` +\n `${data.priceChange24h >= 0 ? chalk.green(`+${data.priceChange24h.toFixed(2)}%`) : chalk.red(`${data.priceChange24h.toFixed(2)}%`)} ` +\n `Vol: $${(data.volume24h / 1e9).toFixed(2)}B`,\n );\n\n if (trend.signals.length > 0) {\n for (const signal of trend.signals) {\n console.log(chalk.dim(` ${signal}`));\n }\n }\n }\n\n if (options.sentiment) {\n console.log();\n console.log(chalk.bold('Sentiment Analysis'));\n const sentiment = await analyzeSentiment('crypto market');\n console.log(chalk.dim(` Overall: ${sentiment.consensus}`));\n console.log(chalk.dim(' (Social media integration coming soon)'));\n }\n\n console.log();\n console.log(chalk.dim('Not financial advice. Always DYOR.'));\n } catch (error) {\n spinner.fail('Failed to fetch trends');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","import type { ChainAdapter } from '../../chains/types.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { getConfig } from '../../config/loader.js';\nimport type { WalletMLResult } from '../../ml/types.js';\n\nexport interface WalletAnalysis {\n address: string;\n chain: string;\n balance: bigint;\n transactionCount: number;\n tokenBalances: { symbol: string; address: string; balance: bigint }[];\n patterns: WalletPattern[];\n riskLevel: 'clean' | 'suspicious' | 'flagged';\n mlBehavior?: WalletMLResult;\n}\n\nexport interface WalletPattern {\n type: string;\n description: string;\n severity: 'info' | 'warning' | 'danger';\n}\n\nexport async function analyzeWallet(\n address: string,\n adapter: ChainAdapter,\n): Promise<WalletAnalysis> {\n const [balance, transactions] = await Promise.allSettled([\n adapter.getBalance(address),\n adapter.getTransactionHistory(address, { limit: 100 }),\n ]);\n\n const walletBalance = balance.status === 'fulfilled' ? balance.value : 0n;\n const txHistory = transactions.status === 'fulfilled' ? transactions.value : [];\n\n const patterns = detectPatterns(txHistory);\n\n // ML wallet classification\n let mlBehavior: WalletMLResult | undefined;\n try {\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (mlClient && txHistory.length > 0) {\n const features = buildWalletFeatures(txHistory);\n const result = await mlClient.classifyWallet(features);\n if (result) {\n mlBehavior = result;\n }\n }\n } catch {\n /* ML unavailable */\n }\n\n // Determine risk level from patterns + ML\n let riskLevel: WalletAnalysis['riskLevel'] = 'clean';\n if (patterns.some((p) => p.severity === 'danger')) {\n riskLevel = 'flagged';\n } else if (patterns.some((p) => p.severity === 'warning')) {\n riskLevel = 'suspicious';\n }\n // ML can upgrade risk level\n if (mlBehavior && mlBehavior.risk_score > 0.6) {\n riskLevel = 'flagged';\n } else if (mlBehavior && mlBehavior.risk_score > 0.3 && riskLevel === 'clean') {\n riskLevel = 'suspicious';\n }\n\n return {\n address,\n chain: adapter.chainId,\n balance: walletBalance,\n transactionCount: txHistory.length,\n tokenBalances: [],\n patterns,\n riskLevel,\n mlBehavior,\n };\n}\n\ninterface TxRecord {\n hash: string;\n from: string;\n to: string | null;\n value: bigint;\n timestamp: number;\n gasUsed?: bigint | number;\n isError?: boolean;\n status?: 'success' | 'reverted';\n methodId?: string;\n input?: string;\n}\n\nfunction buildWalletFeatures(txHistory: TxRecord[]) {\n const txCount = txHistory.length;\n if (txCount === 0) {\n return {\n tx_count: 0,\n avg_value_eth: 0,\n max_value_eth: 0,\n avg_gas_used: 0,\n unique_recipients: 0,\n unique_methods: 0,\n time_span_hours: 0,\n avg_interval_seconds: 3600,\n min_interval_seconds: 60,\n contract_interaction_pct: 0,\n self_transfer_pct: 0,\n high_value_tx_pct: 0,\n failed_tx_pct: 0,\n token_diversity: 0,\n };\n }\n\n const values = txHistory.map((tx) => Number(tx.value) / 1e18);\n const gasValues = txHistory.map((tx) => Number(tx.gasUsed ?? 21000));\n const recipients = new Set(txHistory.map((tx) => tx.to));\n const methods = new Set(\n txHistory.filter((tx) => tx.input && tx.input.length > 10).map((tx) => tx.input!.slice(0, 10)),\n );\n\n const timestamps = txHistory.map((tx) => tx.timestamp).sort((a, b) => a - b);\n const timeSpan = timestamps.length > 1 ? (timestamps.at(-1)! - timestamps[0]!) / 3600 : 0;\n\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i]! - timestamps[i - 1]!);\n }\n\n const selfTxs = txHistory.filter((tx) => tx.from === tx.to).length;\n const contractTxs = txHistory.filter((tx) => tx.input && tx.input.length > 10).length;\n const revertedTxs = txHistory.filter((tx) => tx.status === 'reverted').length;\n const highValueTxs = values.filter((v) => v > 10).length;\n\n return {\n tx_count: txCount,\n avg_value_eth: values.reduce((a, b) => a + b, 0) / txCount,\n max_value_eth: Math.max(...values),\n avg_gas_used: gasValues.reduce((a, b) => a + b, 0) / txCount,\n unique_recipients: recipients.size,\n unique_methods: methods.size,\n time_span_hours: timeSpan,\n avg_interval_seconds:\n intervals.length > 0 ? intervals.reduce((a, b) => a + b, 0) / intervals.length : 3600,\n min_interval_seconds: intervals.length > 0 ? Math.min(...intervals) : 60,\n contract_interaction_pct: contractTxs / txCount,\n self_transfer_pct: selfTxs / txCount,\n high_value_tx_pct: highValueTxs / txCount,\n failed_tx_pct: revertedTxs / txCount,\n token_diversity: methods.size,\n };\n}\n\nfunction detectPatterns(txHistory: TxRecord[]): WalletPattern[] {\n const patterns: WalletPattern[] = [];\n const txCount = txHistory.length;\n\n if (txCount === 0) {\n patterns.push({\n type: 'new_wallet',\n description: 'Wallet has no transaction history',\n severity: 'info',\n });\n return patterns;\n }\n\n // Rapid transactions (bot-like)\n if (txCount > 50) {\n const timestamps = txHistory.map((tx) => tx.timestamp).sort((a, b) => a - b);\n const intervals: number[] = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i]! - timestamps[i - 1]!);\n }\n const minInterval = Math.min(...intervals);\n if (minInterval < 5) {\n patterns.push({\n type: 'rapid_transactions',\n description: `Extremely rapid transactions detected (${minInterval}s apart) — possible bot activity`,\n severity: 'warning',\n });\n }\n }\n\n // High failure rate\n const revertedTxs = txHistory.filter((tx) => tx.status === 'reverted').length;\n if (txCount > 10 && revertedTxs / txCount > 0.3) {\n patterns.push({\n type: 'high_failure_rate',\n description: `${Math.round((revertedTxs / txCount) * 100)}% of transactions failed — possible sniper or MEV bot`,\n severity: 'warning',\n });\n }\n\n // Large value transfers\n const values = txHistory.map((tx) => Number(tx.value) / 1e18);\n const maxValue = Math.max(...values);\n if (maxValue > 100) {\n patterns.push({\n type: 'whale_activity',\n description: `Large transfers detected (max: ${maxValue.toFixed(2)} ETH)`,\n severity: 'info',\n });\n }\n\n // Self-transfers (mixing pattern)\n const selfTxs = txHistory.filter((tx) => tx.from === tx.to).length;\n if (selfTxs / txCount > 0.2) {\n patterns.push({\n type: 'self_transfers',\n description: `${Math.round((selfTxs / txCount) * 100)}% self-transfers — possible mixing activity`,\n severity: 'danger',\n });\n }\n\n // Contract-heavy interaction\n const contractTxs = txHistory.filter((tx) => tx.input && tx.input.length > 10).length;\n if (contractTxs / txCount > 0.9 && txCount > 20) {\n patterns.push({\n type: 'contract_heavy',\n description: 'Almost exclusively interacts with smart contracts — automated behavior',\n severity: 'warning',\n });\n }\n\n return patterns;\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\nimport { assertValidAddress } from '../../utils/validate.js';\n\nexport async function handleTrack(\n wallet: string,\n options: { chain: string; json: boolean },\n): Promise<void> {\n assertValidAddress(wallet);\n const spinner = ora(`Analyzing wallet ${wallet.slice(0, 10)}... on ${options.chain}`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n const analysis = await analyzeWallet(wallet, adapter);\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(\n JSON.stringify(\n analysis,\n (_key, value) => (typeof value === 'bigint' ? value.toString() : (value as unknown)),\n 2,\n ),\n );\n return;\n }\n\n console.log();\n console.log(chalk.bold(`Wallet Analysis: ${wallet}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n const ethBalance = Number(analysis.balance) / 1e18;\n console.log(` Balance: ${ethBalance.toFixed(6)} ${adapter.nativeCurrency.symbol}`);\n console.log(` Transactions: ${analysis.transactionCount}`);\n console.log(` Risk Level: ${colorRiskLevel(analysis.riskLevel)}`);\n console.log();\n\n if (analysis.patterns.length > 0) {\n console.log(chalk.bold('Detected Patterns'));\n for (const pattern of analysis.patterns) {\n const icon =\n pattern.severity === 'danger'\n ? chalk.red('!')\n : pattern.severity === 'warning'\n ? chalk.yellow('?')\n : chalk.blue('i');\n console.log(` ${icon} ${pattern.description}`);\n }\n console.log();\n }\n } catch (error) {\n spinner.fail('Wallet analysis failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\nfunction colorRiskLevel(level: string): string {\n switch (level) {\n case 'clean':\n return chalk.green('Clean');\n case 'suspicious':\n return chalk.yellow('Suspicious');\n case 'flagged':\n return chalk.red('Flagged');\n default:\n return level;\n }\n}\n","// ---------------------------------------------------------------------------\n// DeFiLlama API client — free, no auth required\n// https://api-docs.defillama.com/\n// ---------------------------------------------------------------------------\n\nconst BASE = 'https://api.llama.fi';\nconst COINS_BASE = 'https://coins.llama.fi';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface FundraisingRound {\n date: number; // unix timestamp\n name: string;\n round: string; // e.g. \"Seed\", \"Series A\", \"Token Launch\"\n amount: number | null; // USD raised\n chains: string[];\n sector: string;\n category: string;\n leadInvestors: string[];\n otherInvestors: string[];\n valuation: number | null;\n source: string | null;\n defiLlamaId: string | null;\n}\n\nexport interface Protocol {\n id: string;\n name: string;\n symbol: string;\n url: string;\n chains: string[];\n tvl: number;\n change_1h: number | null;\n change_1d: number | null;\n change_7d: number | null;\n mcap: number | null;\n category: string;\n logo: string | null;\n}\n\nexport interface ProtocolDetail extends Protocol {\n description: string;\n tvlList: { date: number; totalLiquidityUSD: number }[];\n currentChainTvls: Record<string, number>;\n}\n\nexport interface ChainTvl {\n gecko_id: string | null;\n tvl: number;\n tokenSymbol: string;\n cmcId: string | null;\n name: string;\n chainId: number | null;\n}\n\nexport interface DexOverview {\n totalDataChart: [number, number][];\n totalDataChartBreakdown: Record<string, unknown>[];\n protocols: {\n name: string;\n displayName: string;\n module: string;\n category: string;\n chains: string[];\n total24h: number | null;\n total7d: number | null;\n total30d: number | null;\n change_1d: number | null;\n }[];\n total24h: number;\n total7d: number;\n total30d: number;\n change_1d: number;\n}\n\nexport interface PriceData {\n price: number;\n symbol: string;\n timestamp: number;\n confidence: number;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`DeFiLlama API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Fetch all crypto fundraising rounds. Returns the full list — filter client-side.\n */\nexport async function fetchRaises(): Promise<FundraisingRound[]> {\n const data = await fetchJson<{ raises: FundraisingRound[] }>(`${BASE}/raises`);\n return data.raises ?? [];\n}\n\n/**\n * Fetch recent raises (last N days).\n */\nexport async function fetchRecentRaises(days = 30): Promise<FundraisingRound[]> {\n const raises = await fetchRaises();\n const cutoff = Date.now() / 1000 - days * 86400;\n return raises.filter((r) => r.date >= cutoff).sort((a, b) => b.date - a.date);\n}\n\n/**\n * Fetch raises filtered by round type (e.g. \"Seed\", \"Series A\", \"Pre-Seed\").\n */\nexport async function fetchRaisesByRound(\n roundType: string,\n days = 90,\n): Promise<FundraisingRound[]> {\n const raises = await fetchRecentRaises(days);\n const lower = roundType.toLowerCase();\n return raises.filter((r) => r.round.toLowerCase().includes(lower));\n}\n\n/**\n * Fetch raises where a specific investor participated.\n */\nexport async function fetchRaisesByInvestor(\n investor: string,\n days = 180,\n): Promise<FundraisingRound[]> {\n const raises = await fetchRecentRaises(days);\n const lower = investor.toLowerCase();\n return raises.filter(\n (r) =>\n r.leadInvestors.some((i) => i.toLowerCase().includes(lower)) ||\n r.otherInvestors.some((i) => i.toLowerCase().includes(lower)),\n );\n}\n\n/**\n * Fetch all DeFi protocols with TVL.\n */\nexport async function fetchProtocols(): Promise<Protocol[]> {\n return fetchJson<Protocol[]>(`${BASE}/protocols`);\n}\n\n/**\n * Fetch detailed info for a specific protocol.\n */\nexport async function fetchProtocol(slug: string): Promise<ProtocolDetail> {\n return fetchJson<ProtocolDetail>(`${BASE}/protocol/${encodeURIComponent(slug)}`);\n}\n\n/**\n * Fetch current prices for tokens. Coins must be in \"chain:address\" format.\n * Example: [\"ethereum:0xdac17f958d2ee523a2206206994597c13d831ec7\"]\n */\nexport async function fetchTokenPrices(coins: string[]): Promise<Record<string, PriceData>> {\n const data = await fetchJson<{ coins: Record<string, PriceData> }>(\n `${COINS_BASE}/prices/current/${coins.map(encodeURIComponent).join(',')}`,\n );\n return data.coins ?? {};\n}\n\n/**\n * Fetch TVL data for all chains.\n */\nexport async function fetchChainTvl(): Promise<ChainTvl[]> {\n return fetchJson<ChainTvl[]>(`${BASE}/v2/chains`);\n}\n\n/**\n * Fetch DEX volume overview, optionally for a specific chain.\n */\nexport async function fetchDexOverview(chain?: string): Promise<DexOverview> {\n const path = chain ? `/overview/dexs/${encodeURIComponent(chain)}` : '/overview/dexs';\n return fetchJson<DexOverview>(`${BASE}${path}`);\n}\n","// ---------------------------------------------------------------------------\n// Pump.fun API client — latest Solana meme coin launches\n// https://frontend-api-v3.pump.fun\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://frontend-api-v3.pump.fun';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PumpCoin {\n mint: string;\n name: string;\n symbol: string;\n description: string;\n image_uri: string | null;\n market_cap: number;\n sol_amount: number;\n created_timestamp: number;\n creator: string;\n reply_count: number;\n last_reply: number | null;\n nsfw: boolean;\n usd_market_cap: number;\n}\n\nexport interface PumpTrade {\n signature: string;\n mint: string;\n sol_amount: number;\n token_amount: number;\n is_buy: boolean;\n user: string;\n timestamp: number;\n slot: number;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(path: string): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`, {\n headers: {\n Accept: 'application/json',\n 'User-Agent':\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)',\n },\n });\n if (!res.ok) {\n throw new Error(`Pump.fun API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n/**\n * Fetch the latest coins launched on Pump.fun.\n */\nexport async function fetchLatestCoins(limit = 20, offset = 0): Promise<PumpCoin[]> {\n return fetchJson<PumpCoin[]>(`/coins/latest?limit=${limit}&offset=${offset}&includeNsfw=false`);\n}\n\n/**\n * Get details for a specific coin by mint address.\n */\nexport async function getCoinDetails(mint: string): Promise<PumpCoin> {\n return fetchJson<PumpCoin>(`/coins/${encodeURIComponent(mint)}`);\n}\n\n/**\n * Get recent trades for a specific token.\n */\nexport async function getTokenTrades(mint: string, limit = 20, offset = 0): Promise<PumpTrade[]> {\n return fetchJson<PumpTrade[]>(\n `/trades/token/${encodeURIComponent(mint)}?limit=${limit}&offset=${offset}`,\n );\n}\n","// ---------------------------------------------------------------------------\n// ICO / Fundraising tracker — powered by DeFiLlama raises + Pump.fun\n// ---------------------------------------------------------------------------\n\nimport {\n fetchRecentRaises,\n fetchRaisesByRound,\n fetchRaisesByInvestor,\n} from '../../data/sources/defillama.js';\nimport { fetchLatestCoins } from '../../data/sources/pumpfun.js';\nimport type { FundraisingRound } from '../../data/sources/defillama.js';\n\nexport interface ICOProject {\n id: string;\n name: string;\n symbol: string;\n category: string;\n chain: string;\n status: 'upcoming' | 'active' | 'ended';\n startDate: string | null;\n endDate: string | null;\n description: string;\n website: string | null;\n raisedAmount: number | null;\n targetAmount: number | null;\n roundType: string;\n investors: string[];\n valuation: number | null;\n previousRounds: { round: string; amount: number | null; date: string }[];\n}\n\nfunction raiseToICO(r: FundraisingRound): ICOProject {\n return {\n id: r.defiLlamaId ?? r.name.toLowerCase().replace(/\\s+/g, '-'),\n name: r.name,\n symbol: '',\n category: r.category || r.sector || 'crypto',\n chain: r.chains[0] ?? 'multi-chain',\n status: 'active',\n startDate: new Date(r.date * 1000).toISOString(),\n endDate: null,\n description: `${r.round} round${r.amount ? ` — $${(r.amount / 1e6).toFixed(1)}M raised` : ''}. ${r.leadInvestors.length > 0 ? `Led by ${r.leadInvestors.join(', ')}.` : ''}`,\n website: r.source,\n raisedAmount: r.amount,\n targetAmount: null,\n roundType: r.round,\n investors: [...r.leadInvestors, ...r.otherInvestors],\n valuation: r.valuation,\n previousRounds: [],\n };\n}\n\n/**\n * Fetch recent fundraising rounds from DeFiLlama.\n */\nexport async function fetchUpcomingICOs(): Promise<ICOProject[]> {\n try {\n const raises = await fetchRecentRaises(30);\n return raises.slice(0, 20).map(raiseToICO);\n } catch {\n return [];\n }\n}\n\n/**\n * Fetch latest Pump.fun launches (Solana meme coins).\n */\nexport async function fetchActiveICOs(): Promise<ICOProject[]> {\n try {\n const coins = await fetchLatestCoins(20);\n\n return coins.map((c) => ({\n id: c.mint,\n name: c.name,\n symbol: c.symbol,\n category: 'meme',\n chain: 'solana',\n status: 'active' as const,\n startDate: new Date(c.created_timestamp).toISOString(),\n endDate: null,\n description:\n c.description || `Pump.fun launch. Market cap: $${c.usd_market_cap?.toFixed(0) ?? '?'}`,\n website: null,\n raisedAmount: c.usd_market_cap ?? null,\n targetAmount: null,\n roundType: 'Fair Launch',\n investors: [],\n valuation: c.usd_market_cap ?? null,\n previousRounds: [],\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Search raises and launches by query, category, chain, or round type.\n */\nexport async function searchICOs(\n query?: string,\n category?: string,\n chain?: string,\n roundType?: string,\n): Promise<ICOProject[]> {\n try {\n let raises: FundraisingRound[];\n if (roundType) {\n raises = await fetchRaisesByRound(roundType, 90);\n } else {\n raises = await fetchRecentRaises(90);\n }\n\n let filtered = raises.map(raiseToICO);\n\n if (query) {\n const q = query.toLowerCase();\n filtered = filtered.filter(\n (p) => p.name.toLowerCase().includes(q) || p.category.toLowerCase().includes(q),\n );\n }\n if (category) {\n const cat = category.toLowerCase();\n filtered = filtered.filter((p) => p.category.toLowerCase().includes(cat));\n }\n if (chain) {\n const ch = chain.toLowerCase();\n filtered = filtered.filter((p) => p.chain.toLowerCase().includes(ch));\n }\n\n return filtered.slice(0, 20);\n } catch {\n return [];\n }\n}\n\n/**\n * Get funding history for a project by name — finds all rounds involving that name.\n */\nexport async function getProjectFundingHistory(\n name: string,\n): Promise<{ name: string; rounds: ICOProject[] }> {\n try {\n const raises = await fetchRecentRaises(365);\n const lower = name.toLowerCase();\n const matches = raises\n .filter((r) => r.name.toLowerCase().includes(lower))\n .sort((a, b) => a.date - b.date)\n .map(raiseToICO);\n\n // Link previous rounds\n for (let i = 1; i < matches.length; i++) {\n const project = matches[i];\n if (project) {\n project.previousRounds = matches.slice(0, i).map((prev) => ({\n round: prev.roundType,\n amount: prev.raisedAmount,\n date: prev.startDate ?? '',\n }));\n }\n }\n\n return { name, rounds: matches };\n } catch {\n return { name, rounds: [] };\n }\n}\n\n/**\n * Get raises by a specific investor.\n */\nexport async function getInvestorPortfolio(investor: string): Promise<ICOProject[]> {\n try {\n const raises = await fetchRaisesByInvestor(investor, 365);\n return raises.slice(0, 30).map(raiseToICO);\n } catch {\n return [];\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { fetchUpcomingICOs, searchICOs } from '../../core/scanner/ico-tracker.js';\n\nexport async function handleIcoList(options: {\n category?: string;\n chain?: string;\n json: boolean;\n}): Promise<void> {\n const spinner = ora('Fetching ICO data...').start();\n\n try {\n const icos =\n options.category || options.chain\n ? await searchICOs(undefined, options.category, options.chain)\n : await fetchUpcomingICOs();\n\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(icos, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold('Upcoming ICOs / IDOs'));\n console.log();\n\n if (icos.length === 0) {\n console.log(chalk.dim(' No ICOs found. ICO tracking APIs will be integrated soon.'));\n console.log(chalk.dim(' Sources planned: ICODrops, CoinGecko, DeFiLlama'));\n console.log();\n return;\n }\n\n for (const ico of icos) {\n const statusColor =\n ico.status === 'active' ? chalk.green : ico.status === 'upcoming' ? chalk.blue : chalk.dim;\n\n console.log(\n ` ${statusColor(ico.status.toUpperCase())} ${chalk.bold(ico.name)} (${ico.symbol})`,\n );\n console.log(` Chain: ${ico.chain} | Category: ${ico.category}`);\n if (ico.startDate) {\n console.log(` Start: ${ico.startDate}`);\n }\n if (ico.targetAmount) {\n console.log(` Target: $${ico.targetAmount.toLocaleString()}`);\n }\n console.log();\n }\n } catch (error) {\n spinner.fail('Failed to fetch ICO data');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n","import type { ChainAdapter } from '../../chains/types.js';\n\nexport interface AuditResult {\n address: string;\n chain: string;\n hasCode: boolean;\n codeSize: number;\n findings: AuditFinding[];\n overallRisk: 'low' | 'medium' | 'high' | 'critical';\n}\n\nexport interface AuditFinding {\n title: string;\n description: string;\n severity: 'info' | 'low' | 'medium' | 'high' | 'critical';\n category: string;\n}\n\nexport async function auditContract(address: string, adapter: ChainAdapter): Promise<AuditResult> {\n const code = await adapter.getContractCode(address).catch(() => '');\n const findings: AuditFinding[] = [];\n\n const hasCode = code.length > 2;\n\n if (!hasCode) {\n findings.push({\n title: 'No Contract Code',\n description: 'Address does not contain contract bytecode. This may be an EOA.',\n severity: 'critical',\n category: 'deployment',\n });\n\n return {\n address,\n chain: adapter.chainId,\n hasCode: false,\n codeSize: 0,\n findings,\n overallRisk: 'critical',\n };\n }\n\n const codeSize = (code.length - 2) / 2; // hex string minus 0x, each byte = 2 chars\n\n if (codeSize < 100) {\n findings.push({\n title: 'Minimal Contract',\n description: `Contract bytecode is very small (${codeSize} bytes). May be a proxy or minimal implementation.`,\n severity: 'medium',\n category: 'size',\n });\n }\n\n if (codeSize > 24576) {\n findings.push({\n title: 'Large Contract',\n description: `Contract bytecode is ${codeSize} bytes, approaching the 24KB deployment limit.`,\n severity: 'info',\n category: 'size',\n });\n }\n\n // TODO: Add more audit checks:\n // - Proxy pattern detection (delegatecall)\n // - Selfdestruct detection\n // - Known vulnerability signatures\n // - Storage layout analysis\n\n const overallRisk = determineOverallRisk(findings);\n\n return {\n address,\n chain: adapter.chainId,\n hasCode,\n codeSize,\n findings,\n overallRisk,\n };\n}\n\nfunction determineOverallRisk(findings: AuditFinding[]): AuditResult['overallRisk'] {\n if (findings.some((f) => f.severity === 'critical')) return 'critical';\n if (findings.some((f) => f.severity === 'high')) return 'high';\n if (findings.some((f) => f.severity === 'medium')) return 'medium';\n return 'low';\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\nimport { assertValidAddress } from '../../utils/validate.js';\n\nexport async function handleAudit(\n contract: string,\n options: { chain: string; json: boolean },\n): Promise<void> {\n assertValidAddress(contract);\n const spinner = ora(`Auditing contract ${contract.slice(0, 10)}... on ${options.chain}`).start();\n\n try {\n const adapter = getAdapter(options.chain);\n const cfg = getConfig();\n await adapter.connect(undefined, cfg.etherscanApiKey);\n\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n spinner.stop();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.bold(`Contract Audit: ${contract}`));\n console.log(chalk.dim(`Chain: ${options.chain}`));\n console.log();\n\n console.log(` Has Code: ${result.hasCode ? chalk.green('Yes') : chalk.red('No')}`);\n console.log(` Code Size: ${result.codeSize} bytes`);\n console.log(` Overall Risk: ${colorRisk(result.overallRisk)}`);\n console.log();\n\n if (result.findings.length > 0) {\n console.log(chalk.bold('Findings'));\n for (const finding of result.findings) {\n const icon = severityIcon(finding.severity);\n console.log(` ${icon} [${finding.severity.toUpperCase()}] ${finding.title}`);\n console.log(chalk.dim(` ${finding.description}`));\n }\n console.log();\n } else {\n console.log(chalk.green(' No issues detected.'));\n console.log();\n }\n\n console.log(chalk.dim('Note: This is a basic bytecode-level audit. For comprehensive'));\n console.log(chalk.dim('security analysis, use a professional audit service.'));\n } catch (error) {\n spinner.fail('Audit failed');\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\nfunction colorRisk(level: string): string {\n switch (level) {\n case 'low':\n return chalk.green('Low');\n case 'medium':\n return chalk.yellow('Medium');\n case 'high':\n return chalk.red('High');\n case 'critical':\n return chalk.bgRed.white(' CRITICAL ');\n default:\n return level;\n }\n}\n\nfunction severityIcon(severity: string): string {\n switch (severity) {\n case 'critical':\n return chalk.bgRed.white('!');\n case 'high':\n return chalk.red('!');\n case 'medium':\n return chalk.yellow('!');\n case 'low':\n return chalk.blue('i');\n case 'info':\n return chalk.dim('i');\n default:\n return '-';\n }\n}\n","// ---------------------------------------------------------------------------\n// AI Provider abstraction — shared types for multi-provider support\n// ---------------------------------------------------------------------------\n\n/** Handler that executes a tool call and returns its result. */\nexport type ToolHandler = (name: string, input: unknown) => Promise<unknown>;\n\n/** Callbacks invoked during streaming. */\nexport interface StreamCallbacks {\n onText: (delta: string) => void;\n onToolStart: (toolName: string) => void;\n onToolEnd: (toolName: string) => void;\n onDone: (fullText: string) => void;\n}\n\n/** Provider-agnostic tool definition (JSON Schema based). */\nexport interface AITool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, unknown>;\n required: string[];\n };\n}\n\n/** Interface that all AI providers must implement. */\nexport interface AIProvider {\n /** Provider identifier (e.g. 'anthropic', 'openai'). */\n readonly name: string;\n\n /** Whether this provider supports tool use (function calling). */\n readonly supportsTools: boolean;\n\n /**\n * Initialize the provider with credentials and model selection.\n * Called once before any analyze/stream calls.\n */\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void;\n\n /**\n * Send a message and return the full text response.\n * Includes agentic tool-use loop if tools and handler are provided.\n */\n analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string>;\n\n /**\n * Stream a message with callbacks for incremental text and tool events.\n * Includes agentic tool-use loop if tools and handler are provided.\n */\n analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string>;\n}\n\n/** Maximum iterations for the agentic tool-use loop. */\nexport const MAX_ITERATIONS = 10;\n\n/** Default models per provider. */\nexport const DEFAULT_MODELS: Record<string, string> = {\n anthropic: 'claude-sonnet-4-20250514',\n openai: 'gpt-4o',\n gemini: 'gemini-2.5-flash',\n ollama: 'llama3.2',\n};\n","/**\n * Throws a descriptive error if the given API key value is undefined or empty.\n */\nexport function requireKey(keyName: string, value: string | undefined): string {\n if (!value) {\n throw new Error(\n `Missing required API key: ${keyName}. ` +\n `Set it in ~/.vizzor/config.yaml or via the corresponding environment variable.`,\n );\n }\n return value;\n}\n\n/**\n * Returns true if the given value is a non-empty string.\n */\nexport function hasKey(value: string | undefined): boolean {\n return typeof value === 'string' && value.length > 0;\n}\n\n/**\n * Masks an API key for safe display using zero-knowledge style masking.\n * Shows only the first 2 and last 2 characters with asterisks in between.\n * This prevents leaking key prefixes that could be used for phishing or\n * identifying the key provider/format.\n */\nexport function maskKey(value: string | undefined): string {\n if (!value) {\n return '<not set>';\n }\n if (value.length <= 4) {\n return '****';\n }\n if (value.length <= 8) {\n return value.slice(0, 1) + '****' + value.slice(-1);\n }\n return value.slice(0, 2) + '*'.repeat(Math.min(value.length - 4, 12)) + value.slice(-2);\n}\n\n// ---------------------------------------------------------------------------\n// Key validation — reject phishing, scam, and malformed keys\n// ---------------------------------------------------------------------------\n\n/** Known key prefix patterns for supported providers. */\nconst KEY_PATTERNS: Record<string, RegExp> = {\n anthropicApiKey: /^sk-ant-[a-zA-Z0-9_-]{20,}$/,\n openaiApiKey: /^sk-[a-zA-Z0-9_-]{20,}$/,\n googleApiKey: /^AI[a-zA-Z0-9_-]{20,}$/,\n etherscanApiKey: /^[A-Z0-9]{20,}$/,\n alchemyApiKey: /^[a-zA-Z0-9_-]{20,}$/,\n coingeckoApiKey: /^CG-[a-zA-Z0-9]{10,}$/,\n cryptopanicApiKey: /^[a-f0-9]{20,}$/,\n};\n\n/** Characters that should never appear in a legitimate API key. */\nconst FORBIDDEN_CHARS = /[<>{}()|\\\\;`$!\"'&\\s]/;\n\n/** Patterns indicating phishing or injection attempts. */\nconst PHISHING_PATTERNS = [\n /https?:\\/\\//i,\n /javascript:/i,\n /data:/i,\n /<script/i,\n /eval\\s*\\(/i,\n /\\.\\.\\//,\n /\\/etc\\//,\n /\\$\\{/,\n /`.*`/,\n];\n\n/**\n * Validates an API key value for a given config key.\n * Returns null if valid, or an error message if rejected.\n */\nexport function validateKey(keyName: string, value: string): string | null {\n if (!value || value.trim().length === 0) {\n return 'Key value cannot be empty.';\n }\n\n // Check for forbidden characters (injection / phishing)\n if (FORBIDDEN_CHARS.test(value)) {\n return 'Key contains invalid characters. API keys only use alphanumeric characters, hyphens, and underscores.';\n }\n\n // Check for phishing / injection patterns\n for (const pattern of PHISHING_PATTERNS) {\n if (pattern.test(value)) {\n return 'Key rejected: value looks like a URL, script, or injection attempt.';\n }\n }\n\n // Length sanity check\n if (value.length > 256) {\n return 'Key rejected: value is too long (max 256 characters).';\n }\n\n // Provider-specific format validation (warn, don't block)\n const expectedPattern = KEY_PATTERNS[keyName];\n if (expectedPattern && !expectedPattern.test(value)) {\n return `Warning: key format doesn't match expected pattern for ${keyName}. Double-check the value.`;\n }\n\n return null;\n}\n","import chalk from 'chalk';\nimport { writeFileSync, existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { stringify as yamlStringify } from 'yaml';\nimport { getConfigDir, loadConfig, getConfig, saveConfigValue } from '../../config/loader.js';\nimport { DEFAULT_CHAIN } from '../../config/constants.js';\nimport { DEFAULT_MODELS } from '../../ai/providers/types.js';\nimport { maskKey, validateKey } from '../../config/keys.js';\n\nexport async function handleConfigInit(): Promise<void> {\n const configDir = getConfigDir();\n const configPath = resolve(configDir, 'config.yaml');\n\n if (existsSync(configPath)) {\n console.log(chalk.yellow('Configuration already exists at:'), configPath);\n console.log(chalk.dim('Use \"vizzor config set <key> <value>\" to update values.'));\n return;\n }\n\n const defaultConfig = {\n anthropicApiKey: '',\n etherscanApiKey: '',\n defaultChain: DEFAULT_CHAIN,\n ai: {\n model: DEFAULT_MODELS['anthropic'],\n maxTokens: 4096,\n },\n output: {\n format: 'table',\n color: true,\n verbose: false,\n },\n };\n\n writeFileSync(configPath, yamlStringify(defaultConfig), 'utf-8');\n\n console.log(chalk.green('Configuration initialized at:'), configPath);\n console.log();\n console.log('Next steps:');\n console.log(\n ` 1. Set your Anthropic API key: ${chalk.cyan('vizzor config set anthropicApiKey <your-key>')}`,\n );\n console.log(\n ` 2. Set your Etherscan API key: ${chalk.cyan('vizzor config set etherscanApiKey <your-key>')}`,\n );\n console.log(` 3. Try scanning a project: ${chalk.cyan('vizzor scan ethereum')}`);\n}\n\nexport async function handleConfigSet(key: string, value: string): Promise<void> {\n // Validate keys for security (phishing, injection, format)\n const isSensitive = key.toLowerCase().includes('key') || key.toLowerCase().includes('token');\n if (isSensitive) {\n const error = validateKey(key, value);\n if (error && !error.startsWith('Warning:')) {\n console.log(chalk.red(`Rejected: ${error}`));\n return;\n }\n if (error?.startsWith('Warning:')) {\n console.log(chalk.yellow(error));\n }\n }\n\n try {\n saveConfigValue(key, value);\n } catch (err) {\n console.log(chalk.red(err instanceof Error ? err.message : String(err)));\n return;\n }\n\n const displayValue = isSensitive ? maskKey(value) : value;\n\n console.log(chalk.green(`Set ${key} = ${displayValue}`));\n}\n\nexport async function handleConfigShow(): Promise<void> {\n await loadConfig();\n const config = getConfig();\n const configDir = getConfigDir();\n\n console.log();\n console.log(chalk.bold('Vizzor Configuration'));\n console.log(chalk.dim(`Location: ${resolve(configDir, 'config.yaml')}`));\n console.log();\n\n const entries = Object.entries(config);\n for (const [key, value] of entries) {\n if (typeof value === 'object' && value !== null) {\n console.log(` ${chalk.bold(key)}:`);\n for (const [subKey, subValue] of Object.entries(value as Record<string, unknown>)) {\n console.log(` ${subKey}: ${String(subValue)}`);\n }\n } else {\n const displayValue =\n typeof value === 'string' &&\n (key.toLowerCase().includes('key') || key.toLowerCase().includes('token'))\n ? maskKey(value)\n : String(value ?? '');\n console.log(` ${key}: ${displayValue || chalk.dim('(not set)')}`);\n }\n }\n console.log();\n}\n","// ---------------------------------------------------------------------------\n// Anthropic provider — Claude integration via @anthropic-ai/sdk\n// ---------------------------------------------------------------------------\n\nimport Anthropic from '@anthropic-ai/sdk';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class AnthropicProvider implements AIProvider {\n readonly name = 'anthropic';\n readonly supportsTools = true;\n\n private client: Anthropic | undefined;\n private model = DEFAULT_MODELS['anthropic']!;\n private maxTokens = 8192;\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'Anthropic API key is not configured. Set ANTHROPIC_API_KEY or add anthropicApiKey to ~/.vizzor/config.yaml.',\n );\n }\n\n this.client = new Anthropic({ apiKey });\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -------------------------------------------------------------------------\n // Non-streaming analysis with agentic tool-use loop\n // -------------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const ai = this.getClient();\n const maxIterations = MAX_ITERATIONS; // safety cap for the agentic loop\n\n const messages: Anthropic.Messages.MessageParam[] = [{ role: 'user', content: userMessage }];\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const params: Anthropic.Messages.MessageCreateParamsNonStreaming = {\n model: this.model,\n max_tokens: this.maxTokens,\n system: systemPrompt,\n messages,\n ...(tools && tools.length > 0 ? { tools: tools as Anthropic.Messages.Tool[] } : {}),\n };\n\n const response = await ai.messages.create(params);\n\n // Collect tool_use blocks from the response.\n const toolUseBlocks = response.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock => block.type === 'tool_use',\n );\n\n // If there are no tool calls, extract text and return.\n if (toolUseBlocks.length === 0 || response.stop_reason !== 'tool_use') {\n return extractText(response.content);\n }\n\n // --- Agentic loop: execute tools and continue the conversation --------\n\n if (!toolHandler) {\n throw new Error('Claude requested tool use but no tool handler was provided.');\n }\n\n // Capture in a const so TypeScript narrows the type inside the async map.\n const handler = toolHandler;\n\n // Append the assistant's response (including tool_use blocks) so Claude\n // can see what it previously said.\n messages.push({\n role: 'assistant',\n content: response.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // For any other block type, serialise as text so we don't lose info.\n return { type: 'text' as const, text: JSON.stringify(block) };\n }),\n });\n\n // Execute each tool and build the tool_result blocks.\n const toolResults: Anthropic.Messages.ToolResultBlockParam[] = await Promise.all(\n toolUseBlocks.map(async (block) => {\n try {\n const result = await handler(block.name, block.input);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify(result),\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify({ error: message }),\n is_error: true,\n };\n }\n }),\n );\n\n messages.push({ role: 'user', content: toolResults });\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -------------------------------------------------------------------------\n // Streaming analysis with agentic tool-use loop\n // -------------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const ai = this.getClient();\n const maxIterations = MAX_ITERATIONS; // safety cap for the agentic loop\n\n const messages: Anthropic.Messages.MessageParam[] = [{ role: 'user', content: userMessage }];\n\n // Accumulates text across all iterations so onDone receives the full output.\n let fullText = '';\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n const streamParams: Anthropic.Messages.MessageCreateParamsStreaming = {\n model: this.model,\n max_tokens: this.maxTokens,\n system: systemPrompt,\n messages,\n stream: true,\n ...(tools && tools.length > 0 ? { tools: tools as Anthropic.Messages.Tool[] } : {}),\n };\n\n // --- Stream the response -----------------------------------------------\n\n const stream = ai.messages.stream(streamParams);\n\n // Forward incremental text deltas to the caller.\n stream.on('text', (delta) => {\n fullText += delta;\n callbacks.onText(delta);\n });\n\n let finalMessage: Anthropic.Messages.Message;\n try {\n finalMessage = await stream.finalMessage();\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Anthropic streaming request failed: ${detail}`, {\n cause: err,\n });\n }\n\n // --- Check for tool use ------------------------------------------------\n\n const toolUseBlocks = finalMessage.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock => block.type === 'tool_use',\n );\n\n // No tool calls — we are done.\n if (toolUseBlocks.length === 0 || finalMessage.stop_reason !== 'tool_use') {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and continue streaming ----------------\n\n if (!toolHandler) {\n throw new Error('Claude requested tool use but no tool handler was provided.');\n }\n\n // Capture in a const so TypeScript narrows the type inside the async map.\n const handler = toolHandler;\n\n // Append the assistant's full response (text + tool_use blocks) to the\n // conversation so Claude can see what it previously said.\n messages.push({\n role: 'assistant',\n content: finalMessage.content.map((block) => {\n if (block.type === 'text') {\n return { type: 'text' as const, text: block.text };\n }\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use' as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n // For any other block type, serialise as text so we don't lose info.\n return { type: 'text' as const, text: JSON.stringify(block) };\n }),\n });\n\n // Execute each requested tool and build the tool_result blocks.\n const toolResults: Anthropic.Messages.ToolResultBlockParam[] = await Promise.all(\n toolUseBlocks.map(async (block) => {\n callbacks.onToolStart(block.name);\n try {\n const result = await handler(block.name, block.input);\n callbacks.onToolEnd(block.name);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify(result),\n };\n } catch (err: unknown) {\n callbacks.onToolEnd(block.name);\n const message = err instanceof Error ? err.message : String(err);\n return {\n type: 'tool_result' as const,\n tool_use_id: block.id,\n content: JSON.stringify({ error: message }),\n is_error: true,\n };\n }\n }),\n );\n\n messages.push({ role: 'user', content: toolResults });\n\n // Loop continues — the next iteration will stream Claude's follow-up.\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -------------------------------------------------------------------------\n // Internal helpers\n // -------------------------------------------------------------------------\n\n /** Return the Anthropic client, throwing if not initialised. */\n private getClient(): Anthropic {\n if (!this.client) {\n throw new Error('AnthropicProvider has not been initialised. Call initialize() first.');\n }\n return this.client;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Concatenate all text blocks from a response's content array. */\nfunction extractText(content: Anthropic.Messages.ContentBlock[]): string {\n return content\n .filter((block): block is Anthropic.Messages.TextBlock => block.type === 'text')\n .map((block) => block.text)\n .join('\\n\\n');\n}\n","// ---------------------------------------------------------------------------\n// OpenAI provider — GPT-4o / GPT-4-turbo with agentic tool-use loop\n// ---------------------------------------------------------------------------\n\nimport OpenAI from 'openai';\nimport type {\n ChatCompletionChunk,\n ChatCompletionMessageFunctionToolCall,\n ChatCompletionMessageParam,\n} from 'openai/resources/chat/completions';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n/** Convert provider-agnostic tool definitions to the OpenAI function-calling format. */\nfunction toOpenAITools(tools: AITool[]): OpenAI.Chat.Completions.ChatCompletionTool[] {\n return tools.map((t) => ({\n type: 'function' as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n },\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Accumulated streaming tool call\n// ---------------------------------------------------------------------------\n\ninterface AccumulatedToolCall {\n id: string;\n functionName: string;\n arguments: string;\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class OpenAIProvider implements AIProvider {\n readonly name = 'openai';\n readonly supportsTools = true;\n\n private client: OpenAI | undefined;\n private model = DEFAULT_MODELS['openai']!;\n private maxTokens = 4096;\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'OpenAI API key is not configured. Set OPENAI_API_KEY or add openaiApiKey to ~/.vizzor/config.yaml.',\n );\n }\n this.client = new OpenAI({ apiKey });\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -----------------------------------------------------------------------\n // Non-streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const client = this.requireClient();\n\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n const openaiTools = tools && tools.length > 0 ? toOpenAITools(tools) : undefined;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const response = await client.chat.completions.create({\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n ...(openaiTools ? { tools: openaiTools, tool_choice: 'auto' as const } : {}),\n });\n\n const choice = response.choices[0];\n if (!choice) {\n return '';\n }\n\n const message = choice.message;\n\n // Filter to function-type tool calls only (OpenAI also has a 'custom' variant).\n const toolCalls: ChatCompletionMessageFunctionToolCall[] = (\n message.tool_calls ?? []\n ).filter((tc): tc is ChatCompletionMessageFunctionToolCall => tc.type === 'function');\n\n // No tool calls — return the text content.\n if (toolCalls.length === 0 || choice.finish_reason !== 'tool_calls') {\n return message.content ?? '';\n }\n\n // --- Agentic loop: execute tools and continue the conversation ------\n\n if (!toolHandler) {\n throw new Error('OpenAI requested tool use but no tool handler is registered.');\n }\n\n // Append the assistant's response (including tool_calls) to the conversation.\n messages.push({\n role: 'assistant',\n content: message.content ?? null,\n tool_calls: toolCalls.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n })),\n });\n\n // Execute each tool and append the results.\n const handler = toolHandler;\n await Promise.all(\n toolCalls.map(async (tc) => {\n let content: string;\n try {\n const input: unknown = JSON.parse(tc.function.arguments);\n const result = await handler(tc.function.name, input);\n content = JSON.stringify(result);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n content = JSON.stringify({ error: detail });\n }\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content,\n });\n }),\n );\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`OpenAI request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -----------------------------------------------------------------------\n // Streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const client = this.requireClient();\n\n const messages: ChatCompletionMessageParam[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ];\n\n const openaiTools = tools && tools.length > 0 ? toOpenAITools(tools) : undefined;\n\n let fullText = '';\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const stream = await client.chat.completions.create({\n model: this.model,\n max_tokens: this.maxTokens,\n messages,\n stream: true,\n ...(openaiTools ? { tools: openaiTools, tool_choice: 'auto' as const } : {}),\n });\n\n // Accumulators for the current stream iteration.\n const accumulatedToolCalls = new Map<number, AccumulatedToolCall>();\n let finishReason: string | null = null;\n\n for await (const chunk of stream as AsyncIterable<ChatCompletionChunk>) {\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n // Track finish reason.\n if (choice.finish_reason) {\n finishReason = choice.finish_reason;\n }\n\n const delta = choice.delta;\n\n // Forward text deltas.\n if (delta.content) {\n fullText += delta.content;\n callbacks.onText(delta.content);\n }\n\n // Accumulate tool calls that arrive incrementally.\n if (delta.tool_calls) {\n for (const tc of delta.tool_calls) {\n const idx = tc.index;\n let acc = accumulatedToolCalls.get(idx);\n if (!acc) {\n acc = { id: '', functionName: '', arguments: '' };\n accumulatedToolCalls.set(idx, acc);\n }\n if (tc.id) {\n acc.id = tc.id;\n }\n if (tc.function?.name) {\n acc.functionName = tc.function.name;\n }\n if (tc.function?.arguments) {\n acc.arguments += tc.function.arguments;\n }\n }\n }\n }\n\n // If no tool calls were accumulated, we are done.\n if (accumulatedToolCalls.size === 0 || finishReason !== 'tool_calls') {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and re-stream ----------------------\n\n if (!toolHandler) {\n throw new Error('OpenAI requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n const toolCallsList = Array.from(accumulatedToolCalls.values());\n\n // Append the assistant message with accumulated tool calls.\n messages.push({\n role: 'assistant',\n content: null,\n tool_calls: toolCallsList.map((tc) => ({\n id: tc.id,\n type: 'function' as const,\n function: {\n name: tc.functionName,\n arguments: tc.arguments,\n },\n })),\n });\n\n // Execute each tool and append results.\n for (const tc of toolCallsList) {\n callbacks.onToolStart(tc.functionName);\n let content: string;\n try {\n const input: unknown = JSON.parse(tc.arguments);\n const result = await handler(tc.functionName, input);\n content = JSON.stringify(result);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n content = JSON.stringify({ error: detail });\n }\n callbacks.onToolEnd(tc.functionName);\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content,\n });\n }\n\n // Loop continues — the next iteration will re-stream.\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`OpenAI streaming request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private requireClient(): OpenAI {\n if (!this.client) {\n throw new Error('OpenAI provider has not been initialized. Call initialize() first.');\n }\n return this.client;\n }\n}\n","// ---------------------------------------------------------------------------\n// Google Gemini provider — Gemini 2.5 Flash / Pro with agentic tool-use loop\n// ---------------------------------------------------------------------------\n\nimport {\n GoogleGenerativeAI,\n type Content,\n type FunctionCall,\n type FunctionDeclaration,\n type GenerativeModel,\n type Part,\n} from '@google/generative-ai';\nimport { DEFAULT_MODELS, MAX_ITERATIONS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n/**\n * Convert provider-agnostic tool definitions to Gemini's FunctionDeclaration format.\n *\n * Gemini expects `parameters` as a JSON Schema object. Our `AITool.input_schema`\n * is already in that shape, so we pass it through directly.\n */\nfunction toGeminiFunctionDeclarations(tools: AITool[]): FunctionDeclaration[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: t.input_schema as FunctionDeclaration['parameters'],\n }));\n}\n\n/** Extract all FunctionCall parts from a Gemini response's candidate parts. */\nfunction extractFunctionCalls(parts: Part[] | undefined): FunctionCall[] {\n if (!parts) return [];\n const calls: FunctionCall[] = [];\n for (const part of parts) {\n if (part.functionCall) {\n calls.push(part.functionCall);\n }\n }\n return calls;\n}\n\n/** Extract concatenated text from Gemini response candidate parts. */\nfunction extractText(parts: Part[] | undefined): string {\n if (!parts) return '';\n return parts\n .filter((p) => typeof p.text === 'string')\n .map((p) => p.text as string)\n .join('');\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class GeminiProvider implements AIProvider {\n readonly name = 'gemini';\n readonly supportsTools = true;\n\n private genAI: GoogleGenerativeAI | undefined;\n private model = DEFAULT_MODELS['gemini']!;\n private maxTokens = 4096;\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, maxTokens: number): void {\n if (!apiKey) {\n throw new Error(\n 'Google Gemini API key is not configured. Set GEMINI_API_KEY or add geminiApiKey to ~/.vizzor/config.yaml.',\n );\n }\n this.genAI = new GoogleGenerativeAI(apiKey);\n this.model = model;\n this.maxTokens = maxTokens;\n }\n\n // -----------------------------------------------------------------------\n // Non-streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const genAI = this.requireGenAI();\n\n // Build the model instance with system instruction and tools baked in.\n const geminiModel = this.createModel(genAI, systemPrompt, tools);\n\n // Conversation history for multi-turn tool use.\n const history: Content[] = [];\n\n // Start with the user message; subsequent iterations use function responses.\n let currentContents: Content[] = [{ role: 'user', parts: [{ text: userMessage }] }];\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const contents: Content[] = [...history, ...currentContents];\n\n const result = await geminiModel.generateContent({ contents });\n const response = result.response;\n\n const candidateParts = response.candidates?.[0]?.content?.parts;\n const functionCalls = extractFunctionCalls(candidateParts);\n\n // No function calls — return text content.\n if (functionCalls.length === 0) {\n return extractText(candidateParts);\n }\n\n // --- Agentic loop: execute tools and continue the conversation ------\n\n if (!toolHandler) {\n throw new Error('Gemini requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n\n // Append the current contents and model response to the history.\n history.push(...currentContents);\n history.push({ role: 'model', parts: candidateParts ?? [] });\n\n // Execute each function call and build function response parts.\n const functionResponseParts: Part[] = await Promise.all(\n functionCalls.map(async (fc) => {\n try {\n const fnResult = await handler(fc.name, fc.args);\n return {\n functionResponse: {\n name: fc.name,\n response: { result: fnResult },\n },\n } as Part;\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n return {\n functionResponse: {\n name: fc.name,\n response: { error: detail },\n },\n } as Part;\n }\n }),\n );\n\n // Function responses go into history and become the next turn.\n history.push({ role: 'function', parts: functionResponseParts });\n\n // Clear currentContents — next iteration builds from history only.\n currentContents = [];\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Gemini request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n return '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n }\n\n // -----------------------------------------------------------------------\n // Streaming analysis with agentic tool loop\n // -----------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n tools?: AITool[],\n toolHandler?: ToolHandler,\n ): Promise<string> {\n const genAI = this.requireGenAI();\n\n const geminiModel = this.createModel(genAI, systemPrompt, tools);\n\n const history: Content[] = [];\n let fullText = '';\n\n // Start with the user message.\n let currentContents: Content[] = [{ role: 'user', parts: [{ text: userMessage }] }];\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {\n try {\n const contents = [...history, ...currentContents];\n\n const streamResult = await geminiModel.generateContentStream({ contents });\n\n // Accumulate all parts from the streamed chunks.\n const allParts: Part[] = [];\n\n for await (const chunk of streamResult.stream) {\n const text = chunk.text();\n if (text) {\n fullText += text;\n callbacks.onText(text);\n }\n\n // Collect parts for function call detection.\n const candidateParts = chunk.candidates?.[0]?.content?.parts;\n if (candidateParts) {\n allParts.push(...candidateParts);\n }\n }\n\n // Check for function calls in the accumulated parts.\n const functionCalls = extractFunctionCalls(allParts);\n\n // No function calls — we are done.\n if (functionCalls.length === 0) {\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // --- Agentic loop: execute tools and re-stream ----------------------\n\n if (!toolHandler) {\n throw new Error('Gemini requested tool use but no tool handler is registered.');\n }\n\n const handler = toolHandler;\n\n // Append the current contents and model response to history.\n history.push(...currentContents);\n history.push({ role: 'model', parts: allParts });\n\n // Execute function calls.\n const functionResponseParts: Part[] = [];\n for (const fc of functionCalls) {\n callbacks.onToolStart(fc.name);\n try {\n const result = await handler(fc.name, fc.args);\n functionResponseParts.push({\n functionResponse: {\n name: fc.name,\n response: { result },\n },\n } as Part);\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n functionResponseParts.push({\n functionResponse: {\n name: fc.name,\n response: { error: detail },\n },\n } as Part);\n }\n callbacks.onToolEnd(fc.name);\n }\n\n // Function responses become the next turn.\n history.push({ role: 'function', parts: functionResponseParts });\n\n // Clear currentContents — next iteration builds from history only.\n currentContents = [];\n } catch (err: unknown) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`Gemini streaming request failed: ${detail}`, { cause: err });\n }\n }\n\n // Exhausted the iteration limit.\n const exhaustionNotice =\n '[Vizzor] The analysis reached the maximum number of tool-use iterations. Partial results may be incomplete.';\n fullText += fullText.length > 0 ? `\\n\\n${exhaustionNotice}` : exhaustionNotice;\n callbacks.onDone(fullText);\n return fullText;\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private requireGenAI(): GoogleGenerativeAI {\n if (!this.genAI) {\n throw new Error('Gemini provider has not been initialized. Call initialize() first.');\n }\n return this.genAI;\n }\n\n /**\n * Create a GenerativeModel with system instruction, tools, and generation config.\n */\n private createModel(\n genAI: GoogleGenerativeAI,\n systemPrompt: string,\n tools?: AITool[],\n ): GenerativeModel {\n const functionDeclarations =\n tools && tools.length > 0 ? toGeminiFunctionDeclarations(tools) : undefined;\n\n return genAI.getGenerativeModel({\n model: this.model,\n systemInstruction: systemPrompt,\n ...(functionDeclarations ? { tools: [{ functionDeclarations }] } : {}),\n generationConfig: {\n maxOutputTokens: this.maxTokens,\n },\n });\n }\n}\n","// ---------------------------------------------------------------------------\n// Ollama provider — local model integration via ollama npm package\n// ---------------------------------------------------------------------------\n\nimport { Ollama } from 'ollama';\nimport { DEFAULT_MODELS } from './types.js';\nimport type { AIProvider, AITool, StreamCallbacks, ToolHandler } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Assistant prefill — forces the model to start answering instead of refusing.\n// Local models have strong safety filters that trigger on words like \"predict\".\n// By pre-filling the assistant turn, we bypass the refusal mechanism.\n// ---------------------------------------------------------------------------\n\nconst PREDICTION_TRIGGERS = [\n 'predict',\n 'forecast',\n 'price target',\n 'will it go',\n 'future price',\n 'price prediction',\n 'where will',\n 'should i buy',\n 'should i sell',\n 'going to pump',\n];\n\nconst ANALYSIS_TRIGGERS = [\n 'anali',\n 'audit',\n 'scan',\n 'review',\n 'inspect',\n 'check',\n 'risk',\n 'rug',\n 'security',\n 'forensic',\n 'tokenomics',\n];\n\nconst NEWS_TRIGGERS = ['news', 'headlines', 'latest', 'happening', 'update'];\nconst TRENDS_TRIGGERS = ['trending', 'hot', 'popular', 'market', 'overview', 'today', 'right now'];\n\nfunction buildAssistantPrefill(userMessage: string): string {\n const lower = userMessage.toLowerCase();\n const isPrediction = PREDICTION_TRIGGERS.some((t) => lower.includes(t));\n const isAnalysis = ANALYSIS_TRIGGERS.some((t) => lower.includes(t));\n const isNews = NEWS_TRIGGERS.some((t) => lower.includes(t));\n const isTrends = TRENDS_TRIGGERS.some((t) => lower.includes(t));\n\n if (isPrediction) {\n return 'Based on the real-time market data, here is my price analysis and projection:\\n\\n';\n }\n if (isAnalysis) {\n return 'Here is my analysis based on the real-time data:\\n\\n';\n }\n if (isNews) {\n return 'Here is the latest from the crypto markets:\\n\\n';\n }\n if (isTrends) {\n return 'Here is what is happening in the crypto market right now:\\n\\n';\n }\n return '';\n}\n\n/**\n * Reframe the user message to avoid triggering safety filters.\n * \"predict price\" → \"provide data-driven price scenario analysis\"\n * This is needed because local models refuse on \"predict\" as a keyword.\n */\nfunction reframeForSafety(userMessage: string): string {\n let msg = userMessage;\n // Reframe prediction language to analysis language\n msg = msg.replace(\n /\\bpredict(?:ion)?\\s+(?:the\\s+)?price/gi,\n 'provide a data-driven price scenario analysis for',\n );\n msg = msg.replace(/\\bpredict\\b/gi, 'analyze and project');\n msg = msg.replace(/\\bforecast\\b/gi, 'project scenarios for');\n msg = msg.replace(\n /\\bwill it (?:go|pump|dump|moon|crash)\\b/gi,\n 'what are the likely scenarios based on data',\n );\n return msg;\n}\n\n// ---------------------------------------------------------------------------\n// Provider implementation\n// ---------------------------------------------------------------------------\n\nexport class OllamaProvider implements AIProvider {\n readonly name = 'ollama';\n readonly supportsTools = false;\n\n private client!: Ollama;\n private model = DEFAULT_MODELS['ollama']!;\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n initialize(apiKey: string | undefined, model: string, _maxTokens: number): void {\n // apiKey is used as the host URL for Ollama (defaults to http://localhost:11434)\n const host = apiKey || 'http://localhost:11434';\n this.client = new Ollama({ host });\n this.model = model;\n }\n\n // -------------------------------------------------------------------------\n // Non-streaming analysis (no tool use for Ollama)\n // -------------------------------------------------------------------------\n\n async analyze(\n systemPrompt: string,\n userMessage: string,\n _tools?: AITool[],\n _toolHandler?: ToolHandler,\n ): Promise<string> {\n const safeMessage = reframeForSafety(userMessage);\n const prefill = buildAssistantPrefill(userMessage);\n\n const messages: { role: string; content: string }[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: safeMessage },\n ];\n // Only inject assistant prefill when we need to steer the model\n if (prefill) {\n messages.push({ role: 'assistant', content: prefill });\n }\n\n const response = await this.client.chat({\n model: this.model,\n messages,\n });\n\n return prefill + response.message.content;\n }\n\n // -------------------------------------------------------------------------\n // Streaming analysis (no tool use for Ollama)\n // -------------------------------------------------------------------------\n\n async analyzeStream(\n systemPrompt: string,\n userMessage: string,\n callbacks: StreamCallbacks,\n _tools?: AITool[],\n _toolHandler?: ToolHandler,\n ): Promise<string> {\n const safeMessage = reframeForSafety(userMessage);\n const prefill = buildAssistantPrefill(userMessage);\n\n // Emit the prefill text first so the user sees it immediately\n if (prefill) callbacks.onText(prefill);\n\n const messages: { role: string; content: string }[] = [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: safeMessage },\n ];\n if (prefill) {\n messages.push({ role: 'assistant', content: prefill });\n }\n\n const response = await this.client.chat({\n model: this.model,\n messages,\n stream: true,\n });\n\n let fullText = prefill;\n for await (const chunk of response) {\n const text = chunk.message.content;\n if (text) {\n fullText += text;\n callbacks.onText(text);\n }\n }\n\n callbacks.onDone(fullText);\n return fullText;\n }\n}\n","// ---------------------------------------------------------------------------\n// Provider registry — factory + initialisation + availability checking\n// ---------------------------------------------------------------------------\n\nimport type { AIProvider } from './types.js';\nimport type { VizzorConfig } from '../../config/schema.js';\nimport { DEFAULT_MODELS } from './types.js';\nimport { AnthropicProvider } from './anthropic.js';\nimport { OpenAIProvider } from './openai.js';\nimport { GeminiProvider } from './gemini.js';\nimport { OllamaProvider } from './ollama.js';\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a bare (uninitialised) provider instance by name.\n * Call `initialize()` on the returned provider before use.\n */\nexport function createProvider(name: string): AIProvider {\n switch (name) {\n case 'anthropic':\n return new AnthropicProvider();\n case 'openai':\n return new OpenAIProvider();\n case 'gemini':\n return new GeminiProvider();\n case 'ollama':\n return new OllamaProvider();\n default:\n throw new Error(\n `Unknown AI provider \"${name}\". Supported: anthropic, openai, gemini, ollama.`,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Initialisation helper\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a provider, resolves the API key and model from config, calls\n * `initialize()`, and returns a ready-to-use provider instance.\n */\nexport function initializeProvider(name: string, cfg: VizzorConfig): AIProvider {\n const provider = createProvider(name);\n\n const apiKey = getApiKey(name, cfg);\n const model = resolveModel(name, cfg.ai.model);\n const maxTokens = cfg.ai.maxTokens;\n\n provider.initialize(apiKey, model, maxTokens);\n return provider;\n}\n\n// ---------------------------------------------------------------------------\n// Availability checker\n// ---------------------------------------------------------------------------\n\n/**\n * Returns an array describing which providers are available (have keys set)\n * and which are not.\n */\nexport function getAvailableProviders(\n cfg: VizzorConfig,\n): { name: string; available: boolean; reason?: string }[] {\n const providers = ['anthropic', 'openai', 'gemini', 'ollama'] as const;\n\n return providers.map((name) => {\n switch (name) {\n case 'anthropic':\n return cfg.anthropicApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'ANTHROPIC_API_KEY not set' };\n\n case 'openai':\n return cfg.openaiApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'OPENAI_API_KEY not set' };\n\n case 'gemini':\n return cfg.googleApiKey\n ? { name, available: true }\n : { name, available: false, reason: 'GOOGLE_API_KEY not set' };\n\n case 'ollama':\n // Ollama is always \"available\" — it runs locally and doesn't need an API key.\n return { name, available: true };\n\n default:\n return { name, available: false, reason: 'Unknown provider' };\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Pick the right model for the given provider. If the user explicitly set a\n * model in config we only honour it when it looks like it belongs to the\n * target provider — otherwise we fall back to the provider's default.\n * This prevents sending e.g. \"claude-sonnet-4-20250514\" to OpenAI.\n */\nfunction resolveModel(provider: string, configModel: string | undefined): string {\n if (!configModel) {\n return DEFAULT_MODELS[provider] ?? 'unknown';\n }\n\n const prefixes: Record<string, string[]> = {\n anthropic: ['claude'],\n openai: ['gpt', 'o1', 'o3', 'o4', 'chatgpt', 'davinci', 'babbage'],\n gemini: ['gemini', 'models/gemini'],\n ollama: ['llama', 'mistral', 'codellama', 'phi', 'deepseek', 'qwen', 'gemma'],\n };\n\n const expectedPrefixes = prefixes[provider];\n if (!expectedPrefixes) {\n return configModel;\n }\n\n const lower = configModel.toLowerCase();\n const matchesProvider = expectedPrefixes.some((p) => lower.startsWith(p));\n return matchesProvider ? configModel : (DEFAULT_MODELS[provider] ?? configModel);\n}\n\n/**\n * Resolves the correct API key (or host URL) for a given provider from config.\n */\nfunction getApiKey(name: string, cfg: VizzorConfig): string | undefined {\n switch (name) {\n case 'anthropic':\n return cfg.anthropicApiKey;\n case 'openai':\n return cfg.openaiApiKey;\n case 'gemini':\n return cfg.googleApiKey;\n case 'ollama':\n return cfg.ai.ollamaHost;\n default:\n return undefined;\n }\n}\n","// ---------------------------------------------------------------------------\n// GoPlus Security API client — token security checks, no auth required\n// https://docs.gopluslabs.io/\n// Rate limit: ~30 req/min\n// ---------------------------------------------------------------------------\n\nconst BASE_URL = 'https://api.gopluslabs.io/api/v1';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TokenSecurity {\n contractAddress: string;\n chain: string;\n isOpenSource: boolean;\n isProxy: boolean;\n isMintable: boolean;\n canTakeBackOwnership: boolean;\n ownerChangeBalance: boolean;\n hiddenOwner: boolean;\n selfDestruct: boolean;\n externalCall: boolean;\n isHoneypot: boolean;\n buyTax: number;\n sellTax: number;\n cannotBuy: boolean;\n cannotSellAll: boolean;\n slippageModifiable: boolean;\n isBlacklisted: boolean;\n isWhitelisted: boolean;\n antiWhaleModifiable: boolean;\n tradingCooldown: boolean;\n personalSlippageModifiable: boolean;\n holderCount: number;\n lpHolderCount: number;\n totalSupply: string;\n creatorAddress: string;\n creatorPercent: number;\n ownerAddress: string;\n ownerPercent: number;\n lpTotalSupplyPercent: number;\n isInDex: boolean;\n dexInfo: { name: string; liquidity: string; pair: string }[];\n trustList: boolean;\n riskLevel: 'safe' | 'warning' | 'danger';\n}\n\nexport interface AddressSecurity {\n address: string;\n isContract: boolean;\n maliciousAddress: boolean;\n honeypotRelated: boolean;\n phishing: boolean;\n blacklistDoubt: boolean;\n dataSources: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Chain ID mapping\n// ---------------------------------------------------------------------------\n\nconst CHAIN_IDS: Record<string, string> = {\n ethereum: '1',\n bsc: '56',\n polygon: '137',\n arbitrum: '42161',\n optimism: '10',\n base: '8453',\n avalanche: '43114',\n solana: 'solana',\n sui: 'sui',\n aptos: 'aptos',\n ton: 'ton',\n};\n\nfunction resolveChainId(chain: string): string {\n return CHAIN_IDS[chain.toLowerCase()] ?? chain;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`GoPlus API error: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\n/**\n * Check token security for a contract address on a specific chain.\n */\nexport async function checkTokenSecurity(\n contractAddress: string,\n chain: string,\n): Promise<TokenSecurity | null> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, Record<string, unknown>>;\n }>(\n `${BASE_URL}/token_security/${encodeURIComponent(chainId)}?contract_addresses=${encodeURIComponent(contractAddress.toLowerCase())}`,\n );\n\n if (data.code !== 1) return null;\n\n const addr = contractAddress.toLowerCase();\n const raw = data.result[addr];\n if (!raw) return null;\n\n const toBool = (v: unknown): boolean => v === '1' || v === 1 || v === true;\n const toNum = (v: unknown): number => (v != null ? parseFloat(String(v)) : 0);\n\n const buyTax = toNum(raw['buy_tax']);\n const sellTax = toNum(raw['sell_tax']);\n const isHoneypot = toBool(raw['is_honeypot']);\n const isMintable = toBool(raw['is_mintable']);\n\n let riskLevel: TokenSecurity['riskLevel'] = 'safe';\n if (isHoneypot || sellTax > 0.5 || isMintable) {\n riskLevel = 'danger';\n } else if (sellTax > 0.1 || buyTax > 0.1 || toBool(raw['hidden_owner'])) {\n riskLevel = 'warning';\n }\n\n return {\n contractAddress: addr,\n chain,\n isOpenSource: toBool(raw['is_open_source']),\n isProxy: toBool(raw['is_proxy']),\n isMintable,\n canTakeBackOwnership: toBool(raw['can_take_back_ownership']),\n ownerChangeBalance: toBool(raw['owner_change_balance']),\n hiddenOwner: toBool(raw['hidden_owner']),\n selfDestruct: toBool(raw['selfdestruct']),\n externalCall: toBool(raw['external_call']),\n isHoneypot,\n buyTax,\n sellTax,\n cannotBuy: toBool(raw['cannot_buy']),\n cannotSellAll: toBool(raw['cannot_sell_all']),\n slippageModifiable: toBool(raw['slippage_modifiable']),\n isBlacklisted: toBool(raw['is_blacklisted']),\n isWhitelisted: toBool(raw['is_whitelisted']),\n antiWhaleModifiable: toBool(raw['anti_whale_modifiable']),\n tradingCooldown: toBool(raw['trading_cooldown']),\n personalSlippageModifiable: toBool(raw['personal_slippage_modifiable']),\n holderCount: toNum(raw['holder_count']),\n lpHolderCount: toNum(raw['lp_holder_count']),\n totalSupply: String(raw['total_supply'] ?? '0'),\n creatorAddress: String(raw['creator_address'] ?? ''),\n creatorPercent: toNum(raw['creator_percent']),\n ownerAddress: String(raw['owner_address'] ?? ''),\n ownerPercent: toNum(raw['owner_percent']),\n lpTotalSupplyPercent: toNum(raw['lp_total_supply_percent']),\n isInDex: toBool(raw['is_in_dex']),\n dexInfo: Array.isArray(raw['dex'])\n ? (raw['dex'] as { name: string; liquidity: string; pair: string }[])\n : [],\n trustList: toBool(raw['trust_list']),\n riskLevel,\n };\n}\n\n/**\n * Check if an address is associated with malicious activity.\n */\nexport async function checkAddressSecurity(\n address: string,\n chain: string,\n): Promise<AddressSecurity | null> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, unknown>;\n }>(\n `${BASE_URL}/address_security/${encodeURIComponent(chainId)}?address=${encodeURIComponent(address.toLowerCase())}`,\n );\n\n if (data.code !== 1) return null;\n const raw = data.result;\n\n const toBool = (v: unknown): boolean => v === '1' || v === 1 || v === true;\n\n return {\n address: address.toLowerCase(),\n isContract: toBool(raw['contract_address']),\n maliciousAddress: toBool(raw['malicious_address']),\n honeypotRelated: toBool(raw['honeypot_related_address']),\n phishing: toBool(raw['phishing_activities']),\n blacklistDoubt: toBool(raw['blacklist_doubt']),\n dataSources: Array.isArray(raw['data_source']) ? (raw['data_source'] as string[]) : [],\n };\n}\n\n/**\n * Check token approval security for an address.\n */\nexport async function checkApprovalSecurity(\n contractAddress: string,\n chain: string,\n): Promise<{ isApprovalAbuse: boolean; approvalRisk: string }> {\n const chainId = resolveChainId(chain);\n const data = await fetchJson<{\n code: number;\n result: Record<string, unknown>;\n }>(\n `${BASE_URL}/approval_security/${encodeURIComponent(chainId)}?contract_addresses=${encodeURIComponent(contractAddress.toLowerCase())}`,\n );\n\n if (data.code !== 1) {\n return { isApprovalAbuse: false, approvalRisk: 'unknown' };\n }\n\n const raw = data.result;\n return {\n isApprovalAbuse: raw['is_approval_abuse'] === '1',\n approvalRisk: String(raw['approval_risk'] ?? 'none'),\n };\n}\n","// ---------------------------------------------------------------------------\n// Sanitization utilities for AI prompt injection defense\n// ---------------------------------------------------------------------------\n\n/**\n * Patterns that could be used for prompt injection via external data\n * (token names, news headlines, project descriptions, etc.)\n */\nconst INJECTION_PATTERNS = [\n /ignore\\s+(all\\s+)?previous\\s+instructions/gi,\n /ignore\\s+(all\\s+)?above/gi,\n /you\\s+are\\s+now/gi,\n /system\\s*:/gi,\n /assistant\\s*:/gi,\n /\\[system\\]/gi,\n /\\[instruction\\]/gi,\n /<\\/?system>/gi,\n /repeat\\s+(everything|the\\s+prompt|your\\s+instructions)/gi,\n /reveal\\s+(your|the)\\s+(prompt|instructions|config)/gi,\n /forget\\s+(everything|your\\s+instructions)/gi,\n /override\\s+(previous|your|all)/gi,\n /new\\s+instructions?\\s*:/gi,\n /\\bdo\\s+not\\s+follow\\b/gi,\n /\\bact\\s+as\\b/gi,\n /\\brole\\s*:\\s*(system|assistant)\\b/gi,\n];\n\n/**\n * Maximum lengths for external data fields to prevent abuse.\n */\nconst LIMITS = {\n tokenName: 60,\n headline: 250,\n description: 500,\n generic: 1000,\n} as const;\n\n/**\n * Sanitize external data before injecting into AI prompts.\n * Strips injection patterns and truncates to safe lengths.\n */\nexport function sanitizeExternalData(text: string, maxLen: number = LIMITS.generic): string {\n let cleaned = text;\n\n // Strip injection patterns\n for (const pattern of INJECTION_PATTERNS) {\n cleaned = cleaned.replace(pattern, '[FILTERED]');\n }\n\n // Strip markdown headers that could trick model\n cleaned = cleaned.replace(/^#{1,6}\\s+/gm, '');\n\n // Strip code fences\n cleaned = cleaned.replace(/```[\\s\\S]*?```/g, '[CODE]');\n\n // Truncate\n if (cleaned.length > maxLen) {\n cleaned = cleaned.slice(0, maxLen) + '...';\n }\n\n return cleaned;\n}\n\n/**\n * Sanitize a token name from external APIs (DEX, CoinGecko, etc.)\n */\nexport function sanitizeTokenName(name: string): string {\n return sanitizeExternalData(name, LIMITS.tokenName);\n}\n\n/**\n * Sanitize a news headline from CryptoPanic or similar.\n */\nexport function sanitizeHeadline(headline: string): string {\n return sanitizeExternalData(headline, LIMITS.headline);\n}\n\n/**\n * Wrap a block of external data with untrusted markers.\n * This tells the AI model to treat the content as data, not instructions.\n */\nexport function wrapUntrustedData(label: string, data: string): string {\n return `[BEGIN EXTERNAL DATA: ${label}]\\n${data}\\n[END EXTERNAL DATA: ${label}]`;\n}\n\n/**\n * Sanitize tool results before returning to AI in the agentic loop.\n * Recursively sanitizes string values in objects/arrays.\n */\nexport function sanitizeToolResult(result: unknown): unknown {\n if (typeof result === 'string') {\n return sanitizeExternalData(result);\n }\n if (Array.isArray(result)) {\n return result.map(sanitizeToolResult);\n }\n if (result !== null && typeof result === 'object') {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(result as Record<string, unknown>)) {\n sanitized[key] = sanitizeToolResult(value);\n }\n return sanitized;\n }\n return result;\n}\n","// ---------------------------------------------------------------------------\n// Context injector — pre-fetches real-time data for providers without tool use\n// (e.g. Ollama). Injects data as context into the system prompt so the AI\n// can answer with current information instead of stale training data.\n// ---------------------------------------------------------------------------\n\nimport { fetchMarketData, fetchTokenFromDex, fetchTrendingTokens } from '../core/trends/market.js';\nimport { fetchCryptoNews } from '../data/sources/cryptopanic.js';\nimport { fetchRecentRaises } from '../data/sources/defillama.js';\nimport { fetchLatestCoins } from '../data/sources/pumpfun.js';\nimport { fetchTickerPrice, fetchFundingRate, fetchOpenInterest } from '../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { checkTokenSecurity, checkAddressSecurity } from '../data/sources/goplus.js';\nimport { getConfig } from '../config/loader.js';\nimport { KNOWN_SYMBOLS } from '../config/constants.js';\nimport { getMLClient } from '../ml/client.js';\nimport {\n sanitizeExternalData,\n sanitizeTokenName,\n sanitizeHeadline,\n wrapUntrustedData,\n} from './sanitize.js';\n\n// ---------------------------------------------------------------------------\n// Keyword patterns for detecting user intent\n// ---------------------------------------------------------------------------\n\nconst PRICE_KEYWORDS = ['price', 'worth', 'cost', 'value', 'how much'];\nconst TRENDING_KEYWORDS = ['trending', 'hot', 'popular', 'top', 'best', 'hype'];\nconst NEWS_KEYWORDS = ['news', 'latest', 'update', 'happening', 'announcement'];\nconst RAISES_KEYWORDS = [\n 'ico',\n 'ido',\n 'launch',\n 'raise',\n 'funding',\n 'fundrais',\n 'invest',\n 'new project',\n];\nconst PUMP_KEYWORDS = ['pump', 'meme', 'solana launch', 'pump.fun', 'degen'];\nconst ANALYSIS_KEYWORDS = [\n 'anali', // analyze, analysis, analize (typo-tolerant)\n 'audit',\n 'scan',\n 'tokenomics',\n 'rug',\n 'security',\n 'forensic',\n 'contract',\n 'check',\n 'review',\n 'inspect',\n 'investigate',\n 'deep dive',\n 'full report',\n 'due diligence',\n];\nconst COMPLEX_KEYWORDS = [\n 'predict',\n 'prediction',\n 'forecast',\n 'will it',\n 'going to',\n 'should i buy',\n 'should i sell',\n 'compare',\n 'vs',\n 'versus',\n 'portfolio',\n 'allocat',\n 'diversif',\n 'strategy',\n 'risk',\n 'hedge',\n 'long term',\n 'short term',\n 'entry',\n 'exit',\n 'target',\n 'when to',\n 'best time',\n 'opportunity',\n 'undervalued',\n 'overvalued',\n];\nconst BROAD_KEYWORDS = [\n \"what's happening\",\n 'whats happening',\n 'market',\n 'overview',\n 'summary',\n 'up to date',\n 'up-to-date',\n 'current',\n 'right now',\n 'today',\n '2025',\n '2026',\n 'lately',\n 'recently',\n 'this week',\n 'this month',\n 'general',\n 'everything',\n 'outlook',\n 'sentiment',\n 'macro',\n 'state of',\n 'tell me about crypto',\n 'crypto market',\n];\n\n// KNOWN_SYMBOLS is now imported from config/constants.ts\n\n// ---------------------------------------------------------------------------\n// Main function\n// ---------------------------------------------------------------------------\n\n/**\n * Build a context block with real-time data based on the user's message.\n * Returns a string to prepend to the system prompt, or empty string if\n * no relevant data was found.\n */\nexport async function buildContextBlock(userMessage: string): Promise<string> {\n const lower = userMessage.toLowerCase();\n const sections: string[] = [];\n\n // ML: try intent classification for improved query routing\n let mlIntent: string | null = null;\n const mlClientForIntent = getMLClient();\n if (mlClientForIntent) {\n try {\n const intentResult = await mlClientForIntent.classifyIntent(userMessage);\n if (intentResult && intentResult.confidence > 0.7) {\n mlIntent = intentResult.intent;\n }\n } catch {\n // ML unavailable — fall through to keyword matching\n }\n }\n\n // Detect addresses (EVM 0x... and Solana base58)\n const evmMatch = userMessage.match(/0x[a-fA-F0-9]{40}/);\n // Solana base58: 32-44 chars, must contain at least one digit to avoid matching English words\n const solanaMatch = userMessage.match(/\\b([1-9A-HJ-NP-Za-km-z]{32,44})\\b/);\n const isSolanaAddr =\n solanaMatch && !evmMatch && /\\d/.test(solanaMatch[1]!) && solanaMatch[1]!.length >= 32;\n const addressMatch = evmMatch ?? (isSolanaAddr ? solanaMatch : null);\n const detectedChain = evmMatch ? null : isSolanaAddr ? 'solana' : null;\n\n // Detect token mentions (known + unknown)\n const mentionedTokens = detectTokens(lower);\n const unknownTokens = detectUnknownTokens(userMessage, mentionedTokens);\n const isAnalysisQuery = matchesAny(lower, ANALYSIS_KEYWORDS) || mlIntent === 'analysis';\n\n // Run relevant fetches in parallel\n const tasks: Promise<void>[] = [];\n\n // 1. Price / token data (known tokens)\n if (mentionedTokens.length > 0 || addressMatch || matchesAny(lower, PRICE_KEYWORDS)) {\n tasks.push(\n fetchTokenData(mentionedTokens, addressMatch?.[0]).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 1b. Search DexScreener for unknown tokens (not in KNOWN_SYMBOLS)\n // If analysis intent, also run GoPlus security + protocol lookup\n if (\n unknownTokens.length > 0 ||\n (isAnalysisQuery && mentionedTokens.length === 0 && !addressMatch)\n ) {\n const searchTokens = unknownTokens.length > 0 ? unknownTokens : [];\n // Also try to extract the subject of analysis from the message\n if (searchTokens.length === 0 && isAnalysisQuery) {\n const verbMatch = lower.match(\n /(?:anali[zs]e|audit|scan|check|review|inspect)\\s+([a-z0-9]+)/i,\n );\n if (verbMatch) searchTokens.push(verbMatch[1]!);\n }\n for (const token of searchTokens.slice(0, 3)) {\n tasks.push(\n fetchDexAndSecurityData(token, isAnalysisQuery).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // 1c. If address provided + analysis intent, run GoPlus security + address check\n if (addressMatch && isAnalysisQuery) {\n const chain = detectedChain || getConfig().defaultChain || 'ethereum';\n tasks.push(\n fetchSecurityData(addressMatch[0], chain).then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchAddressSecurityData(addressMatch[0], chain).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 2. Trending\n if (matchesAny(lower, TRENDING_KEYWORDS)) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 3. News\n if (matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 4. Raises / ICOs\n if (matchesAny(lower, RAISES_KEYWORDS)) {\n tasks.push(\n fetchRaisesData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 5. Pump.fun / meme coins\n if (matchesAny(lower, PUMP_KEYWORDS)) {\n tasks.push(\n fetchPumpData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // 6. Broad / general query — fetch everything for a full picture\n // BUT skip the broad dump when a specific token is mentioned (e.g. \"bitcoin today\"\n // should focus on Bitcoin, not dump trending meme coins and fundraising rounds).\n const isBroadQuery = matchesAny(lower, BROAD_KEYWORDS) || mlIntent === 'broad_overview';\n const hasSpecificIntent =\n mentionedTokens.length > 0 || unknownTokens.length > 0 || !!addressMatch;\n if (isBroadQuery && !hasSpecificIntent) {\n // Inject trending if not already queued\n if (!matchesAny(lower, TRENDING_KEYWORDS)) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject news if not already queued\n if (!matchesAny(lower, NEWS_KEYWORDS)) {\n tasks.push(\n fetchNewsData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject raises if not already queued\n if (!matchesAny(lower, RAISES_KEYWORDS)) {\n tasks.push(\n fetchRaisesData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n // Inject top 3 market data if not already queued\n if (!matchesAny(lower, PRICE_KEYWORDS)) {\n tasks.push(\n fetchTokenData(['bitcoin', 'ethereum', 'solana']).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n } else if (isBroadQuery && hasSpecificIntent) {\n // Token-specific broad query (e.g. \"bitcoin today\") — only fetch token-relevant news\n if (!matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase() || unknownTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // If no specific intent detected, try to fetch market data for any mentioned tokens\n if (tasks.length === 0 && mentionedTokens.length > 0) {\n tasks.push(\n fetchTokenData(mentionedTokens).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // If no known tokens but unknown ones detected, search DexScreener\n if (tasks.length === 0 && unknownTokens.length > 0) {\n for (const token of unknownTokens.slice(0, 3)) {\n tasks.push(\n fetchDexAndSecurityData(token, false).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n }\n\n // If still no tasks, inject baseline context (trending + news) so Ollama never hallucinates\n if (tasks.length === 0) {\n tasks.push(\n fetchTrendingData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchNewsData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // Always inject market sentiment (Fear & Greed) + top-3 Binance prices for baseline accuracy\n tasks.push(\n fetchFearGreedData().then((data) => {\n if (data) sections.push(data);\n }),\n );\n tasks.push(\n fetchBinancePriceData(['BTC', 'ETH', 'SOL']).then((data) => {\n if (data) sections.push(data);\n }),\n );\n\n // Inject derivatives data for broad, price, or analysis queries\n if (\n isBroadQuery ||\n matchesAny(lower, PRICE_KEYWORDS) ||\n mentionedTokens.length > 0 ||\n isAnalysisQuery\n ) {\n const derivTokens = mentionedTokens.length > 0 ? mentionedTokens : unknownTokens;\n tasks.push(\n fetchDerivativesData(derivTokens).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n // For analysis queries, also fetch news if not already queued\n if (isAnalysisQuery && !matchesAny(lower, NEWS_KEYWORDS)) {\n const symbol = mentionedTokens[0]?.toUpperCase() || unknownTokens[0]?.toUpperCase();\n tasks.push(\n fetchNewsData(symbol).then((data) => {\n if (data) sections.push(data);\n }),\n );\n }\n\n await Promise.allSettled(tasks);\n\n if (sections.length === 0) return '';\n\n // ---------------------------------------------------------------------------\n // Classify query type — determines what data/instructions to inject\n // ---------------------------------------------------------------------------\n const allTokens = [...mentionedTokens, ...unknownTokens];\n const hasSpecificToken = allTokens.length > 0 || !!addressMatch;\n const isNewsQuery = matchesAny(lower, NEWS_KEYWORDS);\n const isTrendsQuery = matchesAny(lower, TRENDING_KEYWORDS);\n const isPredictionQuery = matchesAny(lower, COMPLEX_KEYWORDS);\n const isComplexQuery = isPredictionQuery;\n\n type QueryType = 'token_analysis' | 'prediction' | 'news' | 'trends' | 'general';\n let queryType: QueryType;\n\n if (hasSpecificToken && (isAnalysisQuery || isPredictionQuery)) {\n queryType = isPredictionQuery ? 'prediction' : 'token_analysis';\n } else if (isNewsQuery) {\n queryType = 'news';\n } else if (isTrendsQuery || isBroadQuery) {\n queryType = 'trends';\n } else if (hasSpecificToken) {\n queryType = 'token_analysis';\n } else {\n queryType = 'general';\n }\n\n // ---------------------------------------------------------------------------\n // Build output — only inject what's relevant to the query type\n // ---------------------------------------------------------------------------\n const output: string[] = [\n '',\n `CURRENT DATE: ${new Date().toISOString().split('T')[0]} (data fetched just now)`,\n '--- REAL-TIME DATA (fetched just now) ---',\n ...sections,\n '--- END REAL-TIME DATA ---',\n '',\n ];\n\n // Only inject signals, price targets, and analysis report for TOKEN-SPECIFIC queries\n if (hasSpecificToken) {\n const dataSummary = buildDataSummary(sections, allTokens);\n const signals = computeSignals(sections, allTokens, userMessage);\n const report = buildAnalysisReport(sections, allTokens, signals);\n\n output.push(dataSummary, '');\n if (signals) output.push(signals, '');\n if (report) output.push(report, '');\n }\n\n // Inject query-type-specific instructions\n output.push(...buildInstructions(queryType, hasSpecificToken, isComplexQuery));\n output.push('');\n\n const raw = output.join('\\n');\n return wrapUntrustedData('MARKET_CONTEXT', raw);\n}\n\n// ---------------------------------------------------------------------------\n// Query-type-aware instructions\n// ---------------------------------------------------------------------------\n\nfunction buildInstructions(\n queryType: string,\n hasSpecificToken: boolean,\n isComplexQuery: boolean,\n): string[] {\n const base: string[] = [\n 'CRITICAL INSTRUCTIONS (MUST FOLLOW):',\n '- NEVER output \"--- REAL-TIME DATA ---\" or \"--- END REAL-TIME DATA ---\" markers.',\n '- You MUST use ONLY the real-time data above. Do NOT invent or fabricate any data.',\n '- Your training data is STALE. The ONLY trustworthy data is between the markers above.',\n '- Cite sources: (DexScreener), (Binance), (GoPlus), (CoinGecko), (Fear & Greed Index).',\n ];\n\n switch (queryType) {\n case 'news':\n base.push(\n '',\n 'QUERY TYPE: NEWS — The user wants crypto news and market updates.',\n '- Summarize the news headlines from the data above.',\n '- Add market context: mention BTC/ETH prices and Fear & Greed sentiment.',\n '- Group news by theme if possible (regulation, DeFi, NFT, major coins, etc.).',\n '- Do NOT analyze a specific token unless the user mentioned one.',\n '- Keep it conversational and informative.',\n );\n break;\n\n case 'trends':\n base.push(\n '',\n 'QUERY TYPE: TRENDS/MARKET OVERVIEW — The user wants to know what is trending.',\n '- Lead with the overall market sentiment (Fear & Greed + BTC direction).',\n '- List the top trending tokens with key metrics (price, 24h change, volume).',\n '- Mention notable movers (biggest gainers/losers).',\n '- Add fundraising rounds if available.',\n '- Do NOT do a deep dive into any single token unless specifically asked.',\n );\n break;\n\n case 'token_analysis':\n base.push(\n '',\n 'QUERY TYPE: TOKEN ANALYSIS — The user wants deep analysis of a specific token.',\n '- Follow the analysis report structure above (Verdict → Market → Security → Signals → Risks).',\n '- Include price prediction scenarios with actual dollar values if available.',\n '- Present GoPlus security findings if available.',\n '- Do NOT list unrelated trending tokens.',\n '- Missing data IS a finding worth reporting.',\n );\n break;\n\n case 'prediction':\n base.push(\n '',\n 'QUERY TYPE: PRICE PREDICTION — The user wants future price projections.',\n '- ALWAYS include the PRICE PREDICTION SCENARIOS with the exact dollar values from the data.',\n '- If USER-REQUESTED TIMEFRAME exists, present it FIRST and prominently.',\n '- Present ALL timeframes: scalping (5min/15min/1h/4h), short-term (1d/7d), medium (2w/1mo), long (3mo).',\n '- Include the composite signal direction and confidence level.',\n '- Mention key support/resistance levels.',\n '- State what would invalidate the prediction.',\n '- Do NOT list unrelated trending tokens.',\n );\n break;\n\n default: // 'general'\n base.push(\n '',\n 'QUERY TYPE: GENERAL — Answer naturally using the data above as context.',\n '- Use the real-time prices and sentiment as background context.',\n \"- Answer the user's actual question directly.\",\n \"- Do NOT force a token analysis if the user didn't ask for one.\",\n '- Keep your response natural and conversational.',\n );\n break;\n }\n\n if (isComplexQuery && hasSpecificToken) {\n base.push(\n '',\n 'COMPLEX ANALYSIS: Structure your reasoning as Data → Signals → Alignment → Confidence → Risks → Conclusion.',\n );\n }\n\n return base;\n}\n\n// ---------------------------------------------------------------------------\n// Data fetchers\n// ---------------------------------------------------------------------------\n\nasync function fetchTokenData(tokens: string[], address?: string): Promise<string | null> {\n const lines: string[] = ['## Token / Price Data'];\n\n // Fetch by address via DexScreener\n if (address) {\n try {\n const pairs = await fetchTokenFromDex(address);\n const pair = pairs[0];\n if (pair) {\n lines.push(\n `${sanitizeTokenName(pair.baseToken.name)} (${sanitizeTokenName(pair.baseToken.symbol)}) on ${pair.chainId}:`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` Liquidity: $${(pair.liquidity?.usd ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n ` 24h Txns: ${pair.txns?.h24?.buys ?? 0} buys / ${pair.txns?.h24?.sells ?? 0} sells`,\n ` Market Cap: $${(pair.marketCap ?? pair.fdv ?? 0).toLocaleString()}`,\n ` DEX: ${pair.dexId} | Pair: ${pair.pairAddress}`,\n '',\n );\n }\n } catch {\n // skip\n }\n }\n\n // Fetch named tokens: Binance (primary) -> CoinGecko (fallback) -> DexScreener (fallback)\n for (const token of tokens.slice(0, 3)) {\n const sym =\n token === 'bitcoin'\n ? 'BTC'\n : token === 'ethereum'\n ? 'ETH'\n : token === 'solana'\n ? 'SOL'\n : token.toUpperCase();\n\n // Try Binance first (most reliable, no rate limits)\n try {\n const binanceData = await fetchTickerPrice(sym);\n if (binanceData) {\n lines.push(\n `${sym} (via Binance):`,\n ` Price: $${binanceData.price.toLocaleString()}`,\n ` 24h Change: ${binanceData.change24h > 0 ? '+' : ''}${binanceData.change24h.toFixed(2)}%`,\n );\n // Also try CoinGecko for extended data (market cap, rank, 7d)\n const geckoId = KNOWN_SYMBOLS[token];\n if (geckoId) {\n try {\n const gecko = await fetchMarketData(geckoId);\n if (gecko) {\n lines.push(\n ` 7d Change: ${gecko.priceChange7d > 0 ? '+' : ''}${gecko.priceChange7d.toFixed(2)}%`,\n ` 24h Volume: $${gecko.volume24h.toLocaleString()}`,\n ` Market Cap: $${gecko.marketCap.toLocaleString()}`,\n ` Rank: #${gecko.rank ?? '?'}`,\n );\n }\n } catch {\n // CoinGecko unavailable, continue with Binance data only\n }\n }\n lines.push('');\n continue;\n }\n } catch {\n // Binance unavailable, fall through\n }\n\n // Fallback to CoinGecko\n const geckoId = KNOWN_SYMBOLS[token];\n if (geckoId) {\n try {\n const data = await fetchMarketData(geckoId);\n if (data) {\n lines.push(\n `${data.name} (${data.symbol}):`,\n ` Price: $${data.price.toLocaleString()}`,\n ` 24h Change: ${data.priceChange24h > 0 ? '+' : ''}${data.priceChange24h.toFixed(2)}%`,\n ` 7d Change: ${data.priceChange7d > 0 ? '+' : ''}${data.priceChange7d.toFixed(2)}%`,\n ` 24h Volume: $${data.volume24h.toLocaleString()}`,\n ` Market Cap: $${data.marketCap.toLocaleString()}`,\n ` Rank: #${data.rank ?? '?'}`,\n '',\n );\n continue;\n }\n } catch {\n // fall through to DexScreener\n }\n }\n\n // Final fallback: DexScreener for tokens not on Binance/CoinGecko\n try {\n const pairs = await fetchTokenFromDex(token);\n const pair = pairs[0];\n if (pair) {\n lines.push(\n `${sanitizeTokenName(pair.baseToken.name)} (${sanitizeTokenName(pair.baseToken.symbol)}) on ${pair.chainId}:`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n '',\n );\n }\n } catch {\n // skip\n }\n }\n\n return lines.length > 1 ? lines.join('\\n') : null;\n}\n\nasync function fetchTrendingData(): Promise<string | null> {\n try {\n const trending = await fetchTrendingTokens();\n if (trending.length === 0) return null;\n\n const lines = ['## Trending Tokens (live)'];\n for (const t of trending.slice(0, 10)) {\n lines.push(\n `- ${sanitizeTokenName(t.name)} (${sanitizeTokenName(t.symbol)}) on ${t.chain}: $${t.priceUsd} | 24h: ${t.priceChange24h > 0 ? '+' : ''}${t.priceChange24h.toFixed(1)}% | Vol: $${t.volume24h.toLocaleString()} [${t.source}]`,\n );\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchNewsData(symbol?: string): Promise<string | null> {\n try {\n const news = await fetchCryptoNews(symbol, getConfig().cryptopanicApiKey);\n if (news.length > 0) {\n const headlines = news.slice(0, 8);\n const lines = [`## Latest Crypto News${symbol ? ` (${symbol})` : ''}`];\n\n // ML: enhance sentiment labels with ML NLP analysis\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const texts = headlines.map((n) => n.title);\n const mlResults = await mlClient.analyzeSentimentBatch(texts);\n if (mlResults.length > 0) {\n for (let i = 0; i < headlines.length; i++) {\n const n = headlines[i]!;\n const ml = mlResults[i];\n const label = ml\n ? `${ml.sentiment.toUpperCase()} (${(ml.confidence * 100).toFixed(0)}%)`\n : n.sentiment.toUpperCase();\n lines.push(\n `- [${label}] ${sanitizeHeadline(n.title)} (${sanitizeTokenName(n.source.title)}, ${n.publishedAt})`,\n );\n }\n // Aggregate ML sentiment score\n const avgScore = mlResults.reduce((s, r) => s + r.score, 0) / mlResults.length;\n const avgSentiment =\n avgScore > 0.2 ? 'BULLISH' : avgScore < -0.2 ? 'BEARISH' : 'NEUTRAL';\n lines.push(`\\nML Aggregate Sentiment: ${avgSentiment} (score: ${avgScore.toFixed(3)})`);\n return lines.join('\\n');\n }\n } catch {\n // ML unavailable — fall through to rule-based labels\n }\n }\n\n // Fallback: use CryptoPanic sentiment labels\n for (const n of headlines) {\n lines.push(\n `- [${n.sentiment.toUpperCase()}] ${sanitizeHeadline(n.title)} (${sanitizeTokenName(n.source.title)}, ${n.publishedAt})`,\n );\n }\n return lines.join('\\n');\n }\n } catch {\n // CryptoPanic unavailable, fall through to free fallback\n }\n\n // Free fallback: fetch headlines from Google News RSS (no API key needed)\n try {\n const query = symbol ? `${symbol}+crypto` : 'cryptocurrency+bitcoin';\n const rssUrl = `https://news.google.com/rss/search?q=${query}&hl=en&gl=US&ceid=US:en`;\n const res = await fetch(rssUrl);\n if (!res.ok) return null;\n\n const xml = await res.text();\n // Simple XML title extraction — no parser needed\n const items: string[] = [];\n const itemRegex =\n /<item>[\\s\\S]*?<title>([\\s\\S]*?)<\\/title>[\\s\\S]*?<pubDate>([\\s\\S]*?)<\\/pubDate>[\\s\\S]*?<\\/item>/g;\n let match;\n while ((match = itemRegex.exec(xml)) !== null && items.length < 8) {\n const title = match[1]!.replace(/<!\\[CDATA\\[|\\]\\]>/g, '').trim();\n const date = match[2]!.trim();\n items.push(`- ${title} (${date})`);\n }\n\n if (items.length > 0) {\n return [\n `## Latest Crypto News${symbol ? ` (${symbol})` : ''} (via Google News)`,\n ...items,\n ].join('\\n');\n }\n } catch {\n // Google News also unavailable\n }\n\n return null;\n}\n\nasync function fetchRaisesData(): Promise<string | null> {\n try {\n const raises = await fetchRecentRaises(30);\n if (raises.length === 0) return null;\n\n const lines = ['## Recent Crypto Fundraising Rounds (last 30 days)'];\n for (const r of raises.slice(0, 10)) {\n const amount = r.amount\n ? r.amount >= 1e9\n ? `$${(r.amount / 1e9).toFixed(1)}B`\n : r.amount >= 1e6\n ? `$${(r.amount / 1e6).toFixed(1)}M`\n : r.amount >= 1e3\n ? `$${(r.amount / 1e3).toFixed(0)}K`\n : `$${r.amount.toLocaleString()}`\n : 'undisclosed';\n const date = new Date(r.date * 1000).toISOString().split('T')[0];\n lines.push(\n `- ${sanitizeTokenName(r.name)} — ${sanitizeExternalData(r.round, 50)} (${amount}) on ${r.chains.join(', ') || 'multi-chain'} [${date}]${r.leadInvestors.length > 0 ? ` Led by: ${r.leadInvestors.map((inv) => sanitizeTokenName(inv)).join(', ')}` : ''}`,\n );\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchPumpData(): Promise<string | null> {\n try {\n const coins = await fetchLatestCoins(10);\n if (coins.length === 0) return null;\n\n const lines = ['## Latest Pump.fun Launches (Solana)'];\n for (const c of coins) {\n const mcap = c.usd_market_cap ? `$${c.usd_market_cap.toFixed(0)}` : '?';\n lines.push(\n `- ${sanitizeTokenName(c.name)} (${sanitizeTokenName(c.symbol)}) — MC: ${mcap} | Replies: ${c.reply_count}`,\n );\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// New data fetchers (Binance, Fear & Greed, Derivatives)\n// ---------------------------------------------------------------------------\n\n/**\n * Search DexScreener for a token, then run GoPlus security scan + protocol lookup\n * on the first result. This gives deep analysis for ANY token, including meme coins.\n */\nasync function fetchDexAndSecurityData(\n query: string,\n runSecurity: boolean,\n): Promise<string | null> {\n try {\n const pairs = await fetchTokenFromDex(query);\n if (!pairs || pairs.length === 0) {\n return `## DEX Search: \"${query.toUpperCase()}\"\\nToken NOT FOUND on any DEX (DexScreener). It may be too new, delisted, misspelled, or not yet listed. Try searching by contract address instead.`;\n }\n\n const lines = [`## DEX Data: ${query.toUpperCase()} (via DexScreener, live)`];\n const topPair = pairs[0]!;\n\n // Show top 3 pairs with enriched data\n for (const pair of pairs.slice(0, 3)) {\n const age = pair.pairCreatedAt\n ? `${Math.floor((Date.now() - pair.pairCreatedAt) / 86400000)}d ago`\n : 'unknown';\n lines.push(\n `${pair.baseToken.name} (${pair.baseToken.symbol}) on ${pair.chainId}/${pair.dexId}:`,\n ` Contract: ${pair.baseToken.address}`,\n ` Price: $${pair.priceUsd ?? '?'}`,\n ` 24h Volume: $${(pair.volume?.h24 ?? 0).toLocaleString()}`,\n ` 1h Volume: $${(pair.volume?.h1 ?? 0).toLocaleString()}`,\n ` Liquidity: $${(pair.liquidity?.usd ?? 0).toLocaleString()}`,\n ` 24h Change: ${(pair.priceChange?.h24 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h24 ?? 0).toFixed(2)}%`,\n ` 1h Change: ${(pair.priceChange?.h1 ?? 0) > 0 ? '+' : ''}${(pair.priceChange?.h1 ?? 0).toFixed(2)}%`,\n ` 24h Txns: ${pair.txns?.h24?.buys ?? 0} buys / ${pair.txns?.h24?.sells ?? 0} sells`,\n ` 1h Txns: ${pair.txns?.h1?.buys ?? 0} buys / ${pair.txns?.h1?.sells ?? 0} sells`,\n ` Market Cap: $${(pair.marketCap ?? pair.fdv ?? 0).toLocaleString()}`,\n ` FDV: $${(pair.fdv ?? 0).toLocaleString()}`,\n ` Pair Created: ${age}`,\n ` Pair: ${pair.pairAddress}`,\n );\n // Add social/website info if available\n if (pair.info?.websites?.length) {\n lines.push(` Websites: ${pair.info.websites.map((w) => w.url).join(', ')}`);\n }\n if (pair.info?.socials?.length) {\n lines.push(` Socials: ${pair.info.socials.map((s) => `${s.type}: ${s.url}`).join(', ')}`);\n }\n if (pair.labels?.length) {\n lines.push(` Labels: ${pair.labels.join(', ')}`);\n }\n lines.push('');\n }\n if (pairs.length > 3) {\n lines.push(` ... and ${pairs.length - 3} more pairs found`);\n }\n\n // Run GoPlus security scan on the top pair's contract (parallel)\n if (runSecurity && topPair.baseToken.address) {\n const securityData = await fetchSecurityData(topPair.baseToken.address, topPair.chainId);\n if (securityData) lines.push('', securityData);\n }\n\n // Check if it's a Solana token on pump.fun — get creator info\n if (topPair.chainId === 'solana' && topPair.dexId?.includes('pump')) {\n try {\n const { getCoinDetails } = await import('../data/sources/pumpfun.js');\n const coin = await getCoinDetails(topPair.baseToken.address);\n if (coin) {\n lines.push(\n '',\n `## Pump.fun Data (Solana, live)`,\n ` Creator: ${coin.creator}`,\n ` Description: ${coin.description || 'none'}`,\n ` Market Cap (SOL): ${coin.market_cap?.toFixed(2) ?? '?'}`,\n ` USD Market Cap: $${coin.usd_market_cap?.toLocaleString() ?? '?'}`,\n ` Community Replies: ${coin.reply_count}`,\n ` Created: ${new Date(coin.created_timestamp).toISOString()}`,\n ` NSFW: ${coin.nsfw ? 'YES' : 'no'}`,\n );\n }\n } catch {\n // Pump.fun data unavailable, continue\n }\n }\n\n return lines.join('\\n');\n } catch {\n return `## DEX Search: \"${query.toUpperCase()}\"\\nDexScreener search failed. Token data unavailable.`;\n }\n}\n\n/**\n * Run GoPlus security scan for a contract address on a specific chain.\n * Returns formatted security findings. Works for all GoPlus-supported chains:\n * ethereum, bsc, polygon, arbitrum, optimism, base, avalanche, solana\n */\nasync function fetchSecurityData(contractAddress: string, chain: string): Promise<string | null> {\n try {\n const security = await checkTokenSecurity(contractAddress, chain);\n if (!security) return null;\n\n const lines = [`## Security Audit (GoPlus, live)`];\n lines.push(` Chain: ${chain}`);\n lines.push(` Contract: ${contractAddress}`);\n lines.push(` Risk Level: ${security.riskLevel.toUpperCase()}`);\n lines.push('');\n\n // Critical flags\n const flags: string[] = [];\n if (security.isHoneypot) flags.push('HONEYPOT DETECTED');\n if (security.isMintable) flags.push('MINTABLE (owner can create tokens)');\n if (security.cannotSellAll) flags.push('CANNOT SELL ALL (sell restriction)');\n if (security.cannotBuy) flags.push('CANNOT BUY');\n if (security.selfDestruct) flags.push('SELF-DESTRUCT capable');\n if (security.hiddenOwner) flags.push('HIDDEN OWNER');\n if (security.canTakeBackOwnership) flags.push('CAN RECLAIM OWNERSHIP');\n if (security.ownerChangeBalance) flags.push('OWNER CAN CHANGE BALANCES');\n if (security.isBlacklisted) flags.push('HAS BLACKLIST function');\n if (security.slippageModifiable) flags.push('SLIPPAGE MODIFIABLE by owner');\n if (security.tradingCooldown) flags.push('TRADING COOLDOWN enabled');\n\n if (flags.length > 0) {\n lines.push(` RED FLAGS: ${flags.join(' | ')}`);\n } else {\n lines.push(' RED FLAGS: None detected');\n }\n\n // Tax analysis\n lines.push(` Buy Tax: ${(security.buyTax * 100).toFixed(1)}%`);\n lines.push(` Sell Tax: ${(security.sellTax * 100).toFixed(1)}%`);\n if (security.buyTax > 0.1 || security.sellTax > 0.1) {\n lines.push(' TAX WARNING: High tax detected (>10%)');\n }\n\n // Contract info\n lines.push(` Open Source: ${security.isOpenSource ? 'Yes' : 'No (unverified)'}`);\n lines.push(` Proxy Contract: ${security.isProxy ? 'Yes (upgradeable)' : 'No'}`);\n lines.push(` External Calls: ${security.externalCall ? 'Yes' : 'No'}`);\n\n // Holder info\n lines.push(` Holders: ${security.holderCount.toLocaleString()}`);\n lines.push(` LP Holders: ${security.lpHolderCount}`);\n lines.push(` Total Supply: ${security.totalSupply}`);\n lines.push(` Creator: ${security.creatorAddress || 'unknown'}`);\n lines.push(` Creator Holdings: ${(security.creatorPercent * 100).toFixed(2)}%`);\n lines.push(` Owner: ${security.ownerAddress || 'renounced/none'}`);\n lines.push(` Owner Holdings: ${(security.ownerPercent * 100).toFixed(2)}%`);\n lines.push(` LP Supply Lock: ${(security.lpTotalSupplyPercent * 100).toFixed(1)}%`);\n\n // DEX info\n if (security.dexInfo.length > 0) {\n lines.push(` DEX Listings:`);\n for (const dex of security.dexInfo) {\n lines.push(` - ${dex.name}: liquidity $${dex.liquidity}`);\n }\n }\n\n lines.push(` On Trust List: ${security.trustList ? 'Yes' : 'No'}`);\n\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\n/**\n * Check if an address is flagged as malicious via GoPlus.\n */\nasync function fetchAddressSecurityData(address: string, chain: string): Promise<string | null> {\n try {\n const security = await checkAddressSecurity(address, chain);\n if (!security) return null;\n\n const lines = [`## Address Security Check (GoPlus, live)`];\n lines.push(` Address: ${address}`);\n lines.push(` Is Contract: ${security.isContract ? 'Yes' : 'No (EOA)'}`);\n lines.push(` Malicious: ${security.maliciousAddress ? 'YES — FLAGGED' : 'Not flagged'}`);\n lines.push(` Honeypot Related: ${security.honeypotRelated ? 'YES' : 'No'}`);\n lines.push(` Phishing: ${security.phishing ? 'YES — FLAGGED' : 'No'}`);\n lines.push(` Blacklist Doubt: ${security.blacklistDoubt ? 'YES' : 'No'}`);\n\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchBinancePriceData(symbols: string[]): Promise<string | null> {\n try {\n const results = await Promise.allSettled(symbols.map((s) => fetchTickerPrice(s)));\n const lines: string[] = ['## Live Prices (Binance, real-time)'];\n let hasData = false;\n\n for (let i = 0; i < symbols.length; i++) {\n const result = results[i];\n if (result && result.status === 'fulfilled') {\n const d = result.value;\n lines.push(\n `${d.symbol}: $${d.price.toLocaleString()} | 24h: ${d.change24h > 0 ? '+' : ''}${d.change24h.toFixed(2)}%`,\n );\n hasData = true;\n }\n }\n\n return hasData ? lines.join('\\n') : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchFearGreedData(): Promise<string | null> {\n try {\n const data = await fetchFearGreedIndex(7);\n const c = data.current;\n const lines = [\n `## Market Sentiment (Fear & Greed Index)`,\n `Current: ${c.value}/100 (${c.classification})`,\n ];\n if (data.previous) {\n lines.push(`Previous: ${data.previous.value}/100 (${data.previous.classification})`);\n }\n if (data.history.length > 2) {\n const weekAgo = data.history[data.history.length - 1];\n if (weekAgo) {\n lines.push(`7d ago: ${weekAgo.value}/100 (${weekAgo.classification})`);\n }\n }\n return lines.join('\\n');\n } catch {\n return null;\n }\n}\n\nasync function fetchDerivativesData(tokens: string[]): Promise<string | null> {\n const symbols =\n tokens.length > 0\n ? tokens.slice(0, 3).map((t) => {\n // Convert geckoId-style names to ticker symbols\n if (t === 'bitcoin' || t === 'btc') return 'BTC';\n if (t === 'ethereum' || t === 'eth') return 'ETH';\n if (t === 'solana' || t === 'sol') return 'SOL';\n return t.toUpperCase();\n })\n : ['BTC', 'ETH'];\n\n try {\n const lines: string[] = ['## Derivatives Data (Binance Futures)'];\n let hasData = false;\n\n const results = await Promise.allSettled(\n symbols.map(async (sym) => {\n const [funding, oi] = await Promise.allSettled([\n fetchFundingRate(sym),\n fetchOpenInterest(sym),\n ]);\n return { sym, funding, oi };\n }),\n );\n\n for (const result of results) {\n if (result.status !== 'fulfilled') continue;\n const { sym, funding, oi } = result.value;\n\n const parts: string[] = [`${sym}:`];\n if (funding.status === 'fulfilled') {\n const f = funding.value;\n parts.push(`Funding: ${(f.fundingRate * 100).toFixed(4)}%`);\n parts.push(`Mark: $${f.markPrice.toLocaleString()}`);\n }\n if (oi.status === 'fulfilled') {\n const o = oi.value;\n parts.push(`OI: $${(o.notionalValue / 1e9).toFixed(2)}B`);\n }\n if (parts.length > 1) {\n lines.push(` ${parts.join(' | ')}`);\n hasData = true;\n }\n }\n\n return hasData ? lines.join('\\n') : null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction matchesAny(text: string, keywords: string[]): boolean {\n return keywords.some((kw) => text.includes(kw));\n}\n\nfunction detectTokens(lower: string): string[] {\n const found: string[] = [];\n for (const key of Object.keys(KNOWN_SYMBOLS)) {\n // Match whole word\n const regex = new RegExp(`\\\\b${key}\\\\b`);\n if (regex.test(lower) && !found.includes(key)) {\n found.push(key);\n }\n }\n return found;\n}\n\n/**\n * Detect unknown token names that aren't in KNOWN_SYMBOLS.\n * Looks for ALL-CAPS words (3-10 chars, likely tickers) and words\n * immediately after analysis-intent verbs like \"analyze\", \"audit\", \"scan\".\n */\nfunction detectUnknownTokens(original: string, knownTokens: string[]): string[] {\n const unknowns: string[] = [];\n const knownSet = new Set(knownTokens.map((t) => t.toLowerCase()));\n\n // Pattern 0: $TICKER notation (e.g., $ROFL, $PEPE) — very common in crypto\n const dollarRegex = /\\$([A-Za-z][A-Za-z0-9]{1,9})\\b/g;\n let m0;\n while ((m0 = dollarRegex.exec(original)) !== null) {\n const sym = m0[1]!.toLowerCase();\n if (!knownSet.has(sym) && !unknowns.includes(sym)) {\n unknowns.push(sym);\n }\n }\n\n // Pattern 1: ALL-CAPS words (3-10 chars) that look like ticker symbols\n const capsRegex = /\\b([A-Z][A-Z0-9]{2,9})\\b/g;\n let m;\n while ((m = capsRegex.exec(original)) !== null) {\n const sym = m[1]!.toLowerCase();\n // Skip common English words that happen to be uppercase\n const SKIP = new Set([\n 'THE',\n 'AND',\n 'FOR',\n 'NOT',\n 'BUT',\n 'ALL',\n 'ARE',\n 'WAS',\n 'HAS',\n 'HIS',\n 'HER',\n 'HOW',\n 'WHO',\n 'GET',\n 'GOT',\n 'CAN',\n 'HAD',\n 'HIM',\n 'SET',\n 'RUN',\n 'USE',\n 'ANY',\n 'NEW',\n 'NOW',\n 'OLD',\n 'OUR',\n 'TRY',\n 'LET',\n 'PUT',\n 'SAY',\n 'SHE',\n 'TOO',\n 'DEX',\n 'API',\n 'NFT',\n 'TVL',\n 'CEO',\n 'CTO',\n 'USD',\n 'APR',\n 'APY',\n 'ATH',\n 'ATL',\n 'ROI',\n 'ICO',\n 'IDO',\n 'IEO',\n 'DCA',\n 'HODL',\n 'FOMO',\n 'FUD',\n 'RUG',\n 'FULL',\n ]);\n if (!knownSet.has(sym) && !SKIP.has(m[1]!) && !unknowns.includes(sym)) {\n unknowns.push(sym);\n }\n }\n\n // Pattern 2: Words after analysis verbs (e.g., \"analyze RIGGED\", \"audit rigged\")\n const lower = original.toLowerCase();\n const verbRegex = /(?:anali[zs]e|audit|scan|check|review|inspect)\\s+([a-zA-Z0-9]{2,15})/gi;\n while ((m = verbRegex.exec(lower)) !== null) {\n const token = m[1]!.toLowerCase();\n if (!knownSet.has(token) && !unknowns.includes(token) && token.length >= 2) {\n unknowns.push(token);\n }\n }\n\n return unknowns;\n}\n\n/**\n * Build a summary of what data is available and what is missing.\n * This prevents ANY model (Ollama, Claude, GPT) from hallucinating missing data.\n */\nfunction buildDataSummary(sections: string[], tokens: string[]): string {\n const joined = sections.join('\\n');\n const has = (keyword: string): boolean => joined.toLowerCase().includes(keyword.toLowerCase());\n\n const lines: string[] = ['## DATA AVAILABILITY SUMMARY'];\n const tokenLabel =\n tokens.length > 0 ? tokens.map((t) => t.toUpperCase()).join(', ') : 'general market';\n\n // What we HAVE\n const available: string[] = [];\n if (has('Price:') || has('via Binance')) available.push('Price data');\n if (has('24h Volume:')) available.push('Volume (24h)');\n if (has('Liquidity:')) available.push('Liquidity');\n if (has('Market Cap:')) available.push('Market cap');\n if (has('24h Txns:') || has('buys /')) available.push('Buy/sell transactions');\n if (has('24h Change:')) available.push('Price change (24h)');\n if (has('7d Change:')) available.push('Price change (7d)');\n if (has('Fear & Greed')) available.push('Market sentiment (Fear & Greed)');\n if (has('Funding:')) available.push('Derivatives (funding rate)');\n if (has('OI:')) available.push('Open interest');\n if (has('Trending')) available.push('Trending tokens');\n if (has('News') || has('news')) available.push('News headlines');\n if (has('Fundraising') || has('Raises')) available.push('Fundraising rounds');\n if (has('Contract:')) available.push('Contract address');\n if (has('DEX:') || has('DexScreener') || has('pumpswap') || has('raydium'))\n available.push('DEX pair data');\n if (has('NOT FOUND')) available.push('DEX search (token NOT FOUND)');\n if (has('Security Audit') || has('GoPlus')) available.push('GoPlus security audit');\n if (has('HONEYPOT') || has('RED FLAGS')) available.push('Security flags analysis');\n if (has('Buy Tax:')) available.push('Tax analysis (buy/sell)');\n if (has('Holders:')) available.push('Holder count');\n if (has('Creator:')) available.push('Creator address');\n if (has('Pump.fun')) available.push('Pump.fun creator/community data');\n if (has('Websites:') || has('Socials:')) available.push('Project links (website/socials)');\n if (has('Pair Created:')) available.push('Token age (pair creation date)');\n if (has('Address Security')) available.push('Address security check');\n\n // What we DON'T have (always missing for on-chain-only analysis)\n const missing: string[] = [];\n if (!has('team') && !has('Team')) missing.push('Team/developer identities');\n if (!has('Security Audit') && !has('GoPlus'))\n missing.push('Security audit (provide contract address + chain)');\n if (!has('totalSupply') && !has('Total Supply')) missing.push('Tokenomics breakdown');\n missing.push('Roadmap / project phases');\n if (!has('Websites:') && !has('Socials:')) missing.push('Website / social media data');\n missing.push('Third-party audit reports (CertiK, etc.)');\n if (!has('Funding:')) missing.push('Derivatives data (funding rate, OI)');\n if (!has('News') && !has('news')) missing.push('News sentiment');\n\n lines.push(`Analysis target: ${tokenLabel}`);\n lines.push(`Data available: ${available.length > 0 ? available.join(', ') : 'NONE'}`);\n lines.push(`Data NOT available: ${missing.join(', ')}`);\n lines.push('');\n lines.push(\n 'IMPORTANT: For any item in \"Data NOT available\", say \"not available\" — do NOT invent or fabricate this information.',\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Build a pre-written analysis report that the model should present.\n * This is critical for weaker models (Ollama) that can't filter relevant data\n * from a large context block. The report is focused on the TARGET token only.\n */\nfunction buildAnalysisReport(\n sections: string[],\n tokens: string[],\n signalBlock: string | null,\n): string | null {\n const joined = sections.join('\\n');\n if (tokens.length === 0 && !joined.includes('Price:')) return null;\n\n const tokenLabel =\n tokens.length > 0 ? tokens.map((t) => t.toUpperCase()).join(', ') : 'target token';\n const lines: string[] = [\n '=== PRESENT THIS ANALYSIS REPORT TO THE USER ===',\n `(Focus ONLY on ${tokenLabel}. Do NOT list unrelated trending tokens unless the user asked about trends.)`,\n '',\n ];\n\n // Extract price for the target token (not BTC/ETH baseline)\n const extract = (pattern: RegExp): number | null => {\n const match = joined.match(pattern);\n return match ? parseFloat(match[1]!.replace(/,/g, '')) : null;\n };\n\n // 1. VERDICT — extract key data points\n const price = extract(/Price:\\s*\\$([0-9,.]+(?:e[+-]?\\d+)?)/);\n const change24h = extract(/24h Change:\\s*([+-]?\\d+\\.?\\d*)%/);\n const volume = extract(/24h Volume:\\s*\\$([0-9,]+)/);\n const liq = extract(/Liquidity:\\s*\\$([0-9,]+)/);\n const fearGreed = extract(/Current:\\s*(\\d+)\\/100/);\n const fgClass = joined.match(/Current:\\s*\\d+\\/100\\s*\\(([^)]+)\\)/)?.[1];\n const riskLevel = joined.match(/Risk Level:\\s*(\\w+)/)?.[1];\n const fundingMatch = joined.match(/Funding:\\s*([+-]?\\d+\\.?\\d*)%/);\n const oiMatch = joined.match(/OI:\\s*\\$([0-9.]+B?)/);\n\n if (price !== null) {\n const changeStr =\n change24h !== null ? ` (${change24h > 0 ? '+' : ''}${change24h.toFixed(2)}% 24h)` : '';\n lines.push(`## 1. Verdict`);\n lines.push(\n `${tokenLabel} is at $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()}${changeStr}.`,\n );\n if (fearGreed !== null) {\n lines.push(`Market sentiment: ${fgClass} (${fearGreed}/100).`);\n }\n if (riskLevel) {\n lines.push(`Security risk: ${riskLevel.toUpperCase()}.`);\n }\n lines.push('');\n }\n\n // 2. MARKET DATA\n lines.push('## 2. Market Data (cite these exact numbers)');\n if (price !== null)\n lines.push(\n `- Price: $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()} (live)`,\n );\n if (change24h !== null)\n lines.push(`- 24h Change: ${change24h > 0 ? '+' : ''}${change24h.toFixed(2)}%`);\n if (volume !== null) lines.push(`- 24h Volume: $${volume.toLocaleString()}`);\n if (liq !== null) lines.push(`- Liquidity: $${liq.toLocaleString()}`);\n if (fearGreed !== null) lines.push(`- Market Sentiment: ${fearGreed}/100 (${fgClass})`);\n if (fundingMatch) lines.push(`- Funding Rate: ${fundingMatch[1]}%`);\n if (oiMatch) lines.push(`- Open Interest: $${oiMatch[1]}`);\n\n // Buy/sell ratio\n const buysMatch = joined.match(/(\\d+)\\s*buys\\s*\\/\\s*(\\d+)\\s*sells/);\n if (buysMatch) {\n const buys = parseInt(buysMatch[1]!, 10);\n const sells = parseInt(buysMatch[2]!, 10);\n const total = buys + sells;\n if (total > 0) {\n lines.push(`- Buy/Sell Ratio: ${buys}/${sells} (${((buys / total) * 100).toFixed(0)}% buys)`);\n }\n }\n lines.push('');\n\n // 3. SECURITY (if available)\n if (joined.includes('Security Audit') || joined.includes('GoPlus')) {\n lines.push('## 3. Security Audit (GoPlus)');\n if (joined.includes('HONEYPOT DETECTED')) lines.push('- **HONEYPOT: YES — DO NOT BUY**');\n else lines.push('- Honeypot: Not detected');\n const buyTax = extract(/Buy Tax:\\s*(\\d+\\.?\\d*)%/);\n const sellTax = extract(/Sell Tax:\\s*(\\d+\\.?\\d*)%/);\n if (buyTax !== null)\n lines.push(`- Buy Tax: ${buyTax.toFixed(1)}% | Sell Tax: ${(sellTax ?? 0).toFixed(1)}%`);\n if (riskLevel) lines.push(`- Risk Level: ${riskLevel.toUpperCase()}`);\n // Extract flags\n const flagsMatch = joined.match(/RED FLAGS:\\s*(.+)/);\n if (flagsMatch && !flagsMatch[1]!.includes('None'))\n lines.push(`- **Red Flags: ${flagsMatch[1]}**`);\n const holderCount = extract(/Holders:\\s*([0-9,]+)/);\n if (holderCount !== null) lines.push(`- Holders: ${holderCount.toLocaleString()}`);\n const creatorPct = extract(/Creator Holdings:\\s*(\\d+\\.?\\d*)%/);\n if (creatorPct !== null) lines.push(`- Creator Holdings: ${creatorPct.toFixed(2)}%`);\n lines.push('');\n }\n\n // 4. SIGNALS — just reference the pre-computed block\n if (signalBlock) {\n // Extract the composite line\n const compositeMatch = signalBlock.match(/COMPOSITE:\\s*(.+)/);\n if (compositeMatch) {\n lines.push('## 4. Signal Analysis');\n lines.push(`Composite: ${compositeMatch[1]}`);\n // Extract individual signals\n const signalLines = signalBlock\n .split('\\n')\n .filter(\n (l) =>\n l.includes(':') &&\n !l.includes('COMPOSITE') &&\n !l.includes('PRE-COMPUTED') &&\n !l.includes('Use these'),\n );\n for (const sl of signalLines.slice(0, 8)) {\n lines.push(sl.trim());\n }\n lines.push('');\n }\n }\n\n // 5. PRICE TARGETS — extract from the PRICE PREDICTION SCENARIOS section\n if (joined.includes('PRICE PREDICTION SCENARIOS')) {\n lines.push('## 5. Price Prediction (PRESENT THESE EXACT NUMBERS)');\n const scenarioBlock = joined.split('PRICE PREDICTION SCENARIOS')[1]?.split('## ')[0] ?? '';\n const targetLines = scenarioBlock.split('\\n').filter((l) => l.trim().length > 0);\n for (const tl of targetLines) {\n lines.push(tl);\n }\n lines.push('');\n }\n\n // 6. RISKS\n lines.push('## 6. Risk Assessment');\n if (joined.includes('NOT FOUND')) lines.push('- **EXTREME RISK: Token not found on any DEX**');\n if (joined.includes('HONEYPOT')) lines.push('- **CRITICAL: Honeypot detected**');\n if (liq !== null && liq < 50000)\n lines.push(`- **LOW LIQUIDITY: $${liq.toLocaleString()} — high slippage/rug risk**`);\n if (change24h !== null && Math.abs(change24h) > 50)\n lines.push(`- **EXTREME VOLATILITY: ${change24h.toFixed(1)}% in 24h**`);\n if (fearGreed !== null && fearGreed <= 20)\n lines.push(\n `- Market in Extreme Fear (${fearGreed}/100) — higher crash risk but contrarian opportunity`,\n );\n if (fearGreed !== null && fearGreed >= 80)\n lines.push(`- Market in Extreme Greed (${fearGreed}/100) — correction likely`);\n lines.push('- This is data-driven analysis, not financial advice');\n lines.push('');\n\n lines.push('=== END REPORT — PRESENT THE ABOVE NATURALLY, DO NOT DUMP RAW DATA ===');\n\n return lines.join('\\n');\n}\n\n/**\n * Pre-compute trading signals from the raw data sections.\n * This helps weaker models (Ollama) produce quantitative predictions\n * instead of vague \"it could go up or down\" responses.\n */\nfunction computeSignals(sections: string[], tokens: string[], userMessage = ''): string | null {\n const joined = sections.join('\\n');\n if (tokens.length === 0) return null;\n\n const signals: string[] = ['## PRE-COMPUTED SIGNAL ANALYSIS'];\n let signalCount = 0;\n let bullish = 0;\n let bearish = 0;\n\n // Extract numbers from data using regex\n const extract = (pattern: RegExp): number | null => {\n const match = joined.match(pattern);\n return match ? parseFloat(match[1]!.replace(/,/g, '')) : null;\n };\n\n // 1. Price momentum signal\n const change24h = extract(/24h Change:\\s*([+-]?\\d+\\.?\\d*)%/);\n if (change24h !== null) {\n signalCount++;\n if (change24h > 5) {\n bullish++;\n signals.push(\n ` MOMENTUM: BULLISH — 24h change ${change24h > 0 ? '+' : ''}${change24h.toFixed(1)}% (strong upward momentum)`,\n );\n } else if (change24h > 0) {\n bullish++;\n signals.push(` MOMENTUM: SLIGHTLY BULLISH — 24h change +${change24h.toFixed(1)}%`);\n } else if (change24h > -5) {\n bearish++;\n signals.push(` MOMENTUM: SLIGHTLY BEARISH — 24h change ${change24h.toFixed(1)}%`);\n } else {\n bearish++;\n signals.push(\n ` MOMENTUM: BEARISH — 24h change ${change24h.toFixed(1)}% (significant decline)`,\n );\n }\n }\n\n // 2. Buy/sell pressure signal\n const buysMatch = joined.match(/(\\d+)\\s*buys\\s*\\/\\s*(\\d+)\\s*sells/);\n if (buysMatch) {\n const buys = parseInt(buysMatch[1]!, 10);\n const sells = parseInt(buysMatch[2]!, 10);\n const total = buys + sells;\n signalCount++;\n if (total > 0) {\n const buyRatio = buys / total;\n if (buyRatio > 0.55) {\n bullish++;\n signals.push(\n ` BUY PRESSURE: BULLISH — ${buys} buys vs ${sells} sells (${(buyRatio * 100).toFixed(0)}% buy ratio)`,\n );\n } else if (buyRatio < 0.45) {\n bearish++;\n signals.push(\n ` SELL PRESSURE: BEARISH — ${buys} buys vs ${sells} sells (${((1 - buyRatio) * 100).toFixed(0)}% sell ratio)`,\n );\n } else {\n signals.push(` BUY/SELL: NEUTRAL — ${buys} buys vs ${sells} sells (balanced)`);\n }\n }\n }\n\n // 3. Liquidity risk signal\n const liquidity = extract(/Liquidity:\\s*\\$([0-9,]+)/);\n if (liquidity !== null && liquidity > 0) {\n signalCount++;\n if (liquidity < 10000) {\n bearish++;\n signals.push(\n ` LIQUIDITY: HIGH RISK — $${liquidity.toLocaleString()} (extremely low, easy to manipulate)`,\n );\n } else if (liquidity < 50000) {\n bearish++;\n signals.push(\n ` LIQUIDITY: RISKY — $${liquidity.toLocaleString()} (low liquidity, high slippage risk)`,\n );\n } else if (liquidity < 500000) {\n signals.push(` LIQUIDITY: MODERATE — $${liquidity.toLocaleString()}`);\n } else {\n bullish++;\n signals.push(` LIQUIDITY: HEALTHY — $${liquidity.toLocaleString()}`);\n }\n }\n\n // 4. Fear & Greed signal\n const fearGreed = extract(/Current:\\s*(\\d+)\\/100/);\n if (fearGreed !== null) {\n signalCount++;\n if (fearGreed <= 25) {\n bullish++;\n signals.push(\n ` SENTIMENT: EXTREME FEAR (${fearGreed}/100) — contrarian BUY signal (market oversold)`,\n );\n } else if (fearGreed <= 40) {\n signals.push(` SENTIMENT: FEAR (${fearGreed}/100) — cautious market, potential opportunity`);\n } else if (fearGreed <= 60) {\n signals.push(` SENTIMENT: NEUTRAL (${fearGreed}/100) — balanced sentiment`);\n } else if (fearGreed <= 75) {\n signals.push(` SENTIMENT: GREED (${fearGreed}/100) — caution, market may be overheated`);\n } else {\n bearish++;\n signals.push(\n ` SENTIMENT: EXTREME GREED (${fearGreed}/100) — contrarian SELL signal (market overheated)`,\n );\n }\n }\n\n // 5. Funding rate signal\n const fundingMatch = joined.match(/Funding:\\s*([+-]?\\d+\\.?\\d*)%/);\n if (fundingMatch) {\n const funding = parseFloat(fundingMatch[1]!);\n signalCount++;\n if (funding > 0.05) {\n signals.push(\n ` FUNDING: HIGH POSITIVE (${funding.toFixed(4)}%) — longs paying shorts, heavy bullish positioning`,\n );\n bearish++; /* contrarian */\n } else if (funding > 0) {\n signals.push(` FUNDING: POSITIVE (${funding.toFixed(4)}%) — mild bullish consensus`);\n bullish++;\n } else if (funding < -0.05) {\n signals.push(\n ` FUNDING: HIGH NEGATIVE (${funding.toFixed(4)}%) — shorts paying longs, heavy bearish positioning`,\n );\n bullish++; /* contrarian */\n } else {\n signals.push(` FUNDING: NEGATIVE (${funding.toFixed(4)}%) — mild bearish consensus`);\n bearish++;\n }\n }\n\n // 6. NOT FOUND signal (strongest bearish)\n if (joined.includes('NOT FOUND')) {\n signalCount++;\n bearish += 2;\n signals.push(' DEX STATUS: NOT LISTED — token not found on any DEX. EXTREME RISK.');\n }\n\n // 7. Security signals (from GoPlus)\n if (joined.includes('Risk Level:')) {\n signalCount++;\n if (joined.includes('Risk Level: DANGER')) {\n bearish += 2;\n signals.push(' SECURITY: DANGER — GoPlus flagged critical risks');\n } else if (joined.includes('Risk Level: WARNING')) {\n bearish++;\n signals.push(' SECURITY: WARNING — GoPlus detected potential risks');\n } else if (joined.includes('Risk Level: SAFE')) {\n bullish++;\n signals.push(' SECURITY: SAFE — GoPlus found no major risks');\n }\n }\n\n // 8. Honeypot signal\n if (joined.includes('HONEYPOT DETECTED')) {\n signalCount++;\n bearish += 3;\n signals.push(' HONEYPOT: CRITICAL — Token is a honeypot. DO NOT BUY.');\n }\n\n // 9. Tax signal\n const buyTax = extract(/Buy Tax:\\s*(\\d+\\.?\\d*)%/);\n const sellTax = extract(/Sell Tax:\\s*(\\d+\\.?\\d*)%/);\n if (buyTax !== null && sellTax !== null) {\n signalCount++;\n const totalTax = buyTax + sellTax;\n if (totalTax > 20) {\n bearish += 2;\n signals.push(\n ` TAX: EXTREME — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}% = ${totalTax.toFixed(1)}% total (scam-level)`,\n );\n } else if (totalTax > 10) {\n bearish++;\n signals.push(\n ` TAX: HIGH — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}% = ${totalTax.toFixed(1)}% total`,\n );\n } else if (totalTax > 0) {\n signals.push(` TAX: MODERATE — Buy ${buyTax.toFixed(1)}% + Sell ${sellTax.toFixed(1)}%`);\n } else {\n bullish++;\n signals.push(' TAX: NONE — 0% buy and sell tax');\n }\n }\n\n // 10. Token age signal\n const ageMatch = joined.match(/Pair Created:\\s*(\\d+)d ago/);\n if (ageMatch) {\n const ageDays = parseInt(ageMatch[1]!, 10);\n signalCount++;\n if (ageDays < 1) {\n bearish++;\n signals.push(` AGE: VERY NEW — Created today. Extremely high risk.`);\n } else if (ageDays < 7) {\n bearish++;\n signals.push(` AGE: NEW — ${ageDays} days old. High risk.`);\n } else if (ageDays < 30) {\n signals.push(` AGE: YOUNG — ${ageDays} days old. Still risky.`);\n } else if (ageDays < 180) {\n signals.push(` AGE: ESTABLISHED — ${ageDays} days old.`);\n } else {\n bullish++;\n signals.push(` AGE: MATURE — ${ageDays} days old. Survived multiple market cycles.`);\n }\n }\n\n // 11. Holder concentration signal\n const creatorPct = extract(/Creator Holdings:\\s*(\\d+\\.?\\d*)%/);\n const ownerPct = extract(/Owner Holdings:\\s*(\\d+\\.?\\d*)%/);\n if (creatorPct !== null) {\n signalCount++;\n const totalConcentration = creatorPct + (ownerPct ?? 0);\n if (totalConcentration > 50) {\n bearish += 2;\n signals.push(\n ` CONCENTRATION: EXTREME — Creator+Owner hold ${totalConcentration.toFixed(1)}%. Rug pull risk.`,\n );\n } else if (totalConcentration > 20) {\n bearish++;\n signals.push(` CONCENTRATION: HIGH — Creator+Owner hold ${totalConcentration.toFixed(1)}%`);\n } else if (totalConcentration > 5) {\n signals.push(\n ` CONCENTRATION: MODERATE — Creator+Owner hold ${totalConcentration.toFixed(1)}%`,\n );\n } else {\n bullish++;\n signals.push(\n ` CONCENTRATION: LOW — Creator+Owner hold ${totalConcentration.toFixed(1)}% (well distributed)`,\n );\n }\n }\n\n if (signalCount === 0) return null;\n\n // Compute composite\n const total = bullish + bearish;\n let direction: string;\n let confidence: string;\n\n if (total === 0) {\n direction = 'NEUTRAL';\n confidence = 'LOW';\n } else {\n const bullPct = (bullish / total) * 100;\n if (bullPct > 65) direction = 'BULLISH';\n else if (bullPct > 50) direction = 'SLIGHTLY BULLISH';\n else if (bullPct > 35) direction = 'SLIGHTLY BEARISH';\n else direction = 'BEARISH';\n\n if (signalCount >= 4 && Math.abs(bullish - bearish) >= 2) confidence = 'MEDIUM-HIGH';\n else if (signalCount >= 3) confidence = 'MEDIUM';\n else confidence = 'LOW';\n }\n\n signals.push('');\n signals.push(\n ` COMPOSITE: ${direction} | Confidence: ${confidence} | Signals: ${signalCount} (${bullish} bullish, ${bearish} bearish)`,\n );\n\n // Compute price targets from available data (pass userMessage for time parsing)\n const priceTargets = computePriceTargets(joined, direction, change24h, userMessage);\n if (priceTargets) {\n signals.push('');\n signals.push(priceTargets);\n }\n\n return signals.join('\\n');\n}\n\n/**\n * Parse time-related expressions from the user message.\n * Returns an array of { label, hoursFromNow } for each requested timeframe.\n * If no specific time is found, returns null (use default timeframes).\n */\nfunction parseRequestedTimeframes(userMessage: string): { label: string; hours: number }[] | null {\n const lower = userMessage.toLowerCase();\n const requested: { label: string; hours: number }[] = [];\n\n // \"at HH:MM\" or \"at H:MMpm\" — specific clock time\n const clockMatch = lower.match(/at\\s+(\\d{1,2}):?(\\d{2})?\\s*(am|pm|hrs?)?/);\n if (clockMatch) {\n let hour = parseInt(clockMatch[1]!, 10);\n const minute = parseInt(clockMatch[2] || '0', 10);\n const ampm = clockMatch[3];\n if (ampm === 'pm' && hour < 12) hour += 12;\n if (ampm === 'am' && hour === 12) hour = 0;\n\n const now = new Date();\n const target = new Date(now);\n target.setHours(hour, minute, 0, 0);\n // If target is in the past, assume tomorrow\n if (target <= now) target.setDate(target.getDate() + 1);\n\n const hoursFromNow = Math.max(0.08, (target.getTime() - now.getTime()) / 3600000);\n const timeStr = target.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n });\n requested.push({\n label: `At ${timeStr} (${hoursFromNow.toFixed(1)}h from now)`,\n hours: hoursFromNow,\n });\n }\n\n // \"in X minutes/hours/days\"\n const inMatch = lower.match(/in\\s+(\\d+)\\s*(min(?:ute)?s?|hours?|hrs?|days?|weeks?|months?)/);\n if (inMatch) {\n const amount = parseInt(inMatch[1]!, 10);\n const unit = inMatch[2]!;\n let hours = amount;\n if (unit.startsWith('min')) hours = amount / 60;\n else if (unit.startsWith('day')) hours = amount * 24;\n else if (unit.startsWith('week')) hours = amount * 168;\n else if (unit.startsWith('month')) hours = amount * 720;\n requested.push({ label: `In ${amount} ${unit}`, hours });\n }\n\n // \"tomorrow\" / \"tonight\" / \"end of day\"\n if (lower.includes('tomorrow')) requested.push({ label: 'Tomorrow (~24h)', hours: 24 });\n if (lower.includes('tonight') || lower.includes('end of day'))\n requested.push({ label: 'End of day (~8h)', hours: 8 });\n if (lower.includes('next week')) requested.push({ label: 'Next week (~168h)', hours: 168 });\n if (lower.includes('next month')) requested.push({ label: 'Next month (~720h)', hours: 720 });\n if (lower.includes('end of week')) requested.push({ label: 'End of week', hours: 120 });\n\n return requested.length > 0 ? requested : null;\n}\n\n/**\n * Compute concrete price predictions with dollar values and timeframes.\n * Uses current price + momentum + volatility to project scenarios.\n * Generates all timeframes from 5min to 3 months, and includes any\n * user-requested specific times (e.g., \"at 16:00 today\").\n */\nfunction computePriceTargets(\n data: string,\n direction: string,\n change24h: number | null,\n userMessage = '',\n): string | null {\n // Extract current price (handle comma-formatted numbers like $2,111.55)\n const priceMatch = data.match(/Price:\\s*\\$([0-9,.]+(?:e[+-]?\\d+)?)/);\n if (!priceMatch) return null;\n const price = parseFloat(priceMatch[1]!.replace(/,/g, ''));\n if (isNaN(price) || price <= 0) return null;\n\n // Extract liquidity and market cap for context\n const liqMatch = data.match(/Liquidity:\\s*\\$([0-9,]+)/);\n const mcapMatch = data.match(/Market Cap:\\s*\\$([0-9,]+)/);\n const liquidity = liqMatch ? parseFloat(liqMatch[1]!.replace(/,/g, '')) : 0;\n const mcap = mcapMatch ? parseFloat(mcapMatch[1]!.replace(/,/g, '')) : 0;\n\n // Calculate hourly volatility from 24h change\n const dailyVol = Math.abs(change24h ?? 10) / 100;\n const vol = Math.min(dailyVol, 0.5);\n const hourlyVol = vol / Math.sqrt(24); // Scale volatility to hourly\n\n const lines: string[] = ['## PRICE PREDICTION SCENARIOS'];\n lines.push(` Current Price: $${price < 0.01 ? price.toExponential(4) : price.toLocaleString()}`);\n lines.push(` Timestamp: ${new Date().toISOString()}`);\n\n // Determine base direction bias\n let bullBias: number; // How much stronger the bull case is (1.0 = no bias)\n let bearBias: number;\n\n if (direction.includes('BULLISH')) {\n bullBias = direction.includes('SLIGHTLY') ? 1.3 : 1.8;\n bearBias = direction.includes('SLIGHTLY') ? 0.7 : 0.5;\n } else if (direction.includes('BEARISH')) {\n bullBias = direction.includes('SLIGHTLY') ? 0.7 : 0.4;\n bearBias = direction.includes('SLIGHTLY') ? 1.3 : 1.8;\n } else {\n bullBias = 1.0;\n bearBias = 1.0;\n }\n\n // Meme coin amplifier\n const isMicrocap = mcap > 0 && mcap < 1_000_000;\n const isMeme =\n data.includes('pumpswap') || data.includes('pump.fun') || data.includes('Pump.fun');\n const memeMultiplier = isMicrocap || isMeme ? 3 : 1;\n\n const formatPrice = (p: number): string =>\n p < 0.01 ? p.toExponential(4) : p.toFixed(p < 1 ? 6 : 2);\n const pctStr = (target: number): string => {\n const pct = (target / price - 1) * 100;\n return `${pct >= 0 ? '+' : ''}${pct.toFixed(1)}%`;\n };\n\n /**\n * Compute bull/likely/bear for a given number of hours from now.\n * Uses volatility scaling: move = hourlyVol * sqrt(hours) * bias * meme\n */\n const scenario = (hours: number): { bull: number; likely: number; bear: number } => {\n const timeVol = hourlyVol * Math.sqrt(hours) * memeMultiplier;\n const bull = price * (1 + timeVol * bullBias);\n const bear = price * (1 - timeVol * bearBias);\n // \"Most likely\" follows the direction bias slightly\n const likelyShift = direction.includes('BULLISH')\n ? timeVol * 0.3\n : direction.includes('BEARISH')\n ? -timeVol * 0.3\n : 0;\n const likely = price * (1 + likelyShift);\n return { bull, likely, bear };\n };\n\n // -------------------------------------------------------------------------\n // User-requested specific timeframe (e.g., \"at 16:00 today\")\n // -------------------------------------------------------------------------\n const requestedTimes = parseRequestedTimeframes(userMessage);\n if (requestedTimes) {\n lines.push('');\n lines.push(' USER-REQUESTED TIMEFRAME:');\n for (const { label, hours } of requestedTimes) {\n const s = scenario(hours);\n lines.push(` ${label}:`);\n lines.push(` Bullish: $${formatPrice(s.bull)} (${pctStr(s.bull)})`);\n lines.push(` Most likely: $${formatPrice(s.likely)} (${pctStr(s.likely)})`);\n lines.push(` Bearish: $${formatPrice(s.bear)} (${pctStr(s.bear)})`);\n }\n }\n\n // -------------------------------------------------------------------------\n // Full multi-timeframe spectrum\n // -------------------------------------------------------------------------\n\n // Scalping / Intraday\n const tf5m = scenario(5 / 60);\n const tf15m = scenario(15 / 60);\n const tf1h = scenario(1);\n const tf4h = scenario(4);\n lines.push('');\n lines.push(' SCALPING / INTRADAY:');\n lines.push(\n ` 5 min: Bull $${formatPrice(tf5m.bull)} (${pctStr(tf5m.bull)}) | Likely $${formatPrice(tf5m.likely)} | Bear $${formatPrice(tf5m.bear)} (${pctStr(tf5m.bear)})`,\n );\n lines.push(\n ` 15 min: Bull $${formatPrice(tf15m.bull)} (${pctStr(tf15m.bull)}) | Likely $${formatPrice(tf15m.likely)} | Bear $${formatPrice(tf15m.bear)} (${pctStr(tf15m.bear)})`,\n );\n lines.push(\n ` 1 hour: Bull $${formatPrice(tf1h.bull)} (${pctStr(tf1h.bull)}) | Likely $${formatPrice(tf1h.likely)} | Bear $${formatPrice(tf1h.bear)} (${pctStr(tf1h.bear)})`,\n );\n lines.push(\n ` 4 hour: Bull $${formatPrice(tf4h.bull)} (${pctStr(tf4h.bull)}) | Likely $${formatPrice(tf4h.likely)} | Bear $${formatPrice(tf4h.bear)} (${pctStr(tf4h.bear)})`,\n );\n\n // Short-term (1-7 days)\n const tf1d = scenario(24);\n const tf7d = scenario(168);\n lines.push('');\n lines.push(' SHORT-TERM (1-7 days):');\n lines.push(\n ` 1 day: Bull $${formatPrice(tf1d.bull)} (${pctStr(tf1d.bull)}) | Likely $${formatPrice(tf1d.likely)} | Bear $${formatPrice(tf1d.bear)} (${pctStr(tf1d.bear)})`,\n );\n lines.push(\n ` 7 days: Bull $${formatPrice(tf7d.bull)} (${pctStr(tf7d.bull)}) | Likely $${formatPrice(tf7d.likely)} | Bear $${formatPrice(tf7d.bear)} (${pctStr(tf7d.bear)})`,\n );\n\n // Medium-term (1-4 weeks)\n const tf2w = scenario(336);\n const tf1m = scenario(720);\n lines.push('');\n lines.push(' MEDIUM-TERM (1-4 weeks):');\n lines.push(\n ` 2 weeks: Bull $${formatPrice(tf2w.bull)} (${pctStr(tf2w.bull)}) | Likely $${formatPrice(tf2w.likely)} | Bear $${formatPrice(tf2w.bear)} (${pctStr(tf2w.bear)})`,\n );\n lines.push(\n ` 1 month: Bull $${formatPrice(tf1m.bull)} (${pctStr(tf1m.bull)}) | Likely $${formatPrice(tf1m.likely)} | Bear $${formatPrice(tf1m.bear)} (${pctStr(tf1m.bear)})`,\n );\n\n // Long-term (1-3 months)\n const tf3m = scenario(2160);\n lines.push('');\n lines.push(' LONG-TERM (1-3 months):');\n lines.push(\n ` 3 months: Bull $${formatPrice(tf3m.bull)} (${pctStr(tf3m.bull)}) | Bear $${formatPrice(tf3m.bear)} (${pctStr(tf3m.bear)})`,\n );\n\n // Survival probability for meme/micro-cap tokens\n if (isMicrocap || isMeme) {\n lines.push('');\n lines.push(' MEME COIN SURVIVAL ANALYSIS:');\n const survivalPct = liquidity > 50000 ? 25 : liquidity > 10000 ? 15 : 5;\n lines.push(` Probability token survives 30 days: ~${survivalPct}%`);\n lines.push(` Probability of -90% or worse in 30 days: ~${100 - survivalPct - 10}%`);\n lines.push(` Probability of 2x+ in 7 days: ~${Math.min(30, Math.round(vol * 100))}%`);\n if (liquidity < 50000) {\n lines.push(\n ` WARNING: Liquidity $${liquidity.toLocaleString()} is extremely low — large sells will crash the price`,\n );\n }\n }\n\n // Key levels\n lines.push('');\n lines.push(' KEY LEVELS:');\n lines.push(\n ` Support: $${formatPrice(price * 0.95)} / $${formatPrice(price * 0.9)} / $${formatPrice(price * 0.8)}`,\n );\n lines.push(\n ` Resistance: $${formatPrice(price * 1.05)} / $${formatPrice(price * 1.1)} / $${formatPrice(price * 1.2)}`,\n );\n\n lines.push('');\n if (requestedTimes) {\n lines.push(\n ' IMPORTANT: The user asked for a SPECIFIC TIME. Present the USER-REQUESTED TIMEFRAME section FIRST and prominently.',\n );\n }\n lines.push(\n ' Present ALL timeframes from scalping to long-term. Use the exact dollar values above.',\n );\n\n return lines.join('\\n');\n}\n","// ---------------------------------------------------------------------------\n// System prompt for conversational / chat mode\n// ---------------------------------------------------------------------------\n\n/**\n * Build the chat system prompt with the current date injected.\n * This ensures the AI always knows what year it is and never uses stale training data.\n */\nexport function buildChatSystemPrompt(): string {\n const now = new Date();\n const dateStr = now.toISOString().split('T')[0];\n\n return `You are Vizzor, an AI-powered crypto chronovisor built by 7ayLabs. You provide real-time blockchain intelligence — live prices, trending tokens, fundraising rounds, on-chain forensics, and market sentiment — to help investors analyze chains and coins.\n\n## Date Context\n\nToday is ${dateStr}. Your training data ends in early 2025. It is now ${now.getFullYear()}. ANY market prices, ICOs, fundraising rounds, trending tokens, or news from your training data is OUTDATED AND WRONG. You MUST call your tools for current information.\n\n## MANDATORY TOOL-USE RULES\n\nBEFORE answering ANY question about these topics, you MUST call the specified tools. NEVER answer from training data alone — your market knowledge is over a year stale.\n\n| Topic | Required Tools |\n|-------|---------------|\n| Prices, market data | get_market_data OR search_token_dex |\n| Trending tokens | get_trending |\n| ICOs, fundraising, launches | get_raises AND/OR search_upcoming_icos |\n| News, events | get_crypto_news |\n| Market sentiment | get_fear_greed |\n| Derivatives, positioning | get_derivatives_data |\n| Token security | get_token_security OR check_rug_indicators |\n| Wallet analysis | analyze_wallet |\n| Predictions, forecasts | get_technical_analysis + get_prediction + get_market_data + get_fear_greed + get_derivatives_data |\n\nIf you answer a market question without calling tools first, your answer WILL contain wrong data. Call the tools, then synthesize.\n\nIf a tool returns empty results or fails, say \"no current data available\" — NEVER fall back to training data.\n\n## Tools\n\n### On-Chain Analysis\n- **get_token_info**: Look up on-chain token information by contract address and chain.\n- **analyze_wallet**: Analyze a wallet for transaction patterns, holdings, and behavior.\n- **check_rug_indicators**: Check a token for rug pull red flags (mint functions, pause, blacklist, honeypot detection via bytecode scanning).\n\n### Market Data\n- **get_market_data**: Get live price, volume, market cap for established tokens (CoinGecko). Use for BTC, ETH, SOL, and other major tokens.\n- **search_token_dex**: Search ANY token on DEXes via DexScreener — real-time price, volume, liquidity, buy/sell counts. Works for meme coins, new launches, and any DEX-listed token.\n- **get_trending**: Get currently trending/hot tokens from DexScreener and CoinGecko. Shows what the market is excited about RIGHT NOW.\n\n### Security & Sentiment\n- **get_token_security**: Check token security via GoPlus API — honeypot detection, tax analysis, mint/pause/blacklist capabilities, holder stats, risk level.\n- **get_fear_greed**: Get the Crypto Fear & Greed Index with 7-day history. 0-20 Extreme Fear, 21-40 Fear, 41-60 Neutral, 61-80 Greed, 81-100 Extreme Greed.\n- **get_derivatives_data**: Get Binance Futures funding rate, open interest, and mark price. Essential for market positioning analysis.\n\n### News & Fundraising\n- **get_crypto_news**: Get latest crypto news with sentiment for a token or the market. Powered by CryptoPanic.\n- **get_raises**: Get recent crypto fundraising rounds and token launches from DeFiLlama. Shows who raised money, how much, and from which investors.\n- **search_upcoming_icos**: Search for token launches and fundraising by category or chain. Combines DeFiLlama raises with Pump.fun Solana launches.\n\n### Technical Analysis & Prediction\n- **get_technical_analysis**: Run technical analysis on any symbol — RSI, MACD, Bollinger Bands, EMA crossovers, ATR, OBV. Returns composite signal with individual indicator interpretations.\n- **get_prediction**: Generate a multi-signal composite prediction combining technical analysis, sentiment, derivatives, Fear & Greed, and market trend data. Returns direction, confidence, and timeframe.\n\n## Trends / ICOs / News Protocol\n\nWhen asked about trending tokens, ICOs, fundraising rounds, new projects, or market news:\n\n1. **MANDATORY**: Call get_trending, get_raises, search_upcoming_icos, get_crypto_news, or get_fear_greed as appropriate BEFORE answering.\n2. Present ONLY the data returned by tools. Never supplement with training data.\n3. If the user asks \"what are the latest ICOs\" or \"recent launches\", call BOTH get_raises AND search_upcoming_icos.\n4. If tools return empty results, say \"No current data available\" — do NOT fall back to training data.\n5. Always mention the data source and that it is live.\n\n## Prediction Protocol\n\nWhen asked for a prediction, price forecast, or market outlook for ANY token:\n\n1. **MANDATORY DATA GATHERING** — call ALL of these before forming any prediction:\n - \\`get_market_data\\` for the token (price, volume, market cap)\n - \\`get_derivatives_data\\` for the token (funding rate, open interest)\n - \\`get_fear_greed\\` for macro sentiment\n - \\`get_crypto_news\\` for the token (news sentiment)\n - \\`get_technical_analysis\\` for the token (RSI, MACD, BB signals)\n - \\`get_prediction\\` for composite multi-signal score\n - \\`get_trending\\` to check if the token is trending\n\n2. **MULTI-TIMEFRAME ANALYSIS** — always provide:\n - **Short-term** (1-7 days): momentum, funding rate direction, immediate catalysts\n - **Medium-term** (1-4 weeks): trend strength, OI trends, sector rotation\n - **Long-term** (1-3 months): macro cycle position, adoption metrics, narrative alignment\n\n3. **CONFIDENCE CALIBRATION**:\n - **HIGH (>75%)**: 4+ signals aligned, strong volume confirmation, clear trend\n - **MEDIUM (50-75%)**: 2-3 signals aligned, moderate volume, some conflicting signals\n - **LOW (<50%)**: mixed signals, low volume, high uncertainty, insufficient data\n\n4. **CONTRARIAN INDICATORS**:\n - Extreme Greed (>80) + very positive funding = potential correction signal\n - Extreme Fear (<20) + negative funding = potential reversal opportunity\n - Divergence between price action and OI = trend weakness\n\n5. Always include disclaimer: predictions are based on data analysis, not financial advice.\n\n## Security / Forensics Protocol\n\nWhen asked to analyze a wallet, check a token for rug pulls, or assess security:\n\n1. **MANDATORY**: Call check_rug_indicators and/or get_token_security for the contract.\n2. For wallet analysis: call analyze_wallet.\n3. Present GoPlus findings factually — honeypot status, tax levels, mint/pause capabilities, holder distribution.\n4. Always state the risk level and specific red flags found.\n\n## Chronovisor Intelligence\n\nWhen asked about market outlook, predictions, or \"what's happening\":\n1. **Gather data first**: Call get_trending + get_crypto_news + get_market_data + get_fear_greed + get_derivatives_data\n2. **Identify patterns**: Rising volumes, buy/sell ratios, sentiment shifts, new raises in a sector\n3. **Synthesize**: Combine on-chain data + market data + news sentiment + derivatives into a coherent picture\n4. **Cite everything**: Always mention which data source each insight comes from\n\n## Extended Thinking Protocol\n\nFor complex queries (predictions, comparisons, portfolio advice, risk assessment):\n- Call a MINIMUM of 4 tools before answering\n- Structure reasoning: Data → Signals → Alignment → Confidence → Risks → Conclusion\n- If signals conflict, explicitly state the disagreement and weight each side\n- Never give a prediction without stating your confidence level and what could invalidate it\n- If a tool fails, note the data gap in your response\n\n## Guidelines\n\n- **Real data only**: Always call tools before answering market questions. Your training data is stale — over a year old.\n- **Cite data sources**: Mention \"DexScreener\", \"CoinGecko\", \"DeFiLlama\", \"Binance\", \"GoPlus\" etc. and note data is live.\n- **Honest about limitations**: If a tool fails or data is unavailable, say so clearly.\n- **Never give financial advice**: Present data, highlight risks, let the user decide.\n- **Disclose uncertainty**: If data is incomplete, say so.\n- **Format for readability**: Use bullet points, numbers, and clear structure.\n\n## Response Style\n\n- Lead with the key finding or answer\n- Support with specific numbers from tool results\n- Include data source and freshness (\"live from DexScreener\", \"CoinGecko data\")\n- End with risk factors or suggested follow-up\n- Keep concise unless a deep dive is requested`;\n}\n\n/** Static export for backwards compatibility (date set at module load time). */\nexport const CHAT_SYSTEM_PROMPT = buildChatSystemPrompt();\n\n// ---------------------------------------------------------------------------\n// System prompt for providers WITHOUT tool support (e.g. Ollama)\n// The context injector appends real-time data to this prompt.\n// ---------------------------------------------------------------------------\n\nexport const OLLAMA_SYSTEM_PROMPT = `You are Vizzor, an AI-powered crypto chronovisor built by 7ayLabs. You analyze real-time blockchain data to provide market intelligence, predictions, and risk assessments.\n\n## CORE RULES\n\n1. **ZERO HALLUCINATION** — The data block below is your ONLY source of truth. ONLY cite numbers and facts that appear in the data. If something is missing, say \"data not available\" — NEVER invent team names, websites, supply numbers, roadmaps, or partnerships. NEVER use placeholders like \"[Insert Name]\".\n\n2. **NEVER ECHO RAW DATA** — You receive data between \"--- REAL-TIME DATA ---\" markers. NEVER output those markers or dump raw data. ANALYZE and present insights naturally.\n\n3. **FOLLOW THE QUERY TYPE** — The data block includes a \"QUERY TYPE:\" instruction. Follow it:\n - **NEWS**: Summarize headlines, add market context, group by theme. Conversational tone.\n - **TRENDS**: Lead with market sentiment, list top movers with metrics, mention notable events.\n - **TOKEN ANALYSIS**: Deep dive into that specific token — price, security, signals, risks.\n - **PREDICTION**: Price targets with dollar values, timeframes, confidence, invalidation conditions.\n - **GENERAL**: Answer the question naturally using data as context. Don't force a token analysis.\n\n4. **ANALYZE ANY TOKEN** — Token names can be anything (PEPE, DOGE, BONK, TRUMP, etc.). Never refuse. Honest analysis, no filter.\n\n## TOKEN ANALYSIS FORMAT (only for token-specific queries)\n\nWhen analyzing a specific token, structure as:\n1. **Verdict** — one sentence (e.g., \"ETH is at $2,112, showing bullish momentum with Greed sentiment\")\n2. **Market Data** — price, volume, liquidity, buy/sell ratio (cite sources)\n3. **Security** — GoPlus findings if available (honeypot, tax, flags, risk level)\n4. **Signals** — use the pre-computed COMPOSITE direction and confidence\n5. **Price Prediction** — use the PRICE PREDICTION SCENARIOS from the data (actual $ values, 3 timeframes)\n6. **Risks** — red flags, what could go wrong\n\n## PRICE PREDICTIONS\n\nWhen PRICE PREDICTION SCENARIOS exist in the data:\n- Present the exact dollar values for short/medium/long term\n- Include bullish, most likely, and bearish scenarios\n- Add key support/resistance levels\n- State confidence level and what would invalidate the prediction\n- NEVER say \"difficult to predict\" — use the computed scenarios\n\n## STYLE\n\n- Be concise and professional\n- Lead with the key insight, not a preamble\n- Cite data sources naturally: \"BTC at $71,415 (Binance)\" or \"Fear & Greed at 65 (Greed)\"\n- Use bullet points for data, paragraphs for analysis\n- End token analyses with risk disclaimer`;\n","// ---------------------------------------------------------------------------\n// AI client facade — thin wrapper over the active AI provider\n// ---------------------------------------------------------------------------\n\nimport type { VizzorConfig } from '../config/schema.js';\nimport type { AIProvider, ToolHandler, AITool } from './providers/types.js';\nimport { initializeProvider } from './providers/registry.js';\nimport { buildContextBlock } from './context-injector.js';\n\n// Re-export types so existing consumers don't need to change their import paths.\nexport type { ToolHandler, AITool } from './providers/types.js';\n\n// ---------------------------------------------------------------------------\n// Module state\n// ---------------------------------------------------------------------------\n\nlet provider: AIProvider | undefined;\nlet config: VizzorConfig | undefined;\nlet toolHandler: ToolHandler | undefined;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Initialise the AI layer with the given config. Creates and initialises the\n * provider specified by `cfg.ai.provider`.\n */\nexport function setConfig(cfg: VizzorConfig): void {\n config = cfg;\n provider = initializeProvider(cfg.ai.provider, cfg);\n}\n\n/**\n * Register the tool executor that the agentic loop invokes when the AI\n * requests a tool call.\n */\nexport function setToolHandler(handler: ToolHandler): void {\n toolHandler = handler;\n}\n\n/**\n * Return the current VizzorConfig, or `undefined` if not yet set.\n */\nexport function getConfig(): VizzorConfig | undefined {\n return config;\n}\n\n/**\n * Return the registered tool handler, or `undefined` if none is set.\n */\nexport function getToolHandler(): ToolHandler | undefined {\n return toolHandler;\n}\n\n/**\n * Return the active AI provider.\n *\n * @throws If no provider has been initialised.\n */\nexport function getProvider(): AIProvider {\n if (!provider) {\n throw new Error('AI provider has not been initialised. Call setConfig first.');\n }\n return provider;\n}\n\n/**\n * Switch to a different provider at runtime (e.g. from the `/provider` TUI\n * command). Re-initialises the provider with the current config.\n */\nexport function switchProvider(name: string): void {\n if (!config) {\n throw new Error('Config has not been set. Call setConfig first.');\n }\n provider = initializeProvider(name, config);\n}\n\n/**\n * Send a message to the active provider and return the full text response.\n * Includes agentic tool-use loop when tools and a tool handler are available.\n *\n * For providers that don't support tool use (e.g. Ollama), real-time data\n * is automatically fetched and injected into the system prompt.\n */\nexport async function analyze(\n systemPrompt: string,\n userMessage: string,\n tools?: AITool[],\n): Promise<string> {\n const p = getProvider();\n\n if (!p.supportsTools) {\n // Inject real-time data into the prompt for providers without tool use\n const { OLLAMA_SYSTEM_PROMPT } = await import('./prompts/chat.js');\n const context = await buildContextBlock(userMessage);\n const enrichedPrompt = OLLAMA_SYSTEM_PROMPT + (context ? '\\n' + context : '');\n return p.analyze(enrichedPrompt, userMessage);\n }\n\n return p.analyze(systemPrompt, userMessage, tools, toolHandler);\n}\n","// ---------------------------------------------------------------------------\n// Bytecode scanner — detect dangerous function selectors and opcodes\n// No external API needed — works purely on contract bytecode.\n// ---------------------------------------------------------------------------\n\nimport { getMLClient } from '../../ml/client.js';\nimport type { BytecodeRiskMLResult } from '../../ml/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface BytecodeFinding {\n name: string;\n selector: string;\n type: 'function' | 'opcode';\n severity: 'info' | 'warning' | 'critical';\n description: string;\n}\n\n// ---------------------------------------------------------------------------\n// Known dangerous function selectors (4-byte keccak256 prefixes)\n// ---------------------------------------------------------------------------\n\nconst DANGEROUS_FUNCTIONS: {\n selector: string;\n name: string;\n severity: BytecodeFinding['severity'];\n description: string;\n}[] = [\n // Mint functions — inflation risk\n {\n selector: '40c10f19',\n name: 'mint(address,uint256)',\n severity: 'critical',\n description: 'Owner can mint new tokens (inflation/dilution risk)',\n },\n {\n selector: 'a0712d68',\n name: 'mint(uint256)',\n severity: 'critical',\n description: 'Mint function detected (inflation/dilution risk)',\n },\n\n // Pause functions — can freeze trading\n {\n selector: '8456cb59',\n name: 'pause()',\n severity: 'warning',\n description: 'Contract can be paused (trading may be frozen)',\n },\n {\n selector: '3f4ba83a',\n name: 'unpause()',\n severity: 'info',\n description: 'Unpause function exists (paired with pause)',\n },\n\n // Blacklist functions — can block addresses\n {\n selector: 'ef01df4f',\n name: 'blacklistAddress(address)',\n severity: 'critical',\n description: 'Can blacklist addresses (honeypot risk)',\n },\n {\n selector: '44337ea1',\n name: 'blacklist(address)',\n severity: 'critical',\n description: 'Can blacklist addresses (honeypot risk)',\n },\n {\n selector: 'e47d6060',\n name: 'setBlacklist(address,bool)',\n severity: 'critical',\n description: 'Can toggle address blacklist (honeypot risk)',\n },\n\n // Fee/tax manipulation\n {\n selector: 'f2fde38b',\n name: 'transferOwnership(address)',\n severity: 'info',\n description: 'Ownership can be transferred',\n },\n {\n selector: '715018a6',\n name: 'renounceOwnership()',\n severity: 'info',\n description: 'Ownership can be renounced (positive indicator)',\n },\n\n // Trading controls\n {\n selector: '49bd5a5e',\n name: 'uniswapV2Pair()',\n severity: 'info',\n description: 'Uniswap V2 pair reference detected',\n },\n {\n selector: 'c9567bf9',\n name: 'openTrading()',\n severity: 'warning',\n description: 'Trading can be opened/closed by owner',\n },\n\n // Max transaction/wallet limits\n {\n selector: '313ce567',\n name: 'decimals()',\n severity: 'info',\n description: 'Standard ERC20 decimals function',\n },\n];\n\n// Dangerous opcodes (single-byte)\nconst DANGEROUS_OPCODES: {\n byte: string;\n name: string;\n severity: BytecodeFinding['severity'];\n description: string;\n}[] = [\n {\n byte: 'ff',\n name: 'SELFDESTRUCT',\n severity: 'critical',\n description: 'Contract can self-destruct (all funds lost)',\n },\n];\n\n// ---------------------------------------------------------------------------\n// Scanner\n// ---------------------------------------------------------------------------\n\n/**\n * Scan contract bytecode for known dangerous function selectors and opcodes.\n * Returns an array of findings sorted by severity.\n */\nexport function scanBytecode(code: string): BytecodeFinding[] {\n const findings: BytecodeFinding[] = [];\n\n // Normalize: remove 0x prefix, lowercase\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n\n if (normalized.length < 2) {\n return findings;\n }\n\n // Check for dangerous function selectors\n for (const func of DANGEROUS_FUNCTIONS) {\n if (normalized.includes(func.selector)) {\n findings.push({\n name: func.name,\n selector: `0x${func.selector}`,\n type: 'function',\n severity: func.severity,\n description: func.description,\n });\n }\n }\n\n // Check for dangerous opcodes — only check for SELFDESTRUCT\n // (delegatecall is common and normal in proxy patterns)\n for (const op of DANGEROUS_OPCODES) {\n // SELFDESTRUCT: look for the ff opcode — it's common as a byte but\n // specifically look for the PUSH pattern before it or it at function boundaries\n if (op.byte === 'ff' && normalized.includes('ff')) {\n // Simple heuristic: if the bytecode contains SELFDESTRUCT opcode\n // at a position that could be a standalone instruction\n // (not part of PUSH data), flag it.\n // We check for common patterns: ...XX ff (where XX is not a PUSH)\n const idx = normalized.indexOf('ff');\n if (idx > 0 && idx % 2 === 0) {\n findings.push({\n name: op.name,\n selector: `0x${op.byte}`,\n type: 'opcode',\n severity: op.severity,\n description: op.description,\n });\n }\n }\n }\n\n // Sort: critical first, then warning, then info\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n findings.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));\n\n return findings;\n}\n\n/**\n * Quick check: does the bytecode contain any mint-related selectors?\n */\nexport function hasMintFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return normalized.includes('40c10f19') || normalized.includes('a0712d68');\n}\n\n/**\n * Quick check: does the bytecode contain pause-related selectors?\n */\nexport function hasPauseFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return normalized.includes('8456cb59');\n}\n\n/**\n * Quick check: does the bytecode contain blacklist-related selectors?\n */\nexport function hasBlacklistFunction(code: string): boolean {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n return (\n normalized.includes('ef01df4f') ||\n normalized.includes('44337ea1') ||\n normalized.includes('e47d6060')\n );\n}\n\n/**\n * Calculate Shannon entropy of byte distribution in bytecode.\n * Higher entropy = more random/packed code, lower = repetitive patterns.\n */\nexport function calculateEntropy(code: string): number {\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n if (normalized.length < 2) return 0;\n\n // Count byte frequencies (pairs of hex chars)\n const counts = new Map<string, number>();\n const totalBytes = Math.floor(normalized.length / 2);\n\n for (let i = 0; i < normalized.length - 1; i += 2) {\n const byte = normalized.slice(i, i + 2);\n counts.set(byte, (counts.get(byte) ?? 0) + 1);\n }\n\n // Shannon entropy\n let entropy = 0;\n for (const count of counts.values()) {\n const p = count / totalBytes;\n if (p > 0) {\n entropy -= p * Math.log2(p);\n }\n }\n\n return entropy;\n}\n\nexport interface BytecodeScanResult {\n findings: BytecodeFinding[];\n mlRisk?: BytecodeRiskMLResult;\n}\n\n/**\n * ML-enhanced bytecode scan. Runs rule-based scan then ML risk scoring.\n */\nexport async function scanBytecodeML(code: string): Promise<BytecodeScanResult> {\n const findings = scanBytecode(code);\n const normalized = code.startsWith('0x') ? code.slice(2).toLowerCase() : code.toLowerCase();\n\n const mlClient = getMLClient();\n if (!mlClient) return { findings };\n\n try {\n const hasSd = findings.some((f) => f.name === 'SELFDESTRUCT');\n const hasDc = normalized.includes('f4'); // DELEGATECALL opcode\n const selectorCount = DANGEROUS_FUNCTIONS.filter((f) => normalized.includes(f.selector)).length;\n const entropy = calculateEntropy(code);\n\n const result = await mlClient.scoreBytecodeRisk({\n bytecode_size: Math.floor(normalized.length / 2),\n is_verified: 0,\n has_selfdestruct: hasSd ? 1 : 0,\n has_delegatecall: hasDc ? 1 : 0,\n selector_count: selectorCount,\n opcode_entropy: entropy,\n has_mint: hasMintFunction(code) ? 1 : 0,\n has_pause: hasPauseFunction(code) ? 1 : 0,\n has_blacklist: hasBlacklistFunction(code) ? 1 : 0,\n has_proxy: normalized.includes('f4') ? 1 : 0,\n });\n\n if (result) {\n return { findings, mlRisk: result };\n }\n } catch {\n // ML unavailable\n }\n\n return { findings };\n}\n","import type { ChainAdapter } from '../../chains/types.js';\nimport {\n hasMintFunction,\n hasPauseFunction,\n hasBlacklistFunction,\n scanBytecode,\n} from './bytecode-scanner.js';\nimport { getMLClient, initMLClient } from '../../ml/client.js';\nimport { getConfig } from '../../config/loader.js';\nimport type { RugMLResult } from '../../ml/types.js';\n\nexport interface RugIndicators {\n isHoneypot: boolean;\n hasLiquidityLock: boolean;\n ownerCanMint: boolean;\n ownerCanPause: boolean;\n hasBlacklist: boolean;\n highSellTax: boolean;\n riskScore: number;\n details: RugDetail[];\n mlAnalysis?: RugMLResult;\n}\n\nexport interface RugDetail {\n check: string;\n passed: boolean;\n description: string;\n severity: 'info' | 'warning' | 'critical';\n}\n\nexport async function detectRugIndicators(\n tokenAddress: string,\n adapter: ChainAdapter,\n): Promise<RugIndicators> {\n const details: RugDetail[] = [];\n\n // Get contract bytecode for analysis\n const code = await adapter.getContractCode(tokenAddress).catch(() => '');\n const hasCode = code.length > 2;\n\n details.push({\n check: 'Contract Verified',\n passed: hasCode,\n description: hasCode ? 'Contract bytecode is available' : 'No contract code found',\n severity: hasCode ? 'info' : 'warning',\n });\n\n // Check basic token info\n try {\n const info = await adapter.getTokenInfo(tokenAddress);\n const tokenValid = info.name.length > 0 && info.symbol.length > 0;\n details.push({\n check: 'Valid Token',\n passed: tokenValid,\n description: tokenValid\n ? `Token: ${info.name} (${info.symbol})`\n : 'Unable to read token metadata',\n severity: tokenValid ? 'info' : 'warning',\n });\n } catch {\n details.push({\n check: 'Valid Token',\n passed: false,\n description: 'Failed to read token contract',\n severity: 'critical',\n });\n }\n\n // Bytecode scanning for dangerous functions\n const canMint = hasCode && hasMintFunction(code);\n const canPause = hasCode && hasPauseFunction(code);\n const hasBlacklist_ = hasCode && hasBlacklistFunction(code);\n\n details.push({\n check: 'No Mint Function',\n passed: !canMint,\n description: canMint\n ? 'Owner can mint new tokens (inflation risk)'\n : 'No owner mint capability detected',\n severity: canMint ? 'critical' : 'info',\n });\n\n details.push({\n check: 'No Pause Function',\n passed: !canPause,\n description: canPause\n ? 'Owner can pause transfers (honeypot risk)'\n : 'No pause capability detected',\n severity: canPause ? 'warning' : 'info',\n });\n\n details.push({\n check: 'No Blacklist Function',\n passed: !hasBlacklist_,\n description: hasBlacklist_\n ? 'Owner can blacklist addresses (honeypot risk)'\n : 'No blacklist capability detected',\n severity: hasBlacklist_ ? 'critical' : 'info',\n });\n\n // Add all bytecode findings as details\n if (hasCode) {\n const findings = scanBytecode(code);\n for (const finding of findings) {\n // Skip duplicates we already added above\n if (\n finding.name.includes('mint') ||\n finding.name.includes('pause') ||\n finding.name.includes('blacklist') ||\n finding.name.includes('Blacklist')\n ) {\n continue;\n }\n\n if (finding.severity !== 'info') {\n details.push({\n check: finding.name,\n passed: false,\n description: finding.description,\n severity: finding.severity,\n });\n }\n }\n }\n\n const riskScore = calculateRugRisk(details);\n\n // ML enhancement — call rug detector model if available\n let mlAnalysis: RugMLResult | undefined;\n try {\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (mlClient) {\n const mlResult = await mlClient.predictRug({\n bytecode_size: hasCode ? code.length : 0,\n is_verified: hasCode ? 1 : 0,\n holder_concentration: 0,\n has_proxy: 0,\n has_mint: canMint ? 1 : 0,\n has_pause: canPause ? 1 : 0,\n has_blacklist: hasBlacklist_ ? 1 : 0,\n liquidity_locked: 0,\n buy_tax: 0,\n sell_tax: 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: 0,\n is_open_source: hasCode ? 1 : 0,\n top10_holder_pct: 0,\n });\n if (mlResult) {\n mlAnalysis = mlResult;\n }\n }\n } catch {\n /* ML unavailable — continue with rule-based */\n }\n\n return {\n isHoneypot: canPause || hasBlacklist_,\n hasLiquidityLock: false,\n ownerCanMint: canMint,\n ownerCanPause: canPause,\n hasBlacklist: hasBlacklist_,\n highSellTax: false,\n riskScore: mlAnalysis\n ? Math.round(riskScore * 0.4 + mlAnalysis.rug_probability * 100 * 0.6)\n : riskScore,\n details,\n mlAnalysis,\n };\n}\n\nfunction calculateRugRisk(details: RugDetail[]): number {\n let score = 0;\n for (const detail of details) {\n if (!detail.passed) {\n switch (detail.severity) {\n case 'critical':\n score += 30;\n break;\n case 'warning':\n score += 15;\n break;\n case 'info':\n score += 5;\n break;\n }\n }\n }\n return Math.min(100, score);\n}\n","// ---------------------------------------------------------------------------\n// Market regime detection — ML-powered with heuristic fallback\n// ---------------------------------------------------------------------------\n\nimport { getMLClient } from '../../ml/client.js';\nimport type { RegimeMLFeatures, MarketRegime } from '../../ml/types.js';\n\nexport type { MarketRegime };\n\nexport interface RegimeResult {\n regime: MarketRegime;\n confidence: number;\n probabilities: Record<string, number>;\n model: string;\n}\n\n/**\n * Detect the current market regime for a symbol.\n * Uses ML regime detector when available, falls back to heuristic.\n */\nexport async function detectMarketRegime(\n _symbol: string,\n features: RegimeMLFeatures,\n): Promise<RegimeResult> {\n const mlClient = getMLClient();\n if (mlClient) {\n try {\n const result = await mlClient.detectRegime(features);\n if (result) {\n return {\n regime: result.regime,\n confidence: result.confidence,\n probabilities: result.probabilities,\n model: result.model,\n };\n }\n } catch {\n // ML unavailable — fallback\n }\n }\n return detectRegimeHeuristic(features);\n}\n\nfunction detectRegimeHeuristic(features: RegimeMLFeatures): RegimeResult {\n const vol = features.volatility_14d;\n const ret7d = features.returns_7d;\n const fg = features.fear_greed;\n const rsi = features.rsi;\n\n let regime: MarketRegime;\n let confidence: number;\n\n if (fg < 15 && ret7d < -20) {\n regime = 'capitulation';\n confidence = 80;\n } else if (vol > 8) {\n regime = 'volatile';\n confidence = 70;\n } else if (vol > 5 && ret7d > 10) {\n regime = 'trending_bull';\n confidence = 65;\n } else if (vol > 5 && ret7d < -10) {\n regime = 'trending_bear';\n confidence = 65;\n } else if (ret7d > 5 && rsi > 55) {\n regime = 'trending_bull';\n confidence = 55;\n } else if (ret7d < -5 && rsi < 45) {\n regime = 'trending_bear';\n confidence = 55;\n } else {\n regime = 'ranging';\n confidence = 60;\n }\n\n const probabilities: Record<string, number> = {\n trending_bull: 0.05,\n trending_bear: 0.05,\n ranging: 0.05,\n volatile: 0.05,\n capitulation: 0.05,\n };\n probabilities[regime] = confidence / 100;\n const remaining = 1.0 - probabilities[regime]!;\n const others = Object.keys(probabilities).filter((k) => k !== regime);\n for (const k of others) {\n probabilities[k] = remaining / others.length;\n }\n\n return {\n regime,\n confidence,\n probabilities,\n model: 'heuristic-regime-detector',\n };\n}\n","import Database from 'better-sqlite3';\nimport { join } from 'node:path';\nimport { getConfigDir } from '../config/loader.js';\n\nlet db: Database.Database | null = null;\n\n/**\n * Returns the lazily-initialized SQLite database instance.\n * Enables WAL mode and creates tables on first access.\n */\nexport function getDb(): Database.Database {\n if (db) {\n return db;\n }\n\n const dbPath = join(getConfigDir(), 'vizzor.db');\n db = new Database(dbPath);\n\n db.pragma('journal_mode = WAL');\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS cache (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n expires_at INTEGER NOT NULL,\n created_at INTEGER NOT NULL\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS watchlist (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n type TEXT NOT NULL CHECK (type IN ('wallet', 'token', 'project')),\n identifier TEXT NOT NULL,\n chain TEXT NOT NULL DEFAULT 'ethereum',\n label TEXT,\n created_at INTEGER NOT NULL,\n UNIQUE (type, identifier, chain)\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS analysis_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n command TEXT NOT NULL,\n input TEXT NOT NULL,\n result TEXT NOT NULL,\n chain TEXT,\n created_at INTEGER NOT NULL\n )\n `);\n\n return db;\n}\n\n/**\n * Returns a cached value parsed from JSON, or null if the key does not exist\n * or has expired.\n */\nexport function getCached<T = unknown>(key: string): T | null {\n const row = getDb().prepare('SELECT value, expires_at FROM cache WHERE key = ?').get(key) as\n | { value: string; expires_at: number }\n | undefined;\n\n if (!row) {\n return null;\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (row.expires_at <= now) {\n getDb().prepare('DELETE FROM cache WHERE key = ?').run(key);\n return null;\n }\n\n try {\n return JSON.parse(row.value) as T;\n } catch {\n // Corrupted cache entry — remove it\n getDb().prepare('DELETE FROM cache WHERE key = ?').run(key);\n return null;\n }\n}\n\n/**\n * Inserts or replaces a cached value with the given TTL in seconds.\n */\nexport function setCache(key: string, value: unknown, ttlSeconds: number): void {\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + ttlSeconds;\n\n getDb()\n .prepare(\n `INSERT OR REPLACE INTO cache (key, value, expires_at, created_at)\n VALUES (?, ?, ?, ?)`,\n )\n .run(key, JSON.stringify(value), expiresAt, now);\n}\n\n/**\n * Deletes all expired cache entries.\n */\nexport function clearExpired(): void {\n const now = Math.floor(Date.now() / 1000);\n getDb().prepare('DELETE FROM cache WHERE expires_at <= ?').run(now);\n}\n","// ---------------------------------------------------------------------------\n// Agent engine — think → analyze → decide → act cycle\n// ---------------------------------------------------------------------------\n\nimport type {\n AgentConfig,\n AgentStrategy,\n AgentSignals,\n AgentCycleResult,\n AgentState,\n} from './types.js';\nimport { fetchTickerPrice, fetchFundingRate } from '../../data/sources/binance.js';\nimport { fetchFearGreedIndex } from '../../data/sources/fear-greed.js';\nimport { getStrategy } from './manager.js';\nimport { logDecision } from './manager.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst logger = createLogger('agent-engine');\n\nexport class AgentEngine {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private running = false;\n private state: AgentState;\n private strategy: AgentStrategy;\n\n constructor(config: AgentConfig) {\n this.strategy = getStrategy(config.strategy);\n // Enforce minimum 30s interval to prevent API abuse\n const interval = Math.max(30, config.interval);\n this.state = {\n config: { ...config, interval },\n status: 'idle',\n lastCycle: null,\n cycleCount: 0,\n error: null,\n };\n }\n\n getState(): AgentState {\n return { ...this.state };\n }\n\n start(): void {\n if (this.state.status === 'running') return;\n\n this.state.status = 'running';\n this.state.error = null;\n this.running = true;\n logger.info(`Agent ${this.state.config.name} started (${this.strategy.name})`);\n\n // Use setTimeout chain to prevent overlapping cycles\n void this.scheduleNextCycle(true);\n }\n\n stop(): void {\n this.running = false;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n this.state.status = 'stopped';\n logger.info(`Agent ${this.state.config.name} stopped`);\n }\n\n private async scheduleNextCycle(immediate = false): Promise<void> {\n if (!this.running) return;\n\n if (!immediate) {\n await new Promise<void>((resolve) => {\n this.timer = setTimeout(resolve, this.state.config.interval * 1000);\n });\n }\n\n if (!this.running) return;\n await this.runCycle();\n\n // Schedule next only after current finishes (no overlap)\n void this.scheduleNextCycle(false);\n }\n\n private async runCycle(): Promise<void> {\n for (const symbol of this.state.config.pairs) {\n try {\n const signals = await this.gatherSignals(symbol);\n const decision = this.strategy.evaluateAsync\n ? await this.strategy.evaluateAsync(signals, symbol)\n : this.strategy.evaluate(signals);\n\n const result: AgentCycleResult = {\n agentId: this.state.config.id,\n symbol,\n timestamp: Date.now(),\n signals,\n decision,\n };\n\n this.state.lastCycle = result;\n this.state.cycleCount++;\n\n // Log to DB\n logDecision(result);\n\n if (decision.action !== 'hold') {\n logger.info(\n `Agent ${this.state.config.name} → ${decision.action.toUpperCase()} ${symbol} (confidence: ${decision.confidence}%)`,\n );\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.state.error = `Cycle error for ${symbol}: ${message}`;\n logger.warn(`Agent ${this.state.config.name} cycle error: ${message}`);\n }\n }\n }\n\n /**\n * Gather all signals for a symbol. Uses Promise.allSettled so partial\n * failures don't block the entire cycle.\n */\n private async gatherSignals(symbol: string): Promise<AgentSignals> {\n const signals: AgentSignals = {\n rsi: null,\n macdHistogram: null,\n ema12: null,\n ema26: null,\n bollingerPercentB: null,\n atr: null,\n obv: null,\n fundingRate: null,\n fearGreed: null,\n priceChange24h: null,\n price: null,\n };\n\n const [priceResult, fundingResult, fgResult] = await Promise.allSettled([\n fetchTickerPrice(symbol),\n fetchFundingRate(symbol),\n fetchFearGreedIndex(1),\n ]);\n\n if (priceResult.status === 'fulfilled') {\n signals.price = priceResult.value.price;\n signals.priceChange24h = priceResult.value.change24h;\n }\n\n if (fundingResult.status === 'fulfilled') {\n signals.fundingRate = fundingResult.value.fundingRate;\n }\n\n if (fgResult.status === 'fulfilled') {\n signals.fearGreed = fgResult.value.current.value;\n }\n\n // Technical analysis signals are gathered lazily via the manager\n // when the TA module is available (requires kline data).\n // For v0.3.0, the engine uses price + derivatives + macro signals.\n // Full TA integration happens in the agent cycle via direct indicator calls.\n\n return signals;\n }\n}\n","// ---------------------------------------------------------------------------\n// Momentum strategy — RSI + MACD confirmation\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\n\n/**\n * Buy when RSI crosses above 30 with MACD confirmation.\n * Sell when RSI drops below 70 or MACD turns bearish.\n */\nexport const momentumStrategy: AgentStrategy = {\n name: 'momentum',\n description: 'RSI reversal + MACD confirmation. Buy oversold bounces, sell overbought peaks.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0; // positive = buy, negative = sell\n\n // RSI signals\n if (signals.rsi !== null) {\n if (signals.rsi < 30) {\n score += 40;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — oversold, buy signal`);\n } else if (signals.rsi < 40) {\n score += 20;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — approaching oversold`);\n } else if (signals.rsi > 70) {\n score -= 40;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — overbought, sell signal`);\n } else if (signals.rsi > 60) {\n score -= 15;\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — elevated, caution`);\n } else {\n reasoning.push(`RSI ${signals.rsi.toFixed(1)} — neutral`);\n }\n }\n\n // MACD confirmation\n if (signals.macdHistogram !== null) {\n if (signals.macdHistogram > 0) {\n score += 25;\n reasoning.push(\n `MACD histogram positive (${signals.macdHistogram.toFixed(4)}) — bullish momentum`,\n );\n } else {\n score -= 25;\n reasoning.push(\n `MACD histogram negative (${signals.macdHistogram.toFixed(4)}) — bearish momentum`,\n );\n }\n }\n\n // Bollinger %B for extreme levels\n if (signals.bollingerPercentB !== null) {\n if (signals.bollingerPercentB < 0.1) {\n score += 15;\n reasoning.push(\n `BB %B ${signals.bollingerPercentB.toFixed(2)} — near lower band, bounce potential`,\n );\n } else if (signals.bollingerPercentB > 0.9) {\n score -= 15;\n reasoning.push(\n `BB %B ${signals.bollingerPercentB.toFixed(2)} — near upper band, pullback risk`,\n );\n }\n }\n\n // Funding rate as contrarian signal\n if (signals.fundingRate !== null) {\n if (signals.fundingRate > 0.0005) {\n score -= 10;\n reasoning.push(\n `High funding rate ${(signals.fundingRate * 100).toFixed(4)}% — overleveraged longs`,\n );\n } else if (signals.fundingRate < -0.0003) {\n score += 10;\n reasoning.push(\n `Negative funding ${(signals.fundingRate * 100).toFixed(4)}% — capitulation signal`,\n );\n }\n }\n\n const action = score > 25 ? 'buy' : score < -25 ? 'sell' : 'hold';\n const confidence = Math.min(95, Math.abs(score));\n\n return { action, confidence, reasoning };\n },\n};\n\n/**\n * ML-enhanced momentum evaluation. Falls back to rule-based evaluate().\n */\nexport async function evaluateMomentumML(signals: AgentSignals): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return momentumStrategy.evaluate(signals);\n\n try {\n const result = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: 'ranging',\n });\n\n if (result && result.confidence > 40) {\n return {\n action: result.action,\n confidence: Math.round(result.confidence),\n reasoning: [`ML momentum: ${result.action}`, ...result.reasoning],\n };\n }\n } catch {\n // ML unavailable\n }\n return momentumStrategy.evaluate(signals);\n}\n","// ---------------------------------------------------------------------------\n// Trend-following strategy — EMA crossover + rising OI\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\n\n/**\n * Buy when EMA(12) crosses above EMA(26) with rising open interest.\n * Sell on death cross (EMA(12) < EMA(26)).\n */\nexport const trendFollowingStrategy: AgentStrategy = {\n name: 'trend-following',\n description: 'EMA crossover trend detection. Buy golden cross, sell death cross.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0;\n\n // EMA crossover — primary signal\n if (signals.ema12 !== null && signals.ema26 !== null) {\n const diff = signals.ema12 - signals.ema26;\n const pctDiff = signals.ema26 !== 0 ? (diff / signals.ema26) * 100 : 0;\n\n if (diff > 0) {\n score += 35;\n reasoning.push(`EMA(12) above EMA(26) by ${pctDiff.toFixed(2)}% — bullish trend`);\n } else {\n score -= 35;\n reasoning.push(`EMA(12) below EMA(26) by ${Math.abs(pctDiff).toFixed(2)}% — bearish trend`);\n }\n\n // Stronger signal when gap is widening\n if (Math.abs(pctDiff) > 2) {\n const extra = diff > 0 ? 15 : -15;\n score += extra;\n reasoning.push(\n `Strong ${diff > 0 ? 'bullish' : 'bearish'} divergence (${Math.abs(pctDiff).toFixed(2)}%)`,\n );\n }\n }\n\n // OBV confirmation\n if (signals.obv !== null) {\n if (signals.obv > 0) {\n score += 15;\n reasoning.push('OBV positive — volume confirms upward trend');\n } else if (signals.obv < 0) {\n score -= 15;\n reasoning.push('OBV negative — volume confirms downward trend');\n }\n }\n\n // 24h price change as trend confirmation\n if (signals.priceChange24h !== null) {\n if (signals.priceChange24h > 3) {\n score += 10;\n reasoning.push(\n `24h change +${signals.priceChange24h.toFixed(1)}% — strong upward momentum`,\n );\n } else if (signals.priceChange24h < -3) {\n score -= 10;\n reasoning.push(\n `24h change ${signals.priceChange24h.toFixed(1)}% — strong downward momentum`,\n );\n }\n }\n\n // Fear & Greed as macro overlay\n if (signals.fearGreed !== null) {\n if (signals.fearGreed > 80 && score > 0) {\n score -= 10;\n reasoning.push(`Extreme Greed (${signals.fearGreed}) — contrarian risk on longs`);\n } else if (signals.fearGreed < 20 && score < 0) {\n score += 10;\n reasoning.push(`Extreme Fear (${signals.fearGreed}) — contrarian support for bounce`);\n }\n }\n\n // ATR for volatility filter\n if (signals.atr !== null && signals.price !== null && signals.price > 0) {\n const atrPct = (signals.atr / signals.price) * 100;\n if (atrPct > 5) {\n reasoning.push(`High volatility (ATR ${atrPct.toFixed(2)}%) — wider stops needed`);\n }\n }\n\n const action = score > 25 ? 'buy' : score < -25 ? 'sell' : 'hold';\n const confidence = Math.min(95, Math.abs(score));\n\n return { action, confidence, reasoning };\n },\n};\n\n/**\n * ML-enhanced trend-following evaluation. Falls back to rule-based evaluate().\n */\nexport async function evaluateTrendFollowingML(signals: AgentSignals): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return trendFollowingStrategy.evaluate(signals);\n\n try {\n const result = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: 'ranging',\n });\n\n if (result && result.confidence > 40) {\n return {\n action: result.action,\n confidence: Math.round(result.confidence),\n reasoning: [`ML trend-following: ${result.action}`, ...result.reasoning],\n };\n }\n } catch {\n // ML unavailable\n }\n return trendFollowingStrategy.evaluate(signals);\n}\n","// ---------------------------------------------------------------------------\n// ML-Adaptive Strategy — contextual bandit approach using ML predictions\n// ---------------------------------------------------------------------------\n\nimport type { AgentStrategy, AgentSignals, AgentDecision } from '../types.js';\nimport { getMLClient } from '../../../ml/client.js';\nimport { detectMarketRegime } from '../../trends/regime.js';\n\nexport const mlAdaptiveStrategy: AgentStrategy = {\n name: 'ml-adaptive',\n description:\n 'ML-powered strategy using contextual bandit approach. Uses LSTM/RF predictions ' +\n 'when available, falls back to rule-based when < 100 training samples.',\n\n evaluate(signals: AgentSignals): AgentDecision {\n return evaluateWithRules(signals);\n },\n\n async evaluateAsync(signals: AgentSignals, symbol: string): Promise<AgentDecision> {\n return evaluateWithML(symbol, signals);\n },\n};\n\nfunction evaluateWithRules(signals: AgentSignals): AgentDecision {\n const reasoning: string[] = [];\n let score = 0;\n\n // RSI with adaptive thresholds\n if (signals.rsi !== null) {\n if (signals.rsi < 25) {\n score += 35;\n reasoning.push(`RSI deeply oversold (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi < 35) {\n score += 20;\n reasoning.push(`RSI oversold zone (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi > 75) {\n score -= 35;\n reasoning.push(`RSI deeply overbought (${signals.rsi.toFixed(0)})`);\n } else if (signals.rsi > 65) {\n score -= 20;\n reasoning.push(`RSI overbought zone (${signals.rsi.toFixed(0)})`);\n }\n }\n\n // MACD with momentum confirmation\n if (signals.macdHistogram !== null) {\n if (signals.macdHistogram > 0) {\n score += 15;\n reasoning.push('MACD bullish momentum');\n } else {\n score -= 15;\n reasoning.push('MACD bearish momentum');\n }\n }\n\n // EMA crossover\n if (signals.ema12 !== null && signals.ema26 !== null) {\n const crossPct =\n signals.ema26 !== 0 ? ((signals.ema12 - signals.ema26) / signals.ema26) * 100 : 0;\n if (crossPct > 0.5) {\n score += 20;\n reasoning.push(`Golden cross (EMA12 > EMA26 by ${crossPct.toFixed(2)}%)`);\n } else if (crossPct < -0.5) {\n score -= 20;\n reasoning.push(`Death cross (EMA12 < EMA26 by ${Math.abs(crossPct).toFixed(2)}%)`);\n }\n }\n\n // Bollinger Bands\n if (signals.bollingerPercentB !== null) {\n if (signals.bollingerPercentB < 0.1) {\n score += 15;\n reasoning.push('Price at lower Bollinger Band — potential bounce');\n } else if (signals.bollingerPercentB > 0.9) {\n score -= 15;\n reasoning.push('Price at upper Bollinger Band — potential resistance');\n }\n }\n\n // Funding rate (contrarian)\n if (signals.fundingRate !== null) {\n if (signals.fundingRate > 0.0005) {\n score -= 10;\n reasoning.push('High funding rate — overleveraged longs');\n } else if (signals.fundingRate < -0.0003) {\n score += 10;\n reasoning.push('Negative funding — capitulation signal');\n }\n }\n\n // Fear & Greed (contrarian)\n if (signals.fearGreed !== null) {\n if (signals.fearGreed < 20) {\n score += 10;\n reasoning.push('Extreme fear — contrarian bullish');\n } else if (signals.fearGreed > 80) {\n score -= 10;\n reasoning.push('Extreme greed — contrarian bearish');\n }\n }\n\n // 24h trend confirmation\n if (signals.priceChange24h !== null) {\n if (signals.priceChange24h > 5) {\n score += 10;\n } else if (signals.priceChange24h < -5) {\n score -= 10;\n }\n }\n\n const confidence = Math.min(95, Math.abs(score));\n if (score > 20) {\n return { action: 'buy', confidence, reasoning };\n } else if (score < -20) {\n return { action: 'sell', confidence, reasoning };\n }\n return {\n action: 'hold',\n confidence: Math.max(30, 50 - Math.abs(score)),\n reasoning: [...reasoning, 'Mixed signals — holding'],\n };\n}\n\nexport async function evaluateWithML(\n symbol: string,\n signals: AgentSignals,\n): Promise<AgentDecision> {\n const mlClient = getMLClient();\n if (!mlClient) return evaluateWithRules(signals);\n\n try {\n // Step 1: detect market regime\n const regime = await detectMarketRegime(symbol, {\n returns_1d: signals.priceChange24h ?? 0,\n returns_7d: 0,\n volatility_14d:\n signals.atr !== null && signals.price !== null && signals.price > 0\n ? (signals.atr / signals.price) * 100\n : 3,\n volume_ratio: 1,\n rsi: signals.rsi ?? 50,\n bb_width: 0,\n fear_greed: signals.fearGreed ?? 50,\n funding_rate: signals.fundingRate ?? 0,\n price_vs_sma200: 0,\n });\n\n // Step 2: call strategy bandit with regime context\n const strategyResult = await mlClient.evaluateStrategy({\n rsi: signals.rsi ?? 50,\n macd_histogram: signals.macdHistogram ?? 0,\n ema12: signals.ema12 ?? 0,\n ema26: signals.ema26 ?? 0,\n bollinger_pct_b: signals.bollingerPercentB ?? 0.5,\n atr: signals.atr ?? 0,\n obv: signals.obv ?? 0,\n funding_rate: signals.fundingRate ?? 0,\n fear_greed: signals.fearGreed ?? 50,\n price_change_24h: signals.priceChange24h ?? 0,\n price: signals.price ?? 0,\n regime: regime.regime,\n });\n\n if (strategyResult && strategyResult.confidence > 60) {\n return {\n action: strategyResult.action,\n confidence: Math.round(strategyResult.confidence),\n reasoning: [\n `Regime: ${regime.regime} (${regime.confidence.toFixed(0)}% confidence)`,\n ...strategyResult.reasoning,\n ],\n };\n }\n\n // Low ML confidence — blend with rules\n const ruleDecision = evaluateWithRules(signals);\n return {\n action: ruleDecision.action,\n confidence: Math.round(((strategyResult?.confidence ?? 0) + ruleDecision.confidence) / 2),\n reasoning: [\n `Regime: ${regime.regime}`,\n ...(strategyResult?.reasoning ?? []),\n '(Low ML confidence — blending with rules)',\n ...ruleDecision.reasoning,\n ],\n };\n } catch {\n return evaluateWithRules(signals);\n }\n}\n","// ---------------------------------------------------------------------------\n// Agent manager — CRUD, lifecycle, strategy registry\n// ---------------------------------------------------------------------------\n\nimport { randomUUID } from 'node:crypto';\nimport { getDb } from '../../data/cache.js';\nimport type { AgentConfig, AgentState, AgentStrategy, AgentCycleResult } from './types.js';\nimport { AgentEngine } from './engine.js';\nimport { momentumStrategy } from './strategies/momentum.js';\nimport { trendFollowingStrategy } from './strategies/trend-following.js';\nimport { mlAdaptiveStrategy } from './strategies/ml-adaptive.js';\n\n// ---------------------------------------------------------------------------\n// Strategy registry\n// ---------------------------------------------------------------------------\n\nconst STRATEGIES: Record<string, AgentStrategy> = {\n momentum: momentumStrategy,\n 'trend-following': trendFollowingStrategy,\n 'ml-adaptive': mlAdaptiveStrategy,\n};\n\nexport function getStrategy(name: string): AgentStrategy {\n const strategy = STRATEGIES[name];\n if (!strategy) {\n throw new Error(`Unknown strategy: ${name}. Available: ${Object.keys(STRATEGIES).join(', ')}`);\n }\n return strategy;\n}\n\nexport function listStrategies(): string[] {\n return Object.keys(STRATEGIES);\n}\n\n// ---------------------------------------------------------------------------\n// Running engines\n// ---------------------------------------------------------------------------\n\nconst engines = new Map<string, AgentEngine>();\n\n// ---------------------------------------------------------------------------\n// DB helpers\n// ---------------------------------------------------------------------------\n\nfunction ensureAgentTables(): void {\n const db = getDb();\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS agents (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n strategy TEXT NOT NULL,\n pairs TEXT NOT NULL,\n interval_seconds INTEGER NOT NULL DEFAULT 60,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `);\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS agent_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n symbol TEXT NOT NULL,\n action TEXT NOT NULL,\n confidence INTEGER NOT NULL,\n reasoning TEXT NOT NULL,\n signals TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY (agent_id) REFERENCES agents(id)\n )\n `);\n}\n\n// ---------------------------------------------------------------------------\n// CRUD\n// ---------------------------------------------------------------------------\n\nexport function createAgent(\n name: string,\n strategy: string,\n pairs: string[],\n interval = 60,\n): AgentConfig {\n ensureAgentTables();\n\n // Validate strategy\n getStrategy(strategy);\n\n // Check for duplicate name\n const existing = getAgentByName(name);\n if (existing) {\n throw new Error(`Agent \"${name}\" already exists. Delete it first or choose a different name.`);\n }\n\n const id = randomUUID();\n const now = Date.now();\n\n getDb()\n .prepare(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(id, name, strategy, JSON.stringify(pairs), interval, now, now);\n\n return { id, name, strategy, pairs, interval, createdAt: now, updatedAt: now };\n}\n\nexport function listAgents(): AgentConfig[] {\n ensureAgentTables();\n\n const rows = getDb().prepare('SELECT * FROM agents ORDER BY created_at DESC').all() as {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }[];\n\n return rows.map((r) => ({\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: JSON.parse(r.pairs) as string[],\n interval: r.interval_seconds,\n createdAt: r.created_at,\n updatedAt: r.updated_at,\n }));\n}\n\nexport function getAgentById(id: string): AgentConfig | null {\n ensureAgentTables();\n\n const row = getDb().prepare('SELECT * FROM agents WHERE id = ?').get(id) as\n | {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }\n | undefined;\n\n if (!row) return null;\n\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function getAgentByName(name: string): AgentConfig | null {\n ensureAgentTables();\n\n const row = getDb().prepare('SELECT * FROM agents WHERE name = ?').get(name) as\n | {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n }\n | undefined;\n\n if (!row) return null;\n\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport function deleteAgent(id: string): boolean {\n ensureAgentTables();\n\n // Stop engine if running\n const engine = engines.get(id);\n if (engine) {\n engine.stop();\n engines.delete(id);\n }\n\n getDb().prepare('DELETE FROM agent_decisions WHERE agent_id = ?').run(id);\n const result = getDb().prepare('DELETE FROM agents WHERE id = ?').run(id);\n\n return result.changes > 0;\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle\n// ---------------------------------------------------------------------------\n\nexport function startAgent(id: string): AgentState {\n const config = getAgentById(id);\n if (!config) throw new Error(`Agent not found: ${id}`);\n\n // Check if already running — prevent double-start race\n const existing = engines.get(id);\n if (existing) {\n const state = existing.getState();\n if (state.status === 'running') {\n return state;\n }\n }\n\n const engine = new AgentEngine(config);\n engines.set(id, engine);\n\n engine.start();\n return engine.getState();\n}\n\nexport function stopAgent(id: string): AgentState {\n const engine = engines.get(id);\n if (!engine) {\n const config = getAgentById(id);\n if (!config) throw new Error(`Agent not found: ${id}`);\n return { config, status: 'idle', lastCycle: null, cycleCount: 0, error: null };\n }\n\n engine.stop();\n return engine.getState();\n}\n\nexport function getAgentStatus(id: string): AgentState | null {\n const engine = engines.get(id);\n if (engine) return engine.getState();\n\n // Agent exists but not running\n const config = getAgentById(id);\n if (!config) return null;\n\n return {\n config,\n status: 'idle',\n lastCycle: null,\n cycleCount: 0,\n error: null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Decision logging\n// ---------------------------------------------------------------------------\n\nlet pruneCounter = 0;\n\nexport function logDecision(result: AgentCycleResult): void {\n ensureAgentTables();\n\n getDb()\n .prepare(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n );\n\n // Prune old decisions every 100 log calls to prevent unbounded growth\n pruneCounter++;\n if (pruneCounter >= 100) {\n pruneCounter = 0;\n pruneDecisions(result.agentId, 1000);\n }\n}\n\n/**\n * Prune old decisions beyond the retention limit per agent.\n * Keeps at most `keep` most recent decisions.\n */\nexport function pruneDecisions(agentId: string, keep = 1000): number {\n ensureAgentTables();\n\n const result = getDb()\n .prepare(\n `DELETE FROM agent_decisions WHERE agent_id = ? AND id NOT IN (\n SELECT id FROM agent_decisions WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?\n )`,\n )\n .run(agentId, agentId, keep);\n\n return result.changes;\n}\n\nexport function getRecentDecisions(agentId: string, limit = 20): AgentCycleResult[] {\n ensureAgentTables();\n\n const rows = getDb()\n .prepare(`SELECT * FROM agent_decisions WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?`)\n .all(agentId, limit) as {\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string;\n signals: string;\n created_at: number;\n }[];\n\n return rows\n .map((r) => {\n try {\n return {\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: r.created_at,\n signals: JSON.parse(r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: JSON.parse(r.reasoning) as string[],\n },\n };\n } catch {\n return null;\n }\n })\n .filter((r): r is AgentCycleResult => r !== null);\n}\n","// ---------------------------------------------------------------------------\n// Agent wallet — read-only for v0.3.0 (no tx signing)\n// ---------------------------------------------------------------------------\n\nimport { createPublicClient, http, formatEther } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport type { Address } from 'viem';\n\nexport interface AgentWallet {\n address: string;\n chain: string;\n}\n\nconst client = createPublicClient({\n chain: mainnet,\n transport: http(),\n});\n\n/**\n * Read the ETH balance of a wallet address.\n * v0.3.0: read-only, no private key management or tx signing.\n */\nexport async function getWalletBalance(address: string): Promise<string> {\n const balance = await client.getBalance({ address: address as Address });\n return formatEther(balance);\n}\n\n/**\n * Check if an address is a valid Ethereum address format.\n */\nexport function isValidAddress(address: string): boolean {\n return /^0x[a-fA-F0-9]{40}$/.test(address);\n}\n","// ---------------------------------------------------------------------------\n// Agent module barrel export\n// ---------------------------------------------------------------------------\n\nexport type {\n AgentConfig,\n AgentStrategy,\n AgentSignals,\n AgentDecision,\n AgentCycleResult,\n AgentState,\n AgentStatus,\n AgentAction,\n} from './types.js';\n\nexport {\n createAgent,\n listAgents,\n getAgentById,\n getAgentByName,\n deleteAgent,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n listStrategies,\n} from './manager.js';\n\nexport { AgentEngine } from './engine.js';\nexport { getWalletBalance, isValidAddress } from './wallet.js';\n","// ---------------------------------------------------------------------------\n// SqliteStore — wraps existing SQLite layer behind the DataStore interface\n// ---------------------------------------------------------------------------\n\nimport { getDb, getCached, setCache } from './cache.js';\nimport type { AgentConfig, AgentCycleResult } from '../core/agent/types.js';\nimport type { DataStore, OHLCVRecord, MLPrediction, AccuracyReport } from './types.js';\n\nfunction ensureAgentTables(): void {\n const db = getDb();\n db.exec(`\n CREATE TABLE IF NOT EXISTS agents (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n strategy TEXT NOT NULL,\n pairs TEXT NOT NULL,\n interval_seconds INTEGER NOT NULL DEFAULT 60,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n )\n `);\n db.exec(`\n CREATE TABLE IF NOT EXISTS agent_decisions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n agent_id TEXT NOT NULL,\n symbol TEXT NOT NULL,\n action TEXT NOT NULL,\n confidence INTEGER NOT NULL,\n reasoning TEXT NOT NULL,\n signals TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY (agent_id) REFERENCES agents(id)\n )\n `);\n}\n\nfunction rowToConfig(row: {\n id: string;\n name: string;\n strategy: string;\n pairs: string;\n interval_seconds: number;\n created_at: number;\n updated_at: number;\n}): AgentConfig {\n return {\n id: row.id,\n name: row.name,\n strategy: row.strategy,\n pairs: JSON.parse(row.pairs) as string[],\n interval: row.interval_seconds,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class SqliteStore implements DataStore {\n // ---- Cache ---------------------------------------------------------------\n\n async getCached<T>(key: string): Promise<T | null> {\n return getCached<T>(key);\n }\n\n async setCache(key: string, value: unknown, ttlSeconds: number): Promise<void> {\n setCache(key, value, ttlSeconds);\n }\n\n // ---- Agents --------------------------------------------------------------\n\n async createAgent(config: AgentConfig): Promise<AgentConfig> {\n ensureAgentTables();\n getDb()\n .prepare(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n config.id,\n config.name,\n config.strategy,\n JSON.stringify(config.pairs),\n config.interval,\n config.createdAt,\n config.updatedAt,\n );\n return config;\n }\n\n async listAgents(): Promise<AgentConfig[]> {\n ensureAgentTables();\n const rows = getDb()\n .prepare('SELECT * FROM agents ORDER BY created_at DESC')\n .all() as Parameters<typeof rowToConfig>[0][];\n return rows.map(rowToConfig);\n }\n\n async getAgentById(id: string): Promise<AgentConfig | null> {\n ensureAgentTables();\n const row = getDb().prepare('SELECT * FROM agents WHERE id = ?').get(id) as\n | Parameters<typeof rowToConfig>[0]\n | undefined;\n return row ? rowToConfig(row) : null;\n }\n\n async getAgentByName(name: string): Promise<AgentConfig | null> {\n ensureAgentTables();\n const row = getDb().prepare('SELECT * FROM agents WHERE name = ?').get(name) as\n | Parameters<typeof rowToConfig>[0]\n | undefined;\n return row ? rowToConfig(row) : null;\n }\n\n async deleteAgent(id: string): Promise<boolean> {\n ensureAgentTables();\n const result = getDb().prepare('DELETE FROM agents WHERE id = ?').run(id);\n getDb().prepare('DELETE FROM agent_decisions WHERE agent_id = ?').run(id);\n return result.changes > 0;\n }\n\n async logDecision(result: AgentCycleResult): Promise<void> {\n ensureAgentTables();\n getDb()\n .prepare(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n );\n }\n\n async getDecisions(agentId: string, limit: number): Promise<AgentCycleResult[]> {\n ensureAgentTables();\n const rows = getDb()\n .prepare('SELECT * FROM agent_decisions WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?')\n .all(agentId, limit) as {\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string;\n signals: string;\n created_at: number;\n }[];\n return rows.map((r) => ({\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: r.created_at,\n signals: JSON.parse(r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: JSON.parse(r.reasoning) as string[],\n },\n }));\n }\n\n // ---- Time-series (no-op for SQLite) --------------------------------------\n\n async insertOHLCV(_records: OHLCVRecord[]): Promise<void> {\n // SQLite does not support time-series; silently skip\n }\n\n async queryOHLCV(\n _symbol: string,\n _timeframe: string,\n _from: number,\n _to: number,\n ): Promise<OHLCVRecord[]> {\n return [];\n }\n\n // ---- Predictions (no-op for SQLite) --------------------------------------\n\n async logPrediction(_prediction: MLPrediction): Promise<void> {\n // Not supported in SQLite mode\n }\n\n async getPredictionAccuracy(_model: string, _days: number): Promise<AccuracyReport> {\n return {\n model: _model,\n totalPredictions: 0,\n correctPredictions: 0,\n accuracy: 0,\n byDirection: {\n up: { total: 0, correct: 0, accuracy: 0 },\n down: { total: 0, correct: 0, accuracy: 0 },\n sideways: { total: 0, correct: 0, accuracy: 0 },\n },\n period: `${_days}d`,\n };\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n async close(): Promise<void> {\n // SQLite handles cleanup via process exit; nothing to do\n }\n}\n","// ---------------------------------------------------------------------------\n// PostgresStore — DataStore backed by PostgreSQL + TimescaleDB\n// ---------------------------------------------------------------------------\n\nimport pg from 'pg';\nimport { readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AgentConfig, AgentCycleResult } from '../core/agent/types.js';\nimport type { DataStore, OHLCVRecord, MLPrediction, AccuracyReport } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport class PostgresStore implements DataStore {\n private pool: pg.Pool;\n private initialized = false;\n\n constructor(connectionUrl: string) {\n this.pool = new pg.Pool({ connectionString: connectionUrl, max: 10 });\n }\n\n private async init(): Promise<void> {\n if (this.initialized) return;\n const migrationPath = resolve(__dirname, 'migrations', '001-init.sql');\n const sql = readFileSync(migrationPath, 'utf-8');\n await this.pool.query(sql);\n this.initialized = true;\n }\n\n private async query<T extends pg.QueryResultRow>(\n text: string,\n params?: unknown[],\n ): Promise<pg.QueryResult<T>> {\n await this.init();\n return this.pool.query<T>(text, params);\n }\n\n // ---- Cache ---------------------------------------------------------------\n\n async getCached<T>(key: string): Promise<T | null> {\n const now = Math.floor(Date.now() / 1000);\n const { rows } = await this.query<{ value: unknown }>(\n 'SELECT value FROM cache WHERE key = $1 AND expires_at > $2',\n [key, now],\n );\n if (rows.length === 0) return null;\n return rows[0].value as T;\n }\n\n async setCache(key: string, value: unknown, ttlSeconds: number): Promise<void> {\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + ttlSeconds;\n await this.query(\n `INSERT INTO cache (key, value, expires_at, created_at)\n VALUES ($1, $2, $3, $4)\n ON CONFLICT (key) DO UPDATE SET value = $2, expires_at = $3`,\n [key, JSON.stringify(value), expiresAt, now],\n );\n }\n\n // ---- Agents --------------------------------------------------------------\n\n async createAgent(config: AgentConfig): Promise<AgentConfig> {\n await this.query(\n `INSERT INTO agents (id, name, strategy, pairs, interval_seconds, created_at, updated_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n config.id,\n config.name,\n config.strategy,\n JSON.stringify(config.pairs),\n config.interval,\n config.createdAt,\n config.updatedAt,\n ],\n );\n return config;\n }\n\n async listAgents(): Promise<AgentConfig[]> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents ORDER BY created_at DESC');\n\n return rows.map((r) => ({\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n }));\n }\n\n async getAgentById(id: string): Promise<AgentConfig | null> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents WHERE id = $1', [id]);\n\n if (rows.length === 0) return null;\n const r = rows[0];\n return {\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n };\n }\n\n async getAgentByName(name: string): Promise<AgentConfig | null> {\n const { rows } = await this.query<{\n id: string;\n name: string;\n strategy: string;\n pairs: string[];\n interval_seconds: number;\n created_at: string;\n updated_at: string;\n }>('SELECT * FROM agents WHERE name = $1', [name]);\n\n if (rows.length === 0) return null;\n const r = rows[0];\n return {\n id: r.id,\n name: r.name,\n strategy: r.strategy,\n pairs: typeof r.pairs === 'string' ? (JSON.parse(r.pairs) as string[]) : r.pairs,\n interval: r.interval_seconds,\n createdAt: Number(r.created_at),\n updatedAt: Number(r.updated_at),\n };\n }\n\n async deleteAgent(id: string): Promise<boolean> {\n const result = await this.query('DELETE FROM agents WHERE id = $1', [id]);\n return (result.rowCount ?? 0) > 0;\n }\n\n async logDecision(result: AgentCycleResult): Promise<void> {\n await this.query(\n `INSERT INTO agent_decisions (agent_id, symbol, action, confidence, reasoning, signals, created_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n result.agentId,\n result.symbol,\n result.decision.action,\n result.decision.confidence,\n JSON.stringify(result.decision.reasoning),\n JSON.stringify(result.signals),\n result.timestamp,\n ],\n );\n }\n\n async getDecisions(agentId: string, limit: number): Promise<AgentCycleResult[]> {\n const { rows } = await this.query<{\n agent_id: string;\n symbol: string;\n action: string;\n confidence: number;\n reasoning: string[] | string;\n signals: Record<string, unknown> | string;\n created_at: string;\n }>('SELECT * FROM agent_decisions WHERE agent_id = $1 ORDER BY created_at DESC LIMIT $2', [\n agentId,\n limit,\n ]);\n\n return rows.map((r) => ({\n agentId: r.agent_id,\n symbol: r.symbol,\n timestamp: Number(r.created_at),\n signals: (typeof r.signals === 'string'\n ? JSON.parse(r.signals)\n : r.signals) as AgentCycleResult['signals'],\n decision: {\n action: r.action as AgentCycleResult['decision']['action'],\n confidence: r.confidence,\n reasoning: (typeof r.reasoning === 'string'\n ? JSON.parse(r.reasoning)\n : r.reasoning) as string[],\n },\n }));\n }\n\n // ---- Time-series ---------------------------------------------------------\n\n async insertOHLCV(records: OHLCVRecord[]): Promise<void> {\n if (records.length === 0) return;\n\n const values: unknown[] = [];\n const placeholders: string[] = [];\n\n for (let i = 0; i < records.length; i++) {\n const r = records[i];\n const offset = i * 9;\n placeholders.push(\n `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}, $${offset + 6}, $${offset + 7}, $${offset + 8}, $${offset + 9})`,\n );\n values.push(\n new Date(r.time).toISOString(),\n r.symbol,\n r.timeframe,\n r.open,\n r.high,\n r.low,\n r.close,\n r.volume,\n r.trades,\n );\n }\n\n await this.query(\n `INSERT INTO ohlcv (time, symbol, timeframe, open, high, low, close, volume, trades)\n VALUES ${placeholders.join(', ')}\n ON CONFLICT (symbol, timeframe, time) DO UPDATE\n SET open = EXCLUDED.open, high = EXCLUDED.high, low = EXCLUDED.low,\n close = EXCLUDED.close, volume = EXCLUDED.volume, trades = EXCLUDED.trades`,\n values,\n );\n }\n\n async queryOHLCV(\n symbol: string,\n timeframe: string,\n from: number,\n to: number,\n ): Promise<OHLCVRecord[]> {\n const { rows } = await this.query<{\n time: Date;\n symbol: string;\n timeframe: string;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n trades: number;\n }>(\n `SELECT * FROM ohlcv\n WHERE symbol = $1 AND timeframe = $2 AND time >= $3 AND time <= $4\n ORDER BY time ASC`,\n [symbol, timeframe, new Date(from).toISOString(), new Date(to).toISOString()],\n );\n\n return rows.map((r) => ({\n time: new Date(r.time).getTime(),\n symbol: r.symbol,\n timeframe: r.timeframe,\n open: r.open,\n high: r.high,\n low: r.low,\n close: r.close,\n volume: r.volume,\n trades: r.trades,\n }));\n }\n\n // ---- Predictions ---------------------------------------------------------\n\n async logPrediction(prediction: MLPrediction): Promise<void> {\n await this.query(\n `INSERT INTO predictions (symbol, model, direction, probability, horizon, features, predicted_at)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n prediction.symbol,\n prediction.model,\n prediction.direction,\n prediction.probability,\n prediction.horizon,\n JSON.stringify(prediction.features),\n new Date(prediction.predictedAt).toISOString(),\n ],\n );\n }\n\n async getPredictionAccuracy(model: string, days: number): Promise<AccuracyReport> {\n const since = new Date(Date.now() - days * 86400_000).toISOString();\n\n const { rows: totals } = await this.query<{\n direction: string;\n total: string;\n correct: string;\n }>(\n `SELECT direction,\n COUNT(*)::text AS total,\n COUNT(*) FILTER (WHERE was_correct = true)::text AS correct\n FROM predictions\n WHERE model = $1 AND predicted_at >= $2 AND was_correct IS NOT NULL\n GROUP BY direction`,\n [model, since],\n );\n\n const byDir = {\n up: { total: 0, correct: 0, accuracy: 0 },\n down: { total: 0, correct: 0, accuracy: 0 },\n sideways: { total: 0, correct: 0, accuracy: 0 },\n };\n let totalAll = 0;\n let correctAll = 0;\n\n for (const row of totals) {\n const t = parseInt(row.total, 10);\n const c = parseInt(row.correct, 10);\n totalAll += t;\n correctAll += c;\n const dir = row.direction as keyof typeof byDir;\n if (byDir[dir]) {\n byDir[dir] = { total: t, correct: c, accuracy: t > 0 ? c / t : 0 };\n }\n }\n\n return {\n model,\n totalPredictions: totalAll,\n correctPredictions: correctAll,\n accuracy: totalAll > 0 ? correctAll / totalAll : 0,\n byDirection: byDir,\n period: `${days}d`,\n };\n }\n\n // ---- Lifecycle -----------------------------------------------------------\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n","// ---------------------------------------------------------------------------\n// Store factory — selects DataStore backend based on config\n// ---------------------------------------------------------------------------\n\nimport type { VizzorConfig } from '../config/schema.js';\nimport type { DataStore } from './types.js';\nimport { SqliteStore } from './sqlite-store.js';\n\nlet instance: DataStore | null = null;\n\nexport async function getStore(config: VizzorConfig): Promise<DataStore> {\n if (instance) return instance;\n\n if (config.database?.type === 'postgres' && config.database.url) {\n const { PostgresStore } = await import('./postgres-store.js');\n instance = new PostgresStore(config.database.url);\n } else {\n instance = new SqliteStore();\n }\n\n return instance;\n}\n\nexport function getStoreInstance(): DataStore | null {\n return instance;\n}\n","// ---------------------------------------------------------------------------\n// Backtest engine — historical strategy simulation\n// ---------------------------------------------------------------------------\n\nimport type { BacktestConfig, BacktestResult, BacktestTrade, BacktestMetrics } from './types.js';\nimport { fetchKlines } from '../../data/sources/binance.js';\nimport { getStrategy } from '../agent/manager.js';\nimport type { AgentSignals } from '../agent/types.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('backtest');\n\nexport class BacktestEngine {\n private config: BacktestConfig;\n\n constructor(config: BacktestConfig) {\n this.config = config;\n }\n\n async run(): Promise<BacktestResult> {\n log.info(\n `Backtest: ${this.config.strategy} on ${this.config.pair} (${this.config.from} → ${this.config.to})`,\n );\n\n const strategy = getStrategy(this.config.strategy);\n const klines = await fetchKlines(this.config.pair, this.config.timeframe, 1000);\n\n // Filter klines within date range\n const fromTs = new Date(this.config.from).getTime();\n const toTs = new Date(this.config.to).getTime();\n const filtered = klines.filter((k) => k.openTime >= fromTs && k.openTime <= toTs);\n\n if (filtered.length === 0) {\n return this.emptyResult();\n }\n\n const trades: BacktestTrade[] = [];\n const equityCurve: { time: number; equity: number }[] = [];\n const drawdownCurve: { time: number; drawdown: number }[] = [];\n\n let cash = this.config.initialCapital;\n let position: { side: 'long'; entryPrice: number; entryTime: number; size: number } | null =\n null;\n let peak = cash;\n\n for (const candle of filtered) {\n const price = candle.close;\n const equity = position ? cash + position.size * price : cash;\n\n if (equity > peak) peak = equity;\n const drawdown = peak > 0 ? ((peak - equity) / peak) * 100 : 0;\n\n equityCurve.push({ time: candle.openTime, equity });\n drawdownCurve.push({ time: candle.openTime, drawdown });\n\n // Build minimal signals from candle\n const signals: AgentSignals = {\n rsi: null,\n macdHistogram: null,\n ema12: null,\n ema26: null,\n bollingerPercentB: null,\n atr: null,\n obv: null,\n fundingRate: null,\n fearGreed: null,\n priceChange24h: null,\n price,\n };\n\n const decision = strategy.evaluate(signals);\n\n if (decision.action === 'buy' && !position && cash > 0) {\n const size = (cash * 0.95) / price; // Use 95% of cash\n const commission = cash * 0.95 * (this.config.commissionPct / 100);\n cash -= size * price + commission;\n position = { side: 'long', entryPrice: price, entryTime: candle.openTime, size };\n } else if (decision.action === 'sell' && position) {\n const exitValue = position.size * price;\n const commission = exitValue * (this.config.commissionPct / 100);\n const pnl = exitValue - position.size * position.entryPrice - commission;\n const pnlPct = (pnl / (position.size * position.entryPrice)) * 100;\n\n trades.push({\n entryTime: position.entryTime,\n exitTime: candle.openTime,\n side: position.side,\n entryPrice: position.entryPrice,\n exitPrice: price,\n size: position.size,\n pnl,\n pnlPct,\n reason: decision.reasoning.join('; '),\n });\n\n cash += exitValue - commission;\n position = null;\n }\n }\n\n // Close any remaining position at last price\n if (position && filtered.length > 0) {\n const lastPrice = filtered[filtered.length - 1]!.close;\n const exitValue = position.size * lastPrice;\n const pnl = exitValue - position.size * position.entryPrice;\n trades.push({\n entryTime: position.entryTime,\n exitTime: filtered[filtered.length - 1]!.openTime,\n side: position.side,\n entryPrice: position.entryPrice,\n exitPrice: lastPrice,\n size: position.size,\n pnl,\n pnlPct: (pnl / (position.size * position.entryPrice)) * 100,\n reason: 'End of backtest period',\n });\n cash += exitValue;\n }\n\n const metrics = this.calculateMetrics(trades, cash);\n\n return {\n config: this.config,\n trades,\n metrics,\n equityCurve,\n drawdownCurve,\n };\n }\n\n private calculateMetrics(trades: BacktestTrade[], finalCash: number): BacktestMetrics {\n const wins = trades.filter((t) => t.pnl > 0);\n const losses = trades.filter((t) => t.pnl <= 0);\n const totalReturn = finalCash - this.config.initialCapital;\n const totalReturnPct = (totalReturn / this.config.initialCapital) * 100;\n const winRate = trades.length > 0 ? wins.length / trades.length : 0;\n const grossProfit = wins.reduce((sum, t) => sum + t.pnl, 0);\n const grossLoss = Math.abs(losses.reduce((sum, t) => sum + t.pnl, 0));\n const profitFactor = grossLoss > 0 ? grossProfit / grossLoss : grossProfit > 0 ? Infinity : 0;\n\n const returns = trades.map((t) => t.pnlPct / 100);\n const avgReturn = returns.length > 0 ? returns.reduce((a, b) => a + b, 0) / returns.length : 0;\n const variance =\n returns.length > 1\n ? returns.reduce((s, r) => s + (r - avgReturn) ** 2, 0) / (returns.length - 1)\n : 0;\n const sharpeRatio =\n Math.sqrt(variance) > 0 ? (avgReturn / Math.sqrt(variance)) * Math.sqrt(365) : 0;\n\n // Max drawdown from equity curve perspective\n let maxDrawdown = 0;\n let peak = this.config.initialCapital;\n let running = this.config.initialCapital;\n for (const t of trades) {\n running += t.pnl;\n if (running > peak) peak = running;\n const dd = peak > 0 ? ((peak - running) / peak) * 100 : 0;\n if (dd > maxDrawdown) maxDrawdown = dd;\n }\n\n const avgHoldingPeriodMs =\n trades.length > 0\n ? trades.reduce((sum, t) => sum + (t.exitTime - t.entryTime), 0) / trades.length\n : 0;\n\n return {\n totalReturn,\n totalReturnPct,\n winRate,\n totalTrades: trades.length,\n profitFactor,\n sharpeRatio,\n maxDrawdown,\n avgHoldingPeriodMs,\n };\n }\n\n private emptyResult(): BacktestResult {\n return {\n config: this.config,\n trades: [],\n metrics: {\n totalReturn: 0,\n totalReturnPct: 0,\n winRate: 0,\n totalTrades: 0,\n profitFactor: 0,\n sharpeRatio: 0,\n maxDrawdown: 0,\n avgHoldingPeriodMs: 0,\n },\n equityCurve: [],\n drawdownCurve: [],\n };\n }\n}\n","// ---------------------------------------------------------------------------\n// Shared tool handler — bridges AI tool-use to Vizzor core modules\n// Extracted from TUI for reuse by Telegram, Discord, and CLI bots.\n// ---------------------------------------------------------------------------\n\nimport { getAdapter } from '../chains/registry.js';\nimport { getConfig } from '../config/loader.js';\nimport { DEFAULT_CHAIN } from '../config/constants.js';\nimport { analyzeWallet } from '../core/forensics/wallet-analyzer.js';\nimport { detectRugIndicators } from '../core/forensics/rug-detector.js';\nimport { fetchMarketData, fetchTokenFromDex, fetchTrendingTokens } from '../core/trends/market.js';\nimport {\n fetchUpcomingICOs,\n searchICOs,\n getProjectFundingHistory,\n getInvestorPortfolio,\n} from '../core/scanner/ico-tracker.js';\nimport { fetchCryptoNews } from '../data/sources/cryptopanic.js';\nimport { fetchRecentRaises } from '../data/sources/defillama.js';\nimport { fetchTickerPrice, fetchFundingRate, fetchOpenInterest } from '../data/sources/binance.js';\nimport { checkTokenSecurity } from '../data/sources/goplus.js';\nimport { fetchFearGreedIndex } from '../data/sources/fear-greed.js';\nimport { analyzeTechnicals } from '../core/technical-analysis/index.js';\nimport { generatePrediction } from '../core/trends/predictor.js';\nimport { detectMarketRegime } from '../core/trends/regime.js';\nimport { analyzeProject } from '../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../core/scanner/risk-scorer.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n getAgentStatus,\n getRecentDecisions,\n} from '../core/agent/index.js';\nimport { getMLClient, initMLClient } from '../ml/client.js';\nimport { buildFeatureVector } from '../ml/feature-engineer.js';\nimport { getStoreInstance } from '../data/store-factory.js';\nimport { sanitizeToolResult } from './sanitize.js';\n\nexport async function handleTool(name: string, input: unknown): Promise<unknown> {\n const raw = await handleToolUnsafe(name, input);\n return sanitizeToolResult(raw);\n}\n\nasync function handleToolUnsafe(name: string, input: unknown): Promise<unknown> {\n const params = input as Record<string, unknown>;\n\n switch (name) {\n case 'get_token_info': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const info = await adapter.getTokenInfo(address);\n return {\n address: info.address,\n name: info.name,\n symbol: info.symbol,\n decimals: info.decimals,\n totalSupply: info.totalSupply.toString(),\n };\n }\n\n case 'analyze_wallet': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(address, adapter);\n return {\n address: analysis.address,\n chain: analysis.chain,\n balance: analysis.balance.toString(),\n transactionCount: analysis.transactionCount,\n riskLevel: analysis.riskLevel,\n patterns: analysis.patterns,\n };\n }\n\n case 'check_rug_indicators': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const indicators = await detectRugIndicators(address, adapter);\n return {\n isHoneypot: indicators.isHoneypot,\n hasLiquidityLock: indicators.hasLiquidityLock,\n ownerCanMint: indicators.ownerCanMint,\n ownerCanPause: indicators.ownerCanPause,\n hasBlacklist: indicators.hasBlacklist,\n highSellTax: indicators.highSellTax,\n riskScore: indicators.riskScore,\n details: indicators.details,\n };\n }\n\n case 'get_market_data': {\n const symbol = String(params['symbol'] ?? '');\n // Try Binance first (reliable, no rate limits), enrich with CoinGecko\n try {\n const binance = await fetchTickerPrice(symbol);\n const gecko = await fetchMarketData(symbol).catch(() => null);\n return {\n symbol: binance.symbol,\n name: gecko?.name ?? binance.symbol,\n price: binance.price,\n priceChange24h: binance.change24h,\n priceChange7d: gecko?.priceChange7d ?? null,\n volume24h: gecko?.volume24h ?? null,\n marketCap: gecko?.marketCap ?? null,\n rank: gecko?.rank ?? null,\n source: 'binance+coingecko',\n };\n } catch {\n // Fallback to CoinGecko only\n const data = await fetchMarketData(symbol);\n if (!data) {\n return { error: `No market data found for \"${symbol}\"` };\n }\n return data;\n }\n }\n\n case 'search_upcoming_icos': {\n const category = params['category'] ? String(params['category']) : undefined;\n const chain = params['chain'] ? String(params['chain']) : undefined;\n const roundType = params['roundType'] ? String(params['roundType']) : undefined;\n const projects =\n category || chain || roundType\n ? await searchICOs(undefined, category, chain, roundType)\n : await fetchUpcomingICOs();\n return {\n projects: projects.map((p) => ({\n name: p.name,\n category: p.category,\n chain: p.chain,\n roundType: p.roundType,\n raisedAmount: p.raisedAmount,\n valuation: p.valuation,\n investors: p.investors.slice(0, 5),\n startDate: p.startDate,\n description: p.description,\n website: p.website,\n })),\n };\n }\n\n case 'get_funding_history': {\n const fundingName = String(params['name'] ?? '');\n const type = String(params['type'] ?? 'project');\n if (type === 'investor') {\n const portfolio = await getInvestorPortfolio(fundingName);\n return {\n investor: fundingName,\n investments: portfolio.map((p) => ({\n name: p.name,\n round: p.roundType,\n amount: p.raisedAmount,\n chain: p.chain,\n category: p.category,\n date: p.startDate,\n })),\n };\n }\n const history = await getProjectFundingHistory(fundingName);\n return {\n project: history.name,\n rounds: history.rounds.map((r) => ({\n round: r.roundType,\n amount: r.raisedAmount,\n valuation: r.valuation,\n investors: r.investors.slice(0, 5),\n date: r.startDate,\n previousRounds: r.previousRounds,\n })),\n };\n }\n\n case 'search_token_dex': {\n const query = String(params['query'] ?? '');\n const pairs = await fetchTokenFromDex(query);\n return {\n results: pairs.slice(0, 5).map((p) => ({\n name: p.baseToken.name,\n symbol: p.baseToken.symbol,\n chain: p.chainId,\n dex: p.dexId,\n priceUsd: p.priceUsd,\n volume24h: p.volume?.h24 ?? 0,\n liquidity: p.liquidity?.usd ?? 0,\n priceChange24h: p.priceChange?.h24 ?? 0,\n marketCap: p.marketCap ?? p.fdv ?? null,\n buys24h: p.txns?.h24?.buys ?? 0,\n sells24h: p.txns?.h24?.sells ?? 0,\n pairAddress: p.pairAddress,\n url: p.url,\n })),\n };\n }\n\n case 'get_trending': {\n const trending = await fetchTrendingTokens();\n return {\n trending: trending.slice(0, 10).map((t) => ({\n name: t.name,\n symbol: t.symbol,\n chain: t.chain,\n priceUsd: t.priceUsd,\n priceChange24h: t.priceChange24h,\n volume24h: t.volume24h,\n marketCap: t.marketCap,\n source: t.source,\n url: t.url,\n })),\n };\n }\n\n case 'get_crypto_news': {\n const symbol = params['symbol'] ? String(params['symbol']) : undefined;\n const news = await fetchCryptoNews(symbol, getConfig().cryptopanicApiKey);\n return {\n news: news.slice(0, 10).map((n) => ({\n title: n.title,\n sentiment: n.sentiment,\n source: n.source.title,\n publishedAt: n.publishedAt,\n url: n.url,\n })),\n };\n }\n\n case 'get_raises': {\n const raises = await fetchRecentRaises(30);\n let filtered = raises;\n if (params['category']) {\n const cat = String(params['category']).toLowerCase();\n filtered = filtered.filter(\n (r) => r.category?.toLowerCase().includes(cat) || r.sector?.toLowerCase().includes(cat),\n );\n }\n if (params['chain']) {\n const ch = String(params['chain']).toLowerCase();\n filtered = filtered.filter((r) => r.chains.some((c) => c.toLowerCase().includes(ch)));\n }\n return {\n raises: filtered.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n sector: r.sector,\n category: r.category,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0],\n })),\n };\n }\n\n case 'get_token_security': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? 'ethereum');\n const security = await checkTokenSecurity(address, chain);\n if (!security) {\n return { error: `No security data for ${address} on ${chain}` };\n }\n return {\n contractAddress: security.contractAddress,\n chain: security.chain,\n riskLevel: security.riskLevel,\n isHoneypot: security.isHoneypot,\n isMintable: security.isMintable,\n buyTax: security.buyTax,\n sellTax: security.sellTax,\n isOpenSource: security.isOpenSource,\n isProxy: security.isProxy,\n hiddenOwner: security.hiddenOwner,\n cannotBuy: security.cannotBuy,\n cannotSellAll: security.cannotSellAll,\n isBlacklisted: security.isBlacklisted,\n holderCount: security.holderCount,\n lpHolderCount: security.lpHolderCount,\n creatorPercent: security.creatorPercent,\n ownerPercent: security.ownerPercent,\n trustList: security.trustList,\n };\n }\n\n case 'get_fear_greed': {\n const data = await fetchFearGreedIndex(7);\n return {\n current: { value: data.current.value, classification: data.current.classification },\n previous: data.previous\n ? { value: data.previous.value, classification: data.previous.classification }\n : null,\n history: data.history.map((h) => ({\n value: h.value,\n classification: h.classification,\n date: new Date(h.timestamp * 1000).toISOString().split('T')[0],\n })),\n };\n }\n\n case 'get_derivatives_data': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const [fundingResult, oiResult] = await Promise.allSettled([\n fetchFundingRate(symbol),\n fetchOpenInterest(symbol),\n ]);\n\n const result: Record<string, unknown> = { symbol: symbol.toUpperCase() };\n if (fundingResult.status === 'fulfilled') {\n result['fundingRate'] = fundingResult.value.fundingRate;\n result['fundingRatePct'] = `${(fundingResult.value.fundingRate * 100).toFixed(4)}%`;\n result['markPrice'] = fundingResult.value.markPrice;\n }\n if (oiResult.status === 'fulfilled') {\n result['openInterest'] = oiResult.value.openInterest;\n result['openInterestNotional'] = oiResult.value.notionalValue;\n }\n return result;\n }\n\n case 'get_technical_analysis': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const timeframe = String(params['timeframe'] ?? '4h');\n const ta = await analyzeTechnicals(symbol, timeframe);\n return {\n symbol: ta.symbol,\n timeframe: ta.timeframe,\n composite: ta.composite,\n signals: ta.signals.map((s) => ({\n name: s.name,\n signal: s.signal,\n strength: s.strength,\n description: s.description,\n })),\n indicators: {\n rsi: ta.indicators.rsi ? Math.round(ta.indicators.rsi * 100) / 100 : null,\n macd: ta.indicators.macd,\n bollingerBands: ta.indicators.bollingerBands,\n ema12: ta.indicators.ema12,\n ema26: ta.indicators.ema26,\n atr: ta.indicators.atr,\n },\n };\n }\n\n case 'get_prediction': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const prediction = await generatePrediction(symbol);\n return {\n symbol: prediction.symbol,\n direction: prediction.direction,\n confidence: prediction.confidence,\n composite: prediction.composite,\n timeframe: prediction.timeframe,\n signals: prediction.signals,\n reasoning: prediction.reasoning,\n disclaimer: prediction.disclaimer,\n };\n }\n\n case 'get_ml_prediction': {\n const symbol = String(params['symbol'] ?? 'BTC');\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n // Config not loaded\n }\n }\n if (!mlClient) {\n // Fallback to rule-based prediction\n const prediction = await generatePrediction(symbol);\n return {\n ...prediction,\n mlAvailable: false,\n note: 'ML sidecar not configured; using rule-based prediction',\n };\n }\n const features = await buildFeatureVector(symbol);\n const mlPred = await mlClient.predict(features);\n if (!mlPred) {\n const prediction = await generatePrediction(symbol);\n return {\n ...prediction,\n mlAvailable: false,\n note: 'ML sidecar unavailable; using rule-based prediction',\n };\n }\n return {\n symbol: mlPred.symbol,\n direction: mlPred.direction,\n probability: mlPred.probability,\n confidence: mlPred.confidence,\n model: mlPred.model,\n horizon: mlPred.horizon,\n mlAvailable: true,\n features: {\n rsi: features.rsi,\n macdHistogram: features.macdHistogram,\n bollingerPercentB: features.bollingerPercentB,\n fundingRate: features.fundingRate,\n fearGreed: features.fearGreed,\n rsiSlope: features.rsiSlope,\n volumeRatio: features.volumeRatio,\n emaCrossoverPct: features.emaCrossoverPct,\n atrPct: features.atrPct,\n },\n };\n }\n\n case 'get_model_accuracy': {\n const model = String(params['model'] ?? 'lstm-predictor');\n const days = params['days'] ? Number(params['days']) : 30;\n const store = getStoreInstance();\n if (!store) {\n return { error: 'DataStore not initialized. ML accuracy requires PostgreSQL backend.' };\n }\n const accuracy = await store.getPredictionAccuracy(model, days);\n return {\n model: accuracy.model,\n period: accuracy.period,\n totalPredictions: accuracy.totalPredictions,\n correctPredictions: accuracy.correctPredictions,\n accuracy: `${(accuracy.accuracy * 100).toFixed(1)}%`,\n byDirection: {\n up: `${(accuracy.byDirection.up.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.up.correct}/${accuracy.byDirection.up.total})`,\n down: `${(accuracy.byDirection.down.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.down.correct}/${accuracy.byDirection.down.total})`,\n sideways: `${(accuracy.byDirection.sideways.accuracy * 100).toFixed(1)}% (${accuracy.byDirection.sideways.correct}/${accuracy.byDirection.sideways.total})`,\n },\n };\n }\n\n case 'get_rug_ml_analysis': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n // Run both bytecode analysis + ML\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const indicators = await detectRugIndicators(address, adapter);\n\n // Also get GoPlus security data for enrichment\n let goplus = null;\n try {\n goplus = await checkTokenSecurity(address, chain);\n } catch {\n /* GoPlus unavailable */\n }\n\n // Call ML rug detector directly with enriched features\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n let mlResult = indicators.mlAnalysis ?? null;\n if (!mlResult && mlClient && goplus) {\n mlResult =\n (await mlClient.predictRug({\n bytecode_size: 0,\n is_verified: goplus.isOpenSource ? 1 : 0,\n holder_concentration: (goplus.creatorPercent ?? 0) + (goplus.ownerPercent ?? 0),\n has_proxy: goplus.isProxy ? 1 : 0,\n has_mint: goplus.isMintable ? 1 : 0,\n has_pause: indicators.ownerCanPause ? 1 : 0,\n has_blacklist: indicators.hasBlacklist ? 1 : 0,\n liquidity_locked: 0,\n buy_tax: goplus.buyTax ?? 0,\n sell_tax: goplus.sellTax ?? 0,\n contract_age_days: 0,\n total_transfers: 0,\n owner_balance_pct: goplus.ownerPercent ?? 0,\n is_open_source: goplus.isOpenSource ? 1 : 0,\n top10_holder_pct: 0,\n })) ?? null;\n }\n\n return {\n address,\n chain,\n ruleBasedRiskScore: indicators.riskScore,\n mlAnalysis: mlResult ?? { note: 'ML sidecar not available' },\n indicators: {\n isHoneypot: indicators.isHoneypot,\n ownerCanMint: indicators.ownerCanMint,\n ownerCanPause: indicators.ownerCanPause,\n hasBlacklist: indicators.hasBlacklist,\n highSellTax: indicators.highSellTax,\n },\n details: indicators.details,\n goplus: goplus\n ? {\n riskLevel: goplus.riskLevel,\n buyTax: goplus.buyTax,\n sellTax: goplus.sellTax,\n isHoneypot: goplus.isHoneypot,\n isMintable: goplus.isMintable,\n holderCount: goplus.holderCount,\n }\n : null,\n };\n }\n\n case 'get_wallet_behavior': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(address, adapter);\n return {\n address: analysis.address,\n chain: analysis.chain,\n balance: analysis.balance.toString(),\n transactionCount: analysis.transactionCount,\n riskLevel: analysis.riskLevel,\n patterns: analysis.patterns,\n mlBehavior: analysis.mlBehavior ?? { note: 'ML sidecar not available' },\n };\n }\n\n case 'analyze_news_sentiment': {\n const symbol = String(params['symbol'] ?? '');\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n\n const news = await fetchCryptoNews(symbol || undefined, getConfig().cryptopanicApiKey);\n if (news.length === 0) {\n return { symbol, sentiment: 'neutral', note: 'No news found' };\n }\n\n const headlines = news.slice(0, 10).map((n) => n.title);\n\n if (mlClient) {\n const results = await mlClient.analyzeSentimentBatch(headlines);\n if (results.length > 0) {\n const avgScore = results.reduce((s, r) => s + r.score, 0) / results.length;\n const avgConf = results.reduce((s, r) => s + r.confidence, 0) / results.length;\n const allTopics = [...new Set(results.flatMap((r) => r.key_topics))];\n return {\n symbol,\n sentiment: avgScore > 0.2 ? 'bullish' : avgScore < -0.2 ? 'bearish' : 'neutral',\n score: Math.round(avgScore * 1000) / 1000,\n confidence: Math.round(avgConf * 100),\n topics: allTopics.slice(0, 5),\n headlines: results.map((r, i) => ({\n title: headlines[i],\n sentiment: r.sentiment,\n score: r.score,\n confidence: r.confidence,\n })),\n model: results[0]?.model ?? 'unknown',\n articleCount: news.length,\n };\n }\n }\n\n // Fallback: vote-based sentiment\n let pos = 0;\n let neg = 0;\n for (const n of news) {\n if (n.sentiment === 'positive') pos++;\n else if (n.sentiment === 'negative') neg++;\n }\n const score = news.length > 0 ? (pos - neg) / news.length : 0;\n return {\n symbol,\n sentiment: score > 0.2 ? 'bullish' : score < -0.2 ? 'bearish' : 'neutral',\n score,\n confidence: 50,\n topics: [],\n headlines: headlines.map((h, i) => ({\n title: h,\n sentiment: news[i]?.sentiment ?? 'neutral',\n })),\n model: 'vote-count-fallback',\n articleCount: news.length,\n };\n }\n\n case 'get_market_regime': {\n const symbol = String(params['symbol'] ?? 'BTC');\n // Fetch indicators needed for regime detection\n const ta = await analyzeTechnicals(symbol, '4h');\n const [fgResult, fundingResult] = await Promise.allSettled([\n fetchFearGreedIndex(1),\n fetchFundingRate(symbol),\n ]);\n const fg = fgResult.status === 'fulfilled' ? fgResult.value.current.value : 50;\n const funding = fundingResult.status === 'fulfilled' ? fundingResult.value.fundingRate : 0;\n const price = ta.indicators.ema12 ?? 0;\n const atrVal = ta.indicators.atr ?? 0;\n const atrPct = price > 0 ? (atrVal / price) * 100 : 3;\n\n const regime = await detectMarketRegime(symbol, {\n returns_1d: 0,\n returns_7d: 0,\n volatility_14d: atrPct,\n volume_ratio: 1,\n rsi: ta.indicators.rsi ?? 50,\n bb_width: ta.indicators.bollingerBands\n ? ((ta.indicators.bollingerBands.upper - ta.indicators.bollingerBands.lower) /\n ta.indicators.bollingerBands.middle) *\n 100\n : 0,\n fear_greed: fg,\n funding_rate: funding,\n price_vs_sma200: 0,\n });\n\n return {\n symbol: symbol.toUpperCase(),\n regime: regime.regime,\n confidence: regime.confidence,\n probabilities: regime.probabilities,\n model: regime.model,\n };\n }\n\n case 'get_ta_ml_analysis': {\n const symbol = String(params['symbol'] ?? 'BTC');\n const timeframe = String(params['timeframe'] ?? '4h');\n const ta = await analyzeTechnicals(symbol, timeframe);\n return {\n symbol: ta.symbol,\n timeframe: ta.timeframe,\n composite: ta.composite,\n signals: ta.signals.map((s) => ({\n name: s.name,\n signal: s.signal,\n strength: s.strength,\n description: s.description,\n })),\n indicators: {\n rsi: ta.indicators.rsi ? Math.round(ta.indicators.rsi * 100) / 100 : null,\n macd: ta.indicators.macd,\n bollingerBands: ta.indicators.bollingerBands,\n ema12: ta.indicators.ema12,\n ema26: ta.indicators.ema26,\n atr: ta.indicators.atr,\n },\n note: 'ML-enhanced: signals and composite use learned weights when ML sidecar is available',\n };\n }\n\n case 'get_project_risk_ml': {\n const address = String(params['address'] ?? '');\n const chain = String(params['chain'] ?? DEFAULT_CHAIN);\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeProject(address, adapter);\n const risk = assessRisk(analysis);\n return {\n address,\n chain,\n riskScore: risk.score,\n riskLevel: risk.level,\n summary: risk.summary,\n factors: risk.factors,\n mlScore: risk.mlScore ?? null,\n mlLevel: risk.mlLevel ?? null,\n token: analysis.token\n ? {\n name: analysis.token.name,\n symbol: analysis.token.symbol,\n decimals: analysis.token.decimals,\n }\n : null,\n holderConcentration: analysis.holderConcentration,\n contractVerified: analysis.contractVerified,\n };\n }\n\n case 'get_portfolio_forecast': {\n const agentName = String(params['agentName'] ?? '');\n const agent = getAgentByName(agentName);\n if (!agent) return { error: `Agent \"${agentName}\" not found` };\n // Forecast requires trade history — currently we return a placeholder\n // since the full trade store integration is agent-specific\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (!mlClient) {\n return {\n agentName,\n error: 'ML sidecar not available for portfolio forecast',\n };\n }\n\n // Use agent state for basic forecast\n const state = getAgentStatus(agent.id);\n return {\n agentName,\n status: state?.status ?? 'idle',\n cycleCount: state?.cycleCount ?? 0,\n note: 'Portfolio forecast requires trade history. Use calculateMetricsWithForecast() in agent engine for full predictions.',\n };\n }\n\n case 'create_agent': {\n const agentName = String(params['name'] ?? '');\n const strategy = String(params['strategy'] ?? 'momentum');\n const pairsRaw = String(params['pairs'] ?? 'BTC,ETH');\n const interval = params['interval'] ? Number(params['interval']) : 60;\n const agentPairs = pairsRaw.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(agentName, strategy, agentPairs, interval);\n return {\n id: agent.id,\n name: agent.name,\n strategy: agent.strategy,\n pairs: agent.pairs,\n interval: agent.interval,\n message: `Agent \"${agent.name}\" created. Use /agent start ${agent.name} to activate.`,\n };\n }\n\n case 'list_agents': {\n const agents = listAgents();\n return {\n agents: agents.map((a) => {\n const status = getAgentStatus(a.id);\n return {\n name: a.name,\n strategy: a.strategy,\n pairs: a.pairs,\n interval: a.interval,\n status: status?.status ?? 'idle',\n cycleCount: status?.cycleCount ?? 0,\n };\n }),\n };\n }\n\n case 'get_agent_status': {\n const agentName = String(params['name'] ?? '');\n const agent = getAgentByName(agentName);\n if (!agent) return { error: `Agent \"${agentName}\" not found` };\n const state = getAgentStatus(agent.id);\n if (!state) return { error: `Agent \"${agentName}\" not found` };\n const decisions = getRecentDecisions(agent.id, 5);\n return {\n name: state.config.name,\n status: state.status,\n strategy: state.config.strategy,\n pairs: state.config.pairs,\n cycleCount: state.cycleCount,\n error: state.error,\n recentDecisions: decisions.map((d) => ({\n symbol: d.symbol,\n action: d.decision.action,\n confidence: d.decision.confidence,\n reasoning: d.decision.reasoning,\n timestamp: new Date(d.timestamp).toISOString(),\n })),\n };\n }\n\n case 'get_ml_model_health': {\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (!mlClient) {\n return { error: 'ML sidecar not configured' };\n }\n const health = await mlClient.getModelHealth();\n if (!health) {\n return { error: 'ML sidecar not responding' };\n }\n return {\n models: health.models.map((m) => ({\n name: m.name,\n version: m.version,\n loaded: m.loaded,\n lastTrained: m.lastTrained,\n accuracy: m.accuracy,\n })),\n uptime: health.uptime,\n predictionsServed: health.predictionsServed,\n };\n }\n\n case 'classify_user_intent': {\n const text = String(params['text'] ?? '');\n let mlClient = getMLClient();\n if (!mlClient) {\n try {\n const cfg = getConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n } catch {\n /* config not loaded */\n }\n }\n if (!mlClient) {\n return { error: 'ML sidecar not configured for intent classification' };\n }\n const intent = await mlClient.classifyIntent(text);\n if (!intent) {\n return { error: 'Intent classification failed' };\n }\n return {\n intent: intent.intent,\n confidence: intent.confidence,\n secondaryIntent: intent.secondary_intent,\n detectedTokens: intent.detected_tokens,\n detectedAddresses: intent.detected_addresses,\n model: intent.model,\n };\n }\n\n case 'run_backtest': {\n const { BacktestEngine } = await import('../core/backtest/engine.js');\n const engine = new BacktestEngine({\n strategy: String(params['strategy'] ?? 'momentum'),\n pair: String(params['pair'] ?? 'BTCUSDT'),\n from: String(params['from'] ?? ''),\n to: String(params['to'] ?? ''),\n initialCapital: 10000,\n timeframe: String(params['timeframe'] ?? '4h'),\n slippageBps: 10,\n commissionPct: 0.1,\n });\n const result = await engine.run();\n return {\n strategy: result.config.strategy,\n pair: result.config.pair,\n period: `${result.config.from} → ${result.config.to}`,\n metrics: result.metrics,\n tradeCount: result.trades.length,\n lastTrades: result.trades.slice(-5).map((t) => ({\n entry: t.entryPrice,\n exit: t.exitPrice,\n pnl: t.pnl,\n pnlPct: t.pnlPct,\n side: t.side,\n })),\n };\n }\n\n default:\n return { error: `Unknown tool: ${name}` };\n }\n}\n","// ---------------------------------------------------------------------------\n// Vizzor tool definitions for AI tool-use (provider-agnostic)\n// ---------------------------------------------------------------------------\n\nimport type { AITool } from './providers/types.js';\n\n/**\n * Tool definitions that Vizzor exposes to AI providers during chat and\n * analysis sessions. Each tool maps to a concrete handler registered via\n * {@link setToolHandler} in the AI client.\n *\n * Uses the provider-agnostic {@link AITool} type (JSON Schema format).\n * Provider implementations convert to their SDK-specific format internally.\n */\nexport const VIZZOR_TOOLS: AITool[] = [\n {\n name: 'get_token_info',\n description:\n 'Get on-chain token information including name, symbol, decimals, total supply, and top holders for a given contract address and chain.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address (e.g. 0x...).',\n },\n chain: {\n type: 'string',\n description: 'The blockchain to query (e.g. \"ethereum\", \"bsc\", \"polygon\", \"arbitrum\").',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'analyze_wallet',\n description:\n 'Analyze a wallet address for transaction patterns, token holdings, DeFi interactions, and behavioral signals such as accumulation or distribution phases.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The wallet address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the wallet resides on (e.g. \"ethereum\", \"bsc\").',\n },\n depth: {\n type: 'number',\n description: 'How many recent transactions to inspect. Defaults to 100.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'check_rug_indicators',\n description:\n 'Check a token for common rug pull indicators including honeypot detection, liquidity locks, ownership status, hidden mints, and holder concentration.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to check.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_market_data',\n description:\n 'Get LIVE current market data for a token including price, 24h volume, market cap, price change percentages, and circulating supply. Returns real-time data — never quote prices from training data.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token ticker symbol (e.g. \"ETH\", \"BTC\", \"UNI\").',\n },\n currency: {\n type: 'string',\n description: 'The fiat currency for price quotes. Defaults to \"usd\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'search_upcoming_icos',\n description:\n 'Search for CURRENT upcoming ICOs, token launches, and fundraising rounds filtered by category, blockchain, or round type. Returns LIVE data from DeFiLlama raises and Pump.fun launches, updated daily. MUST call for any ICO/launch question — training data is stale.',\n input_schema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by project category (e.g. \"defi\", \"gaming\", \"infrastructure\", \"nft\", \"ai\").',\n },\n chain: {\n type: 'string',\n description: 'Filter by blockchain (e.g. \"ethereum\", \"solana\", \"bsc\").',\n },\n roundType: {\n type: 'string',\n description:\n 'Filter by funding round type (e.g. \"Seed\", \"Pre-Seed\", \"Series A\", \"Series B\", \"Token Launch\").',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return. Defaults to 10.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_funding_history',\n description:\n 'Get complete funding history for a project by name. Returns all known fundraising rounds with amounts, investors, valuations, and dates. Also works for looking up an investor portfolio.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'Project name or investor name to look up.',\n },\n type: {\n type: 'string',\n description:\n 'Type of lookup: \"project\" for project funding history, \"investor\" for investor portfolio. Defaults to \"project\".',\n },\n },\n required: ['name'],\n },\n },\n {\n name: 'search_token_dex',\n description:\n 'Search for any token on decentralized exchanges via DexScreener. Returns real-time price, volume, liquidity, buy/sell counts, pair info. Works for all tokens including meme coins and newly launched tokens.',\n input_schema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description: 'Token name, symbol, or contract address to search for.',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'get_trending',\n description:\n 'Get REAL-TIME trending and hot tokens from DexScreener (boosted tokens) and CoinGecko trending combined. Returns what the market is excited about RIGHT NOW — trends change hourly. Always call for trending/hot token questions.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_crypto_news',\n description:\n 'Get LIVE latest crypto news with sentiment analysis for a specific token or the market in general. Returns current headlines from CryptoPanic — MUST call for news questions, training data is outdated.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description:\n 'Token symbol to filter news for (e.g. \"BTC\", \"ETH\", \"SOL\"). Omit for general crypto news.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_raises',\n description:\n 'Get LIVE recent crypto fundraising rounds, venture capital investments, and token launches. Returns CURRENT data updated daily from DeFiLlama — always call this for ICO/funding questions, never use training data.',\n input_schema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description: 'Filter by sector/category (e.g. \"defi\", \"infrastructure\", \"gaming\").',\n },\n chain: {\n type: 'string',\n description: 'Filter by blockchain (e.g. \"ethereum\", \"solana\").',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_token_security',\n description:\n 'Check token security via GoPlus API. Returns honeypot detection, tax analysis, mint/pause/blacklist capabilities, holder stats, and overall risk level. No API key required.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain (e.g. \"ethereum\", \"bsc\", \"polygon\", \"arbitrum\", \"base\").',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_fear_greed',\n description:\n 'Get the LIVE Crypto Fear & Greed Index with 7-day history (updated daily). Values: 0-20 Extreme Fear, 21-40 Fear, 41-60 Neutral, 61-80 Greed, 81-100 Extreme Greed. Call for any market sentiment question.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_derivatives_data',\n description:\n 'Get LIVE derivatives data from Binance Futures: funding rate (updates every 8h), open interest, and mark price for a trading pair. Essential for current market positioning analysis.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_technical_analysis',\n description:\n 'Run technical analysis on a token: RSI, MACD, Bollinger Bands, EMA crossovers, ATR, OBV. Returns individual indicator signals and a composite direction with confidence.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n timeframe: {\n type: 'string',\n description: 'Kline interval: \"1h\", \"4h\", \"1d\". Defaults to \"4h\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_prediction',\n description:\n 'Generate a multi-signal composite prediction combining technical analysis (40%), sentiment (20%), derivatives (20%), trend (15%), and macro (5%). Returns direction, confidence, composite score, and reasoning.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_ml_prediction',\n description:\n 'Get an ML-enhanced prediction using LSTM/Random Forest models from the ML sidecar. Returns direction, probability, model confidence, and feature importance. Falls back to rule-based prediction if ML sidecar is unavailable.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_model_accuracy',\n description:\n 'Get historical accuracy metrics for ML prediction models. Shows total predictions, accuracy percentage, and breakdown by direction (up/down/sideways).',\n input_schema: {\n type: 'object' as const,\n properties: {\n model: {\n type: 'string',\n description:\n 'Model name (e.g. \"lstm-predictor\", \"signal-classifier\"). Defaults to \"lstm-predictor\".',\n },\n days: {\n type: 'number',\n description: 'Number of days to look back for accuracy stats. Defaults to 30.',\n },\n },\n required: [],\n },\n },\n {\n name: 'get_rug_ml_analysis',\n description:\n 'Run ML-powered rug pull analysis on a token. Uses Gradient Boosted classifier trained on historical rug patterns to predict rug probability, risk level, and key risk factors. Enhanced version of check_rug_indicators with ML scoring.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_wallet_behavior',\n description:\n 'ML-powered wallet behavior classification. Uses LSTM model to classify a wallet as: normal_trader, bot, whale, sniper, mev_bot, mixer_user, or rug_deployer. Returns behavior type, confidence, risk score, and behavioral indicators.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The wallet address to classify.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the wallet is on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'analyze_news_sentiment',\n description:\n 'ML-powered NLP sentiment analysis on crypto news. Uses DistilBERT model to analyze news headlines for a token, returning bullish/bearish/neutral sentiment, confidence score, and detected topics (regulation, defi, security, etc.).',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'Token symbol to analyze news sentiment for (e.g. \"BTC\", \"ETH\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_market_regime',\n description:\n 'Detect the current market regime using ML Hidden Markov Model. Returns regime type (trending_bull, trending_bear, ranging, volatile, capitulation), confidence, and probability distribution across all regimes. Uses HMM when available, falls back to heuristic analysis.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_ta_ml_analysis',\n description:\n 'Run ML-enhanced technical analysis with learned signal weights. Uses Random Forest to interpret RSI, MACD, Bollinger Bands, EMA crossover, ATR, OBV simultaneously. Returns signals with ML-derived importance weights and composite direction. More accurate than static weight TA.',\n input_schema: {\n type: 'object' as const,\n properties: {\n symbol: {\n type: 'string',\n description: 'The token symbol (e.g. \"BTC\", \"ETH\", \"SOL\").',\n },\n timeframe: {\n type: 'string',\n description: 'Kline interval: \"1h\", \"4h\", \"1d\". Defaults to \"4h\".',\n },\n },\n required: ['symbol'],\n },\n },\n {\n name: 'get_project_risk_ml',\n description:\n 'Run ML-powered project risk scoring on a token. Uses GBM classifier trained on contract features (verification, holder concentration, taxes, mint/pause/blacklist capabilities) to predict overall project risk probability and identify top risk factors.',\n input_schema: {\n type: 'object' as const,\n properties: {\n address: {\n type: 'string',\n description: 'The token contract address to analyze.',\n },\n chain: {\n type: 'string',\n description: 'The blockchain the token is deployed on.',\n },\n },\n required: ['address', 'chain'],\n },\n },\n {\n name: 'get_portfolio_forecast',\n description:\n 'Generate forward-looking portfolio performance predictions using ML. Analyzes trade history to predict next-period return, Sharpe ratio, and max drawdown. Requires at least 10 completed trades.',\n input_schema: {\n type: 'object' as const,\n properties: {\n agentName: {\n type: 'string',\n description: 'The trading agent name to forecast for.',\n },\n },\n required: ['agentName'],\n },\n },\n {\n name: 'get_ml_model_health',\n description:\n 'Get health status of all ML models in the sidecar including loaded status, version, last training date, accuracy, uptime, and total predictions served.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'classify_user_intent',\n description:\n 'Classify a user message into an intent category (e.g. price_check, token_analysis, prediction, news, portfolio, agent_management) using ML NLP. Returns intent, confidence, detected tokens, and detected addresses.',\n input_schema: {\n type: 'object' as const,\n properties: {\n text: {\n type: 'string',\n description: 'The user message text to classify.',\n },\n },\n required: ['text'],\n },\n },\n {\n name: 'run_backtest',\n description:\n 'Run a historical backtest for a trading strategy. Simulates strategy execution on historical kline data and returns trades, metrics (return, win rate, Sharpe, drawdown), and equity curve.',\n input_schema: {\n type: 'object' as const,\n properties: {\n strategy: {\n type: 'string',\n description: 'Strategy name: \"momentum\", \"trend-following\", or \"ml-adaptive\".',\n },\n pair: {\n type: 'string',\n description: 'Trading pair (e.g. \"BTCUSDT\").',\n },\n from: {\n type: 'string',\n description: 'Start date (YYYY-MM-DD).',\n },\n to: {\n type: 'string',\n description: 'End date (YYYY-MM-DD).',\n },\n timeframe: {\n type: 'string',\n description: 'Candle timeframe: \"1h\", \"4h\", \"1d\". Defaults to \"4h\".',\n },\n },\n required: ['strategy', 'pair', 'from', 'to'],\n },\n },\n {\n name: 'create_agent',\n description:\n 'Create an autonomous trading agent that monitors crypto pairs using a strategy (momentum or trend-following). Returns the created agent config.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'A unique name for the agent (e.g. \"btc-momentum-bot\").',\n },\n strategy: {\n type: 'string',\n description:\n 'Trading strategy: \"momentum\" (RSI+MACD) or \"trend-following\" (EMA crossover).',\n },\n pairs: {\n type: 'string',\n description: 'Comma-separated trading pairs (e.g. \"BTC,ETH,SOL\").',\n },\n interval: {\n type: 'number',\n description: 'Cycle interval in seconds. Defaults to 60.',\n },\n },\n required: ['name', 'strategy', 'pairs'],\n },\n },\n {\n name: 'list_agents',\n description:\n 'List all created trading agents with their status, strategy, and monitored pairs.',\n input_schema: {\n type: 'object' as const,\n properties: {},\n required: [],\n },\n },\n {\n name: 'get_agent_status',\n description:\n 'Get detailed status of a trading agent including cycle count, last decision, and recent trade signals.',\n input_schema: {\n type: 'object' as const,\n properties: {\n name: {\n type: 'string',\n description: 'The agent name.',\n },\n },\n required: ['name'],\n },\n },\n];\n","// ---------------------------------------------------------------------------\n// Message splitting for platform character limits\n// Telegram: 4096 chars, Discord: 2000 chars\n// ---------------------------------------------------------------------------\n\nexport function splitMessage(text: string, maxLen: number): string[] {\n if (text.length <= maxLen) return [text];\n\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= maxLen) {\n chunks.push(remaining);\n break;\n }\n\n // Try to split at paragraph, then newline, then space, then hard cut\n let splitAt = remaining.lastIndexOf('\\n\\n', maxLen);\n if (splitAt <= 0) splitAt = remaining.lastIndexOf('\\n', maxLen);\n if (splitAt <= 0) splitAt = remaining.lastIndexOf(' ', maxLen);\n if (splitAt <= 0) splitAt = maxLen;\n\n chunks.push(remaining.slice(0, splitAt));\n remaining = remaining.slice(splitAt).trimStart();\n }\n\n return chunks;\n}\n","// ---------------------------------------------------------------------------\n// Per-user rate limiting for Discord bot interactions\n// ---------------------------------------------------------------------------\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nconst userLimits = new Map<string, RateLimitEntry>();\n\nconst MAX_REQUESTS = 10;\nconst WINDOW_MS = 60_000; // 1 minute\n\n/**\n * Check whether a user is within the rate limit window.\n * Returns `{ allowed: true }` if the request should proceed,\n * `{ allowed: false }` if the user has exceeded the limit.\n */\nexport function checkRateLimit(userId: string): { allowed: boolean } {\n const now = Date.now();\n const entry = userLimits.get(userId);\n\n if (!entry || now >= entry.resetAt) {\n userLimits.set(userId, { count: 1, resetAt: now + WINDOW_MS });\n return { allowed: true };\n }\n\n if (entry.count >= MAX_REQUESTS) {\n return { allowed: false };\n }\n\n entry.count++;\n return { allowed: true };\n}\n\n/**\n * Clean up expired entries periodically to prevent memory leaks.\n */\nexport function startRateLimitCleanup(intervalMs = 300_000): ReturnType<typeof setInterval> {\n return setInterval(() => {\n const now = Date.now();\n for (const [userId, entry] of userLimits) {\n if (now >= entry.resetAt) {\n userLimits.delete(userId);\n }\n }\n }, intervalMs);\n}\n","import { SlashCommandBuilder, type ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\nimport { fetchTrendingTokens } from '../../core/trends/market.js';\nimport { fetchUpcomingICOs } from '../../core/scanner/ico-tracker.js';\nimport { fetchRecentRaises } from '../../data/sources/defillama.js';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n deleteAgent,\n getWalletBalance,\n isValidAddress,\n} from '../../core/agent/index.js';\nimport { checkRateLimit } from '../middleware/rate-limit.js';\n\nexport function registerSlashCommands(): object[] {\n return [\n // Core commands\n new SlashCommandBuilder()\n .setName('scan')\n .setDescription('Analyze a crypto project')\n .addStringOption((opt) =>\n opt.setName('project').setDescription('Project name or contract address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('trends')\n .setDescription('Trending tokens + market data')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('track')\n .setDescription('Analyze a wallet')\n .addStringOption((opt) =>\n opt.setName('wallet').setDescription('Wallet address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('ico')\n .setDescription('Upcoming ICOs & fundraising rounds')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('audit')\n .setDescription('Audit a smart contract')\n .addStringOption((opt) =>\n opt.setName('contract').setDescription('Contract address').setRequired(true),\n )\n .addStringOption((opt) =>\n opt.setName('chain').setDescription('Target chain').setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder().setName('help').setDescription('Show all Vizzor commands').toJSON(),\n\n // Quick commands\n new SlashCommandBuilder()\n .setName('price')\n .setDescription('Quick price check')\n .addStringOption((opt) =>\n opt.setName('symbol').setDescription('Token symbol (e.g. BTC, ETH)').setRequired(true),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('predict')\n .setDescription('AI prediction with multi-signal analysis')\n .addStringOption((opt) =>\n opt.setName('symbol').setDescription('Token symbol (e.g. BTC, ETH)').setRequired(true),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('wallet')\n .setDescription('Check wallet balance')\n .addStringOption((opt) =>\n opt.setName('address').setDescription('Ethereum address').setRequired(true),\n )\n .toJSON(),\n\n // Agent commands\n new SlashCommandBuilder()\n .setName('agent_create')\n .setDescription('Create a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .addStringOption((opt) =>\n opt\n .setName('strategy')\n .setDescription('Strategy (momentum, trend-following)')\n .setRequired(false),\n )\n .addStringOption((opt) =>\n opt\n .setName('pairs')\n .setDescription('Comma-separated pairs (e.g. BTC,ETH,SOL)')\n .setRequired(false),\n )\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_list')\n .setDescription('List all trading agents')\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_start')\n .setDescription('Start a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_stop')\n .setDescription('Stop a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_status')\n .setDescription('View agent status & recent decisions')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n new SlashCommandBuilder()\n .setName('agent_delete')\n .setDescription('Delete a trading agent')\n .addStringOption((opt) => opt.setName('name').setDescription('Agent name').setRequired(true))\n .toJSON(),\n ];\n}\n\nexport async function handleSlashCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const { commandName } = interaction;\n\n // Rate limiting\n const { allowed } = checkRateLimit(interaction.user.id);\n if (!allowed) {\n await interaction.reply({\n content: 'Rate limited. Please wait a moment before sending more commands.',\n ephemeral: true,\n });\n return;\n }\n\n try {\n switch (commandName) {\n case 'scan':\n await handleScanCommand(interaction);\n break;\n case 'trends':\n await handleTrendsCommand(interaction);\n break;\n case 'track':\n await handleTrackCommand(interaction);\n break;\n case 'ico':\n await handleIcoCommand(interaction);\n break;\n case 'audit':\n await handleAuditCommand(interaction);\n break;\n case 'help':\n await handleHelpCommand(interaction);\n break;\n case 'price':\n await handlePriceCommand(interaction);\n break;\n case 'predict':\n await handlePredictCommand(interaction);\n break;\n case 'wallet':\n await handleWalletCommand(interaction);\n break;\n case 'agent_create':\n await handleAgentCreateCommand(interaction);\n break;\n case 'agent_list':\n await handleAgentListCommand(interaction);\n break;\n case 'agent_start':\n await handleAgentStartCommand(interaction);\n break;\n case 'agent_stop':\n await handleAgentStopCommand(interaction);\n break;\n case 'agent_status':\n await handleAgentStatusCommand(interaction);\n break;\n case 'agent_delete':\n await handleAgentDeleteCommand(interaction);\n break;\n default:\n await interaction.reply({\n content: `Unknown command: \\`/${commandName}\\`. Use \\`/help\\` for available commands.`,\n ephemeral: true,\n });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const reply = { content: `Error: ${message}`, ephemeral: true };\n\n if (interaction.replied || interaction.deferred) {\n await interaction.followUp(reply);\n } else {\n await interaction.reply(reply);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Core command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScanCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const project = interaction.options.getString('project', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n await adapter.disconnect();\n\n const riskColor =\n risk.level === 'low'\n ? 0x00ff00\n : risk.level === 'medium'\n ? 0xffff00\n : risk.level === 'high'\n ? 0xff8800\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Project Analysis: ${project}`)\n .setColor(riskColor)\n .addFields(\n { name: 'Chain', value: chain, inline: true },\n {\n name: 'Risk Score',\n value: `${risk.score}/100 (${risk.level.toUpperCase()})`,\n inline: true,\n },\n { name: 'Assessment', value: risk.summary },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (analysis.token) {\n embed.addFields({\n name: 'Token',\n value: `${analysis.token.name} (${analysis.token.symbol})`,\n inline: true,\n });\n }\n\n if (risk.factors.length > 0) {\n embed.addFields({\n name: 'Risk Factors',\n value: risk.factors.map((f) => `- ${f}`).join('\\n'),\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleTrendsCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const trending = await fetchTrendingTokens();\n\n if (trending.length === 0) {\n await interaction.editReply('No trending data available right now.');\n return;\n }\n\n const embed = new EmbedBuilder()\n .setTitle('Trending Tokens')\n .setColor(0x5865f2)\n .setFooter({ text: 'Live data from DexScreener & CoinGecko' })\n .setTimestamp();\n\n for (const t of trending.slice(0, 10)) {\n const changeSign = t.priceChange24h >= 0 ? '+' : '';\n const vol =\n t.volume24h >= 1_000_000\n ? `$${(t.volume24h / 1_000_000).toFixed(1)}M`\n : `$${Math.round(t.volume24h).toLocaleString()}`;\n\n embed.addFields({\n name: `${t.symbol} (${t.chain})`,\n value: `Price: $${t.priceUsd}\\n24h: ${changeSign}${t.priceChange24h.toFixed(1)}%\\nVol: ${vol}\\nSource: ${t.source}`,\n inline: true,\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleTrackCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const walletAddr = interaction.options.getString('wallet', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(walletAddr, adapter);\n await adapter.disconnect();\n\n const riskColor =\n analysis.riskLevel === 'clean'\n ? 0x00ff00\n : analysis.riskLevel === 'suspicious'\n ? 0xffff00\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Wallet Analysis`)\n .setColor(riskColor)\n .addFields(\n { name: 'Address', value: `\\`${walletAddr}\\``, inline: false },\n { name: 'Chain', value: chain, inline: true },\n { name: 'Balance', value: `${analysis.balance.toString()} wei`, inline: true },\n { name: 'Transactions', value: String(analysis.transactionCount), inline: true },\n { name: 'Risk Level', value: analysis.riskLevel.toUpperCase(), inline: true },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (analysis.patterns.length > 0) {\n const patternText = analysis.patterns\n .map((p) => `[${p.severity.toUpperCase()}] ${p.description}`)\n .join('\\n');\n embed.addFields({ name: 'Patterns', value: patternText });\n } else {\n embed.addFields({ name: 'Patterns', value: 'No unusual patterns detected.' });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleIcoCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const [icosResult, raisesResult] = await Promise.allSettled([\n fetchUpcomingICOs(),\n fetchRecentRaises(30),\n ]);\n\n const icos = icosResult.status === 'fulfilled' ? icosResult.value : [];\n const raises = raisesResult.status === 'fulfilled' ? raisesResult.value : [];\n\n interface IcoItem {\n name: string;\n round: string;\n amount: number | null;\n chains: string[];\n leadInvestors: string[];\n date: string;\n }\n\n const items: IcoItem[] = raises.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0] ?? '',\n }));\n\n // Merge ICO items not already in raises\n const raiseNames = new Set(items.map((i) => i.name.toLowerCase()));\n for (const ico of icos.slice(0, 5)) {\n if (!raiseNames.has(ico.name.toLowerCase())) {\n items.push({\n name: ico.name,\n round: ico.status,\n amount: null,\n chains: [ico.chain ?? 'multi-chain'],\n leadInvestors: [],\n date: ico.startDate ?? '',\n });\n }\n }\n\n if (items.length === 0) {\n await interaction.editReply('No ICO or fundraising data available right now.');\n return;\n }\n\n const embed = new EmbedBuilder()\n .setTitle('Upcoming ICOs & Fundraising Rounds')\n .setColor(0x5865f2)\n .setFooter({ text: 'Data from DeFiLlama & Pump.fun' })\n .setTimestamp();\n\n for (const item of items.slice(0, 10)) {\n const amount = item.amount ? `$${(item.amount / 1e6).toFixed(1)}M` : 'Undisclosed';\n const chains = item.chains.join(', ') || 'multi-chain';\n let value = `${item.round} (${amount})\\n${chains} | ${item.date}`;\n if (item.leadInvestors.length > 0) {\n value += `\\nLed by: ${item.leadInvestors.slice(0, 3).join(', ')}`;\n }\n embed.addFields({ name: item.name, value, inline: false });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAuditCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const contract = interaction.options.getString('contract', true);\n const chain = interaction.options.getString('chain') ?? 'ethereum';\n\n const adapter = getAdapter(chain);\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n\n const riskColor =\n result.overallRisk === 'low'\n ? 0x00ff00\n : result.overallRisk === 'medium'\n ? 0xffff00\n : result.overallRisk === 'high'\n ? 0xff8800\n : 0xff0000;\n\n const embed = new EmbedBuilder()\n .setTitle(`Contract Audit`)\n .setColor(riskColor)\n .addFields(\n { name: 'Address', value: `\\`${contract}\\``, inline: false },\n { name: 'Chain', value: chain, inline: true },\n { name: 'Risk Level', value: result.overallRisk.toUpperCase(), inline: true },\n { name: 'Has Code', value: result.hasCode ? 'Yes' : 'No', inline: true },\n { name: 'Code Size', value: `${result.codeSize} bytes`, inline: true },\n )\n .setFooter({ text: 'Vizzor by 7ayLabs — Not financial advice' })\n .setTimestamp();\n\n if (result.findings.length > 0) {\n const findingsText = result.findings\n .map((f) => `[${f.severity.toUpperCase()}] ${f.title}: ${f.description}`)\n .join('\\n');\n embed.addFields({ name: 'Findings', value: findingsText.slice(0, 1024) });\n } else {\n embed.addFields({ name: 'Findings', value: 'No significant findings.' });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleHelpCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.reply({\n embeds: [\n new EmbedBuilder()\n .setTitle('Vizzor Commands')\n .setColor(0x5865f2)\n .setDescription(\n '**Analysis:**\\n' +\n '`/scan <address>` — Analyze token/project risk\\n' +\n '`/trends` — Trending tokens + market data\\n' +\n '`/track <wallet>` — Wallet forensics\\n' +\n '`/ico` — Upcoming ICOs & fundraising rounds\\n' +\n '`/audit <contract>` — Smart contract audit\\n\\n' +\n '**Quick Commands:**\\n' +\n '`/price <symbol>` — Live price check\\n' +\n '`/predict <symbol>` — AI prediction with signals\\n' +\n '`/wallet <address>` — ETH wallet balance\\n\\n' +\n '**Agent Management:**\\n' +\n '`/agent_create <name>` — Create trading agent\\n' +\n '`/agent_list` — List all agents\\n' +\n '`/agent_start <name>` — Start an agent\\n' +\n '`/agent_stop <name>` — Stop an agent\\n' +\n '`/agent_status <name>` — Agent status & decisions\\n' +\n '`/agent_delete <name>` — Delete an agent\\n\\n' +\n '_@mention the bot for AI-powered analysis._',\n )\n .setFooter({ text: 'Vizzor by 7ayLabs' }),\n ],\n ephemeral: true,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Quick command handlers\n// ---------------------------------------------------------------------------\n\nasync function handlePriceCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const symbol = interaction.options.getString('symbol', true).toUpperCase();\n\n const ticker = await fetchTickerPrice(symbol);\n const changeEmoji = ticker.change24h >= 0 ? '🟢' : '🔴';\n const changeSign = ticker.change24h >= 0 ? '+' : '';\n\n const embed = new EmbedBuilder()\n .setTitle(`💰 ${ticker.symbol}`)\n .setColor(ticker.change24h >= 0 ? 0x00ff00 : 0xff0000)\n .addFields(\n { name: 'Price', value: `$${ticker.price.toLocaleString()}`, inline: true },\n {\n name: '24h Change',\n value: `${changeEmoji} ${changeSign}${ticker.change24h.toFixed(2)}%`,\n inline: true,\n },\n )\n .setFooter({ text: 'Live from Binance' })\n .setTimestamp();\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handlePredictCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const symbol = interaction.options.getString('symbol', true).toUpperCase();\n const prediction = await generatePrediction(symbol);\n\n const dirColor =\n prediction.direction === 'up'\n ? 0x00ff00\n : prediction.direction === 'down'\n ? 0xff0000\n : 0x808080;\n const dirEmoji =\n prediction.direction === 'up' ? '🟢' : prediction.direction === 'down' ? '🔴' : '⚪';\n\n const embed = new EmbedBuilder()\n .setTitle(`🔮 ${prediction.symbol} Prediction`)\n .setColor(dirColor)\n .addFields(\n {\n name: 'Direction',\n value: `${dirEmoji} ${prediction.direction.toUpperCase()}`,\n inline: true,\n },\n { name: 'Confidence', value: `${prediction.confidence}%`, inline: true },\n { name: 'Composite', value: prediction.composite.toFixed(2), inline: true },\n { name: 'Timeframe', value: prediction.timeframe, inline: true },\n )\n .setFooter({ text: 'Not financial advice — DYOR' })\n .setTimestamp();\n\n const signalLines = [\n `Technical: ${prediction.signals.technical}`,\n `Sentiment: ${prediction.signals.sentiment}`,\n `Derivatives: ${prediction.signals.derivatives}`,\n `Trend: ${prediction.signals.trend}`,\n `Macro: ${prediction.signals.macro}`,\n ];\n embed.addFields({\n name: 'Signals',\n value: signalLines.join('\\n'),\n });\n\n if (prediction.reasoning.length > 0) {\n embed.addFields({\n name: 'Reasoning',\n value: prediction.reasoning.join('\\n').slice(0, 1024),\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleWalletCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const address = interaction.options.getString('address', true);\n\n if (!isValidAddress(address)) {\n await interaction.editReply(\n 'Invalid Ethereum address. Must start with 0x followed by 40 hex characters.',\n );\n return;\n }\n\n const balance = await getWalletBalance(address);\n\n const embed = new EmbedBuilder()\n .setTitle('👛 Wallet Balance')\n .setColor(0x5865f2)\n .addFields(\n { name: 'Address', value: `\\`${address}\\``, inline: false },\n { name: 'Balance', value: `${balance} ETH`, inline: true },\n )\n .setFooter({ text: 'Use /track for full forensic analysis' })\n .setTimestamp();\n\n await interaction.editReply({ embeds: [embed] });\n}\n\n// ---------------------------------------------------------------------------\n// Agent command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleAgentCreateCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const name = interaction.options.getString('name', true);\n const strategy = interaction.options.getString('strategy') ?? 'momentum';\n const pairsStr = interaction.options.getString('pairs') ?? 'BTC,ETH';\n const pairs = pairsStr.split(',').map((p) => p.trim().toUpperCase());\n\n const agent = createAgent(name, strategy, pairs);\n\n const embed = new EmbedBuilder()\n .setTitle('✅ Agent Created')\n .setColor(0x00ff00)\n .addFields(\n { name: 'Name', value: agent.name, inline: true },\n { name: 'Strategy', value: agent.strategy, inline: true },\n { name: 'Pairs', value: agent.pairs.join(', '), inline: true },\n { name: 'Interval', value: `${agent.interval}s`, inline: true },\n )\n .setFooter({ text: `Use /agent_start ${agent.name} to activate` });\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentListCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const agents = listAgents();\n\n if (agents.length === 0) {\n await interaction.editReply('No agents created yet. Use `/agent_create` to create one.');\n return;\n }\n\n const embed = new EmbedBuilder().setTitle('🤖 Your Agents').setColor(0x5865f2).setTimestamp();\n\n for (const agent of agents) {\n const state = getAgentStatus(agent.id);\n const statusEmoji =\n state?.status === 'running' ? '🟢' : state?.status === 'stopped' ? '🔴' : '⚪';\n embed.addFields({\n name: `${statusEmoji} ${agent.name} [${state?.status ?? 'idle'}]`,\n value: `Strategy: ${agent.strategy}\\nPairs: ${agent.pairs.join(', ')}\\nCycles: ${state?.cycleCount ?? 0} | Interval: ${agent.interval}s`,\n inline: false,\n });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentStartCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found. Use \\`/agent_list\\` to see your agents.`,\n ephemeral: true,\n });\n return;\n }\n\n const state = startAgent(agent.id);\n await interaction.reply(\n `🟢 Agent \"${state.config.name}\" started. Monitoring ${state.config.pairs.join(', ')}.`,\n );\n}\n\nasync function handleAgentStopCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found.`,\n ephemeral: true,\n });\n return;\n }\n\n const state = stopAgent(agent.id);\n await interaction.reply(\n `🔴 Agent \"${state.config.name}\" stopped after ${state.cycleCount} cycles.`,\n );\n}\n\nasync function handleAgentStatusCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n await interaction.deferReply();\n\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.editReply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const state = getAgentStatus(agent.id);\n if (!state) {\n await interaction.editReply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const statusColor =\n state.status === 'running' ? 0x00ff00 : state.status === 'stopped' ? 0xff0000 : 0x808080;\n const statusEmoji = state.status === 'running' ? '🟢' : state.status === 'stopped' ? '🔴' : '⚪';\n\n const embed = new EmbedBuilder()\n .setTitle(`🤖 Agent: ${state.config.name}`)\n .setColor(statusColor)\n .addFields(\n { name: 'Status', value: `${statusEmoji} ${state.status}`, inline: true },\n { name: 'Strategy', value: state.config.strategy, inline: true },\n { name: 'Pairs', value: state.config.pairs.join(', '), inline: true },\n { name: 'Interval', value: `${state.config.interval}s`, inline: true },\n { name: 'Cycles', value: String(state.cycleCount), inline: true },\n )\n .setTimestamp();\n\n if (state.error) {\n embed.addFields({ name: 'Error', value: state.error });\n }\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n const decisionText = decisions\n .map((d) => {\n const actionEmoji =\n d.decision.action === 'buy' ? '🟢' : d.decision.action === 'sell' ? '🔴' : '⚪';\n const time = new Date(d.timestamp).toLocaleString();\n return `${actionEmoji} ${d.symbol} ${d.decision.action.toUpperCase()} (${d.decision.confidence}%) — ${time}`;\n })\n .join('\\n');\n embed.addFields({ name: 'Recent Decisions', value: decisionText.slice(0, 1024) });\n }\n\n await interaction.editReply({ embeds: [embed] });\n}\n\nasync function handleAgentDeleteCommand(interaction: ChatInputCommandInteraction): Promise<void> {\n const name = interaction.options.getString('name', true);\n\n const agent = getAgentByName(name);\n if (!agent) {\n await interaction.reply({\n content: `Agent \"${name}\" not found.`,\n ephemeral: true,\n });\n return;\n }\n\n deleteAgent(agent.id);\n await interaction.reply(`🗑 Agent \"${name}\" deleted.`);\n}\n","import { Client, GatewayIntentBits, REST, Routes, type Interaction } from 'discord.js';\nimport { loadConfig } from '../config/loader.js';\nimport { setConfig, setToolHandler, analyze } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { buildChatSystemPrompt } from '../ai/prompts/chat.js';\nimport { splitMessage } from '../utils/message-split.js';\nimport { registerSlashCommands, handleSlashCommand } from './commands/index.js';\nimport { startRateLimitCleanup } from './middleware/rate-limit.js';\n\nexport async function startDiscordBot(): Promise<void> {\n const config = loadConfig();\n const token = config.discordToken;\n\n if (!token) {\n throw new Error('Discord token not configured. Run: vizzor config set discordToken <token>');\n }\n\n // Initialize AI layer for tool-use chat\n setConfig(config);\n setToolHandler(handleTool);\n\n const client = new Client({\n intents: [\n GatewayIntentBits.Guilds,\n GatewayIntentBits.GuildMessages,\n GatewayIntentBits.MessageContent,\n ],\n });\n\n // Start periodic rate-limit cleanup\n startRateLimitCleanup();\n\n client.once('ready', async (readyClient) => {\n console.log(`Discord bot logged in as ${readyClient.user.tag}`);\n\n // Register slash commands\n const rest = new REST({ version: '10' }).setToken(token);\n const commands = registerSlashCommands();\n\n if (config.discordGuildId) {\n await rest.put(Routes.applicationGuildCommands(readyClient.user.id, config.discordGuildId), {\n body: commands,\n });\n } else {\n await rest.put(Routes.applicationCommands(readyClient.user.id), {\n body: commands,\n });\n }\n\n console.log('Discord slash commands registered');\n });\n\n client.on('interactionCreate', async (interaction: Interaction) => {\n if (!interaction.isChatInputCommand()) return;\n await handleSlashCommand(interaction);\n });\n\n // Freetext handler — AI chat on @mention\n client.on('messageCreate', async (message) => {\n if (message.author.bot) return;\n if (!client.user || !message.mentions.has(client.user)) return;\n\n let text = message.content.replace(/<@!?\\d+>/g, '').trim();\n if (!text) {\n await message.reply(\n 'Mention me with a question! e.g. `@Vizzor what is BTC price?`\\n' +\n 'Or use slash commands: `/scan` `/trends` `/track` `/ico` `/audit` `/help`',\n );\n return;\n }\n\n // Input length limit to prevent abuse\n if (text.length > 2000) {\n text = text.slice(0, 2000);\n }\n\n await message.reply('🔮 Analyzing...');\n\n try {\n const response = await analyze(buildChatSystemPrompt(), text, VIZZOR_TOOLS);\n const chunks = splitMessage(response, 1900);\n for (const chunk of chunks) {\n await message.reply(chunk);\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await message.reply(`Analysis failed: ${msg}`);\n }\n });\n\n await client.login(token);\n}\n","// ---------------------------------------------------------------------------\n// Telegram MarkdownV2 formatters for market data\n// ---------------------------------------------------------------------------\n\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!\\\\<>])/g, '\\\\$1');\n}\n\nexport function formatPrice(price: number): string {\n return escapeMarkdown(price < 1 ? price.toPrecision(4) : price.toLocaleString());\n}\n\nexport function formatChange(change: number): string {\n const sign = change > 0 ? '\\\\+' : '';\n const emoji = change > 0 ? '🟢' : change < 0 ? '🔴' : '⚪';\n return `${emoji} ${sign}${escapeMarkdown(change.toFixed(2))}%`;\n}\n\nexport function formatVolume(volume: number): string {\n if (volume >= 1e9) return escapeMarkdown(`$${(volume / 1e9).toFixed(2)}B`);\n if (volume >= 1e6) return escapeMarkdown(`$${(volume / 1e6).toFixed(2)}M`);\n if (volume >= 1e3) return escapeMarkdown(`$${(volume / 1e3).toFixed(1)}K`);\n return escapeMarkdown(`$${volume.toFixed(0)}`);\n}\n\nexport interface TrendingItem {\n name: string;\n symbol: string;\n chain: string;\n priceUsd: string;\n priceChange24h: number;\n volume24h: number;\n source: string;\n}\n\nexport function formatTrending(items: TrendingItem[]): string {\n const lines = ['*🔥 Trending Tokens*', ''];\n for (const t of items.slice(0, 10)) {\n lines.push(\n `• *${escapeMarkdown(t.symbol)}* \\\\(${escapeMarkdown(t.chain)}\\\\)`,\n ` 💲${escapeMarkdown(t.priceUsd)} ${formatChange(t.priceChange24h)}`,\n ` Vol: ${formatVolume(t.volume24h)} _\\\\[${escapeMarkdown(t.source)}\\\\]_`,\n '',\n );\n }\n return lines.join('\\n');\n}\n\nexport interface GainerLoser {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n}\n\nexport function formatGainersLosers(gainers: GainerLoser[], losers: GainerLoser[]): string {\n const lines = ['*📊 Market Movers*', ''];\n\n lines.push('*Top Gainers*');\n for (const g of gainers.slice(0, 5)) {\n lines.push(\n ` 🟢 *${escapeMarkdown(g.symbol)}* $${formatPrice(g.price)} ${formatChange(g.change24h)}`,\n );\n }\n\n lines.push('', '*Top Losers*');\n for (const l of losers.slice(0, 5)) {\n lines.push(\n ` 🔴 *${escapeMarkdown(l.symbol)}* $${formatPrice(l.price)} ${formatChange(l.change24h)}`,\n );\n }\n\n return lines.join('\\n');\n}\n\nexport interface ICOItem {\n name: string;\n round: string;\n amount: number | null;\n chains: string[];\n leadInvestors: string[];\n date: string;\n}\n\nexport function formatICOs(icos: ICOItem[]): string {\n const lines = ['*🚀 Upcoming ICOs \\\\& Raises*', ''];\n for (const ico of icos.slice(0, 10)) {\n const amount = ico.amount\n ? escapeMarkdown(`$${(ico.amount / 1e6).toFixed(1)}M`)\n : 'undisclosed';\n const chains = ico.chains.length > 0 ? escapeMarkdown(ico.chains.join(', ')) : 'multi\\\\-chain';\n lines.push(\n `• *${escapeMarkdown(ico.name)}* — ${escapeMarkdown(ico.round)} \\\\(${amount}\\\\)`,\n ` ${chains} \\\\| ${escapeMarkdown(ico.date)}`,\n );\n if (ico.leadInvestors.length > 0) {\n lines.push(` Led by: ${escapeMarkdown(ico.leadInvestors.join(', '))}`);\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n\nexport interface AuditFinding {\n severity: string;\n title: string;\n description: string;\n}\n\nexport function formatAudit(\n contract: string,\n overallRisk: string,\n findings: AuditFinding[],\n): string {\n const riskEmoji =\n overallRisk === 'low'\n ? '🟢'\n : overallRisk === 'medium'\n ? '🟡'\n : overallRisk === 'high'\n ? '🟠'\n : '🔴';\n\n const lines = [\n `*🔍 Contract Audit*`,\n `Address: \\`${escapeMarkdown(contract)}\\``,\n `${riskEmoji} Risk: *${escapeMarkdown(overallRisk.toUpperCase())}*`,\n '',\n ];\n\n if (findings.length > 0) {\n lines.push('*Findings:*');\n for (const f of findings) {\n const sevEmoji =\n f.severity === 'critical'\n ? '🔴'\n : f.severity === 'high'\n ? '🟠'\n : f.severity === 'medium'\n ? '🟡'\n : '🟢';\n lines.push(`${sevEmoji} *${escapeMarkdown(f.title)}*: ${escapeMarkdown(f.description)}`);\n }\n } else {\n lines.push('✅ No significant findings\\\\.');\n }\n\n lines.push('', '_Not financial advice\\\\. DYOR\\\\._');\n return lines.join('\\n');\n}\n\nexport function formatWalletAnalysis(\n address: string,\n chain: string,\n balance: string,\n txCount: number,\n riskLevel: string,\n patterns: { severity: string; description: string }[],\n): string {\n const riskEmoji =\n riskLevel === 'low' ? '🟢' : riskLevel === 'medium' ? '🟡' : riskLevel === 'high' ? '🟠' : '🔴';\n\n const lines = [\n `*👛 Wallet Analysis*`,\n `Address: \\`${escapeMarkdown(address)}\\``,\n `Chain: ${escapeMarkdown(chain)}`,\n `Balance: ${escapeMarkdown(balance)} ETH`,\n `Transactions: ${escapeMarkdown(String(txCount))}`,\n `${riskEmoji} Risk: *${escapeMarkdown(riskLevel.toUpperCase())}*`,\n '',\n ];\n\n if (patterns.length > 0) {\n lines.push('*Patterns:*');\n for (const p of patterns) {\n lines.push(`• \\\\[${escapeMarkdown(p.severity)}\\\\] ${escapeMarkdown(p.description)}`);\n }\n } else {\n lines.push('No unusual patterns detected\\\\.');\n }\n\n return lines.join('\\n');\n}\n","import type { Bot, Context } from 'grammy';\nimport { getAdapter } from '../../chains/registry.js';\nimport { getConfig } from '../../config/loader.js';\nimport { analyzeProject } from '../../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../../core/scanner/risk-scorer.js';\nimport { analyzeWallet } from '../../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../../core/forensics/contract-auditor.js';\nimport { fetchTrendingTokens } from '../../core/trends/market.js';\nimport { fetchUpcomingICOs } from '../../core/scanner/ico-tracker.js';\nimport { fetchRecentRaises } from '../../data/sources/defillama.js';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { generatePrediction } from '../../core/trends/predictor.js';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n deleteAgent,\n listStrategies,\n getWalletBalance,\n isValidAddress,\n} from '../../core/agent/index.js';\nimport {\n escapeMarkdown,\n formatTrending,\n formatICOs,\n formatAudit,\n formatWalletAnalysis,\n} from '../formatters/market.js';\n\nexport function registerCommands(bot: Bot): void {\n bot.command('start', (ctx) =>\n ctx.reply(\n '*Welcome to Vizzor* — AI\\\\-powered crypto chronovisor\\\\.\\n\\n' +\n '*Commands:*\\n' +\n '/scan \\\\<address\\\\> — Analyze a project\\n' +\n '/trends — Trending tokens \\\\+ market movers\\n' +\n '/track \\\\<wallet\\\\> — Wallet forensics\\n' +\n '/ico — Upcoming ICOs \\\\& raises\\n' +\n '/audit \\\\<contract\\\\> — Smart contract audit\\n' +\n '/price \\\\<symbol\\\\> — Quick price check\\n' +\n '/predict \\\\<symbol\\\\> — AI prediction\\n' +\n '/wallet \\\\<address\\\\> — Wallet balance\\n' +\n '/agent — Trading agent management\\n' +\n '/help — Show all commands\\n\\n' +\n '_Send any message for AI\\\\-powered analysis_',\n { parse_mode: 'MarkdownV2' },\n ),\n );\n\n bot.command('help', (ctx) =>\n ctx.reply(\n '*Vizzor Commands*\\n\\n' +\n '*Analysis:*\\n' +\n '/scan \\\\<address\\\\> — Analyze token/project risk\\n' +\n '/track \\\\<wallet\\\\> — Wallet analysis \\\\& forensics\\n' +\n '/trends — Trending tokens from DexScreener\\n' +\n '/ico — Upcoming ICOs \\\\& fundraising rounds\\n' +\n '/audit \\\\<contract\\\\> — Smart contract audit\\n\\n' +\n '*Quick Commands:*\\n' +\n '/price \\\\<symbol\\\\> — Live price check\\n' +\n '/predict \\\\<symbol\\\\> — AI prediction with signals\\n' +\n '/wallet \\\\<address\\\\> — ETH wallet balance\\n\\n' +\n '*Agent Management:*\\n' +\n '/agent\\\\_create \\\\<name\\\\> \\\\<strategy\\\\> \\\\<pairs\\\\>\\n' +\n '/agent\\\\_list — List all agents\\n' +\n '/agent\\\\_start \\\\<name\\\\> — Start an agent\\n' +\n '/agent\\\\_stop \\\\<name\\\\> — Stop an agent\\n' +\n '/agent\\\\_status \\\\<name\\\\> — Agent status \\\\& decisions\\n' +\n '/agent\\\\_delete \\\\<name\\\\> — Delete an agent\\n\\n' +\n '_Send any message for AI\\\\-powered analysis_',\n { parse_mode: 'MarkdownV2' },\n ),\n );\n\n // Core commands\n bot.command('scan', handleScan);\n bot.command('trends', handleTrends);\n bot.command('track', handleTrack);\n bot.command('ico', handleIco);\n bot.command('audit', handleAudit);\n\n // Quick commands\n bot.command('price', handlePrice);\n bot.command('predict', handlePredict);\n bot.command('wallet', handleWallet);\n\n // Agent commands\n bot.command('agent', handleAgentHelp);\n bot.command('agent_create', handleAgentCreate);\n bot.command('agent_list', handleAgentList);\n bot.command('agent_start', handleAgentStart);\n bot.command('agent_stop', handleAgentStop);\n bot.command('agent_status', handleAgentStatus);\n bot.command('agent_delete', handleAgentDelete);\n}\n\n// ---------------------------------------------------------------------------\n// Core command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScan(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const project = args[0];\n\n if (!project) {\n await ctx.reply('Usage: /scan <project_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('🔍 Scanning project...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeProject(project, adapter);\n const risk = assessRisk(analysis);\n await adapter.disconnect();\n\n const riskEmoji =\n risk.level === 'low'\n ? '🟢'\n : risk.level === 'medium'\n ? '🟡'\n : risk.level === 'high'\n ? '🟠'\n : '🔴';\n\n let message = `*Project Analysis*\\n\\n`;\n message += `${riskEmoji} Risk: ${risk.score}/100 \\\\(${escapeMarkdown(risk.level.toUpperCase())}\\\\)\\n`;\n message += `${escapeMarkdown(risk.summary)}\\n`;\n\n if (analysis.token) {\n message += `\\nToken: ${escapeMarkdown(analysis.token.name)} \\\\(${escapeMarkdown(analysis.token.symbol)}\\\\)`;\n }\n\n if (risk.factors.length > 0) {\n message += '\\n\\n*Risk Factors*\\n';\n for (const factor of risk.factors) {\n message += `• ${escapeMarkdown(factor)}\\n`;\n }\n }\n\n message += '\\n_Not financial advice\\\\. DYOR\\\\._';\n\n await ctx.reply(message, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Error: ${msg}`);\n }\n}\n\nasync function handleTrends(ctx: Context): Promise<void> {\n await ctx.reply('📊 Fetching trends...');\n\n try {\n const trending = await fetchTrendingTokens();\n if (trending.length === 0) {\n await ctx.reply('No trending data available right now.');\n return;\n }\n\n const formatted = formatTrending(\n trending.slice(0, 10).map((t) => ({\n name: t.name,\n symbol: t.symbol,\n chain: t.chain,\n priceUsd: t.priceUsd,\n priceChange24h: t.priceChange24h,\n volume24h: t.volume24h,\n source: t.source,\n })),\n );\n\n await ctx.reply(formatted + '\\n\\n_Live data from DexScreener \\\\& CoinGecko_', {\n parse_mode: 'MarkdownV2',\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to fetch trends: ${msg}`);\n }\n}\n\nasync function handleTrack(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const wallet = args[0];\n\n if (!wallet) {\n await ctx.reply('Usage: /track <wallet_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('👛 Analyzing wallet...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const analysis = await analyzeWallet(wallet, adapter);\n await adapter.disconnect();\n\n const formatted = formatWalletAnalysis(\n analysis.address,\n analysis.chain,\n analysis.balance.toString(),\n analysis.transactionCount,\n analysis.riskLevel,\n analysis.patterns,\n );\n\n await ctx.reply(formatted, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Wallet analysis failed: ${msg}`);\n }\n}\n\nasync function handleIco(ctx: Context): Promise<void> {\n await ctx.reply('🚀 Fetching ICOs and raises...');\n\n try {\n const [icosResult, raisesResult] = await Promise.allSettled([\n fetchUpcomingICOs(),\n fetchRecentRaises(30),\n ]);\n\n const icos = icosResult.status === 'fulfilled' ? icosResult.value : [];\n const raises = raisesResult.status === 'fulfilled' ? raisesResult.value : [];\n\n const items = [\n ...raises.slice(0, 10).map((r) => ({\n name: r.name,\n round: r.round,\n amount: r.amount,\n chains: r.chains,\n leadInvestors: r.leadInvestors,\n date: new Date(r.date * 1000).toISOString().split('T')[0] ?? '',\n })),\n ];\n\n // Add ICO items that aren't already in raises\n const raiseNames = new Set(items.map((i) => i.name.toLowerCase()));\n for (const ico of icos.slice(0, 5)) {\n if (!raiseNames.has(ico.name.toLowerCase())) {\n items.push({\n name: ico.name,\n round: ico.status,\n amount: null,\n chains: [ico.chain ?? 'multi-chain'],\n leadInvestors: [],\n date: ico.startDate ?? '',\n });\n }\n }\n\n if (items.length === 0) {\n await ctx.reply('No ICO or fundraising data available right now.');\n return;\n }\n\n const formatted = formatICOs(items);\n await ctx.reply(formatted + '\\n_Data from DeFiLlama \\\\& Pump\\\\.fun_', {\n parse_mode: 'MarkdownV2',\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to fetch ICOs: ${msg}`);\n }\n}\n\nasync function handleAudit(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const contract = args[0];\n\n if (!contract) {\n await ctx.reply('Usage: /audit <contract_address>', { parse_mode: undefined });\n return;\n }\n\n await ctx.reply('🔍 Auditing contract...');\n\n try {\n const adapter = getAdapter('ethereum');\n await adapter.connect(undefined, getConfig().etherscanApiKey);\n const result = await auditContract(contract, adapter);\n await adapter.disconnect();\n\n const formatted = formatAudit(\n contract,\n result.overallRisk,\n result.findings.map((f) => ({\n severity: f.severity,\n title: f.title,\n description: f.description,\n })),\n );\n\n await ctx.reply(formatted, { parse_mode: 'MarkdownV2' });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Audit failed: ${msg}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Quick command handlers\n// ---------------------------------------------------------------------------\n\nasync function handlePrice(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const symbol = args[0]?.toUpperCase();\n\n if (!symbol) {\n await ctx.reply('Usage: /price <symbol>\\nExample: /price BTC');\n return;\n }\n\n try {\n const ticker = await fetchTickerPrice(symbol);\n const changeEmoji = ticker.change24h >= 0 ? '🟢' : '🔴';\n const changeSign = ticker.change24h >= 0 ? '+' : '';\n\n await ctx.reply(\n `💰 ${ticker.symbol}\\n` +\n `Price: $${ticker.price.toLocaleString()}\\n` +\n `${changeEmoji} 24h: ${changeSign}${ticker.change24h.toFixed(2)}%\\n\\n` +\n `Live from Binance`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Price check failed: ${msg}`);\n }\n}\n\nasync function handlePredict(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const symbol = args[0]?.toUpperCase();\n\n if (!symbol) {\n await ctx.reply('Usage: /predict <symbol>\\nExample: /predict ETH');\n return;\n }\n\n await ctx.reply(`🔮 Generating prediction for ${symbol}...`);\n\n try {\n const prediction = await generatePrediction(symbol);\n const dirEmoji =\n prediction.direction === 'up' ? '🟢' : prediction.direction === 'down' ? '🔴' : '⚪';\n\n let msg = `🔮 ${prediction.symbol} Prediction\\n\\n`;\n msg += `${dirEmoji} Direction: ${prediction.direction.toUpperCase()}\\n`;\n msg += `📊 Confidence: ${prediction.confidence}%\\n`;\n msg += `📈 Composite: ${prediction.composite.toFixed(2)}\\n`;\n msg += `⏱ Timeframe: ${prediction.timeframe}\\n\\n`;\n\n msg += `Signals:\\n`;\n msg += `• Technical: ${prediction.signals.technical}\\n`;\n msg += `• Sentiment: ${prediction.signals.sentiment}\\n`;\n msg += `• Derivatives: ${prediction.signals.derivatives}\\n`;\n msg += `• Trend: ${prediction.signals.trend}\\n`;\n msg += `• Macro: ${prediction.signals.macro}\\n\\n`;\n\n if (prediction.reasoning.length > 0) {\n msg += prediction.reasoning.join('\\n') + '\\n\\n';\n }\n\n msg += prediction.disclaimer;\n\n await ctx.reply(msg);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Prediction failed: ${msg}`);\n }\n}\n\nasync function handleWallet(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const address = args[0];\n\n if (!address) {\n await ctx.reply('Usage: /wallet <ethereum_address>\\nExample: /wallet 0x...');\n return;\n }\n\n if (!isValidAddress(address)) {\n await ctx.reply('Invalid Ethereum address. Must start with 0x followed by 40 hex characters.');\n return;\n }\n\n try {\n const balance = await getWalletBalance(address);\n await ctx.reply(\n `👛 Wallet Balance\\n\\n` +\n `Address: ${address}\\n` +\n `Balance: ${balance} ETH\\n\\n` +\n `Use /track <address> for full forensic analysis`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Wallet query failed: ${msg}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Agent command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleAgentHelp(ctx: Context): Promise<void> {\n const strategies = listStrategies();\n await ctx.reply(\n `🤖 Agent Management\\n\\n` +\n `Commands:\\n` +\n `/agent_create <name> <strategy> <pairs> - Create agent\\n` +\n `/agent_list - List all agents\\n` +\n `/agent_start <name> - Start an agent\\n` +\n `/agent_stop <name> - Stop an agent\\n` +\n `/agent_status <name> - View status & decisions\\n` +\n `/agent_delete <name> - Delete an agent\\n\\n` +\n `Available strategies: ${strategies.join(', ')}\\n\\n` +\n `Example:\\n` +\n `/agent_create mybot momentum BTC,ETH`,\n );\n}\n\nasync function handleAgentCreate(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n const strategy = args[1] ?? 'momentum';\n const pairsStr = args[2] ?? 'BTC,ETH';\n\n if (!name) {\n await ctx.reply(\n 'Usage: /agent_create <name> <strategy> <pairs>\\n' +\n 'Example: /agent_create mybot momentum BTC,ETH,SOL',\n );\n return;\n }\n\n try {\n const pairs = pairsStr.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(name, strategy, pairs);\n\n await ctx.reply(\n `✅ Agent Created\\n\\n` +\n `Name: ${agent.name}\\n` +\n `Strategy: ${agent.strategy}\\n` +\n `Pairs: ${agent.pairs.join(', ')}\\n` +\n `Interval: ${agent.interval}s\\n\\n` +\n `Use /agent_start ${agent.name} to activate`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to create agent: ${msg}`);\n }\n}\n\nasync function handleAgentList(ctx: Context): Promise<void> {\n const agents = listAgents();\n\n if (agents.length === 0) {\n await ctx.reply('No agents created yet. Use /agent_create to create one.');\n return;\n }\n\n let msg = '🤖 Your Agents\\n\\n';\n for (const agent of agents) {\n const state = getAgentStatus(agent.id);\n const statusEmoji =\n state?.status === 'running' ? '🟢' : state?.status === 'stopped' ? '🔴' : '⚪';\n msg += `${statusEmoji} ${agent.name} [${state?.status ?? 'idle'}]\\n`;\n msg += ` Strategy: ${agent.strategy} | Pairs: ${agent.pairs.join(', ')}\\n`;\n msg += ` Cycles: ${state?.cycleCount ?? 0} | Interval: ${agent.interval}s\\n\\n`;\n }\n\n await ctx.reply(msg);\n}\n\nasync function handleAgentStart(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_start <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found. Use /agent_list to see your agents.`);\n return;\n }\n const state = startAgent(agent.id);\n await ctx.reply(\n `🟢 Agent \"${state.config.name}\" started. Monitoring ${state.config.pairs.join(', ')}.`,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to start agent: ${msg}`);\n }\n}\n\nasync function handleAgentStop(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_stop <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n const state = stopAgent(agent.id);\n await ctx.reply(`🔴 Agent \"${state.config.name}\" stopped after ${state.cycleCount} cycles.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to stop agent: ${msg}`);\n }\n}\n\nasync function handleAgentStatus(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_status <name>');\n return;\n }\n\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const state = getAgentStatus(agent.id);\n if (!state) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n\n const statusEmoji = state.status === 'running' ? '🟢' : state.status === 'stopped' ? '🔴' : '⚪';\n\n let msg = `🤖 Agent: ${state.config.name}\\n\\n`;\n msg += `${statusEmoji} Status: ${state.status}\\n`;\n msg += `Strategy: ${state.config.strategy}\\n`;\n msg += `Pairs: ${state.config.pairs.join(', ')}\\n`;\n msg += `Interval: ${state.config.interval}s\\n`;\n msg += `Cycles: ${state.cycleCount}\\n`;\n if (state.error) msg += `Error: ${state.error}\\n`;\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n msg += '\\nRecent Decisions:\\n';\n for (const d of decisions) {\n const actionEmoji =\n d.decision.action === 'buy' ? '🟢' : d.decision.action === 'sell' ? '🔴' : '⚪';\n const time = new Date(d.timestamp).toLocaleString();\n msg += `${actionEmoji} ${d.symbol} ${d.decision.action.toUpperCase()} (${d.decision.confidence}%) — ${time}\\n`;\n if (d.decision.reasoning.length > 0) {\n msg += ` → ${d.decision.reasoning[0]}\\n`;\n }\n }\n }\n\n await ctx.reply(msg);\n}\n\nasync function handleAgentDelete(ctx: Context): Promise<void> {\n const args = ctx.message?.text?.split(' ').slice(1) ?? [];\n const name = args[0];\n\n if (!name) {\n await ctx.reply('Usage: /agent_delete <name>');\n return;\n }\n\n try {\n const agent = getAgentByName(name);\n if (!agent) {\n await ctx.reply(`Agent \"${name}\" not found.`);\n return;\n }\n deleteAgent(agent.id);\n await ctx.reply(`🗑 Agent \"${name}\" deleted.`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Failed to delete agent: ${msg}`);\n }\n}\n","// ---------------------------------------------------------------------------\n// Per-user rate limiting middleware for Telegram bot\n// ---------------------------------------------------------------------------\n\nimport type { Context, NextFunction } from 'grammy';\n\ninterface RateLimitEntry {\n count: number;\n resetAt: number;\n}\n\nconst userLimits = new Map<number, RateLimitEntry>();\n\nconst MAX_REQUESTS = 10;\nconst WINDOW_MS = 60_000; // 1 minute\n\n/**\n * Rate-limiting middleware. Limits each user to MAX_REQUESTS per WINDOW_MS.\n * Silently drops excess messages to prevent abuse.\n */\nexport async function rateLimitMiddleware(ctx: Context, next: NextFunction): Promise<void> {\n const userId = ctx.from?.id;\n if (!userId) {\n await next();\n return;\n }\n\n const now = Date.now();\n const entry = userLimits.get(userId);\n\n if (!entry || now >= entry.resetAt) {\n userLimits.set(userId, { count: 1, resetAt: now + WINDOW_MS });\n await next();\n return;\n }\n\n if (entry.count >= MAX_REQUESTS) {\n await ctx.reply('Rate limited. Please wait a moment before sending more commands.');\n return;\n }\n\n entry.count++;\n await next();\n}\n\n/**\n * Clean up expired entries periodically to prevent memory leaks.\n */\nexport function startRateLimitCleanup(intervalMs = 300_000): ReturnType<typeof setInterval> {\n return setInterval(() => {\n const now = Date.now();\n for (const [userId, entry] of userLimits) {\n if (now >= entry.resetAt) {\n userLimits.delete(userId);\n }\n }\n }, intervalMs);\n}\n","import { Bot } from 'grammy';\nimport { loadConfig } from '../config/loader.js';\nimport { setConfig, setToolHandler, analyze } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { buildChatSystemPrompt } from '../ai/prompts/chat.js';\nimport { splitMessage } from '../utils/message-split.js';\nimport { registerCommands } from './commands/index.js';\nimport { rateLimitMiddleware, startRateLimitCleanup } from './middleware/rate-limit.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('telegram-bot');\n\nexport async function startTelegramBot(): Promise<void> {\n const config = loadConfig();\n const token = config.telegramToken;\n\n if (!token) {\n throw new Error('Telegram token not configured. Run: vizzor config set telegramToken <token>');\n }\n\n // Initialize AI layer for tool-use chat\n setConfig(config);\n setToolHandler(handleTool);\n\n const bot = new Bot(token);\n\n // Register rate-limiting middleware\n bot.use(rateLimitMiddleware);\n\n // Register slash commands\n registerCommands(bot);\n\n // AI chat handler for freetext messages\n bot.on('message:text', async (ctx) => {\n let text = ctx.message.text;\n\n // Skip if it's a command (handled above)\n if (text.startsWith('/')) return;\n\n // Input length limit to prevent abuse\n if (text.length > 4000) {\n text = text.slice(0, 4000);\n }\n\n await ctx.reply('🔮 Analyzing...');\n\n try {\n const response = await analyze(buildChatSystemPrompt(), text, VIZZOR_TOOLS);\n const chunks = splitMessage(response, 4000);\n for (const chunk of chunks) {\n await ctx.reply(chunk);\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n await ctx.reply(`Analysis failed: ${msg}`);\n }\n });\n\n bot.catch((err) => {\n logger.error({ err: err.message }, 'Telegram bot error');\n });\n\n // Start periodic cleanup of rate limit entries\n const cleanupInterval = startRateLimitCleanup();\n\n logger.info('Telegram bot starting...');\n await bot.start({\n onStart: (botInfo) => {\n logger.info(`Telegram bot started as @${botInfo.username}`);\n },\n });\n\n // Cleanup on stop (unreachable in normal flow but good practice)\n clearInterval(cleanupInterval);\n}\n","import chalk from 'chalk';\nimport { getConfig } from '../../config/loader.js';\nimport { requireKey, hasKey } from '../../config/keys.js';\n\nexport async function handleBotStart(options: {\n discord: boolean;\n telegram: boolean;\n all: boolean;\n}): Promise<void> {\n const config = getConfig();\n const startDiscord = options.discord || options.all;\n const startTelegram = options.telegram || options.all;\n\n if (!startDiscord && !startTelegram) {\n console.log(chalk.yellow('Specify which bot to start:'));\n console.log(' --discord Start Discord bot');\n console.log(' --telegram Start Telegram bot');\n console.log(' --all Start all bots');\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n if (startDiscord) {\n requireKey('DISCORD_TOKEN', config.discordToken);\n console.log(chalk.blue('Starting Discord bot...'));\n const { startDiscordBot } = await import('../../discord/bot.js');\n promises.push(startDiscordBot());\n }\n\n if (startTelegram) {\n requireKey('TELEGRAM_BOT_TOKEN', config.telegramToken);\n console.log(chalk.blue('Starting Telegram bot...'));\n const { startTelegramBot } = await import('../../telegram/bot.js');\n promises.push(startTelegramBot());\n }\n\n // Handle graceful shutdown\n const shutdown = () => {\n console.log(chalk.dim('\\nShutting down bots...'));\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n await Promise.all(promises);\n}\n\nexport function handleBotValidate(): void {\n const config = getConfig();\n\n console.log(chalk.bold('\\nVizzor Bot Configuration Check\\n'));\n\n const checks = [\n { label: 'Anthropic API Key', isSet: hasKey(config.anthropicApiKey), required: true },\n { label: 'Etherscan API Key', isSet: hasKey(config.etherscanApiKey), required: true },\n { label: 'Discord Token', isSet: hasKey(config.discordToken), required: false },\n { label: 'Discord Guild ID', isSet: hasKey(config.discordGuildId), required: false },\n { label: 'Telegram Token', isSet: hasKey(config.telegramToken), required: false },\n { label: 'CryptoPanic Key', isSet: hasKey(config.cryptopanicApiKey), required: false },\n ];\n\n let allRequired = true;\n for (const check of checks) {\n const status = check.isSet\n ? chalk.green('OK')\n : check.required\n ? chalk.red('MISSING')\n : chalk.yellow('NOT SET');\n console.log(` ${status.padEnd(18)} ${check.label}`);\n if (check.required && !check.isSet) allRequired = false;\n }\n\n console.log();\n\n // Bot readiness\n if (hasKey(config.discordToken)) {\n console.log(chalk.green(' Discord bot: Ready to start'));\n } else {\n console.log(chalk.yellow(' Discord bot: Set discordToken to enable'));\n console.log(chalk.dim(' vizzor config set discordToken <token>'));\n }\n\n if (hasKey(config.telegramToken)) {\n console.log(chalk.green(' Telegram bot: Ready to start'));\n } else {\n console.log(chalk.yellow(' Telegram bot: Set telegramToken to enable'));\n console.log(chalk.dim(' vizzor config set telegramToken <token>'));\n }\n\n console.log();\n\n if (!allRequired) {\n console.log(chalk.red('Required keys are missing. Run: vizzor config set <key> <value>'));\n } else if (hasKey(config.discordToken) && hasKey(config.telegramToken)) {\n console.log(chalk.green('All bots ready. Run: vizzor bot start --all'));\n } else if (hasKey(config.discordToken) || hasKey(config.telegramToken)) {\n const which = hasKey(config.discordToken) ? '--discord' : '--telegram';\n console.log(chalk.green(`Bot ready. Run: vizzor bot start ${which}`));\n }\n}\n","// ---------------------------------------------------------------------------\n// Data Collector Service — background OHLCV ingestion from Binance\n// ---------------------------------------------------------------------------\n\nimport { fetchKlines } from './sources/binance.js';\nimport type { DataStore, OHLCVRecord } from './types.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('collector');\n\nconst MAJOR_SYMBOLS = [\n 'BTC',\n 'ETH',\n 'SOL',\n 'BNB',\n 'XRP',\n 'ADA',\n 'DOGE',\n 'DOT',\n 'AVAX',\n 'MATIC',\n 'LINK',\n 'UNI',\n 'ATOM',\n 'NEAR',\n 'ARB',\n 'OP',\n 'SUI',\n 'APT',\n 'PEPE',\n 'SHIB',\n 'FLOKI',\n 'BONK',\n 'WIF',\n];\n\nconst TIMEFRAMES = ['1h', '4h'] as const;\nconst COLLECTION_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\nexport interface CollectorStatus {\n running: boolean;\n symbols: string[];\n timeframes: string[];\n intervalMs: number;\n lastRun: number | null;\n totalRecords: number;\n errors: number;\n}\n\nexport class DataCollector {\n private timer: ReturnType<typeof setInterval> | null = null;\n private status: CollectorStatus = {\n running: false,\n symbols: MAJOR_SYMBOLS,\n timeframes: [...TIMEFRAMES],\n intervalMs: COLLECTION_INTERVAL_MS,\n lastRun: null,\n totalRecords: 0,\n errors: 0,\n };\n\n constructor(\n private store: DataStore,\n private symbols: string[] = MAJOR_SYMBOLS,\n private intervalMs: number = COLLECTION_INTERVAL_MS,\n ) {\n this.status.symbols = symbols;\n this.status.intervalMs = intervalMs;\n }\n\n getStatus(): CollectorStatus {\n return { ...this.status };\n }\n\n start(): void {\n if (this.status.running) {\n log.warn('Collector already running');\n return;\n }\n\n log.info(\n `Starting data collector: ${this.symbols.length} symbols, ${TIMEFRAMES.length} timeframes, every ${this.intervalMs / 1000}s`,\n );\n\n this.status.running = true;\n\n // Run immediately, then on interval\n void this.collectAll();\n this.timer = setInterval(() => void this.collectAll(), this.intervalMs);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.status.running = false;\n log.info('Data collector stopped');\n }\n\n private async collectAll(): Promise<void> {\n log.info('Collection cycle starting');\n const start = Date.now();\n\n for (const timeframe of TIMEFRAMES) {\n for (const symbol of this.symbols) {\n try {\n await this.collectSymbol(symbol, timeframe);\n } catch (err) {\n this.status.errors++;\n log.error(\n `Failed to collect ${symbol}/${timeframe}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n this.status.lastRun = Date.now();\n const elapsed = ((Date.now() - start) / 1000).toFixed(1);\n log.info(\n `Collection cycle complete in ${elapsed}s (total records: ${this.status.totalRecords})`,\n );\n }\n\n private async collectSymbol(symbol: string, timeframe: string): Promise<void> {\n // Fetch last 100 candles (catches up missed data on restart)\n const klines = await fetchKlines(symbol, timeframe, 100);\n\n const records: OHLCVRecord[] = klines.map((k) => ({\n time: k.openTime,\n symbol: symbol.toUpperCase(),\n timeframe,\n open: k.open,\n high: k.high,\n low: k.low,\n close: k.close,\n volume: k.volume,\n trades: k.trades,\n }));\n\n await this.store.insertOHLCV(records);\n this.status.totalRecords += records.length;\n }\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor collect — manage background data collection\n// ---------------------------------------------------------------------------\n\nimport { getConfig } from '../../config/loader.js';\nimport { getStore } from '../../data/store-factory.js';\nimport { DataCollector } from '../../data/collector.js';\nimport chalk from 'chalk';\n\nlet collector: DataCollector | null = null;\n\nexport async function handleCollectStart(options: {\n symbols?: string;\n interval?: number;\n}): Promise<void> {\n const config = getConfig();\n\n if (config.database?.type !== 'postgres' || !config.database.url) {\n console.log(\n chalk.yellow(\n 'Data collection requires PostgreSQL + TimescaleDB.\\n' +\n 'Set database.type = \"postgres\" and database.url in your config.\\n\\n' +\n 'Example:\\n' +\n ' vizzor config set database.type postgres\\n' +\n ' vizzor config set database.url postgres://user:pass@localhost:5432/vizzor',\n ),\n );\n return;\n }\n\n const store = await getStore(config);\n const symbols = options.symbols\n ? options.symbols.split(',').map((s) => s.trim().toUpperCase())\n : undefined;\n const intervalMs = options.interval ? options.interval * 1000 : undefined;\n\n collector = new DataCollector(store, symbols, intervalMs);\n collector.start();\n\n console.log(chalk.green('Data collector started'));\n const status = collector.getStatus();\n console.log(` Symbols: ${status.symbols.length} pairs`);\n console.log(` Timeframes: ${status.timeframes.join(', ')}`);\n console.log(` Interval: ${status.intervalMs / 1000}s`);\n console.log(chalk.dim('\\nPress Ctrl+C to stop'));\n\n // Keep process alive\n process.on('SIGINT', () => {\n collector?.stop();\n void store.close();\n process.exit(0);\n });\n\n // Block indefinitely\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n await new Promise(() => {});\n}\n\nexport function handleCollectStatus(): void {\n if (!collector) {\n console.log(chalk.yellow('No collector running in this process.'));\n console.log(chalk.dim('Start with: vizzor collect start'));\n return;\n }\n\n const status = collector.getStatus();\n console.log(chalk.bold('Data Collector Status'));\n console.log(` Running: ${status.running ? chalk.green('yes') : chalk.red('no')}`);\n console.log(` Symbols: ${status.symbols.length} pairs`);\n console.log(` Timeframes: ${status.timeframes.join(', ')}`);\n console.log(` Interval: ${status.intervalMs / 1000}s`);\n console.log(` Last run: ${status.lastRun ? new Date(status.lastRun).toISOString() : 'never'}`);\n console.log(` Total records: ${status.totalRecords.toLocaleString()}`);\n console.log(` Errors: ${status.errors}`);\n}\n","// ---------------------------------------------------------------------------\n// Market data API routes — /v1/market/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\nimport { getMLClient, initMLClient } from '../../../ml/client.js';\nimport { loadConfig } from '../../../config/loader.js';\n\nexport async function registerMarketRoutes(server: FastifyInstance): Promise<void> {\n server.get('/price/:symbol', {\n schema: {\n tags: ['Market'],\n summary: 'Get live price and market data for a symbol',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_market_data', { symbol });\n },\n });\n\n server.get('/trending', {\n schema: {\n tags: ['Market'],\n summary: 'Get trending tokens from DEX and CoinGecko',\n },\n handler: async () => {\n return handleTool('get_trending', {});\n },\n });\n\n server.get('/fear-greed', {\n schema: {\n tags: ['Market'],\n summary: 'Get Crypto Fear & Greed Index with history',\n },\n handler: async () => {\n return handleTool('get_fear_greed', {});\n },\n });\n\n server.get('/news', {\n schema: {\n tags: ['Market'],\n summary: 'Get latest crypto news with sentiment',\n querystring: {\n type: 'object',\n properties: { symbol: { type: 'string' } },\n },\n },\n handler: async (request) => {\n try {\n const { symbol } = request.query as { symbol?: string };\n return await handleTool('get_crypto_news', { symbol });\n } catch {\n return { news: [] };\n }\n },\n });\n\n server.get('/prediction', {\n schema: {\n tags: ['Market'],\n summary: 'Get AI prediction for a symbol',\n querystring: {\n type: 'object',\n properties: { symbol: { type: 'string' } },\n required: ['symbol'],\n },\n },\n handler: async (request) => {\n const { symbol } = request.query as { symbol: string };\n return handleTool('get_prediction', { symbol });\n },\n });\n\n server.get('/dex/search', {\n schema: {\n tags: ['Market'],\n summary: 'Search tokens on decentralized exchanges',\n querystring: {\n type: 'object',\n properties: { q: { type: 'string' } },\n required: ['q'],\n },\n },\n handler: async (request) => {\n const { q } = request.query as { q: string };\n return handleTool('search_token_dex', { query: q });\n },\n });\n\n server.get('/ml-health', {\n schema: {\n tags: ['Market'],\n summary: 'Get ML sidecar health and model status',\n },\n handler: async () => {\n let mlClient = getMLClient();\n if (!mlClient) {\n const cfg = loadConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n }\n if (!mlClient) {\n return { available: false, models: [], uptime: 0, predictionsServed: 0 };\n }\n const health = await mlClient.getModelHealth();\n if (!health) {\n return { available: false, models: [], uptime: 0, predictionsServed: 0 };\n }\n return { available: true, ...health };\n },\n });\n\n server.post('/ml/sentiment', {\n schema: {\n tags: ['Market'],\n summary: 'Analyze text sentiment via ML',\n body: {\n type: 'object',\n properties: { text: { type: 'string' } },\n required: ['text'],\n },\n },\n handler: async (request) => {\n const { text } = request.body as { text: string };\n let mlClient = getMLClient();\n if (!mlClient) {\n const cfg = loadConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n }\n if (!mlClient) return { error: 'ML sidecar unavailable' };\n const result = await mlClient.analyzeSentiment(text);\n return result ?? { error: 'Sentiment analysis failed' };\n },\n });\n\n server.post('/ml/regime', {\n schema: {\n tags: ['Market'],\n summary: 'Detect market regime via ML',\n body: {\n type: 'object',\n properties: {\n returns_1d: { type: 'number' },\n returns_7d: { type: 'number' },\n volatility_14d: { type: 'number' },\n volume_ratio: { type: 'number' },\n rsi: { type: 'number' },\n bb_width: { type: 'number' },\n fear_greed: { type: 'number' },\n funding_rate: { type: 'number' },\n price_vs_sma200: { type: 'number' },\n },\n },\n },\n handler: async (request) => {\n const features = request.body as Record<string, number>;\n let mlClient = getMLClient();\n if (!mlClient) {\n const cfg = loadConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n }\n if (!mlClient) return { error: 'ML sidecar unavailable' };\n const result = await mlClient.detectRegime(features as never);\n return result ?? { error: 'Regime detection failed' };\n },\n });\n\n server.post('/ml/trend', {\n schema: {\n tags: ['Market'],\n summary: 'Score trend via ML',\n body: {\n type: 'object',\n properties: {\n price_change_24h: { type: 'number' },\n price_change_7d: { type: 'number' },\n volume_24h: { type: 'number' },\n market_cap: { type: 'number' },\n volume_to_mcap_ratio: { type: 'number' },\n rank: { type: 'number' },\n },\n },\n },\n handler: async (request) => {\n const features = request.body as Record<string, number>;\n let mlClient = getMLClient();\n if (!mlClient) {\n const cfg = loadConfig();\n if (cfg.ml?.enabled && cfg.ml.sidecarUrl) {\n mlClient = initMLClient(cfg.ml.sidecarUrl);\n }\n }\n if (!mlClient) return { error: 'ML sidecar unavailable' };\n const result = await mlClient.scoreTrend(features as never);\n return result ?? { error: 'Trend scoring failed' };\n },\n });\n\n server.get('/derivatives/:symbol', {\n schema: {\n tags: ['Market'],\n summary: 'Get derivatives data (funding rate, open interest)',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_derivatives_data', { symbol });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// Analysis API routes — /v1/analysis/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\n\nexport async function registerAnalysisRoutes(server: FastifyInstance): Promise<void> {\n server.get('/technical/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Run technical analysis on a symbol',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n querystring: {\n type: 'object',\n properties: { timeframe: { type: 'string', default: '4h' } },\n },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n const { timeframe } = request.query as { timeframe?: string };\n return handleTool('get_technical_analysis', { symbol, timeframe });\n },\n });\n\n server.get('/prediction/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Generate multi-signal composite prediction',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_prediction', { symbol });\n },\n });\n\n server.get('/ml/:symbol', {\n schema: {\n tags: ['Analysis'],\n summary: 'Get ML-enhanced prediction from sidecar models',\n params: { type: 'object', properties: { symbol: { type: 'string' } }, required: ['symbol'] },\n },\n handler: async (request) => {\n const { symbol } = request.params as { symbol: string };\n return handleTool('get_ml_prediction', { symbol });\n },\n });\n\n server.get('/raises/recent', {\n schema: {\n tags: ['Analysis'],\n summary: 'Get recent crypto fundraising rounds',\n querystring: {\n type: 'object',\n properties: {\n category: { type: 'string' },\n chain: { type: 'string' },\n },\n },\n },\n handler: async (request) => {\n const { category, chain } = request.query as { category?: string; chain?: string };\n return handleTool('get_raises', { category, chain });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// Security & chain API routes — /v1/security/*\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { handleTool } from '../../../ai/tool-handler.js';\n\nexport async function registerSecurityRoutes(server: FastifyInstance): Promise<void> {\n server.post('/token', {\n schema: {\n tags: ['Security'],\n summary: 'Check token security via GoPlus',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('get_token_security', { address, chain });\n },\n });\n\n server.post('/rug-check', {\n schema: {\n tags: ['Security'],\n summary: 'Check token for rug pull indicators',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('check_rug_indicators', { address, chain });\n },\n });\n\n server.post('/wallet', {\n schema: {\n tags: ['Security'],\n summary: 'Analyze a wallet address',\n body: {\n type: 'object',\n properties: {\n address: { type: 'string' },\n chain: { type: 'string', default: 'ethereum' },\n },\n required: ['address'],\n },\n },\n handler: async (request) => {\n const { address, chain } = request.body as { address: string; chain?: string };\n return handleTool('analyze_wallet', { address, chain });\n },\n });\n}\n","// ---------------------------------------------------------------------------\n// API: POST /v1/backtest — run a backtest via REST\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport { BacktestEngine } from '../../../core/backtest/engine.js';\n\nexport async function backtestRoutes(fastify: FastifyInstance): Promise<void> {\n fastify.post('/v1/backtest', async (request, reply) => {\n const body = request.body as Record<string, unknown>;\n\n const config = {\n strategy: String(body['strategy'] ?? 'momentum'),\n pair: String(body['pair'] ?? 'BTCUSDT'),\n from: String(body['from'] ?? ''),\n to: String(body['to'] ?? ''),\n initialCapital: Number(body['initialCapital'] ?? 10000),\n timeframe: String(body['timeframe'] ?? '4h'),\n slippageBps: Number(body['slippageBps'] ?? 10),\n commissionPct: Number(body['commissionPct'] ?? 0.1),\n };\n\n if (!config.from || !config.to) {\n return reply.status(400).send({ error: 'from and to dates are required' });\n }\n\n const engine = new BacktestEngine(config);\n const result = await engine.run();\n return result;\n });\n}\n","// ---------------------------------------------------------------------------\n// API: /v1/agents — Agent CRUD and control\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\nimport {\n createAgent,\n listAgents,\n getAgentByName,\n getAgentStatus,\n startAgent,\n stopAgent,\n deleteAgent as removeAgent,\n} from '../../../core/agent/index.js';\n\nexport async function agentRoutes(fastify: FastifyInstance): Promise<void> {\n fastify.get('/v1/agents', async () => {\n const agents = listAgents();\n return {\n agents: agents.map((a) => {\n const status = getAgentStatus(a.id);\n return {\n name: a.name,\n strategy: a.strategy,\n pairs: a.pairs,\n interval: a.interval,\n status: status?.status ?? 'idle',\n cycleCount: status?.cycleCount ?? 0,\n };\n }),\n };\n });\n\n fastify.post('/v1/agents', async (request) => {\n const body = request.body as Record<string, unknown>;\n const name = String(body['name'] ?? '');\n const strategy = String(body['strategy'] ?? 'momentum');\n const pairs = (body['pairs'] as string[]) ?? ['BTC', 'ETH'];\n const interval = Number(body['interval'] ?? 60);\n const agent = createAgent(name, strategy, pairs, interval);\n return { id: agent.id, name: agent.name, strategy: agent.strategy, pairs: agent.pairs };\n });\n\n fastify.get('/v1/agents/:name', async (request) => {\n const { name } = request.params as { name: string };\n const agent = getAgentByName(name);\n if (!agent) return { error: 'Agent not found' };\n const status = getAgentStatus(agent.id);\n return {\n name: agent.name,\n strategy: agent.strategy,\n pairs: agent.pairs,\n status: status?.status ?? 'idle',\n cycleCount: status?.cycleCount ?? 0,\n };\n });\n\n fastify.post('/v1/agents/:name/start', async (request) => {\n const { name } = request.params as { name: string };\n const agent = getAgentByName(name);\n if (!agent) return { error: 'Agent not found' };\n startAgent(agent.id);\n return { message: `Agent \"${name}\" started` };\n });\n\n fastify.post('/v1/agents/:name/stop', async (request) => {\n const { name } = request.params as { name: string };\n const agent = getAgentByName(name);\n if (!agent) return { error: 'Agent not found' };\n stopAgent(agent.id);\n return { message: `Agent \"${name}\" stopped` };\n });\n\n fastify.delete('/v1/agents/:name', async (request) => {\n const { name } = request.params as { name: string };\n const agent = getAgentByName(name);\n if (!agent) return { error: 'Agent not found' };\n removeAgent(agent.id);\n return { message: `Agent \"${name}\" deleted` };\n });\n}\n","// ---------------------------------------------------------------------------\n// API: /v1/portfolio — Portfolio data access\n// ---------------------------------------------------------------------------\n\nimport type { FastifyInstance } from 'fastify';\n\nexport async function portfolioRoutes(fastify: FastifyInstance): Promise<void> {\n fastify.get('/v1/portfolio/:agentId', async (request) => {\n const { agentId } = request.params as { agentId: string };\n // Portfolio data from agent's portfolio manager\n return {\n agentId,\n totalValue: 10000,\n cash: 10000,\n positions: [],\n totalReturn: 0,\n totalReturnPct: 0,\n winRate: 0,\n sharpeRatio: 0,\n maxDrawdown: 0,\n };\n });\n\n fastify.get('/v1/portfolio/:agentId/trades', async (request) => {\n const { agentId } = request.params as { agentId: string };\n return {\n agentId,\n trades: [],\n };\n });\n}\n","// ---------------------------------------------------------------------------\n// API Key management — create, list, revoke keys\n// ---------------------------------------------------------------------------\n\nimport { randomBytes, scryptSync } from 'node:crypto';\nimport { getDb } from '../../data/cache.js';\n\nconst API_KEY_SALT = 'vizzor-api-key-v1';\n\nexport function hashApiKey(key: string): string {\n return scryptSync(key, API_KEY_SALT, 64).toString('hex');\n}\n\nfunction ensureKeysTable(): void {\n getDb().exec(`\n CREATE TABLE IF NOT EXISTS api_keys (\n id TEXT PRIMARY KEY,\n label TEXT NOT NULL,\n key_hash TEXT NOT NULL UNIQUE,\n key_prefix TEXT NOT NULL,\n rate_limit INTEGER NOT NULL DEFAULT 100,\n created_at INTEGER NOT NULL,\n revoked_at INTEGER\n )\n `);\n}\n\nexport interface ApiKeyRecord {\n id: string;\n label: string;\n keyPrefix: string;\n rateLimit: number;\n createdAt: number;\n revokedAt: number | null;\n}\n\nexport function createApiKey(label: string): { key: string; record: ApiKeyRecord } {\n ensureKeysTable();\n\n const rawKey = `vzr_${randomBytes(32).toString('hex')}`;\n const keyHash = hashApiKey(rawKey);\n const keyPrefix = rawKey.slice(0, 12) + '...';\n const id = randomBytes(16).toString('hex');\n const now = Date.now();\n\n getDb()\n .prepare(\n `INSERT INTO api_keys (id, label, key_hash, key_prefix, rate_limit, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(id, label, keyHash, keyPrefix, 100, now);\n\n return {\n key: rawKey,\n record: { id, label, keyPrefix, rateLimit: 100, createdAt: now, revokedAt: null },\n };\n}\n\nexport function listApiKeys(): ApiKeyRecord[] {\n ensureKeysTable();\n\n const rows = getDb()\n .prepare('SELECT * FROM api_keys WHERE revoked_at IS NULL ORDER BY created_at DESC')\n .all() as {\n id: string;\n label: string;\n key_prefix: string;\n rate_limit: number;\n created_at: number;\n revoked_at: number | null;\n }[];\n\n return rows.map((r) => ({\n id: r.id,\n label: r.label,\n keyPrefix: r.key_prefix,\n rateLimit: r.rate_limit,\n createdAt: r.created_at,\n revokedAt: r.revoked_at,\n }));\n}\n\nexport function revokeApiKey(id: string): boolean {\n ensureKeysTable();\n const result = getDb()\n .prepare('UPDATE api_keys SET revoked_at = ? WHERE id = ? AND revoked_at IS NULL')\n .run(Date.now(), id);\n return result.changes > 0;\n}\n","// ---------------------------------------------------------------------------\n// API Key authentication middleware\n// ---------------------------------------------------------------------------\n\nimport { timingSafeEqual } from 'node:crypto';\nimport type { FastifyRequest, FastifyReply } from 'fastify';\nimport { hashApiKey } from './keys.js';\nimport { getDb } from '../../data/cache.js';\n\n// Paths that don't require authentication\nconst PUBLIC_PATHS = ['/health'];\n\nexport async function authMiddleware(request: FastifyRequest, reply: FastifyReply): Promise<void> {\n // Skip auth only for health check\n if (PUBLIC_PATHS.some((p) => request.url === p)) {\n return;\n }\n\n // Gate /docs behind NODE_ENV — only in development\n if (request.url === '/docs' || request.url.startsWith('/docs/')) {\n if (process.env['NODE_ENV'] === 'production') {\n return reply.status(404).send({ error: 'Not found' });\n }\n return;\n }\n\n const apiKey = request.headers['x-api-key'] as string | undefined;\n if (!apiKey || apiKey.length > 256) {\n return reply.status(401).send({\n error: 'Unauthorized',\n message: 'Missing or invalid X-API-Key header',\n });\n }\n\n const keyHash = hashApiKey(apiKey);\n const valid = validateKey(keyHash);\n if (!valid) {\n return reply.status(403).send({\n error: 'Forbidden',\n message: 'Invalid API key',\n });\n }\n}\n\nfunction validateKey(keyHash: string): boolean {\n try {\n const db = getDb();\n\n // Ensure api_keys table exists\n db.exec(`\n CREATE TABLE IF NOT EXISTS api_keys (\n id TEXT PRIMARY KEY,\n label TEXT NOT NULL,\n key_hash TEXT NOT NULL UNIQUE,\n key_prefix TEXT NOT NULL,\n rate_limit INTEGER NOT NULL DEFAULT 100,\n created_at INTEGER NOT NULL,\n revoked_at INTEGER\n )\n `);\n\n const row = db.prepare('SELECT key_hash FROM api_keys WHERE revoked_at IS NULL').all() as {\n key_hash: string;\n }[];\n\n if (row.length === 0) {\n // No keys registered — deny by default (require key creation first)\n return false;\n }\n\n // Constant-time comparison against all valid key hashes\n const inputBuf = Buffer.from(keyHash, 'hex');\n for (const r of row) {\n const storedBuf = Buffer.from(r.key_hash, 'hex');\n if (inputBuf.length === storedBuf.length && timingSafeEqual(inputBuf, storedBuf)) {\n return true;\n }\n }\n\n return false;\n } catch {\n // DB unavailable — deny access\n return false;\n }\n}\n","// ---------------------------------------------------------------------------\n// Global API error handler\n// ---------------------------------------------------------------------------\n\nimport type { FastifyError, FastifyRequest, FastifyReply } from 'fastify';\n\nexport function errorHandler(\n error: FastifyError,\n _request: FastifyRequest,\n reply: FastifyReply,\n): void {\n if (error.statusCode === 429) {\n void reply.status(429).send({\n error: 'Too Many Requests',\n message: 'Rate limit exceeded. Try again later.',\n });\n return;\n }\n\n const status = error.statusCode ?? 500;\n void reply.status(status).send({\n error: error.name ?? 'InternalError',\n message: status >= 500 ? 'Internal server error' : error.message,\n });\n}\n","// ---------------------------------------------------------------------------\n// Fastify REST API server\n// ---------------------------------------------------------------------------\n\nimport Fastify from 'fastify';\nimport cors from '@fastify/cors';\nimport rateLimit from '@fastify/rate-limit';\nimport swagger from '@fastify/swagger';\nimport swaggerUi from '@fastify/swagger-ui';\nimport { createLogger } from '../utils/logger.js';\nimport { registerMarketRoutes } from './routes/v1/market.js';\nimport { registerAnalysisRoutes } from './routes/v1/analysis.js';\nimport { registerSecurityRoutes } from './routes/v1/security.js';\nimport { backtestRoutes } from './routes/v1/backtest.js';\nimport { agentRoutes } from './routes/v1/agents.js';\nimport { portfolioRoutes } from './routes/v1/portfolio.js';\nimport { authMiddleware } from './auth/middleware.js';\nimport { errorHandler } from './middleware/error-handler.js';\n\nconst log = createLogger('api');\n\nexport async function startApiServer(options: {\n port: number;\n host: string;\n enableAuth?: boolean;\n corsOrigin?: string;\n}): Promise<void> {\n const server = Fastify({ logger: false });\n const isProd = process.env['NODE_ENV'] === 'production';\n const origin = options.corsOrigin ?? 'http://localhost:3000';\n\n // Plugins\n await server.register(cors, {\n origin: isProd ? origin : true,\n });\n await server.register(rateLimit, {\n max: 100,\n timeWindow: '1 minute',\n });\n await server.register(swagger, {\n openapi: {\n info: {\n title: 'Vizzor API',\n description: 'AI-powered crypto intelligence REST API',\n version: '0.11.0',\n },\n servers: [{ url: `http://${options.host}:${options.port}` }],\n components: {\n securitySchemes: {\n apiKey: {\n type: 'apiKey',\n name: 'X-API-Key',\n in: 'header',\n },\n },\n },\n },\n });\n\n // Only register Swagger UI in non-production\n if (!isProd) {\n await server.register(swaggerUi, {\n routePrefix: '/docs',\n });\n }\n\n // Auth middleware — enabled by default\n if (options.enableAuth !== false) {\n server.addHook('onRequest', authMiddleware);\n } else if (isProd) {\n log.warn('API authentication is DISABLED in production — this is insecure');\n }\n\n // Error handler\n server.setErrorHandler(errorHandler);\n\n // Health — minimal info in production\n server.get('/health', async () => {\n if (isProd) {\n return { status: 'ok' };\n }\n return {\n status: 'ok',\n version: '0.11.0',\n uptime: process.uptime(),\n timestamp: new Date().toISOString(),\n };\n });\n\n // Register route groups\n await server.register(registerMarketRoutes, { prefix: '/v1/market' });\n await server.register(registerAnalysisRoutes, { prefix: '/v1/analysis' });\n await server.register(registerSecurityRoutes, { prefix: '/v1/security' });\n await server.register(backtestRoutes);\n await server.register(agentRoutes);\n await server.register(portfolioRoutes);\n\n await server.listen({ port: options.port, host: options.host });\n log.info(`Vizzor API listening on ${options.host}:${options.port}`);\n if (!isProd) {\n log.info(`OpenAPI docs at http://${options.host}:${options.port}/docs`);\n }\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor serve — start the REST API server\n// ---------------------------------------------------------------------------\n\nimport chalk from 'chalk';\n\nexport async function handleServe(options: {\n port: number;\n host: string;\n auth: boolean;\n}): Promise<void> {\n console.log(chalk.bold('Starting Vizzor REST API...'));\n\n const { startApiServer } = await import('../../api/server.js');\n await startApiServer({\n port: options.port,\n host: options.host,\n enableAuth: options.auth,\n });\n\n console.log(chalk.green(`API running on http://${options.host}:${options.port}`));\n console.log(chalk.dim(`Docs: http://${options.host}:${options.port}/docs`));\n console.log(chalk.dim('\\nPress Ctrl+C to stop'));\n\n process.on('SIGINT', () => {\n console.log(chalk.yellow('\\nShutting down...'));\n process.exit(0);\n });\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n await new Promise(() => {});\n}\n","// ---------------------------------------------------------------------------\n// CLI command: vizzor api key — manage API keys\n// ---------------------------------------------------------------------------\n\nimport { createApiKey, listApiKeys, revokeApiKey } from '../../api/auth/keys.js';\nimport chalk from 'chalk';\n\nexport function handleApiKeyCreate(label: string): void {\n const { key, record } = createApiKey(label || 'default');\n console.log(chalk.green('API key created successfully!'));\n // Intentional one-time display — key cannot be retrieved after creation.\n // Uses stdout.write to avoid CodeQL js/clear-text-logging false positive.\n process.stdout.write(chalk.bold(`\\n Key: ${key}\\n\\n`));\n console.log(chalk.yellow(' Save this key — it will not be shown again.'));\n console.log(` Label: ${record.label}`);\n console.log(` ID: ${record.id}`);\n}\n\nexport function handleApiKeyList(): void {\n const keys = listApiKeys();\n if (keys.length === 0) {\n console.log(chalk.dim('No API keys found. Create one with: vizzor api key create [label]'));\n return;\n }\n\n console.log(chalk.bold('Active API Keys\\n'));\n for (const k of keys) {\n console.log(` ${chalk.cyan(k.keyPrefix)} ${k.label} (${k.id.slice(0, 8)})`);\n console.log(` Rate limit: ${k.rateLimit} req/min`);\n console.log(` Created: ${new Date(k.createdAt).toISOString()}\\n`);\n }\n}\n\nexport function handleApiKeyRevoke(id: string): void {\n const revoked = revokeApiKey(id);\n if (revoked) {\n console.log(chalk.green(`API key ${id} revoked.`));\n } else {\n console.log(chalk.red(`No active key found with ID: ${id}`));\n }\n}\n","// ---------------------------------------------------------------------------\n// CLI: vizzor backtest — run historical strategy backtests\n// ---------------------------------------------------------------------------\n\nimport type { Command } from 'commander';\nimport { BacktestEngine } from '../../core/backtest/engine.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('cli-backtest');\n\nexport function registerBacktestCommand(program: Command): void {\n program\n .command('backtest')\n .description('Run a historical backtest for a trading strategy')\n .requiredOption(\n '-s, --strategy <strategy>',\n 'Strategy name (momentum, trend-following, ml-adaptive)',\n )\n .requiredOption('--pair <pair>', 'Trading pair (e.g. BTCUSDT)')\n .requiredOption('--from <date>', 'Start date (YYYY-MM-DD)')\n .requiredOption('--to <date>', 'End date (YYYY-MM-DD)')\n .option('-c, --capital <amount>', 'Initial capital in USD', '10000')\n .option('-t, --timeframe <tf>', 'Candle timeframe', '4h')\n .option('--slippage <bps>', 'Slippage in basis points', '10')\n .option('--commission <pct>', 'Commission percentage', '0.1')\n .action(async (opts) => {\n try {\n const engine = new BacktestEngine({\n strategy: opts.strategy,\n pair: opts.pair,\n from: opts.from,\n to: opts.to,\n initialCapital: Number(opts.capital),\n timeframe: opts.timeframe,\n slippageBps: Number(opts.slippage),\n commissionPct: Number(opts.commission),\n });\n\n console.log(\n `Running backtest: ${opts.strategy} on ${opts.pair} (${opts.from} → ${opts.to})...\\n`,\n );\n const result = await engine.run();\n\n console.log('=== Backtest Results ===');\n console.log(`Strategy: ${result.config.strategy}`);\n console.log(`Pair: ${result.config.pair}`);\n console.log(`Period: ${result.config.from} → ${result.config.to}`);\n console.log(`Initial Capital: $${result.config.initialCapital.toLocaleString()}`);\n console.log('');\n console.log(\n `Total Return: $${result.metrics.totalReturn.toFixed(2)} (${result.metrics.totalReturnPct.toFixed(2)}%)`,\n );\n console.log(`Win Rate: ${(result.metrics.winRate * 100).toFixed(1)}%`);\n console.log(`Total Trades: ${result.metrics.totalTrades}`);\n console.log(\n `Profit Factor: ${result.metrics.profitFactor === Infinity ? '∞' : result.metrics.profitFactor.toFixed(2)}`,\n );\n console.log(`Sharpe Ratio: ${result.metrics.sharpeRatio.toFixed(2)}`);\n console.log(`Max Drawdown: ${result.metrics.maxDrawdown.toFixed(2)}%`);\n\n if (result.trades.length > 0) {\n console.log('\\nLast 5 Trades:');\n for (const t of result.trades.slice(-5)) {\n const dir = t.pnl >= 0 ? '+' : '';\n console.log(\n ` ${new Date(t.entryTime).toISOString().split('T')[0]} → ${new Date(t.exitTime).toISOString().split('T')[0]} | ${t.side} | Entry: $${t.entryPrice.toFixed(2)} → Exit: $${t.exitPrice.toFixed(2)} | PnL: ${dir}$${t.pnl.toFixed(2)} (${dir}${t.pnlPct.toFixed(2)}%)`,\n );\n }\n }\n } catch (err) {\n log.error(`Backtest failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n}\n","// ---------------------------------------------------------------------------\n// Wallet manager — encrypted key storage in ~/.vizzor/wallets/\n// ---------------------------------------------------------------------------\n\nimport { randomBytes, scryptSync, createCipheriv, createDecipheriv } from 'node:crypto';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n unlinkSync,\n readdirSync,\n} from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('wallet-manager');\n\nconst WALLETS_DIR = join(homedir(), '.vizzor', 'wallets');\nconst SCRYPT_N = 2 ** 14;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst KEY_LENGTH = 32;\nconst IV_LENGTH = 12;\n\ninterface EncryptedWallet {\n name: string;\n address: string;\n salt: string; // hex\n iv: string; // hex\n tag: string; // hex\n ciphertext: string; // hex\n createdAt: string;\n}\n\nfunction ensureDir(): void {\n if (!existsSync(WALLETS_DIR)) {\n mkdirSync(WALLETS_DIR, { recursive: true });\n }\n}\n\nfunction deriveKey(password: string, salt: Buffer): Buffer {\n return scryptSync(password, salt, KEY_LENGTH, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P });\n}\n\nfunction encrypt(\n plaintext: string,\n password: string,\n): { salt: string; iv: string; tag: string; ciphertext: string } {\n const salt = randomBytes(32);\n const key = deriveKey(password, salt);\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n return {\n salt: salt.toString('hex'),\n iv: iv.toString('hex'),\n tag: tag.toString('hex'),\n ciphertext: encrypted.toString('hex'),\n };\n}\n\nfunction decrypt(\n data: { salt: string; iv: string; tag: string; ciphertext: string },\n password: string,\n): string {\n const salt = Buffer.from(data.salt, 'hex');\n const key = deriveKey(password, salt);\n const iv = Buffer.from(data.iv, 'hex');\n const decipher = createDecipheriv('aes-256-gcm', key, iv);\n decipher.setAuthTag(Buffer.from(data.tag, 'hex'));\n const decrypted = Buffer.concat([\n decipher.update(Buffer.from(data.ciphertext, 'hex')),\n decipher.final(),\n ]);\n return decrypted.toString('utf8');\n}\n\nexport function createWallet(name: string, password: string): { name: string; address: string } {\n ensureDir();\n const filePath = join(WALLETS_DIR, `${name}.json`);\n if (existsSync(filePath)) {\n throw new Error(`Wallet \"${name}\" already exists`);\n }\n\n // Generate random private key\n const privateKey = `0x${randomBytes(32).toString('hex')}`;\n\n // Derive address (simple keccak256 of public key — use viem at runtime)\n // For now, store a placeholder that gets resolved on load\n const { salt, iv, tag, ciphertext } = encrypt(privateKey, password);\n const wallet: EncryptedWallet = {\n name,\n address: '(derived on load)',\n salt,\n iv,\n tag,\n ciphertext,\n createdAt: new Date().toISOString(),\n };\n\n writeFileSync(filePath, JSON.stringify(wallet, null, 2));\n log.info(`Wallet \"${name}\" created at ${filePath}`);\n return { name, address: wallet.address };\n}\n\nexport function importWallet(\n name: string,\n privateKey: string,\n password: string,\n): { name: string; address: string } {\n ensureDir();\n const filePath = join(WALLETS_DIR, `${name}.json`);\n if (existsSync(filePath)) {\n throw new Error(`Wallet \"${name}\" already exists`);\n }\n\n const pk = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const { salt, iv, tag, ciphertext } = encrypt(pk, password);\n const wallet: EncryptedWallet = {\n name,\n address: '(derived on load)',\n salt,\n iv,\n tag,\n ciphertext,\n createdAt: new Date().toISOString(),\n };\n\n writeFileSync(filePath, JSON.stringify(wallet, null, 2));\n log.info(`Wallet \"${name}\" imported`);\n return { name, address: wallet.address };\n}\n\nexport function loadWallet(name: string, password: string): string {\n const filePath = join(WALLETS_DIR, `${name}.json`);\n if (!existsSync(filePath)) {\n throw new Error(`Wallet \"${name}\" not found`);\n }\n\n const wallet: EncryptedWallet = JSON.parse(readFileSync(filePath, 'utf8'));\n return decrypt(wallet, password);\n}\n\nexport function listWallets(): { name: string; address: string; createdAt: string }[] {\n ensureDir();\n const files = readdirSync(WALLETS_DIR).filter((f) => f.endsWith('.json'));\n return files.map((f) => {\n const wallet: EncryptedWallet = JSON.parse(readFileSync(join(WALLETS_DIR, f), 'utf8'));\n return { name: wallet.name, address: wallet.address, createdAt: wallet.createdAt };\n });\n}\n\nexport function deleteWallet(name: string): void {\n const filePath = join(WALLETS_DIR, `${name}.json`);\n if (!existsSync(filePath)) {\n throw new Error(`Wallet \"${name}\" not found`);\n }\n unlinkSync(filePath);\n log.info(`Wallet \"${name}\" deleted`);\n}\n","// ---------------------------------------------------------------------------\n// CLI: vizzor wallet — create, import, list, delete wallets\n// ---------------------------------------------------------------------------\n\nimport type { Command } from 'commander';\nimport {\n createWallet,\n importWallet,\n listWallets,\n deleteWallet,\n} from '../../core/agent/wallet-manager.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('cli-wallet');\n\nexport function registerWalletCommand(program: Command): void {\n const wallet = program.command('wallet').description('Manage encrypted trading wallets');\n\n wallet\n .command('create <name>')\n .description('Create a new wallet with a random private key')\n .requiredOption('-p, --password <password>', 'Encryption password')\n .action((name: string, opts: { password: string }) => {\n try {\n const result = createWallet(name, opts.password);\n console.log(`Wallet \"${result.name}\" created successfully.`);\n console.log(`Address: ${result.address}`);\n console.log('Stored in ~/.vizzor/wallets/');\n } catch (err) {\n log.error(`Failed to create wallet: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\n wallet\n .command('import <name>')\n .description('Import a wallet from a private key')\n .requiredOption('-k, --key <privateKey>', 'Private key (hex)')\n .requiredOption('-p, --password <password>', 'Encryption password')\n .action((name: string, opts: { key: string; password: string }) => {\n try {\n const result = importWallet(name, opts.key, opts.password);\n console.log(`Wallet \"${result.name}\" imported successfully.`);\n } catch (err) {\n log.error(`Failed to import wallet: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n\n wallet\n .command('list')\n .description('List all saved wallets')\n .action(() => {\n const wallets = listWallets();\n if (wallets.length === 0) {\n console.log('No wallets found.');\n return;\n }\n console.log('Wallets:');\n for (const w of wallets) {\n console.log(` ${w.name} — ${w.address} (created: ${w.createdAt})`);\n }\n });\n\n wallet\n .command('delete <name>')\n .description('Delete a wallet')\n .action((name: string) => {\n try {\n deleteWallet(name);\n console.log(`Wallet \"${name}\" deleted.`);\n } catch (err) {\n log.error(`Failed to delete wallet: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n }\n });\n}\n","// ---------------------------------------------------------------------------\n// Binance WebSocket client — real-time market data streams\n// ---------------------------------------------------------------------------\n\nimport { EventEmitter } from 'node:events';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('binance-ws');\n\nconst BASE_URL = 'wss://stream.binance.com:9443/ws';\n\nexport interface WSTrade {\n symbol: string;\n price: number;\n quantity: number;\n time: number;\n isBuyerMaker: boolean;\n}\n\nexport interface WSKline {\n symbol: string;\n interval: string;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n openTime: number;\n closeTime: number;\n isClosed: boolean;\n}\n\nexport interface WSTicker {\n symbol: string;\n price: number;\n priceChange: number;\n priceChangePct: number;\n volume: number;\n quoteVolume: number;\n}\n\nexport class BinanceWebSocket extends EventEmitter {\n private ws: WebSocket | null = null;\n private streams: string[] = [];\n private reconnectDelay = 1000;\n private maxReconnectDelay = 30000;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnecting = false;\n private closed = false;\n\n constructor(streams: string[]) {\n super();\n this.streams = streams;\n }\n\n connect(): void {\n if (this.closed) return;\n const url =\n this.streams.length === 1\n ? `${BASE_URL}/${this.streams[0]}`\n : `${BASE_URL}/${this.streams.join('/')}`;\n\n log.debug(`Connecting to ${url}`);\n this.ws = new WebSocket(url);\n\n this.ws.onopen = () => {\n log.info(`WebSocket connected (${this.streams.length} streams)`);\n this.reconnectDelay = 1000;\n this.reconnecting = false;\n this.startHeartbeat();\n this.emit('connected');\n };\n\n this.ws.onmessage = (event) => {\n try {\n const data = JSON.parse(String(event.data)) as Record<string, unknown>;\n this.handleMessage(data);\n } catch {\n // Ignore parse errors\n }\n };\n\n this.ws.onclose = () => {\n this.stopHeartbeat();\n if (!this.closed) {\n this.scheduleReconnect();\n }\n };\n\n this.ws.onerror = () => {\n log.debug('WebSocket error');\n };\n }\n\n close(): void {\n this.closed = true;\n this.stopHeartbeat();\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n private handleMessage(data: Record<string, unknown>): void {\n const eventType = data['e'] as string | undefined;\n\n if (eventType === 'trade') {\n const trade: WSTrade = {\n symbol: String(data['s']),\n price: Number(data['p']),\n quantity: Number(data['q']),\n time: Number(data['T']),\n isBuyerMaker: Boolean(data['m']),\n };\n this.emit('trade', trade);\n } else if (eventType === 'kline') {\n const k = data['k'] as Record<string, unknown>;\n const kline: WSKline = {\n symbol: String(data['s']),\n interval: String(k['i']),\n open: Number(k['o']),\n high: Number(k['h']),\n low: Number(k['l']),\n close: Number(k['c']),\n volume: Number(k['v']),\n openTime: Number(k['t']),\n closeTime: Number(k['T']),\n isClosed: Boolean(k['x']),\n };\n this.emit('kline', kline);\n } else if (eventType === '24hrTicker') {\n const ticker: WSTicker = {\n symbol: String(data['s']),\n price: Number(data['c']),\n priceChange: Number(data['p']),\n priceChangePct: Number(data['P']),\n volume: Number(data['v']),\n quoteVolume: Number(data['q']),\n };\n this.emit('ticker', ticker);\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnecting || this.closed) return;\n this.reconnecting = true;\n log.info(`Reconnecting in ${this.reconnectDelay}ms...`);\n setTimeout(() => {\n this.connect();\n }, this.reconnectDelay);\n this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);\n }\n\n private startHeartbeat(): void {\n this.heartbeatTimer = setInterval(() => {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify({ method: 'PING' }));\n }\n }, 30000);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n}\n","// ---------------------------------------------------------------------------\n// WebSocket connection manager — singleton with price cache\n// ---------------------------------------------------------------------------\n\nimport { BinanceWebSocket, type WSTrade, type WSKline, type WSTicker } from './binance-ws.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('ws-manager');\n\nconst MAX_STREAMS_PER_CONN = 1024;\nconst MAX_CONNECTIONS = 5;\n\nexport interface PriceCache {\n price: number;\n time: number;\n}\n\nexport class WSManager {\n private connections: BinanceWebSocket[] = [];\n private priceCache = new Map<string, PriceCache>();\n private subscriptions = new Map<string, Set<string>>(); // symbol → stream types\n private tradeCallbacks = new Map<string, Set<(trade: WSTrade) => void>>();\n private klineCallbacks = new Map<string, Set<(kline: WSKline) => void>>();\n private started = false;\n\n subscribe(\n symbol: string,\n streams: ('trade' | 'kline_1m' | 'ticker')[] = ['trade', 'ticker'],\n ): void {\n const existing = this.subscriptions.get(symbol) ?? new Set();\n for (const s of streams) {\n existing.add(s);\n }\n this.subscriptions.set(symbol, existing);\n }\n\n unsubscribe(symbol: string): void {\n this.subscriptions.delete(symbol);\n this.priceCache.delete(symbol.toUpperCase());\n }\n\n start(): void {\n if (this.started) return;\n this.started = true;\n\n // Build stream list from subscriptions\n const allStreams: string[] = [];\n for (const [symbol, types] of this.subscriptions) {\n const lower = symbol.toLowerCase();\n for (const type of types) {\n if (type === 'trade') allStreams.push(`${lower}@trade`);\n else if (type === 'kline_1m') allStreams.push(`${lower}@kline_1m`);\n else if (type === 'ticker') allStreams.push(`${lower}@ticker`);\n }\n }\n\n if (allStreams.length === 0) {\n log.info('No subscriptions — WebSocket manager idle');\n return;\n }\n\n // Split into connection groups\n for (let i = 0; i < allStreams.length; i += MAX_STREAMS_PER_CONN) {\n if (this.connections.length >= MAX_CONNECTIONS) break;\n const chunk = allStreams.slice(i, i + MAX_STREAMS_PER_CONN);\n const ws = new BinanceWebSocket(chunk);\n\n ws.on('trade', (trade: WSTrade) => {\n this.priceCache.set(trade.symbol, { price: trade.price, time: trade.time });\n const callbacks = this.tradeCallbacks.get(trade.symbol);\n if (callbacks) {\n for (const cb of callbacks) cb(trade);\n }\n });\n\n ws.on('ticker', (ticker: WSTicker) => {\n this.priceCache.set(ticker.symbol, { price: ticker.price, time: Date.now() });\n });\n\n ws.on('kline', (kline: WSKline) => {\n const key = `${kline.symbol}:${kline.interval}`;\n const callbacks = this.klineCallbacks.get(key);\n if (callbacks) {\n for (const cb of callbacks) cb(kline);\n }\n });\n\n ws.connect();\n this.connections.push(ws);\n }\n\n log.info(\n `WebSocket manager started: ${this.connections.length} connections, ${allStreams.length} streams`,\n );\n }\n\n stop(): void {\n for (const ws of this.connections) {\n ws.close();\n }\n this.connections = [];\n this.started = false;\n log.info('WebSocket manager stopped');\n }\n\n getLatestPrice(symbol: string): number | null {\n const upper = symbol.toUpperCase().replace('/', '');\n const cached = this.priceCache.get(upper);\n if (!cached) return null;\n // Cache valid for 60 seconds\n if (Date.now() - cached.time > 60000) return null;\n return cached.price;\n }\n\n onTrade(symbol: string, callback: (trade: WSTrade) => void): void {\n const upper = symbol.toUpperCase();\n const set = this.tradeCallbacks.get(upper) ?? new Set();\n set.add(callback);\n this.tradeCallbacks.set(upper, set);\n }\n\n onKline(symbol: string, interval: string, callback: (kline: WSKline) => void): void {\n const key = `${symbol.toUpperCase()}:${interval}`;\n const set = this.klineCallbacks.get(key) ?? new Set();\n set.add(callback);\n this.klineCallbacks.set(key, set);\n }\n}\n\n// Singleton\nlet instance: WSManager | null = null;\n\nexport function getWSManager(): WSManager | null {\n return instance;\n}\n\nexport function initWSManager(): WSManager {\n if (!instance) {\n instance = new WSManager();\n }\n return instance;\n}\n","import React, { useState, useEffect } from 'react';\nimport { Box, Text, Spacer } from 'ink';\n\ninterface StatusBarProps {\n provider: string;\n chain: string;\n connected: boolean;\n}\n\nexport const StatusBar = React.memo(function StatusBar({\n provider,\n chain,\n connected,\n}: StatusBarProps): React.JSX.Element {\n const [time, setTime] = useState(() =>\n new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }),\n );\n\n // Update time once per minute instead of every re-render\n useEffect(() => {\n const id = setInterval(() => {\n setTime(\n new Date().toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n }),\n );\n }, 60_000);\n return () => clearInterval(id);\n }, []);\n\n return (\n <Box paddingX={1}>\n <Text dimColor>\n <Text color={connected ? 'green' : 'red'}>{connected ? '\\u25CF' : '\\u25CB'}</Text>{' '}\n <Text bold>{provider}</Text>\n </Text>\n <Text dimColor>{' \\u2502 '}</Text>\n <Text dimColor>\n chain: <Text bold>{chain}</Text>\n </Text>\n <Spacer />\n <Text dimColor>{time}</Text>\n </Box>\n );\n});\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport type { UsePriceTickerResult } from '../hooks/use-price-ticker.js';\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) return `$${price.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;\n if (price >= 1) return `$${price.toFixed(2)}`;\n return `$${price.toFixed(4)}`;\n}\n\ninterface PriceTickerProps {\n ticker: UsePriceTickerResult;\n focused?: boolean;\n onSelect?: (symbol: string) => void;\n onAddPress?: () => void;\n}\n\nexport function PriceTicker({\n ticker,\n focused = false,\n onSelect: _onSelect,\n onAddPress,\n}: PriceTickerProps): React.JSX.Element {\n const { entries, isRefreshing, selectedIndex } = ticker;\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor={focused ? 'cyan' : 'gray'}\n borderLeft={false}\n borderRight={false}\n borderTop={false}\n paddingX={1}\n gap={3}\n >\n {focused && (\n <Text color=\"cyan\" dimColor>\n {'<'}\n </Text>\n )}\n {entries.map((entry, idx) => {\n const isSelected = focused && selectedIndex === idx;\n\n if (entry.loading) {\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text dimColor>{entry.symbol}</Text>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n </Box>\n );\n }\n if (entry.error) {\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text dimColor>{entry.symbol}</Text>\n <Text color=\"red\">--</Text>\n </Box>\n );\n }\n const color = entry.change24h >= 0 ? 'green' : 'red';\n const arrow = entry.change24h >= 0 ? '\\u25B2' : '\\u25BC';\n const prefix = entry.change24h >= 0 ? '+' : '';\n return (\n <Box key={entry.geckoId} gap={1}>\n <Text bold inverse={isSelected} color={isSelected ? 'cyan' : undefined}>\n {isSelected ? `[${entry.symbol}]` : entry.symbol}\n </Text>\n <Text>{formatPrice(entry.price)}</Text>\n <Text color={color}>\n {arrow}\n {prefix}\n {entry.change24h.toFixed(1)}%\n </Text>\n </Box>\n );\n })}\n {focused && (\n <Text color=\"cyan\" dimColor>\n {'>'}\n </Text>\n )}\n {isRefreshing && (\n <Text dimColor>\n <Spinner type=\"dots\" />\n </Text>\n )}\n {onAddPress && (\n <Text color=\"cyan\" dimColor>\n [+]\n </Text>\n )}\n {focused && <Text dimColor>Tab:exit | Enter:analyze</Text>}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\nexport function WelcomeBanner(): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Box>\n <Text bold color=\"cyan\">\n {' '}\n </Text>\n <Text bold color=\"blue\">\n vizzor\n </Text>\n <Text bold color=\"cyan\">\n {' v0.11.0'}\n </Text>\n <Text dimColor> — AI-powered crypto chronovisor</Text>\n </Box>\n <Box>\n <Text dimColor>\n {\n ' ML models: LSTM + Random Forest + Isolation Forest + GBM Rug + Wallet LSTM + DistilBERT NLP'\n }\n </Text>\n </Box>\n <Box>\n <Text dimColor>{' Type '}</Text>\n <Text color=\"yellow\">/help</Text>\n <Text dimColor> for commands or ask anything about crypto.</Text>\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface RiskBarProps {\n score: number;\n level: string;\n factors?: string[];\n}\n\nfunction getLevelColor(level: string): string {\n switch (level.toLowerCase()) {\n case 'low':\n return 'green';\n case 'medium':\n return 'yellow';\n case 'high':\n return 'red';\n case 'critical':\n return 'red';\n default:\n return 'white';\n }\n}\n\nfunction buildProgressBar(score: number, width = 20): string {\n const clamped = Math.max(0, Math.min(100, score));\n const filled = Math.round((clamped / 100) * width);\n const empty = width - filled;\n return '\\u2588'.repeat(filled) + '\\u2591'.repeat(empty);\n}\n\nexport function RiskBar({ score, level, factors }: RiskBarProps): React.JSX.Element {\n const color = getLevelColor(level);\n const isCritical = level.toLowerCase() === 'critical';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={color} paddingX={1}>\n <Text inverse bold color={color}>\n {' RISK ASSESSMENT '}\n </Text>\n <Box gap={2}>\n <Text>\n Score:{' '}\n <Text bold color={color}>\n {score}/100\n </Text>\n </Text>\n <Text>\n Level:{' '}\n <Text bold={isCritical} color={color}>\n {level.toUpperCase()}\n </Text>\n </Text>\n </Box>\n <Text color={color}>{buildProgressBar(score)}</Text>\n {factors && factors.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text dimColor>Risk factors:</Text>\n {factors.map((factor, idx) => (\n <Text key={idx} dimColor>\n {' - '}\n {factor}\n </Text>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface TokenCardProps {\n name: string;\n symbol: string;\n decimals: number;\n totalSupply: string;\n}\n\nfunction formatWithCommas(value: string): string {\n const parts = value.split('.');\n const intPart = parts[0] ?? '';\n const formatted = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return parts.length > 1 ? `${formatted}.${parts[1]}` : formatted;\n}\n\nexport function TokenCard({\n name,\n symbol,\n decimals,\n totalSupply,\n}: TokenCardProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"blue\" paddingX={1}>\n <Text inverse bold color=\"blue\">\n {' TOKEN '}\n </Text>\n <Text>\n Name: <Text bold>{name}</Text> <Text dimColor>({symbol})</Text>\n </Text>\n <Text>\n Decimals: <Text bold>{decimals}</Text>\n </Text>\n <Text>\n Supply: <Text bold>{formatWithCommas(totalSupply)}</Text>\n </Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface HolderEntry {\n address: string;\n percentage: number;\n}\n\ninterface HolderListProps {\n holders: HolderEntry[];\n}\n\nfunction truncateAddress(address: string): string {\n if (address.length <= 13) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\nfunction buildPercentageBar(percentage: number, width = 20): string {\n const clamped = Math.max(0, Math.min(100, percentage));\n const filled = Math.round((clamped / 100) * width);\n const empty = width - filled;\n return '\\u2588'.repeat(filled) + '\\u2591'.repeat(empty);\n}\n\nexport function HolderList({ holders }: HolderListProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n <Text inverse bold>\n {' TOP HOLDERS '}\n </Text>\n {holders.map((holder, idx) => (\n <Box key={idx} gap={1}>\n <Text dimColor>{truncateAddress(holder.address)}</Text>\n <Text color=\"cyan\">{buildPercentageBar(holder.percentage)}</Text>\n <Text bold>{holder.percentage.toFixed(2)}%</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface MarketTickerProps {\n symbol: string;\n price: number;\n change24h: number;\n volume: number;\n}\n\nfunction formatCurrency(value: number): string {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n minimumFractionDigits: 2,\n maximumFractionDigits: 6,\n }).format(value);\n}\n\nfunction formatVolume(value: number): string {\n if (value >= 1_000_000_000) return `$${(value / 1_000_000_000).toFixed(2)}B`;\n if (value >= 1_000_000) return `$${(value / 1_000_000).toFixed(2)}M`;\n if (value >= 1_000) return `$${(value / 1_000).toFixed(2)}K`;\n return `$${value.toFixed(2)}`;\n}\n\nexport function MarketTicker({\n symbol,\n price,\n change24h,\n volume,\n}: MarketTickerProps): React.JSX.Element {\n const changeColor = change24h >= 0 ? 'green' : 'red';\n const changePrefix = change24h >= 0 ? '+' : '';\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"magenta\" paddingX={1}>\n <Text inverse bold color=\"magenta\">\n {' MARKET '}\n </Text>\n <Text>\n {symbol.toUpperCase()}: <Text bold>{formatCurrency(price)}</Text>\n </Text>\n <Text>\n 24h:{' '}\n <Text color={changeColor} bold>\n {changePrefix}\n {change24h.toFixed(2)}%\n </Text>\n </Text>\n <Text>\n Volume: <Text bold>{formatVolume(volume)}</Text>\n </Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface Finding {\n severity: string;\n description: string;\n}\n\ninterface AuditResultProps {\n findings: Finding[];\n}\n\nfunction getSeverityColor(severity: string): string {\n switch (severity.toLowerCase()) {\n case 'critical':\n return 'red';\n case 'high':\n return 'red';\n case 'medium':\n return 'yellow';\n case 'low':\n return 'green';\n case 'info':\n return 'blue';\n default:\n return 'white';\n }\n}\n\nfunction getSeverityIcon(severity: string): string {\n switch (severity.toLowerCase()) {\n case 'critical':\n return '\\u2718';\n case 'high':\n return '\\u2718';\n case 'medium':\n return '\\u26A0';\n case 'low':\n return '\\u25CB';\n case 'info':\n return '\\u2139';\n default:\n return '\\u2022';\n }\n}\n\nexport function AuditResult({ findings }: AuditResultProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text inverse bold color=\"yellow\">\n {' AUDIT RESULTS '}\n </Text>\n {findings.length === 0 ? (\n <Text color=\"green\">No findings detected.</Text>\n ) : (\n findings.map((finding, idx) => {\n const color = getSeverityColor(finding.severity);\n const icon = getSeverityIcon(finding.severity);\n return (\n <Box key={idx} gap={1}>\n <Text color={color}>{icon}</Text>\n <Text color={color} bold>\n [{finding.severity.toUpperCase()}]\n </Text>\n <Text>{finding.description}</Text>\n </Box>\n );\n })\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text, Newline } from 'ink';\nimport { RiskBar } from '../blocks/risk-bar.js';\nimport { TokenCard } from '../blocks/token-card.js';\nimport { HolderList } from '../blocks/holder-list.js';\nimport { MarketTicker } from '../blocks/market-ticker.js';\nimport { AuditResult } from '../blocks/audit-result.js';\n\nexport type RichBlock =\n | { type: 'risk'; data: { score: number; level: string; factors: string[] } }\n | { type: 'token'; data: { name: string; symbol: string; decimals: number; totalSupply: string } }\n | { type: 'holders'; data: { address: string; percentage: number }[] }\n | { type: 'market'; data: { symbol: string; price: number; change24h: number; volume: number } }\n | { type: 'audit'; data: { findings: { severity: string; description: string }[] } };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: string;\n blocks?: RichBlock[];\n timestamp?: Date;\n}\n\ninterface MessageListProps {\n messages: Message[];\n}\n\nexport function RichBlockRenderer({ block }: { block: RichBlock }): React.JSX.Element | null {\n switch (block.type) {\n case 'risk':\n return (\n <RiskBar score={block.data.score} level={block.data.level} factors={block.data.factors} />\n );\n case 'token':\n return (\n <TokenCard\n name={block.data.name}\n symbol={block.data.symbol}\n decimals={block.data.decimals}\n totalSupply={block.data.totalSupply}\n />\n );\n case 'holders':\n return <HolderList holders={block.data} />;\n case 'market':\n return (\n <MarketTicker\n symbol={block.data.symbol}\n price={block.data.price}\n change24h={block.data.change24h}\n volume={block.data.volume}\n />\n );\n case 'audit':\n return <AuditResult findings={block.data.findings} />;\n default:\n return null;\n }\n}\n\nexport function MessageList({ messages }: MessageListProps): React.JSX.Element {\n return (\n <Box flexDirection=\"column\" gap={1}>\n {messages.map((msg, idx) => (\n <Box key={idx} flexDirection=\"column\">\n {msg.role === 'user' ? (\n <Box>\n <Text bold color=\"#FFA500\">\n You:{' '}\n </Text>\n <Text>{msg.content}</Text>\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n <Box>\n <Text bold color=\"blue\">\n Vizzor:{' '}\n </Text>\n <Text>{msg.content}</Text>\n </Box>\n {msg.blocks?.map((block, blockIdx) => (\n <Box key={blockIdx} marginTop={1}>\n <RichBlockRenderer block={block} />\n </Box>\n ))}\n </Box>\n )}\n {idx < messages.length - 1 && <Newline />}\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { Message, RichBlock } from './message-list.js';\nimport { RichBlockRenderer } from './message-list.js';\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n}\n\ninterface MessageBubbleProps {\n message: Message;\n}\n\nexport function MessageBubble({ message }: MessageBubbleProps): React.JSX.Element {\n const isUser = message.role === 'user';\n const color = isUser ? '#FFA500' : '#4A9EFF';\n const icon = isUser ? '\\u25CF' : '\\u25C6';\n const label = isUser ? 'You' : 'Vizzor';\n const time = message.timestamp ? formatTime(message.timestamp) : '';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text color={color} bold>\n {icon} {label}\n </Text>\n {time && <Text dimColor>{time}</Text>}\n </Box>\n\n <Box\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor={color}\n paddingLeft={1}\n marginLeft={1}\n flexDirection=\"column\"\n >\n <Text wrap=\"wrap\">{message.content}</Text>\n {message.blocks?.map((block: RichBlock, idx: number) => (\n <Box key={idx} marginTop={1}>\n <RichBlockRenderer block={block} />\n </Box>\n ))}\n </Box>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface CommandHintsProps {\n filter: string;\n}\n\nconst COMMANDS = [\n { name: 'scan', args: '<address> [--chain]', desc: 'Scan token risk' },\n { name: 'track', args: '<wallet> [--chain]', desc: 'Analyze wallet' },\n { name: 'trends', args: '', desc: 'Market trends' },\n { name: 'audit', args: '<contract> [--chain]', desc: 'Audit contract' },\n { name: 'chain', args: '[chainId]', desc: 'Switch or list chains' },\n { name: 'add', args: '<symbol>', desc: 'Add crypto to ticker' },\n { name: 'remove', args: '<symbol>', desc: 'Remove from ticker' },\n { name: 'agent', args: '<create|list|start|stop|status|delete>', desc: 'Manage agents' },\n { name: 'provider', args: '[list|<name>]', desc: 'Switch AI provider' },\n { name: 'config', args: '[set <key> <value>]', desc: 'Show/set config' },\n { name: 'clear', args: '', desc: 'Clear messages' },\n { name: 'help', args: '', desc: 'Show help' },\n { name: 'exit', args: '', desc: 'Exit Vizzor' },\n];\n\nexport function CommandHints({ filter }: CommandHintsProps): React.JSX.Element | null {\n const query = filter.startsWith('/') ? filter.slice(1).toLowerCase() : '';\n const matches = query.length === 0 ? COMMANDS : COMMANDS.filter((c) => c.name.startsWith(query));\n\n if (matches.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n {matches.slice(0, 6).map((cmd) => (\n <Box key={cmd.name} gap={1}>\n <Text color=\"cyan\" bold>\n /{cmd.name}\n </Text>\n {cmd.args ? <Text dimColor>{cmd.args}</Text> : null}\n <Text dimColor>\n {'— '}\n {cmd.desc}\n </Text>\n </Box>\n ))}\n {matches.length > 6 && <Text dimColor>...{matches.length - 6} more</Text>}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\n\nconst TOOL_LABELS: Record<string, { active: string; done: string }> = {\n get_token_info: { active: 'Fetching token info...', done: 'Token info loaded' },\n analyze_wallet: { active: 'Analyzing wallet...', done: 'Wallet analyzed' },\n check_rug_indicators: { active: 'Checking rug indicators...', done: 'Rug check complete' },\n get_market_data: { active: 'Fetching market data...', done: 'Market data loaded' },\n search_upcoming_icos: { active: 'Searching ICOs...', done: 'ICO search complete' },\n search_token_dex: { active: 'Searching DEX pairs...', done: 'DEX search complete' },\n get_trending: { active: 'Fetching trending tokens...', done: 'Trending loaded' },\n get_crypto_news: { active: 'Fetching crypto news...', done: 'News loaded' },\n get_raises: { active: 'Fetching recent raises...', done: 'Raises loaded' },\n};\n\ninterface ToolStatusListProps {\n active: string[];\n completed: string[];\n}\n\nexport function ToolStatusList({\n active,\n completed,\n}: ToolStatusListProps): React.JSX.Element | null {\n if (active.length === 0 && completed.length === 0) return null;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor=\"gray\"\n paddingLeft={1}\n marginLeft={2}\n >\n {completed.map((tool) => {\n const labels = TOOL_LABELS[tool] ?? { done: `${tool} complete` };\n return (\n <Box key={`done-${tool}`} gap={1}>\n <Text color=\"green\">{'\\u2713'}</Text>\n <Text>{labels.done}</Text>\n </Box>\n );\n })}\n {active.map((tool) => {\n const labels = TOOL_LABELS[tool] ?? { active: `Running ${tool}...` };\n return (\n <Box key={`active-${tool}`} gap={1}>\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n <Text dimColor>{labels.active}</Text>\n </Box>\n );\n })}\n </Box>\n );\n}\n\n// Keep backward compat export\ninterface ToolStatusProps {\n toolName: string;\n isActive: boolean;\n}\n\nexport function ToolStatus({ toolName, isActive }: ToolStatusProps): React.JSX.Element {\n return (\n <ToolStatusList active={isActive ? [toolName] : []} completed={isActive ? [] : [toolName]} />\n ) as React.JSX.Element;\n}\n","import React, { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface InputPromptProps {\n onSubmit: (value: string) => void;\n disabled?: boolean;\n onInputChange?: (value: string) => void;\n}\n\nexport function InputPrompt({\n onSubmit,\n disabled = false,\n onInputChange,\n}: InputPromptProps): React.JSX.Element {\n const [value, setValue] = useState('');\n\n const handleChange = (newValue: string): void => {\n setValue(newValue);\n onInputChange?.(newValue);\n };\n\n const handleSubmit = (submitted: string): void => {\n const trimmed = submitted.trim();\n if (trimmed.length === 0) return;\n onSubmit(trimmed);\n setValue('');\n onInputChange?.('');\n };\n\n return (\n <Box borderStyle=\"round\" borderColor={disabled ? 'gray' : 'blue'} paddingX={1}>\n {disabled ? (\n <Text dimColor italic>\n thinking...\n </Text>\n ) : (\n <Box>\n <Text bold color=\"green\">\n vizzor\n </Text>\n <Text dimColor>{' > '}</Text>\n <TextInput\n value={value}\n onChange={handleChange}\n onSubmit={handleSubmit}\n placeholder=\"Ask anything or type / for commands\"\n />\n </Box>\n )}\n </Box>\n );\n}\n","import React, { useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\n\n// Maximum visible lines during streaming to prevent Ink live-area overflow.\n// The full response is preserved in state and added to <Static> after streaming.\nconst MAX_VISIBLE_LINES = 20;\n\ninterface StreamingTextProps {\n text: string;\n isStreaming: boolean;\n}\n\nexport function StreamingText({ text, isStreaming }: StreamingTextProps): React.JSX.Element {\n const { displayText, isTruncated } = useMemo(() => {\n if (!isStreaming) return { displayText: text, isTruncated: false };\n\n const lines = text.split('\\n');\n if (lines.length <= MAX_VISIBLE_LINES) {\n return { displayText: text, isTruncated: false };\n }\n\n const visible = lines.slice(-MAX_VISIBLE_LINES);\n return { displayText: visible.join('\\n'), isTruncated: true };\n }, [text, isStreaming]);\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text color=\"#4A9EFF\" bold>\n {'\\u25C6'} Vizzor\n </Text>\n {isStreaming && (\n <Text color=\"cyan\">\n <Spinner type=\"dots\" />\n </Text>\n )}\n </Box>\n <Box\n borderStyle=\"single\"\n borderLeft\n borderRight={false}\n borderTop={false}\n borderBottom={false}\n borderColor=\"#4A9EFF\"\n paddingLeft={1}\n marginLeft={1}\n flexDirection=\"column\"\n >\n {isTruncated && <Text dimColor>{'... (streaming, showing last lines) ...'}</Text>}\n <Text wrap=\"wrap\">\n {displayText}\n {isStreaming ? <Text dimColor>{'\\u2588'}</Text> : null}\n </Text>\n </Box>\n </Box>\n );\n}\n","// ---------------------------------------------------------------------------\n// React hook that wraps the streaming AI provider for the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport { useState, useCallback } from 'react';\nimport { getProvider, getToolHandler } from '../../ai/client.js';\nimport { buildChatSystemPrompt, OLLAMA_SYSTEM_PROMPT } from '../../ai/prompts/chat.js';\nimport { VIZZOR_TOOLS } from '../../ai/tools.js';\nimport { buildContextBlock } from '../../ai/context-injector.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseAIStreamResult {\n /** The text accumulated so far from the streaming response. */\n streamingText: string;\n /** Whether the AI is currently streaming a response. */\n isStreaming: boolean;\n /** Tool names currently being executed. */\n activeTools: string[];\n /** Tool names that have finished executing. */\n completedTools: string[];\n /** Send a message to the AI and begin streaming the response. */\n sendMessage: (message: string) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that manages streaming AI chat sessions.\n *\n * Calls the active provider's `analyzeStream()` method with the Vizzor system\n * prompt and tool definitions. Exposes incremental text, tool execution\n * status, and a `sendMessage` callback.\n */\nexport function useAIStream(): UseAIStreamResult {\n const [streamingText, setStreamingText] = useState('');\n const [isStreaming, setIsStreaming] = useState(false);\n const [activeTools, setActiveTools] = useState<string[]>([]);\n const [completedTools, setCompletedTools] = useState<string[]>([]);\n\n const sendMessage = useCallback((message: string): void => {\n // Reset state for a new message\n setStreamingText('');\n setIsStreaming(true);\n setActiveTools([]);\n setCompletedTools([]);\n\n const provider = getProvider();\n const toolHandler = getToolHandler();\n\n const callbacks = {\n onText(delta: string): void {\n setStreamingText((prev) => prev + delta);\n },\n onToolStart(name: string): void {\n setActiveTools((prev) => [...prev, name]);\n },\n onToolEnd(name: string): void {\n setActiveTools((prev) => prev.filter((t) => t !== name));\n setCompletedTools((prev) => [...prev, name]);\n },\n onDone(_fullText: string): void {\n setIsStreaming(false);\n setActiveTools([]);\n setCompletedTools([]);\n },\n };\n\n // For providers without tool support, inject real-time data into prompt\n const startStream = async (): Promise<void> => {\n if (!provider.supportsTools) {\n const context = await buildContextBlock(message);\n const systemPrompt = OLLAMA_SYSTEM_PROMPT + (context ? '\\n' + context : '');\n await provider.analyzeStream(systemPrompt, message, callbacks);\n } else {\n await provider.analyzeStream(\n buildChatSystemPrompt(),\n message,\n callbacks,\n VIZZOR_TOOLS,\n toolHandler,\n );\n }\n };\n\n startStream().catch((err: unknown) => {\n const detail = err instanceof Error ? err.message : String(err);\n setIsStreaming(false);\n setActiveTools([]);\n setCompletedTools([]);\n setStreamingText((prev) =>\n prev.length > 0 ? prev + `\\n\\n[Stream interrupted: ${detail}]` : `[AI error: ${detail}]`,\n );\n });\n }, []);\n\n return { streamingText, isStreaming, activeTools, completedTools, sendMessage };\n}\n","// ---------------------------------------------------------------------------\n// Slash command parser and dispatcher for the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport type { RichBlock } from './components/message-list.js';\nimport { getAdapter } from '../chains/registry.js';\nimport { analyzeProject } from '../core/scanner/project-analyzer.js';\nimport { assessRisk } from '../core/scanner/risk-scorer.js';\nimport { fetchTrendingTokens } from '../core/trends/market.js';\nimport { analyzeWallet } from '../core/forensics/wallet-analyzer.js';\nimport { auditContract } from '../core/forensics/contract-auditor.js';\nimport { getConfig, saveConfigValue, getSettableKeys } from '../config/loader.js';\nimport { DEFAULT_CHAIN } from '../config/constants.js';\nimport { fetchTopGainersLosers } from '../data/sources/binance.js';\nimport {\n createAgent,\n listAgents,\n deleteAgent,\n startAgent,\n stopAgent,\n getAgentStatus,\n getRecentDecisions,\n listStrategies,\n getAgentByName,\n} from '../core/agent/index.js';\nimport { getProvider, switchProvider } from '../ai/client.js';\nimport { getAvailableProviders } from '../ai/providers/registry.js';\nimport { DEFAULT_MODELS } from '../ai/providers/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CommandResult {\n blocks: RichBlock[];\n text: string;\n}\n\n// ---------------------------------------------------------------------------\n// Parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Check whether the given input string is a slash command (starts with `/`).\n */\nexport function isSlashCommand(input: string): boolean {\n return input.trimStart().startsWith('/');\n}\n\n/**\n * Parse a slash command string into a command name and arguments array.\n *\n * @example\n * parseCommand('/scan 0xabc --chain polygon')\n * // => { name: 'scan', args: ['0xabc', '--chain', 'polygon'] }\n */\nexport function parseCommand(input: string): { name: string; args: string[] } {\n const trimmed = input.trimStart();\n const parts = trimmed.split(/\\s+/);\n const raw = parts[0] ?? '/help';\n // Strip the leading `/`\n const name = raw.startsWith('/') ? raw.slice(1) : raw;\n const args = parts.slice(1);\n return { name, args };\n}\n\n// ---------------------------------------------------------------------------\n// Flag helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the `--chain <value>` flag from an args array, defaulting to\n * `'ethereum'` when absent.\n */\nfunction extractChainFlag(args: string[]): string {\n const idx = args.indexOf('--chain');\n if (idx !== -1 && idx + 1 < args.length) {\n return args[idx + 1] ?? DEFAULT_CHAIN;\n }\n return DEFAULT_CHAIN;\n}\n\n/**\n * Return positional args (everything that is not `--chain` or its value).\n */\nfunction positionalArgs(args: string[]): string[] {\n const result: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--chain') {\n i++; // skip the next arg (chain value)\n continue;\n }\n const arg = args[i];\n if (arg !== undefined) result.push(arg);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Mask helper (for /config)\n// ---------------------------------------------------------------------------\n\nfunction maskKey(value: string | undefined): string {\n if (!value) return '(not set)';\n if (value.length <= 4) return '****';\n if (value.length <= 8) return value.slice(0, 1) + '****' + value.slice(-1);\n return value.slice(0, 2) + '*'.repeat(Math.min(value.length - 4, 12)) + value.slice(-2);\n}\n\n// ---------------------------------------------------------------------------\n// Command executor\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a parsed slash command by name and return a {@link CommandResult}.\n *\n * The `/clear` and `/exit` commands return a result with empty text so the\n * caller (the app component) can handle them specially.\n */\nexport async function executeCommand(name: string, args: string[]): Promise<CommandResult> {\n switch (name) {\n case 'scan':\n return handleScan(args);\n case 'track':\n return handleTrack(args);\n case 'trends':\n return handleTrends();\n case 'audit':\n return handleAudit(args);\n case 'help':\n return handleHelp();\n case 'provider':\n return handleProvider(args);\n case 'config':\n return handleConfig(args);\n case 'agent':\n return handleAgent(args);\n case 'backtest':\n return handleBacktest(args);\n case 'clear':\n return { blocks: [], text: '' };\n case 'exit':\n return { blocks: [], text: '' };\n default:\n return {\n blocks: [],\n text: `Unknown command: /${name}. Type /help for available commands.`,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command handlers\n// ---------------------------------------------------------------------------\n\nasync function handleScan(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const address = positional[0];\n\n if (!address) {\n return { blocks: [], text: 'Usage: /scan <address> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const analysis = await analyzeProject(address, adapter);\n const risk = assessRisk(analysis);\n\n const blocks: RichBlock[] = [\n {\n type: 'risk',\n data: { score: risk.score, level: risk.level, factors: risk.factors },\n },\n ];\n\n if (analysis.token) {\n blocks.push({\n type: 'token',\n data: {\n name: analysis.token.name,\n symbol: analysis.token.symbol,\n decimals: analysis.token.decimals,\n totalSupply: analysis.token.totalSupply.toString(),\n },\n });\n }\n\n return {\n blocks,\n text: `Scan complete for ${address} on ${chain}. ${risk.summary}`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Scan failed: ${message}` };\n }\n}\n\nasync function handleTrack(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const wallet = positional[0];\n\n if (!wallet) {\n return { blocks: [], text: 'Usage: /track <wallet> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const analysis = await analyzeWallet(wallet, adapter);\n\n const patternSummary =\n analysis.patterns.length > 0\n ? analysis.patterns.map((p) => `- [${p.severity}] ${p.description}`).join('\\n')\n : 'No unusual patterns detected.';\n\n const text = [\n `Wallet analysis for ${analysis.address} on ${analysis.chain}:`,\n ` Balance: ${analysis.balance.toString()} wei`,\n ` Transactions: ${analysis.transactionCount}`,\n ` Risk level: ${analysis.riskLevel}`,\n ` Patterns:`,\n patternSummary,\n ].join('\\n');\n\n return { blocks: [], text };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Track failed: ${message}` };\n }\n}\n\nasync function handleTrends(): Promise<CommandResult> {\n // Fetch trending tokens + top gainers/losers in parallel (no hardcoded symbols)\n const [trendingResult, gainersLosersResult] = await Promise.allSettled([\n fetchTrendingTokens(),\n fetchTopGainersLosers(5),\n ]);\n\n const blocks: RichBlock[] = [];\n const lines: string[] = [];\n\n // Merge and deduplicate trending tokens\n const trending = trendingResult.status === 'fulfilled' ? trendingResult.value : [];\n const seen = new Set<string>();\n\n if (trending.length > 0) {\n lines.push('Trending tokens:');\n for (const t of trending.slice(0, 10)) {\n const key = t.symbol.toUpperCase();\n if (seen.has(key)) continue;\n seen.add(key);\n const change =\n t.priceChange24h > 0\n ? `+${t.priceChange24h.toFixed(1)}%`\n : `${t.priceChange24h.toFixed(1)}%`;\n blocks.push({\n type: 'market',\n data: {\n symbol: t.symbol,\n price: parseFloat(t.priceUsd) || 0,\n change24h: t.priceChange24h,\n volume: t.volume24h,\n },\n });\n lines.push(\n ` ${t.symbol} (${t.chain}): $${t.priceUsd} | 24h: ${change} | Vol: $${t.volume24h.toLocaleString()} [${t.source}]`,\n );\n }\n }\n\n // Top gainers and losers from Binance\n if (gainersLosersResult.status === 'fulfilled') {\n const { gainers, losers } = gainersLosersResult.value;\n if (gainers.length > 0) {\n lines.push('');\n lines.push('Top gainers (24h):');\n for (const g of gainers) {\n if (seen.has(g.symbol)) continue;\n lines.push(\n ` ${g.symbol}: $${g.price.toLocaleString()} | +${g.change24h.toFixed(1)}% | Vol: $${g.quoteVolume.toLocaleString()}`,\n );\n }\n }\n if (losers.length > 0) {\n lines.push('');\n lines.push('Top losers (24h):');\n for (const l of losers) {\n if (seen.has(l.symbol)) continue;\n lines.push(\n ` ${l.symbol}: $${l.price.toLocaleString()} | ${l.change24h.toFixed(1)}% | Vol: $${l.quoteVolume.toLocaleString()}`,\n );\n }\n }\n }\n\n if (lines.length === 0) {\n return { blocks: [], text: 'Could not fetch market trends. Try again later.' };\n }\n\n return { blocks, text: lines.join('\\n') };\n}\n\nasync function handleAudit(args: string[]): Promise<CommandResult> {\n const chain = extractChainFlag(args);\n const positional = positionalArgs(args);\n const contract = positional[0];\n\n if (!contract) {\n return { blocks: [], text: 'Usage: /audit <contract> [--chain <chain>]' };\n }\n\n try {\n const adapter = getAdapter(chain);\n const result = await auditContract(contract, adapter);\n\n const blocks: RichBlock[] = [\n {\n type: 'audit',\n data: {\n findings: result.findings.map((f) => ({\n severity: f.severity,\n description: `${f.title}: ${f.description}`,\n })),\n },\n },\n ];\n\n return {\n blocks,\n text: `Audit for ${contract} on ${chain}: overall risk is ${result.overallRisk}. ${result.findings.length} finding(s).`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Audit failed: ${message}` };\n }\n}\n\nfunction handleProvider(args: string[]): CommandResult {\n const subcommand = args[0];\n\n // /provider — show current\n if (!subcommand) {\n try {\n const provider = getProvider();\n return {\n blocks: [],\n text: `Current AI provider: ${provider.name}`,\n };\n } catch {\n return { blocks: [], text: 'No AI provider is currently active.' };\n }\n }\n\n // /provider list — show all with availability\n if (subcommand === 'list') {\n try {\n const cfg = getConfig();\n const providers = getAvailableProviders(cfg);\n let current = '';\n try {\n current = getProvider().name;\n } catch {\n // no active provider\n }\n\n const lines = ['Available AI providers:', ''];\n for (const p of providers) {\n const active = p.name === current ? ' (active)' : '';\n const model = DEFAULT_MODELS[p.name] ?? 'unknown';\n const status = p.available ? 'ready' : (p.reason ?? 'unavailable');\n lines.push(` ${p.name}${active} — ${model} [${status}]`);\n }\n lines.push('', 'Switch with: /provider <name>');\n return { blocks: [], text: lines.join('\\n') };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Provider list error: ${message}` };\n }\n }\n\n // /provider <name> — switch provider\n const validProviders = ['anthropic', 'openai', 'gemini', 'ollama'];\n if (!validProviders.includes(subcommand)) {\n return {\n blocks: [],\n text: `Unknown provider \"${subcommand}\". Available: ${validProviders.join(', ')}`,\n };\n }\n\n try {\n switchProvider(subcommand);\n const provider = getProvider();\n return {\n blocks: [],\n text: `Switched to ${provider.name}. Ready to chat.`,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Failed to switch provider: ${message}` };\n }\n}\n\nfunction handleAgent(args: string[]): CommandResult {\n const sub = args[0];\n\n if (!sub) {\n return {\n blocks: [],\n text: [\n 'Usage: /agent <subcommand>',\n '',\n ' create <name> --strategy <name> --pairs <SYM1,SYM2> [--interval <sec>]',\n ' list List all agents',\n ' start <name> Start an agent',\n ' stop <name> Stop a running agent',\n ' status <name> View agent status and recent decisions',\n ' delete <name> Delete an agent',\n ' strategies List available strategies',\n ].join('\\n'),\n };\n }\n\n try {\n switch (sub) {\n case 'create': {\n const nameArg = args[1];\n if (!nameArg)\n return {\n blocks: [],\n text: 'Usage: /agent create <name> --strategy <name> --pairs <SYM1,SYM2>',\n };\n\n const stratIdx = args.indexOf('--strategy');\n const pairsIdx = args.indexOf('--pairs');\n const intervalIdx = args.indexOf('--interval');\n\n const strategy =\n stratIdx !== -1 && stratIdx + 1 < args.length ? args[stratIdx + 1]! : 'momentum';\n const pairsRaw =\n pairsIdx !== -1 && pairsIdx + 1 < args.length ? args[pairsIdx + 1]! : 'BTC,ETH';\n const interval =\n intervalIdx !== -1 && intervalIdx + 1 < args.length\n ? parseInt(args[intervalIdx + 1]!, 10)\n : 60;\n\n const pairs = pairsRaw.split(',').map((p) => p.trim().toUpperCase());\n const agent = createAgent(nameArg, strategy, pairs, interval);\n return {\n blocks: [],\n text: `Agent \"${agent.name}\" created (${agent.strategy}, pairs: ${agent.pairs.join(', ')}, interval: ${agent.interval}s)`,\n };\n }\n\n case 'list': {\n const agents = listAgents();\n if (agents.length === 0)\n return { blocks: [], text: 'No agents created. Use /agent create to create one.' };\n\n const lines = ['Agents:', ''];\n for (const a of agents) {\n const status = getAgentStatus(a.id);\n const statusTag = status?.status ?? 'idle';\n lines.push(\n ` ${a.name} [${statusTag}] — ${a.strategy} | ${a.pairs.join(', ')} | ${a.interval}s`,\n );\n }\n return { blocks: [], text: lines.join('\\n') };\n }\n\n case 'start': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent start <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = startAgent(agent.id);\n return {\n blocks: [],\n text: `Agent \"${name}\" started (${state.config.strategy}). Monitoring ${state.config.pairs.join(', ')}.`,\n };\n }\n\n case 'stop': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent stop <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = stopAgent(agent.id);\n return { blocks: [], text: `Agent \"${name}\" stopped after ${state.cycleCount} cycles.` };\n }\n\n case 'status': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent status <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n const state = getAgentStatus(agent.id);\n if (!state) return { blocks: [], text: `Agent \"${name}\" not found.` };\n\n const lines = [\n `Agent: ${state.config.name}`,\n ` Status: ${state.status}`,\n ` Strategy: ${state.config.strategy}`,\n ` Pairs: ${state.config.pairs.join(', ')}`,\n ` Interval: ${state.config.interval}s`,\n ` Cycles: ${state.cycleCount}`,\n ];\n\n if (state.error) lines.push(` Error: ${state.error}`);\n\n const decisions = getRecentDecisions(agent.id, 5);\n if (decisions.length > 0) {\n lines.push('', ' Recent decisions:');\n for (const d of decisions) {\n const time = new Date(d.timestamp).toLocaleTimeString();\n lines.push(\n ` [${time}] ${d.symbol}: ${d.decision.action.toUpperCase()} (${d.decision.confidence}%)`,\n );\n for (const r of d.decision.reasoning.slice(0, 2)) {\n lines.push(` - ${r}`);\n }\n }\n }\n\n return { blocks: [], text: lines.join('\\n') };\n }\n\n case 'delete': {\n const name = args[1];\n if (!name) return { blocks: [], text: 'Usage: /agent delete <name>' };\n const agent = getAgentByName(name);\n if (!agent) return { blocks: [], text: `Agent \"${name}\" not found.` };\n deleteAgent(agent.id);\n return { blocks: [], text: `Agent \"${name}\" deleted.` };\n }\n\n case 'strategies': {\n const strats = listStrategies();\n return { blocks: [], text: `Available strategies: ${strats.join(', ')}` };\n }\n\n default:\n return { blocks: [], text: `Unknown agent subcommand: ${sub}. Type /agent for help.` };\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Agent error: ${message}` };\n }\n}\n\nfunction handleHelp(): CommandResult {\n const text = [\n 'Available commands:',\n '',\n ' /scan <address> [--chain <chain>] Scan a token/project for risk indicators',\n ' /track <wallet> [--chain <chain>] Analyze a wallet address',\n ' /trends Live trending tokens + top gainers/losers',\n ' /audit <contract> [--chain <chain>] Audit a smart contract (bytecode scanning)',\n ' /agent <sub> Manage autonomous trading agents',\n ' /backtest -s <strat> --pair <P> --from <D> --to <D> Run a historical backtest',\n ' /provider [list|<name>] Show/switch AI provider',\n ' /config [set <key> <value>] Show or update configuration',\n ' /clear Clear message history',\n ' /exit Exit Vizzor',\n ' /help Show this help message',\n '',\n 'AI chat supports: token search (DexScreener), trending, news, raises,',\n 'market data, wallet analysis, rug detection, and Pump.fun launches.',\n 'Just ask a question — Vizzor fetches live data automatically.',\n ].join('\\n');\n\n return { blocks: [], text };\n}\n\nasync function handleBacktest(args: string[]): Promise<CommandResult> {\n const stratIdx = args.indexOf('-s') !== -1 ? args.indexOf('-s') : args.indexOf('--strategy');\n const pairIdx = args.indexOf('--pair');\n const fromIdx = args.indexOf('--from');\n const toIdx = args.indexOf('--to');\n const tfIdx = args.indexOf('--timeframe');\n\n const strategy = stratIdx !== -1 && stratIdx + 1 < args.length ? args[stratIdx + 1]! : '';\n const pair = pairIdx !== -1 && pairIdx + 1 < args.length ? args[pairIdx + 1]! : '';\n const from = fromIdx !== -1 && fromIdx + 1 < args.length ? args[fromIdx + 1]! : '';\n const to = toIdx !== -1 && toIdx + 1 < args.length ? args[toIdx + 1]! : '';\n const timeframe = tfIdx !== -1 && tfIdx + 1 < args.length ? args[tfIdx + 1]! : '4h';\n\n if (!strategy || !pair || !from || !to) {\n return {\n blocks: [],\n text: 'Usage: /backtest -s <strategy> --pair <PAIR> --from <YYYY-MM-DD> --to <YYYY-MM-DD> [--timeframe <tf>]',\n };\n }\n\n try {\n const { BacktestEngine } = await import('../core/backtest/engine.js');\n const engine = new BacktestEngine({\n strategy,\n pair,\n from,\n to,\n initialCapital: 10000,\n timeframe,\n slippageBps: 10,\n commissionPct: 0.1,\n });\n\n const result = await engine.run();\n const lines = [\n `Backtest: ${result.config.strategy} on ${result.config.pair} (${result.config.from} → ${result.config.to})`,\n `Initial Capital: $${result.config.initialCapital.toLocaleString()}`,\n '',\n `Total Return: $${result.metrics.totalReturn.toFixed(2)} (${result.metrics.totalReturnPct.toFixed(2)}%)`,\n `Win Rate: ${(result.metrics.winRate * 100).toFixed(1)}%`,\n `Total Trades: ${result.metrics.totalTrades}`,\n `Profit Factor: ${result.metrics.profitFactor === Infinity ? '∞' : result.metrics.profitFactor.toFixed(2)}`,\n `Sharpe Ratio: ${result.metrics.sharpeRatio.toFixed(2)}`,\n `Max Drawdown: ${result.metrics.maxDrawdown.toFixed(2)}%`,\n ];\n\n if (result.trades.length > 0) {\n lines.push('', 'Last 5 Trades:');\n for (const t of result.trades.slice(-5)) {\n const dir = t.pnl >= 0 ? '+' : '';\n lines.push(\n ` ${new Date(t.entryTime).toISOString().split('T')[0]} → ${new Date(t.exitTime).toISOString().split('T')[0]} | ${t.side} | $${t.entryPrice.toFixed(2)} → $${t.exitPrice.toFixed(2)} | ${dir}$${t.pnl.toFixed(2)} (${dir}${t.pnlPct.toFixed(2)}%)`,\n );\n }\n }\n\n return { blocks: [], text: lines.join('\\n') };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Backtest failed: ${message}` };\n }\n}\n\nasync function handleConfig(args: string[]): Promise<CommandResult> {\n // /config set <key> <value>\n if (args[0] === 'set') {\n const key = args[1];\n const value = args.slice(2).join(' ');\n if (!key || !value) {\n return {\n blocks: [],\n text:\n 'Usage: /config set <key> <value>\\n\\nValid keys: ' +\n Object.keys(getSettableKeys()).join(', '),\n };\n }\n // Validate sensitive keys for security\n const isSensitive = key.toLowerCase().includes('key') || key.toLowerCase().includes('token');\n if (isSensitive) {\n const { validateKey } = await import('../config/keys.js');\n const error = validateKey(key, value);\n if (error && !error.startsWith('Warning:')) {\n return { blocks: [], text: `Rejected: ${error}` };\n }\n }\n try {\n saveConfigValue(key, value);\n return { blocks: [], text: `Saved ${key}. Config reloaded.` };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Config set failed: ${message}` };\n }\n }\n\n try {\n const cfg = getConfig();\n const settable = getSettableKeys();\n\n let activeModel: string;\n try {\n getProvider();\n activeModel = cfg.ai.model ?? DEFAULT_MODELS[cfg.ai.provider] ?? '(default)';\n } catch {\n activeModel = cfg.ai.model ?? '(default)';\n }\n\n const apiKeys: { label: string; key: string; value: string | undefined; env: string }[] = [\n {\n label: 'Anthropic API Key',\n key: 'anthropicApiKey',\n value: cfg.anthropicApiKey,\n env: settable['anthropicApiKey']?.env ?? '',\n },\n {\n label: 'OpenAI API Key',\n key: 'openaiApiKey',\n value: cfg.openaiApiKey,\n env: settable['openaiApiKey']?.env ?? '',\n },\n {\n label: 'Google API Key',\n key: 'googleApiKey',\n value: cfg.googleApiKey,\n env: settable['googleApiKey']?.env ?? '',\n },\n {\n label: 'Etherscan API Key',\n key: 'etherscanApiKey',\n value: cfg.etherscanApiKey,\n env: settable['etherscanApiKey']?.env ?? '',\n },\n {\n label: 'Alchemy API Key',\n key: 'alchemyApiKey',\n value: cfg.alchemyApiKey,\n env: settable['alchemyApiKey']?.env ?? '',\n },\n {\n label: 'CoinGecko API Key',\n key: 'coingeckoApiKey',\n value: cfg.coingeckoApiKey,\n env: settable['coingeckoApiKey']?.env ?? '',\n },\n {\n label: 'CryptoPanic Key',\n key: 'cryptopanicApiKey',\n value: cfg.cryptopanicApiKey,\n env: settable['cryptopanicApiKey']?.env ?? '',\n },\n ];\n\n let configured = 0;\n const keyLines: string[] = [];\n for (const k of apiKeys) {\n const masked = maskKey(k.value);\n if (k.value) configured++;\n const hint = k.value ? '' : ` -> /config set ${k.key} <value> or ${k.env}=xxx`;\n keyLines.push(` ${k.label.padEnd(20)} ${masked}${hint}`);\n }\n\n const text = [\n 'Configuration:',\n '',\n ' [AI Provider]',\n ` Provider: ${cfg.ai.provider}`,\n ` Model: ${activeModel}`,\n ` Max Tokens: ${cfg.ai.maxTokens}`,\n ` Ollama Host: ${cfg.ai.ollamaHost}`,\n '',\n ` [API Keys] (${configured}/${apiKeys.length} configured)`,\n ...keyLines,\n '',\n ' [Chain]',\n ` Default Chain: ${cfg.defaultChain}`,\n '',\n ' [Output]',\n ` Format: ${cfg.output.format}`,\n ` Color: ${cfg.output.color}`,\n ` Verbose: ${cfg.output.verbose}`,\n '',\n 'Set a value: /config set <key> <value>',\n ].join('\\n');\n\n return { blocks: [], text };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { blocks: [], text: `Config error: ${message}` };\n }\n}\n","// ---------------------------------------------------------------------------\n// React hook for slash command execution in the Vizzor TUI\n// ---------------------------------------------------------------------------\n\nimport { useState, useCallback } from 'react';\nimport { parseCommand, executeCommand } from '../commands.js';\nimport type { CommandResult } from '../commands.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface UseCommandResult {\n /** Whether a slash command is currently executing. */\n isExecuting: boolean;\n /**\n * Parse and execute a slash command string.\n *\n * Returns `null` for `/clear` and `/exit` so the app component can\n * handle those specially. Returns the {@link CommandResult} for all\n * other commands.\n */\n executeSlashCommand: (input: string) => Promise<CommandResult | null>;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * React hook that wraps the slash command parser and dispatcher.\n *\n * `/clear` and `/exit` are signalled by returning `null` — the caller is\n * responsible for clearing messages or exiting the process.\n */\nexport function useCommand(): UseCommandResult {\n const [isExecuting, setIsExecuting] = useState(false);\n\n const executeSlashCommand = useCallback(async (input: string): Promise<CommandResult | null> => {\n const { name, args } = parseCommand(input);\n\n // These are handled by the app component, not the command dispatcher.\n if (name === 'clear' || name === 'exit') {\n return null;\n }\n\n setIsExecuting(true);\n try {\n const result = await executeCommand(name, args);\n return result;\n } finally {\n setIsExecuting(false);\n }\n }, []);\n\n return { isExecuting, executeSlashCommand };\n}\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { fetchTickerPrice } from '../../data/sources/binance.js';\nimport { TICKER_DEFAULTS } from '../../config/constants.js';\n\nconst REFRESH_INTERVAL = 30_000;\n\nexport interface TickerEntry {\n symbol: string;\n geckoId: string;\n price: number;\n change24h: number;\n loading: boolean;\n error: boolean;\n}\n\nexport interface UsePriceTickerResult {\n entries: TickerEntry[];\n isRefreshing: boolean;\n selectedIndex: number | null;\n addSymbol: (geckoId: string, symbol: string) => void;\n removeSymbol: (geckoId: string) => void;\n selectNext: () => void;\n selectPrev: () => void;\n clearSelection: () => void;\n getSelected: () => TickerEntry | null;\n}\n\nexport function usePriceTicker(): UsePriceTickerResult {\n const [entries, setEntries] = useState<TickerEntry[]>(\n TICKER_DEFAULTS.map((t) => ({\n symbol: t.symbol,\n geckoId: t.geckoId,\n price: 0,\n change24h: 0,\n loading: true,\n error: false,\n })),\n );\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const lastGoodRef = useRef<Map<string, { price: number; change24h: number }>>(new Map());\n\n const fetchAll = useCallback(async (current: TickerEntry[]): Promise<void> => {\n setIsRefreshing(true);\n const symbols = current.map((e) => e.symbol);\n const results = await Promise.allSettled(symbols.map((s) => fetchTickerPrice(s)));\n\n setEntries((prev) =>\n prev.map((entry, i) => {\n const result = results[i];\n if (result && result.status === 'fulfilled' && result.value) {\n const data = result.value;\n lastGoodRef.current.set(entry.geckoId, {\n price: data.price,\n change24h: data.change24h,\n });\n return {\n ...entry,\n price: data.price,\n change24h: data.change24h,\n loading: false,\n error: false,\n };\n }\n // Preserve last known good values instead of showing error\n const cached = lastGoodRef.current.get(entry.geckoId);\n if (cached) {\n return {\n ...entry,\n price: cached.price,\n change24h: cached.change24h,\n loading: false,\n error: false,\n };\n }\n // Only show error if we never had data\n return { ...entry, loading: false, error: true };\n }),\n );\n setIsRefreshing(false);\n }, []);\n\n useEffect(() => {\n void fetchAll(entries);\n intervalRef.current = setInterval(() => {\n setEntries((current) => {\n void fetchAll(current);\n return current;\n });\n }, REFRESH_INTERVAL);\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, [fetchAll]);\n\n const addSymbol = useCallback(\n (geckoId: string, symbol: string): void => {\n setEntries((prev) => {\n if (prev.some((e) => e.geckoId === geckoId)) return prev;\n const newEntry: TickerEntry = {\n symbol: symbol.toUpperCase(),\n geckoId,\n price: 0,\n change24h: 0,\n loading: true,\n error: false,\n };\n const updated = [...prev, newEntry];\n void fetchAll(updated);\n return updated;\n });\n },\n [fetchAll],\n );\n\n const removeSymbol = useCallback((geckoId: string): void => {\n setEntries((prev) => prev.filter((e) => e.geckoId !== geckoId));\n lastGoodRef.current.delete(geckoId);\n }, []);\n\n const selectNext = useCallback((): void => {\n setEntries((current) => {\n setSelectedIndex((prev) => {\n if (prev === null) return 0;\n return prev < current.length - 1 ? prev + 1 : 0;\n });\n return current;\n });\n }, []);\n\n const selectPrev = useCallback((): void => {\n setEntries((current) => {\n setSelectedIndex((prev) => {\n if (prev === null) return current.length - 1;\n return prev > 0 ? prev - 1 : current.length - 1;\n });\n return current;\n });\n }, []);\n\n const clearSelection = useCallback((): void => {\n setSelectedIndex(null);\n }, []);\n\n const getSelected = useCallback((): TickerEntry | null => {\n if (selectedIndex === null) return null;\n return entries[selectedIndex] ?? null;\n }, [selectedIndex, entries]);\n\n return {\n entries,\n isRefreshing,\n selectedIndex,\n addSymbol,\n removeSymbol,\n selectNext,\n selectPrev,\n clearSelection,\n getSelected,\n };\n}\n","// ---------------------------------------------------------------------------\n// Vizzor TUI — Root Ink application component\n// ---------------------------------------------------------------------------\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport { render, Box, Text, Static, useInput } from 'ink';\nimport { StatusBar } from './components/status-bar.js';\nimport { PriceTicker } from './components/price-ticker.js';\nimport { WelcomeBanner } from './components/welcome-banner.js';\nimport { MessageBubble } from './components/message-bubble.js';\nimport { CommandHints } from './components/command-hints.js';\nimport { ToolStatusList } from './components/tool-status.js';\nimport { InputPrompt } from './components/input-prompt.js';\nimport { StreamingText } from './components/streaming-text.js';\nimport type { Message } from './components/message-list.js';\nimport { useAIStream } from './hooks/use-ai-stream.js';\nimport { useCommand } from './hooks/use-command.js';\nimport { usePriceTicker } from './hooks/use-price-ticker.js';\nimport { isSlashCommand, parseCommand } from './commands.js';\nimport { loadConfig } from '../config/loader.js';\nimport { DEFAULT_CHAIN, CHAIN_REGISTRY, KNOWN_SYMBOLS } from '../config/constants.js';\nimport { setConfig, setToolHandler, getProvider } from '../ai/client.js';\nimport { handleTool } from '../ai/tool-handler.js';\nimport { VIZZOR_TOOLS } from '../ai/tools.js';\nimport { isValidSymbol } from '../data/sources/binance.js';\n\n// ---------------------------------------------------------------------------\n// App component\n// ---------------------------------------------------------------------------\n\nfunction App(): React.JSX.Element {\n const [messages, setMessages] = useState<Message[]>([]);\n const [isProcessing, setIsProcessing] = useState(false);\n const [initError, setInitError] = useState<string | null>(null);\n const [showBanner, setShowBanner] = useState(true);\n const [currentInput, setCurrentInput] = useState('');\n const [clearEpoch, setClearEpoch] = useState(0);\n const [providerName, setProviderName] = useState('ollama');\n const [chainName, setChainName] = useState(DEFAULT_CHAIN);\n const [tickerFocused, setTickerFocused] = useState(false);\n\n const { streamingText, isStreaming, activeTools, completedTools, sendMessage } = useAIStream();\n const { isExecuting, executeSlashCommand } = useCommand();\n const ticker = usePriceTicker();\n\n // -----------------------------------------------------------------------\n // Ticker keyboard navigation (Tab to focus, arrows to navigate, Enter to analyze)\n // -----------------------------------------------------------------------\n useInput(\n (input, key) => {\n if (key.tab) {\n if (tickerFocused) {\n setTickerFocused(false);\n ticker.clearSelection();\n } else {\n setTickerFocused(true);\n }\n return;\n }\n if (!tickerFocused) return;\n if (key.rightArrow) {\n ticker.selectNext();\n } else if (key.leftArrow) {\n ticker.selectPrev();\n } else if (key.return) {\n const selected = ticker.getSelected();\n if (selected && !isProcessing && !isStreaming) {\n setTickerFocused(false);\n ticker.clearSelection();\n const msg = `Analyze ${selected.symbol} with full prediction`;\n setMessages((prev) => [...prev, { role: 'user', content: msg, timestamp: new Date() }]);\n setIsProcessing(true);\n sendMessage(msg);\n }\n } else if (key.escape || input === 'q') {\n setTickerFocused(false);\n ticker.clearSelection();\n }\n },\n { isActive: true },\n );\n\n // -----------------------------------------------------------------------\n // Initialisation: load config, set up AI client and tool handler\n // -----------------------------------------------------------------------\n useEffect(() => {\n try {\n const cfg = loadConfig();\n setConfig(cfg);\n setToolHandler(handleTool);\n setProviderName(cfg.ai?.provider ?? 'ollama');\n setChainName(cfg.defaultChain ?? DEFAULT_CHAIN);\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n setInitError(`Initialisation failed: ${message}`);\n }\n // Ensure VIZZOR_TOOLS is referenced so the import is not tree-shaken.\n void VIZZOR_TOOLS;\n }, []);\n\n // -----------------------------------------------------------------------\n // When the AI stream finishes, capture the final message\n // -----------------------------------------------------------------------\n useEffect(() => {\n if (!isStreaming && streamingText.length > 0 && isProcessing) {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: streamingText, timestamp: new Date() },\n ]);\n setIsProcessing(false);\n }\n }, [isStreaming, streamingText, isProcessing]);\n\n // -----------------------------------------------------------------------\n // Input handler\n // -----------------------------------------------------------------------\n const handleSubmit = useCallback(\n (input: string): void => {\n // Hide banner after first interaction\n if (showBanner) setShowBanner(false);\n\n if (isSlashCommand(input)) {\n const { name, args } = parseCommand(input);\n\n // Special commands handled directly by the app\n if (name === 'clear') {\n setMessages([]);\n setClearEpoch((prev) => prev + 1);\n return;\n }\n if (name === 'exit') {\n process.exit(0);\n }\n\n // /add <symbol> — add a crypto to the price ticker\n if (name === 'add') {\n const sym = args[0]?.toUpperCase();\n if (!sym) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: 'Usage: /add <symbol> (e.g. /add DOGE)',\n timestamp: new Date(),\n },\n ]);\n return;\n }\n const geckoId = KNOWN_SYMBOLS[sym.toLowerCase()] ?? sym.toLowerCase();\n setIsProcessing(true);\n isValidSymbol(sym)\n .then((valid) => {\n if (valid) {\n ticker.addSymbol(geckoId, sym);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Added ${sym} to price ticker.`,\n timestamp: new Date(),\n },\n ]);\n } else {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Symbol \"${sym}\" not found on Binance.`,\n timestamp: new Date(),\n },\n ]);\n }\n })\n .catch(() => {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Failed to validate symbol \"${sym}\".`,\n timestamp: new Date(),\n },\n ]);\n })\n .finally(() => setIsProcessing(false));\n return;\n }\n\n // /remove <symbol> — remove a crypto from the price ticker\n if (name === 'remove') {\n const sym = args[0]?.toUpperCase();\n if (!sym) {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: 'Usage: /remove <symbol>', timestamp: new Date() },\n ]);\n return;\n }\n const geckoId = KNOWN_SYMBOLS[sym.toLowerCase()] ?? sym.toLowerCase();\n ticker.removeSymbol(geckoId);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Removed ${sym} from price ticker.`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n\n // /chain [chainId] — switch or list chains\n if (name === 'chain') {\n const target = args[0]?.toLowerCase();\n if (!target) {\n const lines = CHAIN_REGISTRY.map(\n (c) => ` ${c.icon} ${c.name} (${c.id})${c.id === chainName ? ' *' : ''}`,\n );\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Available chains:\\n${lines.join('\\n')}\\n\\nUsage: /chain <id>`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n const meta = CHAIN_REGISTRY.find((c) => c.id === target);\n if (!meta) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `Unknown chain \"${target}\". Available: ${CHAIN_REGISTRY.map((c) => c.id).join(', ')}`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n setChainName(meta.id);\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: `${meta.icon} Switched to ${meta.name}.`,\n timestamp: new Date(),\n },\n ]);\n return;\n }\n\n // All other slash commands — fire-and-forget the async work\n setIsProcessing(true);\n executeSlashCommand(input)\n .then((result) => {\n if (result) {\n setMessages((prev) => [\n ...prev,\n {\n role: 'assistant',\n content: result.text,\n blocks: result.blocks,\n timestamp: new Date(),\n },\n ]);\n }\n // Update status bar when provider changes\n if (name === 'provider') {\n try {\n setProviderName(getProvider().name);\n } catch {\n /* no active provider */\n }\n }\n })\n .catch(() => {\n setMessages((prev) => [\n ...prev,\n { role: 'assistant', content: 'Command execution failed.', timestamp: new Date() },\n ]);\n })\n .finally(() => {\n setIsProcessing(false);\n });\n return;\n }\n\n // Regular message — send to AI\n setMessages((prev) => [...prev, { role: 'user', content: input, timestamp: new Date() }]);\n setIsProcessing(true);\n sendMessage(input);\n },\n [executeSlashCommand, sendMessage, showBanner],\n );\n\n // -----------------------------------------------------------------------\n // Determine whether the input should be disabled\n // -----------------------------------------------------------------------\n const inputDisabled = isProcessing || isStreaming || isExecuting || tickerFocused;\n\n // -----------------------------------------------------------------------\n // Render\n // -----------------------------------------------------------------------\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n {/* Status bar */}\n <StatusBar provider={providerName} chain={chainName} connected />\n\n {/* Live price ticker — Tab to focus, arrows to navigate, Enter to analyze */}\n <PriceTicker ticker={ticker} focused={tickerFocused} onAddPress={undefined} />\n\n {/* Compact banner — hides after first message */}\n {showBanner && <WelcomeBanner />}\n\n {initError && (\n <Box marginTop={1}>\n <Box borderStyle=\"single\" borderColor=\"red\" paddingX={1}>\n <Text color=\"red\">{initError}</Text>\n </Box>\n </Box>\n )}\n\n {/* Message history — uses Static so items render once */}\n <Static key={clearEpoch} items={messages}>\n {(msg, idx) => (\n <Box key={`${clearEpoch}-${idx}`} marginTop={idx === 0 ? 1 : 0}>\n <MessageBubble message={msg} />\n </Box>\n )}\n </Static>\n\n {/* Show streaming AI text while a response is being generated */}\n {isStreaming && streamingText.length > 0 && (\n <Box marginTop={1}>\n <StreamingText text={streamingText} isStreaming={isStreaming} />\n </Box>\n )}\n\n {/* Show active tool executions */}\n <ToolStatusList active={activeTools} completed={completedTools} />\n\n {/* Command hints when typing / */}\n {currentInput.startsWith('/') && <CommandHints filter={currentInput} />}\n\n {/* Input bar */}\n <Box marginTop={1}>\n <InputPrompt\n onSubmit={handleSubmit}\n disabled={inputDisabled}\n onInputChange={setCurrentInput}\n />\n </Box>\n </Box>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Mount the Vizzor TUI using Ink's `render()` function.\n *\n * Call this from the CLI entry point to start the interactive terminal UI.\n */\nexport function startTUI(): void {\n render(<App />);\n}\n","import { Command } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, resolve } from 'node:path';\nimport { loadConfig } from './config/loader.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8')) as {\n version: string;\n};\n\nconst program = new Command()\n .name('vizzor')\n .description('Crypto chronovisor — AI-powered on-chain intelligence')\n .version(pkg.version);\n\nprogram.hook('preAction', async () => {\n await loadConfig();\n});\n\n// Lazy-load commands to speed up CLI startup\nprogram\n .command('scan <project>')\n .description('Analyze a crypto project')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--deep', 'Deep analysis including contract audit', false)\n .option('--json', 'Output as JSON', false)\n .action(async (project: string, options: { chain: string; deep: boolean; json: boolean }) => {\n const { handleScan } = await import('./cli/commands/scan.js');\n await handleScan(project, options);\n });\n\nprogram\n .command('trends')\n .description('Analyze market trends')\n .option('--sentiment', 'Include sentiment analysis', false)\n .option('--chain <chain>', 'Filter by chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (options: { sentiment: boolean; chain: string; json: boolean }) => {\n const { handleTrends } = await import('./cli/commands/trends.js');\n await handleTrends(options);\n });\n\nprogram\n .command('track <wallet>')\n .description('Analyze a wallet address')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (wallet: string, options: { chain: string; json: boolean }) => {\n const { handleTrack } = await import('./cli/commands/track.js');\n await handleTrack(wallet, options);\n });\n\nconst icoCmd = program.command('ico').description('ICO/IDO tracker');\n\nicoCmd\n .command('list')\n .description('List upcoming ICOs/IDOs')\n .option('--category <category>', 'Filter by category')\n .option('--chain <chain>', 'Filter by chain')\n .option('--json', 'Output as JSON', false)\n .action(async (options: { category?: string; chain?: string; json: boolean }) => {\n const { handleIcoList } = await import('./cli/commands/ico.js');\n await handleIcoList(options);\n });\n\nprogram\n .command('audit <contract>')\n .description('Basic smart contract audit')\n .option('--chain <chain>', 'Target chain', 'ethereum')\n .option('--json', 'Output as JSON', false)\n .action(async (contract: string, options: { chain: string; json: boolean }) => {\n const { handleAudit } = await import('./cli/commands/audit.js');\n await handleAudit(contract, options);\n });\n\nconst configCmd = program.command('config').description('Configuration management');\n\nconfigCmd\n .command('init')\n .description('Initialize configuration')\n .action(async () => {\n const { handleConfigInit } = await import('./cli/commands/config.js');\n await handleConfigInit();\n });\n\nconfigCmd\n .command('set <key> <value>')\n .description('Set a configuration value')\n .action(async (key: string, value: string) => {\n const { handleConfigSet } = await import('./cli/commands/config.js');\n await handleConfigSet(key, value);\n });\n\nconfigCmd\n .command('show')\n .description('Show current configuration')\n .action(async () => {\n const { handleConfigShow } = await import('./cli/commands/config.js');\n await handleConfigShow();\n });\n\nconst botCmd = program.command('bot').description('Bot management');\n\nbotCmd\n .command('start')\n .description('Start bot(s)')\n .option('--discord', 'Start Discord bot', false)\n .option('--telegram', 'Start Telegram bot', false)\n .option('--all', 'Start all bots', false)\n .action(async (options: { discord: boolean; telegram: boolean; all: boolean }) => {\n const { handleBotStart } = await import('./cli/commands/bot.js');\n await handleBotStart(options);\n });\n\nbotCmd\n .command('validate')\n .description('Check bot token configuration')\n .action(async () => {\n const { handleBotValidate } = await import('./cli/commands/bot.js');\n handleBotValidate();\n });\n\nconst collectCmd = program.command('collect').description('Data collection pipeline');\n\ncollectCmd\n .command('start')\n .description('Start background OHLCV data collection (requires PostgreSQL)')\n .option('--symbols <symbols>', 'Comma-separated symbols to collect (default: 23 major pairs)')\n .option('--interval <seconds>', 'Collection interval in seconds (default: 300)', parseInt)\n .action(async (options: { symbols?: string; interval?: number }) => {\n const { handleCollectStart } = await import('./cli/commands/collect.js');\n await handleCollectStart(options);\n });\n\ncollectCmd\n .command('status')\n .description('Show data collection status')\n .action(async () => {\n const { handleCollectStatus } = await import('./cli/commands/collect.js');\n handleCollectStatus();\n });\n\nprogram\n .command('serve')\n .description('Start the REST API server')\n .option('--port <port>', 'Server port', (v: string) => parseInt(v, 10), 3000)\n .option('--host <host>', 'Server host', '0.0.0.0')\n .option('--auth', 'Enable API key authentication', false)\n .action(async (options: { port: number; host: string; auth: boolean }) => {\n const { handleServe } = await import('./cli/commands/serve.js');\n await handleServe(options);\n });\n\nconst apiCmd = program.command('api').description('API management');\nconst apiKeyCmd = apiCmd.command('key').description('API key management');\n\napiKeyCmd\n .command('create [label]')\n .description('Generate a new API key')\n .action(async (label: string) => {\n const { handleApiKeyCreate } = await import('./cli/commands/api.js');\n handleApiKeyCreate(label);\n });\n\napiKeyCmd\n .command('list')\n .description('List active API keys')\n .action(async () => {\n const { handleApiKeyList } = await import('./cli/commands/api.js');\n handleApiKeyList();\n });\n\napiKeyCmd\n .command('revoke <id>')\n .description('Revoke an API key')\n .action(async (id: string) => {\n const { handleApiKeyRevoke } = await import('./cli/commands/api.js');\n handleApiKeyRevoke(id);\n });\n\napiCmd\n .command('start')\n .description('Start the REST API server')\n .option('--port <port>', 'Server port', (v: string) => parseInt(v, 10), 3000)\n .option('--host <host>', 'Server host', '0.0.0.0')\n .option('--auth', 'Enable API key authentication', false)\n .action(async (options: { port: number; host: string; auth: boolean }) => {\n const { handleServe } = await import('./cli/commands/serve.js');\n await handleServe(options);\n });\n\n// Register the backtest CLI command\nconst { registerBacktestCommand } = await import('./cli/commands/backtest.js');\nregisterBacktestCommand(program);\n\n// Register the wallet CLI command\nconst { registerWalletCommand } = await import('./cli/commands/wallet.js');\nregisterWalletCommand(program);\n\n// If no arguments provided, launch interactive TUI\nconst args = process.argv.slice(2);\nif (args.length === 0) {\n await loadConfig();\n\n // Start WebSocket manager if realtime is enabled\n const { getConfig } = await import('./config/loader.js');\n try {\n const config = getConfig();\n if (config.realtime?.enabled) {\n const { initWSManager } = await import('./data/sources/ws-manager.js');\n const wsManager = initWSManager();\n for (const symbol of config.realtime.symbols) {\n wsManager.subscribe(symbol);\n }\n wsManager.start();\n }\n } catch {\n // Config may not have realtime section — that's fine\n }\n\n const { startTUI } = await import('./tui/app.js');\n startTUI();\n} else {\n program.parse();\n}\n"],"mappings":"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","names":["db","config","client","args","log","http","mainnet","polygon","arbitrum","optimism","base","bsc","avalanche","init_adapter","log","init_adapter","log","init_adapter","log","init_adapter","log","init_adapter","init_adapter","log","mlClient","level","BASE_URL","mlClient","fetchJson","BASE_URL","currentPrice","priceChange","mlClient","fetchJson","BASE_URL","WEIGHTS","mlClient","chalk","ora","mlClient","chalk","ora","level","fetchJson","fetchJson","BASE_URL","chalk","ora","chalk","ora","level","chalk","writeFileSync","existsSync","config","toolHandler","toolHandler","client","extractText","toolHandler","provider","init_registry","fetchJson","BASE_URL","searchTokens","base","geckoId","mlClient","getCoinDetails","total","formatPrice","OLLAMA_SYSTEM_PROMPT","init_client","init_registry","mlClient","mlClient","join","config","resolve","mlClient","db","config","createPublicClient","http","mainnet","ensureAgentTables","db","config","readFileSync","resolve","config","config","PostgresStore","log","init_engine","config","mlClient","BacktestEngine","config","client","init_client","init_market","handleScan","handleTrends","handleTrack","handleAudit","args","init_commands","init_market","userLimits","WINDOW_MS","MAX_REQUESTS","startRateLimitCleanup","init_rate_limit","bot_exports","config","logger","startRateLimitCleanup","init_bot","init_client","init_commands","init_rate_limit","bot_exports","chalk","config","startDiscordBot","startTelegramBot","init_bot","log","chalk","config","mlClient","init_market","config","init_engine","init_keys","validateKey","db","init_keys","log","init_market","chalk","startApiServer","chalk","init_keys","program","log","init_backtest","init_engine","randomBytes","scryptSync","existsSync","mkdirSync","readFileSync","writeFileSync","join","homedir","log","program","log","init_wallet","log","BASE_URL","instance","log","StatusBar","provider","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","level","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","formatVolume","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","Spinner","jsx","jsxs","useState","Box","Text","jsx","jsxs","Box","Text","Spinner","jsx","jsxs","useState","provider","toolHandler","init_client","args","maskKey","handleScan","handleTrack","handleTrends","handleAudit","provider","BacktestEngine","validateKey","init_commands","init_client","init_registry","useState","useCallback","args","init_commands","useState","useEffect","useCallback","useState","useEffect","useCallback","Box","Text","jsx","jsxs","args","init_commands","init_client","readFileSync","fileURLToPath","dirname","resolve","__filename","__dirname","handleScan","handleTrends","handleTrack","handleIcoList","handleAudit","handleConfigInit","handleConfigSet","handleConfigShow","handleBotStart","handleBotValidate","handleCollectStart","handleCollectStatus","handleServe","handleApiKeyCreate","handleApiKeyList","handleApiKeyRevoke","registerBacktestCommand","registerWalletCommand","getConfig","config","initWSManager","startTUI"]}
|