Conversation
📝 WalkthroughWalkthroughRefactored Arrakis V1 adaptor to use a FACTORIES-driven getApy pipeline: fetch APYs from an indexer, enumerate deployers and pools, fetch token metadata and balances via multicall, retrieve prices, compute TVL (filtering < $1,000), and export apy plus a public URL and timetravel flag. Changes
Sequence DiagramsequenceDiagram
participant Module as Arrakis Module
participant Indexer as Arrakis Indexer
participant Factory as Chain/Factory
participant MultiCall as MultiCall Service
participant PriceSvc as LLama Price Service
participant Output as Pools Output
Module->>Indexer: fetch APY data
Indexer-->>Module: apyByVault map
Module->>Factory: iterate FACTORIES -> getDeployers()
Factory-->>Module: deployer list
Module->>Factory: getPools(deployer)
Factory-->>Module: vault addresses
Module->>MultiCall: request token0/token1 & balances
MultiCall-->>Module: token addresses & balances
Module->>PriceSvc: fetch token prices & metadata
PriceSvc-->>Module: prices, symbols, decimals
Module->>Module: compute TVL per vault (filter < $1000)
Module->>Output: emit pool objects (pool, chain, project, symbol, tvlUsd, apyBase, underlyingTokens)
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 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 |
|
The arrakis-v1 adapter exports pools: Test Suites: 1 passed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/adaptors/arrakis-v1/index.js`:
- Around line 86-91: The uniqueTokens array currently builds a Set from
token0Results.output and token1Results.output directly, which can include
null/undefined and break later multicall targets; update the construction that
derives uniqueTokens (the code using token0Results, token1Results and the
variable uniqueTokens) to filter out null/undefined outputs first (e.g., map to
r.output then .filter(t => t != null) or .filter(Boolean)) before creating the
Set so only valid token addresses are included.
- Around line 136-140: Price lookups use checksummed token0/token1 so keys like
`${chain}:${token0}` don't match DefiLlama's lowercase keys; update the key
construction in the price lookup (variables price0Key and price1Key) to
lowercase the token portion (e.g., use `${chain}:${token0.toLowerCase()}` and
`${chain}:${token1.toLowerCase()}` or otherwise lowercase the full key) so the
prices lookup from the prices object returns the correct values for price0 and
price1.
🧹 Nitpick comments (2)
src/adaptors/arrakis-v1/index.js (2)
49-60: Consider parallelizinggetPoolscalls for better performance.The sequential
awaitinside thefor...ofloop processes deployers one at a time. If there are many deployers, this could slow down the adapter significantly.♻️ Proposed parallel implementation
- const vaultAddresses = []; - for (const deployer of deployers) { - const vaultsResult = await sdk.api.abi.call({ - target: factoryAddress, - abi: arrakisABI.getPools, - params: [deployer], - chain: chain, - }); - - if (vaultsResult.output && vaultsResult.output.length > 0) { - vaultAddresses.push(...vaultsResult.output); - } - } + const vaultsResults = await Promise.all( + deployers.map((deployer) => + sdk.api.abi.call({ + target: factoryAddress, + abi: arrakisABI.getPools, + params: [deployer], + chain: chain, + }) + ) + ); + + const vaultAddresses = vaultsResults + .filter((result) => result.output && result.output.length > 0) + .flatMap((result) => result.output);
148-156: Consider lowercasing the pool address for consistency.Many DefiLlama adapters lowercase pool addresses to ensure consistent identifiers across the system. This prevents duplicate pool entries if the same address appears with different cases.
♻️ Suggested change
allPools.push({ - pool: vault, + pool: vault.toLowerCase(), chain: utils.formatChain(chain), project: 'arrakis-v1', symbol: `${token0Meta.symbol}-${token1Meta.symbol}`, tvlUsd: tvlUsd, apyBase: apyBase, underlyingTokens: [token0, token1], });
|
The arrakis-v1 adapter exports pools: Test Suites: 1 passed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/adaptors/arrakis-v1/index.js`:
- Around line 114-119: The axios GET for prices (the priceKeys -> prices call)
currently has no error handling so a failed request will crash processing for
the chain; wrap the axios.get(...) that populates prices in a try-catch, catch
and log the error via the existing logger, and provide a safe fallback (e.g.,
set prices = {} or skip tokens with missing prices) so processing continues for
other chains; ensure references to priceKeys and prices remain and that
downstream code can handle empty/missing price entries gracefully.
🧹 Nitpick comments (3)
src/adaptors/arrakis-v1/index.js (3)
17-31: Consider logging when APY data is unavailable for debugging.The error handling silently falls back to an empty
apyByVaultmap. While this prevents the adapter from failing, it may make debugging difficult when APY values are unexpectedly 0.Consider also logging when the API response doesn't contain the expected data structure:
if (arrakisResponse.data.success && arrakisResponse.data.vaults) { arrakisResponse.data.vaults.forEach((vault) => { const apyBase = vault.averageApr || 0; apyByVault[vault.id.toLowerCase()] = apyBase; }); + } else { + console.warn('Arrakis APY API returned unexpected response structure'); }
47-60: Sequential deployer iteration could be parallelized for performance.The
getPoolscalls are made sequentially for each deployer. If there are many deployers, this could slow down the adapter. Consider parallelizing:// Get all vaults for each deployer const vaultAddresses = []; - for (const deployer of deployers) { - const vaultsResult = await sdk.api.abi.call({ + const vaultResults = await Promise.all( + deployers.map((deployer) => + sdk.api.abi.call({ + target: factoryAddress, + abi: arrakisABI.getPools, + params: [deployer], + chain: chain, + }) + ) + ); + + for (const vaultsResult of vaultResults) { + if (vaultsResult.output && vaultsResult.output.length > 0) { + vaultAddresses.push(...vaultsResult.output); + } + } - target: factoryAddress, - abi: arrakisABI.getPools, - params: [deployer], - chain: chain, - }); - - if (vaultsResult.output && vaultsResult.output.length > 0) { - vaultAddresses.push(...vaultsResult.output); - } - }
133-134: Potential precision loss withNumber()for large token balances.Using
Number()on blockchain balance values (which can be very large integers) may cause precision loss due to JavaScript's floating-point limitations. For tokens with high decimals or large supplies, consider using a BigInt-safe approach:- const amount0 = Number(balances[0]) / 10 ** token0Meta.decimals; - const amount1 = Number(balances[1]) / 10 ** token1Meta.decimals; + const amount0 = Number(BigInt(balances[0])) / 10 ** token0Meta.decimals; + const amount1 = Number(BigInt(balances[1])) / 10 ** token1Meta.decimals;However, since the TVL calculation multiplies by price and the final result is in USD (typically < trillions), the current approach is likely acceptable in practice for most pools. Just be aware of potential edge cases with extremely large balances.
| const priceKeys = uniqueTokens.map((t) => `${chain}:${t.toLowerCase()}`); | ||
| const prices = ( | ||
| await axios.get( | ||
| `https://coins.llama.fi/prices/current/${priceKeys.join(',')}` | ||
| ) | ||
| ).data.coins; |
There was a problem hiding this comment.
Add error handling for the price API call.
If the price API call fails, it will throw an unhandled exception and skip processing for the entire chain. Consider wrapping this in a try-catch or providing a fallback:
- const priceKeys = uniqueTokens.map((t) => `${chain}:${t.toLowerCase()}`);
- const prices = (
- await axios.get(
- `https://coins.llama.fi/prices/current/${priceKeys.join(',')}`
- )
- ).data.coins;
+ const priceKeys = uniqueTokens.map((t) => `${chain}:${t.toLowerCase()}`);
+ let prices = {};
+ try {
+ prices = (
+ await axios.get(
+ `https://coins.llama.fi/prices/current/${priceKeys.join(',')}`
+ )
+ ).data.coins;
+ } catch (priceError) {
+ console.error(`Error fetching prices for ${chain}:`, priceError.message);
+ continue;
+ }🤖 Prompt for AI Agents
In `@src/adaptors/arrakis-v1/index.js` around lines 114 - 119, The axios GET for
prices (the priceKeys -> prices call) currently has no error handling so a
failed request will crash processing for the chain; wrap the axios.get(...) that
populates prices in a try-catch, catch and log the error via the existing
logger, and provide a safe fallback (e.g., set prices = {} or skip tokens with
missing prices) so processing continues for other chains; ensure references to
priceKeys and prices remain and that downstream code can handle empty/missing
price entries gracefully.
Summary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.