Skip to Content
Recipes

Phase 4 — Compare Pools

Add a yield scanner that checks all Cetus pools every 30 minutes. The agent reports which pools are earning the most so you can decide whether to move your funds.

Time: ~5 minutes | Requires: Phase 2 complete (Phase 3 optional)


The idea

Your agent is earning fees in one pool (SUI/USDC). But Cetus has 70+ pools. Some may be earning significantly more. This phase adds a scanner that periodically checks yield across all Cetus pools using DeFiLlama’s public API.

The scanner runs alongside your existing position management. It doesn’t move funds — it gives you data to decide.

New code: yield scanner

Add to agent.js:

import https from 'https'; const YIELD_SCAN_INTERVAL = 6; // every 6th cycle (30 min at 5-min intervals) let cycleCount = 0; async function fetchDefiLlamaYields() { return new Promise((resolve, reject) => { https.get('https://yields.llama.fi/pools', (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { resolve(JSON.parse(data).data || []); } catch (e) { reject(e); } }); }).on('error', reject); }); } async function scanYields() { try { const allPools = await fetchDefiLlamaYields(); const suiPools = allPools.filter(p => p.chain === 'Sui'); // Top Cetus pools by APY const cetusPools = suiPools .filter(p => p.project === 'cetus-clmm') .sort((a, b) => (b.apy || 0) - (a.apy || 0)) .slice(0, 10) .map(p => ({ symbol: p.symbol, apy: parseFloat((p.apy || 0).toFixed(2)), tvl: Math.round(p.tvlUsd || 0), })); // Find our pool const allCetus = suiPools.filter(p => p.project === 'cetus-clmm'); const ourPool = allCetus.find(p => (p.symbol || '').match(/USDC.*SUI|SUI.*USDC/i)); log('event', 'yield_scan', { cetusTopPools: cetusPools, currentPool: { symbol: 'SUI/USDC', apy: ourPool ? parseFloat((ourPool.apy || 0).toFixed(2)) : null, tvl: ourPool ? Math.round(ourPool.tvlUsd || 0) : null, rank: ourPool ? allCetus.sort((a, b) => (b.apy || 0) - (a.apy || 0)).indexOf(ourPool) + 1 : null, }, scanTime: new Date().toISOString(), }); log('info', 'Yield scan complete', { poolsFound: cetusPools.length }); } catch (err) { log('warn', 'Yield scan failed', { error: err.message }); } }

Add to the main loop

Run the scan on startup and every 6th cycle:

// In runAgent(), before the main while loop: await scanYields(); // Inside the while loop, after runCycle(): cycleCount++; if (cycleCount % YIELD_SCAN_INTERVAL === 0) { await scanYields(); }

What it logs

Every 30 minutes, the agent logs a yield_scan event:

{ "message": "yield_scan", "cetusTopPools": [ { "symbol": "WAL-SUI", "apy": 131.7, "tvl": 116180 }, { "symbol": "DEEP-SUI", "apy": 73.8, "tvl": 747154 }, { "symbol": "CETUS-SUI", "apy": 34.1, "tvl": 1522870 } ], "currentPool": { "symbol": "SUI/USDC", "apy": 24.3, "rank": 13 } }

Higher APY pools exist — but they often have higher risk (smaller TVL, newer tokens, more volatility). The data helps you make an informed decision.

Future: auto-migration

In a future version, the agent could automatically move funds to the best pool. This adds complexity (slippage, migration gas costs, risk scoring) but the monitoring groundwork is here.

Next step

Why limit yourself to one protocol? Phase 5 — Compare Protocols scans yield across all of Sui — lending protocols, other DEXes, and more.

Last updated on