Conversation
Adds yldfi auto-compounding vault yields using Yearn Kong API for APY data. yldfi is a yield optimizer using Yearn V3 tokenized strategies. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a new YLD adapter module that lists three vaults, fetches prices and per-vault ERC4626 info in parallel, builds normalized APY/tvl entries per vault, logs and skips failed fetches, and exports Changes
Sequence DiagramsequenceDiagram
participant Client
participant YLD_Adapter as "YLD Adapter\n(src/adaptors/yld/index.js)"
participant PriceSvc as "Price Service\n(getPrices)"
participant ERC4626 as "ERC4626 Utility\n(getVaultInfo)"
participant Blockchain
Client->>YLD_Adapter: call apy()
YLD_Adapter->>PriceSvc: fetch all token prices
PriceSvc-->>YLD_Adapter: return prices
YLD_Adapter->>ERC4626: request vault info (parallel for each vault)
ERC4626->>Blockchain: read ERC4626 on-chain data (totalAssets, decimals, etc.)
Blockchain-->>ERC4626: return on-chain values
ERC4626-->>YLD_Adapter: return normalized vault info (tvl, apyBase, underlying token)
YLD_Adapter->>Client: return array of standardized APY entries (successful vaults only)
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Error while running yldfi adapter: Test Suites: 1 failed, 1 total |
- Rename adapter directory from yldfi to yld - Fetch strategy vaults dynamically from yldfi.co/api/vaults - Only include strategy vaults (ys-prefix) to avoid double counting - Update project slug to 'yld' Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
|
The only failing test is the protocol slug validation — |
Both y-prefix (wrapper) and ys-prefix (strategy) vaults are valid deposit targets. Wrapper vaults can be used as LlamaLend collateral. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
There was a problem hiding this comment.
Pull request overview
Adds a new yld APY adapter to the adapters codebase, fetching vault addresses from yldfi.co and pulling APY/TVL data from Yearn’s Kong GraphQL API to produce DefiLlama-compatible pool objects.
Changes:
- Introduces
src/adaptors/yld/index.jsimplementing dynamic vault discovery viahttps://yldfi.co/api/vaults. - Queries Yearn Kong GraphQL (
https://kong.yearn.farm/api/gql) for APY/TVL for the discovered vaults. - Maps Kong vault data into standardized pool objects for the adapter output.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| @@ -0,0 +1,59 @@ | |||
| const axios = require('axios'); | |||
| const utils = require('../utils'); | |||
src/adaptors/yld/index.js
Outdated
| const vaultAddresses = Object.entries(vaultData) | ||
| .filter(([key, v]) => (key.startsWith('ys') || key.startsWith('y')) && v && typeof v === 'object' && v.address) | ||
| .map(([, v]) => v.address); |
Kong API provides multiple APY windows. Use weeklyNet (7-day) to be consistent with what yldfi.co shows users. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
Address Copilot review comments: - Remove unused utils require - Clarify that both wrapper + strategy vaults are intentionally included Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/adaptors/yld/index.js (1)
30-32: Tighten vault key filtering to explicit prefixes.Line 31 currently accepts any key starting with
y, which is broader than the intended strategy/wrapper prefixes and may include unrelated entries.🔍 Proposed refinement
const vaultAddresses = Object.entries(vaultData) - .filter(([key, v]) => (key.startsWith('ys') || key.startsWith('y')) && v && typeof v === 'object' && v.address) + .filter( + ([key, v]) => + (key.startsWith('ys-') || key.startsWith('y-')) && + v && + typeof v === 'object' && + v.address + ) .map(([, v]) => v.address);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/adaptors/yld/index.js` around lines 30 - 32, The current vaultAddresses computation over vaultData uses key.startsWith('y') which is too broad; update the filter in the vaultAddresses creation to check keys against an explicit list of allowed prefixes (e.g., const allowedPrefixes = ['ys', 'yv', 'yve', ...]) and only accept keys where allowedPrefixes.some(p => key.startsWith(p)). Keep the other guards (v && typeof v === 'object' && v.address') and the .map(([, v]) => v.address) unchanged so vaultAddresses still extracts addresses from valid vault objects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/adaptors/yld/index.js`:
- Around line 41-52: Guard against malformed vault entries by first filtering
the vaults array for entries that have the required nested properties (check
vault.asset, vault.asset.symbol, vault.asset.address, vault.tvl &&
vault.tvl.close, vault.apy && vault.apy.net, and vault.symbol) and skip any
vaults missing them, then map the filtered list to your output; when mapping,
explicitly coerce numeric values using Number(...) with a safe fallback (e.g.,
Number(vault.tvl.close) || 0 and Number(vault.apy.net) ? * 100 : 0) and use
toLowerCase() only on strings (e.g., vault.symbol && vault.symbol.toLowerCase(),
vault.address && vault.address.toLowerCase()) to avoid runtime errors — apply
these checks around the existing vaults.map logic and the pool, symbol, tvlUsd,
apyBase, underlyingTokens, and url constructions.
- Around line 29-39: The axios calls to fetch vaults and to post the GraphQL
query (axios.get for VAULTS_API and axios.post for KONG_API with variables {
addresses: vaultAddresses } and query) lack timeouts; update both calls to
include an explicit timeout (e.g., 10000–15000 ms) via axios request options so
the adaptor won’t hang on slow/unresponsive upstreams, ensuring the same timeout
pattern used across other adaptors in the codebase.
---
Nitpick comments:
In `@src/adaptors/yld/index.js`:
- Around line 30-32: The current vaultAddresses computation over vaultData uses
key.startsWith('y') which is too broad; update the filter in the vaultAddresses
creation to check keys against an explicit list of allowed prefixes (e.g., const
allowedPrefixes = ['ys', 'yv', 'yve', ...]) and only accept keys where
allowedPrefixes.some(p => key.startsWith(p)). Keep the other guards (v && typeof
v === 'object' && v.address') and the .map(([, v]) => v.address) unchanged so
vaultAddresses still extracts addresses from valid vault objects.
Shows the vault product name so users can distinguish between wrapper and strategy vaults with the same underlying asset. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
- Use explicit vault key prefixes instead of broad startsWith('y')
- Guard against malformed vault payloads with field validation
- Coerce numeric values with Number() to prevent type issues
- Add 10s timeout to both API calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
Matches convention of other yield-server adapters and Yearn's own adapter. Weekly is too volatile due to harvest timing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
- Use utils.formatSymbol for underlying asset symbol (convention) - Use utils.formatChain for chain name (convention) - Add poolMeta with vault symbol to distinguish strategy vs wrapper - Re-add utils import Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
Switch from Kong API to DefiLlama's standard ERC-4626 utility. Calculates APY from 24h convertToAssets growth on-chain. Matches pattern used by Frax and Resupply adapters. - Remove Kong API dependency - Remove dynamic vault fetching (hardcode like other ERC-4626 adapters) - Use utils.formatSymbol and utils.formatChain - Add poolMeta to distinguish vaults with same underlying Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
Matches Frax convention — show the vault token symbol, not underlying. Remove poolMeta since vault symbols are already unique. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/adaptors/yld/index.js`:
- Around line 25-33: The tvlUsd field is currently just normalized token units
(info.tvl / 1e18) but needs to be USD-valued; update the code that builds the
return object (around getERC4626Info / the tvlUsd assignment) to multiply the
normalized token amount by the underlying token USD price (use vault.underlying)
using the same timestamp basis as info (or pass info.timestamp), e.g., fetch the
USD price via the existing price utility (e.g., utils.getPrice /
utils.getTokenUsdPrice or equivalent) for chain 'ethereum' and multiply before
assigning tvlUsd; ensure you reference info.tvl, vault.underlying, and
getERC4626Info when implementing the change.
- Line 29: The PR uses an unregistered protocol slug by setting project: 'yld'
in the adaptor (the 'project' key/value pair), which will fail validation;
either register the 'yld' slug in the public yields protocol configuration (add
the slug and its metadata to the public protocol config) or update the adaptor
to reference an existing registered slug instead of 'yld' so the value used by
the adaptor matches an entry in the public protocol config.
| return { | ||
| pool: `${vault.address}-ethereum`.toLowerCase(), | ||
| chain: utils.formatChain('ethereum'), | ||
| project: 'yld', |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Verify whether `yld` is present in the public yields protocol config
curl -s 'https://api.llama.fi/config/yields?a=1' \
| jq -r '.protocols[]?.slug' \
| rg -n '^yld$' || trueRepository: DefiLlama/yield-server
Length of output: 48
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# First, check if API is returning valid data at all
echo "=== API Response Preview ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq '.protocols | length' 2>/dev/null || echo "API query failed or invalid JSON"
# Try extracting all protocol slugs to see what's there
echo -e "\n=== Sample of Protocol Slugs ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq -r '.protocols[]?.slug' 2>/dev/null | head -20 || echo "Failed to extract slugs"
# Count total protocols
echo -e "\n=== Total Protocols ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq -r '.protocols[]?.slug' 2>/dev/null | wc -l
# Specifically check for yld
echo -e "\n=== Check for 'yld' specifically ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq -r '.protocols[]?.slug' 2>/dev/null | grep -c '^yld$' || echo "yld not found"Repository: DefiLlama/yield-server
Length of output: 341
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check the actual JSON structure
echo "=== First protocol object ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq '.protocols[0]' 2>/dev/null | head -30
# Also check if there's a root-level field that contains protocol info
echo -e "\n=== Top-level keys ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq 'keys' 2>/dev/null
# Search local repo for yld protocol definition
echo -e "\n=== Local yld references ==="
find . -type f -name "*.js" -o -name "*.json" | xargs grep -l "yld" | grep -E "(config|protocol|adaptor)" | head -10Repository: DefiLlama/yield-server
Length of output: 95
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Get raw API response (first 1000 chars to see structure)
echo "=== Raw API Response (first portion) ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | head -c 1000
# Try to understand the actual structure
echo -e "\n\n=== API response first 100 lines ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | head -100
# Search local repo for yld-related files
echo -e "\n\n=== YLD files in repo ==="
find . -type f \( -name "*yld*" -o -path "*/yld/*" \) | head -20
# Check the yld adaptor file itself
echo -e "\n\n=== Content of src/adaptors/yld/index.js ==="
if [ -f "src/adaptors/yld/index.js" ]; then
cat -n "src/adaptors/yld/index.js"
fiRepository: DefiLlama/yield-server
Length of output: 1108
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if 'yld' exists as a protocol key
echo "=== Checking for 'yld' in protocols ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq 'has("protocols") and .protocols | has("yld")' 2>/dev/null
# List sample protocol keys to see the pattern
echo -e "\n=== Sample protocol keys ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq '.protocols | keys[:20]' 2>/dev/null
# Count all protocol keys
echo -e "\n=== Total protocol count ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | jq '.protocols | keys | length' 2>/dev/null
# Check the yld adaptor file
echo -e "\n=== src/adaptors/yld/index.js ==="
if [ -f "src/adaptors/yld/index.js" ]; then
head -50 "src/adaptors/yld/index.js"
fiRepository: DefiLlama/yield-server
Length of output: 105
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search for 'yld' directly in the API response using grep
echo "=== Searching for 'yld' in API response ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | grep -o '"yld"' || echo "yld not found in API response"
# Count occurrences
echo -e "\n=== Count of 'yld' in API ==="
curl -s 'https://api.llama.fi/config/yields?a=1' | grep -c '"yld"' || echo "0"
# Check the yld adaptor file
echo -e "\n=== src/adaptors/yld/index.js (first 60 lines) ==="
if [ -f "src/adaptors/yld/index.js" ]; then
head -60 "src/adaptors/yld/index.js"
else
echo "File not found"
fi
# Look for protocol config files in repo
echo -e "\n=== Protocol config files ==="
find . -type f -name "*.json" | grep -i protocol | head -10Repository: DefiLlama/yield-server
Length of output: 2229
Protocol slug 'yld' is not registered in the public protocol config.
Line 29 uses project: 'yld', but verification confirms the slug is absent from the public yields protocol configuration. This will cause validation failures and CI blockers. The protocol slug must be registered in the protocol config before this PR can be merged.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/adaptors/yld/index.js` at line 29, The PR uses an unregistered protocol
slug by setting project: 'yld' in the adaptor (the 'project' key/value pair),
which will fail validation; either register the 'yld' slug in the public yields
protocol configuration (add the slug and its metadata to the public protocol
config) or update the adaptor to reference an existing registered slug instead
of 'yld' so the value used by the adaptor matches an entry in the public
protocol config.
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
totalAssets returns raw token amounts, not USD. Multiply by underlying token price from DefiLlama coins API for accurate tvlUsd. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Error while running yld adapter: Test Suites: 1 failed, 1 total |
|
The yld adapter exports pools: Test Suites: 1 passed, 1 total |
Summary
Test plan
Related