import { runAllHealthChecks, formatHealthCheckError, } from './health-checks.js'; import { readFileSync } from 'fs'; import { join } from 'path'; const DEFAULT_RPC_URL = 'http://localhost:8081/api/rpc'; const DEFAULT_WEBAPP_URL = 'http://localhost:8081'; const DEFAULT_GRAPHQL_URL = 'http://localhost:8081/api/graphql'; export interface ContractAddresses { Kraiken: string; Stake: string; LiquidityManager: string; OptimizerProxy?: string; } export interface StackConfig { rpcUrl: string; webAppUrl: string; graphqlUrl: string; contracts: ContractAddresses; } /** * Load contract addresses, preferring env var overrides over the deployments file. * Env vars: STACK_KRAIKEN_ADDRESS, STACK_STAKE_ADDRESS, STACK_LM_ADDRESS. * Falls back to onchain/deployments-local.json when env vars are absent. */ function loadContractAddresses(): ContractAddresses { const envKraiken = process.env.STACK_KRAIKEN_ADDRESS; const envStake = process.env.STACK_STAKE_ADDRESS; const envLm = process.env.STACK_LM_ADDRESS; if (envKraiken && envStake && envLm) { const envOptimizerProxy = process.env.STACK_OPTIMIZER_PROXY_ADDRESS; return { Kraiken: envKraiken, Stake: envStake, LiquidityManager: envLm, ...(envOptimizerProxy !== undefined ? { OptimizerProxy: envOptimizerProxy } : {}), }; } let fileContracts!: ContractAddresses; try { const deploymentsPath = join(process.cwd(), 'onchain', 'deployments-local.json'); const deploymentsJson = readFileSync(deploymentsPath, 'utf-8'); const deployments = JSON.parse(deploymentsJson); fileContracts = deployments.contracts; } catch (error) { console.error('Failed to load contract addresses from deployments-local.json:', error); throw new Error('Cannot run tests without deployed contract addresses'); } return { Kraiken: envKraiken ?? fileContracts.Kraiken, Stake: envStake ?? fileContracts.Stake, LiquidityManager: envLm ?? fileContracts.LiquidityManager, ...(fileContracts.OptimizerProxy !== undefined ? { OptimizerProxy: fileContracts.OptimizerProxy } : {}), }; } /** * Get stack configuration from environment variables. * Tests should NOT start their own stack - they require a pre-existing healthy stack. */ export function getStackConfig(): StackConfig { return { rpcUrl: process.env.STACK_RPC_URL ?? DEFAULT_RPC_URL, webAppUrl: process.env.STACK_WEBAPP_URL ?? DEFAULT_WEBAPP_URL, graphqlUrl: process.env.STACK_GRAPHQL_URL ?? DEFAULT_GRAPHQL_URL, contracts: loadContractAddresses(), }; } /** * Validate that a healthy stack exists and is functional. * If validation fails, the test run should exit immediately. * * Tests do NOT manage stack lifecycle - stack must be started externally via: * ./scripts/dev.sh start */ export async function validateStackHealthy(config: StackConfig): Promise { const results = await runAllHealthChecks(config); const failures = results.filter(r => !r.success); if (failures.length > 0) { const errorMessage = formatHealthCheckError(results); console.error('\nāŒ Stack health validation failed'); console.error('Tests require a pre-existing healthy stack.'); console.error('Start the stack with: ./scripts/dev.sh start\n'); console.error(errorMessage); process.exit(1); } console.log('āœ… Stack health validation passed'); }