BEGIN; CREATE TABLE IF NOT EXISTS tokens ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, address TEXT NOT NULL, name TEXT, symbol TEXT, decimals INTEGER, total_supply NUMERIC(78, 0), logo_url TEXT, website_url TEXT, description TEXT, verified BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (chain_id, address) ); CREATE INDEX IF NOT EXISTS idx_tokens_chain_id ON tokens (chain_id); CREATE INDEX IF NOT EXISTS idx_tokens_chain_symbol ON tokens (chain_id, symbol); CREATE INDEX IF NOT EXISTS idx_tokens_chain_name ON tokens (chain_id, name); CREATE TABLE IF NOT EXISTS token_market_data ( chain_id INTEGER NOT NULL, token_address TEXT NOT NULL, price_usd NUMERIC(38, 18), price_change_24h NUMERIC(38, 18), volume_24h NUMERIC(38, 18) NOT NULL DEFAULT 0, volume_7d NUMERIC(38, 18) NOT NULL DEFAULT 0, volume_30d NUMERIC(38, 18) NOT NULL DEFAULT 0, market_cap_usd NUMERIC(38, 18), liquidity_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, holders_count INTEGER NOT NULL DEFAULT 0, transfers_24h INTEGER NOT NULL DEFAULT 0, last_updated TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (chain_id, token_address) ); CREATE INDEX IF NOT EXISTS idx_token_market_data_volume_24h ON token_market_data (chain_id, volume_24h DESC); CREATE INDEX IF NOT EXISTS idx_token_market_data_liquidity ON token_market_data (chain_id, liquidity_usd DESC); CREATE TABLE IF NOT EXISTS liquidity_pools ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, pool_address TEXT NOT NULL, token0_address TEXT NOT NULL, token1_address TEXT NOT NULL, dex_type TEXT NOT NULL, factory_address TEXT, router_address TEXT, reserve0 NUMERIC(78, 0) NOT NULL DEFAULT 0, reserve1 NUMERIC(78, 0) NOT NULL DEFAULT 0, reserve0_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, reserve1_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, total_liquidity_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, volume_24h NUMERIC(38, 18) NOT NULL DEFAULT 0, fee_tier INTEGER, created_at_block BIGINT, created_at_timestamp TIMESTAMPTZ, last_updated TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (chain_id, pool_address) ); CREATE INDEX IF NOT EXISTS idx_liquidity_pools_chain_liquidity ON liquidity_pools (chain_id, total_liquidity_usd DESC); CREATE INDEX IF NOT EXISTS idx_liquidity_pools_chain_token0 ON liquidity_pools (chain_id, token0_address); CREATE INDEX IF NOT EXISTS idx_liquidity_pools_chain_token1 ON liquidity_pools (chain_id, token1_address); CREATE TABLE IF NOT EXISTS pool_reserves_history ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, pool_address TEXT NOT NULL, reserve0 NUMERIC(78, 0) NOT NULL, reserve1 NUMERIC(78, 0) NOT NULL, reserve0_usd NUMERIC(38, 18), reserve1_usd NUMERIC(38, 18), total_liquidity_usd NUMERIC(38, 18), block_number BIGINT NOT NULL, timestamp TIMESTAMPTZ NOT NULL ); CREATE INDEX IF NOT EXISTS idx_pool_reserves_history_lookup ON pool_reserves_history (chain_id, pool_address, timestamp DESC); CREATE TABLE IF NOT EXISTS swap_events ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, pool_address TEXT NOT NULL, token0_address TEXT NOT NULL, token1_address TEXT NOT NULL, amount_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, price_usd NUMERIC(38, 18), transaction_hash TEXT, log_index INTEGER, block_number BIGINT, timestamp TIMESTAMPTZ NOT NULL ); CREATE INDEX IF NOT EXISTS idx_swap_events_pool_time ON swap_events (chain_id, pool_address, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_swap_events_token_time ON swap_events (chain_id, token0_address, token1_address, timestamp DESC); CREATE UNIQUE INDEX IF NOT EXISTS idx_swap_events_unique_log ON swap_events ( chain_id, pool_address, COALESCE(transaction_hash, ''), COALESCE(log_index, -1) ); CREATE TABLE IF NOT EXISTS token_ohlcv ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, token_address TEXT NOT NULL, pool_address TEXT NOT NULL DEFAULT '', interval_type TEXT NOT NULL, open_price NUMERIC(38, 18) NOT NULL, high_price NUMERIC(38, 18) NOT NULL, low_price NUMERIC(38, 18) NOT NULL, close_price NUMERIC(38, 18) NOT NULL, volume NUMERIC(38, 18) NOT NULL DEFAULT 0, volume_usd NUMERIC(38, 18) NOT NULL DEFAULT 0, timestamp TIMESTAMPTZ NOT NULL, UNIQUE (chain_id, token_address, pool_address, interval_type, timestamp) ); CREATE INDEX IF NOT EXISTS idx_token_ohlcv_lookup ON token_ohlcv (chain_id, token_address, interval_type, timestamp DESC); CREATE TABLE IF NOT EXISTS provider_health_snapshots ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, provider TEXT NOT NULL, status TEXT NOT NULL, supports_execution BOOLEAN NOT NULL DEFAULT FALSE, supports_quote BOOLEAN NOT NULL DEFAULT FALSE, metadata JSONB NOT NULL DEFAULT '{}'::jsonb, captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_provider_health_snapshots_lookup ON provider_health_snapshots (chain_id, provider, captured_at DESC); CREATE TABLE IF NOT EXISTS route_plan_cache ( plan_id TEXT PRIMARY KEY, request_hash TEXT NOT NULL, chain_id INTEGER NOT NULL, destination_chain_id INTEGER NOT NULL, decision TEXT NOT NULL, response_json JSONB NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), expires_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS idx_route_plan_cache_lookup ON route_plan_cache (request_hash, expires_at DESC); CREATE TABLE IF NOT EXISTS route_execution_metrics ( id BIGSERIAL PRIMARY KEY, plan_id TEXT NOT NULL, chain_id INTEGER NOT NULL, provider TEXT NOT NULL, hop_index INTEGER NOT NULL, token_in_address TEXT NOT NULL, token_out_address TEXT NOT NULL, estimated_amount_out NUMERIC(78, 0), actual_amount_out NUMERIC(78, 0), status TEXT NOT NULL, metadata JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_route_execution_metrics_lookup ON route_execution_metrics (plan_id, hop_index, created_at DESC); COMMIT;