A Python toolkit for indexing Aerodrome liquidity pools, filtering votable pools, enriching them with metadata, and computing live epoch‐to‐date fees & bribes (in USD) using CoinGecko.
p y t h f a r m s/
├── abi/
│ ├── LpSugar.json
│ ├── POOL_ABI.json
│ ├── RewardsSugar.json
│ ├── V2_FACTORY_ABI.json
│ └── V3_FACTORY_ABI.json
│
├── data/
│ ├── enriched_votable_pools.json
│ ├── indexed_pools.json
│ ├── live_epoch_fees_usd.json
│ ├── sugar_pools.json
│ ├── token_to_id.json
│ └── votable_pools.json
│
├── scripts/
│ ├── helper/
│ │ └── 1_get_coingecko_token_ids.py
│ │
│ ├── 1_get_sugar_pools.py
│ ├── 2_filter_votable_pools.py
│ ├── 3_enriched_votable_pools.py
│ └── 4_live_epoch_fees_with_coingecko.py
│
├── venv/ ← Python virtual environment (ignored by Git)
├── .env ← Environment variables (RPC URL, RewardsSugar address)
├── .gitignore
├── README.md
└── requirements.txt
-
Clone the repo (if you haven’t already):
git clone https://github.com/yourusername/pythfarms.git cd pythfarms -
Create a Python virtual environment and install dependencies:
python3 -m venv venv source venv/bin/activate # macOS/Linux venv\Scripts\activate # Windows pip install --upgrade pip pip install -r requirements.txt
-
Create a
.envfile in the project root with the following variables:RPC_URL=<YOUR_BASE_RPC_ENDPOINT> REWARDS_SUGAR_ADDRESS=<RewardsSugar_contract_address_on_Base>RPC_URLmust point to a Base‐compatible JSON‐RPC node (e.g. Ankr, Alchemy, etc.).REWARDS_SUGAR_ADDRESSis the deployed RewardsSugar contract on Base, e.g.0x….
-
Verify your ABI files are in
abi/:LpSugar.jsonPOOL_ABI.jsonRewardsSugar.jsonV2_FACTORY_ABI.jsonV3_FACTORY_ABI.json
Below is the recommended order to run each script. Each step writes a JSON file under data/:
(You can also simply run the entire flow with ./run_all.sh)
The optimized results will be printed to the console.
python scripts/1_get_sugar_pools.py-
Input: None
-
Output:
-
data/sugar_pools.json- Contains an array of all pools (basic volatile, V3, CL) as returned by LpSugar’s
all(...).
- Contains an array of all pools (basic volatile, V3, CL) as returned by LpSugar’s
-
-
What it does:
- Connects to LpSugar on Base.
- Paginates through
all(limit, offset)until all pools are fetched. - Saves them to
data/sugar_pools.json.
python scripts/2_filter_votable_pools.py-
Input:
data/sugar_pools.json
-
Output:
-
data/votable_pools.json- Subset of pools that have
gauge_alive == true.
- Subset of pools that have
-
-
What it does:
- Reads
sugar_pools.json. - Keeps only those entries where
"gauge_alive": true. - Writes the filtered array to
votable_pools.json.
- Reads
python scripts/3_enriched_votable_pools.py-
Input:
data/votable_pools.json
-
Output:
-
data/enriched_votable_pools.json-
Each pool object now has:
symbol:"TOKEN0/TOKEN1"(from ERC-20 calls)token0,token1(addresses)decimals,liquidity,reserve0,reserve1, etc., if pulled from the pool contract
-
-
-
What it does:
-
Reads
votable_pools.json. -
For each pool:
- Reads on-chain
token0.symbol()andtoken1.symbol(). - Attempts to read
pool.symbol()(if available). - Reads
decimals(), reserves (reserve0,reserve1), etc. - Populates a unified
symbolfield and any missing fields.
- Reads on-chain
-
Saves enriched data to
enriched_votable_pools.json.
-
python scripts/helper/1_get_coingecko_token_ids.py-
Input:
data/enriched_votable_pools.json
-
Output:
-
data/token_to_id.json{ "0xTokenAddr…": "coingecko-id", … }
-
-
What it does:
- Reads all pools from
enriched_votable_pools.json, extracts uniquetoken0/token1addresses. - Fetches CoinGecko’s
/coins/list?include_platform=true, which returns every CoinGecko coin with a"platforms"dictionary. - Builds a mapping for any coin whose
"platforms"contain"base": "<token_address>". - Writes out
{ contract_address: coingecko_id }totoken_to_id.json.
- Reads all pools from
python scripts/4_live_epoch_fees_with_coingecko.py-
Input:
data/enriched_votable_pools.jsondata/token_to_id.json
-
Output:
-
data/live_epoch_fees_usd.json[ { "pool": "0xPoolAddress...", "symbol": "TOKEN0/TOKEN1", "fee0_amount": 1234500000000000000, "fee1_amount": 987650000000000000, "fees_usd": 234.56, "bribes_usd": 12.34, "bribes": [ { "token": "0xBribeTokenAddr", "symbol": "BRIBSY", "amount": 5000000000000000000, "amount_token": 5.0, "amount_usd": 7.50 }, { "token": "0xAnotherBribeToken", "symbol": "ABC", "amount": 2000000, "amount_token": 2.0, "amount_usd": 4.84 } ], "total_usd": 246.90 }, … ]
-
-
What it does:
-
Reads
enriched_votable_pools.jsonto get each pool’stoken0/token1. -
Reads
token_to_id.jsonto map each token address → CoinGecko ID. -
Calls CoinGecko’s
/simple/price?ids={comma-separated-ids}&vs_currencies=usdin batches of ≲80 IDs at a time (to respect rate limits). -
Builds a dictionary
{ contract_address: Decimal(usd_price) }for each token. -
For each pool:
- Uses Sugar’s
epochsByAddress(1, 0, poolAddress)to fetch the “live” (current‐epoch)LpEpochstruct. - Splits
fees[]intofee0_amount(fortoken0) andfee1_amount(fortoken1). - Converts each raw
feeX_amount→ decimal usingdecimals()and multiplies by the USD price to getfees_usd. - Iterates
bribes[], computes detailed{ token, symbol, amount, amount_token, amount_usd }for each bribe token. - Sums all bribe USD →
bribes_usd. - Computes
total_usd = fees_usd + bribes_usd. - Stores a JSON object per pool, sorted descending by
total_usd.
- Uses Sugar’s
-
Writes the final array to
live_epoch_fees_usd.json.
-
web3==6.x.x
python-dotenv
requests
tqdm