Files
strategic/tests/integration/protocol-integration.test.ts
2026-02-09 21:51:54 -08:00

235 lines
8.7 KiB
TypeScript

import { describe, it, expect, beforeAll } from "vitest";
import { StrategyCompiler } from "../../src/planner/compiler.js";
import { loadStrategy, substituteBlinds } from "../../src/strategy.js";
import { getChainConfig } from "../../src/config/chains.js";
import { JsonRpcProvider, Contract, getAddress } from "ethers";
import { join } from "path";
import * as dotenv from "dotenv";
// Load environment variables
dotenv.config();
describe("Protocol Integration Tests - Recursive Leverage Strategy", () => {
const RPC_MAINNET = process.env.RPC_MAINNET;
const RPC_POLYGON = process.env.RPC_POLYGON;
const RPC_BASE = process.env.RPC_BASE;
const RPC_OPTIMISM = process.env.RPC_OPTIMISM;
// Aave v3 Pool contract ABI (minimal for testing)
const AAVE_POOL_ABI = [
"function getReserveData(address asset) external view returns (tuple(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint40))",
"function getReservesList() external view returns (address[])",
];
describe("Mainnet Protocol Contracts", () => {
it.skipIf(!RPC_MAINNET)("should connect to Aave v3 Pool on mainnet", async () => {
const provider = new JsonRpcProvider(RPC_MAINNET);
const chainConfig = getChainConfig("mainnet");
if (!chainConfig.protocols.aaveV3?.pool) {
throw new Error("Aave v3 pool address not configured");
}
const poolAddress = getAddress(chainConfig.protocols.aaveV3.pool);
const poolContract = new Contract(poolAddress, AAVE_POOL_ABI, provider);
// Test connection by calling getReservesList
const reserves = await poolContract.getReservesList();
expect(reserves).toBeDefined();
expect(Array.isArray(reserves)).toBe(true);
expect(reserves.length).toBeGreaterThan(0);
});
it.skipIf(!RPC_MAINNET)("should verify Aave v3 Pool address is correct", async () => {
const provider = new JsonRpcProvider(RPC_MAINNET);
const chainConfig = getChainConfig("mainnet");
if (!chainConfig.protocols.aaveV3?.pool) {
throw new Error("Aave v3 pool address not configured");
}
const poolAddress = getAddress(chainConfig.protocols.aaveV3.pool);
// Verify contract exists by checking code
const code = await provider.getCode(poolAddress);
expect(code).not.toBe("0x");
expect(code.length).toBeGreaterThan(2);
});
it.skipIf(!RPC_MAINNET)("should compile recursive leverage strategy with real protocol addresses", async () => {
const strategyPath = join(
process.cwd(),
"strategies",
"sample.recursive.json"
);
if (!require("fs").existsSync(strategyPath)) {
return;
}
const strategy = loadStrategy(strategyPath);
// Substitute blind values for testing
const blindValues = {
collateralAmount: "1000000", // 1 USDC (6 decimals)
leverageFactor: "500000", // 0.5 USDC
};
const resolvedStrategy = substituteBlinds(strategy, blindValues);
const compiler = new StrategyCompiler(resolvedStrategy.chain);
const plan = await compiler.compile(resolvedStrategy);
expect(plan.calls.length).toBeGreaterThan(0);
// Verify the compiled calls target the correct Aave pool address
const chainConfig = getChainConfig("mainnet");
const aavePoolAddress = chainConfig.protocols.aaveV3?.pool;
if (aavePoolAddress) {
const checksummedPoolAddress = getAddress(aavePoolAddress);
const supplyCall = plan.calls.find(call =>
getAddress(call.to).toLowerCase() === checksummedPoolAddress.toLowerCase()
);
expect(supplyCall).toBeDefined();
expect(supplyCall?.description).toContain("Aave");
}
});
it.skipIf(!RPC_MAINNET)("should verify USDC is a valid reserve in Aave v3", async () => {
const provider = new JsonRpcProvider(RPC_MAINNET);
const chainConfig = getChainConfig("mainnet");
if (!chainConfig.protocols.aaveV3?.pool) {
throw new Error("Aave v3 pool address not configured");
}
const poolAddress = getAddress(chainConfig.protocols.aaveV3.pool);
const poolContract = new Contract(poolAddress, AAVE_POOL_ABI, provider);
// USDC address on mainnet
const USDC_ADDRESS = getAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
// Get reserve data for USDC
const reserveData = await poolContract.getReserveData(USDC_ADDRESS);
expect(reserveData).toBeDefined();
// Verify it's a valid reserve (liquidityIndex should be > 0)
const liquidityIndex = reserveData[0];
expect(liquidityIndex).toBeDefined();
expect(Number(liquidityIndex)).toBeGreaterThan(0);
});
it.skipIf(!RPC_MAINNET)("should verify Uniswap V3 Router address", async () => {
const provider = new JsonRpcProvider(RPC_MAINNET);
const chainConfig = getChainConfig("mainnet");
if (!chainConfig.protocols.uniswapV3?.router) {
throw new Error("Uniswap V3 router address not configured");
}
const routerAddress = getAddress(chainConfig.protocols.uniswapV3.router);
// Verify contract exists
const code = await provider.getCode(routerAddress);
expect(code).not.toBe("0x");
expect(code.length).toBeGreaterThan(2);
});
});
describe("Polygon Protocol Contracts", () => {
it.skipIf(!RPC_POLYGON)("should connect to Polygon RPC and verify chain config", async () => {
const provider = new JsonRpcProvider(RPC_POLYGON);
// Note: Polygon chain config may not be implemented yet
// This test verifies RPC connectivity only
// Verify we can connect
const blockNumber = await provider.getBlockNumber();
expect(blockNumber).toBeGreaterThan(0);
// Verify chain ID matches Polygon
const network = await provider.getNetwork();
expect(network.chainId).toBe(BigInt(137));
});
});
describe("Base Protocol Contracts", () => {
it.skipIf(!RPC_BASE)("should connect to Base RPC and verify chain config", async () => {
const provider = new JsonRpcProvider(RPC_BASE);
const chainConfig = getChainConfig("base");
// Verify we can connect
const blockNumber = await provider.getBlockNumber();
expect(blockNumber).toBeGreaterThan(0);
// Verify chain ID matches
const network = await provider.getNetwork();
expect(network.chainId).toBe(BigInt(8453));
});
});
describe("Optimism Protocol Contracts", () => {
it.skipIf(!RPC_OPTIMISM)("should connect to Optimism RPC and verify chain config", async () => {
const provider = new JsonRpcProvider(RPC_OPTIMISM);
const chainConfig = getChainConfig("optimism");
// Verify we can connect
const blockNumber = await provider.getBlockNumber();
expect(blockNumber).toBeGreaterThan(0);
// Verify chain ID matches
const network = await provider.getNetwork();
expect(network.chainId).toBe(BigInt(10));
});
});
describe("Recursive Leverage Strategy - Full Integration", () => {
it.skipIf(!RPC_MAINNET)("should compile and validate recursive leverage strategy against real contracts", async () => {
const strategyPath = join(
process.cwd(),
"strategies",
"sample.recursive.json"
);
if (!require("fs").existsSync(strategyPath)) {
return;
}
const provider = new JsonRpcProvider(RPC_MAINNET);
const strategy = loadStrategy(strategyPath);
const chainConfig = getChainConfig(strategy.chain);
// Substitute blind values
const blindValues = {
collateralAmount: "1000000", // 1 USDC
leverageFactor: "500000", // 0.5 USDC
};
const resolvedStrategy = substituteBlinds(strategy, blindValues);
// Compile strategy
const compiler = new StrategyCompiler(resolvedStrategy.chain);
const plan = await compiler.compile(resolvedStrategy);
expect(plan.calls.length).toBeGreaterThan(0);
// Verify all calls target valid contract addresses
for (const call of plan.calls) {
const callAddress = getAddress(call.to);
const code = await provider.getCode(callAddress);
expect(code).not.toBe("0x");
expect(code.length).toBeGreaterThan(2);
}
// Verify Aave pool address matches configuration
const aavePoolAddress = chainConfig.protocols.aaveV3?.pool;
if (aavePoolAddress) {
const checksummedPoolAddress = getAddress(aavePoolAddress);
const aaveCalls = plan.calls.filter(call =>
getAddress(call.to).toLowerCase() === checksummedPoolAddress.toLowerCase()
);
expect(aaveCalls.length).toBeGreaterThan(0);
}
});
});
});