Note: see in example subsection or in scripts/readme.md how to fetch data (incl. ts data for vol or not), optimize, and get lp output
This module provides two main tools for working with Shadow protocol voting data:
- fetch_votes: Fetches pool data and on-chain votes for a given period, saving a dashboard JSON file for analytics and optimization.
- optimizer: Calculates the optimal allocation of your voting power to maximize bribe rewards, and compares your actual votes to the theoretical best.
Argument:
periodif specified, fetches votes for an elapsed periodhistorical_dashboard_pathto past bribes and fees -- is only useful to recompute the optimal votes for a past epoch ( bcs then the API doesn't broadcast the bribes and fees any more)- we do not need any argument to see existing votes -- the
get_user_votes()function in the shadow manager automatically fetches last (=existing) votes by the veNFT owner onchain
Fetch votes dashboard for the next period:
python scripts/shadow/shadow_manager.py fetchFetch votes dashboard for a specific period:
python scripts/shadow/shadow_manager.py fetch --period 2899Fetch historical votes for a previous period (using an existing dashboard):
python scripts/shadow/shadow_manager.py fetch --period 2898 --historical_dashboard_path data/shadow/historical/2898_votes_dashboard_170725.jsonFetch votes and include volatility data:
python scripts/shadow/shadow_manager.py fetch --with-volatility- Fetches pools from the Shadow API.
- Fetches on-chain votes for each pool for the specified period.
- Produces a dashboard file containing:
pool(address)symbolfee_last_7d_usdvol_last_7dbribes_usdpool_votes_period
- Saves the dashboard with the period number in the filename.
This script is intended to be called from the manager (shadow_manager.py), but you can also run its functions directly.
-
run_fetch(period=None, historical_dashboard_path=None)period(optional): Integer period number to fetch. If not provided, fetches for the next period.historical_dashboard_path(optional): Path to an existing dashboard file for historical fetches.
| Flag | Description | Example |
|---|---|---|
| --period | Specify the period number to fetch | --period 2899 |
| --historical_dashboard_path | Path to dashboard for historical fetch | --historical_dashboard_path data/shadow/2898_votes_dashboard.json |
| --with-volatility | Include volatility data (slower but more comprehensive) | --with-volatility |
data/shadow/{period}_votes_dashboard.jsondata/shadow/historical/{period}_votes_dashboard_{date}.json- For historical fetches:
data/shadow/historical/{period}_historical_votes_dashboard.json
- Loads a dashboard file for a given period.
- Fetches your voting power from the blockchain.
- Calculates the optimal allocation of your votes to maximize bribe rewards.
- For historical optimization, removes your actual votes from the dashboard and re-optimizes.
- Saves or displays the results in human-readable and bot formats.
{
"total_expected_usd": 561.21,
"allocations": [
{
"symbol": "CL-wS-GOGLZ-0.5%",
"pool": "0x1f4efc47e5a5ab6539d95a76e2dde6d74462acea",
"votes": 2695.6835792317534,
"pct": 45,
"exp_usd": 256.72
},
{
"symbol": "CL-wS-NAVI-2.0%",
"pool": "0x28f1bb2952ae8742b9e16fd515e3d01f4be6bc30",
"votes": 1766.5794435975142,
"pct": 29,
"exp_usd": 167.14
},
{
"symbol": "CL-USDC-stS-0.1093%",
"pool": "0x2bcb79fd1e0c4251b6f94daee25d4c6ff330cdf8",
"votes": 1537.1868359668588,
"pct": 26,
"exp_usd": 137.35
}
],
"re_run": false,
"period": 2900
}Run via the manager (shadow_manager.py):
-
run_optimize(period=None, save=True, is_historical=False)period(optional): Period to optimize for. If not provided, uses the next period.save(optional): IfTrue, saves results to file. IfFalse, displays in terminal.is_historical(optional): IfTrue, runs historical optimization.
| Flag | Description | Example |
|---|---|---|
| --period | Specify the period to optimize | --period 2899 |
| --historical | Run historical optimization | --historical |
| --display | Display results in terminal instead of saving | --display |
Optimize for the next period (default):
python scripts/shadow/shadow_manager.py optimizeOptimize for a specific period:
python scripts/shadow/shadow_manager.py optimize --period 2899Run historical optimization (removes your actual votes and re-optimizes):
python scripts/shadow/shadow_manager.py optimize --period 2898 --historicalYou will be prompted for the path to the historical dashboard file.
Display results in the terminal:
python scripts/shadow/shadow_manager.py optimize --period 2899 --display- Current optimization:
optimized_votes/shadow/{period}_optimized_votes_human.jsonoptimized_votes/shadow/{period}_optimized_votes_bot.txt- Also saved to:
optimized_votes/shadow/optimized_votes_human.jsonandoptimized_votes/shadow/optimized_votes_bot.txt
- Historical optimization:
optimized_votes/shadow/historical/{period}_historical_optimal_votes.jsonoptimized_votes/shadow/historical/{period}_historical_optimal_votes_bot.txt
- Make sure your
.envfile is set up with the correct RPC and contract addresses. - The pools are always fetched fresh from the API for each run (except for historical fetches).
- For historical optimization, you must provide the dashboard file for the period you want to analyze.
- Fetches pools from the Shadow API
- Calculates emissions-based APR for both the current and next epoch
- For each pool, calculates:
- Current epoch APR: Rewards being earned now based on votes from last epoch
- Next epoch APR: Expected rewards for next epoch based on current votes
- APR at different investment sizes (default: $1k, $10k, $50k)
- How investment size impacts APR due to dilution effects
- Produces a comprehensive LP dashboard showing how APR scales with investment size
- Helps identify optimal pools for LP positions based on emissions rewards
================ LP DASHBOARD ================
Date: 2025-09-10
Showing top 30 pools by next epoch APR
----------------------------------------------
Pool TVL Curr APR Next APR APR @ $1k APR @ $10k APR @ $50k
----------------------------------------------
CL-USDC-stS-0.1047% $231.26K 51.45% 50.89% 50.67% 48.92% 43.84%
wS/GOGLZ $371.86K 70.59% 48.63% 48.53% 47.73% 44.72%
USDC/EUL $0.09M 2.19% 2.05% 2.05% 2.04% 2.00%
...
Run via the manager (shadow_manager.py):
python scripts/shadow/shadow_manager.py lp_dashboard| Flag | Description | Example |
|---|---|---|
| --sizes | Custom investment sizes to calculate APR for | --sizes 5000 25000 100000 |
| --top | Number of top pools to display (default: 30) | --top 50 |
| --no-save | Don't save the dashboard to file | --no-save |
| --no-display | Don't display the dashboard in terminal | --no-display |
Generate default LP dashboard:
python scripts/shadow/shadow_manager.py lp_dashboardGenerate LP dashboard with custom investment sizes:
python scripts/shadow/shadow_manager.py lp_dashboard --sizes 5000 25000 100000Show more pools in the dashboard:
python scripts/shadow/shadow_manager.py lp_dashboard --top 50lp_dashboard/shadow/lp_dashboard_{date}.jsonlp_dashboard/shadow/lp_dashboard.json
This module provides three main tools for working with Aerodrome protocol voting data:
- fetch_votes: Fetches pool data, on-chain votes, and relay votes, saving a dashboard JSON file for analytics and optimization.
- optimizer: Calculates the optimal allocation of your voting power to maximize fees and bribe rewards.
- analytics: Analyzes vote allocation performance and calculates expected returns.
- Fetches all pools from the LpSugar contract.
- Filters for votable pools with active gauges.
- Enriches pools with token symbols.
- Fetches token prices from CoinGecko.
- Retrieves fees and bribes for the current epoch from RewardsSugar.
- Fetches relay votes if configured.
- Produces a dashboard file containing:
- Pool information (address, symbol, type)
- Current fees and bribes
- On-chain vote weights
- Our NFT votes
- Relay votes (if applicable)
This script is intended to be called from the manager (aero_manager.py):
python scripts/aero/aero_manager.py fetch| Flag | Description |
|---|---|
| --historical | Fetch historical data (not fully implemented yet) |
input_data/aero/votes_dashboard.json
- Loads the votes dashboard file.
- Calculates the optimal allocation of your votes to maximize fees and bribes using an equal-marginal algorithm.
- Produces human-readable and bot-friendly output files.
{
"total_expected_usd": 723.45,
"allocations": [
{
"symbol": "WETH/USDC",
"pool": "0x1234567890abcdef1234567890abcdef12345678",
"votes": 1245.6789,
"pct": 40,
"exp_usd": 312.45
},
{
"symbol": "AERO/USDC",
"pool": "0xabcdef1234567890abcdef1234567890abcdef12",
"votes": 987.6543,
"pct": 35,
"exp_usd": 254.32
},
{
"symbol": "wstETH/WETH",
"pool": "0x7890abcdef1234567890abcdef1234567890abcd",
"votes": 765.4321,
"pct": 25,
"exp_usd": 156.68
}
]
}Run via the manager (aero_manager.py):
python scripts/aero/aero_manager.py optimize| Flag | Description |
|---|---|
| --display | Display results in terminal instead of saving files |
- optimized_votes_human.json: Human-readable JSON with vote allocations
- optimized_votes_bot.txt: Bot-friendly format for submitting votes
- Analyzes vote allocation performance.
- Calculates NFT value and expected returns.
- Computes forecasted APR.
- Optionally compares current votes with optimal allocation.
Run via the manager (aero_manager.py):
python scripts/aero/aero_manager.py analyze| Flag | Description |
|---|---|
| --compare | Compare with optimal allocation (if available) |
- analytics_report.json: Latest analytics report
analytics/aero/analytics_report_YYYYMMDD.json: Date-stamped reports
When running analytics, you'll see a summary like:
================ ANALYTICS SUMMARY ================
Voting Power: 5000
Token Price: $0.45
NFT Value: $2250.00
Expected USD per Epoch: $723.45
Forecasted APR: 16.72%
==================================================
- Simulates optimal vote allocation based on current votes and bribes
- Assumes that the remaining votes (total vote power minus current votes) will be allocated optimally
- Fetches total potential voting power from the veAERO contract
- Calculates what APRs would look like if remaining votes were allocated according to equal marginal strategy
- Shows how LPs could benefit from the simulated optimal voting scenario
- Helps identify pools that might receive higher vote weight in the future
- Requires a votes_dashboard and lp_dashboard to compute the optimized votes and the aprs from them.
===== Top 30 Pools by APR (Optimized) =====
1. WETH/USDC - APR: 123.45% - TVL: $62,439,102.55 - Weight: 15.23%
2. WETH/cbBTC - APR: 92.31% - TVL: $29,837,389.91 - Weight: 8.76%
3. USDC/cbBTC - APR: 78.65% - TVL: $25,160,849.28 - Weight: 5.43%
...
Run via the manager (aero_manager.py):
python scripts/aero/aero_manager.py lp_optimized| Flag | Description | Example |
|---|---|---|
| --votes | Path to votes dashboard JSON | --votes input_data/custom.json |
| --lp | Path to LP dashboard JSON | --lp lp_dashboard/custom.json |
| --output | Path to save optimized LP dashboard | --output custom/output.json |
| --top | Number of top pools to display (default: 30) | --top 50 |
| --no-display | Don't display the dashboard in terminal | --no-display |
Generate default optimized LP dashboard:
python scripts/aero/aero_manager.py lp_optimizedUse custom input files:
python scripts/aero/aero_manager.py lp_optimized --votes custom_votes.json --lp custom_lp.jsonlp_optimized/aero/optimized_lp.json: Contains optimized LP dashboard with simulated APRs
- Fetches pools from Aerodrome
- Calculates emissions-based APR for both the current and next epoch
- For each pool, calculates:
- Current epoch APR: Rewards being earned now based on votes from last epoch
- Next epoch APR: Expected rewards for next epoch based on current votes
- APR at different investment sizes (default: $1k, $10k, $50k)
- How investment size impacts APR due to dilution effects
- Produces a comprehensive LP dashboard showing how APR scales with investment size
- Helps identify optimal pools for LP positions based on emissions rewards
================ AERO LP DASHBOARD ================
Date: 2025-09-12
Showing top 30 pools by APR
--------------------------------------------------
Pool TVL APR APR @ $1.0k APR @ $10.0k APR @ $50.0k
--------------------------------------------------
WETH/noice $108.17K 2106.82% 2087.53% 1928.53% 1440.81%
ZORA/WETH $368.33K 804.80% 802.63% 783.53% 708.61%
WETH/TOSHI $270.85K 666.61% 664.16% 642.88% 562.73%
Mog/WETH $70.73K 558.90% 551.11% 489.67% 327.43%
...
Run via the manager (shadow_manager.py):
python scripts/aero/aero_manager.py lp_dashboardEnsure your .env file contains the following variables:
RPC_URL=<Base network RPC URL>
LP_SUGAR_ADDRESS=<LpSugar contract address>
REWARDS_SUGAR_ADDRESS=<RewardsSugar contract address>
VOTER_ADDRESS=<Voter contract address>
VE_ADDRESS=<Ve contract address>
NFT_ID=<Your veNFT ID>
# for relay support
RELAY_ACCOUNT=<Relay account address>
RELAY_SUGAR_ADDRESS=<RelaySugar contract address>
Here's a quick reference for all available commands:
# Fetch votes data
python scripts/aero/aero_manager.py fetch
# Optimize votes
python scripts/aero/aero_manager.py optimize
python scripts/aero/aero_manager.py optimize --display
# Analyze votes
python scripts/aero/aero_manager.py analyze
python scripts/aero/aero_manager.py analyze --compare- The pools are fetched fresh from on-chain data for each run.
- Price data is fetched from CoinGecko during both fetch and analytics operations.
- The optimizer uses an equal-marginal algorithm to maximize expected returns.
- The dashboard is always saved to votes_dashboard.json as the primary data source.