-- Migration: Admin Configuration Schema -- Description: Creates tables for managing API keys, endpoints, and service configuration -- For Token Aggregation Service Control Panel -- API Keys Management CREATE TABLE IF NOT EXISTS api_keys ( id BIGSERIAL PRIMARY KEY, provider VARCHAR(50) NOT NULL CHECK (provider IN ('coingecko', 'coinmarketcap', 'dexscreener', 'custom')), key_name VARCHAR(255) NOT NULL, api_key_encrypted TEXT NOT NULL, is_active BOOLEAN DEFAULT true, rate_limit_per_minute INTEGER, rate_limit_per_day INTEGER, last_used_at TIMESTAMP WITH TIME ZONE, expires_at TIMESTAMP WITH TIME ZONE, created_by VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(provider, key_name) ); CREATE INDEX idx_api_keys_provider ON api_keys(provider); CREATE INDEX idx_api_keys_active ON api_keys(is_active) WHERE is_active = true; -- API Endpoints Configuration CREATE TABLE IF NOT EXISTS api_endpoints ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, endpoint_type VARCHAR(50) NOT NULL CHECK (endpoint_type IN ('rpc', 'explorer', 'indexer', 'custom')), endpoint_name VARCHAR(255) NOT NULL, endpoint_url TEXT NOT NULL, is_primary BOOLEAN DEFAULT false, is_active BOOLEAN DEFAULT true, requires_auth BOOLEAN DEFAULT false, auth_type VARCHAR(50), auth_config JSONB, rate_limit_per_minute INTEGER, timeout_ms INTEGER DEFAULT 10000, health_check_enabled BOOLEAN DEFAULT true, last_health_check TIMESTAMP WITH TIME ZONE, health_check_status VARCHAR(20), created_by VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(chain_id, endpoint_type, endpoint_name) ); CREATE INDEX idx_api_endpoints_chain ON api_endpoints(chain_id); CREATE INDEX idx_api_endpoints_type ON api_endpoints(endpoint_type); CREATE INDEX idx_api_endpoints_active ON api_endpoints(is_active) WHERE is_active = true; -- DEX Factory Configuration CREATE TABLE IF NOT EXISTS dex_factory_config ( id BIGSERIAL PRIMARY KEY, chain_id INTEGER NOT NULL, dex_type VARCHAR(20) NOT NULL CHECK (dex_type IN ('uniswap_v2', 'uniswap_v3', 'dodo', 'custom')), factory_address VARCHAR(42) NOT NULL, router_address VARCHAR(42), pool_manager_address VARCHAR(42), start_block BIGINT DEFAULT 0, is_active BOOLEAN DEFAULT true, description TEXT, created_by VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(chain_id, dex_type, factory_address) ); CREATE INDEX idx_dex_factory_chain ON dex_factory_config(chain_id); CREATE INDEX idx_dex_factory_type ON dex_factory_config(dex_type); -- Admin Users CREATE TABLE IF NOT EXISTS admin_users ( id BIGSERIAL PRIMARY KEY, username VARCHAR(255) NOT NULL UNIQUE, email VARCHAR(255), password_hash TEXT NOT NULL, role VARCHAR(50) DEFAULT 'admin' CHECK (role IN ('super_admin', 'admin', 'operator', 'viewer')), is_active BOOLEAN DEFAULT true, last_login TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_admin_users_username ON admin_users(username); CREATE INDEX idx_admin_users_active ON admin_users(is_active) WHERE is_active = true; -- Admin Sessions CREATE TABLE IF NOT EXISTS admin_sessions ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE, session_token VARCHAR(255) NOT NULL UNIQUE, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, ip_address INET, user_agent TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_admin_sessions_token ON admin_sessions(session_token); CREATE INDEX idx_admin_sessions_user ON admin_sessions(user_id); -- Audit Log CREATE TABLE IF NOT EXISTS admin_audit_log ( id BIGSERIAL PRIMARY KEY, user_id BIGINT REFERENCES admin_users(id), action VARCHAR(100) NOT NULL, resource_type VARCHAR(50) NOT NULL, resource_id BIGINT, old_values JSONB, new_values JSONB, ip_address INET, user_agent TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_audit_log_user ON admin_audit_log(user_id); CREATE INDEX idx_audit_log_resource ON admin_audit_log(resource_type, resource_id); CREATE INDEX idx_audit_log_created ON admin_audit_log(created_at DESC); -- Update triggers (if update_updated_at_column function exists) DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'update_updated_at_column') THEN CREATE TRIGGER update_api_keys_updated_at BEFORE UPDATE ON api_keys FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_api_endpoints_updated_at BEFORE UPDATE ON api_endpoints FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_dex_factory_config_updated_at BEFORE UPDATE ON dex_factory_config FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_admin_users_updated_at BEFORE UPDATE ON admin_users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); END IF; END $$;