This document contains notes, common commands, and architectural insights for developers actively working on the (LP Yield Optimizer Vault). For a user-facing guide, see README.md. For a high-level overview, see ARCHITECTURE.md.
- Follow the
README.md: Complete all steps in the main README, including cloning, installing dependencies, and setting up the.envfile. - Crucial Environment Variables:
LOG_LEVEL=debug: This is your most important debugging tool. It provides verbose output for every step of the AVM cycle.AVM_MODE=live: The system will not run without this. This is a safety switch to prevent accidental execution.CRYPTOCOMPARE_API: The system will fail during data fetching if this is not set. A free key is sufficient for development.
# Run the main AVM service with a full execution loop
go run ./cmd/avm/main.go
# Reset the database to a clean state (drops all tables)
go run ./scripts/reset_db.go
# Build the production binary
go build -o avm-service ./cmd/avmThe entire logic is orchestrated within the runAVMCycle function.
datafetcher.GetPools&datafetcher.GetTokens: Gathers all external data. This is the most network-intensive part.vm.Get...: Queries the blockchain for the vault's current state.analyzer.CalculatePoolScores: The "brain" applies the scoring model.analyzer.DetermineTargetAllocations: The portfolio is constructed here.planner.GenerateActionPlan: The high-level strategy is converted into concrete steps.vm.ExecuteActionPlan: The steps are executed in two phases (withdrawals, then deposits).state.SaveCycleSnapshot: The results are persisted to the database.
A core design principle is "fail fast and safe." You will see extensive validation in:
internal/datafetcher: Every piece of data from an external API or on-chain query is scrutinized. If data is missing or invalid (e.g., negative price,NaNvalue), the process for that asset or pool fails immediately. We do not proceed with incomplete data.internal/wallet: All transaction messages are validated usingValidateBasic()before being signed.internal/planner: All inputs to the planner are validated to prevent planning based on corrupted state.
This is the most critical safety feature. It is not just a simple check.
- Simulation (
internal/simulations): Theplannerfirst calls the simulation functions to get anExpected...outcome (e.g.,ExpectedTokenOut,ExpectedSharesOut). This is a prediction based on the current chain state. - Enforcement (
internal/wallet/transactions.go): Thetransactionsbuilder takes theExpected...value and theSlippageTolerancePctfrom the parameters. It calculates the absolute minimum acceptable outcome (e.g.,minAmountOut = expectedAmount * (1 - slippageTolerance)). This minimum value is then embedded directly into the final transaction message sent to the chain. The chain itself will cause the transaction to fail if this minimum is not met.
This abstraction is key for testability. It decouples the core logic (analyzer, planner) from the live implementation. To test the full runAVMCycle loop, you can create a mockVault that implements this interface and simulates transaction outcomes without needing a live chain or wallet.
- Check the Logs: The first step is always to set
LOG_LEVEL=debugin your.envfile and re-run the cycle. The logs are verbose and component-specific, which helps narrow down where an issue occurred. - Check the Dashboard: Open
http://localhost:8080. The dashboard is the best way to see the results of a cycle. Did the vault value drop unexpectedly? Were there any actions in the "Recent Cycles" table? - Inspect the Database: If a cycle completed but the results look wrong, inspect the
cycle_snapshotstable directly usingpsql. You canjsonb_prettyto view theaction_planandaction_receiptsJSON columns to see exactly what the AVM intended to do and what it recorded as the result.
-
Implement Parameter Optimizer:
- Create a new
internal/optimizerpackage. - The main function should take recent
CycleSnapshotdata and the currentScoringParameters. - It should analyze the performance contribution of different factors (e.g., did pools with high
EdenWeightunderperform?) and suggest small, incremental changes to the parameters. - Integrate this into the main loop in
cmd/avm/main.goto run everyNcycles.
- Create a new
-
Implement Correlation Analysis:
- In
datafetcher, add logic to calculate a correlation matrix for the historical returns of the main assets in the pools. - In
analyzer/SelectTopPools.go, modifyDetermineTargetAllocationsto use this matrix to penalize or cap allocations to highly correlated assets, improving diversification.
- In
-
Implement Testing Suite:
- Unit Tests: Start with pure functions in
internal/utils,internal/analyzer, andinternal/planner. - Integration Tests: Create a
mockVaultand write a test for the fullrunAVMCycleloop to verify the end-to-end logic without broadcasting transactions.
- Unit Tests: Start with pure functions in
- API Rate Limiting: The CryptoCompare API has rate limits. The
FetchHistoricalPriceDatafunction has basic retry logic, but if you run many cycles in rapid succession during development, you may get temporarily blocked. - Keyring Backend: The default
testkeyring backend is unencrypted and not suitable for production. A production deployment would require switching to theosbackend (with a strong password) or integrating with a hardware security module (HSM). - Gas Simulation Failures: The code currently falls back to a default gas limit if the simulation fails. While this is a safe fallback, frequent simulation failures indicate a problem with the RPC node or the transaction structure and should be investigated.
- State Drift on Crash: If the AVM crashes mid-execution (after withdrawals but before deposits), the vault will be left in a consolidated USDC state. The next cycle will start from this state and should correct it, but this is a known complexity of autonomous systems.