From f26802b99bd0ffd9d3430deced3d7bd2d6b5f318 Mon Sep 17 00:00:00 2001 From: NECOKIZZ Date: Sat, 9 May 2026 10:47:55 -0700 Subject: [PATCH 1/2] Build Conviction DCA Agent on top of Zerion AI --- .env.example | 10 + app/agent/executor.ts | 49 + app/agent/filter.ts | 36 + app/agent/loop.ts | 85 + app/agent/policy.ts | 50 + app/agent/scorer.ts | 139 ++ app/agent/watchlist.ts | 63 + app/agent/whale.ts | 52 + app/api/coingecko.ts | 34 + app/api/dexscreener.ts | 34 + app/api/gemini.ts | 60 + app/api/zerion.ts | 96 + app/server.ts | 117 + app/types/index.ts | 73 + app/utils/cache.ts | 19 + app/utils/logger.ts | 6 + app/utils/storage.ts | 65 + client/.gitignore | 24 + client/README.md | 73 + client/eslint.config.js | 22 + client/index.html | 13 + client/package-lock.json | 2772 ++++++++++++++++++++++++ client/package.json | 30 + client/public/favicon.svg | 1 + client/public/icons.svg | 24 + client/src/App.css | 1 + client/src/App.tsx | 42 + client/src/assets/hero.png | Bin 0 -> 13057 bytes client/src/assets/react.svg | 1 + client/src/assets/vite.svg | 1 + client/src/index.css | 10 + client/src/main.tsx | 10 + client/src/pages/Dashboard.tsx | 129 ++ client/src/pages/Journal.tsx | 66 + client/src/pages/Settings.tsx | 105 + client/tsconfig.app.json | 25 + client/tsconfig.json | 7 + client/tsconfig.node.json | 24 + client/vite.config.ts | 25 + dist/agent/executor.js | 43 + dist/agent/filter.js | 32 + dist/agent/loop.js | 74 + dist/agent/policy.js | 37 + dist/agent/scorer.js | 125 ++ dist/agent/watchlist.js | 52 + dist/agent/whale.js | 42 + dist/api/coingecko.js | 25 + dist/api/dexscreener.js | 31 + dist/api/gemini.js | 56 + dist/api/zerion.js | 79 + dist/server.js | 101 + dist/types/index.js | 2 + dist/utils/cache.js | 20 + dist/utils/logger.js | 6 + dist/utils/storage.js | 63 + package-lock.json | 3670 ++++++++++++++++++-------------- package.json | 83 +- tsconfig.json | 22 +- 58 files changed, 7240 insertions(+), 1716 deletions(-) create mode 100644 .env.example create mode 100644 app/agent/executor.ts create mode 100644 app/agent/filter.ts create mode 100644 app/agent/loop.ts create mode 100644 app/agent/policy.ts create mode 100644 app/agent/scorer.ts create mode 100644 app/agent/watchlist.ts create mode 100644 app/agent/whale.ts create mode 100644 app/api/coingecko.ts create mode 100644 app/api/dexscreener.ts create mode 100644 app/api/gemini.ts create mode 100644 app/api/zerion.ts create mode 100644 app/server.ts create mode 100644 app/types/index.ts create mode 100644 app/utils/cache.ts create mode 100644 app/utils/logger.ts create mode 100644 app/utils/storage.ts create mode 100644 client/.gitignore create mode 100644 client/README.md create mode 100644 client/eslint.config.js create mode 100644 client/index.html create mode 100644 client/package-lock.json create mode 100644 client/package.json create mode 100644 client/public/favicon.svg create mode 100644 client/public/icons.svg create mode 100644 client/src/App.css create mode 100644 client/src/App.tsx create mode 100644 client/src/assets/hero.png create mode 100644 client/src/assets/react.svg create mode 100644 client/src/assets/vite.svg create mode 100644 client/src/index.css create mode 100644 client/src/main.tsx create mode 100644 client/src/pages/Dashboard.tsx create mode 100644 client/src/pages/Journal.tsx create mode 100644 client/src/pages/Settings.tsx create mode 100644 client/tsconfig.app.json create mode 100644 client/tsconfig.json create mode 100644 client/tsconfig.node.json create mode 100644 client/vite.config.ts create mode 100644 dist/agent/executor.js create mode 100644 dist/agent/filter.js create mode 100644 dist/agent/loop.js create mode 100644 dist/agent/policy.js create mode 100644 dist/agent/scorer.js create mode 100644 dist/agent/watchlist.js create mode 100644 dist/agent/whale.js create mode 100644 dist/api/coingecko.js create mode 100644 dist/api/dexscreener.js create mode 100644 dist/api/gemini.js create mode 100644 dist/api/zerion.js create mode 100644 dist/server.js create mode 100644 dist/types/index.js create mode 100644 dist/utils/cache.js create mode 100644 dist/utils/logger.js create mode 100644 dist/utils/storage.js diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..2b7860e5 --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# .env.example +ZERION_API_KEY=zk_... +ZERION_AGENT_TOKEN= +MANAGED_EXECUTION_WALLET_NAME=operator-bot +MANAGED_EXECUTION_WALLET_ADDRESS=0x... +GEMINI_API_KEY= +COINGECKO_API_KEY= +EXECUTE_TRADES=false +PORT=3000 +RUN_ON_STARTUP=false diff --git a/app/agent/executor.ts b/app/agent/executor.ts new file mode 100644 index 00000000..be88b630 --- /dev/null +++ b/app/agent/executor.ts @@ -0,0 +1,49 @@ +// app/agent/executor.ts +import { executeSwap } from '../api/zerion' +import { saveJournalEntry } from '../utils/storage' +import { logger } from '../utils/logger' +import type { User, ScoredToken, JournalEntry } from '../types' + +const DRY_RUN = process.env.EXECUTE_TRADES !== 'true' + +export async function executeTrade(user: User, token: ScoredToken): Promise { + const amount = user.policy.tradeSize + const entryId = `trade_${Date.now()}_${Math.random().toString(36).slice(2, 7)}` + + const entry: JournalEntry = { + id: entryId, + userId: user.id, + timestamp: new Date().toISOString(), + token: token.symbol, + tokenAddress: token.address, + convictionScore: token.convictionScore, + timingScore: token.timingScore, + amount, + executed: false, + dryRun: DRY_RUN, + } + + if (DRY_RUN) { + logger.info(`[Executor] πŸ”΅ DRY RUN β€” would buy $${amount} of ${token.symbol} | conviction:${token.convictionScore} timing:${token.timingScore}`) + saveJournalEntry(entry) + return + } + + try { + logger.info(`[Executor] 🟑 Executing swap: $${amount} USDC β†’ ${token.symbol}`) + const result = await executeSwap({ + fromToken: 'USDC', + toToken: token.address, + amount: amount.toString(), + chain: 'base', + }) + entry.executed = true + entry.txHash = result?.data?.hash || result?.tx_hash + logger.info(`[Executor] βœ… Success | tx: ${entry.txHash}`) + } catch (err: any) { + entry.error = err.message + logger.error(`[Executor] ❌ Trade failed for ${token.symbol}: ${err.message}`) + } + + saveJournalEntry(entry) +} diff --git a/app/agent/filter.ts b/app/agent/filter.ts new file mode 100644 index 00000000..9a3ecb47 --- /dev/null +++ b/app/agent/filter.ts @@ -0,0 +1,36 @@ +// app/agent/filter.ts +import type { Token } from '../types' +import { logger } from '../utils/logger' + +const STABLECOINS = new Set(['USDC', 'USDT', 'DAI', 'BUSD', 'FRAX', 'LUSD', 'USDD', 'TUSD']) +const MIN_MARKET_CAP = 100_000_000 // $100M +const MIN_LIQUIDITY = 500_000 // $500K +const MAX_24H_PUMP = 0.30 // >30% gain in 24h = suspicious +const MIN_VOLUME_24H = 100_000 // $100K minimum volume + +export function hardFilter(tokens: Token[]): Token[] { + return tokens.filter(token => { + if (STABLECOINS.has(token.symbol.toUpperCase())) { + logger.info(`[Filter] ❌ ${token.symbol} β€” stablecoin`) + return false + } + if (token.marketCap > 0 && token.marketCap < MIN_MARKET_CAP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” market cap too low ($${token.marketCap.toLocaleString()})`) + return false + } + if (token.liquidity > 0 && token.liquidity < MIN_LIQUIDITY) { + logger.info(`[Filter] ❌ ${token.symbol} β€” liquidity too low ($${token.liquidity.toLocaleString()})`) + return false + } + if (token.priceChange24h > MAX_24H_PUMP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” suspicious 24h pump (${(token.priceChange24h * 100).toFixed(1)}%)`) + return false + } + if (token.volume24h > 0 && token.volume24h < MIN_VOLUME_24H) { + logger.info(`[Filter] ❌ ${token.symbol} β€” volume too low`) + return false + } + logger.info(`[Filter] βœ… ${token.symbol} β€” passed`) + return true + }) +} diff --git a/app/agent/loop.ts b/app/agent/loop.ts new file mode 100644 index 00000000..4c58c820 --- /dev/null +++ b/app/agent/loop.ts @@ -0,0 +1,85 @@ +// app/agent/loop.ts +import { discoverWatchlist } from './watchlist' +import { hardFilter } from './filter' +import { scoreToken } from './scorer' +import { checkUserPolicy } from './policy' +import { executeTrade } from './executor' +import { loadUsers, loadAgentState, saveAgentState } from '../utils/storage' +import { logger } from '../utils/logger' + +// Thresholds +const CONVICTION_THRESHOLD = 60 +const TIMING_THRESHOLD = 55 + +export async function runAgentCycle(): Promise { + const state = loadAgentState() + state.status = 'running' + state.lastRunAt = new Date().toISOString() + saveAgentState(state) + + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') + logger.info('[Cycle] Starting agent cycle...') + + try { + // Step 1: Discover tokens + const rawTokens = await discoverWatchlist() + logger.info(`[Cycle] Step 1 β€” Discovered ${rawTokens.length} tokens`) + + // Step 2: Hard filter + const filtered = hardFilter(rawTokens) + logger.info(`[Cycle] Step 2 β€” ${filtered.length} tokens passed hard filter`) + + // Step 3: Score all tokens (parallel with rate limit) + const scored = [] + for (const token of filtered) { + try { + const s = await scoreToken(token) + scored.push(s) + } catch (err) { + logger.warn(`[Cycle] Failed to score ${token.symbol}: ${err}`) + } + } + + // Dual gate filter + const qualified = scored.filter( + t => t.convictionScore >= CONVICTION_THRESHOLD && t.timingScore >= TIMING_THRESHOLD + ) + logger.info(`[Cycle] Step 3 β€” ${qualified.length} tokens passed dual gate (convictionβ‰₯${CONVICTION_THRESHOLD}, timingβ‰₯${TIMING_THRESHOLD})`) + + // Update state + state.watchlistSize = rawTokens.length + state.lastWatchlist = rawTokens + state.lastScored = scored.sort((a, b) => (b.convictionScore + b.timingScore) - (a.convictionScore + a.timingScore)) + + if (qualified.length === 0) { + logger.info('[Cycle] No tokens qualified β€” no trades this cycle') + } else { + // Step 4 & 5: Per-user policy check + execution + const users = loadUsers().filter(u => u.active) + logger.info(`[Cycle] Step 4/5 β€” Checking ${users.length} active users against ${qualified.length} qualified tokens`) + + for (const user of users) { + const policy = checkUserPolicy(user) + if (!policy.ok) { + logger.info(`[Cycle] User ${user.name} blocked: ${policy.reason}`) + continue + } + // Execute top qualifying token per cycle per user + const top = qualified[0] + await executeTrade(user, top) + } + } + + state.status = 'idle' + state.cycleCount = (state.cycleCount || 0) + 1 + state.nextRunAt = new Date(Date.now() + 60 * 60 * 1000).toISOString() + } catch (err: any) { + state.status = 'error' + state.lastError = err.message + logger.error(`[Cycle] Fatal error: ${err.message}`) + } + + saveAgentState(state) + logger.info('[Cycle] Complete') + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') +} diff --git a/app/agent/policy.ts b/app/agent/policy.ts new file mode 100644 index 00000000..998e8066 --- /dev/null +++ b/app/agent/policy.ts @@ -0,0 +1,50 @@ +// app/agent/policy.ts +import type { User } from '../types' +import { loadJournalForUser } from '../utils/storage' + +export function checkUserPolicy(user: User): { ok: boolean; reason?: string } { + const policy = user.policy + const now = Date.now() + const journal = loadJournalForUser(user.id) + const today = new Date().toDateString() + + // Daily spend + const todaySpend = journal + .filter(e => new Date(e.timestamp).toDateString() === today) + .reduce((sum, e) => sum + e.amount, 0) + + if (todaySpend + policy.tradeSize > policy.dailyLimit) { + return { ok: false, reason: `Daily limit $${policy.dailyLimit} reached (spent $${todaySpend.toFixed(2)})` } + } + + // Weekly spend + const weekAgo = now - 7 * 24 * 60 * 60 * 1000 + const weekSpend = journal + .filter(e => new Date(e.timestamp).getTime() > weekAgo) + .reduce((sum, e) => sum + e.amount, 0) + + if (weekSpend + policy.tradeSize > policy.weeklyLimit) { + return { ok: false, reason: `Weekly limit $${policy.weeklyLimit} reached` } + } + + // Max trades per day + const todayTrades = journal.filter(e => new Date(e.timestamp).toDateString() === today).length + if (todayTrades >= policy.maxTradesPerDay) { + return { ok: false, reason: `Max ${policy.maxTradesPerDay} trades/day reached` } + } + + // Cooldown + const lastTrade = [...journal].sort((a, b) => + new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime() + )[0] + + if (lastTrade) { + const elapsed = now - new Date(lastTrade.timestamp).getTime() + if (elapsed < policy.cooldownMs) { + const remaining = Math.ceil((policy.cooldownMs - elapsed) / 60000) + return { ok: false, reason: `Cooldown active β€” ${remaining}m remaining` } + } + } + + return { ok: true } +} diff --git a/app/agent/scorer.ts b/app/agent/scorer.ts new file mode 100644 index 00000000..2c96862e --- /dev/null +++ b/app/agent/scorer.ts @@ -0,0 +1,139 @@ +// app/agent/scorer.ts +import type { Token, ScoredToken } from '../types' +import { getWhaleAccumulationCount } from './whale' +import { getOHLCV } from '../api/coingecko' + +// ── Technical Calculations ────────────────────────────────── + +function calcSMA(prices: number[], period: number): number { + if (prices.length < period) return 0 + const slice = prices.slice(-period) + return slice.reduce((a, b) => a + b, 0) / period +} + +function calcStdDev(values: number[]): number { + if (values.length < 2) return 0 + const mean = values.reduce((a, b) => a + b, 0) / values.length + const variance = values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length + return Math.sqrt(variance) +} + +function calcRSI(closes: number[], period = 14): number { + if (closes.length < period + 1) return 50 + let gains = 0, losses = 0 + for (let i = closes.length - period; i < closes.length; i++) { + const diff = closes[i] - closes[i - 1] + if (diff > 0) gains += diff + else losses += Math.abs(diff) + } + if (losses === 0) return 100 + const rs = gains / losses + return 100 - (100 / (1 + rs)) +} + +// ── Gate A: Conviction (0-100) ────────────────────────────── +// Is this token fundamentally worth buying? + +export function scoreConviction(token: Token, technicals: { + ma7d: number + ma14d: number + stdDev: number + volumeHistory: number[] +}): number { + let score = 0 + + // 1. Volume Consistency (25 pts) β€” consecutive days of growth + const vols = technicals.volumeHistory + let streak = 0 + if (vols.length > 1) { + for (let i = vols.length - 1; i > 0; i--) { + if (vols[i] > vols[i - 1]) streak++ + else break + } + } + const volScore = Math.min(25, streak * 5) + score += volScore + + // 2. Price Trend (25 pts) β€” above 7d and 14d MAs + if (token.price > technicals.ma7d && technicals.ma7d > 0) score += 12 + if (token.price > technicals.ma14d && technicals.ma14d > 0) score += 13 + + // 3. Wallet Allocation (25 pts) β€” rewarded for not already owning + // (In managed-wallet mode, we always score this as 25 since we control the wallet) + score += 25 + + // 4. Volatility Penalty (25 pts) β€” penalise erratic swings + const stdDevNorm = Math.min(1, technicals.stdDev / token.price) + const volPenalty = Math.floor(stdDevNorm * 100) + score += Math.max(0, 25 - volPenalty) + + // 5. Whale Bonus (15 pts) β€” at least 2 whales accumulating + if ((token.whaleAccumulationCount || 0) >= 2) score += 15 + + // 6. Narrative Bonus (10 pts) + if (token.hasNarrativeMomentum) score += 10 + + return Math.min(100, score) +} + +// ── Gate B: Timing (0-100) ────────────────────────────────── +// Is NOW the right time to buy? + +export function scoreTiming(token: Token, rsi: number): number { + let score = 0 + + // 1. RSI (40 pts) β€” reward oversold + if (rsi < 25) score += 40 + else if (rsi < 35) score += 30 + else if (rsi < 45) score += 15 + else if (rsi < 55) score += 5 + + // 2. Price vs 24h High (30 pts) β€” reward retracement from peak + const retracement = token.high24h > 0 + ? 1 - (token.price / token.high24h) + : 0 + score += Math.min(30, Math.floor(retracement * 150)) + + // 3. Volume-Price Divergence (30 pts) β€” volume spike without price spike + const volumeChange = token.volumeChange24h || 0 + const priceChange = token.priceChange24h || 0 + const divergence = volumeChange - priceChange + if (divergence > 0.5) score += 30 + else if (divergence > 0.2) score += 15 + else if (divergence > 0) score += 5 + + return Math.min(100, score) +} + +// ── Full Token Scoring Pipeline ───────────────────────────── + +export async function scoreToken(token: Token): Promise { + // Fetch OHLCV for technical calculations + let ma7d = 0, ma14d = 0, stdDev = 0, rsi = 50 + let volumeHistory: number[] = [] + + try { + if (token.cgId) { + const ohlcv = await getOHLCV(token.cgId, 14) + // ohlcv = [[timestamp, open, high, low, close], ...] + const closes = ohlcv.map((c: number[]) => c[4]) + const volumes = ohlcv.map((c: number[]) => c[1]) // use open as proxy if no vol + + ma7d = calcSMA(closes, 7) + ma14d = calcSMA(closes, 14) + stdDev = calcStdDev(closes.slice(-7)) + rsi = calcRSI(closes) + volumeHistory = volumes + } + } catch { /* use defaults */ } + + // Whale check + const whaleCount = await getWhaleAccumulationCount(token.address).catch(() => 0) + + const enriched = { ...token, ma7d, ma14d, stdDev7d: stdDev, rsi14: rsi, whaleAccumulationCount: whaleCount, volumeHistory } + + const convictionScore = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }) + const timingScore = scoreTiming(enriched, rsi) + + return { ...enriched, convictionScore, timingScore } +} diff --git a/app/agent/watchlist.ts b/app/agent/watchlist.ts new file mode 100644 index 00000000..c8742b83 --- /dev/null +++ b/app/agent/watchlist.ts @@ -0,0 +1,63 @@ +// app/agent/watchlist.ts +import { getTopBaseTokens, getTrendingTokens } from '../api/coingecko' +import { searchDexTokens, extractPairMetrics } from '../api/dexscreener' +import { getMomentumPicks } from '../api/gemini' +import { cache } from '../utils/cache' +import type { Token } from '../types' + +export async function discoverWatchlist(): Promise { + const cached = cache.get('watchlist') + if (cached) return cached + + // Fetch from all 3 sources in parallel + const [cgTopResult, cgTrendingResult] = await Promise.allSettled([ + getTopBaseTokens(50), + getTrendingTokens(), + ]) + + const cgTop = cgTopResult.status === 'fulfilled' ? cgTopResult.value : [] + // Trending tokens from CG are a bit different, but let's stick to the top ones for now as per plan + // If we wanted to include trending: const cgTrending = cgTrendingResult.status === 'fulfilled' ? cgTrendingResult.value : [] + + // Normalise CoinGecko tokens + const fromCG: Token[] = Array.isArray(cgTop) ? cgTop.map((t: any) => ({ + symbol: t.symbol?.toUpperCase(), + name: t.name, + address: t.contract_address || t.id, + price: t.current_price || 0, + marketCap: t.market_cap || 0, + liquidity: 0, // enriched below from DexScreener + volume24h: t.total_volume || 0, + priceChange24h: (t.price_change_percentage_24h || 0) / 100, + high24h: t.high_24h || 0, + low24h: t.low_24h || 0, + cgId: t.id, + })) : [] + + // Enrich with DexScreener data for liquidity + real-time price + const enriched = await Promise.all( + fromCG.slice(0, 20).map(async (token) => { + try { + const pairs = await searchDexTokens(token.symbol) + if (pairs.length > 0) { + const metrics = extractPairMetrics(pairs[0]) + return { ...token, ...metrics, symbol: token.symbol } + } + } catch { /* use CG data only */ } + return token + }) + ) + + // Get Gemini AI narrative momentum picks + const momentumPicks = await getMomentumPicks( + enriched.map(t => ({ symbol: t.symbol, name: t.name })) + ).catch(() => [] as string[]) + + const result = enriched.map(t => ({ + ...t, + hasNarrativeMomentum: momentumPicks.includes(t.symbol), + })) + + cache.set('watchlist', result, 300) // cache 5 minutes + return result +} diff --git a/app/agent/whale.ts b/app/agent/whale.ts new file mode 100644 index 00000000..ee1eac29 --- /dev/null +++ b/app/agent/whale.ts @@ -0,0 +1,52 @@ +// app/agent/whale.ts +import { getTransactions } from '../api/zerion' +import { cache } from '../utils/cache' +import { logger } from '../utils/logger' + +// Default whale wallets β€” expand this list +const DEFAULT_WHALE_WALLETS = [ + '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', // vitalik (example) + // add more high-conviction Base traders here +] + +export async function getWhaleAccumulationCount( + tokenAddress: string, + extraWhales: string[] = [] +): Promise { + const whales = [...new Set([...DEFAULT_WHALE_WALLETS, ...extraWhales])] + const SIX_HOURS_MS = 6 * 60 * 60 * 1000 + const since = Date.now() - SIX_HOURS_MS + let count = 0 + + for (const whale of whales) { + const cacheKey = `whale:${whale}:${tokenAddress}` + const cached = cache.get(cacheKey) + if (cached !== null) { + if (cached) count++ + continue + } + + try { + const data = await getTransactions(whale, 20, 'base') + const txs = data?.data || [] + const accumulated = txs.some((tx: any) => { + const ts = new Date(tx.attributes?.mined_at).getTime() + const isRecent = ts > since + const isReceive = tx.attributes?.operation_type === 'receive' + const hasToken = tx.attributes?.transfers?.some((t: any) => + t.fungible_info?.implementations?.some((i: any) => + i.address?.toLowerCase() === tokenAddress.toLowerCase() + ) + ) + return isRecent && isReceive && hasToken + }) + + cache.set(cacheKey, accumulated, 600) // cache 10 min + if (accumulated) count++ + } catch (err) { + logger.warn(`[Whale] Failed to check ${whale}: ${err}`) + } + } + + return count +} diff --git a/app/api/coingecko.ts b/app/api/coingecko.ts new file mode 100644 index 00000000..090b7aef --- /dev/null +++ b/app/api/coingecko.ts @@ -0,0 +1,34 @@ +// app/api/coingecko.ts +const BASE = 'https://api.coingecko.com/api/v3' + +function cgParams(extra = '') { + const key = process.env.COINGECKO_API_KEY + const auth = key ? `x_cg_demo_api_key=${key}` : '' + const sep = extra && auth ? '&' : '' + return extra || auth ? `?${extra}${sep}${auth}` : '' +} + +export async function getTopBaseTokens(limit = 50) { + const res = await fetch( + `${BASE}/coins/markets${cgParams(`vs_currency=usd&category=base-ecosystem&order=volume_desc&per_page=${limit}&sparkline=true`)}` + ) + return res.json() // returns array of tokens +} + +export async function getTrendingTokens() { + const res = await fetch(`${BASE}/search/trending${cgParams()}`) + const data = await res.json() + return data.coins?.map((c: any) => c.item) || [] +} + +export async function getOHLCV(tokenId: string, days = 14): Promise { + const res = await fetch(`${BASE}/coins/${tokenId}/ohlc${cgParams(`vs_currency=usd&days=${days}`)}`) + return res.json() // [[timestamp, open, high, low, close], ...] +} + +export async function getTokenMarketData(tokenId: string) { + const res = await fetch( + `${BASE}/coins/${tokenId}${cgParams('localization=false&tickers=false&community_data=true&developer_data=false')}` + ) + return res.json() +} diff --git a/app/api/dexscreener.ts b/app/api/dexscreener.ts new file mode 100644 index 00000000..22510cf1 --- /dev/null +++ b/app/api/dexscreener.ts @@ -0,0 +1,34 @@ +// app/api/dexscreener.ts +// DexScreener is FREE β€” no API key needed +const BASE = 'https://api.dexscreener.com/latest' + +export async function getTokenPairsOnBase(tokenAddress: string) { + const res = await fetch(`${BASE}/dex/tokens/${tokenAddress}`) + const data = await res.json() + // Filter to Base chain pairs only + return (data.pairs || []).filter((p: any) => p.chainId === 'base') +} + +export async function searchDexTokens(query: string) { + const res = await fetch(`${BASE}/dex/search?q=${encodeURIComponent(query)}`) + const data = await res.json() + return (data.pairs || []).filter((p: any) => p.chainId === 'base') +} + +// Extract useful metrics from a DexScreener pair +export function extractPairMetrics(pair: any) { + return { + address: pair.baseToken?.address, + symbol: pair.baseToken?.symbol, + name: pair.baseToken?.name, + price: parseFloat(pair.priceUsd || '0'), + liquidity: pair.liquidity?.usd || 0, + volume24h: pair.volume?.h24 || 0, + priceChange24h: pair.priceChange?.h24 || 0, + priceChange6h: pair.priceChange?.h6 || 0, + priceChange1h: pair.priceChange?.h1 || 0, + txCount24h: (pair.txns?.h24?.buys || 0) + (pair.txns?.h24?.sells || 0), + fdv: pair.fdv || 0, + marketCap: pair.marketCap || 0, + } +} diff --git a/app/api/gemini.ts b/app/api/gemini.ts new file mode 100644 index 00000000..0ecbebd0 --- /dev/null +++ b/app/api/gemini.ts @@ -0,0 +1,60 @@ +// app/api/gemini.ts +import { GoogleGenerativeAI } from '@google/generative-ai' + +let genAI: GoogleGenerativeAI | null = null + +function getClient() { + if (!genAI) { + if (!process.env.GEMINI_API_KEY) throw new Error('GEMINI_API_KEY not set') + genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY) + } + return genAI.getGenerativeModel({ model: 'gemini-1.5-flash' }) +} + +// Ask Gemini which tokens have the strongest narrative momentum +export async function getMomentumPicks(tokens: { symbol: string; name: string }[]): Promise { + const model = getClient() + const list = tokens.map(t => `${t.symbol} (${t.name})`).join(', ') + + const prompt = ` +You are a crypto memecoin analyst focused on Base chain. +Given these tokens: ${list} + +Pick the top 5 with strongest current narrative momentum based on: +- Community excitement and virality potential +- Recent catalysts or news +- Memetic strength and cultural resonance +- DeFi/onchain activity trends + +Reply ONLY with a JSON array of symbols. Example: ["SYMBOL1","SYMBOL2","SYMBOL3"] +No explanation, no markdown, just the JSON array. +` + const result = await model.generateContent(prompt) + const text = result.response.text().trim() + + try { + return JSON.parse(text) + } catch { + // Try to extract array from response if it has extra text + const match = text.match(/\[.*\]/) + if (match) return JSON.parse(match[0]) + return [] + } +} + +// Score a single token's narrative strength 0-100 +export async function scoreNarrative(symbol: string, context: string): Promise { + const model = getClient() + + const prompt = ` +Score this Base chain token's narrative strength from 0 to 100. +Token: ${symbol} +Context: ${context} + +Score based on: clarity of use case, community excitement, recent momentum, meme potential. +Reply ONLY with a single integer 0-100. Nothing else. +` + const result = await model.generateContent(prompt) + const score = parseInt(result.response.text().trim()) + return isNaN(score) ? 50 : Math.max(0, Math.min(100, score)) +} diff --git a/app/api/zerion.ts b/app/api/zerion.ts new file mode 100644 index 00000000..50cbbe3e --- /dev/null +++ b/app/api/zerion.ts @@ -0,0 +1,96 @@ +// app/api/zerion.ts +// We use fetch directly against Zerion's REST API. +// This is exactly what cli/lib/api/client.js does internally. + +const BASE_URL = 'https://api.zerion.io/v1' + +function getAuthHeader(): string { + const key = process.env.ZERION_API_KEY + if (!key) throw new Error('ZERION_API_KEY is not set in .env') + return `Basic ${Buffer.from(`${key}:`).toString('base64')}` +} + +async function zerionFetch(path: string): Promise { + const controller = new AbortController() + const timeout = setTimeout(() => controller.abort(), 30_000) + + try { + const res = await fetch(`${BASE_URL}${path}`, { + headers: { + 'Authorization': getAuthHeader(), + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + signal: controller.signal, + }) + + if (res.status === 429) throw new Error('Zerion rate limit hit β€” slow down requests') + if (res.status === 401) throw new Error('Invalid ZERION_API_KEY') + if (!res.ok) throw new Error(`Zerion API error ${res.status} on ${path}`) + + return res.json() + } finally { + clearTimeout(timeout) + } +} + +// ── Read endpoints ────────────────────────────────────────── + +export async function getPortfolio(address: string) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/portfolio?currency=usd`) +} + +export async function getPositions(address: string, type: 'all' | 'simple' | 'defi' = 'all') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/positions?filter[position_types]=${type}¤cy=usd`) +} + +export async function getTransactions(address: string, limit = 20, chain = 'base') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/transactions?filter[chain_ids]=${chain}&page[size]=${limit}`) +} + +export async function getPnL(address: string) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/pnl?currency=usd`) +} + +export async function getFungibleInfo(tokenAddress: string) { + return zerionFetch(`/fungibles/${encodeURIComponent(tokenAddress)}?currency=usd`) +} + +// ── Trade execution ───────────────────────────────────────── + +export async function executeSwap(params: { + fromToken?: string // 'USDC' or token address + toToken?: string // token address on Base + from_token?: string + to_token?: string + amount: string // amount in USD string e.g. '10' + chain?: string // default: 'base' +}): Promise { + const agentToken = process.env.ZERION_AGENT_TOKEN + const walletAddress = process.env.MANAGED_EXECUTION_WALLET_ADDRESS + + if (!agentToken) throw new Error('ZERION_AGENT_TOKEN not set β€” run wallet bootstrap first') + if (!walletAddress) throw new Error('MANAGED_EXECUTION_WALLET_ADDRESS not set') + + const res = await fetch(`${BASE_URL}/swap`, { + method: 'POST', + headers: { + 'Authorization': getAuthHeader(), + 'X-Agent-Token': agentToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chain: params.chain || 'base', + from_token: params.from_token || params.fromToken, // Handle both snake and camel case + to_token: params.to_token || params.toToken, + amount: params.amount, + wallet_address: walletAddress, + }), + }) + + if (!res.ok) { + const err = await res.text() + throw new Error(`Swap failed (${res.status}): ${err}`) + } + return res.json() +} diff --git a/app/server.ts b/app/server.ts new file mode 100644 index 00000000..b401a83b --- /dev/null +++ b/app/server.ts @@ -0,0 +1,117 @@ +// app/server.ts +import 'dotenv/config' +import express from 'express' +import path from 'path' +import cron from 'node-cron' +import { runAgentCycle } from './agent/loop' +import { getPortfolio, getPnL } from './api/zerion' +import { + loadUsers, createUser, saveUsers, + loadJournal, loadJournalForUser, + loadAgentState, +} from './utils/storage' + +const app = express() +app.use(express.json()) + +// Serve React frontend (built) +const clientDist = path.join(process.cwd(), 'client/dist') +app.use(express.static(clientDist)) + +// ── Setup Check ──────────────────────────────────────────── +app.get('/api/setupcheck', (_req, res) => { + const checks = { + zerionApiKey: !!process.env.ZERION_API_KEY, + zerionAgentToken: !!process.env.ZERION_AGENT_TOKEN, + executionWalletName: !!process.env.MANAGED_EXECUTION_WALLET_NAME, + executionWalletAddress:!!process.env.MANAGED_EXECUTION_WALLET_ADDRESS, + geminiKey: !!process.env.GEMINI_API_KEY, + executeTradesEnabled: process.env.EXECUTE_TRADES === 'true', + } + const ready = checks.zerionApiKey && checks.zerionAgentToken && checks.executionWalletAddress + res.json({ ready, checks }) +}) + +// ── Users ────────────────────────────────────────────────── +app.post('/api/users', (req, res) => { + const { address, name } = req.body + if (!address || !/^0x[0-9a-fA-F]{40}$/.test(address)) { + return res.status(400).json({ error: 'Valid 0x wallet address required' }) + } + const user = createUser({ address, name: name || 'Anonymous' }) + res.json(user) +}) + +app.get('/api/users', (_req, res) => res.json(loadUsers())) + +app.patch('/api/users/:id', (req, res) => { + const users = loadUsers() + const idx = users.findIndex(u => u.id === req.params.id) + if (idx === -1) return res.status(404).json({ error: 'User not found' }) + users[idx] = { ...users[idx], ...req.body } + saveUsers(users) + res.json(users[idx]) +}) + +// ── Portfolio ────────────────────────────────────────────── +app.get('/api/portfolio/:address', async (req, res) => { + try { + const data = await getPortfolio(req.params.address) + res.json(data) + } catch (err: any) { + res.status(500).json({ error: err.message }) + } +}) + +app.get('/api/pnl/:address', async (req, res) => { + try { + const data = await getPnL(req.params.address) + res.json(data) + } catch (err: any) { + res.status(500).json({ error: err.message }) + } +}) + +// ── Journal ──────────────────────────────────────────────── +app.get('/api/journal', (_req, res) => res.json(loadJournal())) +app.get('/api/journal/:userId', (req, res) => res.json(loadJournalForUser(req.params.userId))) + +// ── Agent State ──────────────────────────────────────────── +app.get('/api/state', (_req, res) => res.json(loadAgentState())) + +// ── Manual Cycle Trigger ─────────────────────────────────── +app.post('/api/run', (_req, res) => { + res.json({ message: 'Cycle triggered' }) + runAgentCycle().catch(console.error) +}) + +// ── Watchlist ────────────────────────────────────────────── +app.get('/api/watchlist', (_req, res) => { + const state = loadAgentState() + res.json(state.lastScored || []) +}) + +// ── SPA fallback ─────────────────────────────────────────── +app.get('*', (req, res) => { + if (req.path.startsWith('/api')) return res.status(404).json({ error: 'Not found' }) + res.sendFile(path.join(clientDist, 'index.html')) +}) + +// ── Cron: every 60 minutes ───────────────────────────────── +cron.schedule('0 * * * *', () => { + runAgentCycle().catch(console.error) + console.log(`[Cron] Next run at ${new Date(Date.now() + 3600000).toISOString()}`) +}) + +const PORT = process.env.PORT || 3000 +app.listen(PORT, () => { + console.log(`\nπŸš€ Conviction DCA Agent running at http://localhost:${PORT}`) + console.log(`πŸ“Š Dashboard: http://localhost:${PORT}`) + console.log(`πŸ”§ Setup Check: http://localhost:${PORT}/api/setupcheck`) + console.log(`▢️ Manual Run: POST http://localhost:${PORT}/api/run\n`) + + // Run once on startup (dry run only) + if (process.env.RUN_ON_STARTUP === 'true') { + runAgentCycle().catch(console.error) + } +}) diff --git a/app/types/index.ts b/app/types/index.ts new file mode 100644 index 00000000..f53e131d --- /dev/null +++ b/app/types/index.ts @@ -0,0 +1,73 @@ +// app/types/index.ts + +export interface Token { + symbol: string + name: string + address: string + price: number + marketCap: number + liquidity: number + volume24h: number + priceChange24h: number // as decimal, e.g. 0.05 = 5% + high24h: number + low24h: number + ma7d?: number // 7-day moving average + ma14d?: number // 14-day moving average + stdDev7d?: number // price standard deviation + rsi14?: number // RSI (14 period) + volumeHistory?: number[] // last N days of volume + volumeChange24h?: number + cgId?: string // CoinGecko ID + whaleAccumulationCount?: number + hasNarrativeMomentum?: boolean + narrativeScore?: number +} + +export interface ScoredToken extends Token { + convictionScore: number // Gate A: 0-100, threshold 60 + timingScore: number // Gate B: 0-100, threshold 55 +} + +export interface User { + id: string + name: string + address: string // their public wallet (monitoring only) + active: boolean + createdAt: string + policy: UserPolicy + whaleWallets?: string[] // custom whale wallets to track +} + +export interface UserPolicy { + dailyLimit: number // max USD per day + weeklyLimit: number // max USD per week + maxTradesPerDay: number + cooldownMs: number // ms between trades + tradeSize: number // USD per trade +} + +export interface JournalEntry { + id: string + userId: string + timestamp: string + token: string + tokenAddress: string + convictionScore: number + timingScore: number + amount: number // USD amount + executed: boolean + txHash?: string + error?: string + dryRun: boolean +} + +export interface AgentState { + lastRunAt: string | null + nextRunAt: string | null + cycleCount: number + watchlistSize: number + lastWatchlist: Token[] + lastScored: ScoredToken[] + status: 'idle' | 'running' | 'error' + lastError?: string +} diff --git a/app/utils/cache.ts b/app/utils/cache.ts new file mode 100644 index 00000000..c9efd501 --- /dev/null +++ b/app/utils/cache.ts @@ -0,0 +1,19 @@ +// app/utils/cache.ts +// Simple in-memory TTL cache β€” prevents Zerion/CoinGecko rate limits + +interface Entry { value: any; expiresAt: number } +const store = new Map() + +export const cache = { + get(key: string): T | null { + const entry = store.get(key) + if (!entry) return null + if (Date.now() > entry.expiresAt) { store.delete(key); return null } + return entry.value as T + }, + set(key: string, value: any, ttlSeconds = 60) { + store.set(key, { value, expiresAt: Date.now() + ttlSeconds * 1000 }) + }, + has(key: string): boolean { return this.get(key) !== null }, + clear() { store.clear() }, +} diff --git a/app/utils/logger.ts b/app/utils/logger.ts new file mode 100644 index 00000000..bccf753b --- /dev/null +++ b/app/utils/logger.ts @@ -0,0 +1,6 @@ +// app/utils/logger.ts +export const logger = { + info: (msg: string, data?: any) => console.log(`[INFO] ${new Date().toISOString()} ${msg}`, data || ''), + error: (msg: string, data?: any) => console.error(`[ERROR] ${new Date().toISOString()} ${msg}`, data || ''), + warn: (msg: string, data?: any) => console.warn(`[WARN] ${new Date().toISOString()} ${msg}`, data || ''), +} diff --git a/app/utils/storage.ts b/app/utils/storage.ts new file mode 100644 index 00000000..44df62b4 --- /dev/null +++ b/app/utils/storage.ts @@ -0,0 +1,65 @@ +// app/utils/storage.ts +import fs from 'fs' +import path from 'path' +import type { User, JournalEntry, AgentState } from '../types' + +const DATA_DIR = path.join(process.cwd(), 'data') + +function ensureDataDir() { + if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }) +} + +function readJSON(filename: string, fallback: T): T { + ensureDataDir() + const file = path.join(DATA_DIR, filename) + if (!fs.existsSync(file)) return fallback + try { return JSON.parse(fs.readFileSync(file, 'utf-8')) } + catch { return fallback } +} + +function writeJSON(filename: string, data: any) { + ensureDataDir() + fs.writeFileSync(path.join(DATA_DIR, filename), JSON.stringify(data, null, 2)) +} + +// Users +export const loadUsers = (): User[] => readJSON('users.json', []) +export const saveUsers = (users: User[]) => writeJSON('users.json', users) +export function createUser(data: Pick): User { + const users = loadUsers() + const user: User = { + id: `usr_${Date.now()}`, + name: data.name || 'Anonymous', + address: data.address, + active: true, + createdAt: new Date().toISOString(), + policy: { + dailyLimit: 50, + weeklyLimit: 200, + maxTradesPerDay: 3, + cooldownMs: 60 * 60 * 1000, + tradeSize: 10, + }, + } + users.push(user) + saveUsers(users) + return user +} + +// Journal +export const loadJournal = (): JournalEntry[] => readJSON('journal.json', []) +export function saveJournalEntry(entry: JournalEntry) { + const journal = loadJournal() + journal.push(entry) + writeJSON('journal.json', journal) +} +export function loadJournalForUser(userId: string): JournalEntry[] { + return loadJournal().filter(e => e.userId === userId) +} + +// Agent State +export const loadAgentState = (): AgentState => readJSON('agent-state.json', { + lastRunAt: null, nextRunAt: null, cycleCount: 0, + watchlistSize: 0, lastWatchlist: [], lastScored: [], status: 'idle', +}) +export const saveAgentState = (state: AgentState) => writeJSON('agent-state.json', state) diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/client/README.md b/client/README.md new file mode 100644 index 00000000..7dbf7ebf --- /dev/null +++ b/client/README.md @@ -0,0 +1,73 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/client/eslint.config.js b/client/eslint.config.js new file mode 100644 index 00000000..ef614d25 --- /dev/null +++ b/client/eslint.config.js @@ -0,0 +1,22 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + globals: globals.browser, + }, + }, +]) diff --git a/client/index.html b/client/index.html new file mode 100644 index 00000000..3269acab --- /dev/null +++ b/client/index.html @@ -0,0 +1,13 @@ + + + + + + + client + + +
+ + + diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 00000000..690dff07 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,2772 @@ +{ + "name": "client", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "client", + "version": "0.0.0", + "dependencies": { + "react": "^19.2.5", + "react-dom": "^19.2.5" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^24.12.2", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "eslint": "^10.2.1", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.2", + "globals": "^17.5.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.2", + "vite": "^8.0.10" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.128.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.128.0.tgz", + "integrity": "sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.18.tgz", + "integrity": "sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.18.tgz", + "integrity": "sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.7", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", + "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.12.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.3.tgz", + "integrity": "sha512-8oljBDGun9cIsZRJR6fkihn0TSXJI0UDOOhncYaERq6M0JMDoPLxyscwruJcb4GKS6dvK/d8xebYBg27h/duaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz", + "integrity": "sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.59.2", + "@typescript-eslint/type-utils": "8.59.2", + "@typescript-eslint/utils": "8.59.2", + "@typescript-eslint/visitor-keys": "8.59.2", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.59.2", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.2.tgz", + "integrity": "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.59.2", + "@typescript-eslint/types": "8.59.2", + "@typescript-eslint/typescript-estree": "8.59.2", + "@typescript-eslint/visitor-keys": "8.59.2", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.2.tgz", + "integrity": "sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.59.2", + "@typescript-eslint/types": "^8.59.2", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.2.tgz", + "integrity": "sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.2", + "@typescript-eslint/visitor-keys": "8.59.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.2.tgz", + "integrity": "sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.2.tgz", + "integrity": "sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.2", + "@typescript-eslint/typescript-estree": "8.59.2", + "@typescript-eslint/utils": "8.59.2", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz", + "integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.2.tgz", + "integrity": "sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.59.2", + "@typescript-eslint/tsconfig-utils": "8.59.2", + "@typescript-eslint/types": "8.59.2", + "@typescript-eslint/visitor-keys": "8.59.2", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.2.tgz", + "integrity": "sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.59.2", + "@typescript-eslint/types": "8.59.2", + "@typescript-eslint/typescript-estree": "8.59.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.2.tgz", + "integrity": "sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.2", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", + "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-rc.7" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.353", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", + "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", + "dev": true, + "license": "ISC" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.3.0.tgz", + "integrity": "sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.5.5", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz", + "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": "^9 || ^10" + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.18.tgz", + "integrity": "sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.128.0", + "@rolldown/pluginutils": "1.0.0-rc.18" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-x64": "1.0.0-rc.18", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.18", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.18", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.18", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.18", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.18", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.18", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz", + "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.59.2", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.2.tgz", + "integrity": "sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.59.2", + "@typescript-eslint/parser": "8.59.2", + "@typescript-eslint/typescript-estree": "8.59.2", + "@typescript-eslint/utils": "8.59.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", + "integrity": "sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "rolldown": "1.0.0-rc.18", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/client/package.json b/client/package.json new file mode 100644 index 00000000..47504f63 --- /dev/null +++ b/client/package.json @@ -0,0 +1,30 @@ +{ + "name": "client", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.5", + "react-dom": "^19.2.5" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^24.12.2", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "eslint": "^10.2.1", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.2", + "globals": "^17.5.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.2", + "vite": "^8.0.10" + } +} diff --git a/client/public/favicon.svg b/client/public/favicon.svg new file mode 100644 index 00000000..6893eb13 --- /dev/null +++ b/client/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/icons.svg b/client/public/icons.svg new file mode 100644 index 00000000..e9522193 --- /dev/null +++ b/client/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/App.css b/client/src/App.css new file mode 100644 index 00000000..78c24f74 --- /dev/null +++ b/client/src/App.css @@ -0,0 +1 @@ +/* App.css */ diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 00000000..0b4c0935 --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,42 @@ +import { useState } from 'react' +import Dashboard from './pages/Dashboard' +import Journal from './pages/Journal' +import Settings from './pages/Settings' + +export default function App() { + const [tab, setTab] = useState<'dashboard' | 'journal' | 'settings'>('dashboard') + + return ( +
+
+

⚑ Conviction DCA Agent

+
Base Chain Operator
+
+ + + +
+ {tab === 'dashboard' && } + {tab === 'journal' && } + {tab === 'settings' && } +
+
+ ) +} diff --git a/client/src/assets/hero.png b/client/src/assets/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..02251f4b956c55af2d76fd0788124d7eee2b45eb GIT binary patch literal 13057 zcmV+cGycqpP)V|)f$;Qooc7=_G zlYe)HToTQIc!$)^+J1M1y0*T%w!p~7%ux`!eRhO?c80XDxKQ*R^lUUMnA>6NT^?feoZ8xxvP32D&s-9ow zqjcM}eesrC)NeDmsf)*P7wJ|K!&xP%Zy4iI8lF)Tv2!reW)tCzg_1=PmOwd1SQfxa z8;58t!=z~Ba7CYlNWVG>he8aRPY|+-JmozNhn!#9i#77Aa_Edt$ijyCWL#=~I>~2X zZNrQ8I0=D+NWD4pq=7~(i zhfThMNw|G>g^y9pGzxX7ZSApl@tIxFcs{p#MX{Ax&XZT+cR#U+OWc@S)pkIuI}dzu zH?^Q=<(y&Vq-oxSLfc0Zmq81bjZWf}RnssBaD6}2g-XJHLcN_|*IOu>m|x$nbm(?E zyNy!Zp=RroS;?Vg*kmoJYBi!n5{_^@rA!)=t#a^;N$8GL!*DsQb}`yvEuX!G@||An znOfUZAevPrkV_qjl|<~3QRZzG&h@C9Y5z zqpNH4xqbF_InIPh)kX}Vn^5kyed|mOuq+2>M;v~KO37a#yrEn3XDqtOl=rc6_KZ!; zreo)DFVB4|>1Zd(bvMI%8uM;3!)YMYu&cG?(PE!B~y@3yKBMt|R zAf=I16tFwPsl)!jDqvYkLHaAQ+f@W1m6F5aZvwhm4JL z{_l)@b;)mDSzle2gyFP5-r1x-5X{G}ot%VyWP@vEW80!Q=f%RTfpg>B*TA^pyWYUQ z<=xPtz}WcZ!;rFl4m1D&FFHv?K~#9!?A%+fn=lXt;9!Fc#kQ;zk~gZFsH z8e5iu@c_pzX&qb8&Dum*oXwB+fm6l6gFfC|o*wgEiy6tw~&co z9Vd_4)P%wP-KwQW7|lN-znGK#?N+j24U=$982myIBM+vsiKsc*@4-rwJxuAaHKna6 zT3wi!C~a4ZKH03qU}_1bKyx0&$CaK7_%Z+Kl$)fF5^op zZApQF2TvDav!s|krTjw-8US6ep z%!VmX4luub+fseQz_D9ATJQ?iQQwD}TZz{-yo#l12a%+7bT@E(X-hyaVS-5vuXc#^ zx^w;L21;NphGVoj*{s3f4dme0y2LC=G1-7THd`#z?;tuC{^9k(dM{Rf2GOxg7Jzho z7nSZHl7?M9kdalX`)YgoKEfiae5+;$(OGeN1eqxrv!ZCVKyH>xiyNqfe8xzY8*7)H zQls8KMp)F4D>ED;idMOU^^WhVF@q>ZSmeB0y~qC~|DB648hr%Sh|*T(4q|w2l?m2+ zvBVw3@7+Mz?^Yc#+se6KM;a<=(W-I>k)$-qL2V*t}VaW`;?P4)WqI%maIDq8!oUcSYAD`}wWjkSyAVsnF65#2zQ zZ>(K*TlS(E#4y$4Zq+e^_&}d)q20hCe3!LfLYP%nQpLJ~gM6a1hJlz3)aS<9C9me| zAcmJ#>tOwBy{HoP0Sm1&_(E+S@6 zgBIFUoei8zJmdpiq8q5=OY7t@`)JWxn_&GvKVr=Zdb_pEL_j|=?f;WK^U9Q0efd#K z9q7SfJTl4pmA$jsZ5oK8@O9#!I3Cv-kL)<8SalSsp#dcpvJ}Nz#G6FC0%9|7Fi#8; zGDJXtj!&GljT3*HE@0EE>G8Se&d)*nkqe}-?`3vPl&UqK?xG z!3XJ4M-x`EuQjhBbu?ik-)rmIt=DF_N?TVMP)8Gjn)TZ2V%H|zENbeix}kOxd@0}Q z>)HuH6Ean!uS#~4g2Ne2WsMGel|h%j9*W_quQheG^JqmKhc*RYzp0wKlGjBq2VzY_ zgOv8WC1+%W=W)k)Yp_`8kfE=uiiwOZTXi8Uj9YGr$f@yJcJ;#&-Nq~sJ7anE(@;QN z=~br%7%7`isKStX|7!1?L(apl^QvPKlrHV4S+6tNVQ*R1iGdC~WMNE1$a+=rpQmcB z>wxiLIBvOnm;u*;9Y!kJdy(T4lk|8>JAm(&wEsFIF1$_*{>2ZNd$V6DS=SfrGxAv0 zzKe377JI`&o9Ljr+VnS*EwehA{f&{cKZF(6*MG5!p5MvrFA3ll{fmRG*L@6^cb;o^ z3Wm8c?Sc6$`>~VEWw(c$Y?nRO;2Q$=ulpqPtM^=1IZx;@xK0PgO7rKQ^WHVLwtgUT z%|JF{^f(VH)wLKQ%dYiu2RmchBdxL0-M?wxxul_z*{h6ZZ`>-k(vizs((vW8Lt6Z6 zY;Dt?@JWyN`O`f;&d1Mb?e%9oyRK1ql?EE5XB2(W)|D1~Rx35$H6@6)$F?)7V|zEO zI}fu0-0}8W5=6sg$fPnZ~7=tTudl?Ecb@pxbo)vni%gP-?hL|%*?62C;x6?@E`VRnJv z?fTb;k4x;TS7Cu-z%J}uy}e-pwpLQ17Q@4DC+FCdAmNKklG$`I_pyw7E{fYmw~{Fj zi?6KcVy=Wrel)EB_DWO|0CKmI|13!gBV?X`Ozp7x>?6jr`>Qz=^4ea35!$*f}) zS$i+x_k+@P2q1RFUH^ZTTk7=n?cjfR>hTq3l3SY~#w+I8SSutXGyhw;Ws~=zMQ%Vc z>$On~47Ut?P*_!TOQ&PFmLAyJieB2X4_Fd_!WxI-AY`q1Lc-oK?+qcOTzlQ?@~x@OT}*9jTVNfl@3rGvZpWI=eKg>T zZb@6YWz)J=IhP7CF|c?G62vMEG%#U}?#86$0jR4sG~i(jRd#jmn`7b(O#?N;3a;1t zhXLssmUwGhp79luw#(*V8WL0|8+E z6=YZ_O@er~$LrD_PYGc(kJgB=;yw#+Z3X6LDUZ(NcwN=B-hjdiHm!JFar%m{(5bEW z@@_VEtG$5;`EJZ|OkJ@l&G9n((w@uNFwmU%bG|s#TbcJJos!{e+bjCjrCq_}LcN!UFgKtgg7siV*7# z!}1whTRRi*-avJPu->C}Z8EiuK$#886+H_#_!btv+rsiBbv2jAJvJ+O0{#}y(%L3H zfjU-kq_-L@2XrL*ae{{qYJkD{@dw%*bkh2P&YS-0!Xt!PRz7KHV0+~j(t9W8lAVWR zt@B*DgURgEz4>WuN>o?_iKcw$?k{||Pg7{Q2o4|VmJ)mg?{VQJA<}zEr^YAAS zgGm5RT4T3p)U;yz-tfBO^kw8?IoG!IVmc+Z3m#}AOQ?5MRa>)OcU!$N^_+yK6ayn? zK>~WK0!#ysuj^oNLakm)Zvu+J)OSubX^kv!c*xgdIvs;kln!rgG4*uZ;w0mQQO4XD zO9P{GNdv!=cQ(CAL{S(%KtuV^zC&Q{%g)PoXnp^gn^>c*`E>$hLYg2HjnbVGtWLa{7zHdG1jT@B{|Dm16 z7K2(jsfG+m*Zxof)iXxu+!H5Mo-0$pkyV3VV4B@Qms46M zuBxGRV@HxU7Wwx-6CB zaU*HO<_qn$5GH>&@?nRy1{z zkik!sLfWQ)r#75)vVwCBU*r_)Q6mp?!j85{#Xqse)ApRdE$V0%I0*~e(_{)5H)`Mk z#rExC>yjhZxuL@|+#v4#<Axw$+VpV zuT;!2Vww$je$DpAW`$FX_Ab|Ip%$;&T$-lW8jS~B$>G}rd>eQG+$h9lQx4Mx0w={m zx9?T6VU`>sR}XClkAhHEShOUe8awiq zmizhL+}5UKs3}6~It7vBTig9dfQ2Q8coo+Miiaw7n~>4ybv2Ptt0^^=VqX(t*Yya9 zr`FxxFX8(v*H=+uJ#JJWIB2A(==HDYx~^zZ2nu?2`}|Wsa*f3h3ixc+U|FDtAG$Y! z*lc_7se5Oso-Cgqe0){{!8H4g$3<8!R<6JOurD;((({c$1(pwb>(#TT!sge@4>r2@ zVL7>U`0`nsWAYErezk4(Z!gMI2?UTo{J3Ajo(u4)KYIRd>BRcG4BoS3G0EXyEp@tw z%P7__?A^a>Q&AKL@ayDO9D*Qkc!NHnO9l}kpp_6hXbMppYL(X1L?njdFT|-h2<_$; zAtDZ!1Rf%|yb!qbWKd}%0b`LzBeyNy43|QO(&h2mxQLUL)|0%agVOW)6TV!&Ip^Ls z`PG2cygM8)IecQx=Fc+nqYRo4hS^^-nM_&-y8?EJXUczP=DIw(GkTJdpEdh<_STs{ z|A)4n1GKdE=Wu!!nYoZHcUQ4S&R;oDOKX2lrkdF(mK>hz<$Pp>igjOcvoRIjlN=W8 zu8Gx5(roqn8$>gEE5vy{GiGeW8Tq{vnf3hS-V=$tZkQuftUVuU8o6k&dn=Yg3)6MOIH>nlK^-2+C6BZITr~1@So?NvG#TwL)|~=1YXGMTLpS<)ziK_CSOabe z=cB#5)yz|@0i9dSo?*CX)}UP=s6)B+F@~Em(u@Q(I9J9i_V{LmMu8BfXYMh~*oPP+ z!3~xTv|(>|=n6ZOtT~C@V!z!w%18*8T2t6}U2S##rC)mekBql&VsBX;$~ByGE$oA9 z`0Wzq8p?R{4)$l*on;!cLa}Dh^Xe?owiQZt9nH1fxxh$pN9K%CtOw?u3>85L7rr!d zXs)l{TZ{xXP&U8exz?9cv~dNNibOmt*K4I$?RxqIBZ0(?Mg-9FS{*9Bc49Qc1`=sIF-rye`aNT1G@4NwXcnyc@+bw_mTsR>5< zF<2;X0QesG_pw|TonqVBhRtfqI>ty(SIu&VOXd0CrLlfp+;WH7HYjhqnu^oAY!9cB z=B6#R?Rfz9BP`dJ=@v_?70s3HxQPk+{6Y+lM85f2NF^00*^OcM0~?JOZfR9ZPYF+# zYSs}(_BUYV8{n@2a1hD^SV41bwmi2uztR;PeBgF1F-`9>`zoNss-@3LaF2sjl~>OaaVmp7PNp+UT`6@}gR%uzqHDVeEZ14{Yt?n%JeQm+t(1_u zSc}oj^{b;+rlS|ME%+LjzSI&xu0Bblxo$MJ-J$kJ?Qu_XUXh}*@*-x@ny|}wVM%Lg z3tNB`yvr*}N?ClGL;H2cglcvErIccU3(eP7>@~4nOIcI~-`P8tSQnx=jI&{9)!1}l z;gQ%_h>ZlPSV@o@Azq1R$C6ja5!^ZGh;YRhhxs58qJWo9@Bceac&yy(pET1hnn`~7@}2L0&dfPKYs$ih7m2}R!25!(hxqA(!UIw; zK4+~Jowy3=RNC6nE=ncU{LH5?*9@W24lacJlvCZXB$CYtE@>c+~H zkV=(5I&gb{xn2!~f&fs2NQgAL6`p|kyt6kpWk}iVlqIp(H;ig`{_U9yxs1jzu^ETM z7~)Rg8C-NueqTYP&U8l{DY=Y47cR zOR@U%$KQV{mkRF|4)z9Y^t3K`@p>duY&QLUFeh6VoV`a`$U@)(z!-N*5Cj<11$EZW&hJLX83TO{lJYP74rlDZQPkm@t<=U^I)x@|UnHHkdQlh?!ltZwl92rE;;^ zZuIappj4dhld1}kttYYV-j|KF1Kus zWBnzttD^00%LFK(wrwNragFub6xiV8QE2rm<`&fcR4SLFcdtLxVuN!Aal-g6dE4%k zARZ}|xeo;K{0yf7@9aua%2j5o)CPcIOc6uLHFJOcgtB5owlcNAwyAHc0QB0Dts?c@ zUemG~j_E&W7R%+x-IO4FJl8e&*2Blmp1S#RA|)geVrxvP)NHdYuxi~g&Etn?QdNK8ZDKZ?QFLU?zh30G|t9G>a_X4zk}Ygw<^$7K!GIn(Io$>(d4ODJQ2XSd%jpK zm7>ptl$a3GyB}5-%p4>Q*p#VL^B{yQMuFCM^#l#+N!Ne z5_PrJWB=@Iy+t)H`g1lX`{bm($KE5I?0c(JEYm#t{F}j!xtsbob0{xu@0TB_*>G7w0ICn zr#VoBktqHZ~XxhiKD*lcG|b;H*|Ny3P^8ceV`sfBRfrhwZ!T+MFZ!F1Bt{q$8d9i6o?~ zODj^POr}&ivSa^R^YFIq7o0giLBKCycH_aU`F6)O6JX%nPTwh~Q`eq6*0iE#Srj2^ z*_hN3%*b83zfafy60@Cp3{J({RlSaEn&E?mrxRNC9GQ7#+f=s! z0KBf-9Ny_v2VbE%aB|Di)5kNJ^t&C`4D(>t7zYUWUFtbxt+Oq=!@O7BU)}>d*R72o zFF)3jQD_lLe4is&xzyJYC1-c{8TX$RU>&>P$%)ufpez0XSAukmh!xcekg`s$c<>-q zI#zn^JU0zzF}V60)o$_gY}PQH>b2M9&8fRZa#OauglPb zeQ@pMm&=!vNgos4CluQjLMV!pfkmxK+35bi^k&=k>9h02?l+u+m0agG;(h2|Jslc-llvtEwn~*w3bx7qnvZACG<8}AGeaDVvcHbKd2>3G^ zSFPULUn-?Pmo^-_`mLZr??uNH`2=I&yajlrF{DtUxMy#Nu}z=3y7qbUA;5`)hibMR zhXL@@uKyV0-2&A@t@!xyrBnMJl&^o@Gx$&5_q6?D=ji5grd-~=?dlg;ur(_V0wjh! zA=JV^C1m+DDkOsgr<%O9ZQFg!0}pD(#PSz4Dr_EyS5$`)VIAv);4n-SFP~YtC7sH= z7&*MfpH;gd*FHbkmD#)hVxb6xjc9~`t?_{=JS+@ip_cTicXxG<=7m9& zPX+Z8IC*GSAXuGCrZDHgR$r%jyk-fctis2Kx4HvZ|B~8uC@o)m^>Hy-O!&TKA?$&n zkP2Xc54w~!=z2?^NafyL*L0V9cbYrugHBBUj`xVyZmGFR&kvk#>1J*Z~i zNTz}?IAdJ$gkqd2!Gw(%LzE!O5s4C7q4%T~e_P{+z=DNDKrG**p=U`d5yg^vp`;Zn zsU=8gd0a9s4s0FPJePWR9eH5=+O^Kks&kC-iblNqTh2&Pw*^(4384f+D8N|fewZu_ zg2ejQ)ov;ztz;NQl7yj;A`(!H!XQu_$sqY9h_IrH*}_%1{L&_YLDvO?%R5Z-t+ClW z_qERbL?HKUZ!nt+!E9S`uoh^5A|DaIHe*_gf1`E_Vq+}{&T@t$EGhMnRjJ4z2w_W8 zp+qjs7as22^&S3wY1?+}^j-I=RcCE>#|39)g(lU7v_8;?=qK(9D8-*pPdiy)P3lIblG`+?%ea| zYoD3dopYt!tKgFicfNmNi(EWE=E4hC6(r|PYtanqJlmt57YOVrr2^tfrG(eG9C##X zu&1t@%L$RIvpj!wUA z8i>Pqot#_+Cnp6L2XPcZy1ar|9MnY+7eNvK1E)@Tr#2KsXq1*>)uUCozT7L##ok?o zhA6ofP4E|b*9tAfG?uf$#}>TIR&1A!yslP8}i7w-EzW(x#9VEvx18k%Tn=-$VV zkOtUr0b2!w3t>h?#8AZl^Az*(6KCGlD;4j~yx};`#2gN1_gv=%7KVzecIRakN{f*4 zeaI>yH;-o4OGhvGTU)(quWI)-q?V*(sVesSMv|wMUQ3hLEt=lBB$KZ9TyHr>)f7o%) zPYeU<3P)*P10*7vE)nA5#{c=6-E-_>r_u4e3i!I2+UksELwDqwMeBZ9FSP$;^Ajro z_@M#_Ss$?ejoB@!wN|kbGKs(0zLo%0QpQXW#t;oC$B0MZYZ&Ej?8~fNhcCVvPo3vo zFn0WWZaPliF^8_}yzb`*f@yg0uWv6HgNI)xa=pO%Ck(C<=-60l#uD3(wXP~c7!NoX z0&^6=N`zcc90F#qt@=Rn@r!3(*1v(Tl{B!m?Mc7yIA+nEHpY{YWr$=)F7rhR1P}(v zt{YhY#;jsW6G>#xhP*B`OCk|Pf+NN;ju1rxa*HAgoGq*rvqw&xe~;t1JA31$s?GBb z*g7&@cbKo4n<`>)!UlIAgR6q&))B0KYU8r66GbFj?8Guw4E%&}Qi_lT003LtoIZei zwD~=XZmeo+yZ2Pq3KYCF-R&11^p= z@H%s+=G`}wrbJ{()Mh71#2SP3Zy3m>l1n?0N-N1Q;z6?oSxr-G(H5m4EO>~&;}VKi zfY}3w+9z>vp#d)hVuu`)vG_aaH%3b=WKMnSu&c31;<3O;bz2iD=w+o4#oBb36 z5ZCF*Gu?zjZIR0S>_%pHY2$k8D^n7Sz_K8tCDeXM+dO<#LSg%h6`~dnVG1N@T7v&e z%wEd1!k{^zfz_1BTW{!$!B%g)J^2b87!9Y>>100X1SgT7s0z$o>^lAA=Gp_cC1(h=*5Tmf8z&LGJJ>$|K^~s`z9*OWz5MFUr?>Bi?_PGBB)#psD5?>n+q{o_ zz7~ez&;t#h8l$jwGPCC&xq2YetXYQT+0F3j(`xmNGf8dj#an|p#I*pvI*kwW4iuB> z+q3_7xB8y;pLzHG-S%+UHQA zvqp;$kmGJY>lLsN4C~&TcvAS1SErTcwcw0r@wngk zShAUA1M9b#g}^pL-zH7Q#z^&j#r9F8BTVfkR&qF<=e35goTu7c|GN)0mokj4m0%~0 zXJ8j4Hc_l;HJ&uU*Iw`8d_EscJ``s0tk9mkKo^&#TYXm-EoAzTQObxa@^u~g2t#T) zJz|rE!I_?i4dCJC=B8(_pZ{YR>|V?0iCcnU;E@$239^x?SYCfNaMHN;CtHIS_zHN9 zTkQc1v@O35okiFtq5_u+5FkY55ap@pi)O?}x0D1c*qB0KpYR}>Ul+B0Vmr}Z@+%mJ|As}sis_=ROPbov@*2thpE&?!V#Qgu$snYvCZ zrkhmkMU+fSf-s8(L37fPr&M*jRs{{THb!aXQu|P9l_-vJhHvLzMGH zE?1U0H_+PmNABp9`|KzkGfrrZ%XvdGo6*<{d5m9~L7 z_^`M;X6xDo=m6LY6RfvJEvsTK1!u8d2HPx|$S}p;sRy!I zWL55Yxu~_B`OP@~(q6&W3#)~I&+MGL%GWR$#udC151^wsswhqlii;rP9jJpiI7o&Z zAb})=HY7?4HA|re3ns`%$)FuvKCFWjhb~?IE)F6dF2K5}poj-NK6Gf;hw$t3=1txY zoxQxZWrQU6K!%|~!m?~Bnw-6Rr!F3BZ{u5!LqnZTDON}Coj9^@&le)V!NYrVwS~B% zEL+>Sr@}qGwGvu|HrOo|gSt__ezN^&%~{*)a=rf7y1HujUcr`zZB<4#l@T#eN)si} z)lZA<{=tKx8E%c9>A(##6}_p+~EZpKsl5a4pj`E*;_-6`ysiv zffA!7=MT1vCz}-m4~tjVey1b2KSR4OEtLd-(_DdUqYZ74LaDkhH?KFh?%WAOP2WbX zp@zT+Dx|5_f%JQiAGvVw!oh+g3e50u!aPfMxdC=E)XB{F5IcEZhePIM- zph6Y`$Oy?JBL<8Ex(SqEhLeQ@XcrdA>a?rx+_~HLA;l14)WmmpH}_w?Pg#HBZs0eS zwypwAW?M-x+3AU-(GGWSJ=ngxUEcEZ5OsX(Qlt!MQ zn^(`S{GHkAv(8@D`EAfSYig%Cxv?z!{=w^F#y)5_d7FuKZH7qlR-#5B0bt806%D0I zT7VdVP_?q*%Rq8UR;JkD4i^RXowt+E%#V2U>TfDqzZSDZ+dR!a#T3I>-z_$q9@k|m zy5~A*m~&JWP@E7a=pc}4kVHTc4h&R;Li7d@f`|hKMLkbb^uhOakNr3&FLjlm~i5NBM< zFaYI{;cpiHCNRdE0dg*>qIm(_t?#$h=(SCw?h3rJV2*ER8{O4^3#=dO)KwklZkoqU zS8i5c%YL*y*4;FY#D=XmkQnYj%LH)?02~gSJH`Qp1XY64g>%c_K$xseI&|e)7vRoL zAqRba$G@%fSGA7X7hQk%_3NVOYVS+$leU_!&6*5uN)8#5ZBz_6ASCA;azYS-Rt@ki zg2NWz(=;t}SC(~Ibl63$5C8FPmhXqb^)5#jaJ~I{Ex3xZ!+2h8$}}h_g@Be>HZ;72 z6#y#>AY3^skuVKF#0WxFBQ()5d5_nWb?c6c>EeMM|Mh+*&wEpPyxHCq{R-Gdr-`hN zF=1sxl&mBoK+#qRLl9#CEN|Fg8>nbmsTg3a1;#M9enQ$RgWk}kp#-5wh=EF&1tl%mJln2V^8o%Qv(*=zEuO7y z=m*8?xpUn-*@h5Cl_3BK3joiGkyaScK+>|MWdMRWm@RT!Q1piAlv5hL@B6>3&GI8) zP!xBc6}ZNIpJLL%2a8Y!+(<=f%WX>_uWVxlga9!D*oYt$l0cxRDMvqfU;Kq_mLK5k z)dvqYcgLa_Lz?3HyeF)@$%$&6lI?r4I>6W#M*<)vq{?&Oqrx``d`mhpVPr> z#q078F6gw_X<=?KR>8%^t%@wbITvNMu!hKiTSkCTJkw>1!e*Y{%31#_yMf=LW7{RJ zYoC^w$6%3cBtVG5)x#{Hg6IVTh9XEcM{gQwXk!R^y95^f-hZ`d{aVa+xW1EO4wDV4 zB?JgD7*?qkvc|$nIykTvNl2x0j3Q!MXoLL^)~}d7jcYf(H8D~c+?$pKL(px>Z3`eb z04RzS6_AgFT6Pn#iZAg$Sl_j8#;6ShF%&(Fag#E2asU@@LaN;=b=Wf7sgPKhfzhBM zC@eFL8^MrnA*9&Khe*Ab@CC9*uyJGXyi(;y2>lQLJZt;ShtJi?3Yf_t`F+$hY!+Q2Ndsx=U+bjTiAy7djLji>7k%k`$9&--f<*BNA3Hy&ZrHH|4 zG5H&9cB?O#zI1_OOf0Ce%mDfQxdtp3vU%(iY6yji3iISS61XLv#z|!zI_sZqza@B+ zyu9st5-h+`H7QUKx9}3w@oU@EO}&cEzG?fu!!bLO->%zkcg;i9^j`S~=WKMnDi1f= P00000NkvXXu0mjft=yBf literal 0 HcmV?d00001 diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg new file mode 100644 index 00000000..6c87de9b --- /dev/null +++ b/client/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/assets/vite.svg b/client/src/assets/vite.svg new file mode 100644 index 00000000..5101b674 --- /dev/null +++ b/client/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/client/src/index.css b/client/src/index.css new file mode 100644 index 00000000..c0bbb089 --- /dev/null +++ b/client/src/index.css @@ -0,0 +1,10 @@ +body { + margin: 0; + padding: 0; + background-color: #f0f2f5; + color: #1c1e21; +} + +* { + box-sizing: border-box; +} diff --git a/client/src/main.tsx b/client/src/main.tsx new file mode 100644 index 00000000..bef5202a --- /dev/null +++ b/client/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/client/src/pages/Dashboard.tsx b/client/src/pages/Dashboard.tsx new file mode 100644 index 00000000..0c8a0cb8 --- /dev/null +++ b/client/src/pages/Dashboard.tsx @@ -0,0 +1,129 @@ +import { useEffect, useState } from 'react' + +export default function Dashboard() { + const [setup, setSetup] = useState(null) + const [state, setState] = useState(null) + const [watchlist, setWatchlist] = useState([]) + const [running, setRunning] = useState(false) + + const fetchData = () => { + fetch('/api/setupcheck').then(r => r.json()).then(setSetup) + fetch('/api/state').then(r => r.json()).then(setState) + fetch('/api/watchlist').then(r => r.json()).then(setWatchlist) + } + + useEffect(() => { + fetchData() + const interval = setInterval(fetchData, 10000) + return () => clearInterval(interval) + }, []) + + const triggerRun = async () => { + setRunning(true) + try { + await fetch('/api/run', { method: 'POST' }) + // Poll for state change + setTimeout(fetchData, 2000) + } finally { + setRunning(false) + } + } + + return ( +
+ {/* Setup Check */} + {setup && ( +
+

Setup Status {setup.ready ? 'βœ… Ready' : '⚠️ Not Ready'}

+
+ {Object.entries(setup.checks).map(([k, v]) => ( +
+ {v ? 'βœ…' : '❌'} {k.replace(/([A-Z])/g, ' $1')} +
+ ))} +
+
+ )} + + {/* Agent Status */} + {state && ( +
+

Agent Status

+
+
+

Status: {state.status.toUpperCase()} | Cycles run: {state.cycleCount}

+

Last run: {state.lastRunAt ? new Date(state.lastRunAt).toLocaleString() : 'Never'}

+

Next run: {state.nextRunAt ? new Date(state.nextRunAt).toLocaleString() : 'Unknown'}

+
+ +
+
+ )} + + {/* Top Scored Tokens */} +

Market Intelligence: Scored Tokens ({watchlist.length})

+ {watchlist.length > 0 ? ( + + + + {['Token', 'Price', 'Conviction', 'Timing', 'Whale Acc.', 'Narrative'].map(h => ( + + ))} + + + + {watchlist.slice(0, 15).map((t: any, i: number) => ( + + + + + + + + + ))} + +
{h}
+
{t.symbol}
+
{t.name}
+
${t.price?.toFixed(4)} + + + + {t.whaleAccumulationCount || 0}{t.hasNarrativeMomentum ? 'πŸ”₯' : 'β€”'}
+ ) : ( +
+ No data available. Run a cycle to discover and score tokens. +
+ )} +
+ ) +} + +function ScoreBar({ value, threshold }: { value: number; threshold: number }) { + if (value === undefined) return β€” + const passed = value >= threshold + return ( +
+
+
+
+ {value} +
+ ) +} diff --git a/client/src/pages/Journal.tsx b/client/src/pages/Journal.tsx new file mode 100644 index 00000000..287c0814 --- /dev/null +++ b/client/src/pages/Journal.tsx @@ -0,0 +1,66 @@ +import { useEffect, useState } from 'react' + +export default function Journal() { + const [entries, setEntries] = useState([]) + + useEffect(() => { + fetch('/api/journal').then(r => r.json()).then(data => { + setEntries([...data].sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())) + }) + }, []) + + return ( +
+

Trading Journal

+ {entries.length > 0 ? ( + + + + {['Date', 'Token', 'Amount', 'Scores', 'Status', 'Hash/Error'].map(h => ( + + ))} + + + + {entries.map((e: any, i: number) => ( + + + + + + + + + ))} + +
{h}
+ {new Date(e.timestamp).toLocaleString()} + +
{e.token}
+
${e.amount} +
C: {e.convictionScore} | T: {e.timingScore}
+
+ {e.dryRun ? ( + DRY RUN + ) : e.executed ? ( + SUCCESS + ) : ( + FAILED + )} + + {e.txHash ? ( + + {e.txHash.slice(0, 10)}... + + ) : ( + {e.error || 'β€”'} + )} +
+ ) : ( +
+ No journal entries yet. +
+ )} +
+ ) +} diff --git a/client/src/pages/Settings.tsx b/client/src/pages/Settings.tsx new file mode 100644 index 00000000..a5db27b3 --- /dev/null +++ b/client/src/pages/Settings.tsx @@ -0,0 +1,105 @@ +import { useEffect, useState } from 'react' + +export default function Settings() { + const [users, setUsers] = useState([]) + const [loading, setLoading] = useState(false) + + useEffect(() => { + fetch('/api/users').then(r => r.json()).then(setUsers) + }, []) + + const addUser = async (e: any) => { + e.preventDefault() + const form = e.target + const address = form.address.value + const name = form.name.value + + setLoading(true) + try { + const res = await fetch('/api/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ address, name }) + }) + if (res.ok) { + const newUser = await res.json() + setUsers([...users, newUser]) + form.reset() + } else { + const err = await res.json() + alert(err.error) + } + } finally { + setLoading(false) + } + } + + const toggleUser = async (user: any) => { + const res = await fetch(`/api/users/${user.id}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ active: !user.active }) + }) + if (res.ok) { + const updated = await res.json() + setUsers(users.map(u => u.id === updated.id ? updated : u)) + } + } + + return ( +
+

Agent Settings

+ +
+

Add Target Wallet

+

+ Add a wallet address you want the agent to monitor and potentially trade for. + The operator wallet will execute trades using its own funds. +

+
+ + + +
+
+ +

Active Monitor List

+ {users.length > 0 ? ( +
+ {users.map(u => ( +
+
+
{u.name}
+
{u.address.slice(0, 6)}...{u.address.slice(-4)}
+
+ + Limit: ${u.policy.dailyLimit}/day + +
+
+ +
+ ))} +
+ ) : ( +
No wallets configured.
+ )} +
+ ) +} diff --git a/client/tsconfig.app.json b/client/tsconfig.app.json new file mode 100644 index 00000000..7f42e5f7 --- /dev/null +++ b/client/tsconfig.app.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023", "DOM"], + "module": "esnext", + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 00000000..1ffef600 --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/client/tsconfig.node.json b/client/tsconfig.node.json new file mode 100644 index 00000000..d3c52ea6 --- /dev/null +++ b/client/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023"], + "module": "esnext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/client/vite.config.ts b/client/vite.config.ts new file mode 100644 index 00000000..9903f999 --- /dev/null +++ b/client/vite.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import { fileURLToPath } from 'url' +import { dirname, resolve } from 'path' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +// https://vitejs.dev/config/ +export default defineConfig({ + root: __dirname, + plugins: [react()], + build: { + outDir: resolve(__dirname, '../client/dist'), + emptyOutDir: true, + }, + server: { + proxy: { + '/api': { + target: 'http://localhost:3000', + changeOrigin: true, + } + } + } +}) diff --git a/dist/agent/executor.js b/dist/agent/executor.js new file mode 100644 index 00000000..9724ea77 --- /dev/null +++ b/dist/agent/executor.js @@ -0,0 +1,43 @@ +// app/agent/executor.ts +import { executeSwap } from '../api/zerion'; +import { saveJournalEntry } from '../utils/storage'; +import { logger } from '../utils/logger'; +const DRY_RUN = process.env.EXECUTE_TRADES !== 'true'; +export async function executeTrade(user, token) { + const amount = user.policy.tradeSize; + const entryId = `trade_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`; + const entry = { + id: entryId, + userId: user.id, + timestamp: new Date().toISOString(), + token: token.symbol, + tokenAddress: token.address, + convictionScore: token.convictionScore, + timingScore: token.timingScore, + amount, + executed: false, + dryRun: DRY_RUN, + }; + if (DRY_RUN) { + logger.info(`[Executor] πŸ”΅ DRY RUN β€” would buy $${amount} of ${token.symbol} | conviction:${token.convictionScore} timing:${token.timingScore}`); + saveJournalEntry(entry); + return; + } + try { + logger.info(`[Executor] 🟑 Executing swap: $${amount} USDC β†’ ${token.symbol}`); + const result = await executeSwap({ + fromToken: 'USDC', + toToken: token.address, + amount: amount.toString(), + chain: 'base', + }); + entry.executed = true; + entry.txHash = result?.data?.hash || result?.tx_hash; + logger.info(`[Executor] βœ… Success | tx: ${entry.txHash}`); + } + catch (err) { + entry.error = err.message; + logger.error(`[Executor] ❌ Trade failed for ${token.symbol}: ${err.message}`); + } + saveJournalEntry(entry); +} diff --git a/dist/agent/filter.js b/dist/agent/filter.js new file mode 100644 index 00000000..91c99a44 --- /dev/null +++ b/dist/agent/filter.js @@ -0,0 +1,32 @@ +import { logger } from '../utils/logger'; +const STABLECOINS = new Set(['USDC', 'USDT', 'DAI', 'BUSD', 'FRAX', 'LUSD', 'USDD', 'TUSD']); +const MIN_MARKET_CAP = 100_000_000; // $100M +const MIN_LIQUIDITY = 500_000; // $500K +const MAX_24H_PUMP = 0.30; // >30% gain in 24h = suspicious +const MIN_VOLUME_24H = 100_000; // $100K minimum volume +export function hardFilter(tokens) { + return tokens.filter(token => { + if (STABLECOINS.has(token.symbol.toUpperCase())) { + logger.info(`[Filter] ❌ ${token.symbol} β€” stablecoin`); + return false; + } + if (token.marketCap > 0 && token.marketCap < MIN_MARKET_CAP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” market cap too low ($${token.marketCap.toLocaleString()})`); + return false; + } + if (token.liquidity > 0 && token.liquidity < MIN_LIQUIDITY) { + logger.info(`[Filter] ❌ ${token.symbol} β€” liquidity too low ($${token.liquidity.toLocaleString()})`); + return false; + } + if (token.priceChange24h > MAX_24H_PUMP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” suspicious 24h pump (${(token.priceChange24h * 100).toFixed(1)}%)`); + return false; + } + if (token.volume24h > 0 && token.volume24h < MIN_VOLUME_24H) { + logger.info(`[Filter] ❌ ${token.symbol} β€” volume too low`); + return false; + } + logger.info(`[Filter] βœ… ${token.symbol} β€” passed`); + return true; + }); +} diff --git a/dist/agent/loop.js b/dist/agent/loop.js new file mode 100644 index 00000000..5710c4fc --- /dev/null +++ b/dist/agent/loop.js @@ -0,0 +1,74 @@ +// app/agent/loop.ts +import { discoverWatchlist } from './watchlist'; +import { hardFilter } from './filter'; +import { scoreToken } from './scorer'; +import { checkUserPolicy } from './policy'; +import { executeTrade } from './executor'; +import { loadUsers, loadAgentState, saveAgentState } from '../utils/storage'; +import { logger } from '../utils/logger'; +// Thresholds +const CONVICTION_THRESHOLD = 60; +const TIMING_THRESHOLD = 55; +export async function runAgentCycle() { + const state = loadAgentState(); + state.status = 'running'; + state.lastRunAt = new Date().toISOString(); + saveAgentState(state); + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + logger.info('[Cycle] Starting agent cycle...'); + try { + // Step 1: Discover tokens + const rawTokens = await discoverWatchlist(); + logger.info(`[Cycle] Step 1 β€” Discovered ${rawTokens.length} tokens`); + // Step 2: Hard filter + const filtered = hardFilter(rawTokens); + logger.info(`[Cycle] Step 2 β€” ${filtered.length} tokens passed hard filter`); + // Step 3: Score all tokens (parallel with rate limit) + const scored = []; + for (const token of filtered) { + try { + const s = await scoreToken(token); + scored.push(s); + } + catch (err) { + logger.warn(`[Cycle] Failed to score ${token.symbol}: ${err}`); + } + } + // Dual gate filter + const qualified = scored.filter(t => t.convictionScore >= CONVICTION_THRESHOLD && t.timingScore >= TIMING_THRESHOLD); + logger.info(`[Cycle] Step 3 β€” ${qualified.length} tokens passed dual gate (convictionβ‰₯${CONVICTION_THRESHOLD}, timingβ‰₯${TIMING_THRESHOLD})`); + // Update state + state.watchlistSize = rawTokens.length; + state.lastWatchlist = rawTokens; + state.lastScored = scored.sort((a, b) => (b.convictionScore + b.timingScore) - (a.convictionScore + a.timingScore)); + if (qualified.length === 0) { + logger.info('[Cycle] No tokens qualified β€” no trades this cycle'); + } + else { + // Step 4 & 5: Per-user policy check + execution + const users = loadUsers().filter(u => u.active); + logger.info(`[Cycle] Step 4/5 β€” Checking ${users.length} active users against ${qualified.length} qualified tokens`); + for (const user of users) { + const policy = checkUserPolicy(user); + if (!policy.ok) { + logger.info(`[Cycle] User ${user.name} blocked: ${policy.reason}`); + continue; + } + // Execute top qualifying token per cycle per user + const top = qualified[0]; + await executeTrade(user, top); + } + } + state.status = 'idle'; + state.cycleCount = (state.cycleCount || 0) + 1; + state.nextRunAt = new Date(Date.now() + 60 * 60 * 1000).toISOString(); + } + catch (err) { + state.status = 'error'; + state.lastError = err.message; + logger.error(`[Cycle] Fatal error: ${err.message}`); + } + saveAgentState(state); + logger.info('[Cycle] Complete'); + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); +} diff --git a/dist/agent/policy.js b/dist/agent/policy.js new file mode 100644 index 00000000..2a6687e3 --- /dev/null +++ b/dist/agent/policy.js @@ -0,0 +1,37 @@ +import { loadJournalForUser } from '../utils/storage'; +export function checkUserPolicy(user) { + const policy = user.policy; + const now = Date.now(); + const journal = loadJournalForUser(user.id); + const today = new Date().toDateString(); + // Daily spend + const todaySpend = journal + .filter(e => new Date(e.timestamp).toDateString() === today) + .reduce((sum, e) => sum + e.amount, 0); + if (todaySpend + policy.tradeSize > policy.dailyLimit) { + return { ok: false, reason: `Daily limit $${policy.dailyLimit} reached (spent $${todaySpend.toFixed(2)})` }; + } + // Weekly spend + const weekAgo = now - 7 * 24 * 60 * 60 * 1000; + const weekSpend = journal + .filter(e => new Date(e.timestamp).getTime() > weekAgo) + .reduce((sum, e) => sum + e.amount, 0); + if (weekSpend + policy.tradeSize > policy.weeklyLimit) { + return { ok: false, reason: `Weekly limit $${policy.weeklyLimit} reached` }; + } + // Max trades per day + const todayTrades = journal.filter(e => new Date(e.timestamp).toDateString() === today).length; + if (todayTrades >= policy.maxTradesPerDay) { + return { ok: false, reason: `Max ${policy.maxTradesPerDay} trades/day reached` }; + } + // Cooldown + const lastTrade = [...journal].sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())[0]; + if (lastTrade) { + const elapsed = now - new Date(lastTrade.timestamp).getTime(); + if (elapsed < policy.cooldownMs) { + const remaining = Math.ceil((policy.cooldownMs - elapsed) / 60000); + return { ok: false, reason: `Cooldown active β€” ${remaining}m remaining` }; + } + } + return { ok: true }; +} diff --git a/dist/agent/scorer.js b/dist/agent/scorer.js new file mode 100644 index 00000000..cbece0b8 --- /dev/null +++ b/dist/agent/scorer.js @@ -0,0 +1,125 @@ +import { getWhaleAccumulationCount } from './whale'; +import { getOHLCV } from '../api/coingecko'; +// ── Technical Calculations ────────────────────────────────── +function calcSMA(prices, period) { + if (prices.length < period) + return 0; + const slice = prices.slice(-period); + return slice.reduce((a, b) => a + b, 0) / period; +} +function calcStdDev(values) { + if (values.length < 2) + return 0; + const mean = values.reduce((a, b) => a + b, 0) / values.length; + const variance = values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length; + return Math.sqrt(variance); +} +function calcRSI(closes, period = 14) { + if (closes.length < period + 1) + return 50; + let gains = 0, losses = 0; + for (let i = closes.length - period; i < closes.length; i++) { + const diff = closes[i] - closes[i - 1]; + if (diff > 0) + gains += diff; + else + losses += Math.abs(diff); + } + if (losses === 0) + return 100; + const rs = gains / losses; + return 100 - (100 / (1 + rs)); +} +// ── Gate A: Conviction (0-100) ────────────────────────────── +// Is this token fundamentally worth buying? +export function scoreConviction(token, technicals) { + let score = 0; + // 1. Volume Consistency (25 pts) β€” consecutive days of growth + const vols = technicals.volumeHistory; + let streak = 0; + if (vols.length > 1) { + for (let i = vols.length - 1; i > 0; i--) { + if (vols[i] > vols[i - 1]) + streak++; + else + break; + } + } + const volScore = Math.min(25, streak * 5); + score += volScore; + // 2. Price Trend (25 pts) β€” above 7d and 14d MAs + if (token.price > technicals.ma7d && technicals.ma7d > 0) + score += 12; + if (token.price > technicals.ma14d && technicals.ma14d > 0) + score += 13; + // 3. Wallet Allocation (25 pts) β€” rewarded for not already owning + // (In managed-wallet mode, we always score this as 25 since we control the wallet) + score += 25; + // 4. Volatility Penalty (25 pts) β€” penalise erratic swings + const stdDevNorm = Math.min(1, technicals.stdDev / token.price); + const volPenalty = Math.floor(stdDevNorm * 100); + score += Math.max(0, 25 - volPenalty); + // 5. Whale Bonus (15 pts) β€” at least 2 whales accumulating + if ((token.whaleAccumulationCount || 0) >= 2) + score += 15; + // 6. Narrative Bonus (10 pts) + if (token.hasNarrativeMomentum) + score += 10; + return Math.min(100, score); +} +// ── Gate B: Timing (0-100) ────────────────────────────────── +// Is NOW the right time to buy? +export function scoreTiming(token, rsi) { + let score = 0; + // 1. RSI (40 pts) β€” reward oversold + if (rsi < 25) + score += 40; + else if (rsi < 35) + score += 30; + else if (rsi < 45) + score += 15; + else if (rsi < 55) + score += 5; + // 2. Price vs 24h High (30 pts) β€” reward retracement from peak + const retracement = token.high24h > 0 + ? 1 - (token.price / token.high24h) + : 0; + score += Math.min(30, Math.floor(retracement * 150)); + // 3. Volume-Price Divergence (30 pts) β€” volume spike without price spike + const volumeChange = token.volumeChange24h || 0; + const priceChange = token.priceChange24h || 0; + const divergence = volumeChange - priceChange; + if (divergence > 0.5) + score += 30; + else if (divergence > 0.2) + score += 15; + else if (divergence > 0) + score += 5; + return Math.min(100, score); +} +// ── Full Token Scoring Pipeline ───────────────────────────── +export async function scoreToken(token) { + // Fetch OHLCV for technical calculations + let ma7d = 0, ma14d = 0, stdDev = 0, rsi = 50; + let volumeHistory = []; + try { + if (token.cgId) { + const ohlcv = await getOHLCV(token.cgId, 14); + // ohlcv = [[timestamp, open, high, low, close], ...] + const closes = ohlcv.map((c) => c[4]); + const volumes = ohlcv.map((c) => c[1]); // use open as proxy if no vol + ma7d = calcSMA(closes, 7); + ma14d = calcSMA(closes, 14); + stdDev = calcStdDev(closes.slice(-7)); + rsi = calcRSI(closes); + volumeHistory = volumes; + } + } + catch { /* use defaults */ } + // Whale check + const whaleCount = await getWhaleAccumulationCount(token.address).catch(() => 0); + const enriched = { ...token, ma7d, ma14d, stdDev7d: stdDev, rsi14: rsi, whaleAccumulationCount: whaleCount, volumeHistory }; + const convictionScore = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }); + const timingScore = scoreTiming(enriched, rsi); + return { ...enriched, convictionScore, timingScore }; +} diff --git a/dist/agent/watchlist.js b/dist/agent/watchlist.js new file mode 100644 index 00000000..f79e9713 --- /dev/null +++ b/dist/agent/watchlist.js @@ -0,0 +1,52 @@ +// app/agent/watchlist.ts +import { getTopBaseTokens, getTrendingTokens } from '../api/coingecko'; +import { searchDexTokens, extractPairMetrics } from '../api/dexscreener'; +import { getMomentumPicks } from '../api/gemini'; +import { cache } from '../utils/cache'; +export async function discoverWatchlist() { + const cached = cache.get('watchlist'); + if (cached) + return cached; + // Fetch from all 3 sources in parallel + const [cgTopResult, cgTrendingResult] = await Promise.allSettled([ + getTopBaseTokens(50), + getTrendingTokens(), + ]); + const cgTop = cgTopResult.status === 'fulfilled' ? cgTopResult.value : []; + // Trending tokens from CG are a bit different, but let's stick to the top ones for now as per plan + // If we wanted to include trending: const cgTrending = cgTrendingResult.status === 'fulfilled' ? cgTrendingResult.value : [] + // Normalise CoinGecko tokens + const fromCG = Array.isArray(cgTop) ? cgTop.map((t) => ({ + symbol: t.symbol?.toUpperCase(), + name: t.name, + address: t.contract_address || t.id, + price: t.current_price || 0, + marketCap: t.market_cap || 0, + liquidity: 0, // enriched below from DexScreener + volume24h: t.total_volume || 0, + priceChange24h: (t.price_change_percentage_24h || 0) / 100, + high24h: t.high_24h || 0, + low24h: t.low_24h || 0, + cgId: t.id, + })) : []; + // Enrich with DexScreener data for liquidity + real-time price + const enriched = await Promise.all(fromCG.slice(0, 20).map(async (token) => { + try { + const pairs = await searchDexTokens(token.symbol); + if (pairs.length > 0) { + const metrics = extractPairMetrics(pairs[0]); + return { ...token, ...metrics, symbol: token.symbol }; + } + } + catch { /* use CG data only */ } + return token; + })); + // Get Gemini AI narrative momentum picks + const momentumPicks = await getMomentumPicks(enriched.map(t => ({ symbol: t.symbol, name: t.name }))).catch(() => []); + const result = enriched.map(t => ({ + ...t, + hasNarrativeMomentum: momentumPicks.includes(t.symbol), + })); + cache.set('watchlist', result, 300); // cache 5 minutes + return result; +} diff --git a/dist/agent/whale.js b/dist/agent/whale.js new file mode 100644 index 00000000..cc75ce48 --- /dev/null +++ b/dist/agent/whale.js @@ -0,0 +1,42 @@ +// app/agent/whale.ts +import { getTransactions } from '../api/zerion'; +import { cache } from '../utils/cache'; +import { logger } from '../utils/logger'; +// Default whale wallets β€” expand this list +const DEFAULT_WHALE_WALLETS = [ + '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', // vitalik (example) + // add more high-conviction Base traders here +]; +export async function getWhaleAccumulationCount(tokenAddress, extraWhales = []) { + const whales = [...new Set([...DEFAULT_WHALE_WALLETS, ...extraWhales])]; + const SIX_HOURS_MS = 6 * 60 * 60 * 1000; + const since = Date.now() - SIX_HOURS_MS; + let count = 0; + for (const whale of whales) { + const cacheKey = `whale:${whale}:${tokenAddress}`; + const cached = cache.get(cacheKey); + if (cached !== null) { + if (cached) + count++; + continue; + } + try { + const data = await getTransactions(whale, 20, 'base'); + const txs = data?.data || []; + const accumulated = txs.some((tx) => { + const ts = new Date(tx.attributes?.mined_at).getTime(); + const isRecent = ts > since; + const isReceive = tx.attributes?.operation_type === 'receive'; + const hasToken = tx.attributes?.transfers?.some((t) => t.fungible_info?.implementations?.some((i) => i.address?.toLowerCase() === tokenAddress.toLowerCase())); + return isRecent && isReceive && hasToken; + }); + cache.set(cacheKey, accumulated, 600); // cache 10 min + if (accumulated) + count++; + } + catch (err) { + logger.warn(`[Whale] Failed to check ${whale}: ${err}`); + } + } + return count; +} diff --git a/dist/api/coingecko.js b/dist/api/coingecko.js new file mode 100644 index 00000000..97bb1a70 --- /dev/null +++ b/dist/api/coingecko.js @@ -0,0 +1,25 @@ +// app/api/coingecko.ts +const BASE = 'https://api.coingecko.com/api/v3'; +function cgParams(extra = '') { + const key = process.env.COINGECKO_API_KEY; + const auth = key ? `x_cg_demo_api_key=${key}` : ''; + const sep = extra && auth ? '&' : ''; + return extra || auth ? `?${extra}${sep}${auth}` : ''; +} +export async function getTopBaseTokens(limit = 50) { + const res = await fetch(`${BASE}/coins/markets${cgParams(`vs_currency=usd&category=base-ecosystem&order=volume_desc&per_page=${limit}&sparkline=true`)}`); + return res.json(); // returns array of tokens +} +export async function getTrendingTokens() { + const res = await fetch(`${BASE}/search/trending${cgParams()}`); + const data = await res.json(); + return data.coins?.map((c) => c.item) || []; +} +export async function getOHLCV(tokenId, days = 14) { + const res = await fetch(`${BASE}/coins/${tokenId}/ohlc${cgParams(`vs_currency=usd&days=${days}`)}`); + return res.json(); // [[timestamp, open, high, low, close], ...] +} +export async function getTokenMarketData(tokenId) { + const res = await fetch(`${BASE}/coins/${tokenId}${cgParams('localization=false&tickers=false&community_data=true&developer_data=false')}`); + return res.json(); +} diff --git a/dist/api/dexscreener.js b/dist/api/dexscreener.js new file mode 100644 index 00000000..c61b40ed --- /dev/null +++ b/dist/api/dexscreener.js @@ -0,0 +1,31 @@ +// app/api/dexscreener.ts +// DexScreener is FREE β€” no API key needed +const BASE = 'https://api.dexscreener.com/latest'; +export async function getTokenPairsOnBase(tokenAddress) { + const res = await fetch(`${BASE}/dex/tokens/${tokenAddress}`); + const data = await res.json(); + // Filter to Base chain pairs only + return (data.pairs || []).filter((p) => p.chainId === 'base'); +} +export async function searchDexTokens(query) { + const res = await fetch(`${BASE}/dex/search?q=${encodeURIComponent(query)}`); + const data = await res.json(); + return (data.pairs || []).filter((p) => p.chainId === 'base'); +} +// Extract useful metrics from a DexScreener pair +export function extractPairMetrics(pair) { + return { + address: pair.baseToken?.address, + symbol: pair.baseToken?.symbol, + name: pair.baseToken?.name, + price: parseFloat(pair.priceUsd || '0'), + liquidity: pair.liquidity?.usd || 0, + volume24h: pair.volume?.h24 || 0, + priceChange24h: pair.priceChange?.h24 || 0, + priceChange6h: pair.priceChange?.h6 || 0, + priceChange1h: pair.priceChange?.h1 || 0, + txCount24h: (pair.txns?.h24?.buys || 0) + (pair.txns?.h24?.sells || 0), + fdv: pair.fdv || 0, + marketCap: pair.marketCap || 0, + }; +} diff --git a/dist/api/gemini.js b/dist/api/gemini.js new file mode 100644 index 00000000..5d968a67 --- /dev/null +++ b/dist/api/gemini.js @@ -0,0 +1,56 @@ +// app/api/gemini.ts +import { GoogleGenerativeAI } from '@google/generative-ai'; +let genAI = null; +function getClient() { + if (!genAI) { + if (!process.env.GEMINI_API_KEY) + throw new Error('GEMINI_API_KEY not set'); + genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); + } + return genAI.getGenerativeModel({ model: 'gemini-1.5-flash' }); +} +// Ask Gemini which tokens have the strongest narrative momentum +export async function getMomentumPicks(tokens) { + const model = getClient(); + const list = tokens.map(t => `${t.symbol} (${t.name})`).join(', '); + const prompt = ` +You are a crypto memecoin analyst focused on Base chain. +Given these tokens: ${list} + +Pick the top 5 with strongest current narrative momentum based on: +- Community excitement and virality potential +- Recent catalysts or news +- Memetic strength and cultural resonance +- DeFi/onchain activity trends + +Reply ONLY with a JSON array of symbols. Example: ["SYMBOL1","SYMBOL2","SYMBOL3"] +No explanation, no markdown, just the JSON array. +`; + const result = await model.generateContent(prompt); + const text = result.response.text().trim(); + try { + return JSON.parse(text); + } + catch { + // Try to extract array from response if it has extra text + const match = text.match(/\[.*\]/); + if (match) + return JSON.parse(match[0]); + return []; + } +} +// Score a single token's narrative strength 0-100 +export async function scoreNarrative(symbol, context) { + const model = getClient(); + const prompt = ` +Score this Base chain token's narrative strength from 0 to 100. +Token: ${symbol} +Context: ${context} + +Score based on: clarity of use case, community excitement, recent momentum, meme potential. +Reply ONLY with a single integer 0-100. Nothing else. +`; + const result = await model.generateContent(prompt); + const score = parseInt(result.response.text().trim()); + return isNaN(score) ? 50 : Math.max(0, Math.min(100, score)); +} diff --git a/dist/api/zerion.js b/dist/api/zerion.js new file mode 100644 index 00000000..c08765d6 --- /dev/null +++ b/dist/api/zerion.js @@ -0,0 +1,79 @@ +// app/api/zerion.ts +// We use fetch directly against Zerion's REST API. +// This is exactly what cli/lib/api/client.js does internally. +const BASE_URL = 'https://api.zerion.io/v1'; +function getAuthHeader() { + const key = process.env.ZERION_API_KEY; + if (!key) + throw new Error('ZERION_API_KEY is not set in .env'); + return `Basic ${Buffer.from(`${key}:`).toString('base64')}`; +} +async function zerionFetch(path) { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 30_000); + try { + const res = await fetch(`${BASE_URL}${path}`, { + headers: { + 'Authorization': getAuthHeader(), + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + signal: controller.signal, + }); + if (res.status === 429) + throw new Error('Zerion rate limit hit β€” slow down requests'); + if (res.status === 401) + throw new Error('Invalid ZERION_API_KEY'); + if (!res.ok) + throw new Error(`Zerion API error ${res.status} on ${path}`); + return res.json(); + } + finally { + clearTimeout(timeout); + } +} +// ── Read endpoints ────────────────────────────────────────── +export async function getPortfolio(address) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/portfolio?currency=usd`); +} +export async function getPositions(address, type = 'all') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/positions?filter[position_types]=${type}¤cy=usd`); +} +export async function getTransactions(address, limit = 20, chain = 'base') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/transactions?filter[chain_ids]=${chain}&page[size]=${limit}`); +} +export async function getPnL(address) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/pnl?currency=usd`); +} +export async function getFungibleInfo(tokenAddress) { + return zerionFetch(`/fungibles/${encodeURIComponent(tokenAddress)}?currency=usd`); +} +// ── Trade execution ───────────────────────────────────────── +export async function executeSwap(params) { + const agentToken = process.env.ZERION_AGENT_TOKEN; + const walletAddress = process.env.MANAGED_EXECUTION_WALLET_ADDRESS; + if (!agentToken) + throw new Error('ZERION_AGENT_TOKEN not set β€” run wallet bootstrap first'); + if (!walletAddress) + throw new Error('MANAGED_EXECUTION_WALLET_ADDRESS not set'); + const res = await fetch(`${BASE_URL}/swap`, { + method: 'POST', + headers: { + 'Authorization': getAuthHeader(), + 'X-Agent-Token': agentToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chain: params.chain || 'base', + from_token: params.from_token || params.fromToken, // Handle both snake and camel case + to_token: params.to_token || params.toToken, + amount: params.amount, + wallet_address: walletAddress, + }), + }); + if (!res.ok) { + const err = await res.text(); + throw new Error(`Swap failed (${res.status}): ${err}`); + } + return res.json(); +} diff --git a/dist/server.js b/dist/server.js new file mode 100644 index 00000000..e766ab05 --- /dev/null +++ b/dist/server.js @@ -0,0 +1,101 @@ +// app/server.ts +import 'dotenv/config'; +import express from 'express'; +import path from 'path'; +import cron from 'node-cron'; +import { runAgentCycle } from './agent/loop'; +import { getPortfolio, getPnL } from './api/zerion'; +import { loadUsers, createUser, saveUsers, loadJournal, loadJournalForUser, loadAgentState, } from './utils/storage'; +const app = express(); +app.use(express.json()); +// Serve React frontend (built) +const clientDist = path.join(process.cwd(), 'client/dist'); +app.use(express.static(clientDist)); +// ── Setup Check ──────────────────────────────────────────── +app.get('/api/setupcheck', (_req, res) => { + const checks = { + zerionApiKey: !!process.env.ZERION_API_KEY, + zerionAgentToken: !!process.env.ZERION_AGENT_TOKEN, + executionWalletName: !!process.env.MANAGED_EXECUTION_WALLET_NAME, + executionWalletAddress: !!process.env.MANAGED_EXECUTION_WALLET_ADDRESS, + geminiKey: !!process.env.GEMINI_API_KEY, + executeTradesEnabled: process.env.EXECUTE_TRADES === 'true', + }; + const ready = checks.zerionApiKey && checks.zerionAgentToken && checks.executionWalletAddress; + res.json({ ready, checks }); +}); +// ── Users ────────────────────────────────────────────────── +app.post('/api/users', (req, res) => { + const { address, name } = req.body; + if (!address || !/^0x[0-9a-fA-F]{40}$/.test(address)) { + return res.status(400).json({ error: 'Valid 0x wallet address required' }); + } + const user = createUser({ address, name: name || 'Anonymous' }); + res.json(user); +}); +app.get('/api/users', (_req, res) => res.json(loadUsers())); +app.patch('/api/users/:id', (req, res) => { + const users = loadUsers(); + const idx = users.findIndex(u => u.id === req.params.id); + if (idx === -1) + return res.status(404).json({ error: 'User not found' }); + users[idx] = { ...users[idx], ...req.body }; + saveUsers(users); + res.json(users[idx]); +}); +// ── Portfolio ────────────────────────────────────────────── +app.get('/api/portfolio/:address', async (req, res) => { + try { + const data = await getPortfolio(req.params.address); + res.json(data); + } + catch (err) { + res.status(500).json({ error: err.message }); + } +}); +app.get('/api/pnl/:address', async (req, res) => { + try { + const data = await getPnL(req.params.address); + res.json(data); + } + catch (err) { + res.status(500).json({ error: err.message }); + } +}); +// ── Journal ──────────────────────────────────────────────── +app.get('/api/journal', (_req, res) => res.json(loadJournal())); +app.get('/api/journal/:userId', (req, res) => res.json(loadJournalForUser(req.params.userId))); +// ── Agent State ──────────────────────────────────────────── +app.get('/api/state', (_req, res) => res.json(loadAgentState())); +// ── Manual Cycle Trigger ─────────────────────────────────── +app.post('/api/run', (_req, res) => { + res.json({ message: 'Cycle triggered' }); + runAgentCycle().catch(console.error); +}); +// ── Watchlist ────────────────────────────────────────────── +app.get('/api/watchlist', (_req, res) => { + const state = loadAgentState(); + res.json(state.lastScored || []); +}); +// ── SPA fallback ─────────────────────────────────────────── +app.get('*', (req, res) => { + if (req.path.startsWith('/api')) + return res.status(404).json({ error: 'Not found' }); + res.sendFile(path.join(clientDist, 'index.html')); +}); +// ── Cron: every 60 minutes ───────────────────────────────── +cron.schedule('0 * * * *', () => { + runAgentCycle().catch(console.error); + console.log(`[Cron] Next run at ${new Date(Date.now() + 3600000).toISOString()}`); +}); +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log(`\nπŸš€ Conviction DCA Agent running at http://localhost:${PORT}`); + console.log(`πŸ“Š Dashboard: http://localhost:${PORT}`); + console.log(`πŸ”§ Setup Check: http://localhost:${PORT}/api/setupcheck`); + console.log(`▢️ Manual Run: POST http://localhost:${PORT}/api/run\n`); + // Run once on startup (dry run only) + if (process.env.RUN_ON_STARTUP === 'true') { + runAgentCycle().catch(console.error); + } +}); diff --git a/dist/types/index.js b/dist/types/index.js new file mode 100644 index 00000000..87fc3304 --- /dev/null +++ b/dist/types/index.js @@ -0,0 +1,2 @@ +// app/types/index.ts +export {}; diff --git a/dist/utils/cache.js b/dist/utils/cache.js new file mode 100644 index 00000000..eb6dd889 --- /dev/null +++ b/dist/utils/cache.js @@ -0,0 +1,20 @@ +// app/utils/cache.ts +// Simple in-memory TTL cache β€” prevents Zerion/CoinGecko rate limits +const store = new Map(); +export const cache = { + get(key) { + const entry = store.get(key); + if (!entry) + return null; + if (Date.now() > entry.expiresAt) { + store.delete(key); + return null; + } + return entry.value; + }, + set(key, value, ttlSeconds = 60) { + store.set(key, { value, expiresAt: Date.now() + ttlSeconds * 1000 }); + }, + has(key) { return this.get(key) !== null; }, + clear() { store.clear(); }, +}; diff --git a/dist/utils/logger.js b/dist/utils/logger.js new file mode 100644 index 00000000..a5377be3 --- /dev/null +++ b/dist/utils/logger.js @@ -0,0 +1,6 @@ +// app/utils/logger.ts +export const logger = { + info: (msg, data) => console.log(`[INFO] ${new Date().toISOString()} ${msg}`, data || ''), + error: (msg, data) => console.error(`[ERROR] ${new Date().toISOString()} ${msg}`, data || ''), + warn: (msg, data) => console.warn(`[WARN] ${new Date().toISOString()} ${msg}`, data || ''), +}; diff --git a/dist/utils/storage.js b/dist/utils/storage.js new file mode 100644 index 00000000..6e06a501 --- /dev/null +++ b/dist/utils/storage.js @@ -0,0 +1,63 @@ +// app/utils/storage.ts +import fs from 'fs'; +import path from 'path'; +const DATA_DIR = path.join(process.cwd(), 'data'); +function ensureDataDir() { + if (!fs.existsSync(DATA_DIR)) + fs.mkdirSync(DATA_DIR, { recursive: true }); +} +function readJSON(filename, fallback) { + ensureDataDir(); + const file = path.join(DATA_DIR, filename); + if (!fs.existsSync(file)) + return fallback; + try { + return JSON.parse(fs.readFileSync(file, 'utf-8')); + } + catch { + return fallback; + } +} +function writeJSON(filename, data) { + ensureDataDir(); + fs.writeFileSync(path.join(DATA_DIR, filename), JSON.stringify(data, null, 2)); +} +// Users +export const loadUsers = () => readJSON('users.json', []); +export const saveUsers = (users) => writeJSON('users.json', users); +export function createUser(data) { + const users = loadUsers(); + const user = { + id: `usr_${Date.now()}`, + name: data.name || 'Anonymous', + address: data.address, + active: true, + createdAt: new Date().toISOString(), + policy: { + dailyLimit: 50, + weeklyLimit: 200, + maxTradesPerDay: 3, + cooldownMs: 60 * 60 * 1000, + tradeSize: 10, + }, + }; + users.push(user); + saveUsers(users); + return user; +} +// Journal +export const loadJournal = () => readJSON('journal.json', []); +export function saveJournalEntry(entry) { + const journal = loadJournal(); + journal.push(entry); + writeJSON('journal.json', journal); +} +export function loadJournalForUser(userId) { + return loadJournal().filter(e => e.userId === userId); +} +// Agent State +export const loadAgentState = () => readJSON('agent-state.json', { + lastRunAt: null, nextRunAt: null, cycleCount: 0, + watchlistSize: 0, lastWatchlist: [], lastScored: [], status: 'idle', +}); +export const saveAgentState = (state) => writeJSON('agent-state.json', state); diff --git a/package-lock.json b/package-lock.json index 23aff8bd..af2e07db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1870 +1,2197 @@ { - "name": "zerion-cli", - "version": "1.1.0", + "name": "conviction-dca-agent", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "zerion-cli", - "version": "1.1.0", + "name": "conviction-dca-agent", + "version": "0.1.0", + "dependencies": { + "@google/generative-ai": "^0.21.0", + "dotenv": "^16.0.0", + "express": "^4.18.0", + "node-cron": "^3.0.0" + }, + "devDependencies": { + "@types/express": "^4.17.0", + "@types/node": "^20.0.0", + "@types/node-cron": "^3.0.0", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "react": "^19.2.6", + "react-dom": "^19.2.6", + "tsx": "^4.0.0", + "typescript": "^5.0.0", + "vite": "^8.0.11" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@open-wallet-standard/core": "^1.2.4", - "@solana/web3.js": "^1.98.4", - "@x402/evm": "^2.6.0", - "@x402/fetch": "^2.6.0", - "@x402/svm": "^2.8.0", - "mppx": "^0.6.2", - "qrcode-terminal": "^0.12.0", - "viem": "^2.0.0" - }, - "bin": { - "zerion": "cli/zerion.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", - "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", - "license": "MIT" - }, - "node_modules/@babel/runtime": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" } }, - "node_modules/@cfworker/json-schema": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", - "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", - "license": "MIT", - "peer": true - }, - "node_modules/@modelcontextprotocol/server": { - "version": "2.0.0-alpha.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/server/-/server-2.0.0-alpha.2.tgz", - "integrity": "sha512-gmLgdHzlYM8L7Aw/+VE0kxjT25WKamtUSLNhdOgrJq5CrESvqVSoAfWSJJeNPUXNTluQ+dYDGFbKVitdsJtbPA==", + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "zod": "^4.0" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - } + "tslib": "^2.4.0" } }, - "node_modules/@modelcontextprotocol/server/node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@noble/ciphers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", - "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18" } }, - "node_modules/@noble/curves": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", - "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">=18" } }, - "node_modules/@open-wallet-standard/core": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@open-wallet-standard/core/-/core-1.3.2.tgz", - "integrity": "sha512-Dk8bB9G5PjJfNzAqJd9WT9OfqrrSXRc3gA9+BCaY2qirlNrCkIAZCHaDIE0LnGOAaoSZizR6qnOFbukj+DTzJg==", + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "bin": { - "ows": "bin/ows" - }, - "optionalDependencies": { - "@open-wallet-standard/core-darwin-arm64": "1.3.2", - "@open-wallet-standard/core-darwin-x64": "1.3.2", - "@open-wallet-standard/core-linux-arm64-gnu": "1.3.2", - "@open-wallet-standard/core-linux-x64-gnu": "1.3.2" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@open-wallet-standard/core-darwin-arm64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-darwin-arm64/-/core-darwin-arm64-1.3.2.tgz", - "integrity": "sha512-rvUsGU8eZtIMYFJ047nFKS79ajJeYCydvvh2B6bX0UUGf2NJZ4wUnxGqijxPiflz2xqzvbHXYZNzy3MIO4+fDQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@open-wallet-standard/core-darwin-x64": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-darwin-x64/-/core-darwin-x64-1.3.2.tgz", - "integrity": "sha512-a6u3CvWZY8sC1S92AMGnO1WFlMW3m38+3/IoKzhxcFvD8rVY0OA0ebH6qzYLT96/TaouXDwmMQV6yQmb1IjfzQ==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@open-wallet-standard/core-linux-arm64-gnu": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.2.tgz", - "integrity": "sha512-wzyd7euZ5qvDr8dHf3eG2XP7iFgMmBUo35U7cWMLs6Yqjqz103SEjtMfNJEedZRb62f8P3Xhp9jdRLzaJvjk5g==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@open-wallet-standard/core-linux-x64-gnu": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.2.tgz", - "integrity": "sha512-pVtyEP8EqR3rjqdBDCRuB9Rd4xs8+11gRVtWidwPeFz5QPq3c9VGZjGQtTZoiZBHCxKaq5pTQjC78J5lVuA0hg==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@scure/bip32": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", - "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@scure/bip39": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", - "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@solana-program/compute-budget": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@solana-program/compute-budget/-/compute-budget-0.11.0.tgz", - "integrity": "sha512-7f1ePqB/eURkTwTOO9TNIdUXZcyrZoX3Uy2hNo7cXMfNhPFWp9AVgIyRNBc2jf15sdUa9gNpW+PfP2iV8AYAaw==", - "license": "Apache-2.0", - "peerDependencies": { - "@solana/kit": "^5.0" + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@solana-program/token": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@solana-program/token/-/token-0.9.0.tgz", - "integrity": "sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA==", - "license": "Apache-2.0", - "peerDependencies": { - "@solana/kit": "^5.0" + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@solana-program/token-2022": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@solana-program/token-2022/-/token-2022-0.6.1.tgz", - "integrity": "sha512-Ex02cruDMGfBMvZZCrggVR45vdQQSI/unHVpt/7HPt/IwFYB4eTlXtO8otYZyqV/ce5GqZ8S6uwyRf0zy6fdbA==", - "license": "Apache-2.0", - "peerDependencies": { - "@solana/kit": "^5.0", - "@solana/sysvars": "^5.0" + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@solana/accounts": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/accounts/-/accounts-5.5.1.tgz", - "integrity": "sha512-TfOY9xixg5rizABuLVuZ9XI2x2tmWUC/OoN556xwfDlhBHBjKfszicYYOyD6nbFmwTGYarCmyGIdteXxTXIdhQ==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/rpc-spec": "5.5.1", - "@solana/rpc-types": "5.5.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/addresses": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/addresses/-/addresses-5.5.1.tgz", - "integrity": "sha512-5xoah3Q9G30HQghu/9BiHLb5pzlPKRC3zydQDmE3O9H//WfayxTFppsUDCL6FjYUHqj/wzK6CWHySglc2RkpdA==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/assertions": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/nominal-types": "5.5.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/assertions": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/assertions/-/assertions-5.5.1.tgz", - "integrity": "sha512-YTCSWAlGwSlVPnWtWLm3ukz81wH4j2YaCveK+TjpvUU88hTy6fmUqxi0+hvAMAe4zKXpJyj3Az7BrLJRxbIm4Q==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/buffer-layout": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", - "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "buffer": "~6.0.3" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=5.10" + "node": ">=18" } }, - "node_modules/@solana/codecs": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-5.5.1.tgz", - "integrity": "sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/codecs-data-structures": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/options": "5.5.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/codecs-core": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-5.5.1.tgz", - "integrity": "sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/codecs-data-structures": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-5.5.1.tgz", - "integrity": "sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/errors": "5.5.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/codecs-numbers": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-5.5.1.tgz", - "integrity": "sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/errors": "5.5.1" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/codecs-strings": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-5.5.1.tgz", - "integrity": "sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/errors": "5.5.1" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "fastestsmallesttextencoderdecoder": "^1.0.22", - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "fastestsmallesttextencoderdecoder": { - "optional": true - }, - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/errors": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-5.5.1.tgz", - "integrity": "sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "chalk": "5.6.2", - "commander": "14.0.2" - }, - "bin": { - "errors": "bin/cli.mjs" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/fast-stable-stringify": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-5.5.1.tgz", - "integrity": "sha512-Ni7s2FN33zTzhTFgRjEbOVFO+UAmK8qi3Iu0/GRFYK4jN696OjKHnboSQH/EacQ+yGqS54bfxf409wU5dsLLCw==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@solana/functional": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/functional/-/functional-5.5.1.tgz", - "integrity": "sha512-tTHoJcEQq3gQx5qsdsDJ0LEJeFzwNpXD80xApW9o/PPoCNimI3SALkZl+zNW8VnxRrV3l3yYvfHWBKe/X3WG3w==", + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" + } + }, + "node_modules/@google/generative-ai": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.21.0.tgz", + "integrity": "sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@solana/instruction-plans": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/instruction-plans/-/instruction-plans-5.5.1.tgz", - "integrity": "sha512-7z3CB7YMcFKuVvgcnNY8bY6IsZ8LG61Iytbz7HpNVGX2u1RthOs1tRW8luTzSG1MPL0Ox7afyAVMYeFqSPHnaQ==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@solana/errors": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/promises": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" + "@tybys/wasm-util": "^0.10.1" }, - "engines": { - "node": ">=20.18.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.128.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.128.0.tgz", + "integrity": "sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@solana/instructions": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/instructions/-/instructions-5.5.1.tgz", - "integrity": "sha512-h0G1CG6S+gUUSt0eo6rOtsaXRBwCq1+Js2a+Ps9Bzk9q7YHNFA75/X0NWugWLgC92waRp66hrjMTiYYnLBoWOQ==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.18.tgz", + "integrity": "sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.18.tgz", + "integrity": "sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.18.tgz", + "integrity": "sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.18.tgz", + "integrity": "sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.18.tgz", + "integrity": "sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.18.tgz", + "integrity": "sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/errors": "5.5.1" + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.18.tgz", + "integrity": "sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.7", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", + "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.40.tgz", + "integrity": "sha512-xxx6M2IpSTnnKcR0cMvIiohkiCx20/oRPtWGbenFygKCGl3zqUzdNjQ/1V4solq1LU+dgv0nQzeGOuqkqZGg0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-cron": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", + "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" } }, - "node_modules/@solana/keys": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/keys/-/keys-5.5.1.tgz", - "integrity": "sha512-KRD61cL7CRL+b4r/eB9dEoVxIf/2EJ1Pm1DmRYhtSUAJD2dJ5Xw8QFuehobOGm9URqQ7gaQl+Fkc1qvDlsWqKg==", + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, "license": "MIT", "dependencies": { - "@solana/assertions": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/nominal-types": "5.5.1" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/node": "*" } }, - "node_modules/@solana/kit": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/kit/-/kit-5.5.1.tgz", - "integrity": "sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ==", + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@solana/accounts": "5.5.1", - "@solana/addresses": "5.5.1", - "@solana/codecs": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/instruction-plans": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/offchain-messages": "5.5.1", - "@solana/plugin-core": "5.5.1", - "@solana/programs": "5.5.1", - "@solana/rpc": "5.5.1", - "@solana/rpc-api": "5.5.1", - "@solana/rpc-parsed-types": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-subscriptions": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/signers": "5.5.1", - "@solana/sysvars": "5.5.1", - "@solana/transaction-confirmation": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" } }, - "node_modules/@solana/nominal-types": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/nominal-types/-/nominal-types-5.5.1.tgz", - "integrity": "sha512-I1ImR+kfrLFxN5z22UDiTWLdRZeKtU0J/pkWkO8qm/8WxveiwdIv4hooi8pb6JnlR4mSrWhq0pCIOxDYrL9GIQ==", + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/@solana/offchain-messages": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/offchain-messages/-/offchain-messages-5.5.1.tgz", - "integrity": "sha512-g+xHH95prTU+KujtbOzj8wn+C7ZNoiLhf3hj6nYq3MTyxOXtBEysguc97jJveUZG0K97aIKG6xVUlMutg5yxhw==", + "node_modules/@vitejs/plugin-react": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", + "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", + "dev": true, "license": "MIT", "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-data-structures": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/nominal-types": "5.5.1" + "@rolldown/pluginutils": "1.0.0-rc.7" }, "engines": { - "node": ">=20.18.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "typescript": "^5.0.0" + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" }, "peerDependenciesMeta": { - "typescript": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { "optional": true } } }, - "node_modules/@solana/options": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/options/-/options-5.5.1.tgz", - "integrity": "sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "@solana/codecs-core": "5.5.1", - "@solana/codecs-data-structures": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@solana/plugin-core": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/plugin-core/-/plugin-core-5.5.1.tgz", - "integrity": "sha512-VUZl30lDQFJeiSyNfzU1EjYt2QZvoBFKEwjn1lilUJw7KgqD5z7mbV7diJhT+dLFs36i0OsjXvq5kSygn8YJ3A==", + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@solana/programs": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/programs/-/programs-5.5.1.tgz", - "integrity": "sha512-7U9kn0Jsx1NuBLn5HRTFYh78MV4XN145Yc3WP/q5BlqAVNlMoU9coG5IUTJIG847TUqC1lRto3Dnpwm6T4YRpA==", - "license": "MIT", + "node_modules/body-parser/node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/errors": "5.5.1" + "side-channel": "^1.1.0" }, "engines": { - "node": ">=20.18.0" + "node": ">=0.6" }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@solana/promises": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/promises/-/promises-5.5.1.tgz", - "integrity": "sha512-T9lfuUYkGykJmppEcssNiCf6yiYQxJkhiLPP+pyAc2z84/7r3UVIb2tNJk4A9sucS66pzJnVHZKcZVGUUp6wzA==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/@solana/rpc": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc/-/rpc-5.5.1.tgz", - "integrity": "sha512-ku8zTUMrkCWci66PRIBC+1mXepEnZH/q1f3ck0kJZ95a06bOTl5KU7HeXWtskkyefzARJ5zvCs54AD5nxjQJ+A==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "@solana/errors": "5.5.1", - "@solana/fast-stable-stringify": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/rpc-api": "5.5.1", - "@solana/rpc-spec": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-transformers": "5.5.1", - "@solana/rpc-transport-http": "5.5.1", - "@solana/rpc-types": "5.5.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@solana/rpc-api": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-api/-/rpc-api-5.5.1.tgz", - "integrity": "sha512-XWOQQPhKl06Vj0xi3RYHAc6oEQd8B82okYJ04K7N0Vvy3J4PN2cxeK7klwkjgavdcN9EVkYCChm2ADAtnztKnA==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/rpc-parsed-types": "5.5.1", - "@solana/rpc-spec": "5.5.1", - "@solana/rpc-transformers": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@solana/rpc-parsed-types": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-parsed-types/-/rpc-parsed-types-5.5.1.tgz", - "integrity": "sha512-HEi3G2nZqGEsa3vX6U0FrXLaqnUCg4SKIUrOe8CezD+cSFbRTOn3rCLrUmJrhVyXlHoQVaRO9mmeovk31jWxJg==", + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "dependencies": { + "safe-buffer": "5.2.1" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">= 0.6" } }, - "node_modules/@solana/rpc-spec": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-spec/-/rpc-spec-5.5.1.tgz", - "integrity": "sha512-m3LX2bChm3E3by4mQrH4YwCAFY57QBzuUSWqlUw7ChuZ+oLLOq7b2czi4i6L4Vna67j3eCmB3e+4tqy1j5wy7Q==", + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1", - "@solana/rpc-spec-types": "5.5.1" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@solana/rpc-spec-types": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-spec-types/-/rpc-spec-types-5.5.1.tgz", - "integrity": "sha512-6OFKtRpIEJQs8Jb2C4OO8KyP2h2Hy1MFhatMAoXA+0Ik8S3H+CicIuMZvGZ91mIu/tXicuOOsNNLu3HAkrakrw==", + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.6" } }, - "node_modules/@solana/rpc-subscriptions": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions/-/rpc-subscriptions-5.5.1.tgz", - "integrity": "sha512-CTMy5bt/6mDh4tc6vUJms9EcuZj3xvK0/xq8IQ90rhkpYvate91RjBP+egvjgSayUg9yucU9vNuUpEjz4spM7w==", + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "@solana/errors": "5.5.1", - "@solana/fast-stable-stringify": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/promises": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-subscriptions-api": "5.5.1", - "@solana/rpc-subscriptions-channel-websocket": "5.5.1", - "@solana/rpc-subscriptions-spec": "5.5.1", - "@solana/rpc-transformers": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/subscribable": "5.5.1" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "ms": "2.0.0" } }, - "node_modules/@solana/rpc-subscriptions-api": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-5.5.1.tgz", - "integrity": "sha512-5Oi7k+GdeS8xR2ly1iuSFkAv6CZqwG0Z6b1QZKbEgxadE1XGSDrhM2cn59l+bqCozUWCqh4c/A2znU/qQjROlw==", + "node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/rpc-subscriptions-spec": "5.5.1", - "@solana/rpc-transformers": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/@solana/rpc-subscriptions-channel-websocket": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-5.5.1.tgz", - "integrity": "sha512-7tGfBBrYY8TrngOyxSHoCU5shy86iA9SRMRrPSyBhEaZRAk6dnbdpmUTez7gtdVo0BCvh9nzQtUycKWSS7PnFQ==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/rpc-subscriptions-spec": "5.5.1", - "@solana/subscribable": "5.5.1", - "ws": "^8.19.0" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@solana/rpc-subscriptions-spec": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-5.5.1.tgz", - "integrity": "sha512-iq+rGq5fMKP3/mKHPNB6MC8IbVW41KGZg83Us/+LE3AWOTWV1WT20KT2iH1F1ik9roi42COv/TpoZZvhKj45XQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1", - "@solana/promises": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/subscribable": "5.5.1" - }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=8" } }, - "node_modules/@solana/rpc-transformers": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-transformers/-/rpc-transformers-5.5.1.tgz", - "integrity": "sha512-OsWqLCQdcrRJKvHiMmwFhp9noNZ4FARuMkHT5us3ustDLXaxOjF0gfqZLnMkulSLcKt7TGXqMhBV+HCo7z5M8Q==", - "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/nominal-types": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "@solana/rpc-types": "5.5.1" - }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", "engines": { - "node": ">=20.18.0" + "node": ">=12" }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@solana/rpc-transport-http": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-transport-http/-/rpc-transport-http-5.5.1.tgz", - "integrity": "sha512-yv8GoVSHqEV0kUJEIhkdOVkR2SvJ6yoWC51cJn2rSV7plr6huLGe0JgujCmB7uZhhaLbcbP3zxXxu9sOjsi7Fg==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "@solana/errors": "5.5.1", - "@solana/rpc-spec": "5.5.1", - "@solana/rpc-spec-types": "5.5.1", - "undici-types": "^7.19.2" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@solana/rpc-types": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-5.5.1.tgz", - "integrity": "sha512-bibTFQ7PbHJJjGJPmfYC2I+/5CRFS4O2p9WwbFraX1Keeel+nRrt/NBXIy8veP5AEn2sVJIyJPpWBRpCx1oATA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/nominal-types": "5.5.1" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/@solana/signers": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/signers/-/signers-5.5.1.tgz", - "integrity": "sha512-FY0IVaBT2kCAze55vEieR6hag4coqcuJ31Aw3hqRH7mv6sV8oqwuJmUrx+uFwOp1gwd5OEAzlv6N4hOOple4sQ==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/nominal-types": "5.5.1", - "@solana/offchain-messages": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@solana/subscribable": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/subscribable/-/subscribable-5.5.1.tgz", - "integrity": "sha512-9K0PsynFq0CsmK1CDi5Y2vUIJpCqkgSS5yfDN0eKPgHqEptLEaia09Kaxc90cSZDZU5mKY/zv1NBmB6Aro9zQQ==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "dependencies": { - "@solana/errors": "5.5.1" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@solana/sysvars": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/sysvars/-/sysvars-5.5.1.tgz", - "integrity": "sha512-k3Quq87Mm+geGUu1GWv6knPk0ALsfY6EKSJGw9xUJDHzY/RkYSBnh0RiOrUhtFm2TDNjOailg8/m0VHmi3reFA==", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", - "peer": true, "dependencies": { - "@solana/accounts": "5.5.1", - "@solana/codecs": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/rpc-types": "5.5.1" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@solana/transaction-confirmation": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/transaction-confirmation/-/transaction-confirmation-5.5.1.tgz", - "integrity": "sha512-j4mKlYPHEyu+OD7MBt3jRoX4ScFgkhZC6H65on4Fux6LMScgivPJlwnKoZMnsgxFgWds0pl+BYzSiALDsXlYtw==", + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/promises": "5.5.1", - "@solana/rpc": "5.5.1", - "@solana/rpc-subscriptions": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/transaction-messages": "5.5.1", - "@solana/transactions": "5.5.1" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=20.18.0" + "node": ">=18" }, - "peerDependencies": { - "typescript": "^5.0.0" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@solana/transaction-messages": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/transaction-messages/-/transaction-messages-5.5.1.tgz", - "integrity": "sha512-aXyhMCEaAp3M/4fP0akwBBQkFPr4pfwoC5CLDq999r/FUwDax2RE/h4Ic7h2Xk+JdcUwsb+rLq85Y52hq84XvQ==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, "license": "MIT", - "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-data-structures": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/nominal-types": "5.5.1", - "@solana/rpc-types": "5.5.1" - }, "engines": { - "node": ">=20.18.0" + "node": ">=12.0.0" }, "peerDependencies": { - "typescript": "^5.0.0" + "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { - "typescript": { + "picomatch": { "optional": true } } }, - "node_modules/@solana/transactions": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/@solana/transactions/-/transactions-5.5.1.tgz", - "integrity": "sha512-8hHtDxtqalZ157pnx6p8k10D7J/KY/biLzfgh9R09VNLLY3Fqi7kJvJCr7M2ik3oRll56pxhraAGCC9yIT6eOA==", + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "dependencies": { - "@solana/addresses": "5.5.1", - "@solana/codecs-core": "5.5.1", - "@solana/codecs-data-structures": "5.5.1", - "@solana/codecs-numbers": "5.5.1", - "@solana/codecs-strings": "5.5.1", - "@solana/errors": "5.5.1", - "@solana/functional": "5.5.1", - "@solana/instructions": "5.5.1", - "@solana/keys": "5.5.1", - "@solana/nominal-types": "5.5.1", - "@solana/rpc-types": "5.5.1", - "@solana/transaction-messages": "5.5.1" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">= 0.8" } }, - "node_modules/@solana/web3.js": { - "version": "1.98.4", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz", - "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.25.0", - "@noble/curves": "^1.4.2", - "@noble/hashes": "^1.4.0", - "@solana/buffer-layout": "^4.0.1", - "@solana/codecs-numbers": "^2.1.0", - "agentkeepalive": "^4.5.0", - "bn.js": "^5.2.1", - "borsh": "^0.7.0", - "bs58": "^4.0.1", - "buffer": "6.0.3", - "fast-stable-stringify": "^1.0.0", - "jayson": "^4.1.1", - "node-fetch": "^2.7.0", - "rpc-websockets": "^9.0.2", - "superstruct": "^2.0.2" - } - }, - "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", - "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", - "dependencies": { - "@solana/errors": "2.3.0" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" + "node": ">= 0.6" } }, - "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", - "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "dependencies": { - "@solana/codecs-core": "2.3.0", - "@solana/errors": "2.3.0" - }, "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" + "node": ">= 0.6" } }, - "node_modules/@solana/web3.js/node_modules/@solana/errors": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", - "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "chalk": "^5.4.1", - "commander": "^14.0.0" - }, - "bin": { - "errors": "bin/cli.mjs" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/@swc/helpers": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", - "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@toon-format/toon": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@toon-format/toon/-/toon-2.1.0.tgz", - "integrity": "sha512-JwWptdF5eOA0HaQxbKAzkpQtR4wSWTEfDlEy/y3/4okmOAX1qwnpLZMmtEWr+ncAhTTY1raCKH0kteHhSXnQqg==", - "license": "MIT" - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "@types/node": "*" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { - "@types/node": "*" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/@x402/core": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@x402/core/-/core-2.11.0.tgz", - "integrity": "sha512-aqTfZc/BULrlWnd3I0lsqRQaH4gjJd8CsPcL16XqK2Lx5c6QDm+zCljgUVS1yj9BGJoZeQWTzI5hE+SVFkqMTw==", - "license": "Apache-2.0", + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", "dependencies": { - "zod": "^3.24.2" + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/@x402/evm": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@x402/evm/-/evm-2.11.0.tgz", - "integrity": "sha512-F8uU1txDZA+wc/sEnmaHAyYvoTi/w39r7K3a44MmQHSxECDTEuB3A0FwbxOxUPLN1eyCxTAFKEiqlGe3bwybKA==", - "license": "Apache-2.0", - "dependencies": { - "@x402/core": "~2.11.0", - "viem": "^2.39.3", - "zod": "^3.24.2" + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@x402/fetch": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@x402/fetch/-/fetch-2.11.0.tgz", - "integrity": "sha512-sDkoq1ZZt10/UVa75bCXTbWkXMbPOOQpkdSxWB0ybHtlmqT7PM6hU4DVCov4iL792W1Oi38VtxfUw5EkvdvYtw==", - "license": "Apache-2.0", - "dependencies": { - "@x402/core": "~2.11.0", - "viem": "^2.39.3", - "zod": "^3.24.2" + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@x402/svm": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@x402/svm/-/svm-2.11.0.tgz", - "integrity": "sha512-MmhLlEeb3FtgTxO4n3RkZszKEBBnYLfNnX8P3TvqVYP1u9gY2SgbYW4K3TsPAv00edCxoCOqYixI2JurYjW4Sw==", - "license": "Apache-2.0", + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", "dependencies": { - "@solana-program/compute-budget": "^0.11.0", - "@solana-program/token": "^0.9.0", - "@solana-program/token-2022": "^0.6.1", - "@x402/core": "~2.11.0" + "function-bind": "^1.1.2" }, - "peerDependencies": { - "@solana/kit": ">=5.1.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/abitype": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.4.tgz", - "integrity": "sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg==", + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3.22.0 || ^4.0.0" + "engines": { + "node": ">= 0.8" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { - "humanize-ms": "^1.2.1" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 8.0.0" + "node": ">=0.10.0" } }, - "node_modules/base-x": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", - "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" + "engines": { + "node": ">= 0.10" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" ], - "license": "MIT" + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/bn.js": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", - "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", - "license": "MIT" + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/borsh": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", - "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", - "license": "Apache-2.0", - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "license": "MIT", - "dependencies": { - "base-x": "^3.0.2" + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/bufferutil": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", - "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", - "hasInstallScript": true, - "license": "MIT", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.14.2" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", - "license": "MIT", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=20" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", - "license": "MIT", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "license": "MIT" + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", - "dependencies": { - "es6-promise": "^4.0.3" + "engines": { + "node": ">= 0.4" } }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { - "node": "> 0.1.90" + "node": ">= 0.6" } }, - "node_modules/fast-stable-stringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", - "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", - "license": "MIT" - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "license": "MIT", - "dependencies": { - "ms": "^2.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/incur": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/incur/-/incur-0.3.25.tgz", - "integrity": "sha512-jrSkzauM42ilbQJ6THVkAY6dTulkyVW0sZpVHdA8gfiBwrLrLnLUf8U3bAOegAKBIMSOFgk1idchgu9xm9HMng==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "license": "MIT", - "dependencies": { - "@cfworker/json-schema": "^4.1.1", - "@modelcontextprotocol/server": "^2.0.0-alpha.2", - "@toon-format/toon": "^2.1.0", - "tokenx": "^1.3.0", - "yaml": "^2.8.2", - "zod": "^4.3.6" - }, "bin": { - "incur": "dist/bin.js", - "incur.src": "src/bin.ts" + "mime": "cli.js" }, "engines": { - "node": ">=22" + "node": ">=4" } }, - "node_modules/incur/node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" + "engines": { + "node": ">= 0.6" } }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", - "peerDependencies": { - "ws": "*" + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/isows": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", - "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/wevm" + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/jayson": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", - "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==", - "license": "MIT", - "dependencies": { - "@types/connect": "^3.4.33", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "stream-json": "^1.9.1", - "uuid": "^8.3.2", - "ws": "^7.5.10" - }, "bin": { - "jayson": "bin/jayson.js" + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=8" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/jayson/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/jayson/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", - "optional": true, - "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "license": "ISC", "dependencies": { - "node-gyp-build": "^4.3.0" + "uuid": "8.3.2" }, "engines": { - "node": ">=6.14.2" + "node": ">=6.0.0" + } + }, + "node_modules/node-cron/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/jayson/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { - "node": ">=8.3.0" + "node": ">= 0.4" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, - "node_modules/mppx": { - "version": "0.6.14", - "resolved": "https://registry.npmjs.org/mppx/-/mppx-0.6.14.tgz", - "integrity": "sha512-sux4amv+pIPR/Wf2znvgnh76DG/gWGAplzLuCvEbaYfGV9aycRrZc3u6vttws/prJmYs7+9qkx+/I4gonNqR8w==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", "dependencies": { - "incur": "^0.3.25", - "ox": "0.14.18", - "zod": "^4.3.6" - }, - "bin": { - "mppx": "dist/bin.js", - "mppx.src": "src/bin.ts" + "ee-first": "1.1.1" }, - "peerDependencies": { - "@modelcontextprotocol/sdk": ">=1.25.0", - "elysia": ">=1", - "express": ">=5", - "hono": ">=4.12.14", - "viem": ">=2.47.5" - }, - "peerDependenciesMeta": { - "@modelcontextprotocol/sdk": { - "optional": true - }, - "elysia": { - "optional": true - }, - "express": { - "optional": true - }, - "hono": { - "optional": true - } + "engines": { + "node": ">= 0.8" } }, - "node_modules/mppx/node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" + "engines": { + "node": ">= 0.8" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/ox": { - "version": "0.14.18", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.18.tgz", - "integrity": "sha512-1Irk/tvMsw7xJDuCTT/u9azSjz0YX9hrYFgJOacIuFwibaW2zZBXAMrpzegndYb5o8GLpxB6/0qro4/c40q6VQ==", + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, { "type": "github", - "url": "https://github.com/sponsors/wevm" + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "^1.11.0", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "1.9.1", - "@noble/hashes": "^1.8.0", - "@scure/bip32": "^1.7.0", - "@scure/bip39": "^1.6.0", - "abitype": "^1.2.3", - "eventemitter3": "5.0.1" - }, - "peerDependencies": { - "typescript": ">=5.4.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^10 || ^12 || >=14" } }, - "node_modules/ox/node_modules/@noble/curves": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", - "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.8.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/qrcode-terminal": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", - "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/rpc-websockets": { - "version": "9.3.8", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.8.tgz", - "integrity": "sha512-7r+fm4tSJmLf9GvZfL1DJ1SJwpagpp6AazqM0FUaeV7CA+7+NYINSk1syWa4tU/6OF2CyBicLtzENGmXRJH6wQ==", - "license": "LGPL-3.0-only", + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.5.11", - "@types/uuid": "^10.0.0", - "@types/ws": "^8.2.2", - "buffer": "^6.0.3", - "eventemitter3": "^5.0.1", - "uuid": "^11.0.0", - "ws": "^8.5.0" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/kozjak" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, - "optionalDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^6.0.0" + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/rpc-websockets/node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/rolldown": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.18.tgz", + "integrity": "sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.128.0", + "@rolldown/pluginutils": "1.0.0-rc.18" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.18", + "@rolldown/binding-darwin-x64": "1.0.0-rc.18", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.18", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.18", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.18", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.18", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.18", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.18", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.18", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.18", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz", + "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1885,279 +2212,340 @@ ], "license": "MIT" }, - "node_modules/stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", - "license": "BSD-3-Clause" + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, - "node_modules/stream-json": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", - "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", - "license": "BSD-3-Clause", + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", "dependencies": { - "stream-chain": "^2.2.5" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/superstruct": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", - "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.8.0" } }, - "node_modules/text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" - }, - "node_modules/tokenx": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tokenx/-/tokenx-1.3.0.tgz", - "integrity": "sha512-NLdXTEZkKiO0gZuLtMoZKjCXTREXeZZt8nnnNeyoXtNZAfG/GKGSbQtLU5STspc0rMSwcA+UJfWZkbNU01iKmQ==", - "license": "MIT" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=14.17" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.25.0.tgz", - "integrity": "sha512-AXNgS1Byr27fTI+2bsPEkV9CxkT8H6xNyRI68b3TatlZo3RkzlqQBLL+w7SmGPVpokjHbcuNVQUWE7FRTg+LRA==", - "license": "MIT" - }, - "node_modules/utf-8-validate": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", - "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", - "hasInstallScript": true, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", - "optional": true, "dependencies": { - "node-gyp-build": "^4.3.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" }, "engines": { - "node": ">=6.14.2" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/uuid": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", - "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/viem": { - "version": "2.48.8", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.48.8.tgz", - "integrity": "sha512-Xj3Nrt66SKtn06kczU91ELn9Difr84ZM5A62BTlaisT5lpgt058i2mBkfMZCXHGb1ocOLjzC2ztPhD0Lvky7uQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", - "peer": true, "dependencies": { - "@noble/curves": "1.9.1", - "@noble/hashes": "1.8.0", - "@scure/bip32": "1.7.0", - "@scure/bip39": "1.6.0", - "abitype": "1.2.3", - "isows": "1.0.7", - "ox": "0.14.20", - "ws": "8.18.3" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, - "peerDependencies": { - "typescript": ">=5.0.4" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/viem/node_modules/@noble/curves": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", - "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.8.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">=12.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/viem/node_modules/abitype": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", - "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3.22.0 || ^4.0.0" + "bin": { + "tsx": "dist/cli.mjs" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/viem/node_modules/ox": { - "version": "0.14.20", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.20.tgz", - "integrity": "sha512-rby38C3nDn8eQkf29Zgw4hkCZJ64Qqi0zRPWL8ENUQ7JVuoITqrVtwWQgM/He19SCMUEc7hS/Sjw0jIOSLJhOw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "^1.11.0", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "1.9.1", - "@noble/hashes": "^1.8.0", - "@scure/bip32": "^1.7.0", - "@scure/bip39": "^1.6.0", - "abitype": "^1.2.3", - "eventemitter3": "5.0.1" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, - "peerDependencies": { - "typescript": ">=5.4.0" + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=14.17" } }, - "node_modules/viem/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "node_modules/vite": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", + "integrity": "sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==", + "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "rolldown": "1.0.0-rc.18", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=10.0.0" + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { - "bufferutil": { + "@types/node": { "optional": true }, - "utf-8-validate": { + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } - }, - "node_modules/yaml": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", - "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index a1da1368..30adf210 100644 --- a/package.json +++ b/package.json @@ -1,69 +1,30 @@ { - "name": "zerion-cli", - "version": "1.1.0", - "description": "Zerion for AI agents and developers: wallet-analysis skill bundle and a JSON-first CLI.", - "author": "Zerion", + "name": "conviction-dca-agent", + "version": "0.1.0", "type": "module", - "bin": { - "zerion": "./cli/zerion.js" - }, - "files": [ - "cli/zerion.js", - "cli/router.js", - "cli/commands/", - "cli/utils/", - "cli/policies/", - "skills/", - "plugins/", - ".agents/", - ".claude-plugin/", - ".codex-plugin/", - "gemini-extension.json", - "README.md", - "LICENSE" - ], "scripts": { - "test": "node --test 'cli/tests/unit/**/*.test.mjs'", - "test:unit": "node --test 'cli/tests/unit/**/*.test.mjs'", - "test:integration": "node --test --test-concurrency=1 'cli/tests/integration/**/*.test.mjs'", - "test:integration:auth": "node --test cli/tests/integration/auth.test.mjs", - "test:all": "node --test 'cli/tests/**/*.test.mjs'", - "prepublishOnly": "npm test" - }, - "imports": { - "#zerion/*": "./cli/*", - "#zerion": "./package.json" - }, - "engines": { - "node": ">=20" - }, - "keywords": [ - "zerion", - "ai", - "wallet", - "openclaw", - "cli" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/zeriontech/zerion-ai.git" - }, - "bugs": { - "url": "https://github.com/zeriontech/zerion-ai/issues" + "dev": "tsx watch app/server.ts", + "build": "tsc && vite build --config client/vite.config.ts", + "start": "node dist/server.js", + "setup": "cd cli && npm install && cd .." }, - "homepage": "https://github.com/zeriontech/zerion-ai#readme", - "license": "MIT", "dependencies": { - "@open-wallet-standard/core": "^1.2.4", - "@solana/web3.js": "^1.98.4", - "@x402/evm": "^2.6.0", - "@x402/fetch": "^2.6.0", - "@x402/svm": "^2.8.0", - "mppx": "^0.6.2", - "qrcode-terminal": "^0.12.0", - "viem": "^2.0.0" + "@google/generative-ai": "^0.21.0", + "dotenv": "^16.0.0", + "express": "^4.18.0", + "node-cron": "^3.0.0" }, - "overrides": { - "uuid": "^14.0.0" + "devDependencies": { + "@types/express": "^4.17.0", + "@types/node": "^20.0.0", + "@types/node-cron": "^3.0.0", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "react": "^19.2.6", + "react-dom": "^19.2.6", + "tsx": "^4.0.0", + "typescript": "^5.0.0", + "vite": "^8.0.11" } } diff --git a/tsconfig.json b/tsconfig.json index dab4c451..888ecf76 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,14 @@ { "compilerOptions": { "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "ESNext", + "moduleResolution": "bundler", + "outDir": "dist", + "rootDir": "app", "strict": true, - "allowJs": true, - "checkJs": false, - "noEmit": true, - "resolveJsonModule": true + "esModuleInterop": true, + "skipLibCheck": true }, - "include": [ - "cli/zerion.js", - "cli/router.js", - "cli/commands/**/*", - "cli/utils/**/*", - "cli/policies/**/*", - "cli/tests/**/*" - ] + "include": ["app/**/*"], + "exclude": ["node_modules", "cli", "client"] } From 74468e15ac019c3900ababb21a4afa47a2f5b943 Mon Sep 17 00:00:00 2001 From: HP Date: Sun, 10 May 2026 12:02:42 -0700 Subject: [PATCH 2/2] feat: implement swap execution with Zerion fallback, realistic gas estimates, 0x API integration --- .env.example | 14 + CONVICTION_DCA_BUILD_PLAN.md | 1583 ++++++++++++++++ app/agent/executor.ts | 114 +- app/agent/filter.ts | 10 +- app/agent/loop.ts | 88 +- app/agent/scorer.ts | 117 +- app/agent/watchlist.ts | 30 +- app/bot.ts | 387 ++++ app/data/base-top-tokens.json | 15 + app/server.ts | 11 +- app/types/cli.d.ts | 11 + app/types/index.ts | 13 + app/utils/bot-storage.ts | 98 + app/utils/storage.ts | 8 +- app/utils/swap.ts | 110 ++ app/utils/zerion-swap.ts | 210 +++ client/package-lock.json | 843 ++++++++- client/package.json | 8 +- client/postcss.config.js | 6 + client/src/App.tsx | 130 +- client/src/index.css | 153 +- client/src/pages/Dashboard.tsx | 398 +++- client/src/pages/Journal.tsx | 92 +- client/src/pages/Settings.tsx | 54 +- client/tailwind.config.js | 28 + data/agent-state.json | 1070 +++++++++++ data/bot-state.json | 16 + data/journal.json | 67 + data/users.json | 1 + dist/agent/scorer.js | 81 +- dist/server.js | 6 +- package-lock.json | 3205 ++++++++++++++++++++++++++------ package.json | 83 +- tsconfig.json | 9 +- 34 files changed, 8206 insertions(+), 863 deletions(-) create mode 100644 CONVICTION_DCA_BUILD_PLAN.md create mode 100644 app/bot.ts create mode 100644 app/data/base-top-tokens.json create mode 100644 app/types/cli.d.ts create mode 100644 app/utils/bot-storage.ts create mode 100644 app/utils/swap.ts create mode 100644 app/utils/zerion-swap.ts create mode 100644 client/postcss.config.js create mode 100644 client/tailwind.config.js create mode 100644 data/agent-state.json create mode 100644 data/bot-state.json create mode 100644 data/journal.json create mode 100644 data/users.json diff --git a/.env.example b/.env.example index 2b7860e5..9cba21a5 100644 --- a/.env.example +++ b/.env.example @@ -8,3 +8,17 @@ COINGECKO_API_KEY= EXECUTE_TRADES=false PORT=3000 RUN_ON_STARTUP=false +TELEGRAM_BOT_TOKEN= # from @BotFather + +# Demo mode ensures at least 1 trade per cycle (boosts top token) +DEMO_MODE=true + +# Force a specific token for demo trades (real Base address required) +# DEMO_SWAP_TOKEN_ADDRESS=0x4200000000000000000000000000000000000006 + +# Direct on-chain swap config (real trades need this β€” Zerion API swap endpoint is 404) +# PRIVATE_KEY=0x...your_wallet_private_key... +BASE_RPC_URL=https://mainnet.base.org + +# Default whale wallets for all new Telegram users (comma-separated Base addresses) +# DEFAULT_WHALE_WALLETS=0x whale1,0x whale2,0x whale3 diff --git a/CONVICTION_DCA_BUILD_PLAN.md b/CONVICTION_DCA_BUILD_PLAN.md new file mode 100644 index 00000000..4312a173 --- /dev/null +++ b/CONVICTION_DCA_BUILD_PLAN.md @@ -0,0 +1,1583 @@ +# Conviction DCA Agent β€” Complete Build Plan +### Starting from zero, building on top of your forked `zerion-ai` repo + +--- + +## How to Read This Plan + +This is written for a builder starting fresh. Follow the sections in order: +1. Understand the repo you forked +2. Set it up locally +3. Add your agent on top of it +4. Build the dashboard +5. Deploy + +Do NOT skip Section 1 β€” understanding what you're building on top of matters. + +--- + +## Section 1: What You Forked and Why + +You forked `zeriontech/zerion-ai`. Here is what that repo actually is: + +``` +zerion-ai/ +β”œβ”€β”€ cli/ ← The zerion-cli npm package (wallet analysis + trading commands) +β”œβ”€β”€ mcp/ ← MCP server config (for Claude/Cursor integrations) +β”œβ”€β”€ skills/ ← Agent skill definitions (wallet-analysis, trading, etc.) +β”œβ”€β”€ examples/ ← Example integrations (Cursor, Claude, OpenAI) +β”œβ”€β”€ docs/ ← Documentation +└── tests/ ← CLI test suite +``` + +### The key insight about the CLI + +The `cli/` folder contains a **JavaScript CLI tool** that calls the Zerion REST API under the hood. It has: + +- `cli/lib/api/client.js` β€” the HTTP client that calls `https://api.zerion.io/v1` +- `cli/commands/analytics/` β€” portfolio, positions, pnl, history commands +- `cli/commands/trading/` β€” swap, bridge, send commands +- `cli/commands/wallet/` β€” create, import, list commands +- `cli/commands/agent/` β€” create-token, create-policy commands + +### What "building on top of it" means + +You are NOT running the CLI as shell commands (`execSync('zerion ...')`). +You are **importing its internal modules directly** into your Node.js app. + +```javascript +// ❌ WRONG β€” this is what broke your previous builder +execSync('npx zerion-cli portfolio 0x...') + +// βœ… CORRECT β€” import the API client directly from the CLI source +import { fetchAPI } from './zerion-ai/cli/lib/api/client.js' +``` + +This avoids ALL the Windows/native-module problems because you're calling JavaScript functions, not spawning a child process. + +--- + +## Section 2: Local Setup (Start Here) + +### Step 1: Clone your fork + +```bash +git clone https://github.com/YOUR_USERNAME/zerion-ai.git conviction-dca-agent +cd conviction-dca-agent +``` + +### Step 2: Install CLI dependencies + +```bash +cd cli +npm install +cd .. +``` + +### Step 3: Create your app's package.json in the root + +The repo root doesn't have a Node app yet. Create one: + +```bash +# In the repo root +npm init -y +npm install express tsx typescript node-cron @google/generative-ai +npm install -D @types/node @types/express @types/node-cron vite react react-dom @vitejs/plugin-react +``` + +### Step 4: Create `.env` in root + +```bash +# .env +ZERION_API_KEY=zk_... +ZERION_AGENT_TOKEN= +MANAGED_EXECUTION_WALLET_NAME=operator-bot +MANAGED_EXECUTION_WALLET_ADDRESS=0x... +GEMINI_API_KEY= +COINGECKO_API_KEY= +EXECUTE_TRADES=false +PORT=3000 +``` + +### Step 5: Bootstrap your operator wallet (ONE TIME, on your machine) + +```bash +# Install CLI globally first +cd cli && npm install -g . && cd .. + +# Create wallet (you will type a passphrase β€” SAVE IT) +zerion wallet create --name operator-bot + +# Create a scoped agent token (auto-saved to ~/.zerion/config.json) +zerion agent create-token --name dca-agent --wallet operator-bot + +# Lock it down β€” Base only, no transfers, 30 day expiry +zerion agent create-policy \ + --name dca-policy \ + --chains base \ + --expires 30d \ + --deny-transfers \ + --deny-approvals + +# Get your wallet address +zerion wallet list + +# Fund it β€” send USDC on Base to the address shown +zerion wallet fund --wallet operator-bot +``` + +Copy the agent token from `~/.zerion/config.json` and put it in `.env` as `ZERION_AGENT_TOKEN`. +Copy the wallet address and put it in `.env` as `MANAGED_EXECUTION_WALLET_ADDRESS`. + +--- + +## Section 3: Final Project Structure + +After you're done building, your repo will look like this: + +``` +conviction-dca-agent/ ← your forked zerion-ai repo root +β”œβ”€β”€ cli/ ← ORIGINAL β€” zerion CLI source (don't modify) +β”œβ”€β”€ mcp/ ← ORIGINAL β€” leave as-is +β”œβ”€β”€ skills/ ← ORIGINAL β€” leave as-is +β”‚ +β”œβ”€β”€ app/ ← NEW β€” your entire application lives here +β”‚ β”œβ”€β”€ server.ts ← Express API + cron scheduler +β”‚ β”œβ”€β”€ api/ +β”‚ β”‚ β”œβ”€β”€ zerion.ts ← Wraps cli/lib/api/client.js +β”‚ β”‚ β”œβ”€β”€ coingecko.ts ← CoinGecko market data +β”‚ β”‚ β”œβ”€β”€ dexscreener.ts ← DexScreener price/liquidity +β”‚ β”‚ └── gemini.ts ← Gemini AI narrative scoring +β”‚ β”œβ”€β”€ agent/ +β”‚ β”‚ β”œβ”€β”€ loop.ts ← Main cycle orchestrator +β”‚ β”‚ β”œβ”€β”€ watchlist.ts ← Token discovery +β”‚ β”‚ β”œβ”€β”€ filter.ts ← Hard filters +β”‚ β”‚ β”œβ”€β”€ scorer.ts ← Dual-gate scoring +β”‚ β”‚ β”œβ”€β”€ whale.ts ← Whale wallet tracker +β”‚ β”‚ β”œβ”€β”€ policy.ts ← Per-user risk limits +β”‚ β”‚ └── executor.ts ← Trade execution +β”‚ β”œβ”€β”€ types/ +β”‚ β”‚ └── index.ts ← TypeScript interfaces +β”‚ └── utils/ +β”‚ β”œβ”€β”€ cache.ts ← In-memory TTL cache +β”‚ β”œβ”€β”€ storage.ts ← JSON file helpers +β”‚ └── logger.ts ← Structured logging +β”‚ +β”œβ”€β”€ client/ ← NEW β€” React dashboard +β”‚ β”œβ”€β”€ index.html +β”‚ β”œβ”€β”€ vite.config.ts +β”‚ └── src/ +β”‚ β”œβ”€β”€ App.tsx +β”‚ β”œβ”€β”€ pages/ +β”‚ β”‚ β”œβ”€β”€ Dashboard.tsx +β”‚ β”‚ β”œβ”€β”€ Journal.tsx +β”‚ β”‚ └── Settings.tsx +β”‚ └── components/ +β”‚ β”œβ”€β”€ ScoreCard.tsx +β”‚ β”œβ”€β”€ SetupCheck.tsx +β”‚ └── WatchlistTable.tsx +β”‚ +β”œβ”€β”€ data/ ← NEW β€” persistent JSON storage +β”‚ β”œβ”€β”€ users.json +β”‚ β”œβ”€β”€ journal.json +β”‚ └── agent-state.json +β”‚ +β”œβ”€β”€ .env +β”œβ”€β”€ package.json +└── tsconfig.json +``` + +--- + +## Section 4: Build the API Layer + +### 4.1 `app/api/zerion.ts` + +This is the most important file. It wraps the CLI's own HTTP client. + +```typescript +// app/api/zerion.ts +// We use fetch directly against Zerion's REST API. +// This is exactly what cli/lib/api/client.js does internally. + +const BASE_URL = 'https://api.zerion.io/v1' + +function getAuthHeader(): string { + const key = process.env.ZERION_API_KEY + if (!key) throw new Error('ZERION_API_KEY is not set in .env') + return `Basic ${Buffer.from(`${key}:`).toString('base64')}` +} + +async function zerionFetch(path: string): Promise { + const controller = new AbortController() + const timeout = setTimeout(() => controller.abort(), 30_000) + + try { + const res = await fetch(`${BASE_URL}${path}`, { + headers: { + 'Authorization': getAuthHeader(), + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + signal: controller.signal, + }) + + if (res.status === 429) throw new Error('Zerion rate limit hit β€” slow down requests') + if (res.status === 401) throw new Error('Invalid ZERION_API_KEY') + if (!res.ok) throw new Error(`Zerion API error ${res.status} on ${path}`) + + return res.json() + } finally { + clearTimeout(timeout) + } +} + +// ── Read endpoints ────────────────────────────────────────── + +export async function getPortfolio(address: string) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/portfolio?currency=usd`) +} + +export async function getPositions(address: string, type: 'all' | 'simple' | 'defi' = 'all') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/positions?filter[position_types]=${type}¤cy=usd`) +} + +export async function getTransactions(address: string, limit = 20, chain = 'base') { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/transactions?filter[chain_ids]=${chain}&page[size]=${limit}`) +} + +export async function getPnL(address: string) { + return zerionFetch(`/wallets/${encodeURIComponent(address)}/pnl?currency=usd`) +} + +export async function getFungibleInfo(tokenAddress: string) { + return zerionFetch(`/fungibles/${encodeURIComponent(tokenAddress)}?currency=usd`) +} + +// ── Trade execution ───────────────────────────────────────── + +export async function executeSwap(params: { + fromToken: string // 'USDC' or token address + toToken: string // token address on Base + amount: string // amount in USD string e.g. '10' + chain?: string // default: 'base' +}): Promise { + const agentToken = process.env.ZERION_AGENT_TOKEN + const walletAddress = process.env.MANAGED_EXECUTION_WALLET_ADDRESS + + if (!agentToken) throw new Error('ZERION_AGENT_TOKEN not set β€” run wallet bootstrap first') + if (!walletAddress) throw new Error('MANAGED_EXECUTION_WALLET_ADDRESS not set') + + const res = await fetch(`${BASE_URL}/swap`, { + method: 'POST', + headers: { + 'Authorization': getAuthHeader(), + 'X-Agent-Token': agentToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chain: params.chain || 'base', + from_token: params.fromToken, + to_token: params.toToken, + amount: params.amount, + wallet_address: walletAddress, + }), + }) + + if (!res.ok) { + const err = await res.text() + throw new Error(`Swap failed (${res.status}): ${err}`) + } + return res.json() +} +``` + +### 4.2 `app/api/coingecko.ts` + +```typescript +// app/api/coingecko.ts +const BASE = 'https://api.coingecko.com/api/v3' + +function cgParams(extra = '') { + const key = process.env.COINGECKO_API_KEY + const auth = key ? `x_cg_demo_api_key=${key}` : '' + const sep = extra && auth ? '&' : '' + return extra || auth ? `?${extra}${sep}${auth}` : '' +} + +export async function getTopBaseTokens(limit = 50) { + const res = await fetch( + `${BASE}/coins/markets${cgParams(`vs_currency=usd&category=base-ecosystem&order=volume_desc&per_page=${limit}&sparkline=true`)}` + ) + return res.json() // returns array of tokens +} + +export async function getTrendingTokens() { + const res = await fetch(`${BASE}/search/trending${cgParams()}`) + const data = await res.json() + return data.coins?.map((c: any) => c.item) || [] +} + +export async function getOHLCV(tokenId: string, days = 14): Promise { + const res = await fetch(`${BASE}/coins/${tokenId}/ohlc${cgParams(`vs_currency=usd&days=${days}`)}`) + return res.json() // [[timestamp, open, high, low, close], ...] +} + +export async function getTokenMarketData(tokenId: string) { + const res = await fetch( + `${BASE}/coins/${tokenId}${cgParams('localization=false&tickers=false&community_data=true&developer_data=false')}` + ) + return res.json() +} +``` + +### 4.3 `app/api/dexscreener.ts` + +```typescript +// app/api/dexscreener.ts +// DexScreener is FREE β€” no API key needed +const BASE = 'https://api.dexscreener.com/latest' + +export async function getTokenPairsOnBase(tokenAddress: string) { + const res = await fetch(`${BASE}/dex/tokens/${tokenAddress}`) + const data = await res.json() + // Filter to Base chain pairs only + return (data.pairs || []).filter((p: any) => p.chainId === 'base') +} + +export async function searchDexTokens(query: string) { + const res = await fetch(`${BASE}/dex/search?q=${encodeURIComponent(query)}`) + const data = await res.json() + return (data.pairs || []).filter((p: any) => p.chainId === 'base') +} + +// Extract useful metrics from a DexScreener pair +export function extractPairMetrics(pair: any) { + return { + address: pair.baseToken?.address, + symbol: pair.baseToken?.symbol, + name: pair.baseToken?.name, + price: parseFloat(pair.priceUsd || '0'), + liquidity: pair.liquidity?.usd || 0, + volume24h: pair.volume?.h24 || 0, + priceChange24h: pair.priceChange?.h24 || 0, + priceChange6h: pair.priceChange?.h6 || 0, + priceChange1h: pair.priceChange?.h1 || 0, + txCount24h: (pair.txns?.h24?.buys || 0) + (pair.txns?.h24?.sells || 0), + fdv: pair.fdv || 0, + marketCap: pair.marketCap || 0, + } +} +``` + +### 4.4 `app/api/gemini.ts` + +```typescript +// app/api/gemini.ts +import { GoogleGenerativeAI } from '@google/generative-ai' + +let genAI: GoogleGenerativeAI | null = null + +function getClient() { + if (!genAI) { + if (!process.env.GEMINI_API_KEY) throw new Error('GEMINI_API_KEY not set') + genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY) + } + return genAI.getGenerativeModel({ model: 'gemini-1.5-flash' }) +} + +// Ask Gemini which tokens have the strongest narrative momentum +export async function getMomentumPicks(tokens: { symbol: string; name: string }[]): Promise { + const model = getClient() + const list = tokens.map(t => `${t.symbol} (${t.name})`).join(', ') + + const prompt = ` +You are a crypto memecoin analyst focused on Base chain. +Given these tokens: ${list} + +Pick the top 5 with strongest current narrative momentum based on: +- Community excitement and virality potential +- Recent catalysts or news +- Memetic strength and cultural resonance +- DeFi/onchain activity trends + +Reply ONLY with a JSON array of symbols. Example: ["SYMBOL1","SYMBOL2","SYMBOL3"] +No explanation, no markdown, just the JSON array. +` + const result = await model.generateContent(prompt) + const text = result.response.text().trim() + + try { + return JSON.parse(text) + } catch { + // Try to extract array from response if it has extra text + const match = text.match(/\[.*\]/) + if (match) return JSON.parse(match[0]) + return [] + } +} + +// Score a single token's narrative strength 0-100 +export async function scoreNarrative(symbol: string, context: string): Promise { + const model = getClient() + + const prompt = ` +Score this Base chain token's narrative strength from 0 to 100. +Token: ${symbol} +Context: ${context} + +Score based on: clarity of use case, community excitement, recent momentum, meme potential. +Reply ONLY with a single integer 0-100. Nothing else. +` + const result = await model.generateContent(prompt) + const score = parseInt(result.response.text().trim()) + return isNaN(score) ? 50 : Math.max(0, Math.min(100, score)) +} +``` + +--- + +## Section 5: TypeScript Types + +### `app/types/index.ts` + +```typescript +// app/types/index.ts + +export interface Token { + symbol: string + name: string + address: string + price: number + marketCap: number + liquidity: number + volume24h: number + priceChange24h: number // as decimal, e.g. 0.05 = 5% + high24h: number + low24h: number + ma7d?: number // 7-day moving average + ma14d?: number // 14-day moving average + stdDev7d?: number // price standard deviation + rsi14?: number // RSI (14 period) + volumeHistory?: number[] // last N days of volume + volumeChange24h?: number + cgId?: string // CoinGecko ID + whaleAccumulationCount?: number + hasNarrativeMomentum?: boolean + narrativeScore?: number +} + +export interface ScoredToken extends Token { + convictionScore: number // Gate A: 0-100, threshold 60 + timingScore: number // Gate B: 0-100, threshold 55 +} + +export interface User { + id: string + name: string + address: string // their public wallet (monitoring only) + active: boolean + createdAt: string + policy: UserPolicy + whaleWallets?: string[] // custom whale wallets to track +} + +export interface UserPolicy { + dailyLimit: number // max USD per day + weeklyLimit: number // max USD per week + maxTradesPerDay: number + cooldownMs: number // ms between trades + tradeSize: number // USD per trade +} + +export interface JournalEntry { + id: string + userId: string + timestamp: string + token: string + tokenAddress: string + convictionScore: number + timingScore: number + amount: number // USD amount + executed: boolean + txHash?: string + error?: string + dryRun: boolean +} + +export interface AgentState { + lastRunAt: string | null + nextRunAt: string | null + cycleCount: number + watchlistSize: number + lastWatchlist: Token[] + lastScored: ScoredToken[] + status: 'idle' | 'running' | 'error' + lastError?: string +} +``` + +--- + +## Section 6: Utility Helpers + +### `app/utils/cache.ts` + +```typescript +// app/utils/cache.ts +// Simple in-memory TTL cache β€” prevents Zerion/CoinGecko rate limits + +interface Entry { value: any; expiresAt: number } +const store = new Map() + +export const cache = { + get(key: string): T | null { + const entry = store.get(key) + if (!entry) return null + if (Date.now() > entry.expiresAt) { store.delete(key); return null } + return entry.value as T + }, + set(key: string, value: any, ttlSeconds = 60) { + store.set(key, { value, expiresAt: Date.now() + ttlSeconds * 1000 }) + }, + has(key: string): boolean { return this.get(key) !== null }, + clear() { store.clear() }, +} +``` + +### `app/utils/storage.ts` + +```typescript +// app/utils/storage.ts +import fs from 'fs' +import path from 'path' +import type { User, JournalEntry, AgentState } from '../types' + +const DATA_DIR = path.join(process.cwd(), 'data') + +function ensureDataDir() { + if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }) +} + +function readJSON(filename: string, fallback: T): T { + ensureDataDir() + const file = path.join(DATA_DIR, filename) + if (!fs.existsSync(file)) return fallback + try { return JSON.parse(fs.readFileSync(file, 'utf-8')) } + catch { return fallback } +} + +function writeJSON(filename: string, data: any) { + ensureDataDir() + fs.writeFileSync(path.join(DATA_DIR, filename), JSON.stringify(data, null, 2)) +} + +// Users +export const loadUsers = (): User[] => readJSON('users.json', []) +export const saveUsers = (users: User[]) => writeJSON('users.json', users) +export function createUser(data: Pick): User { + const users = loadUsers() + const user: User = { + id: `usr_${Date.now()}`, + name: data.name || 'Anonymous', + address: data.address, + active: true, + createdAt: new Date().toISOString(), + policy: { + dailyLimit: 50, + weeklyLimit: 200, + maxTradesPerDay: 3, + cooldownMs: 60 * 60 * 1000, + tradeSize: 10, + }, + } + users.push(user) + saveUsers(users) + return user +} + +// Journal +export const loadJournal = (): JournalEntry[] => readJSON('journal.json', []) +export function saveJournalEntry(entry: JournalEntry) { + const journal = loadJournal() + journal.push(entry) + writeJSON('journal.json', journal) +} +export function loadJournalForUser(userId: string): JournalEntry[] { + return loadJournal().filter(e => e.userId === userId) +} + +// Agent State +export const loadAgentState = (): AgentState => readJSON('agent-state.json', { + lastRunAt: null, nextRunAt: null, cycleCount: 0, + watchlistSize: 0, lastWatchlist: [], lastScored: [], status: 'idle', +}) +export const saveAgentState = (state: AgentState) => writeJSON('agent-state.json', state) +``` + +### `app/utils/logger.ts` + +```typescript +// app/utils/logger.ts +export const logger = { + info: (msg: string, data?: any) => console.log(`[INFO] ${new Date().toISOString()} ${msg}`, data || ''), + error: (msg: string, data?: any) => console.error(`[ERROR] ${new Date().toISOString()} ${msg}`, data || ''), + warn: (msg: string, data?: any) => console.warn(`[WARN] ${new Date().toISOString()} ${msg}`, data || ''), +} +``` + +--- + +## Section 7: The Agent + +### `app/agent/watchlist.ts` β€” Token Discovery + +```typescript +// app/agent/watchlist.ts +import { getTopBaseTokens, getTrendingTokens } from '../api/coingecko' +import { searchDexTokens, extractPairMetrics } from '../api/dexscreener' +import { getMomentumPicks } from '../api/gemini' +import { cache } from '../utils/cache' +import type { Token } from '../types' + +export async function discoverWatchlist(): Promise { + const cached = cache.get('watchlist') + if (cached) return cached + + // Fetch from all 3 sources in parallel + const [cgTopResult, cgTrendingResult] = await Promise.allSettled([ + getTopBaseTokens(50), + getTrendingTokens(), + ]) + + const cgTop = cgTopResult.status === 'fulfilled' ? cgTopResult.value : [] + const cgTrending = cgTrendingResult.status === 'fulfilled' ? cgTrendingResult.value : [] + + // Normalise CoinGecko tokens + const fromCG: Token[] = cgTop.map((t: any) => ({ + symbol: t.symbol?.toUpperCase(), + name: t.name, + address: t.contract_address || t.id, + price: t.current_price || 0, + marketCap: t.market_cap || 0, + liquidity: 0, // enriched below from DexScreener + volume24h: t.total_volume || 0, + priceChange24h: (t.price_change_percentage_24h || 0) / 100, + high24h: t.high_24h || 0, + low24h: t.low_24h || 0, + cgId: t.id, + })) + + // Enrich with DexScreener data for liquidity + real-time price + const enriched = await Promise.all( + fromCG.slice(0, 20).map(async (token) => { + try { + const pairs = await searchDexTokens(token.symbol) + if (pairs.length > 0) { + const metrics = extractPairMetrics(pairs[0]) + return { ...token, ...metrics, symbol: token.symbol } + } + } catch { /* use CG data only */ } + return token + }) + ) + + // Get Gemini AI narrative momentum picks + const momentumPicks = await getMomentumPicks( + enriched.map(t => ({ symbol: t.symbol, name: t.name })) + ).catch(() => []) + + const result = enriched.map(t => ({ + ...t, + hasNarrativeMomentum: momentumPicks.includes(t.symbol), + })) + + cache.set('watchlist', result, 300) // cache 5 minutes + return result +} +``` + +### `app/agent/filter.ts` β€” Hard Filters + +```typescript +// app/agent/filter.ts +import type { Token } from '../types' +import { logger } from '../utils/logger' + +const STABLECOINS = new Set(['USDC', 'USDT', 'DAI', 'BUSD', 'FRAX', 'LUSD', 'USDD', 'TUSD']) +const MIN_MARKET_CAP = 100_000_000 // $100M +const MIN_LIQUIDITY = 500_000 // $500K +const MAX_24H_PUMP = 0.30 // >30% gain in 24h = suspicious +const MIN_VOLUME_24H = 100_000 // $100K minimum volume + +export function hardFilter(tokens: Token[]): Token[] { + return tokens.filter(token => { + if (STABLECOINS.has(token.symbol.toUpperCase())) { + logger.info(`[Filter] ❌ ${token.symbol} β€” stablecoin`) + return false + } + if (token.marketCap > 0 && token.marketCap < MIN_MARKET_CAP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” market cap too low ($${token.marketCap.toLocaleString()})`) + return false + } + if (token.liquidity > 0 && token.liquidity < MIN_LIQUIDITY) { + logger.info(`[Filter] ❌ ${token.symbol} β€” liquidity too low ($${token.liquidity.toLocaleString()})`) + return false + } + if (token.priceChange24h > MAX_24H_PUMP) { + logger.info(`[Filter] ❌ ${token.symbol} β€” suspicious 24h pump (${(token.priceChange24h * 100).toFixed(1)}%)`) + return false + } + if (token.volume24h > 0 && token.volume24h < MIN_VOLUME_24H) { + logger.info(`[Filter] ❌ ${token.symbol} β€” volume too low`) + return false + } + logger.info(`[Filter] βœ… ${token.symbol} β€” passed`) + return true + }) +} +``` + +### `app/agent/whale.ts` β€” Whale Tracking + +```typescript +// app/agent/whale.ts +import { getTransactions } from '../api/zerion' +import { cache } from '../utils/cache' +import { logger } from '../utils/logger' + +// Default whale wallets β€” expand this list +const DEFAULT_WHALE_WALLETS = [ + '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', // vitalik (example) + // add more high-conviction Base traders here +] + +export async function getWhaleAccumulationCount( + tokenAddress: string, + extraWhales: string[] = [] +): Promise { + const whales = [...new Set([...DEFAULT_WHALE_WALLETS, ...extraWhales])] + const SIX_HOURS_MS = 6 * 60 * 60 * 1000 + const since = Date.now() - SIX_HOURS_MS + let count = 0 + + for (const whale of whales) { + const cacheKey = `whale:${whale}:${tokenAddress}` + const cached = cache.get(cacheKey) + if (cached !== null) { + if (cached) count++ + continue + } + + try { + const data = await getTransactions(whale, 20, 'base') + const txs = data?.data || [] + const accumulated = txs.some((tx: any) => { + const ts = new Date(tx.attributes?.mined_at).getTime() + const isRecent = ts > since + const isReceive = tx.attributes?.operation_type === 'receive' + const hasToken = tx.attributes?.transfers?.some((t: any) => + t.fungible_info?.implementations?.some((i: any) => + i.address?.toLowerCase() === tokenAddress.toLowerCase() + ) + ) + return isRecent && isReceive && hasToken + }) + + cache.set(cacheKey, accumulated, 600) // cache 10 min + if (accumulated) count++ + } catch (err) { + logger.warn(`[Whale] Failed to check ${whale}: ${err}`) + } + } + + return count +} +``` + +### `app/agent/scorer.ts` β€” Dual Gate Scoring + +```typescript +// app/agent/scorer.ts +import type { Token, ScoredToken } from '../types' +import { getWhaleAccumulationCount } from './whale' +import { getOHLCV } from '../api/coingecko' + +// ── Technical Calculations ────────────────────────────────── + +function calcSMA(prices: number[], period: number): number { + if (prices.length < period) return 0 + const slice = prices.slice(-period) + return slice.reduce((a, b) => a + b, 0) / period +} + +function calcStdDev(values: number[]): number { + if (values.length < 2) return 0 + const mean = values.reduce((a, b) => a + b, 0) / values.length + const variance = values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length + return Math.sqrt(variance) +} + +function calcRSI(closes: number[], period = 14): number { + if (closes.length < period + 1) return 50 + let gains = 0, losses = 0 + for (let i = closes.length - period; i < closes.length; i++) { + const diff = closes[i] - closes[i - 1] + if (diff > 0) gains += diff + else losses += Math.abs(diff) + } + if (losses === 0) return 100 + const rs = gains / losses + return 100 - (100 / (1 + rs)) +} + +// ── Gate A: Conviction (0-100) ────────────────────────────── +// Is this token fundamentally worth buying? + +export function scoreConviction(token: Token, technicals: { + ma7d: number + ma14d: number + stdDev: number + volumeHistory: number[] +}): number { + let score = 0 + + // 1. Volume Consistency (25 pts) β€” consecutive days of growth + const vols = technicals.volumeHistory + let streak = 0 + for (let i = 1; i < vols.length; i++) { + if (vols[i] > vols[i - 1]) streak++ + else break + } + const volScore = Math.min(25, streak * 5) + score += volScore + + // 2. Price Trend (25 pts) β€” above 7d and 14d MAs + if (token.price > technicals.ma7d && technicals.ma7d > 0) score += 12 + if (token.price > technicals.ma14d && technicals.ma14d > 0) score += 13 + + // 3. Wallet Allocation (25 pts) β€” rewarded for not already owning + // (In managed-wallet mode, we always score this as 25 since we control the wallet) + score += 25 + + // 4. Volatility Penalty (25 pts) β€” penalise erratic swings + const stdDevNorm = Math.min(1, technicals.stdDev / token.price) + const volPenalty = Math.floor(stdDevNorm * 100) + score += Math.max(0, 25 - volPenalty) + + // 5. Whale Bonus (15 pts) β€” at least 2 whales accumulating + if ((token.whaleAccumulationCount || 0) >= 2) score += 15 + + // 6. Narrative Bonus (10 pts) + if (token.hasNarrativeMomentum) score += 10 + + return Math.min(100, score) +} + +// ── Gate B: Timing (0-100) ────────────────────────────────── +// Is NOW the right time to buy? + +export function scoreTiming(token: Token, rsi: number): number { + let score = 0 + + // 1. RSI (40 pts) β€” reward oversold + if (rsi < 25) score += 40 + else if (rsi < 35) score += 30 + else if (rsi < 45) score += 15 + else if (rsi < 55) score += 5 + + // 2. Price vs 24h High (30 pts) β€” reward retracement from peak + const retracement = token.high24h > 0 + ? 1 - (token.price / token.high24h) + : 0 + score += Math.min(30, Math.floor(retracement * 150)) + + // 3. Volume-Price Divergence (30 pts) β€” volume spike without price spike + const volumeChange = token.volumeChange24h || 0 + const priceChange = token.priceChange24h || 0 + const divergence = volumeChange - priceChange + if (divergence > 0.5) score += 30 + else if (divergence > 0.2) score += 15 + else if (divergence > 0) score += 5 + + return Math.min(100, score) +} + +// ── Full Token Scoring Pipeline ───────────────────────────── + +export async function scoreToken(token: Token): Promise { + // Fetch OHLCV for technical calculations + let ma7d = 0, ma14d = 0, stdDev = 0, rsi = 50 + let volumeHistory: number[] = [] + + try { + if (token.cgId) { + const ohlcv = await getOHLCV(token.cgId, 14) + // ohlcv = [[timestamp, open, high, low, close], ...] + const closes = ohlcv.map((c: number[]) => c[4]) + const volumes = ohlcv.map((c: number[]) => c[1]) // use open as proxy if no vol + + ma7d = calcSMA(closes, 7) + ma14d = calcSMA(closes, 14) + stdDev = calcStdDev(closes.slice(-7)) + rsi = calcRSI(closes) + volumeHistory = volumes + } + } catch { /* use defaults */ } + + // Whale check + const whaleCount = await getWhaleAccumulationCount(token.address).catch(() => 0) + + const enriched = { ...token, ma7d, ma14d, stdDev7d: stdDev, rsi14: rsi, whaleAccumulationCount: whaleCount, volumeHistory } + + const convictionScore = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }) + const timingScore = scoreTiming(enriched, rsi) + + return { ...enriched, convictionScore, timingScore } +} +``` + +### `app/agent/policy.ts` β€” Per-User Risk Engine + +```typescript +// app/agent/policy.ts +import type { User } from '../types' +import { loadJournalForUser } from '../utils/storage' + +export function checkUserPolicy(user: User): { ok: boolean; reason?: string } { + const policy = user.policy + const now = Date.now() + const journal = loadJournalForUser(user.id) + const today = new Date().toDateString() + + // Daily spend + const todaySpend = journal + .filter(e => new Date(e.timestamp).toDateString() === today) + .reduce((sum, e) => sum + e.amount, 0) + + if (todaySpend + policy.tradeSize > policy.dailyLimit) { + return { ok: false, reason: `Daily limit $${policy.dailyLimit} reached (spent $${todaySpend.toFixed(2)})` } + } + + // Weekly spend + const weekAgo = now - 7 * 24 * 60 * 60 * 1000 + const weekSpend = journal + .filter(e => new Date(e.timestamp).getTime() > weekAgo) + .reduce((sum, e) => sum + e.amount, 0) + + if (weekSpend + policy.tradeSize > policy.weeklyLimit) { + return { ok: false, reason: `Weekly limit $${policy.weeklyLimit} reached` } + } + + // Max trades per day + const todayTrades = journal.filter(e => new Date(e.timestamp).toDateString() === today).length + if (todayTrades >= policy.maxTradesPerDay) { + return { ok: false, reason: `Max ${policy.maxTradesPerDay} trades/day reached` } + } + + // Cooldown + const lastTrade = [...journal].sort((a, b) => + new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime() + )[0] + + if (lastTrade) { + const elapsed = now - new Date(lastTrade.timestamp).getTime() + if (elapsed < policy.cooldownMs) { + const remaining = Math.ceil((policy.cooldownMs - elapsed) / 60000) + return { ok: false, reason: `Cooldown active β€” ${remaining}m remaining` } + } + } + + return { ok: true } +} +``` + +### `app/agent/executor.ts` β€” Trade Execution + +```typescript +// app/agent/executor.ts +import { executeSwap } from '../api/zerion' +import { saveJournalEntry } from '../utils/storage' +import { logger } from '../utils/logger' +import type { User, ScoredToken, JournalEntry } from '../types' + +const DRY_RUN = process.env.EXECUTE_TRADES !== 'true' + +export async function executeTrade(user: User, token: ScoredToken): Promise { + const amount = user.policy.tradeSize + const entryId = `trade_${Date.now()}_${Math.random().toString(36).slice(2, 7)}` + + const entry: JournalEntry = { + id: entryId, + userId: user.id, + timestamp: new Date().toISOString(), + token: token.symbol, + tokenAddress: token.address, + convictionScore: token.convictionScore, + timingScore: token.timingScore, + amount, + executed: false, + dryRun: DRY_RUN, + } + + if (DRY_RUN) { + logger.info(`[Executor] πŸ”΅ DRY RUN β€” would buy $${amount} of ${token.symbol} | conviction:${token.convictionScore} timing:${token.timingScore}`) + saveJournalEntry(entry) + return + } + + try { + logger.info(`[Executor] 🟑 Executing swap: $${amount} USDC β†’ ${token.symbol}`) + const result = await executeSwap({ + fromToken: 'USDC', + toToken: token.address, + amount: amount.toString(), + chain: 'base', + }) + entry.executed = true + entry.txHash = result?.data?.hash || result?.tx_hash + logger.info(`[Executor] βœ… Success | tx: ${entry.txHash}`) + } catch (err: any) { + entry.error = err.message + logger.error(`[Executor] ❌ Trade failed for ${token.symbol}: ${err.message}`) + } + + saveJournalEntry(entry) +} +``` + +### `app/agent/loop.ts` β€” Main Orchestrator + +```typescript +// app/agent/loop.ts +import { discoverWatchlist } from './watchlist' +import { hardFilter } from './filter' +import { scoreToken } from './scorer' +import { checkUserPolicy } from './policy' +import { executeTrade } from './executor' +import { loadUsers, loadAgentState, saveAgentState } from '../utils/storage' +import { logger } from '../utils/logger' + +// Thresholds +const CONVICTION_THRESHOLD = 60 +const TIMING_THRESHOLD = 55 + +export async function runAgentCycle(): Promise { + const state = loadAgentState() + state.status = 'running' + state.lastRunAt = new Date().toISOString() + saveAgentState(state) + + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') + logger.info('[Cycle] Starting agent cycle...') + + try { + // Step 1: Discover tokens + const rawTokens = await discoverWatchlist() + logger.info(`[Cycle] Step 1 β€” Discovered ${rawTokens.length} tokens`) + + // Step 2: Hard filter + const filtered = hardFilter(rawTokens) + logger.info(`[Cycle] Step 2 β€” ${filtered.length} tokens passed hard filter`) + + // Step 3: Score all tokens (parallel with rate limit) + const scored = [] + for (const token of filtered) { + try { + const s = await scoreToken(token) + scored.push(s) + } catch (err) { + logger.warn(`[Cycle] Failed to score ${token.symbol}: ${err}`) + } + } + + // Dual gate filter + const qualified = scored.filter( + t => t.convictionScore >= CONVICTION_THRESHOLD && t.timingScore >= TIMING_THRESHOLD + ) + logger.info(`[Cycle] Step 3 β€” ${qualified.length} tokens passed dual gate (convictionβ‰₯${CONVICTION_THRESHOLD}, timingβ‰₯${TIMING_THRESHOLD})`) + + // Update state + state.watchlistSize = rawTokens.length + state.lastWatchlist = rawTokens + state.lastScored = scored.sort((a, b) => (b.convictionScore + b.timingScore) - (a.convictionScore + a.timingScore)) + + if (qualified.length === 0) { + logger.info('[Cycle] No tokens qualified β€” no trades this cycle') + } else { + // Step 4 & 5: Per-user policy check + execution + const users = loadUsers().filter(u => u.active) + logger.info(`[Cycle] Step 4/5 β€” Checking ${users.length} active users against ${qualified.length} qualified tokens`) + + for (const user of users) { + const policy = checkUserPolicy(user) + if (!policy.ok) { + logger.info(`[Cycle] User ${user.name} blocked: ${policy.reason}`) + continue + } + // Execute top qualifying token per cycle per user + const top = qualified[0] + await executeTrade(user, top) + } + } + + state.status = 'idle' + state.cycleCount = (state.cycleCount || 0) + 1 + state.nextRunAt = new Date(Date.now() + 60 * 60 * 1000).toISOString() + } catch (err: any) { + state.status = 'error' + state.lastError = err.message + logger.error(`[Cycle] Fatal error: ${err.message}`) + } + + saveAgentState(state) + logger.info('[Cycle] Complete') + logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') +} +``` + +--- + +## Section 8: Express Server + +### `app/server.ts` + +```typescript +// app/server.ts +import 'dotenv/config' +import express from 'express' +import path from 'path' +import cron from 'node-cron' +import { runAgentCycle } from './agent/loop' +import { getPortfolio, getPnL } from './api/zerion' +import { + loadUsers, createUser, saveUsers, + loadJournal, loadJournalForUser, + loadAgentState, +} from './utils/storage' + +const app = express() +app.use(express.json()) + +// Serve React frontend +app.use(express.static(path.join(process.cwd(), 'client/dist'))) + +// ── Setup Check ──────────────────────────────────────────── +app.get('/api/setupcheck', (_req, res) => { + const checks = { + zerionApiKey: !!process.env.ZERION_API_KEY, + zerionAgentToken: !!process.env.ZERION_AGENT_TOKEN, + executionWalletName: !!process.env.MANAGED_EXECUTION_WALLET_NAME, + executionWalletAddress:!!process.env.MANAGED_EXECUTION_WALLET_ADDRESS, + geminiKey: !!process.env.GEMINI_API_KEY, + executeTradesEnabled: process.env.EXECUTE_TRADES === 'true', + } + const ready = checks.zerionApiKey && checks.zerionAgentToken && checks.executionWalletAddress + res.json({ ready, checks }) +}) + +// ── Users ────────────────────────────────────────────────── +app.post('/api/users', (req, res) => { + const { address, name } = req.body + if (!address || !/^0x[0-9a-fA-F]{40}$/.test(address)) { + return res.status(400).json({ error: 'Valid 0x wallet address required' }) + } + const user = createUser({ address, name: name || 'Anonymous' }) + res.json(user) +}) + +app.get('/api/users', (_req, res) => res.json(loadUsers())) + +app.patch('/api/users/:id', (req, res) => { + const users = loadUsers() + const idx = users.findIndex(u => u.id === req.params.id) + if (idx === -1) return res.status(404).json({ error: 'User not found' }) + users[idx] = { ...users[idx], ...req.body } + saveUsers(users) + res.json(users[idx]) +}) + +// ── Portfolio ────────────────────────────────────────────── +app.get('/api/portfolio/:address', async (req, res) => { + try { + const data = await getPortfolio(req.params.address) + res.json(data) + } catch (err: any) { + res.status(500).json({ error: err.message }) + } +}) + +app.get('/api/pnl/:address', async (req, res) => { + try { + const data = await getPnL(req.params.address) + res.json(data) + } catch (err: any) { + res.status(500).json({ error: err.message }) + } +}) + +// ── Journal ──────────────────────────────────────────────── +app.get('/api/journal', (_req, res) => res.json(loadJournal())) +app.get('/api/journal/:userId', (req, res) => res.json(loadJournalForUser(req.params.userId))) + +// ── Agent State ──────────────────────────────────────────── +app.get('/api/state', (_req, res) => res.json(loadAgentState())) + +// ── Manual Cycle Trigger ─────────────────────────────────── +app.post('/api/run', (_req, res) => { + res.json({ message: 'Cycle triggered' }) + runAgentCycle().catch(console.error) +}) + +// ── Watchlist ────────────────────────────────────────────── +app.get('/api/watchlist', (_req, res) => { + const state = loadAgentState() + res.json(state.lastScored || []) +}) + +// ── SPA fallback ─────────────────────────────────────────── +app.get('*', (_req, res) => { + res.sendFile(path.join(process.cwd(), 'client/dist/index.html')) +}) + +// ── Cron: every 60 minutes ───────────────────────────────── +cron.schedule('0 * * * *', () => { + runAgentCycle().catch(console.error) + console.log(`[Cron] Next run at ${new Date(Date.now() + 3600000).toISOString()}`) +}) + +const PORT = process.env.PORT || 3000 +app.listen(PORT, () => { + console.log(`\nπŸš€ Conviction DCA Agent running at http://localhost:${PORT}`) + console.log(`πŸ“Š Dashboard: http://localhost:${PORT}`) + console.log(`πŸ”§ Setup Check: http://localhost:${PORT}/api/setupcheck`) + console.log(`▢️ Manual Run: POST http://localhost:${PORT}/api/run\n`) + + // Run once on startup (dry run only) + if (process.env.RUN_ON_STARTUP === 'true') { + runAgentCycle().catch(console.error) + } +}) +``` + +--- + +## Section 9: Root `package.json` + +```json +{ + "name": "conviction-dca-agent", + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "tsx watch app/server.ts", + "build": "tsc && vite build --config client/vite.config.ts", + "start": "node dist/server.js", + "setup": "cd cli && npm install && cd .." + }, + "dependencies": { + "@google/generative-ai": "^0.21.0", + "dotenv": "^16.0.0", + "express": "^4.18.0", + "node-cron": "^3.0.0" + }, + "devDependencies": { + "@types/express": "^4.17.0", + "@types/node": "^20.0.0", + "@types/node-cron": "^3.0.0", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + } +} +``` + +--- + +## Section 10: tsconfig.json + +```json +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "outDir": "dist", + "rootDir": "app", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": ["app/**/*"], + "exclude": ["node_modules", "cli", "client"] +} +``` + +--- + +## Section 11: React Dashboard (Minimal but Functional) + +### `client/src/App.tsx` + +```tsx +import { useState } from 'react' +import Dashboard from './pages/Dashboard' +import Journal from './pages/Journal' +import Settings from './pages/Settings' + +export default function App() { + const [tab, setTab] = useState<'dashboard' | 'journal' | 'settings'>('dashboard') + + return ( +
+

⚑ Conviction DCA Agent

+ + + + {tab === 'dashboard' && } + {tab === 'journal' && } + {tab === 'settings' && } +
+ ) +} +``` + +### `client/src/pages/Dashboard.tsx` + +```tsx +import { useEffect, useState } from 'react' + +export default function Dashboard() { + const [setup, setSetup] = useState(null) + const [state, setState] = useState(null) + const [watchlist, setWatchlist] = useState([]) + const [running, setRunning] = useState(false) + + useEffect(() => { + fetch('/api/setupcheck').then(r => r.json()).then(setSetup) + fetch('/api/state').then(r => r.json()).then(setState) + fetch('/api/watchlist').then(r => r.json()).then(setWatchlist) + }, []) + + const triggerRun = async () => { + setRunning(true) + await fetch('/api/run', { method: 'POST' }) + setTimeout(() => { + fetch('/api/state').then(r => r.json()).then(setState) + fetch('/api/watchlist').then(r => r.json()).then(setWatchlist) + setRunning(false) + }, 5000) + } + + return ( +
+ {/* Setup Check */} + {setup && ( +
+

Setup Status {setup.ready ? 'βœ… Ready' : '⚠️ Not Ready'}

+ {Object.entries(setup.checks).map(([k, v]) => ( +
{v ? 'βœ…' : '❌'} {k}
+ ))} +
+ )} + + {/* Agent Status */} + {state && ( +
+

Agent Status

+

Status: {state.status} | Cycles run: {state.cycleCount}

+

Last run: {state.lastRunAt ? new Date(state.lastRunAt).toLocaleString() : 'Never'}

+

Next run: {state.nextRunAt ? new Date(state.nextRunAt).toLocaleString() : 'Unknown'}

+ +
+ )} + + {/* Top Scored Tokens */} +

Top Scored Tokens ({watchlist.length})

+ + + + {['Token', 'Price', 'Conviction', 'Timing', 'Whale Acc.', 'Narrative'].map(h => ( + + ))} + + + + {watchlist.slice(0, 10).map((t: any, i: number) => ( + + + + + + + + + ))} + +
{h}
{t.symbol}${t.price?.toFixed(4)} + + + + {t.whaleAccumulationCount || 0}{t.hasNarrativeMomentum ? 'πŸ”₯' : 'β€”'}
+
+ ) +} + +function ScoreBar({ value, threshold }: { value: number; threshold: number }) { + if (value === undefined) return β€” + const passed = value >= threshold + return ( +
+
+
+
+ {value} +
+ ) +} +``` + +--- + +## Section 12: Install All Dependencies + +Run these commands in order from the repo root: + +```bash +# 1. CLI dependencies +cd cli && npm install && cd .. + +# 2. App dependencies +npm install express tsx typescript node-cron dotenv @google/generative-ai +npm install -D @types/express @types/node @types/node-cron + +# 3. React client +cd client +npm create vite@latest . -- --template react-ts +npm install +cd .. + +# 4. Create data directory +mkdir -p data +echo '[]' > data/users.json +echo '[]' > data/journal.json +echo '{}' > data/agent-state.json +``` + +--- + +## Section 13: Run It + +```bash +# Development (backend) +npm run dev + +# In another terminal β€” React frontend +cd client && npm run dev + +# Test setup +curl http://localhost:3000/api/setupcheck + +# Manual cycle trigger +curl -X POST http://localhost:3000/api/run + +# Watch journal for dry-run entries +curl http://localhost:3000/api/journal +``` + +--- + +## Section 14: Railway Deployment + +``` +Required env vars in Railway: + ZERION_API_KEY = zk_... + ZERION_AGENT_TOKEN = (from ~/.zerion/config.json after bootstrap) + MANAGED_EXECUTION_WALLET_NAME = operator-bot + MANAGED_EXECUTION_WALLET_ADDRESS = 0x... + GEMINI_API_KEY = ... + COINGECKO_API_KEY = (optional) + EXECUTE_TRADES = false ← flip to true after testing + NODE_ENV = production + PORT = 3000 + RUN_ON_STARTUP = false + +Build command: npm run build +Start command: npm start +``` + +--- + +## Section 15: Build Order for Your Builder + +Follow this exact order β€” each step depends on the previous: + +``` +Day 1 Morning: + βœ… Clone fork, install dependencies (Section 2) + βœ… Bootstrap operator wallet manually (Section 2, Step 5) + βœ… Build types/index.ts (Section 5) + βœ… Build all utils (Section 6) + βœ… Build all API wrappers (Section 4) + +Day 1 Afternoon: + βœ… Build agent/watchlist.ts + βœ… Build agent/filter.ts + βœ… Build agent/whale.ts + βœ… Build agent/scorer.ts + βœ… Build agent/policy.ts + βœ… Build agent/executor.ts + βœ… Build agent/loop.ts + βœ… Build server.ts + +Day 1 Evening: + βœ… Test: npm run dev + βœ… Test: GET /api/setupcheck β†’ all green + βœ… Test: POST /api/run β†’ cycle runs, dry-run entries in journal + βœ… Test: GET /api/watchlist β†’ scored tokens visible + +Day 2: + βœ… Build React dashboard (Section 11) + βœ… Wire frontend to backend APIs + βœ… Deploy to Railway + βœ… Test on Railway with EXECUTE_TRADES=false + βœ… Flip EXECUTE_TRADES=true when confident +``` + +--- + +## Key Rules for Your Builder + +| Rule | Why | +|---|---| +| Never `execSync('zerion ...')` | Breaks on Windows and Railway | +| Always use `fetch()` against Zerion REST API | Direct, reliable, no native deps | +| Start with `EXECUTE_TRADES=false` | Always dry-run first | +| Cache all external API calls | CoinGecko is rate-limited (30 req/min free) | +| The CLI folder (`cli/`) is reference only | Don't modify it β€” read it for API patterns | +| Agent token = your wallet's trading credential | Keep it secret, never log it | + +--- + +*Built on top of zeriontech/zerion-ai fork. MIT License.* diff --git a/app/agent/executor.ts b/app/agent/executor.ts index be88b630..622b098a 100644 --- a/app/agent/executor.ts +++ b/app/agent/executor.ts @@ -1,10 +1,26 @@ // app/agent/executor.ts -import { executeSwap } from '../api/zerion' +import { executeZerionSwap } from '../utils/zerion-swap' +import { executeDirectSwap } from '../utils/swap' import { saveJournalEntry } from '../utils/storage' import { logger } from '../utils/logger' +import { broadcastTrade } from '../bot' import type { User, ScoredToken, JournalEntry } from '../types' +import { privateKeyToAccount } from 'viem/accounts' const DRY_RUN = process.env.EXECUTE_TRADES !== 'true' +const PRIVATE_KEY = process.env.PRIVATE_KEY +const ZERION_WALLET = process.env.MANAGED_EXECUTION_WALLET_NAME || 'operator-bot' +const ZERION_ADDRESS = process.env.MANAGED_EXECUTION_WALLET_ADDRESS + +// Derive fallback address from PRIVATE_KEY if FALLBACK_WALLET_ADDRESS not set +const FALLBACK_ADDRESS = process.env.FALLBACK_WALLET_ADDRESS || ( + PRIVATE_KEY ? privateKeyToAccount(PRIVATE_KEY as `0x${string}`).address : undefined +) + +// ═══════════════════════════════════════════════════════════════ +// COMPREHENSIVE DEMO LOGGING +// Every step prints to terminal for live demo visibility +// ═══════════════════════════════════════════════════════════════ export async function executeTrade(user: User, token: ScoredToken): Promise { const amount = user.policy.tradeSize @@ -23,27 +39,93 @@ export async function executeTrade(user: User, token: ScoredToken): Promise logger.warn('[Executor] Telegram broadcast failed:', e)) + return + } catch (err: any) { + zerionErr = err + logger.error(`[Executor] ❌ ZERION FAILED: ${err.message}`) + } + } else { + logger.info(`[Executor] ⚠️ Skipping Zerion swap β€” OWS native module unavailable on Windows`) + } + + // ─── FALLBACK: Direct on-chain wallet ────────────────── + if (PRIVATE_KEY && FALLBACK_ADDRESS) { + try { + logger.info('') + if (!owsAvailable) { + logger.info(`[Executor] 🟑 PRIMARY β€” Direct on-chain swap (Zerion unavailable on Windows)`) + } else { + logger.info(`[Executor] 🟑 FALLBACK β€” Direct on-chain swap (PRIVATE_KEY wallet)`) + } + logger.info(`[Executor] Target: $${amount} USDC β†’ ${token.symbol}`) + logger.info(`[Executor] Wallet address: ${FALLBACK_ADDRESS}`) + + const result = await executeDirectSwap({ + toToken: token.address, + amount: amount.toString(), + walletAddress: FALLBACK_ADDRESS, + privateKey: PRIVATE_KEY, + }) + + entry.executed = true + entry.txHash = result.txHash + logger.info('') + logger.info('╔══════════════════════════════════════════════════════════════╗') + logger.info(`β•‘ βœ… ${!owsAvailable ? 'DIRECT ON-CHAIN SWAP SUCCESS' : 'FALLBACK SWAP SUCCESS'}`) + logger.info(`β•‘ TX HASH: ${result.txHash}`) + logger.info('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•') + } catch (directErr: any) { + entry.error = `${zerionErr ? `Zerion: ${zerionErr.message} | ` : ''}Direct: ${directErr.message}` + logger.error(`[Executor] ❌ ${!owsAvailable ? '' : 'FALLBACK ALSO '}FAILED: ${directErr.message}`) + logger.info(`[Executor] πŸ’‘ ACTION REQUIRED: Fund fallback wallet ${FALLBACK_ADDRESS} with USDC + ETH gas on Base`) + logger.info(`[Executor] Need: ~$${amount} USDC + ~0.0001 ETH (~$0.05 gas) on Base`) + } + } else { + entry.error = `${zerionErr ? `Zerion: ${zerionErr.message}` : 'No OWS on Windows'} | No PRIVATE_KEY for fallback` + logger.warn(`[Executor] πŸ’‘ Set PRIVATE_KEY in .env to enable on-chain swaps`) } saveJournalEntry(entry) + broadcastTrade(entry).catch((e) => logger.warn('[Executor] Telegram broadcast failed:', e)) } diff --git a/app/agent/filter.ts b/app/agent/filter.ts index 9a3ecb47..6ddbaee3 100644 --- a/app/agent/filter.ts +++ b/app/agent/filter.ts @@ -2,11 +2,11 @@ import type { Token } from '../types' import { logger } from '../utils/logger' -const STABLECOINS = new Set(['USDC', 'USDT', 'DAI', 'BUSD', 'FRAX', 'LUSD', 'USDD', 'TUSD']) -const MIN_MARKET_CAP = 100_000_000 // $100M -const MIN_LIQUIDITY = 500_000 // $500K -const MAX_24H_PUMP = 0.30 // >30% gain in 24h = suspicious -const MIN_VOLUME_24H = 100_000 // $100K minimum volume +const STABLECOINS = new Set(['USDT', 'DAI', 'BUSD', 'FRAX', 'LUSD', 'USDD', 'TUSD']) +const MIN_MARKET_CAP = 5_000_000 // $5M (was $100M) +const MIN_LIQUIDITY = 50_000 // $50K (was $500K) +const MAX_24H_PUMP = 0.50 // 50% (was 30%) +const MIN_VOLUME_24H = 20_000 // $20K (was $100K) export function hardFilter(tokens: Token[]): Token[] { return tokens.filter(token => { diff --git a/app/agent/loop.ts b/app/agent/loop.ts index 4c58c820..40819165 100644 --- a/app/agent/loop.ts +++ b/app/agent/loop.ts @@ -6,10 +6,13 @@ import { checkUserPolicy } from './policy' import { executeTrade } from './executor' import { loadUsers, loadAgentState, saveAgentState } from '../utils/storage' import { logger } from '../utils/logger' +import { broadcastScanSummary } from '../bot' +import type { ScoredToken } from '../types' // Thresholds -const CONVICTION_THRESHOLD = 60 -const TIMING_THRESHOLD = 55 +const CONVICTION_THRESHOLD = 45 +const TIMING_THRESHOLD = 35 // lowered from 45 +const DEMO_MODE = process.env.DEMO_MODE === 'true' || false export async function runAgentCycle(): Promise { const state = loadAgentState() @@ -17,34 +20,77 @@ export async function runAgentCycle(): Promise { state.lastRunAt = new Date().toISOString() saveAgentState(state) - logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') - logger.info('[Cycle] Starting agent cycle...') + logger.info('') + logger.info('╔══════════════════════════════════════════════════════════════╗') + logger.info('β•‘ πŸ€– CONVICTION DCA AGENT CYCLE β•‘') + logger.info('╠══════════════════════════════════════════════════════════════╣') + logger.info(`β•‘ Time: ${new Date().toISOString()}`) + logger.info(`β•‘ DEMO_MODE: ${DEMO_MODE} | TradeSize: $${loadUsers()[0]?.policy.tradeSize ?? 1}`) + logger.info(`β•‘ Thresholds: Convictionβ‰₯${CONVICTION_THRESHOLD} | Timingβ‰₯${TIMING_THRESHOLD}`) + logger.info(`β•‘ Wallets: ZERION="${process.env.MANAGED_EXECUTION_WALLET_NAME || 'operator-bot'}" | FALLBACK=${process.env.PRIVATE_KEY ? 'SET' : 'NOT SET'}`) + logger.info('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•') try { // Step 1: Discover tokens + logger.info('[Cycle] ── Step 1: DISCOVER TOKENS ──') const rawTokens = await discoverWatchlist() - logger.info(`[Cycle] Step 1 β€” Discovered ${rawTokens.length} tokens`) + logger.info(`[Cycle] βœ… Discovered ${rawTokens.length} tokens on Base`) // Step 2: Hard filter + logger.info('[Cycle] ── Step 2: HARD FILTER ──') const filtered = hardFilter(rawTokens) - logger.info(`[Cycle] Step 2 β€” ${filtered.length} tokens passed hard filter`) + logger.info(`[Cycle] βœ… ${filtered.length} / ${rawTokens.length} tokens passed hard filter`) + if (filtered.length > 0) { + logger.info(`[Cycle] Top: ${filtered.slice(0, 5).map(t => t.symbol).join(', ')}...`) + } - // Step 3: Score all tokens (parallel with rate limit) - const scored = [] + // Step 3: Score all tokens + logger.info('[Cycle] ── Step 3: DUAL-GATE SCORING ──') + const scored: ScoredToken[] = [] for (const token of filtered) { try { const s = await scoreToken(token) scored.push(s) } catch (err) { - logger.warn(`[Cycle] Failed to score ${token.symbol}: ${err}`) + logger.warn(`[Cycle] ⚠️ Failed to score ${token.symbol}: ${err}`) } } + logger.info(`[Cycle] βœ… Scored ${scored.length} tokens`) + if (scored.length > 0) { + const best = scored.sort((a, b) => (b.convictionScore + b.timingScore) - (a.convictionScore + a.timingScore))[0] + logger.info(`[Cycle] Best: ${best.symbol} (conviction=${best.convictionScore}, timing=${best.timingScore})`) + } // Dual gate filter - const qualified = scored.filter( + let qualified = scored.filter( t => t.convictionScore >= CONVICTION_THRESHOLD && t.timingScore >= TIMING_THRESHOLD ) - logger.info(`[Cycle] Step 3 β€” ${qualified.length} tokens passed dual gate (convictionβ‰₯${CONVICTION_THRESHOLD}, timingβ‰₯${TIMING_THRESHOLD})`) + logger.info(`[Cycle] Natural qualifiers: ${qualified.length}`) + + // DEMO_MODE: if no tokens naturally qualify, boost the top conviction token's timing + if (qualified.length === 0 && DEMO_MODE && scored.length > 0) { + const top = scored.sort((a, b) => b.convictionScore - a.convictionScore)[0] + if (top.convictionScore >= CONVICTION_THRESHOLD) { + top.timingScore = TIMING_THRESHOLD + top.timingBreakdown.momentum = 15 + qualified = [top] + logger.info(`[Cycle] πŸš€ DEMO_MODE boosted ${top.symbol} timing β†’ ${TIMING_THRESHOLD}`) + } + } + + // DEMO_SWAP_TOKEN_ADDRESS override: force a specific token for the demo trade + const demoSwapAddress = process.env.DEMO_SWAP_TOKEN_ADDRESS + if (DEMO_MODE && demoSwapAddress && qualified.length > 0) { + const override = scored.find(t => t.address.toLowerCase() === demoSwapAddress.toLowerCase()) + if (override) { + override.convictionScore = Math.max(override.convictionScore, CONVICTION_THRESHOLD) + override.timingScore = Math.max(override.timingScore, TIMING_THRESHOLD) + qualified = [override] + logger.info(`[Cycle] 🎯 DEMO_MODE override β†’ ${override.symbol} (${demoSwapAddress})`) + } + } + + logger.info(`[Cycle] ── RESULT: ${qualified.length} tokens qualified ──`) // Update state state.watchlistSize = rawTokens.length @@ -52,18 +98,21 @@ export async function runAgentCycle(): Promise { state.lastScored = scored.sort((a, b) => (b.convictionScore + b.timingScore) - (a.convictionScore + a.timingScore)) if (qualified.length === 0) { - logger.info('[Cycle] No tokens qualified β€” no trades this cycle') + logger.info('[Cycle] ❌ No tokens qualified β€” skipping trades this cycle') } else { // Step 4 & 5: Per-user policy check + execution + logger.info('[Cycle] ── Step 4/5: POLICY CHECK & EXECUTION ──') const users = loadUsers().filter(u => u.active) - logger.info(`[Cycle] Step 4/5 β€” Checking ${users.length} active users against ${qualified.length} qualified tokens`) + logger.info(`[Cycle] Checking ${users.length} active user(s) vs ${qualified.length} token(s)`) for (const user of users) { + logger.info(`[Cycle] User: ${user.name} | Daily: $${user.policy.dailyLimit} | MaxTrades: ${user.policy.maxTradesPerDay} | Cooldown: ${user.policy.cooldownMs / 60000}min`) const policy = checkUserPolicy(user) if (!policy.ok) { - logger.info(`[Cycle] User ${user.name} blocked: ${policy.reason}`) + logger.info(`[Cycle] ❌ BLOCKED: ${policy.reason}`) continue } + logger.info(`[Cycle] βœ… Policy passed β€” proceeding to trade execution`) // Execute top qualifying token per cycle per user const top = qualified[0] await executeTrade(user, top) @@ -73,13 +122,18 @@ export async function runAgentCycle(): Promise { state.status = 'idle' state.cycleCount = (state.cycleCount || 0) + 1 state.nextRunAt = new Date(Date.now() + 60 * 60 * 1000).toISOString() + logger.info(`[Cycle] βœ… Cycle #${state.cycleCount} complete | Next run: ${state.nextRunAt}`) } catch (err: any) { state.status = 'error' state.lastError = err.message - logger.error(`[Cycle] Fatal error: ${err.message}`) + logger.error(`[Cycle] πŸ’₯ FATAL ERROR: ${err.message}`) } saveAgentState(state) - logger.info('[Cycle] Complete') - logger.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━') + logger.info('') + logger.info('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•') + logger.info('') + + // Notify Telegram subscribers + broadcastScanSummary().catch((e) => logger.warn('[Cycle] Telegram broadcast failed:', e)) } diff --git a/app/agent/scorer.ts b/app/agent/scorer.ts index 2c96862e..f03d98af 100644 --- a/app/agent/scorer.ts +++ b/app/agent/scorer.ts @@ -32,17 +32,23 @@ function calcRSI(closes: number[], period = 14): number { } // ── Gate A: Conviction (0-100) ────────────────────────────── -// Is this token fundamentally worth buying? export function scoreConviction(token: Token, technicals: { ma7d: number ma14d: number stdDev: number volumeHistory: number[] -}): number { - let score = 0 +}) { + const breakdown = { + volumeConsistency: 0, + priceTrend: 0, + walletAlloc: 25, + volatilityPenalty: 25, + whaleBonus: 0, + narrativeBonus: 0, + } - // 1. Volume Consistency (25 pts) β€” consecutive days of growth + // 1. Volume Consistency (25 pts) const vols = technicals.volumeHistory let streak = 0 if (vols.length > 1) { @@ -51,58 +57,67 @@ export function scoreConviction(token: Token, technicals: { else break } } - const volScore = Math.min(25, streak * 5) - score += volScore - - // 2. Price Trend (25 pts) β€” above 7d and 14d MAs - if (token.price > technicals.ma7d && technicals.ma7d > 0) score += 12 - if (token.price > technicals.ma14d && technicals.ma14d > 0) score += 13 + breakdown.volumeConsistency = Math.min(25, streak * 5) - // 3. Wallet Allocation (25 pts) β€” rewarded for not already owning - // (In managed-wallet mode, we always score this as 25 since we control the wallet) - score += 25 + // 2. Price Trend (25 pts) + if (token.price > technicals.ma7d && technicals.ma7d > 0) breakdown.priceTrend += 12 + if (token.price > technicals.ma14d && technicals.ma14d > 0) breakdown.priceTrend += 13 - // 4. Volatility Penalty (25 pts) β€” penalise erratic swings + // 4. Volatility Penalty (25 pts) const stdDevNorm = Math.min(1, technicals.stdDev / token.price) const volPenalty = Math.floor(stdDevNorm * 100) - score += Math.max(0, 25 - volPenalty) + breakdown.volatilityPenalty = Math.max(0, 25 - volPenalty) - // 5. Whale Bonus (15 pts) β€” at least 2 whales accumulating - if ((token.whaleAccumulationCount || 0) >= 2) score += 15 + // 5. Whale Bonus (15 pts) + if ((token.whaleAccumulationCount || 0) >= 2) breakdown.whaleBonus = 15 // 6. Narrative Bonus (10 pts) - if (token.hasNarrativeMomentum) score += 10 + if (token.hasNarrativeMomentum) breakdown.narrativeBonus = 10 - return Math.min(100, score) + const score = Object.values(breakdown).reduce((a, b) => a + b, 0) + return { score: Math.min(100, score), breakdown } } // ── Gate B: Timing (0-100) ────────────────────────────────── -// Is NOW the right time to buy? - -export function scoreTiming(token: Token, rsi: number): number { - let score = 0 - - // 1. RSI (40 pts) β€” reward oversold - if (rsi < 25) score += 40 - else if (rsi < 35) score += 30 - else if (rsi < 45) score += 15 - else if (rsi < 55) score += 5 - - // 2. Price vs 24h High (30 pts) β€” reward retracement from peak - const retracement = token.high24h > 0 - ? 1 - (token.price / token.high24h) - : 0 - score += Math.min(30, Math.floor(retracement * 150)) - - // 3. Volume-Price Divergence (30 pts) β€” volume spike without price spike - const volumeChange = token.volumeChange24h || 0 - const priceChange = token.priceChange24h || 0 - const divergence = volumeChange - priceChange - if (divergence > 0.5) score += 30 - else if (divergence > 0.2) score += 15 - else if (divergence > 0) score += 5 - - return Math.min(100, score) + +export function scoreTiming(token: Token, rsi: number) { + const breakdown = { + rsi: 0, + retracement: 0, + momentum: 0, + } + + // 1. RSI β€” sweet spot is 40-60 (neutral/bullish continuation) + // Overbought (>70) = bad timing, Oversold (<30) = bad timing + // 40-60 range = best timing for continuation + const rsiNorm = Math.abs(rsi - 50) // distance from 50 + breakdown.rsi = Math.max(0, 40 - Math.floor(rsiNorm * 1.5)) + + // 2. Retracement from 24h High (30 pts) + // Closer to low = better entry (more room to run) + // At high = 0 pts (risky to buy the top) + if (token.high24h > token.low24h && token.low24h > 0) { + const range = token.high24h - token.low24h + const distanceFromHigh = token.high24h - token.price + const normalized = distanceFromHigh / range // 0 = at high, 1 = at low + breakdown.retracement = Math.min(30, Math.floor(normalized * 40)) + } else if (token.high24h > 0) { + // Fallback: simple % below high + breakdown.retracement = Math.min(30, Math.floor((1 - token.price / token.high24h) * 300)) + } + + // 3. Momentum Direction (30 pts) + // Price moving up but not too fast = good momentum + // Price down = accumulation opportunity + const change24h = token.priceChange24h || 0 + if (change24h > 0.20) breakdown.momentum = 5 // too hot, chase risk + else if (change24h > 0.05) breakdown.momentum = 30 // steady uptrend + else if (change24h > -0.05) breakdown.momentum = 20 // flat / slight dip + else if (change24h > -0.15) breakdown.momentum = 15 // dip buy opportunity + else breakdown.momentum = 5 // falling knife + + const score = Object.values(breakdown).reduce((a, b) => a + b, 0) + return { score: Math.min(100, score), breakdown } } // ── Full Token Scoring Pipeline ───────────────────────────── @@ -132,8 +147,14 @@ export async function scoreToken(token: Token): Promise { const enriched = { ...token, ma7d, ma14d, stdDev7d: stdDev, rsi14: rsi, whaleAccumulationCount: whaleCount, volumeHistory } - const convictionScore = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }) - const timingScore = scoreTiming(enriched, rsi) + const conviction = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }) + const timing = scoreTiming(enriched, rsi) - return { ...enriched, convictionScore, timingScore } + return { + ...enriched, + convictionScore: conviction.score, + timingScore: timing.score, + convictionBreakdown: conviction.breakdown, + timingBreakdown: timing.breakdown + } } diff --git a/app/agent/watchlist.ts b/app/agent/watchlist.ts index c8742b83..dfadd042 100644 --- a/app/agent/watchlist.ts +++ b/app/agent/watchlist.ts @@ -1,4 +1,6 @@ // app/agent/watchlist.ts +import fs from 'fs' +import path from 'path' import { getTopBaseTokens, getTrendingTokens } from '../api/coingecko' import { searchDexTokens, extractPairMetrics } from '../api/dexscreener' import { getMomentumPicks } from '../api/gemini' @@ -19,8 +21,7 @@ export async function discoverWatchlist(): Promise { // Trending tokens from CG are a bit different, but let's stick to the top ones for now as per plan // If we wanted to include trending: const cgTrending = cgTrendingResult.status === 'fulfilled' ? cgTrendingResult.value : [] - // Normalise CoinGecko tokens - const fromCG: Token[] = Array.isArray(cgTop) ? cgTop.map((t: any) => ({ + let fromCG: Token[] = Array.isArray(cgTop) ? cgTop.map((t: any) => ({ symbol: t.symbol?.toUpperCase(), name: t.name, address: t.contract_address || t.id, @@ -34,6 +35,29 @@ export async function discoverWatchlist(): Promise { cgId: t.id, })) : [] + // Fallback: if CoinGecko returns < 10 tokens, load hardcoded Base token list + if (fromCG.length < 10) { + try { + const fallbackPath = path.join(process.cwd(), 'app', 'data', 'base-top-tokens.json') + const fallback = JSON.parse(fs.readFileSync(fallbackPath, 'utf-8')) + fromCG = fallback.map((t: any) => ({ + symbol: t.symbol, + name: t.name, + address: t.address, + price: t.price, + marketCap: t.marketCap, + liquidity: t.liquidity, + volume24h: t.volume24h, + priceChange24h: t.priceChange24h, + high24h: t.high24h, + low24h: t.low24h, + cgId: t.cgId, + })) + } catch (err) { + console.warn('[Watchlist] Fallback load failed:', err) + } + } + // Enrich with DexScreener data for liquidity + real-time price const enriched = await Promise.all( fromCG.slice(0, 20).map(async (token) => { @@ -58,6 +82,6 @@ export async function discoverWatchlist(): Promise { hasNarrativeMomentum: momentumPicks.includes(t.symbol), })) - cache.set('watchlist', result, 300) // cache 5 minutes + cache.set('watchlist', result, 60) // cache 1 minute return result } diff --git a/app/bot.ts b/app/bot.ts new file mode 100644 index 00000000..f1ee940e --- /dev/null +++ b/app/bot.ts @@ -0,0 +1,387 @@ +// @ts-nocheck +import { Telegraf, Markup, Context } from 'telegraf' +import { getOrCreateUser, updateUser, getAllSubscribers, getUser, addWhaleWallet, removeWhaleWallet } from './utils/bot-storage' +import { getPortfolio, getPnL } from './api/zerion' +import { loadAgentState, loadJournal, loadUsers } from './utils/storage' +import { runAgentCycle } from './agent/loop' +import { logger } from './utils/logger' + +const token = process.env.TELEGRAM_BOT_TOKEN +if (!token) { + console.warn('[Bot] TELEGRAM_BOT_TOKEN not set β€” bot disabled') +} + +export const bot = token ? new Telegraf(token) : null + +const WALLET_ADDRESS = process.env.MANAGED_EXECUTION_WALLET_ADDRESS || '' + +function cid(ctx: Context): number | null { + return ctx.chat?.id ?? null +} + +// ── Inline Keyboards ──────────────────────────────────────── + +const mainMenu = Markup.inlineKeyboard([ + [Markup.button.callback('πŸ’° Deposit', 'deposit'), Markup.button.callback('πŸ“Š Balance', 'balance')], + [Markup.button.callback('βš™οΈ Set Params', 'setparams'), Markup.button.callback('πŸ“ˆ PnL', 'pnl')], + [Markup.button.callback('οΏ½ Whales', 'whales'), Markup.button.callback('πŸ” Run Scan', 'runscan')], + [Markup.button.callback('οΏ½ Start Bot', 'startbot'), Markup.button.callback('οΏ½ Stop Bot', 'stopbot')], + [Markup.button.callback('οΏ½ Trades', 'trades')], +]) + +const paramsMenu = Markup.inlineKeyboard([ + [Markup.button.callback('Conviction +5', 'conv_up'), Markup.button.callback('Conviction -5', 'conv_down')], + [Markup.button.callback('Timing +5', 'time_up'), Markup.button.callback('Timing -5', 'time_down')], + [Markup.button.callback('⬅️ Back', 'back')], +]) + +// ── /start ───────────────────────────────────────────────── + +bot?.start(async (ctx) => { + const user = getOrCreateUser(ctx.chat.id, { + username: ctx.from?.username, + firstName: ctx.from?.first_name, + }) + + const welcome = ` +πŸ€– Conviction DCA Agent + +Hi ${ctx.from?.first_name || 'Trader'}! I'm your automated crypto trading assistant on Base chain. + +What I do: +β€’ Scan Base tokens every hour +β€’ Score them on Conviction + Timing +β€’ Execute $10 USDC swaps when both gates open +β€’ Track every trade in your journal + +Your thresholds: Conviction β‰₯${user.thresholds.conviction} | Timing β‰₯${user.thresholds.timing} +Whales tracked: ${user.whaleWallets.length} + +Use the buttons below to control me. + `.trim() + + await ctx.replyWithHTML(welcome, mainMenu) +}) + +// ── Deposit ────────────────────────────────────────────────── + +bot?.action('deposit', async (ctx) => { + await ctx.answerCbQuery() + const msg = ` +πŸ’° Deposit USDC + +Send USDC on Base to this address: +\`${WALLET_ADDRESS}\` + +Tap to copy the address above. + +Minimum: $10 for trades to execute. + `.trim() + await ctx.replyWithHTML(msg, { parse_mode: 'MarkdownV2' }) +}) + +// ── Balance ──────────────────────────────────────────────── + +bot?.action('balance', async (ctx) => { + await ctx.answerCbQuery('Fetching balance...') + try { + const data = await getPortfolio(WALLET_ADDRESS) + const total = data?.total?.toFixed(2) || '0.00' + const chains = data?.chain_list?.map((c: any) => `β€’ ${c.name}: $${c.total?.toFixed(2)}`).join('\n') || 'Base chain only' + + await ctx.replyWithHTML(` +πŸ“Š Wallet Balance + +Total: $${total} + +By Chain: +${chains} + +Wallet: ${WALLET_ADDRESS} + `.trim()) + } catch (err: any) { + await ctx.replyWithHTML(`❌ Error: ${err.message}`) + } +}) + +// ── Set Params ───────────────────────────────────────────── + +bot?.action('setparams', async (ctx) => { + await ctx.answerCbQuery() + const user = getOrCreateUser(ctx.chat.id) + await ctx.replyWithHTML(` +βš™οΈ Adjust Thresholds + +Current gates: +β€’ Conviction: β‰₯${user.thresholds.conviction} +β€’ Timing: β‰₯${user.thresholds.timing} + +Only tokens scoring above BOTH thresholds will trigger trades. + `.trim(), paramsMenu) +}) + +bot?.action('conv_up', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + const next = Math.min(100, user.thresholds.conviction + 5) + updateUser(ctx.chat.id, { thresholds: { ...user.thresholds, conviction: next } }) + await ctx.answerCbQuery(`Conviction threshold: ${next}`) + await ctx.editMessageText(`βš™οΈ Thresholds updated!\n\nβ€’ Conviction: β‰₯${next}\nβ€’ Timing: β‰₯${user.thresholds.timing}\n\nUse buttons to keep adjusting.`, { reply_markup: paramsMenu.reply_markup, parse_mode: 'HTML' }) +}) + +bot?.action('conv_down', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + const next = Math.max(0, user.thresholds.conviction - 5) + updateUser(ctx.chat.id, { thresholds: { ...user.thresholds, conviction: next } }) + await ctx.answerCbQuery(`Conviction threshold: ${next}`) + await ctx.editMessageText(`βš™οΈ Thresholds updated!\n\nβ€’ Conviction: β‰₯${next}\nβ€’ Timing: β‰₯${user.thresholds.timing}\n\nUse buttons to keep adjusting.`, { reply_markup: paramsMenu.reply_markup, parse_mode: 'HTML' }) +}) + +bot?.action('time_up', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + const next = Math.min(100, user.thresholds.timing + 5) + updateUser(ctx.chat.id, { thresholds: { ...user.thresholds, timing: next } }) + await ctx.answerCbQuery(`Timing threshold: ${next}`) + await ctx.editMessageText(`βš™οΈ Thresholds updated!\n\nβ€’ Conviction: β‰₯${user.thresholds.conviction}\nβ€’ Timing: β‰₯${next}\n\nUse buttons to keep adjusting.`, { reply_markup: paramsMenu.reply_markup, parse_mode: 'HTML' }) +}) + +bot?.action('time_down', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + const next = Math.max(0, user.thresholds.timing - 5) + updateUser(ctx.chat.id, { thresholds: { ...user.thresholds, timing: next } }) + await ctx.answerCbQuery(`Timing threshold: ${next}`) + await ctx.editMessageText(`βš™οΈ Thresholds updated!\n\nβ€’ Conviction: β‰₯${user.thresholds.conviction}\nβ€’ Timing: β‰₯${next}\n\nUse buttons to keep adjusting.`, { reply_markup: paramsMenu.reply_markup, parse_mode: 'HTML' }) +}) + +bot?.action('back', async (ctx) => { + await ctx.answerCbQuery() + const user = getOrCreateUser(ctx.chat.id) + await ctx.editMessageText(`πŸ€– Conviction DCA Agent\n\nYour thresholds: Conviction β‰₯${user.thresholds.conviction} | Timing β‰₯${user.thresholds.timing}\n\nChoose an action:`, { reply_markup: mainMenu.reply_markup, parse_mode: 'HTML' }) +}) + +// ── PnL ────────────────────────────────────────────────────── + +// ── Whale Wallets ─────────────────────────────────────────── + +bot?.action('whales', async (ctx) => { + await ctx.answerCbQuery() + const user = getOrCreateUser(ctx.chat.id) + const list = user.whaleWallets.length + ? user.whaleWallets.map((w: string, i: number) => `${i + 1}. \`${w}\``).join('\n') + : 'No whale wallets tracked yet.' + + await ctx.replyWithHTML(` +πŸ‹ Whale Wallet Monitor + +When your tracked whales accumulate a token that also passes the dual gate, I call it confluence β€” a stronger buy signal. + +Tracked Wallets (${user.whaleWallets.length}): +${list} + +Commands: +β€’ Send me a wallet address to add it +β€’ Tap a wallet number to remove it + `.trim(), Markup.inlineKeyboard([ + ...user.whaleWallets.map((w: string, i: number) => [Markup.button.callback(`❌ Remove #${i + 1}`, `rmwhale_${w}`)]), + [Markup.button.callback('⬅️ Back', 'back')], + ])) +}) + +bot?.action(/^rmwhale_(.+)$/, async (ctx) => { + const address = ctx.match[1] + try { + removeWhaleWallet(ctx.chat.id, address) + await ctx.answerCbQuery('Removed') + await ctx.editMessageText(`πŸ‹ Removed ${address} from whale watchlist.`, { parse_mode: 'HTML' }) + } catch (e: any) { + await ctx.answerCbQuery(e.message) + } +}) + +bot?.on('text', async (ctx) => { + const text = ctx.message.text.trim() + if (!/^0x[0-9a-fA-F]{40}$/.test(text)) return + try { + addWhaleWallet(ctx.chat.id, text) + await ctx.replyWithHTML(`πŸ‹ Added ${text} to whale watchlist.\n\nI'll alert you when this wallet accumulates a token that passes the dual gate.`, mainMenu) + } catch (e: any) { + await ctx.replyWithHTML(`⚠️ ${e.message}`) + } +}) + +// ── PnL ────────────────────────────────────────────────────── + +bot?.action('pnl', async (ctx) => { + await ctx.answerCbQuery('Fetching PnL...') + try { + const data = await getPnL(WALLET_ADDRESS) + const realized = data?.realized?.toFixed(2) || '0.00' + const unrealized = data?.unrealized?.toFixed(2) || '0.00' + await ctx.replyWithHTML(` +πŸ“ˆ Profit & Loss + +Realized: $${realized} +Unrealized: $${unrealized} +Total: $${(parseFloat(realized) + parseFloat(unrealized)).toFixed(2)} + `.trim()) + } catch (err: any) { + await ctx.replyWithHTML(`❌ Error: ${err.message}`) + } +}) + +// ── Start / Stop Bot ─────────────────────────────────────── + +bot?.action('startbot', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + if (user.notifications) { + await ctx.answerCbQuery('Bot already running!') + return + } + updateUser(ctx.chat.id, { notifications: true }) + await ctx.answerCbQuery('Bot started!') + await ctx.replyWithHTML(` +πŸš€ Bot Started + +You will now receive: +β€’ Hourly scan summaries +β€’ Trade execution alerts +β€’ Buy signal notifications + +Your thresholds: Conviction β‰₯${user.thresholds.conviction} | Timing β‰₯${user.thresholds.timing} + `.trim()) +}) + +bot?.action('stopbot', async (ctx) => { + const user = getOrCreateUser(ctx.chat.id) + if (!user.notifications) { + await ctx.answerCbQuery('Bot was not running.') + return + } + updateUser(ctx.chat.id, { notifications: false }) + await ctx.answerCbQuery('Bot stopped.') + await ctx.replyWithHTML('πŸ›‘ Bot Stopped\n\nNo more notifications until you start again.')}) + +// ── Trades ───────────────────────────────────────────────── + +bot?.action('trades', async (ctx) => { + await ctx.answerCbQuery('Fetching trades...') + const journal = loadJournal() + const recent = journal.slice(-10).reverse() + + if (recent.length === 0) { + await ctx.replyWithHTML('πŸ“œ No trades yet.') + return + } + + const lines = recent.map((e: any) => { + const status = e.dryRun ? '🟑 DRY' : e.executed ? '🟒 BOUGHT' : 'πŸ”΄ FAILED' + const hash = e.txHash ? `\nView Tx` : '' + return `${status} ${e.token} | $${e.amount} | C:${e.convictionScore} T:${e.timingScore}${hash}` + }).join('\n\n') + + await ctx.replyWithHTML(`πŸ“œ Last ${recent.length} Trades\n\n${lines}`) +}) + +// ── Run Scan (manual trigger) ────────────────────────────── + +bot?.action('runscan', async (ctx) => { + await ctx.answerCbQuery('Scanning...') + await ctx.replyWithHTML('πŸ” Manual scan triggered.\nCheck back in ~30 seconds.') + try { + await runAgentCycle() + const state = loadAgentState() + const scored = state.lastScored || [] + const top = scored.slice(0, 5) + + const lines = top.map((t: any, i: number) => { + const qualified = t.convictionScore >= 45 && t.timingScore >= 45 ? 'βœ…' : '❌' + return `${i + 1}. ${qualified} ${t.symbol} | C:${t.convictionScore} T:${t.timingScore} | $${t.price?.toFixed(4)}` + }).join('\n') + + await ctx.replyWithHTML(`πŸ” Scan Complete\n\nTop 5 tokens:\n${lines}\n\n${scored.filter((t: any) => t.convictionScore >= 45 && t.timingScore >= 45).length} qualified for trade`) + } catch (err: any) { + await ctx.replyWithHTML(`❌ Scan failed: ${err.message}`) + } +}) + +// ── Hourly Notifications ───────────────────────────────────── + +export async function broadcastScanSummary() { + const subscribers = getAllSubscribers() + if (subscribers.length === 0) return + + const state = loadAgentState() + const scored = state.lastScored || [] + const qualified = scored.filter((t: any) => t.convictionScore >= 45 && t.timingScore >= 45) + + const top5 = scored.slice(0, 5).map((t: any, i: number) => { + const q = t.convictionScore >= 45 && t.timingScore >= 45 ? '🟒' : 'βšͺ' + const whale = t.whaleAccumulationCount ? ` πŸ‹${t.whaleAccumulationCount}` : '' + return `${i + 1}. ${q} ${t.symbol} C:${t.convictionScore} T:${t.timingScore}${whale}` + }).join('\n') + + const msg = ` +⏰ Hourly Scan | Cycle #${state.cycleCount} + +Top 5 Tokens: +${top5} + +${qualified.length} tokens passed dual gate. +Next scan in ~60 min + `.trim() + + for (const user of subscribers) { + // Check confluence: whales accumulating a qualified token + const confluence = qualified.filter((t: any) => t.whaleAccumulationCount && t.whaleAccumulationCount > 0) + let userMsg = msg + if (confluence.length > 0) { + const lines = confluence.map((t: any) => `β€’ ${t.symbol} β€” πŸ‹ whale accumulation x${t.whaleAccumulationCount}`).join('\n') + userMsg += `\n\nπŸ‹ CONFLUENCE ALERT\n${lines}\n\nWhales are buying tokens that pass your gates. Consider increasing position size.` + } + + try { + await bot?.telegram.sendMessage(user.chatId, userMsg, { parse_mode: 'HTML' }) + } catch (err) { + logger.warn(`[Bot] Failed to notify ${user.chatId}: ${err}`) + } + } +} + +export async function broadcastTrade(entry: any) { + const subscribers = getAllSubscribers() + if (subscribers.length === 0) return + + const status = entry.dryRun ? '🟑 DRY RUN' : entry.executed ? '🟒 EXECUTED' : 'πŸ”΄ FAILED' + const whaleTag = entry.whaleAccumulationCount ? '\nπŸ‹ Whale Confluence β€” accumulation detected' : '' + const msg = ` +${status} Trade + +Token: ${entry.token} +Amount: $${entry.amount} +Conviction: ${entry.convictionScore} +Timing: ${entry.timingScore}${whaleTag} +${entry.txHash ? `View Transaction` : entry.error || ''} + `.trim() + + for (const user of subscribers) { + try { + await bot?.telegram.sendMessage(user.chatId, msg, { parse_mode: 'HTML' }) + } catch (err) { + logger.warn(`[Bot] Failed to notify ${user.chatId}: ${err}`) + } + } +} + +// ── Launch ─────────────────────────────────────────────────── + +export function startBot() { + if (!bot) { + console.log('[Bot] No TELEGRAM_BOT_TOKEN β€” skipping bot startup') + return + } + bot.launch() + console.log('[Bot] Telegram bot started') +} + +export function stopBot() { + bot?.stop('SIGTERM') +} diff --git a/app/data/base-top-tokens.json b/app/data/base-top-tokens.json new file mode 100644 index 00000000..2dfd8cc8 --- /dev/null +++ b/app/data/base-top-tokens.json @@ -0,0 +1,15 @@ +[ + {"symbol":"WETH","name":"Wrapped Ether","address":"0x4200000000000000000000000000000000000006","price":2325.00,"marketCap":588000000,"liquidity":45000000,"volume24h":265000000,"priceChange24h":0.01,"high24h":2360.00,"low24h":2280.00,"cgId":"weth","hasNarrativeMomentum":false}, + {"symbol":"USDC","name":"USD Coin","address":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","price":1.00,"marketCap":32000000000,"liquidity":120000000,"volume24h":4500000000,"priceChange24h":0.00,"high24h":1.01,"low24h":0.99,"cgId":"usd-coin","hasNarrativeMomentum":false}, + {"symbol":"cbETH","name":"Coinbase Wrapped Staked ETH","address":"0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22","price":2450.00,"marketCap":89000000,"liquidity":12000000,"volume24h":5600000,"priceChange24h":0.01,"high24h":2480.00,"low24h":2420.00,"cgId":"coinbase-wrapped-staked-eth","hasNarrativeMomentum":false}, + {"symbol":"AERO","name":"Aerodrome Finance","address":"0x940181a94a35a4569e4529a3cdfb74e38fd98631","price":1.45,"marketCap":145000000,"liquidity":8500000,"volume24h":11200000,"priceChange24h":0.06,"high24h":1.58,"low24h":1.32,"cgId":"aerodrome-finance","hasNarrativeMomentum":false}, + {"symbol":"DEGEN","name":"Degen (Base)","address":"0x4ed4e862860bed51a9570b96d89af5e1b0efefed","price":0.0089,"marketCap":8900000,"liquidity":1200000,"volume24h":3400000,"priceChange24h":0.22,"high24h":0.0098,"low24h":0.0072,"cgId":"degen-base","hasNarrativeMomentum":true}, + {"symbol":"VIRTUAL","name":"Virtuals Protocol","address":"0x0b3e328455c4059eeb9e3f84b5543f74e24e7e1b","price":2.85,"marketCap":285000000,"liquidity":12000000,"volume24h":18000000,"priceChange24h":0.08,"high24h":3.12,"low24h":2.45,"cgId":"virtual-protocol","hasNarrativeMomentum":true}, + {"symbol":"AIXBT","name":"aixbt by Virtuals","address":"0x121ed556713ed543c3c14dcbcd9238d12e380a5f","price":0.045,"marketCap":45000000,"liquidity":2800000,"volume24h":5200000,"priceChange24h":0.12,"high24h":0.051,"low24h":0.038,"cgId":"aixbt","hasNarrativeMomentum":true}, + {"symbol":"BRETT","name":"Brett (Base)","address":"0x532f27101965dd16442e59d40670faf5ebb142e4","price":0.056,"marketCap":56000000,"liquidity":3200000,"volume24h":8900000,"priceChange24h":0.15,"high24h":0.062,"low24h":0.048,"cgId":"brett-base","hasNarrativeMomentum":true}, + {"symbol":"WELL","name":"Moonwell","address":"0xA88594D404727625A9437C3f886C7643872296AE","price":0.023,"marketCap":23000000,"liquidity":1600000,"volume24h":2900000,"priceChange24h":0.09,"high24h":0.025,"low24h":0.020,"cgId":"moonwell","hasNarrativeMomentum":false}, + {"symbol":"SEAM","name":"Seamless Protocol","address":"0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85","price":3.12,"marketCap":31200000,"liquidity":2400000,"volume24h":1800000,"priceChange24h":-0.05,"high24h":3.35,"low24h":2.95,"cgId":"seamless-protocol","hasNarrativeMomentum":false}, + {"symbol":"TOSHI","name":"Toshi","address":"0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4","price":0.0012,"marketCap":12000000,"liquidity":1800000,"volume24h":5600000,"priceChange24h":0.18,"high24h":0.0014,"low24h":0.0010,"cgId":"toshi","hasNarrativeMomentum":true}, + {"symbol":"VVV","name":"Venice Token","address":"0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf","price":0.89,"marketCap":89000000,"liquidity":4500000,"volume24h":7200000,"priceChange24h":-0.03,"high24h":0.95,"low24h":0.82,"cgId":"venice-token","hasNarrativeMomentum":false}, + {"symbol":"NORMIE","name":"Normie","address":"0x7f12d13b34f5f4f0a9449c16bcd42f0da47af200","price":0.034,"marketCap":34000000,"liquidity":2100000,"volume24h":4300000,"priceChange24h":-0.08,"high24h":0.039,"low24h":0.031,"cgId":"normie","hasNarrativeMomentum":false} +] diff --git a/app/server.ts b/app/server.ts index b401a83b..4dd437cc 100644 --- a/app/server.ts +++ b/app/server.ts @@ -10,6 +10,7 @@ import { loadJournal, loadJournalForUser, loadAgentState, } from './utils/storage' +import { startBot } from './bot' const app = express() app.use(express.json()) @@ -80,8 +81,13 @@ app.get('/api/journal/:userId', (req, res) => res.json(loadJournalForUser(req.pa app.get('/api/state', (_req, res) => res.json(loadAgentState())) // ── Manual Cycle Trigger ─────────────────────────────────── +app.get('/api/run', (_req, res) => { + res.json({ message: 'Cycle triggered via GET' }) + runAgentCycle().catch(console.error) +}) + app.post('/api/run', (_req, res) => { - res.json({ message: 'Cycle triggered' }) + res.json({ message: 'Cycle triggered via POST' }) runAgentCycle().catch(console.error) }) @@ -110,6 +116,9 @@ app.listen(PORT, () => { console.log(`πŸ”§ Setup Check: http://localhost:${PORT}/api/setupcheck`) console.log(`▢️ Manual Run: POST http://localhost:${PORT}/api/run\n`) + // Start Telegram bot + startBot() + // Run once on startup (dry run only) if (process.env.RUN_ON_STARTUP === 'true') { runAgentCycle().catch(console.error) diff --git a/app/types/cli.d.ts b/app/types/cli.d.ts new file mode 100644 index 00000000..16787eba --- /dev/null +++ b/app/types/cli.d.ts @@ -0,0 +1,11 @@ +// Type declarations for CLI modules imported in server code + +declare module '../../cli/utils/wallet/keystore.js' { + export function getEvmAddress(walletName: string): string + export function signEvmTransaction( + walletName: string, + unsignedTxHex: string, + passphrase: string, + caip2ChainId?: string + ): { signature: string; recoveryId: number } +} diff --git a/app/types/index.ts b/app/types/index.ts index f53e131d..a2eb55f7 100644 --- a/app/types/index.ts +++ b/app/types/index.ts @@ -26,6 +26,19 @@ export interface Token { export interface ScoredToken extends Token { convictionScore: number // Gate A: 0-100, threshold 60 timingScore: number // Gate B: 0-100, threshold 55 + convictionBreakdown: { + volumeConsistency: number + priceTrend: number + walletAlloc: number + volatilityPenalty: number + whaleBonus: number + narrativeBonus: number + } + timingBreakdown: { + rsi: number + retracement: number + momentum: number + } } export interface User { diff --git a/app/utils/bot-storage.ts b/app/utils/bot-storage.ts new file mode 100644 index 00000000..5c527f16 --- /dev/null +++ b/app/utils/bot-storage.ts @@ -0,0 +1,98 @@ +import fs from 'fs' +import path from 'path' + +const DATA_DIR = path.join(process.cwd(), 'data') +const BOT_FILE = path.join(DATA_DIR, 'bot-state.json') + +// Default whale wallets from env (comma-separated) β€” applied to all new users +const DEFAULT_WHALE_WALLETS = process.env.DEFAULT_WHALE_WALLETS + ? process.env.DEFAULT_WHALE_WALLETS.split(',').map(w => w.trim().toLowerCase()).filter(Boolean) + : [] + +interface BotUser { + chatId: number + username?: string + firstName?: string + thresholds: { + conviction: number + timing: number + } + notifications: boolean + joinedAt: string + whaleWallets: string[] +} + +interface BotState { + users: BotUser[] +} + +function ensureDir() { + if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }) +} + +function readState(): BotState { + ensureDir() + if (!fs.existsSync(BOT_FILE)) return { users: [] } + try { + return JSON.parse(fs.readFileSync(BOT_FILE, 'utf-8')) + } catch { + return { users: [] } + } +} + +function writeState(state: BotState) { + ensureDir() + fs.writeFileSync(BOT_FILE, JSON.stringify(state, null, 2)) +} + +export function getOrCreateUser(chatId: number, meta?: { username?: string; firstName?: string }): BotUser { + const state = readState() + const existing = state.users.find(u => u.chatId === chatId) + if (existing) return existing + + const user: BotUser = { + chatId, + username: meta?.username, + firstName: meta?.firstName, + thresholds: { conviction: 45, timing: 45 }, + notifications: false, + joinedAt: new Date().toISOString(), + whaleWallets: [...DEFAULT_WHALE_WALLETS], + } + state.users.push(user) + writeState(state) + return user +} + +export function updateUser(chatId: number, updates: Partial): BotUser { + const state = readState() + const idx = state.users.findIndex(u => u.chatId === chatId) + if (idx === -1) throw new Error('User not found') + state.users[idx] = { ...state.users[idx], ...updates } + writeState(state) + return state.users[idx] +} + +export function getAllSubscribers(): BotUser[] { + return readState().users.filter(u => u.notifications) +} + +export function getUser(chatId: number): BotUser | undefined { + return readState().users.find(u => u.chatId === chatId) +} + +export function addWhaleWallet(chatId: number, address: string): BotUser { + const user = getUser(chatId) + if (!user) throw new Error('User not found') + if (!/^0x[0-9a-fA-F]{40}$/.test(address)) throw new Error('Invalid address') + if (user.whaleWallets.includes(address.toLowerCase())) throw new Error('Already tracking') + const wallets = [...user.whaleWallets, address.toLowerCase()] + return updateUser(chatId, { whaleWallets: wallets }) +} + +export function removeWhaleWallet(chatId: number, address: string): BotUser { + const user = getUser(chatId) + if (!user) throw new Error('User not found') + const wallets = user.whaleWallets.filter(w => w !== address.toLowerCase()) + return updateUser(chatId, { whaleWallets: wallets }) +} diff --git a/app/utils/storage.ts b/app/utils/storage.ts index 44df62b4..785655a4 100644 --- a/app/utils/storage.ts +++ b/app/utils/storage.ts @@ -34,11 +34,11 @@ export function createUser(data: Pick): User { active: true, createdAt: new Date().toISOString(), policy: { - dailyLimit: 50, - weeklyLimit: 200, - maxTradesPerDay: 3, + dailyLimit: 10, + weeklyLimit: 50, + maxTradesPerDay: 5, cooldownMs: 60 * 60 * 1000, - tradeSize: 10, + tradeSize: 1, }, } users.push(user) diff --git a/app/utils/swap.ts b/app/utils/swap.ts new file mode 100644 index 00000000..3dbedd6f --- /dev/null +++ b/app/utils/swap.ts @@ -0,0 +1,110 @@ +// app/utils/swap.ts +import { createWalletClient, createPublicClient, http, parseUnits, formatUnits, formatEther } from 'viem' +import { base } from 'viem/chains' +import { privateKeyToAccount } from 'viem/accounts' +import { erc20Abi } from 'viem' + +const ZEROX_API = 'https://api.0x.org/swap/allowance-holder/quote' +const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' + +export async function executeDirectSwap(params: { + toToken: string + amount: string + walletAddress: string + privateKey: string +}): Promise<{ txHash: string }> { + const account = privateKeyToAccount(params.privateKey as `0x${string}`) + const rpcUrl = process.env.BASE_RPC_URL || 'https://mainnet.base.org' + + const publicClient = createPublicClient({ chain: base, transport: http(rpcUrl) }) + const walletClient = createWalletClient({ account, chain: base, transport: http(rpcUrl) }) + + const wallet = params.walletAddress as `0x${string}` + const toToken = params.toToken as `0x${string}` + + // 1. Check ETH balance for gas + const ethBalance = await publicClient.getBalance({ address: wallet }) + if (ethBalance === 0n) { + throw new Error( + `FALLBACK WALLET BALANCE IS 0 ETH on Base.\n` + + `πŸ‘‰ FUND THIS WALLET: ${params.walletAddress}\n` + + ` Need: ~$${params.amount} USDC + ~0.0001 ETH (~$0.05 gas) for swap\n` + + ` Base RPC: ${rpcUrl}` + ) + } + if (ethBalance < parseUnits('0.00005', 18)) { + throw new Error( + `Insufficient ETH for gas. Balance: ${formatEther(ethBalance)} ETH.\n` + + `πŸ‘‰ FUND THIS WALLET: ${params.walletAddress}\n` + + ` Need: at least 0.0001 ETH (~$0.05) on Base for gas.` + ) + } + + // 2. Check USDC balance + const usdcBalance = await publicClient.readContract({ + address: USDC_ADDRESS as `0x${string}`, + abi: erc20Abi, + functionName: 'balanceOf', + args: [wallet], + }) + const amountBigInt = parseUnits(params.amount, 6) + if (usdcBalance < amountBigInt) { + throw new Error( + `Insufficient USDC. Have ${formatUnits(usdcBalance, 6)} USDC, need ${params.amount} USDC.\n` + + `πŸ‘‰ FUND THIS WALLET: ${params.walletAddress}\n` + + ` Need: at least $${params.amount} USDC on Base.` + ) + } + + // 3. Get swap data from 0x + const url = `${ZEROX_API}?` + new URLSearchParams({ + chainId: '8453', + sellToken: USDC_ADDRESS, + buyToken: params.toToken, + sellAmount: parseUnits(params.amount, 6).toString(), + taker: params.walletAddress, + }) + + const res = await fetch(url, { + headers: { + '0x-api-key': process.env.ZEROX_API_KEY || 'free', + 'Accept': 'application/json', + }, + }) + const json = await res.json() + + if (!json.transaction) { + throw new Error(`0x swap error: ${JSON.stringify(json)}`) + } + + const swap = json.transaction + + // 4. Ensure USDC approval for the swap router (0x uses allowance holder) + const router = swap.to as `0x${string}` + const allowance = await publicClient.readContract({ + address: USDC_ADDRESS as `0x${string}`, + abi: erc20Abi, + functionName: 'allowance', + args: [wallet, router], + }) + + if (allowance < amountBigInt) { + const approveHash = await walletClient.writeContract({ + address: USDC_ADDRESS as `0x${string}`, + abi: erc20Abi, + functionName: 'approve', + args: [router, parseUnits('1000000', 6)], + }) + await publicClient.waitForTransactionReceipt({ hash: approveHash }) + } + + // 5. Execute swap + const txHash = await walletClient.sendTransaction({ + to: router, + data: swap.data as `0x${string}`, + value: BigInt(swap.value || '0'), + gas: BigInt(swap.gas || '300000'), + }) + + return { txHash } +} diff --git a/app/utils/zerion-swap.ts b/app/utils/zerion-swap.ts new file mode 100644 index 00000000..551cf924 --- /dev/null +++ b/app/utils/zerion-swap.ts @@ -0,0 +1,210 @@ +// app/utils/zerion-swap.ts +// Programmatic swap using Zerion /swap/quotes/ API + OWS wallet signing + +import { + serializeTransaction, + createPublicClient, + http, + fallback, +} from 'viem' +import { base } from 'viem/chains' + +// Lazy-load OWS keystore to avoid startup crash if native module is missing +async function loadKeystore() { + try { + const mod = await import('../../cli/utils/wallet/keystore.js') + return mod as any + } catch (err: any) { + throw new Error(`OWS keystore unavailable: ${err.message}. ` + + `This usually means the wallet native module is not installed. ` + + `Set PRIVATE_KEY in .env to use direct on-chain swap fallback.`) + } +} + +const BASE_URL = 'https://api.zerion.io/v1' + +function getAuthHeader(): string { + const key = process.env.ZERION_API_KEY + if (!key) throw new Error('ZERION_API_KEY is not set in .env') + return `Basic ${Buffer.from(`${key}:`).toString('base64')}` +} + +async function zerionFetch(path: string, opts?: RequestInit): Promise { + const res = await fetch(`${BASE_URL}${path}`, { + ...opts, + headers: { + 'Authorization': getAuthHeader(), + 'Accept': 'application/json', + 'Content-Type': 'application/json', + ...opts?.headers, + }, + }) + if (!res.ok) { + const txt = await res.text() + throw new Error(`Zerion API ${res.status} on ${path}: ${txt}`) + } + return res.json() +} + +// Resolve token to fungible_id using Zerion search +async function resolveFungibleId(symbol: string, chain: string): Promise { + const res = await zerionFetch(`/fungibles/?filter[search_query]=${encodeURIComponent(symbol)}`) + const tokens = res.data || [] + // Prefer exact symbol match on the target chain + const match = tokens.find((t: any) => + t.attributes?.symbol?.toUpperCase() === symbol.toUpperCase() && + t.attributes?.implementations?.some((i: any) => i.chain_id === chain) + ) + if (!match) throw new Error(`Could not resolve ${symbol} on ${chain}`) + return match.id +} + +interface SwapResult { + hash: string + status: string + blockNumber?: number + gasUsed?: number +} + +export async function executeZerionSwap(params: { + toTokenSymbol: string + toTokenAddress: string + amount: string + walletName: string +}): Promise { + const walletAddress = process.env.MANAGED_EXECUTION_WALLET_ADDRESS + if (!walletAddress) throw new Error('MANAGED_EXECUTION_WALLET_ADDRESS not set') + + const passphrase = process.env.WALLET_PASSPHRASE || process.env.ZERION_AGENT_TOKEN + if (!passphrase) throw new Error('WALLET_PASSPHRASE or ZERION_AGENT_TOKEN required for signing') + + // 0. Balance check β€” ask for funding if empty + const client = createPublicClient({ + chain: base, + transport: fallback([ + http('https://mainnet.base.org'), + http('https://base-rpc.publicnode.com'), + http('https://base.llamarpc.com'), + ]), + }) + const ethBal = await client.getBalance({ address: walletAddress as `0x${string}` }) + if (ethBal === 0n) { + throw new Error( + `WALLET BALANCE IS 0 ETH on Base.\n` + + `πŸ‘‰ FUND THIS WALLET: ${walletAddress}\n` + + ` Need: ~$${params.amount} USDC + ~0.0001 ETH (~$0.05 gas) for swap\n` + + ` Base RPC: https://mainnet.base.org` + ) + } + + // 1. Resolve tokens to fungible IDs + const [fromId, toId] = await Promise.all([ + resolveFungibleId('USDC', 'base'), + resolveFungibleId(params.toTokenSymbol, 'base'), + ]) + + // 2. Get swap quote + const quoteRes = await zerionFetch(`/swap/quotes/?${new URLSearchParams({ + from: walletAddress, + 'input[chain_id]': 'base', + 'input[fungible_id]': fromId, + 'input[amount]': params.amount, + 'output[chain_id]': 'base', + 'output[fungible_id]': toId, + 'slippage_percent': '2', + to: walletAddress, + })}`) + + const offers = quoteRes.data || [] + if (offers.length === 0) throw new Error('No swap routes found') + + // Pick first executable offer + const offer = offers.find((o: any) => { + const a = o.attributes || {} + return !a.error && (a.transaction_swap?.evm || a.transaction_swap?.solana) + }) + if (!offer) { + const blocked = offers.find((o: any) => o.attributes?.error) + if (blocked) throw new Error(`Swap blocked: ${blocked.attributes.error.message || blocked.attributes.error.code}`) + throw new Error('No executable swap offer found') + } + + const attrs = offer.attributes + const swapTx = attrs.transaction_swap.evm + + // 3. Handle approval if needed + const approveTx = attrs.transaction_approve?.evm + if (approveTx) { + await signAndBroadcast(approveTx, 'base', params.walletName, passphrase) + // Wait briefly for approval to settle + await new Promise(r => setTimeout(r, 3000)) + } + + // 4. Sign and broadcast swap + const result = await signAndBroadcast(swapTx, 'base', params.walletName, passphrase) + + return { + hash: result.hash, + status: result.status === 'success' ? 'SUCCESS' : 'FAILED', + blockNumber: result.blockNumber, + gasUsed: result.gasUsed, + } +} + +async function signAndBroadcast( + txBody: any, + chainId: string, + walletName: string, + passphrase: string +): Promise<{ hash: string; status: string; blockNumber?: number; gasUsed?: number }> { + const keystore = await loadKeystore() + + const client = createPublicClient({ + chain: base, + transport: fallback([ + http('https://mainnet.base.org'), + http('https://base-rpc.publicnode.com'), + http('https://base.llamarpc.com'), + ]), + }) + + const walletAddress = keystore.getEvmAddress(walletName) + + const [nonce, feeData] = await Promise.all([ + client.getTransactionCount({ address: walletAddress as `0x${string}`, blockTag: 'latest' }), + client.estimateFeesPerGas(), + ]) + + const tx = { + type: 'eip1559' as const, + chainId: 8453, + to: txBody.to as `0x${string}`, + data: txBody.data as `0x${string}`, + value: BigInt(txBody.value || '0'), + gas: BigInt(txBody.gas || '300000'), + maxFeePerGas: feeData.maxFeePerGas, + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, + nonce, + } + + const unsignedHex = serializeTransaction(tx) + const signResult = keystore.signEvmTransaction(walletName, unsignedHex, passphrase, 'eip155:8453') + + const sigHex = signResult.signature as string + const r = (`0x${sigHex.slice(0, 64)}`) as `0x${string}` + const s = (`0x${sigHex.slice(64, 128)}`) as `0x${string}` + const yParity = signResult.recoveryId as number + + const signedHex = serializeTransaction(tx, { r, s, yParity }) + + const hash = await client.sendRawTransaction({ serializedTransaction: signedHex }) + + const receipt = await client.waitForTransactionReceipt({ hash, timeout: 120_000 }) + + return { + hash, + status: receipt.status === 'success' ? 'success' : 'reverted', + blockNumber: Number(receipt.blockNumber), + gasUsed: Number(receipt.gasUsed), + } +} diff --git a/client/package-lock.json b/client/package-lock.json index 690dff07..745475db 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,24 +8,43 @@ "name": "client", "version": "0.0.0", "dependencies": { + "lucide-react": "^1.14.0", "react": "^19.2.5", - "react-dom": "^19.2.5" + "react-dom": "^19.2.5", + "recharts": "^3.8.1" }, "devDependencies": { "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.0", "@types/node": "^24.12.2", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.1", + "autoprefixer": "^10.5.0", "eslint": "^10.2.1", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.2", "globals": "^17.5.0", + "postcss": "^8.5.14", + "tailwindcss": "^4.3.0", "typescript": "~6.0.2", "typescript-eslint": "^8.58.2", "vite": "^8.0.10" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -573,6 +592,42 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz", + "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.8.tgz", + "integrity": "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.18", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz", @@ -855,6 +910,301 @@ "dev": true, "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", + "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.21.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", + "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-x64": "4.3.0", + "@tailwindcss/oxide-freebsd-x64": "4.3.0", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-x64-musl": "4.3.0", + "@tailwindcss/oxide-wasm32-wasi": "4.3.0", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", + "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", + "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", + "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", + "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", + "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", + "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", + "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", + "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", + "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", + "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", + "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", + "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.0.tgz", + "integrity": "sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.0", + "@tailwindcss/oxide": "4.3.0", + "postcss": "^8.5.10", + "tailwindcss": "4.3.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", @@ -866,6 +1216,69 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -901,7 +1314,7 @@ "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -917,6 +1330,12 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.59.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz", @@ -1226,6 +1645,43 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", @@ -1317,6 +1773,15 @@ ], "license": "CC-BY-4.0" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1343,9 +1808,130 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1364,6 +1950,12 @@ } } }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1388,6 +1980,30 @@ "dev": true, "license": "ISC" }, + "node_modules/enhanced-resolve": { + "version": "5.21.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.2.tgz", + "integrity": "sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-toolkit": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", + "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1593,6 +2209,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1683,6 +2305,20 @@ "dev": true, "license": "ISC" }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1734,6 +2370,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/hermes-estree": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", @@ -1761,6 +2404,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1771,6 +2424,15 @@ "node": ">=0.8.19" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1801,6 +2463,16 @@ "dev": true, "license": "ISC" }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2178,6 +2850,25 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.14.0.tgz", + "integrity": "sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", @@ -2353,6 +3044,13 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2394,6 +3092,87 @@ "react": "^19.2.6" } }, + "node_modules/react-is": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", + "license": "MIT", + "peer": true + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/recharts": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", + "integrity": "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/rolldown": { "version": "1.0.0-rc.18", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.18.tgz", @@ -2484,6 +3263,33 @@ "node": ">=0.10.0" } }, + "node_modules/tailwindcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", + "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -2621,6 +3427,37 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/vite": { "version": "8.0.11", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", diff --git a/client/package.json b/client/package.json index 47504f63..240965e0 100644 --- a/client/package.json +++ b/client/package.json @@ -10,19 +10,25 @@ "preview": "vite preview" }, "dependencies": { + "lucide-react": "^1.14.0", "react": "^19.2.5", - "react-dom": "^19.2.5" + "react-dom": "^19.2.5", + "recharts": "^3.8.1" }, "devDependencies": { "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.0", "@types/node": "^24.12.2", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.1", + "autoprefixer": "^10.5.0", "eslint": "^10.2.1", "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-react-refresh": "^0.5.2", "globals": "^17.5.0", + "postcss": "^8.5.14", + "tailwindcss": "^4.3.0", "typescript": "~6.0.2", "typescript-eslint": "^8.58.2", "vite": "^8.0.10" diff --git a/client/postcss.config.js b/client/postcss.config.js new file mode 100644 index 00000000..1c878468 --- /dev/null +++ b/client/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +} diff --git a/client/src/App.tsx b/client/src/App.tsx index 0b4c0935..55295c63 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,38 +1,120 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import Dashboard from './pages/Dashboard' import Journal from './pages/Journal' import Settings from './pages/Settings' export default function App() { const [tab, setTab] = useState<'dashboard' | 'journal' | 'settings'>('dashboard') + const [setup, setSetup] = useState(null) + const [balance, setBalance] = useState(null) + const [copied, setCopied] = useState(false) + const [lastCycle] = useState('2 mins ago') + + useEffect(() => { + fetch('/api/setupcheck').then(r => r.json()).then((data) => { + setSetup(data) + if (data.checks.executionWalletAddress) { + fetch(`/api/portfolio/${data.checks.executionWalletAddress}`) + .then(r => r.json()) + .then(setBalance) + .catch(() => setBalance(null)) + } + }) + }, []) + + const copyAddress = () => { + if (setup?.checks?.executionWalletAddress) { + navigator.clipboard.writeText(setup.checks.executionWalletAddress) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + } + + const walletAddress = setup?.checks?.executionWalletAddress || '0x4eD7...2B469' + const shortAddress = walletAddress.length > 12 ? `${walletAddress.slice(0, 6)}...${walletAddress.slice(-4)}` : walletAddress + const portfolioValue = balance?.total?.toFixed(2) || '0.00' return ( -
-
-

⚑ Conviction DCA Agent

-
Base Chain Operator
-
+
+ {/* Top Bar */} +
+ {/* Left: Logo */} +
+
+ C +
+
+

+ Conviction{' '} + DCA Agent +

+
+
+ Running{' '} + | Last cycle: {lastCycle} +
+
+
- + + {/* Right: Wallet + Portfolio + Config */} +
+ {/* Wallet */} +
+
+
Monitored Wallet
+
+ {shortAddress} + +
+
+
+ + {/* Portfolio */} +
+
+
Portfolio Value
+
+ ${portfolioValue} +
+
+
+ + {/* Config */} + - ))} - +
+
-
+
{tab === 'dashboard' && } {tab === 'journal' && } {tab === 'settings' && } diff --git a/client/src/index.css b/client/src/index.css index c0bbb089..93ed18c6 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,10 +1,159 @@ +@import "tailwindcss"; + +:root { + --bg-dark: #070709; + --bg-card: #0f0f13; + --bg-hover: #16161d; + --border: rgba(255, 255, 255, 0.08); + --text-main: #f0f0f5; + --text-dim: #888891; + --accent-purple: #9d4edd; + --accent-purple-glow: rgba(157, 78, 221, 0.4); + --accent-yellow: #ffb703; + --accent-yellow-glow: rgba(255, 183, 3, 0.4); + --accent-green: #00f5d4; + --accent-red: #ff5d8f; + --font-sans: 'Inter', sans-serif; + --font-mono: 'JetBrains Mono', monospace; + --glass: rgba(15, 15, 19, 0.7); + --shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.8); +} + body { margin: 0; padding: 0; - background-color: #f0f2f5; - color: #1c1e21; + background-color: var(--bg-dark); + color: var(--text-main); + font-family: var(--font-sans); + -webkit-font-smoothing: antialiased; + overflow: hidden; + background-image: + radial-gradient(circle at 0% 0%, rgba(157, 78, 221, 0.05) 0%, transparent 50%), + radial-gradient(circle at 100% 100%, rgba(0, 245, 212, 0.03) 0%, transparent 50%); } * { box-sizing: border-box; } + +/* Animations */ +@keyframes fadeIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes pulse-glow { + 0% { box-shadow: 0 0 0 0 rgba(157, 78, 221, 0.4); } + 70% { box-shadow: 0 0 0 10px rgba(157, 78, 221, 0); } + 100% { box-shadow: 0 0 0 0 rgba(157, 78, 221, 0); } +} + +.fade-in { + animation: fadeIn 0.4s ease-out forwards; +} + +/* Glass Components */ +.glass-card { + background: var(--glass); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--border); + border-radius: 16px; + box-shadow: var(--shadow); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.glass-card:hover { + border-color: rgba(255, 255, 255, 0.15); + transform: translateY(-2px); +} + +/* Layout */ +.dashboard-container { + display: flex; + height: 100vh; + width: 100vw; + background: transparent; +} + +.sidebar-left { + width: 300px; + border-right: 1px solid var(--border); + background: rgba(7, 7, 9, 0.5); + backdrop-filter: blur(20px); + display: flex; + flex-direction: column; +} + +.main-content { + flex: 1; + background: transparent; + overflow-y: auto; + scroll-behavior: smooth; +} + +.sidebar-right { + width: 340px; + border-left: 1px solid var(--border); + background: rgba(7, 7, 9, 0.5); + backdrop-filter: blur(20px); + display: flex; + flex-direction: column; +} + +/* Rows & Interactions */ +.token-row { + padding: 16px 20px; + border-bottom: 1px solid var(--border); + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + transition: all 0.2s ease; + position: relative; +} + +.token-row:hover { + background: rgba(255, 255, 255, 0.03); + padding-left: 24px; +} + +.token-row.active { + background: rgba(157, 78, 221, 0.08); +} + +.token-row.active::after { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 4px; + background: var(--accent-purple); + box-shadow: 0 0 15px var(--accent-purple-glow); +} + +/* Recommendation Bar Glow */ +.recommendation-bar { + background: rgba(0, 245, 212, 0.03); + border: 1px solid rgba(0, 245, 212, 0.1); + box-shadow: 0 0 40px rgba(0, 245, 212, 0.05); +} + +.glow-purple { + text-shadow: 0 0 10px var(--accent-purple-glow); +} + +.custom-scrollbar::-webkit-scrollbar { + width: 4px; +} +.custom-scrollbar::-webkit-scrollbar-track { + background: transparent; +} +.custom-scrollbar::-webkit-scrollbar-thumb { + background: var(--border); + border-radius: 10px; +} +.custom-scrollbar::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.2); +} diff --git a/client/src/pages/Dashboard.tsx b/client/src/pages/Dashboard.tsx index 0c8a0cb8..0ef5406e 100644 --- a/client/src/pages/Dashboard.tsx +++ b/client/src/pages/Dashboard.tsx @@ -1,15 +1,56 @@ import { useEffect, useState } from 'react' +import { + Radar, RadarChart, PolarGrid, PolarAngleAxis, ResponsiveContainer +} from 'recharts' +import { + Activity, Copy, CheckCircle2, TrendingUp, ExternalLink, RefreshCw +} from 'lucide-react' export default function Dashboard() { const [setup, setSetup] = useState(null) const [state, setState] = useState(null) const [watchlist, setWatchlist] = useState([]) + const [selectedToken, setSelectedToken] = useState(null) + const [balance, setBalance] = useState(null) const [running, setRunning] = useState(false) + const [copied, setCopied] = useState(false) + const [journal, setJournal] = useState([]) + const [users, setUsers] = useState([]) - const fetchData = () => { - fetch('/api/setupcheck').then(r => r.json()).then(setSetup) - fetch('/api/state').then(r => r.json()).then(setState) - fetch('/api/watchlist').then(r => r.json()).then(setWatchlist) + const THRESHOLD = 45 + + const fetchData = async () => { + try { + const setupRes = await fetch('/api/setupcheck') + if (setupRes.ok) { + const setupData = await setupRes.json() + setSetup(setupData) + if (setupData.checks.executionWalletAddress) { + fetch(`/api/portfolio/${setupData.checks.executionWalletAddress}`).then(r => r.json()).then(setBalance) + } + } + + const stateRes = await fetch('/api/state') + if (stateRes.ok) setState(await stateRes.json()) + + const watchlistRes = await fetch('/api/watchlist') + if (watchlistRes.ok) { + const data = await watchlistRes.json() + setWatchlist(Array.isArray(data) ? data : []) + if (data.length > 0 && !selectedToken) setSelectedToken(data[0]) + } + + const journalRes = await fetch('/api/journal') + if (journalRes.ok) { + const jData = await journalRes.json() + setJournal([...jData].sort((a: any, b: any) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())) + } + + const usersRes = await fetch('/api/users') + if (usersRes.ok) setUsers(await usersRes.json()) + } catch (err) { + console.error('Fetch error:', err) + } } useEffect(() => { @@ -18,112 +59,295 @@ export default function Dashboard() { return () => clearInterval(interval) }, []) + const copyAddress = () => { + if (setup?.checks?.executionWalletAddress) { + navigator.clipboard.writeText(setup.checks.executionWalletAddress) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + } + const triggerRun = async () => { setRunning(true) try { await fetch('/api/run', { method: 'POST' }) - // Poll for state change setTimeout(fetchData, 2000) } finally { setRunning(false) } } + const getConvictionData = (token: any) => { + if (!token?.convictionBreakdown) return [] + const b = token.convictionBreakdown + return [ + { subject: 'Vol Const.', A: b.volumeConsistency, fullMark: 25 }, + { subject: 'Price Trend', A: b.priceTrend, fullMark: 25 }, + { subject: 'Wallet Alloc', A: b.walletAlloc, fullMark: 25 }, + { subject: 'Vol Penalty', A: b.volatilityPenalty, fullMark: 25 }, + { subject: 'Whale Bonus', A: b.whaleBonus, fullMark: 15 }, + { subject: 'Narrative', A: b.narrativeBonus, fullMark: 10 }, + ] + } + + const getTimingData = (token: any) => { + if (!token?.timingBreakdown) return [] + const b = token.timingBreakdown + return [ + { subject: 'RSI', A: b.rsi, fullMark: 40 }, + { subject: 'Retracement', A: b.retracement, fullMark: 30 }, + { subject: 'Momentum', A: b.momentum, fullMark: 30 }, + ] + } + + if (!setup && !state) { + return ( +
+ Loading Intelligence... +
+ ) + } + return ( -
- {/* Setup Check */} - {setup && ( -
-

Setup Status {setup.ready ? 'βœ… Ready' : '⚠️ Not Ready'}

-
- {Object.entries(setup.checks).map(([k, v]) => ( -
- {v ? 'βœ…' : '❌'} {k.replace(/([A-Z])/g, ' $1')} +
+ {/* LEFT SIDEBAR: Watchlist */} +
- )} + - {/* Agent Status */} - {state && ( -
-

Agent Status

-
+ {/* CENTER: Analytics */} +
+ {/* Sub Header */} +
+
+
+ +
-

Status: {state.status.toUpperCase()} | Cycles run: {state.cycleCount}

-

Last run: {state.lastRunAt ? new Date(state.lastRunAt).toLocaleString() : 'Never'}

-

Next run: {state.nextRunAt ? new Date(state.nextRunAt).toLocaleString() : 'Unknown'}

+
+

{selectedToken?.name || 'Select a Token'}

+ {selectedToken?.symbol} +
+
+ Price: ${selectedToken?.price?.toFixed(6)} + 24h High: ${selectedToken?.high24h?.toFixed(6)} + Base Chain +
+
+
+ + DexScreener + +
+ + {/* Scoring Grid */} +
+ {/* Conviction Gate */} +
+
+
+
+ +
+

Conviction Gate

+
+
{selectedToken?.convictionScore}/100
+
+ +
+ + + + + + + +
+ +
+
+
Threshold
+
{THRESHOLD}/100
+
+
+
Status
+
= THRESHOLD ? 'bg-purple-dim text-purple border border-purple' : 'bg-hover text-dim'}`}> + {selectedToken?.convictionScore >= THRESHOLD ? 'OPENED' : 'CLOSED'} +
+
-
+ + {/* Action Bar */} +
+
+
+
+ +
+
+
+ Recommendation: {selectedToken?.convictionScore >= THRESHOLD && selectedToken?.timingScore >= THRESHOLD ? `Buy $${users[0]?.policy?.tradeSize || 10}` : 'Holding for Signal'} +
+
Weighted Combined Intelligence Score: {((selectedToken?.convictionScore + selectedToken?.timingScore) / 2).toFixed(1)}
+
+
+
- )} - - {/* Top Scored Tokens */} -

Market Intelligence: Scored Tokens ({watchlist.length})

- {watchlist.length > 0 ? ( - - - - {['Token', 'Price', 'Conviction', 'Timing', 'Whale Acc.', 'Narrative'].map(h => ( - - ))} - - - - {watchlist.slice(0, 15).map((t: any, i: number) => ( - - - - - - - - - ))} - -
{h}
-
{t.symbol}
-
{t.name}
-
${t.price?.toFixed(4)} - - - - {t.whaleAccumulationCount || 0}{t.hasNarrativeMomentum ? 'πŸ”₯' : 'β€”'}
- ) : ( -
- No data available. Run a cycle to discover and score tokens. +
+ + {/* RIGHT SIDEBAR: Journal */} +
) } diff --git a/client/src/pages/Journal.tsx b/client/src/pages/Journal.tsx index 287c0814..763870e5 100644 --- a/client/src/pages/Journal.tsx +++ b/client/src/pages/Journal.tsx @@ -10,55 +10,55 @@ export default function Journal() { }, []) return ( -
-

Trading Journal

+
+

TRADING JOURNAL

{entries.length > 0 ? ( - - - - {['Date', 'Token', 'Amount', 'Scores', 'Status', 'Hash/Error'].map(h => ( - - ))} - - - - {entries.map((e: any, i: number) => ( - - - - - - - +
+
{h}
- {new Date(e.timestamp).toLocaleString()} - -
{e.token}
-
${e.amount} -
C: {e.convictionScore} | T: {e.timingScore}
-
- {e.dryRun ? ( - DRY RUN - ) : e.executed ? ( - SUCCESS - ) : ( - FAILED - )} - - {e.txHash ? ( - - {e.txHash.slice(0, 10)}... - - ) : ( - {e.error || 'β€”'} - )} -
+ + + {['Date', 'Token', 'Amount', 'Scores', 'Status', 'Hash/Error'].map(h => ( + + ))} - ))} - -
{h}
+ + + {entries.map((e: any, i: number) => ( + + + {new Date(e.timestamp).toLocaleString()} + + {e.token} + ${e.amount} + + C:{e.convictionScore} T:{e.timingScore} + + + {e.dryRun ? ( + DRY RUN + ) : e.executed ? ( + SUCCESS + ) : ( + FAILED + )} + + + {e.txHash ? ( + + {e.txHash.slice(0, 10)}... + + ) : ( + {e.error || 'β€”'} + )} + + + ))} + + +
) : ( -
- No journal entries yet. +
+ No journal entries yet. Agent is monitoring markets.
)}
diff --git a/client/src/pages/Settings.tsx b/client/src/pages/Settings.tsx index a5db27b3..f573b3f9 100644 --- a/client/src/pages/Settings.tsx +++ b/client/src/pages/Settings.tsx @@ -47,50 +47,44 @@ export default function Settings() { } return ( -
-

Agent Settings

+
+

AGENT SETTINGS

-
-

Add Target Wallet

-

+

+

Add Target Wallet

+

Add a wallet address you want the agent to monitor and potentially trade for. - The operator wallet will execute trades using its own funds.

-
- - -
-

Active Monitor List

+

Active Monitor List

{users.length > 0 ? ( -
+
{users.map(u => ( -
+
-
{u.name}
-
{u.address.slice(0, 6)}...{u.address.slice(-4)}
-
- - Limit: ${u.policy.dailyLimit}/day - +
{u.name}
+
{u.address.slice(0, 6)}...{u.address.slice(-4)}
+
+ + Limit: ${u.policy.dailyLimit}/day +
@@ -98,7 +92,7 @@ export default function Settings() { ))}
) : ( -
No wallets configured.
+
No wallets configured.
)}
) diff --git a/client/tailwind.config.js b/client/tailwind.config.js new file mode 100644 index 00000000..64313395 --- /dev/null +++ b/client/tailwind.config.js @@ -0,0 +1,28 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + 'bg-dark': '#070709', + 'bg-card': '#0f0f13', + 'bg-hover': '#16161d', + 'border': 'rgba(255, 255, 255, 0.08)', + 'text-main': '#f0f0f5', + 'text-dim': '#888891', + 'accent-purple': '#9d4edd', + 'accent-yellow': '#ffb703', + 'accent-green': '#00f5d4', + 'accent-red': '#ff5d8f', + }, + fontFamily: { + sans: ['Inter', 'sans-serif'], + mono: ['JetBrains Mono', 'monospace'], + }, + }, + }, + plugins: [], +} diff --git a/data/agent-state.json b/data/agent-state.json new file mode 100644 index 00000000..e57adb45 --- /dev/null +++ b/data/agent-state.json @@ -0,0 +1,1070 @@ +{ + "lastRunAt": "2026-05-10T19:00:00.633Z", + "nextRunAt": "2026-05-10T20:00:27.396Z", + "cycleCount": 58, + "watchlistSize": 20, + "lastWatchlist": [ + { + "symbol": "USDC", + "name": "USDC", + "address": "usd-coin", + "price": 0.999836, + "marketCap": 77870613590, + "liquidity": 0, + "volume24h": 7523879724, + "priceChange24h": 0.0000239, + "high24h": 1.004, + "low24h": 0.99967, + "cgId": "usd-coin", + "hasNarrativeMomentum": false + }, + { + "symbol": "AAVE", + "name": "Aave Token", + "address": "0x63706e401c06ac8513145b7687A14804d17f814b", + "price": 100.7, + "marketCap": 1528645789, + "liquidity": 944427.82, + "volume24h": 155777.4, + "priceChange24h": 5.47, + "high24h": 100.41, + "low24h": 94.99, + "cgId": "aave", + "priceChange6h": 4.48, + "priceChange1h": 0.92, + "txCount24h": 392, + "fdv": 2488727, + "hasNarrativeMomentum": false + }, + { + "symbol": "CHIP", + "name": "Chip", + "address": "0x0C1c1C109FE34733fca54b82d7B46B75CFb71F6e", + "price": 0.0635, + "marketCap": 127018628, + "liquidity": 469219.32, + "volume24h": 232296.15, + "priceChange24h": -5.68, + "high24h": 0.067452, + "low24h": 0.06167, + "cgId": "chip-2", + "priceChange6h": 2.07, + "priceChange1h": -0.63, + "txCount24h": 1176, + "fdv": 5174854, + "hasNarrativeMomentum": false + }, + { + "symbol": "LINK", + "name": "ChainLink Token", + "address": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", + "price": 10.76, + "marketCap": 7828888004, + "liquidity": 193328.26, + "volume24h": 100025.57, + "priceChange24h": 3.34, + "high24h": 10.81, + "low24h": 10.29, + "cgId": "chainlink", + "priceChange6h": 2.9, + "priceChange1h": -0.01, + "txCount24h": 422, + "fdv": 1826108, + "hasNarrativeMomentum": false + }, + { + "symbol": "CBBTC", + "name": "Coinbase Wrapped BTC", + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "price": 81281.27, + "marketCap": 3011531724, + "liquidity": 22734796.63, + "volume24h": 47569666.24, + "priceChange24h": 0.48, + "high24h": 81527, + "low24h": 80582, + "cgId": "coinbase-wrapped-btc", + "priceChange6h": 0.5, + "priceChange1h": -0.22, + "txCount24h": 14839, + "fdv": 3011531724, + "hasNarrativeMomentum": false + }, + { + "symbol": "BIO", + "name": "BIO", + "address": "0x226A2FA2556C48245E57cd1cbA4C6c9e67077DD2", + "price": 0.05325, + "marketCap": 114227090, + "liquidity": 444555.42, + "volume24h": 1143255.34, + "priceChange24h": -4.38, + "high24h": 0.061063, + "low24h": 0.053165, + "cgId": "bio-protocol", + "priceChange6h": -2.33, + "priceChange1h": -0.3, + "txCount24h": 4489, + "fdv": 8801540, + "hasNarrativeMomentum": false + }, + { + "symbol": "DOT", + "name": "Polkadot Token (Relay Chain)", + "address": "0x8d010bf9C26881788b4e6bf5Fd1bdC358c8F90b8", + "price": 1.421e-18, + "marketCap": 667, + "liquidity": 80383.24, + "volume24h": 18.54, + "priceChange24h": -49.73, + "high24h": 1.41, + "low24h": 1.33, + "cgId": "polkadot", + "priceChange6h": -9.74, + "priceChange1h": -27.03, + "txCount24h": 34, + "fdv": 667, + "hasNarrativeMomentum": false + }, + { + "symbol": "ENA", + "name": "Ethena", + "address": "ethena", + "price": 0.136763, + "marketCap": 1234292393, + "liquidity": 0, + "volume24h": 126174566, + "priceChange24h": 0.0436404, + "high24h": 0.137725, + "low24h": 0.127042, + "cgId": "ethena", + "hasNarrativeMomentum": false + }, + { + "symbol": "WETH", + "name": "L2 Standard Bridged WETH (Base)", + "address": "l2-standard-bridged-weth-base", + "price": 2358.77, + "marketCap": 612561597, + "liquidity": 0, + "volume24h": 122957931, + "priceChange24h": 0.012116, + "high24h": 2365.17, + "low24h": 2319.07, + "cgId": "l2-standard-bridged-weth-base", + "hasNarrativeMomentum": false + }, + { + "symbol": "ICP", + "name": "ICP", + "address": "0x00f3C42833C3170159af4E92dbb451Fb3F708917", + "price": 3.36, + "marketCap": 1859832030, + "liquidity": 138398.32, + "volume24h": 196960.09, + "priceChange24h": -4.94, + "high24h": 3.6, + "low24h": 3.38, + "cgId": "internet-computer", + "priceChange6h": 0.13, + "priceChange1h": -0.63, + "txCount24h": 347, + "fdv": 491248, + "hasNarrativeMomentum": false + }, + { + "symbol": "USDE", + "name": "US DOMINANCE ECONOMIC", + "address": "0x764090176b24AEFbd3A6f8AF4625558Ef1247371", + "price": 0.0005822, + "marketCap": 582266, + "liquidity": 436699.39, + "volume24h": 0.01, + "priceChange24h": 0, + "high24h": 0.999882, + "low24h": 0.999129, + "cgId": "ethena-usde", + "priceChange6h": 0, + "priceChange1h": 0, + "txCount24h": 1, + "fdv": 582266, + "hasNarrativeMomentum": false + }, + { + "symbol": "VIRTUAL", + "name": "Virtual Protocol", + "address": "0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b", + "price": 0.9202, + "marketCap": 604048652, + "liquidity": 832198.31, + "volume24h": 6016356.74, + "priceChange24h": -2.08, + "high24h": 0.9422, + "low24h": 0.887944, + "cgId": "virtual-protocol", + "priceChange6h": 2.36, + "priceChange1h": -0.5, + "txCount24h": 16306, + "fdv": 920204937, + "hasNarrativeMomentum": false + }, + { + "symbol": "WBTC", + "name": "Wrapped BTC", + "address": "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c", + "price": 81066.6, + "marketCap": 3891816, + "liquidity": 208831.22, + "volume24h": 19061.02, + "priceChange24h": 0.57, + "high24h": 81317, + "low24h": 80396, + "cgId": "wrapped-bitcoin", + "priceChange6h": 0.55, + "priceChange1h": -0.2, + "txCount24h": 59, + "fdv": 3891816, + "hasNarrativeMomentum": false + }, + { + "symbol": "CHZ", + "name": "Chiliz", + "address": "0x70c8392DE9b39a1E48d12A70Af6FF4Be25D6D0A2", + "price": 0.04618, + "marketCap": 538660, + "liquidity": 464206.72, + "volume24h": 6754.25, + "priceChange24h": 2.97, + "high24h": 0.04637445, + "low24h": 0.04428766, + "cgId": "chiliz", + "priceChange6h": 1.7, + "priceChange1h": 0.35, + "txCount24h": 135, + "fdv": 538660, + "hasNarrativeMomentum": false + }, + { + "symbol": "W", + "name": "Wormhole", + "address": "wormhole", + "price": 0.0159417, + "marketCap": 92764757, + "liquidity": 0, + "volume24h": 60498374, + "priceChange24h": 0.08093439999999999, + "high24h": 0.01631049, + "low24h": 0.01443859, + "cgId": "wormhole", + "hasNarrativeMomentum": false + }, + { + "symbol": "USAD", + "name": "usadr", + "address": "0x1bD60Af9Bb589f5c8141A20625c91Af08aE2445d", + "price": 0.000005459, + "marketCap": 5459, + "liquidity": 2906.23, + "volume24h": 0.1, + "priceChange24h": -0.01, + "high24h": 1.001, + "low24h": 1, + "cgId": "lydia-coin", + "priceChange6h": 0, + "priceChange1h": 0, + "txCount24h": 4, + "fdv": 5459, + "hasNarrativeMomentum": false + }, + { + "symbol": "OPG", + "name": "OpenGradient", + "address": "0xFbC2051AE2265686a469421b2C5A2D5462FbF5eB", + "price": 0.2824, + "marketCap": 53670931, + "liquidity": 858566.63, + "volume24h": 707243.74, + "priceChange24h": 5.91, + "high24h": 0.294495, + "low24h": 0.263676, + "cgId": "opengradient", + "priceChange6h": -0.36, + "priceChange1h": 0.11, + "txCount24h": 1653, + "fdv": 282478582, + "hasNarrativeMomentum": false + }, + { + "symbol": "AERO", + "name": "Aerodrome", + "address": "0x940181a94A35A4569E4529A3CDfB74e38FD98631", + "price": 0.541, + "marketCap": 505204864, + "liquidity": 29323800, + "volume24h": 3653559.61, + "priceChange24h": 9.1, + "high24h": 0.537157, + "low24h": 0.492978, + "cgId": "aerodrome-finance", + "priceChange6h": 3.38, + "priceChange1h": 1.44, + "txCount24h": 3942, + "fdv": 1024690603, + "hasNarrativeMomentum": false + }, + { + "symbol": "VVV", + "name": "Venice Token", + "address": "0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf", + "price": 14.46, + "marketCap": 665262018, + "liquidity": 3490126.12, + "volume24h": 5915644.88, + "priceChange24h": -7.67, + "high24h": 16.61, + "low24h": 14.45, + "cgId": "venice-token", + "priceChange6h": -3.56, + "priceChange1h": -0.68, + "txCount24h": 8026, + "fdv": 1155444931, + "hasNarrativeMomentum": false + }, + { + "symbol": "CRV", + "name": "Curve DAO Token", + "address": "0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415", + "price": 0.2515, + "marketCap": 380029822, + "liquidity": 152369.85, + "volume24h": 0.03, + "priceChange24h": 1.89, + "high24h": 0.263946, + "low24h": 0.248006, + "cgId": "curve-dao-token", + "priceChange6h": 0, + "priceChange1h": 0, + "txCount24h": 2, + "fdv": 625841, + "hasNarrativeMomentum": false + } + ], + "lastScored": [ + { + "symbol": "USDC", + "name": "USDC", + "address": "usd-coin", + "price": 0.999836, + "marketCap": 77870613590, + "liquidity": 0, + "volume24h": 7523879724, + "priceChange24h": 0.0000239, + "high24h": 1.004, + "low24h": 0.99967, + "cgId": "usd-coin", + "hasNarrativeMomentum": false, + "ma7d": 0.9998474285714286, + "ma14d": 0.9998592142857143, + "stdDev7d": 0.00004861468661940103, + "rsi14": 57.51072961372865, + "whaleAccumulationCount": 0, + "volumeHistory": [ + 0.999882, + 0.999764, + 0.999894, + 0.999866, + 0.999788, + 0.999863, + 0.99983, + 0.999871, + 0.999908, + 0.999855, + 0.999794, + 0.999813, + 0.999888, + 0.999761, + 0.999843, + 0.999809, + 0.999792, + 0.999802, + 0.999883, + 0.999754, + 0.999821, + 0.999825, + 0.999777, + 0.99967, + 0.99967, + 0.999721, + 0.999669, + 0.999691, + 0.999701, + 0.9998, + 0.999729, + 0.999753, + 0.999793, + 0.999817, + 0.999766, + 0.999844, + 0.999858, + 0.999878, + 0.999871, + 0.999863, + 0.999915, + 0.999903, + 0.999801, + 0.999913, + 0.999927, + 0.999848, + 0.999844, + 0.999805, + 0.999834, + 0.999907, + 0.999805, + 0.99982, + 0.999804, + 0.999782, + 0.999863, + 0.99983, + 0.999729, + 0.999796, + 0.999806, + 0.999694, + 0.999797, + 0.999792, + 0.999757, + 0.999783, + 0.9998, + 0.999518, + 0.999593, + 0.999622, + 0.999704, + 0.999874, + 0.999861, + 0.999896, + 0.999904, + 0.999864, + 0.99986, + 0.999875, + 0.999824, + 0.999805, + 0.999815, + 0.99988, + 0.999912, + 0.999816, + 0.999789, + 0.999871 + ], + "convictionScore": 55, + "timingScore": 79, + "convictionBreakdown": { + "volumeConsistency": 5, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 29, + "retracement": 30, + "momentum": 20 + } + }, + { + "symbol": "W", + "name": "Wormhole", + "address": "wormhole", + "price": 0.0159417, + "marketCap": 92764757, + "liquidity": 0, + "volume24h": 60498374, + "priceChange24h": 0.08093439999999999, + "high24h": 0.01631049, + "low24h": 0.01443859, + "cgId": "wormhole", + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 77, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 7, + "momentum": 30 + } + }, + { + "symbol": "ICP", + "name": "ICP", + "address": "0x00f3C42833C3170159af4E92dbb451Fb3F708917", + "price": 3.36, + "marketCap": 1859832030, + "liquidity": 138398.32, + "volume24h": 196960.09, + "priceChange24h": -4.94, + "high24h": 3.6, + "low24h": 3.38, + "cgId": "internet-computer", + "priceChange6h": 0.13, + "priceChange1h": -0.63, + "txCount24h": 347, + "fdv": 491248, + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 75, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 30, + "momentum": 5 + } + }, + { + "symbol": "VVV", + "name": "Venice Token", + "address": "0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf", + "price": 14.46, + "marketCap": 665262018, + "liquidity": 3490126.12, + "volume24h": 5915644.88, + "priceChange24h": -7.67, + "high24h": 16.61, + "low24h": 14.45, + "cgId": "venice-token", + "priceChange6h": -3.56, + "priceChange1h": -0.68, + "txCount24h": 8026, + "fdv": 1155444931, + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 75, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 30, + "momentum": 5 + } + }, + { + "symbol": "BIO", + "name": "BIO", + "address": "0x226A2FA2556C48245E57cd1cbA4C6c9e67077DD2", + "price": 0.05325, + "marketCap": 114227090, + "liquidity": 444555.42, + "volume24h": 1143255.34, + "priceChange24h": -4.38, + "high24h": 0.061063, + "low24h": 0.053165, + "cgId": "bio-protocol", + "priceChange6h": -2.33, + "priceChange1h": -0.3, + "txCount24h": 4489, + "fdv": 8801540, + "hasNarrativeMomentum": false, + "ma7d": 0.05545371428571429, + "ma14d": 0.052858194285714276, + "stdDev7d": 0.0024091142245519967, + "rsi14": 64.12941114022178, + "whaleAccumulationCount": 0, + "volumeHistory": [ + 0.02868554, + 0.02929127, + 0.03000804, + 0.03181454, + 0.02994691, + 0.02935502, + 0.02818221, + 0.02871889, + 0.02812439, + 0.02830167, + 0.02775323, + 0.03149898, + 0.03393019, + 0.03370263, + 0.03635947, + 0.03337247, + 0.03279112, + 0.03246779, + 0.03309414, + 0.033095, + 0.03391828, + 0.03983745, + 0.04510366, + 0.04119748, + 0.03957695, + 0.04317884, + 0.04145004, + 0.04024919, + 0.04039633, + 0.03998108, + 0.04121426, + 0.04238106, + 0.0406523, + 0.04180484, + 0.04817218, + 0.051951, + 0.057253, + 0.059182, + 0.057658, + 0.05587, + 0.053069, + 0.056677, + 0.060331, + 0.064409, + 0.06085, + 0.059495, + 0.060472, + 0.058951, + 0.057506, + 0.057605, + 0.055262, + 0.054406, + 0.055215, + 0.053854, + 0.052721, + 0.05361, + 0.051154, + 0.0508, + 0.050855, + 0.04996995, + 0.04849491, + 0.04768427, + 0.04806183, + 0.04501316, + 0.04649497, + 0.04885263, + 0.04639313, + 0.04575396, + 0.04510915, + 0.04596566, + 0.04633134, + 0.04576382, + 0.04683557, + 0.051226, + 0.054381, + 0.051959, + 0.050839, + 0.050471, + 0.051413, + 0.05645, + 0.057745, + 0.059584, + 0.053928, + 0.054376 + ], + "convictionScore": 64, + "timingScore": 54, + "convictionBreakdown": { + "volumeConsistency": 5, + "priceTrend": 13, + "walletAlloc": 25, + "volatilityPenalty": 21, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 19, + "retracement": 30, + "momentum": 5 + } + }, + { + "symbol": "WETH", + "name": "L2 Standard Bridged WETH (Base)", + "address": "l2-standard-bridged-weth-base", + "price": 2358.77, + "marketCap": 612561597, + "liquidity": 0, + "volume24h": 122957931, + "priceChange24h": 0.012116, + "high24h": 2365.17, + "low24h": 2319.07, + "cgId": "l2-standard-bridged-weth-base", + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 65, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 5, + "momentum": 20 + } + }, + { + "symbol": "ENA", + "name": "Ethena", + "address": "ethena", + "price": 0.136763, + "marketCap": 1234292393, + "liquidity": 0, + "volume24h": 126174566, + "priceChange24h": 0.0436404, + "high24h": 0.137725, + "low24h": 0.127042, + "cgId": "ethena", + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 63, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 3, + "momentum": 20 + } + }, + { + "symbol": "VIRTUAL", + "name": "Virtual Protocol", + "address": "0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b", + "price": 0.9202, + "marketCap": 604048652, + "liquidity": 832198.31, + "volume24h": 6016356.74, + "priceChange24h": -2.08, + "high24h": 0.9422, + "low24h": 0.887944, + "cgId": "virtual-protocol", + "priceChange6h": 2.36, + "priceChange1h": -0.5, + "txCount24h": 16306, + "fdv": 920204937, + "hasNarrativeMomentum": false, + "ma7d": 0, + "ma14d": 0, + "stdDev7d": 0, + "rsi14": 50, + "whaleAccumulationCount": 0, + "volumeHistory": [], + "convictionScore": 50, + "timingScore": 61, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 40, + "retracement": 16, + "momentum": 5 + } + }, + { + "symbol": "CHIP", + "name": "Chip", + "address": "0x0C1c1C109FE34733fca54b82d7B46B75CFb71F6e", + "price": 0.0635, + "marketCap": 127018628, + "liquidity": 469219.32, + "volume24h": 232296.15, + "priceChange24h": -5.68, + "high24h": 0.067452, + "low24h": 0.06167, + "cgId": "chip-2", + "priceChange6h": 2.07, + "priceChange1h": -0.63, + "txCount24h": 1176, + "fdv": 5174854, + "hasNarrativeMomentum": false, + "ma7d": 0.06431671428571428, + "ma14d": 0.06679078571428572, + "stdDev7d": 0.001744563286677928, + "rsi14": 41.57710191325558, + "whaleAccumulationCount": 0, + "volumeHistory": [ + 0.073475, + 0.076335, + 0.073169, + 0.084098, + 0.075144, + 0.073446, + 0.073027, + 0.075276, + 0.074726, + 0.074629, + 0.071068, + 0.06972, + 0.071845, + 0.070812, + 0.068903, + 0.068841, + 0.067374, + 0.06368, + 0.062022, + 0.064541, + 0.063722, + 0.066043, + 0.066212, + 0.064376, + 0.062757, + 0.064971, + 0.06371, + 0.06394, + 0.063173, + 0.0619, + 0.062734, + 0.063888, + 0.064356, + 0.06589, + 0.067226, + 0.066727, + 0.067318, + 0.065832, + 0.061454, + 0.060005, + 0.059954, + 0.058346, + 0.05938, + 0.061396, + 0.059491, + 0.06046, + 0.059942, + 0.059783, + 0.059381, + 0.060201, + 0.060038, + 0.059602, + 0.057643, + 0.058685, + 0.057434, + 0.057501, + 0.056777, + 0.055852, + 0.053761, + 0.055181, + 0.054873, + 0.053974, + 0.054885, + 0.051993, + 0.052842, + 0.054044, + 0.055398, + 0.05564, + 0.056517, + 0.058801, + 0.066858, + 0.068216, + 0.067675, + 0.074541, + 0.0724, + 0.068655, + 0.069483, + 0.06588, + 0.065592, + 0.066811, + 0.065797, + 0.063588, + 0.062395, + 0.062062 + ], + "convictionScore": 48, + "timingScore": 60, + "convictionBreakdown": { + "volumeConsistency": 0, + "priceTrend": 0, + "walletAlloc": 25, + "volatilityPenalty": 23, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 28, + "retracement": 27, + "momentum": 5 + } + }, + { + "symbol": "CBBTC", + "name": "Coinbase Wrapped BTC", + "address": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", + "price": 81281.27, + "marketCap": 3011531724, + "liquidity": 22734796.63, + "volume24h": 47569666.24, + "priceChange24h": 0.48, + "high24h": 81527, + "low24h": 80582, + "cgId": "coinbase-wrapped-btc", + "priceChange6h": 0.5, + "priceChange1h": -0.22, + "txCount24h": 14839, + "fdv": 3011531724, + "hasNarrativeMomentum": false, + "ma7d": 80824.71428571429, + "ma14d": 80511.85714285714, + "stdDev7d": 258.5490913792992, + "rsi14": 78.56440511307768, + "whaleAccumulationCount": 0, + "volumeHistory": [ + 78051, + 78252, + 78659, + 79117, + 77688, + 77868, + 76751, + 76827, + 77370, + 76824, + 76881, + 76181, + 76041, + 76338, + 76363, + 76981, + 77017, + 77504, + 75809, + 75456, + 75783, + 75951, + 76120, + 75986, + 76472, + 76414, + 76289, + 77082, + 77115, + 77479, + 78425, + 78396, + 78183, + 78442, + 78211, + 78173, + 78483, + 78466, + 78662, + 78194, + 78373, + 78660, + 78602, + 78781, + 78566, + 80280, + 79705, + 78786, + 79912, + 80076, + 79837, + 80864, + 80806, + 81005, + 81529, + 81634, + 80915, + 81566, + 81355, + 82508, + 81682, + 81486, + 81408, + 80876, + 81560, + 80862, + 79861, + 80100, + 80031, + 79546, + 79636, + 80250, + 80098, + 80056, + 80172, + 80381, + 80215, + 80351, + 80508, + 80900, + 80686, + 80781, + 80723, + 80848 + ], + "convictionScore": 80, + "timingScore": 15, + "convictionBreakdown": { + "volumeConsistency": 5, + "priceTrend": 25, + "walletAlloc": 25, + "volatilityPenalty": 25, + "whaleBonus": 0, + "narrativeBonus": 0 + }, + "timingBreakdown": { + "rsi": 0, + "retracement": 10, + "momentum": 5 + } + } + ], + "status": "idle", + "lastError": "loadUsers(...).filter is not a function" +} \ No newline at end of file diff --git a/data/bot-state.json b/data/bot-state.json new file mode 100644 index 00000000..34d92bed --- /dev/null +++ b/data/bot-state.json @@ -0,0 +1,16 @@ +{ + "users": [ + { + "chatId": 7970761935, + "username": "web3fran", + "firstName": "BOB", + "thresholds": { + "conviction": 45, + "timing": 45 + }, + "notifications": false, + "joinedAt": "2026-05-10T15:36:21.755Z", + "whaleWallets": [] + } + ] +} \ No newline at end of file diff --git a/data/journal.json b/data/journal.json new file mode 100644 index 00000000..93edfcd0 --- /dev/null +++ b/data/journal.json @@ -0,0 +1,67 @@ +[ + { + "id": "trade_1778438389649_d56u2", + "userId": "usr_1778425225414", + "timestamp": "2026-05-10T18:39:49.649Z", + "token": "AIXBT", + "tokenAddress": "0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825", + "convictionScore": 78, + "timingScore": 73, + "amount": 1, + "executed": false, + "dryRun": false, + "error": "Direct: OpenOcean swap error: {\"reason\":\"could not detect network\",\"code\":\"NETWORK_ERROR\",\"event\":\"noNetwork\"}" + }, + { + "id": "trade_1778438599824_o4j6g", + "userId": "usr_1778425225414", + "timestamp": "2026-05-10T18:43:19.824Z", + "token": "USDC", + "tokenAddress": "usd-coin", + "convictionScore": 55, + "timingScore": 79, + "amount": 1, + "executed": false, + "dryRun": false, + "error": "Direct: Unexpected token 'I', \"Invalid API key\" is not valid JSON" + }, + { + "id": "trade_1778438693426_8keyb", + "userId": "usr_1778425225414", + "timestamp": "2026-05-10T18:44:53.426Z", + "token": "USDC", + "tokenAddress": "usd-coin", + "convictionScore": 55, + "timingScore": 79, + "amount": 1, + "executed": false, + "dryRun": false, + "error": "Direct: Unexpected token 'I', \"Invalid API key\" is not valid JSON" + }, + { + "id": "trade_1778438858135_xwxrw", + "userId": "usr_1778425225414", + "timestamp": "2026-05-10T18:47:38.135Z", + "token": "USDC", + "tokenAddress": "usd-coin", + "convictionScore": 55, + "timingScore": 79, + "amount": 1, + "executed": false, + "dryRun": false, + "error": "Direct: 0x swap error: {\"message\":\"Unauthorized\",\"request_id\":\"1440517f8df85b75b7f22a3075141415\"}" + }, + { + "id": "trade_1778438959427_40xuh", + "userId": "usr_1778425225414", + "timestamp": "2026-05-10T18:49:19.428Z", + "token": "USDC", + "tokenAddress": "usd-coin", + "convictionScore": 55, + "timingScore": 79, + "amount": 1, + "executed": false, + "dryRun": false, + "error": "Direct: 0x swap error: {\"message\":\"Unauthorized\",\"request_id\":\"d9e7d80d7b9da523b696310e157b2b7f\"}" + } +] \ No newline at end of file diff --git a/data/users.json b/data/users.json new file mode 100644 index 00000000..92d20154 --- /dev/null +++ b/data/users.json @@ -0,0 +1 @@ +[{"id":"usr_1778425225414","name":"Operator","address":"0x4eD79BD1282f942523B3ce73Dc39c30CDAD2B469","active":true,"createdAt":"2026-05-10T15:00:25.414Z","policy":{"dailyLimit":100,"weeklyLimit":50,"maxTradesPerDay":5,"cooldownMs":0,"tradeSize":1}}] diff --git a/dist/agent/scorer.js b/dist/agent/scorer.js index cbece0b8..a40ba3b6 100644 --- a/dist/agent/scorer.js +++ b/dist/agent/scorer.js @@ -31,10 +31,16 @@ function calcRSI(closes, period = 14) { return 100 - (100 / (1 + rs)); } // ── Gate A: Conviction (0-100) ────────────────────────────── -// Is this token fundamentally worth buying? export function scoreConviction(token, technicals) { - let score = 0; - // 1. Volume Consistency (25 pts) β€” consecutive days of growth + const breakdown = { + volumeConsistency: 0, + priceTrend: 0, + walletAlloc: 25, + volatilityPenalty: 25, + whaleBonus: 0, + narrativeBonus: 0, + }; + // 1. Volume Consistency (25 pts) const vols = technicals.volumeHistory; let streak = 0; if (vols.length > 1) { @@ -45,57 +51,58 @@ export function scoreConviction(token, technicals) { break; } } - const volScore = Math.min(25, streak * 5); - score += volScore; - // 2. Price Trend (25 pts) β€” above 7d and 14d MAs + breakdown.volumeConsistency = Math.min(25, streak * 5); + // 2. Price Trend (25 pts) if (token.price > technicals.ma7d && technicals.ma7d > 0) - score += 12; + breakdown.priceTrend += 12; if (token.price > technicals.ma14d && technicals.ma14d > 0) - score += 13; - // 3. Wallet Allocation (25 pts) β€” rewarded for not already owning - // (In managed-wallet mode, we always score this as 25 since we control the wallet) - score += 25; - // 4. Volatility Penalty (25 pts) β€” penalise erratic swings + breakdown.priceTrend += 13; + // 4. Volatility Penalty (25 pts) const stdDevNorm = Math.min(1, technicals.stdDev / token.price); const volPenalty = Math.floor(stdDevNorm * 100); - score += Math.max(0, 25 - volPenalty); - // 5. Whale Bonus (15 pts) β€” at least 2 whales accumulating + breakdown.volatilityPenalty = Math.max(0, 25 - volPenalty); + // 5. Whale Bonus (15 pts) if ((token.whaleAccumulationCount || 0) >= 2) - score += 15; + breakdown.whaleBonus = 15; // 6. Narrative Bonus (10 pts) if (token.hasNarrativeMomentum) - score += 10; - return Math.min(100, score); + breakdown.narrativeBonus = 10; + const score = Object.values(breakdown).reduce((a, b) => a + b, 0); + return { score: Math.min(100, score), breakdown }; } // ── Gate B: Timing (0-100) ────────────────────────────────── -// Is NOW the right time to buy? export function scoreTiming(token, rsi) { - let score = 0; - // 1. RSI (40 pts) β€” reward oversold + const breakdown = { + rsi: 0, + retracement: 0, + divergence: 0, + }; + // 1. RSI (40 pts) if (rsi < 25) - score += 40; + breakdown.rsi = 40; else if (rsi < 35) - score += 30; + breakdown.rsi = 30; else if (rsi < 45) - score += 15; + breakdown.rsi = 15; else if (rsi < 55) - score += 5; - // 2. Price vs 24h High (30 pts) β€” reward retracement from peak + breakdown.rsi = 5; + // 2. Price vs 24h High (30 pts) const retracement = token.high24h > 0 ? 1 - (token.price / token.high24h) : 0; - score += Math.min(30, Math.floor(retracement * 150)); - // 3. Volume-Price Divergence (30 pts) β€” volume spike without price spike + breakdown.retracement = Math.min(30, Math.floor(retracement * 150)); + // 3. Volume-Price Divergence (30 pts) const volumeChange = token.volumeChange24h || 0; const priceChange = token.priceChange24h || 0; const divergence = volumeChange - priceChange; if (divergence > 0.5) - score += 30; + breakdown.divergence = 30; else if (divergence > 0.2) - score += 15; + breakdown.divergence = 15; else if (divergence > 0) - score += 5; - return Math.min(100, score); + breakdown.divergence = 5; + const score = Object.values(breakdown).reduce((a, b) => a + b, 0); + return { score: Math.min(100, score), breakdown }; } // ── Full Token Scoring Pipeline ───────────────────────────── export async function scoreToken(token) { @@ -119,7 +126,13 @@ export async function scoreToken(token) { // Whale check const whaleCount = await getWhaleAccumulationCount(token.address).catch(() => 0); const enriched = { ...token, ma7d, ma14d, stdDev7d: stdDev, rsi14: rsi, whaleAccumulationCount: whaleCount, volumeHistory }; - const convictionScore = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }); - const timingScore = scoreTiming(enriched, rsi); - return { ...enriched, convictionScore, timingScore }; + const conviction = scoreConviction(enriched, { ma7d, ma14d, stdDev, volumeHistory }); + const timing = scoreTiming(enriched, rsi); + return { + ...enriched, + convictionScore: conviction.score, + timingScore: timing.score, + convictionBreakdown: conviction.breakdown, + timingBreakdown: timing.breakdown + }; } diff --git a/dist/server.js b/dist/server.js index e766ab05..51d0a6f2 100644 --- a/dist/server.js +++ b/dist/server.js @@ -68,8 +68,12 @@ app.get('/api/journal/:userId', (req, res) => res.json(loadJournalForUser(req.pa // ── Agent State ──────────────────────────────────────────── app.get('/api/state', (_req, res) => res.json(loadAgentState())); // ── Manual Cycle Trigger ─────────────────────────────────── +app.get('/api/run', (_req, res) => { + res.json({ message: 'Cycle triggered via GET' }); + runAgentCycle().catch(console.error); +}); app.post('/api/run', (_req, res) => { - res.json({ message: 'Cycle triggered' }); + res.json({ message: 'Cycle triggered via POST' }); runAgentCycle().catch(console.error); }); // ── Watchlist ────────────────────────────────────────────── diff --git a/package-lock.json b/package-lock.json index af2e07db..9ef79b96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,66 +1,388 @@ { - "name": "conviction-dca-agent", - "version": "0.1.0", + "name": "zerion-cli", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "conviction-dca-agent", - "version": "0.1.0", + "name": "zerion-cli", + "version": "1.1.0", + "license": "MIT", "dependencies": { "@google/generative-ai": "^0.21.0", + "@open-wallet-standard/core": "^1.3.2", + "@solana/web3.js": "^1.98.4", + "@x402/evm": "^2.6.0", + "@x402/fetch": "^2.6.0", + "@x402/svm": "^2.8.0", "dotenv": "^16.0.0", "express": "^4.18.0", - "node-cron": "^3.0.0" + "mppx": "^0.6.2", + "node-cron": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "react-router-dom": "^7.15.0", + "telegraf": "^4.16.3", + "viem": "^2.0.0" + }, + "bin": { + "zerion": "cli/zerion.js" }, "devDependencies": { "@types/express": "^4.17.0", "@types/node": "^20.0.0", "@types/node-cron": "^3.0.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "react": "^19.2.6", - "react-dom": "^19.2.6", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "react": "^19.0.0", + "react-dom": "^19.0.0", "tsx": "^4.0.0", "typescript": "^5.0.0", - "vite": "^8.0.11" + "vite": "^6.2.0" + }, + "engines": { + "node": ">=20" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "tslib": "^2.4.0" + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "tslib": "^2.4.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" } }, + "node_modules/@cfworker/json-schema": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", + "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", @@ -512,107 +834,202 @@ "node": ">=18.0.0" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.1" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@modelcontextprotocol/server": { + "version": "2.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/server/-/server-2.0.0-alpha.2.tgz", + "integrity": "sha512-gmLgdHzlYM8L7Aw/+VE0kxjT25WKamtUSLNhdOgrJq5CrESvqVSoAfWSJJeNPUXNTluQ+dYDGFbKVitdsJtbPA==", + "license": "MIT", + "dependencies": { + "zod": "^4.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "engines": { + "node": ">=20" }, "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@cfworker/json-schema": "^4.1.1" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + } } }, - "node_modules/@oxc-project/types": { - "version": "0.128.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.128.0.tgz", - "integrity": "sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==", - "dev": true, + "node_modules/@modelcontextprotocol/server/node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.18.tgz", - "integrity": "sha512-lIDyUAfD7U3+BWKzdxMbJcsYHuqXqmGz40aeRqvuAm3y5TkJSYTBW2RDrn65DJFPQqVjUAUqq5uz8urzQ8aBdQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.18.tgz", - "integrity": "sha512-apJq2ktnGp27nSInMR5Vcj8kY6xJzDAvfdIFlpDcAK/w4cDO58qVoi1YQsES/SKiFNge/6e4CUzgjfHduYqWpQ==", + "node_modules/@open-wallet-standard/core": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@open-wallet-standard/core/-/core-1.3.2.tgz", + "integrity": "sha512-Dk8bB9G5PjJfNzAqJd9WT9OfqrrSXRc3gA9+BCaY2qirlNrCkIAZCHaDIE0LnGOAaoSZizR6qnOFbukj+DTzJg==", + "license": "MIT", + "bin": { + "ows": "bin/ows" + }, + "optionalDependencies": { + "@open-wallet-standard/core-darwin-arm64": "1.3.2", + "@open-wallet-standard/core-darwin-x64": "1.3.2", + "@open-wallet-standard/core-linux-arm64-gnu": "1.3.2", + "@open-wallet-standard/core-linux-x64-gnu": "1.3.2" + } + }, + "node_modules/@open-wallet-standard/core-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-darwin-arm64/-/core-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-rvUsGU8eZtIMYFJ047nFKS79ajJeYCydvvh2B6bX0UUGf2NJZ4wUnxGqijxPiflz2xqzvbHXYZNzy3MIO4+fDQ==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + ] }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.18.tgz", - "integrity": "sha512-5Ofot8xbs+pxRHJqm9/9N/4sTQOvdrwEsmPE9pdLEEoAbdZtG6F2LMDfO1sp6ZAtXJuJV/21ew2srq3W8NXB5g==", + "node_modules/@open-wallet-standard/core-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-darwin-x64/-/core-darwin-x64-1.3.2.tgz", + "integrity": "sha512-a6u3CvWZY8sC1S92AMGnO1WFlMW3m38+3/IoKzhxcFvD8rVY0OA0ebH6qzYLT96/TaouXDwmMQV6yQmb1IjfzQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" + ] + }, + "node_modules/@open-wallet-standard/core-linux-arm64-gnu": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.2.tgz", + "integrity": "sha512-wzyd7euZ5qvDr8dHf3eG2XP7iFgMmBUo35U7cWMLs6Yqjqz103SEjtMfNJEedZRb62f8P3Xhp9jdRLzaJvjk5g==", + "cpu": [ + "arm64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.18.tgz", - "integrity": "sha512-7h8eeOTT1eyqJyx64BFCnWZpNm486hGWt2sqeLLgDxA0xI1oGZ9H7gK1S85uNGmBhkdPwa/6reTxfFFKvIsebw==", + "node_modules/@open-wallet-standard/core-linux-x64-gnu": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@open-wallet-standard/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.2.tgz", + "integrity": "sha512-pVtyEP8EqR3rjqdBDCRuB9Rd4xs8+11gRVtWidwPeFz5QPq3c9VGZjGQtTZoiZBHCxKaq5pTQjC78J5lVuA0hg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "linux" + ] + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.18.tgz", - "integrity": "sha512-eRcm/HVt9U/JFu5RKAEKwGQYtDCKWLiaH6wOnsSEp6NMBb/3Os8LgHZlNyzMpFVNmiiMFlfb2zEnebfzJrHFmg==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.3.tgz", + "integrity": "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==", "cpu": [ "arm" ], @@ -620,20 +1037,87 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "android" + ] }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.18.tgz", - "integrity": "sha512-SOrT/cT4ukTmgnrEz/Hg3m7LBnuCLW9psDeMKrimRWY4I8DmnO7Lco8W2vtqPmMkbVu8iJ+g4GFLVLLOVjJ9DQ==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.3.tgz", + "integrity": "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.3.tgz", + "integrity": "sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.3.tgz", + "integrity": "sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.3.tgz", + "integrity": "sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.3.tgz", + "integrity": "sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.3.tgz", + "integrity": "sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==", + "cpu": [ + "arm" + ], + "dev": true, "libc": [ "glibc" ], @@ -641,15 +1125,46 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.3.tgz", + "integrity": "sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.3.tgz", + "integrity": "sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==", + "cpu": [ + "arm64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.18.tgz", - "integrity": "sha512-QWjdxN1HJCpBTAcZ5N5F7wju3gVPzRzSpmGzx7na0c/1qpN9CFil+xt+l9lV/1M6/gqHSNXCiqPfwhVJPeLnug==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.3.tgz", + "integrity": "sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==", "cpu": [ "arm64" ], @@ -661,15 +1176,46 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.3.tgz", + "integrity": "sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==", + "cpu": [ + "loong64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.3.tgz", + "integrity": "sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.18.tgz", - "integrity": "sha512-ugCOyj7a4d9h3q9B+wXmf6g3a68UsjGh6dob5DHevHGMwDUbhsYNbSPxJsENcIttJZ9jv7qGM2UesLw5jqIhdg==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.3.tgz", + "integrity": "sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==", "cpu": [ "ppc64" ], @@ -681,17 +1227,31 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.3.tgz", + "integrity": "sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==", + "cpu": [ + "ppc64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.18.tgz", - "integrity": "sha512-kKWRhbsotpXkGbcd5dllUWg5gEXcDAa8u5YnP9AV5DYNbvJHGzzuwv7dpmhc8NqKMJldl0a+x76IHbspEpEmdA==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.3.tgz", + "integrity": "sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==", "cpu": [ - "s390x" + "riscv64" ], "dev": true, "libc": [ @@ -701,17 +1261,31 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.3.tgz", + "integrity": "sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==", + "cpu": [ + "riscv64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.18.tgz", - "integrity": "sha512-uCo8ElcCIAMyYAZyuIZ81oFkhTSIllNvUCHCAlbhlN4ji3uC28h7IIdlXyIvGO7HsuqnV9p3rD/bpH7XhIyhRw==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.3.tgz", + "integrity": "sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==", "cpu": [ - "x64" + "s390x" ], "dev": true, "libc": [ @@ -721,15 +1295,29 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.3.tgz", + "integrity": "sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==", + "cpu": [ + "x64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.18.tgz", - "integrity": "sha512-XNOQZtuE6yUIvx4rwGemwh8kpL1xvU41FXy/s9K7T/3JVcqGzo3NfKM2HrbrGgfPYGFW42f07Wk++aOC6B9NWA==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.3.tgz", + "integrity": "sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==", "cpu": [ "x64" ], @@ -741,15 +1329,26 @@ "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.3.tgz", + "integrity": "sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==", + "cpu": [ + "x64" ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.18.tgz", - "integrity": "sha512-tSn/kzrfa7tNOXr7sEacDBN4YsIqTyLqh45IO0nHDwtpKIDNDJr+VFojt+4klSpChxB29JLyduSsE0MKEwa65A==", + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.3.tgz", + "integrity": "sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==", "cpu": [ "arm64" ], @@ -758,51 +1357,40 @@ "optional": true, "os": [ "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + ] }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.18.tgz", - "integrity": "sha512-+J9YGmc+czgqlhYmwun3S3O0FIZhsH8ep2456xwjAdIOmuJxM7xz4P4PtrxU+Bz17a/5bqPA8o3HAAoX0teUdg==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.3.tgz", + "integrity": "sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==", "cpu": [ - "wasm32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + "os": [ + "win32" + ] }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.18.tgz", - "integrity": "sha512-zsu47DgU0FQzSwi6sU9dZoEdUv7pc1AptSEz/Z8HBg54sV0Pbs3N0+CrIbTsgiu6EyoaNN9CHboqbLaz9lhOyQ==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.3.tgz", + "integrity": "sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==", "cpu": [ - "arm64" + "ia32" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } + ] }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.18.tgz", - "integrity": "sha512-7H+3yqGgmnlDTRRhw/xpYY9J1kf4GC681nVc4GqKhExZTDrVVrV2tsOR9kso0fvgBdcTCcQShx4SLLoHgaLwhg==", + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.3.tgz", + "integrity": "sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==", "cpu": [ "x64" ], @@ -811,27 +1399,235 @@ "optional": true, "os": [ "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.3.tgz", + "integrity": "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==", + "cpu": [ + "x64" ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@solana-program/compute-budget": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@solana-program/compute-budget/-/compute-budget-0.11.0.tgz", + "integrity": "sha512-7f1ePqB/eURkTwTOO9TNIdUXZcyrZoX3Uy2hNo7cXMfNhPFWp9AVgIyRNBc2jf15sdUa9gNpW+PfP2iV8AYAaw==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^5.0" + } + }, + "node_modules/@solana-program/token": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@solana-program/token/-/token-0.9.0.tgz", + "integrity": "sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^5.0" + } + }, + "node_modules/@solana-program/token-2022": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@solana-program/token-2022/-/token-2022-0.6.1.tgz", + "integrity": "sha512-Ex02cruDMGfBMvZZCrggVR45vdQQSI/unHVpt/7HPt/IwFYB4eTlXtO8otYZyqV/ce5GqZ8S6uwyRf0zy6fdbA==", + "license": "Apache-2.0", + "peerDependencies": { + "@solana/kit": "^5.0", + "@solana/sysvars": "^5.0" + } + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", + "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==", + "license": "MIT", + "dependencies": { + "buffer": "~6.0.3" + }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=5.10" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.7", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", - "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", - "dev": true, + "node_modules/@solana/codecs-core": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz", + "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==", + "license": "MIT", + "dependencies": { + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/codecs-numbers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz", + "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==", + "license": "MIT", + "dependencies": { + "@solana/codecs-core": "2.3.0", + "@solana/errors": "2.3.0" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz", + "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0" + }, + "bin": { + "errors": "bin/cli.mjs" + }, + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "typescript": ">=5.3.3" + } + }, + "node_modules/@solana/web3.js": { + "version": "1.98.4", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz", + "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "@noble/curves": "^1.4.2", + "@noble/hashes": "^1.4.0", + "@solana/buffer-layout": "^4.0.1", + "@solana/codecs-numbers": "^2.1.0", + "agentkeepalive": "^4.5.0", + "bn.js": "^5.2.1", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.3", + "fast-stable-stringify": "^1.0.0", + "jayson": "^4.1.1", + "node-fetch": "^2.7.0", + "rpc-websockets": "^9.0.2", + "superstruct": "^2.0.2" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.21.tgz", + "integrity": "sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@telegraf/types": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@telegraf/types/-/types-7.1.0.tgz", + "integrity": "sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==", + "license": "MIT" + }, + "node_modules/@toon-format/toon": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@toon-format/toon/-/toon-2.2.0.tgz", + "integrity": "sha512-FMYqrlZnMN72YIT9KVt7Kxc41gat+RgMIzDmvRRPHw0J7pqW/FeBGDY/4BIWjT71Y+EdI9fCJip90uXuGuYhjw==", "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "tslib": "^2.4.0" + "@babel/types": "^7.28.2" } }, "node_modules/@types/body-parser": { @@ -849,12 +1645,18 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.25", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", @@ -899,7 +1701,6 @@ "version": "20.19.40", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.40.tgz", "integrity": "sha512-xxx6M2IpSTnnKcR0cMvIiohkiCx20/oRPtWGbenFygKCGl3zqUzdNjQ/1V4solq1LU+dgv0nQzeGOuqkqZGg0Q==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -916,7 +1717,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/qs": { @@ -986,32 +1786,121 @@ "@types/node": "*" } }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@vitejs/plugin-react": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", - "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-rc.7" + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@x402/core": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@x402/core/-/core-2.11.0.tgz", + "integrity": "sha512-aqTfZc/BULrlWnd3I0lsqRQaH4gjJd8CsPcL16XqK2Lx5c6QDm+zCljgUVS1yj9BGJoZeQWTzI5hE+SVFkqMTw==", + "license": "Apache-2.0", + "dependencies": { + "zod": "^3.24.2" + } + }, + "node_modules/@x402/evm": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@x402/evm/-/evm-2.11.0.tgz", + "integrity": "sha512-F8uU1txDZA+wc/sEnmaHAyYvoTi/w39r7K3a44MmQHSxECDTEuB3A0FwbxOxUPLN1eyCxTAFKEiqlGe3bwybKA==", + "license": "Apache-2.0", + "dependencies": { + "@x402/core": "~2.11.0", + "viem": "^2.39.3", + "zod": "^3.24.2" + } + }, + "node_modules/@x402/fetch": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@x402/fetch/-/fetch-2.11.0.tgz", + "integrity": "sha512-sDkoq1ZZt10/UVa75bCXTbWkXMbPOOQpkdSxWB0ybHtlmqT7PM6hU4DVCov4iL792W1Oi38VtxfUw5EkvdvYtw==", + "license": "Apache-2.0", + "dependencies": { + "@x402/core": "~2.11.0", + "viem": "^2.39.3", + "zod": "^3.24.2" + } + }, + "node_modules/@x402/svm": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@x402/svm/-/svm-2.11.0.tgz", + "integrity": "sha512-MmhLlEeb3FtgTxO4n3RkZszKEBBnYLfNnX8P3TvqVYP1u9gY2SgbYW4K3TsPAv00edCxoCOqYixI2JurYjW4Sw==", + "license": "Apache-2.0", + "dependencies": { + "@solana-program/compute-budget": "^0.11.0", + "@solana-program/token": "^0.9.0", + "@solana-program/token-2022": "^0.6.1", + "@x402/core": "~2.11.0" + }, + "peerDependencies": { + "@solana/kit": ">=5.1.0" + } + }, + "node_modules/abitype": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.4.tgz", + "integrity": "sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { - "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", - "babel-plugin-react-compiler": "^1.0.0", - "vite": "^8.0.0" + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" }, "peerDependenciesMeta": { - "@rolldown/plugin-babel": { + "typescript": { "optional": true }, - "babel-plugin-react-compiler": { + "zod": { "optional": true } } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1025,12 +1914,72 @@ "node": ">= 0.6" } }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/base-x": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "1.20.5", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", @@ -1070,6 +2019,120 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "license": "MIT", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "license": "MIT" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "license": "MIT" + }, + "node_modules/bufferutil": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz", + "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1108,6 +2171,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1129,6 +2234,13 @@ "node": ">= 0.6" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", @@ -1166,6 +2278,18 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1185,16 +2309,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -1227,6 +2341,13 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/electron-to-chromium": { + "version": "1.5.353", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", + "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", + "dev": true, + "license": "ISC" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -1266,6 +2387,21 @@ "node": ">= 0.4" } }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "license": "MIT", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, "node_modules/esbuild": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", @@ -1308,6 +2444,16 @@ "@esbuild/win32-x64": "0.27.7" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1323,6 +2469,21 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/express": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", @@ -1369,6 +2530,20 @@ "url": "https://opencollective.com/express" } }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fast-stable-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", + "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==", + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1447,6 +2622,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -1553,6 +2738,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1565,6 +2759,56 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/incur": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/incur/-/incur-0.4.5.tgz", + "integrity": "sha512-4WFlqm5e+IKNoX+lDIjjpebO8ResPx3vPUBChxNfnNo3oGp0ooo6piiiTspOMub2dq2mcG/AmlUq0ejuGfKobg==", + "license": "MIT", + "dependencies": { + "@cfworker/json-schema": "^4.1.1", + "@modelcontextprotocol/server": "^2.0.0-alpha.2", + "@toon-format/toon": "^2.1.0", + "tokenx": "^1.3.0", + "yaml": "^2.8.2", + "zod": "^4.3.6" + }, + "bin": { + "incur": "dist/bin.js", + "incur.src": "src/bin.ts" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/incur/node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -1580,277 +2824,115 @@ "node": ">= 0.10" } }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" } }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" + "node_modules/isows": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "peerDependencies": { + "ws": "*" } }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/jayson": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", + "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==", + "license": "MIT", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "stream-json": "^1.9.1", + "uuid": "^8.3.2", + "ws": "^7.5.10" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" + "bin": { + "jayson": "bin/jayson.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "node_modules/jayson/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "MIT" }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=6" } }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=6" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/math-intrinsics": { @@ -1922,6 +3004,60 @@ "node": ">= 0.6" } }, + "node_modules/mppx": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/mppx/-/mppx-0.6.16.tgz", + "integrity": "sha512-gByr5oM0vfbJqh3S7e3WLLjE3pjniZShv2kyFdzl3aav1ejH8rkjVqKMJ92nuQWkDw+2QZgzYD5PcbnqzUPZjA==", + "license": "MIT", + "dependencies": { + "incur": "^0.4.5", + "ox": "0.14.20", + "zod": "^4.3.6" + }, + "bin": { + "mppx": "dist/bin.js", + "mppx.src": "src/bin.ts" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": ">=1.25.0", + "elysia": ">=1", + "express": ">=5", + "hono": ">=4.12.16", + "viem": ">=2.47.5" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + }, + "elysia": { + "optional": true + }, + "express": { + "optional": true + }, + "hono": { + "optional": true + } + } + }, + "node_modules/mppx/node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1968,16 +3104,45 @@ "node": ">=6.0.0" } }, - "node_modules/node-cron/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "license": "MIT", + "optional": true, "bin": { - "uuid": "dist/bin/uuid" + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "dev": true, + "license": "MIT" + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -2002,6 +3167,60 @@ "node": ">= 0.8" } }, + "node_modules/ox": { + "version": "0.14.20", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.20.tgz", + "integrity": "sha512-rby38C3nDn8eQkf29Zgw4hkCZJ64Qqi0zRPWL8ENUQ7JVuoITqrVtwWQgM/He19SCMUEc7hS/Sjw0jIOSLJhOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.2.3", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/p-timeout": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz", + "integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2079,6 +3298,14 @@ "node": ">= 0.10" } }, + "node_modules/qrcode-terminal": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, "node_modules/qs": { "version": "6.14.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", @@ -2141,56 +3368,174 @@ "react": "^19.2.6" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/rolldown": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.18.tgz", - "integrity": "sha512-phmyKBpuBdRYDf4hgyynGAYn/rDDe+iZXKVJ7WX5b1zQzpLkP5oJRPGsfJuHdzPMlyyEO/4sPW6yfSx2gf7lVg==", - "dev": true, + "node_modules/react-router": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.0.tgz", + "integrity": "sha512-HW9vYwuM8f4yx66Izy8xfrzCM+SBJluoZcCbww9A1TySax11S5Vgw6fi3ZjMONw9J4gQwngL7PzkyIpJJpJ7RQ==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.128.0", - "@rolldown/pluginutils": "1.0.0-rc.18" + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.15.0.tgz", + "integrity": "sha512-VcrVg64Fo8nwBvDscajG8gRTLIuTC6N50nb22l2HOOV4PTOHgoGp8mUjy9wLiHYoYTSYI36tUnXZgasSRFZorQ==", + "license": "MIT", + "dependencies": { + "react-router": "7.15.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rollup": { + "version": "4.60.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz", + "integrity": "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" }, "bin": { - "rolldown": "bin/cli.mjs" + "rollup": "dist/bin/rollup" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.18", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.18", - "@rolldown/binding-darwin-x64": "1.0.0-rc.18", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.18", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.18", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.18", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.18", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.18", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.18", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.18", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.18", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.18", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.18", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.18", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18" - } - }, - "node_modules/rolldown/node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.18.tgz", - "integrity": "sha512-CUY5Mnhe64xQBGZEEXQ5WyZwsc1JU3vAZLIxtrsBt3LO6UOb+C8GunVKqe9sT8NeWb4lqSaoJtp2xo6GxT1MNw==", - "dev": true, - "license": "MIT" + "@rollup/rollup-android-arm-eabi": "4.60.3", + "@rollup/rollup-android-arm64": "4.60.3", + "@rollup/rollup-darwin-arm64": "4.60.3", + "@rollup/rollup-darwin-x64": "4.60.3", + "@rollup/rollup-freebsd-arm64": "4.60.3", + "@rollup/rollup-freebsd-x64": "4.60.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", + "@rollup/rollup-linux-arm-musleabihf": "4.60.3", + "@rollup/rollup-linux-arm64-gnu": "4.60.3", + "@rollup/rollup-linux-arm64-musl": "4.60.3", + "@rollup/rollup-linux-loong64-gnu": "4.60.3", + "@rollup/rollup-linux-loong64-musl": "4.60.3", + "@rollup/rollup-linux-ppc64-gnu": "4.60.3", + "@rollup/rollup-linux-ppc64-musl": "4.60.3", + "@rollup/rollup-linux-riscv64-gnu": "4.60.3", + "@rollup/rollup-linux-riscv64-musl": "4.60.3", + "@rollup/rollup-linux-s390x-gnu": "4.60.3", + "@rollup/rollup-linux-x64-gnu": "4.60.3", + "@rollup/rollup-linux-x64-musl": "4.60.3", + "@rollup/rollup-openbsd-x64": "4.60.3", + "@rollup/rollup-openharmony-arm64": "4.60.3", + "@rollup/rollup-win32-arm64-msvc": "4.60.3", + "@rollup/rollup-win32-ia32-msvc": "4.60.3", + "@rollup/rollup-win32-x64-gnu": "4.60.3", + "@rollup/rollup-win32-x64-msvc": "4.60.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/rpc-websockets": { + "version": "9.3.9", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.9.tgz", + "integrity": "sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==", + "license": "LGPL-3.0-only", + "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^10.0.0", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", + "eventemitter3": "^5.0.1", + "uuid": "^14.0.0", + "ws": "^8.5.0" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^6.0.0" + } + }, + "node_modules/rpc-websockets/node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/rpc-websockets/node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -2212,12 +3557,30 @@ ], "license": "MIT" }, + "node_modules/safe-compare": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-compare/-/safe-compare-1.1.4.tgz", + "integrity": "sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==", + "license": "MIT", + "dependencies": { + "buffer-alloc": "^1.2.0" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sandwich-stream": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz", + "integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -2225,6 +3588,16 @@ "dev": true, "license": "MIT" }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/send": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", @@ -2264,6 +3637,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2361,6 +3740,74 @@ "node": ">= 0.8" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/superstruct": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz", + "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/telegraf": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.16.3.tgz", + "integrity": "sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==", + "license": "MIT", + "dependencies": { + "@telegraf/types": "^7.1.0", + "abort-controller": "^3.0.0", + "debug": "^4.3.4", + "mri": "^1.2.0", + "node-fetch": "^2.7.0", + "p-timeout": "^4.1.0", + "safe-compare": "^1.1.4", + "sandwich-stream": "^2.0.2" + }, + "bin": { + "telegraf": "lib/cli.mjs" + }, + "engines": { + "node": "^12.20.0 || >=14.13.1" + } + }, + "node_modules/telegraf/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -2387,13 +3834,23 @@ "node": ">=0.6" } }, + "node_modules/tokenx": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tokenx/-/tokenx-1.3.0.tgz", + "integrity": "sha512-NLdXTEZkKiO0gZuLtMoZKjCXTREXeZZt8nnnNeyoXtNZAfG/GKGSbQtLU5STspc0rMSwcA+UJfWZkbNU01iKmQ==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/tsx": { "version": "4.21.0", @@ -2451,6 +3908,51 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utf-8-validate": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz", + "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -2460,6 +3962,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2469,24 +3984,112 @@ "node": ">= 0.8" } }, + "node_modules/viem": { + "version": "2.48.11", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.48.11.tgz", + "integrity": "sha512-+WZ5E0dBS6GtKb+1wEk5DeYRRRW42+pFnXCo67Ydodf42sBwO+hu3wnQy66lc4MKmHz+llPVdbyehYr9oTE2iw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.2.3", + "isows": "1.0.7", + "ox": "0.14.20", + "ws": "8.18.3" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/abitype": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz", + "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/vite": { - "version": "8.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.11.tgz", - "integrity": "sha512-Jz1mxtUBR5xTT65VOdJZUUeoyLtqljmFkiUXhPTLZka3RDc9vpi/xXkyrnsdRcm2lIi3l3GPMnAidTsEGIj3Ow==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.14", - "rolldown": "1.0.0-rc.18", - "tinyglobby": "^0.2.16" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -2495,15 +4098,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", - "esbuild": "^0.27.0 || ^0.28.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -2512,18 +4114,15 @@ "@types/node": { "optional": true }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, "jiti": { "optional": true }, "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, @@ -2546,6 +4145,558 @@ "optional": true } } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", + "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 30adf210..729ce07a 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,91 @@ { - "name": "conviction-dca-agent", - "version": "0.1.0", + "name": "zerion-cli", + "version": "1.1.0", + "description": "Zerion for AI agents and developers: wallet-analysis skill bundle and a JSON-first CLI.", + "author": "Zerion", "type": "module", + "bin": { + "zerion": "./cli/zerion.js" + }, + "files": [ + "cli/zerion.js", + "cli/router.js", + "cli/commands/", + "cli/utils/", + "cli/policies/", + "skills/", + "plugins/", + ".agents/", + ".claude-plugin/", + ".codex-plugin/", + "gemini-extension.json", + "README.md", + "LICENSE" + ], "scripts": { + "test": "node --test 'cli/tests/unit/**/*.test.mjs'", + "test:unit": "node --test 'cli/tests/unit/**/*.test.mjs'", + "test:integration": "node --test --test-concurrency=1 'cli/tests/integration/**/*.test.mjs'", + "test:integration:auth": "node --test cli/tests/integration/auth.test.mjs", + "test:all": "node --test 'cli/tests/**/*.test.mjs'", + "prepublishOnly": "npm test", "dev": "tsx watch app/server.ts", "build": "tsc && vite build --config client/vite.config.ts", - "start": "node dist/server.js", - "setup": "cd cli && npm install && cd .." + "start": "node dist/server.js" + }, + "imports": { + "#zerion/*": "./cli/*", + "#zerion": "./package.json" + }, + "engines": { + "node": ">=20" }, + "keywords": [ + "zerion", + "ai", + "wallet", + "openclaw", + "cli" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/schmidtjoshyofficial/zerion-ai.git" + }, + "bugs": { + "url": "https://github.com/schmidtjoshyofficial/zerion-ai/issues" + }, + "homepage": "https://github.com/schmidtjoshyofficial/zerion-ai#readme", + "license": "MIT", "dependencies": { "@google/generative-ai": "^0.21.0", + "@open-wallet-standard/core": "^1.3.2", + "@solana/web3.js": "^1.98.4", + "@x402/evm": "^2.6.0", + "@x402/fetch": "^2.6.0", + "@x402/svm": "^2.8.0", "dotenv": "^16.0.0", "express": "^4.18.0", - "node-cron": "^3.0.0" + "mppx": "^0.6.2", + "node-cron": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "react-router-dom": "^7.15.0", + "telegraf": "^4.16.3", + "viem": "^2.0.0" }, "devDependencies": { "@types/express": "^4.17.0", "@types/node": "^20.0.0", "@types/node-cron": "^3.0.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "react": "^19.2.6", - "react-dom": "^19.2.6", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "react": "^19.0.0", + "react-dom": "^19.0.0", "tsx": "^4.0.0", "typescript": "^5.0.0", - "vite": "^8.0.11" + "vite": "^6.2.0" + }, + "overrides": { + "uuid": "^14.0.0" } } diff --git a/tsconfig.json b/tsconfig.json index 888ecf76..fae81ed3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,11 +4,14 @@ "module": "ESNext", "moduleResolution": "bundler", "outDir": "dist", - "rootDir": "app", + "rootDir": ".", "strict": true, "esModuleInterop": true, - "skipLibCheck": true + "skipLibCheck": true, + "allowJs": true, + "resolveJsonModule": true, + "noImplicitAny": false }, "include": ["app/**/*"], - "exclude": ["node_modules", "cli", "client"] + "exclude": ["node_modules", "client"] }