Phase 5 — Watch the Sui yield landscape
Your agent runs on Cetus — its concentrated-liquidity position is the engine. Phase 5 widens the agent’s situational awareness: it pulls live yield data for the rest of Sui DeFi so the operator can see how the position compares in context. The agent stays where it is. You stay informed.
Time: ~5 minutes | Requires: Phase 4 complete
The idea
After Phase 4 the agent already ranks Cetus pools and knows whether it’s in the strongest one. Phase 5 widens the lens: how does your Cetus position look against the broader Sui yield landscape?
Two shapes of yield exist on Sui:
- DEX liquidity — Cetus, Bluefin, FlowX, Full Sail, and others. Fee-based returns, exposure to impermanent loss, requires active management.
- Lending — NAVI, Scallop, Kai Finance. Interest-based returns, no impermanent loss, set-and-forget.
You don’t need to move funds based on this data — for most operators, knowing the landscape is enough. But seeing your Cetus APY alongside the rest of the ecosystem tells you when conditions across Sui DeFi are shifting versus when something specific is happening on your venue.
Update the yield scanner
Extend the scanYields() function from Phase 4:
async function scanYields() {
try {
const allPools = await fetchDefiLlamaYields();
const suiPools = allPools.filter(p => p.chain === 'Sui');
// Phase 4: Top Cetus pools (already implemented)
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) }));
// Phase 5: Landscape view
const protocols = {};
for (const p of suiPools) {
if (!protocols[p.project]) protocols[p.project] = [];
protocols[p.project].push(p);
}
const crossProtocol = [];
// Lending protocols — find best SUI and USDC lending rates
for (const proj of ['navi-lending', 'scallop-lend', 'current', 'kai-finance']) {
const pools = protocols[proj] || [];
for (const asset of ['SUI', 'HASUI', 'USDC']) {
const pool = pools.find(p => p.symbol === asset);
if (pool) {
crossProtocol.push({
protocol: proj, type: 'lending', asset: pool.symbol,
apy: parseFloat((pool.apy || 0).toFixed(2)),
tvl: Math.round(pool.tvlUsd || 0),
});
}
}
}
// Other DEX pools — find best SUI/USDC pool per DEX
for (const proj of ['cetus-clmm', 'bluefin-spot', 'turbos', 'flowx-v3', 'full-sail']) {
const pools = protocols[proj] || [];
const suiUsdc = pools.find(p => (p.symbol || '').match(/SUI.*USDC|USDC.*SUI/i));
if (suiUsdc) {
crossProtocol.push({
protocol: proj, type: 'lp', asset: suiUsdc.symbol,
apy: parseFloat((suiUsdc.apy || 0).toFixed(2)),
tvl: Math.round(suiUsdc.tvlUsd || 0),
});
}
}
crossProtocol.sort((a, b) => b.apy - a.apy);
const ourPool = suiPools.find(p => p.project === 'cetus-clmm' && (p.symbol || '').match(/USDC.*SUI|SUI.*USDC/i));
log('event', 'yield_scan', {
cetusTopPools: cetusPools,
crossProtocol,
currentPool: {
symbol: 'SUI/USDC', protocol: 'cetus-clmm',
apy: ourPool ? parseFloat((ourPool.apy || 0).toFixed(2)) : null,
tvl: ourPool ? Math.round(ourPool.tvlUsd || 0) : null,
},
landscapeLeader: crossProtocol[0] || null,
scanTime: new Date().toISOString(),
});
} catch (err) {
log('warn', 'Yield scan failed', { error: err.message });
}
}What it logs
The yield_scan event now carries landscape context alongside the agent’s own position:
{
"crossProtocol": [
{ "protocol": "flowx-v3", "type": "lp", "asset": "SUI-USDC", "apy": 32.7, "tvl": 55270 },
{ "protocol": "bluefin-spot", "type": "lp", "asset": "SUI-USDC", "apy": 32.6, "tvl": 3270836 },
{ "protocol": "cetus-clmm", "type": "lp", "asset": "USDC-SUI", "apy": 24.3, "tvl": 1488269 },
{ "protocol": "kai-finance", "type": "lending", "asset": "SUI", "apy": 6.2, "tvl": 3710052 },
{ "protocol": "scallop-lend", "type": "lending", "asset": "SUI", "apy": 2.9, "tvl": 3359492 }
],
"landscapeLeader": { "protocol": "flowx-v3", "type": "lp", "asset": "SUI-USDC", "apy": 32.7 }
}Reading the data
The crossProtocol array gives you two views into the Sui yield landscape:
DEX pools (Cetus, Bluefin, FlowX, Full Sail, etc.) — fee-based yield. Higher headline APYs, with the usual trade-offs:
- Impermanent loss: if token prices diverge, your LP value can lag a simple hold
- Active range management, gas on every reposition
- Returns swing with trading volume
Lending protocols (NAVI, Scallop, Kai Finance) — interest-based yield. Lower headline APY in exchange for:
- No impermanent loss
- No repositioning, no gas drag
- More predictable, easier to reason about
For most operators of a Cetus yield agent, the useful read is “is my position in line with comparable Sui CLMM venues today, and is the broader yield market normal?” — not “should I migrate to lending.” If the landscape data tells you something actionable, the operator makes the call; the agent doesn’t reach across protocols on its own.
What’s next
You now have a complete Cetus yield agent: monitoring, position management, adaptive sizing, intra-Cetus pool ranking, and broader landscape awareness. Natural next directions:
- Auto-rebalance across Cetus pools when one materially out-yields your current pool over a sustained window — extends Phase 4’s ranking into action
- Multi-pool: hold positions in several Cetus pools simultaneously and balance allocation
- Risk management: stop-loss if position value drops below a threshold
- Dashboard: visualize all this data in a web UI (see the dogfood dashboard for an example)
Related
- WaaP for Agents — CLI reference
- Morpho Yield Optimizer — similar yield strategy on EVM
- Polymarket Agent — trading agent on Polygon