Skip to content

add new flare vaults to yield page#2437

Open
agbanusi wants to merge 6 commits intoDefiLlama:masterfrom
mystic-finance:new-flare-vaults
Open

add new flare vaults to yield page#2437
agbanusi wants to merge 6 commits intoDefiLlama:masterfrom
mystic-finance:new-flare-vaults

Conversation

@agbanusi
Copy link

@agbanusi agbanusi commented Mar 2, 2026

Summary by CodeRabbit

  • New Features
    • Adds Mystic Finance vault data aggregation for the Flare chain.
    • Displays APY (base and optional rewards) and TVL (USD) per vault.
    • Shows underlying token details and normalized token-based TVL.
    • Provides per-vault performance metrics and direct links to each vault on the Mystic Finance app.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new Mystic Finance adaptor for the FLARE chain (src/adaptors/mystic-finance/index.js) that defines three ERC4626 vaults and implements async apy(timestamp) to fetch vault info and token prices, compute per-vault tvlUsd, and return standardized vault metric objects; exports timetravel, apy, and url.

Changes

Cohort / File(s) Summary
Mystic Finance Adaptor
src/adaptors/mystic-finance/index.js
New file adding VAULTS and an apy(timestamp) implementation that concurrently queries ERC4626 vault info (getERC4626Info) and token prices (getPrices), optionally augments APY data via getData, computes per-vault tvlUsd (using decimals and prices), assembles metric objects, and exports timetravel: false, apy, and url.

Sequence Diagram(s)

sequenceDiagram
participant Caller
participant Adaptor
participant ERC4626 as ERC4626 Provider
participant PriceAPI as Price Provider
participant External as External API

Caller->>Adaptor: call apy(timestamp)
Adaptor->>ERC4626: getERC4626Info(vaults) (concurrent)
Adaptor->>PriceAPI: getPrices(underlyingTokens)
Adaptor->>External: getData(optional vault/APY info)
ERC4626-->>Adaptor: vault info (tvl, decimals, symbol)
PriceAPI-->>Adaptor: token prices
External-->>Adaptor: campaignApr / vaultApr (optional)
Adaptor->>Adaptor: compute tvlUsd, apyBase, apyReward, build metrics
Adaptor-->>Caller: return array of vault metric objects
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰✨ I hopped to Flare with numbers to share,
Three vaults in line, their balances fair.
I fetched prices and sums with a twitch of my paw,
TVL and APY, neat as the law.
Mystic hops — a rabbit's small cheer!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add new flare vaults to yield page' directly and accurately describes the main change in the PR: adding a new Mystic Finance adaptor for Flare network vaults.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/adaptors/mystic-finance/index.js (1)

29-33: Consider partial-failure handling for vault fetches.

Using Promise.all means one failing vault request drops the entire adaptor response. Promise.allSettled would preserve healthy vaults and improve resilience.

Resilience-oriented refactor
-  const vaultInfos = await Promise.all(
+  const vaultInfos = await Promise.allSettled(
     VAULTS.map((vault) =>
       getERC4626Info(vault.address, CHAIN, timestamp)
     )
   );
...
-  return VAULTS.map((vault, i) => {
-    const { tvl, apyBase } = vaultInfos[i];
+  return VAULTS.flatMap((vault, i) => {
+    if (vaultInfos[i].status !== 'fulfilled') return [];
+    const { tvl, apyBase } = vaultInfos[i].value;
     ...
-    return {
+    return [{
       ...
-    };
+    }];
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 29 - 33, The current use
of Promise.all when building vaultInfos with VAULTS.map(... getERC4626Info(...))
causes a single failing getERC4626Info call to reject the whole operation;
replace Promise.all with Promise.allSettled to collect per-vault results, then
filter the settled results for status === "fulfilled" and map to their .value to
build vaultInfos (optionally log or handle rejected entries), keeping the same
inputs (VAULTS, getERC4626Info, CHAIN, timestamp) and downstream consumers
unchanged.
🤖 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/mystic-finance/index.js`:
- Around line 42-46: tvl is used in arithmetic without normalizing its type
which risks precision loss; convert the raw tvl (from vaultInfos[i] /
sdk.api.abi.call().output) to a BigNumber/number-safe representation before
dividing by 10 ** vault.decimals and computing tokenAmount/ tvlUsd. Locate where
tvl is read (variable tvl from vaultInfos[i]) and replace the implicit division
with a normalized value (e.g., parse/BigNumber conversion) so tokenAmount =
normalizedTvl.dividedBy(10 ** vault.decimals) (or equivalent) and then compute
price and tvlUsd using that normalizedTvl to avoid JS precision issues.

---

Nitpick comments:
In `@src/adaptors/mystic-finance/index.js`:
- Around line 29-33: The current use of Promise.all when building vaultInfos
with VAULTS.map(... getERC4626Info(...)) causes a single failing getERC4626Info
call to reject the whole operation; replace Promise.all with Promise.allSettled
to collect per-vault results, then filter the settled results for status ===
"fulfilled" and map to their .value to build vaultInfos (optionally log or
handle rejected entries), keeping the same inputs (VAULTS, getERC4626Info,
CHAIN, timestamp) and downstream consumers unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b86e5e and 200bb3c.

📒 Files selected for processing (1)
  • src/adaptors/mystic-finance/index.js

Comment on lines +42 to +46
const { tvl, apyBase } = vaultInfos[i];
const tokenAmount = tvl / 10 ** vault.decimals;
const price =
pricesByAddress[vault.underlyingToken.toLowerCase()] || 0;
const tvlUsd = tokenAmount * price;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, verify the file exists and examine the specific lines
find . -name "index.js" -path "*/mystic-finance/*" | head -20

Repository: DefiLlama/yield-server

Length of output: 104


🏁 Script executed:

# Search for getERC4626Info to understand what it returns
rg -n "getERC4626Info" --type js -A 5 -B 2

Repository: DefiLlama/yield-server

Length of output: 12732


🏁 Script executed:

# Check the vaultInfos structure and tvl usage in mystic-finance adapter
rg -n "vaultInfos|tvl" "src/adaptors/mystic-finance/" --type js -C 3

Repository: DefiLlama/yield-server

Length of output: 1868


🏁 Script executed:

# Compare TVL normalization patterns across adapters
rg -n "Number\(" "src/adaptors/" --type js | grep -i "tvl\|liquidity\|amount" | head -20

Repository: DefiLlama/yield-server

Length of output: 1893


🏁 Script executed:

# Read getERC4626Info implementation from utils.js
sed -n '470,550p' src/adaptors/utils.js

Repository: DefiLlama/yield-server

Length of output: 2036


🏁 Script executed:

# Check what getERC4626Info returns by looking at the complete function
rg -n "exports.getERC4626Info" -A 80 src/adaptors/utils.js | head -100

Repository: DefiLlama/yield-server

Length of output: 2360


🏁 Script executed:

# Check frax adapter's usage of tvl after getERC4626Info
sed -n '23,36p' src/adaptors/frax/index.js

Repository: DefiLlama/yield-server

Length of output: 465


🏁 Script executed:

# Check 40-acres adapter's usage of tvl
sed -n '5,20p' src/adaptors/40-acres/index.js

Repository: DefiLlama/yield-server

Length of output: 578


🏁 Script executed:

# Look for how sdk.api.abi.call output is typically used in other adapters
rg -n "\.output\s*/" src/adaptors --type js | head -15

Repository: DefiLlama/yield-server

Length of output: 1303


🏁 Script executed:

# Check if defillama SDK types reveal what abi.call returns
find . -name "*.ts" -o -name "*.d.ts" | xargs grep -l "api.abi.call" 2>/dev/null | head -5

Repository: DefiLlama/yield-server

Length of output: 237


🏁 Script executed:

# Check one of the TypeScript files to see how output is typed
sed -n '1,50p' src/adaptors/abracadabra-spell/common.ts | head -40

Repository: DefiLlama/yield-server

Length of output: 1308


🏁 Script executed:

# Search for the defillama SDK import and see if there are any type hints
rg -n "sdk.api.abi.call" -B 2 -A 10 src/adaptors/altura/index.js | head -30

Repository: DefiLlama/yield-server

Length of output: 48


🏁 Script executed:

# Check if there's any error handling around tvl usage in adapters
rg -n "tvl.*NaN|isFinite.*tvl|Number.*tvl" src/adaptors --type js

Repository: DefiLlama/yield-server

Length of output: 14458


🏁 Script executed:

# Look at pok-vault which explicitly uses Number(ethers.utils.formatEther(tvl))
# to understand why it needs this conversion
cat -n src/adaptors/pok-vault/index.js

Repository: DefiLlama/yield-server

Length of output: 777


🏁 Script executed:

# Look for documentation or test files about sdk.api.abi.call return type
rg -n "output.*string|output.*number|output.*BigInt" src/adaptors --type js -A 2 | head -30

Repository: DefiLlama/yield-server

Length of output: 46156


🏁 Script executed:

# Check if mystic-finance adapter has any tests or error handling
find . -name "*mystic*" -type f | head -10

Repository: DefiLlama/yield-server

Length of output: 48


🏁 Script executed:

# Look at umami-finance which explicitly does Number(tvlRaw) / 10 ** vault.decimals
sed -n '70,80p' src/adaptors/umami-finance/umamiGmSynthVaults.js

Repository: DefiLlama/yield-server

Length of output: 376


Normalize tvl to a number before division to avoid precision loss and align with existing patterns.

Line 43 performs arithmetic on tvl without explicit conversion. While JavaScript's implicit type coercion allows this to work, tvl comes from sdk.api.abi.call().output (returning blockchain data) and may be a string or large number representation. Direct division can silently lose precision for very large values exceeding JavaScript's safe integer limit (2^53). Similar adapters like umami-finance normalize this value explicitly.

Proposed fix
-    const { tvl, apyBase } = vaultInfos[i];
-    const tokenAmount = tvl / 10 ** vault.decimals;
+    const { tvl, apyBase } = vaultInfos[i];
+    const tokenAmount = Number(tvl) / 10 ** vault.decimals;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { tvl, apyBase } = vaultInfos[i];
const tokenAmount = tvl / 10 ** vault.decimals;
const price =
pricesByAddress[vault.underlyingToken.toLowerCase()] || 0;
const tvlUsd = tokenAmount * price;
const { tvl, apyBase } = vaultInfos[i];
const tokenAmount = Number(tvl) / 10 ** vault.decimals;
const price =
pricesByAddress[vault.underlyingToken.toLowerCase()] || 0;
const tvlUsd = tokenAmount * price;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 42 - 46, tvl is used in
arithmetic without normalizing its type which risks precision loss; convert the
raw tvl (from vaultInfos[i] / sdk.api.abi.call().output) to a
BigNumber/number-safe representation before dividing by 10 ** vault.decimals and
computing tokenAmount/ tvlUsd. Locate where tvl is read (variable tvl from
vaultInfos[i]) and replace the implicit division with a normalized value (e.g.,
parse/BigNumber conversion) so tokenAmount = normalizedTvl.dividedBy(10 **
vault.decimals) (or equivalent) and then compute price and tvlUsd using that
normalizedTvl to avoid JS precision issues.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/adaptors/mystic-finance/index.js (1)

56-56: Replace magic chainId=14 with a named constant.

Hardcoding the chain id in the URL makes future edits easy to miss. Prefer a shared constant beside CHAIN.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` at line 56, Replace the magic number 14
in the URL template with a named constant defined alongside the existing CHAIN
exports; add a constant like MYSTIC_FINANCE_CHAIN_ID (or CHAIN.MYSTIC_FINANCE)
near CHAIN and then change the URL construction from `chainId=14` to
`chainId=${MYSTIC_FINANCE_CHAIN_ID}` (or `chainId=${CHAIN.MYSTIC_FINANCE}`)
where the URL is built using `vault.address` so the chain id is referenced by
name rather than a hardcoded literal.
🤖 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/mystic-finance/index.js`:
- Around line 29-33: The current Promise.all call that builds vaultInfos
(VAULTS.map(... getERC4626Info ...)) will reject the whole apy() flow if any
single RPC fails; replace Promise.all with Promise.allSettled for the VAULTS ->
getERC4626Info batch, then process the settled results by keeping only entries
with status === "fulfilled" (use result.value) and skip rejected ones
(optionally log errors), e.g., compute vaultInfos from the settled array using
.flatMap/.filter+map so downstream code receives only successful ERC4626 info
objects while individual vault RPC failures do not break the entire apy() call.

---

Nitpick comments:
In `@src/adaptors/mystic-finance/index.js`:
- Line 56: Replace the magic number 14 in the URL template with a named constant
defined alongside the existing CHAIN exports; add a constant like
MYSTIC_FINANCE_CHAIN_ID (or CHAIN.MYSTIC_FINANCE) near CHAIN and then change the
URL construction from `chainId=14` to `chainId=${MYSTIC_FINANCE_CHAIN_ID}` (or
`chainId=${CHAIN.MYSTIC_FINANCE}`) where the URL is built using `vault.address`
so the chain id is referenced by name rather than a hardcoded literal.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 200bb3c and 8af222b.

📒 Files selected for processing (1)
  • src/adaptors/mystic-finance/index.js

Comment on lines +29 to +33
const vaultInfos = await Promise.all(
VAULTS.map((vault) =>
getERC4626Info(vault.address, CHAIN, timestamp)
)
);
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "index.js" -path "*/mystic-finance/*" | head -20

Repository: DefiLlama/yield-server

Length of output: 104


🏁 Script executed:

cat -n ./src/adaptors/mystic-finance/index.js

Repository: DefiLlama/yield-server

Length of output: 2261


Use Promise.allSettled() to prevent single vault RPC failures from blocking the entire adaptor.

The current Promise.all pattern fails fast—if any vault's RPC call fails, the entire apy() function rejects and no vaults report data. This makes the adaptor completely unavailable if a single vault experiences transient RPC issues.

Replace Promise.all with Promise.allSettled to handle individual vault failures gracefully, and use .flatMap() to skip failed results:

Proposed resilient fetch pattern
 const apy = async (timestamp) => {
-  const vaultInfos = await Promise.all(
-    VAULTS.map((vault) =>
-      getERC4626Info(vault.address, CHAIN, timestamp)
-    )
-  );
-
-  // Fetch underlying token prices
   const priceKeys = VAULTS.map(
     (vault) => vault.underlyingToken
   );
-  const { pricesByAddress } = await getPrices(priceKeys, CHAIN);
+  const [vaultInfoResults, { pricesByAddress }] = await Promise.all([
+    Promise.allSettled(
+      VAULTS.map((vault) => getERC4626Info(vault.address, CHAIN, timestamp))
+    ),
+    getPrices(priceKeys, CHAIN),
+  ]);
 
-  return VAULTS.map((vault, i) => {
-    const { tvl, apyBase } = vaultInfos[i];
+  return VAULTS.flatMap((vault, i) => {
+    const result = vaultInfoResults[i];
+    if (result.status !== 'fulfilled') return [];
+    const { tvl, apyBase } = result.value;
     const tokenAmount = tvl / 10 ** vault.decimals;
     const price =
       pricesByAddress[vault.underlyingToken.toLowerCase()] || 0;
     const tvlUsd = tokenAmount * price;
 
-    return {
+    return [{
       pool: `${vault.address}-${CHAIN}`,
       chain: formatChain(CHAIN),
       project: PROJECT_NAME,
       symbol: vault.symbol,
       tvlUsd,
       apyBase,
       underlyingTokens: [vault.underlyingToken],
       url: `https://app.mysticfinance.xyz/vault?vaultAddress=${vault.address}&chainId=14`,
-    };
+    }];
   });
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 29 - 33, The current
Promise.all call that builds vaultInfos (VAULTS.map(... getERC4626Info ...))
will reject the whole apy() flow if any single RPC fails; replace Promise.all
with Promise.allSettled for the VAULTS -> getERC4626Info batch, then process the
settled results by keeping only entries with status === "fulfilled" (use
result.value) and skip rejected ones (optionally log errors), e.g., compute
vaultInfos from the settled array using .flatMap/.filter+map so downstream code
receives only successful ERC4626 info objects while individual vault RPC
failures do not break the entire apy() call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implement this pls @agbanusi

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/adaptors/mystic-finance/index.js (1)

29-40: ⚠️ Potential issue | 🟠 Major

Make vault RPC fetching resilient to partial failures.

A single getERC4626Info rejection currently fails the full adaptor response. Prefer Promise.allSettled for vault calls and skip failed vaults so healthy pools still report.

Proposed resilient + parallel fetch update
 const apy = async (timestamp) => {
-  const vaultInfos = await Promise.all(
-    VAULTS.map((vault) =>
-      getERC4626Info(vault.address, CHAIN, timestamp)
-    )
-  );
-
-  // Fetch underlying token prices
   const priceKeys = VAULTS.map(
     (vault) => vault.underlyingToken
   );
-  const { pricesByAddress } = await getPrices(priceKeys, CHAIN);
+  const [vaultInfoResults, { pricesByAddress }] = await Promise.all([
+    Promise.allSettled(
+      VAULTS.map((vault) =>
+        getERC4626Info(vault.address, CHAIN, timestamp)
+      )
+    ),
+    getPrices(priceKeys, CHAIN),
+  ]);
 
-  return VAULTS.map((vault, i) => {
-    const { tvl, apyBase } = vaultInfos[i];
+  return VAULTS.flatMap((vault, i) => {
+    const result = vaultInfoResults[i];
+    if (result.status !== 'fulfilled') return [];
+    const { tvl, apyBase } = result.value;
     const tokenAmount = tvl / 10 ** vault.decimals;
     const price =
       pricesByAddress[vault.underlyingToken.toLowerCase()] || 0;
     const tvlUsd = tokenAmount * price;
 
-    return {
+    return [{
       pool: `${vault.address}-${CHAIN}`,
       chain: formatChain(CHAIN),
       project: PROJECT_NAME,
       symbol: vault.symbol,
       tvlUsd,
       apyBase,
       underlyingTokens: [vault.underlyingToken],
       url: `https://app.mysticfinance.xyz/vault?vaultAddress=${vault.address}&chainId=14`,
-    };
+    }];
   });
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 29 - 40, Replace the
Promise.all call for getERC4626Info with Promise.allSettled over VAULTS.map(v =>
getERC4626Info(v.address, CHAIN, timestamp)), then filter the settled results
for those with status === "fulfilled" and extract result.value into vaultInfos,
logging or recording any rejections; next compute priceKeys from the filtered
vaults (use the corresponding VAULTS entries or the returned vaultInfos'
underlyingToken) and call getPrices only for those keys so a single failing
getERC4626Info does not abort the whole adapter (ensure code paths that consume
vaultInfos handle the reduced set and handle the case of zero successful
vaults).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/adaptors/mystic-finance/index.js`:
- Around line 29-40: Replace the Promise.all call for getERC4626Info with
Promise.allSettled over VAULTS.map(v => getERC4626Info(v.address, CHAIN,
timestamp)), then filter the settled results for those with status ===
"fulfilled" and extract result.value into vaultInfos, logging or recording any
rejections; next compute priceKeys from the filtered vaults (use the
corresponding VAULTS entries or the returned vaultInfos' underlyingToken) and
call getPrices only for those keys so a single failing getERC4626Info does not
abort the whole adapter (ensure code paths that consume vaultInfos handle the
reduced set and handle the case of zero successful vaults).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8af222b and d384ce3.

📒 Files selected for processing (1)
  • src/adaptors/mystic-finance/index.js

@llamatester
Copy link

Error while running mystic-finance adapter:

Test Suites: 1 failed, 1 total
Tests: 1 failed, 21 passed, 22 total
Snapshots: 0 total
Time: 0.271 s
Ran all test suites.

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬──────────────────┬─────────────┬────────────────────┬─────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                               │ chain   │ project          │ symbol      │ tvlUsd             │ apyBase │ underlyingTokens                                 │ url                                                                                                      │
├─────────┼────────────────────────────────────────────────────┼─────────┼──────────────────┼─────────────┼────────────────────┼─────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1-flare' │ 'Flare' │ 'mystic-finance' │ 'COREUSDT0' │ 12214957.941319717 │ 0       │ [ '0xe7cd86e13AC4309349F30B3435a9d337750fC82D' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1&chainId=14' │
│ 1       │ '0x53184adabf312b490bf1ebcfdc896feff6019a14-flare' │ 'Flare' │ 'mystic-finance' │ 'CSXRP'     │ 4423713.858584706  │ 0       │ [ '0xAd552A648C74D49E10027AB8a618A3ad4901c5bE' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x53184adabf312b490bf1ebcfdc896feff6019a14&chainId=14' │
│ 2       │ '0x1aeada3c251215f1294720b80fcb3d1d005f3585-flare' │ 'Flare' │ 'mystic-finance' │ 'COREWFLR'  │ 556580.2040940927  │ 0       │ [ '0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x1aeada3c251215f1294720b80fcb3d1d005f3585&chainId=14' │
└─────────┴────────────────────────────────────────────────────┴─────────┴──────────────────┴─────────────┴────────────────────┴─────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/adaptors/mystic-finance/index.js (1)

1-2: Remove unused sdk import.

The @defillama/sdk is imported but never used in this file. The actual SDK usage is encapsulated within the getERC4626Info utility function.

Proposed fix
-const sdk = require('@defillama/sdk');
 const { formatChain, getERC4626Info, getPrices } = require('../utils');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 1 - 2, Remove the unused
import of the DefiLlama SDK from this module: delete the line that declares
"const sdk = require('@defillama/sdk');" since sdk is not referenced in this
file and SDK functionality is provided by the existing utility "getERC4626Info"
(and other imports like "formatChain" and "getPrices")—ensure only the necessary
imports remain at the top of the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/adaptors/mystic-finance/index.js`:
- Around line 1-2: Remove the unused import of the DefiLlama SDK from this
module: delete the line that declares "const sdk = require('@defillama/sdk');"
since sdk is not referenced in this file and SDK functionality is provided by
the existing utility "getERC4626Info" (and other imports like "formatChain" and
"getPrices")—ensure only the necessary imports remain at the top of the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b92c3e4c-bd77-45b3-8e4a-b5eb8b95030d

📥 Commits

Reviewing files that changed from the base of the PR and between d384ce3 and 116b51b.

📒 Files selected for processing (1)
  • src/adaptors/mystic-finance/index.js

@llamatester
Copy link

Error while running mystic-finance adapter:

Test Suites: 1 failed, 1 total
Tests: 4 failed, 18 passed, 22 total
Snapshots: 0 total
Time: 0.28 s
Ran all test suites.

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬──────────────────────────┬─────────────┬────────────────────┬────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┐
│ (index) │ pool                                               │ chain   │ project                  │ symbol      │ tvlUsd             │ apyBase                │ underlyingTokens                                 │ url                                                                                                      │ apyReward          │
├─────────┼────────────────────────────────────────────────────┼─────────┼──────────────────────────┼─────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┤
│ 0       │ '0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'COREUSDT0' │ 12177700.005295645 │ 4.3788229556900085     │ [ '0xe7cd86e13AC4309349F30B3435a9d337750fC82D' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1&chainId=14' │ 10.776682424111627 │
│ 1       │ '0x53184adabf312b490bf1ebcfdc896feff6019a14-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'CSXRP'     │ 4414880.728623866  │ 0.00019954933527591904 │ [ '0xAd552A648C74D49E10027AB8a618A3ad4901c5bE' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x53184adabf312b490bf1ebcfdc896feff6019a14&chainId=14' │ 1.5017826829690484 │
│ 2       │ '0x1aeada3c251215f1294720b80fcb3d1d005f3585-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'COREWFLR'  │ 555716.4495576153  │ 0.003364863991911875   │ [ '0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x1aeada3c251215f1294720b80fcb3d1d005f3585&chainId=14' │ 14.817860436585088 │
└─────────┴────────────────────────────────────────────────────┴─────────┴──────────────────────────┴─────────────┴────────────────────┴────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┘

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/adaptors/mystic-finance/index.js (1)

29-33: ⚠️ Potential issue | 🟠 Major

Avoid fail-fast batching for vault RPCs.

One transient getERC4626Info() failure still rejects the whole adaptor, so all three pools disappear instead of only the failed vault. Promise.allSettled() is safer here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 29 - 33, Replace the
fail-fast Promise.all call that gathers ERC4626 data so a single failing vault
doesn’t reject the entire batch: use Promise.allSettled on VAULTS.map(...)
calling getERC4626Info(vault.address, CHAIN, timestamp), then filter settled
results to keep only those with status "fulfilled" (extracting .value into
vaultInfos) and log or record any rejected entries (from .reason) so only the
failed vault is skipped and the rest of the adaptor continues to operate.
🤖 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/mystic-finance/index.js`:
- Around line 43-48: The call to getData(...) returns undefined because getData
(in src/adaptors/utils.js) calls axios.get(...) without awaiting or returning
the response body, so the morpho vaults (vaultsApiData) never get populated; fix
getData by awaiting axios.get(...) and returning the parsed response data (e.g.,
response.data) so callers like the getData('https://api.mysticfinance...') in
this file receive the API payload and allow downstream logic (vaultsApiData
population, reward APR and vaultApr override) to run correctly.
- Around line 57-59: The current assignment for apyReward and vaultApr uses
truthy checks that drop valid zero values (apiVault.campaignApr or
apiVault.vaultApr === 0); update the logic in the block that reads vaultsApiData
and sets apiVault, apyReward and vaultApr so it treats 0 as a valid value by
checking explicitly for null/undefined (e.g., test apiVault !== null/undefined
and apiVault.campaignApr !== null/undefined) rather than relying on truthiness;
ensure apyReward and vaultApr pick the API numeric value when present (including
0) and only fall back to null/fallback when truly missing.

---

Duplicate comments:
In `@src/adaptors/mystic-finance/index.js`:
- Around line 29-33: Replace the fail-fast Promise.all call that gathers ERC4626
data so a single failing vault doesn’t reject the entire batch: use
Promise.allSettled on VAULTS.map(...) calling getERC4626Info(vault.address,
CHAIN, timestamp), then filter settled results to keep only those with status
"fulfilled" (extracting .value into vaultInfos) and log or record any rejected
entries (from .reason) so only the failed vault is skipped and the rest of the
adaptor continues to operate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e08f1f7d-6679-4d15-b519-17e167d31416

📥 Commits

Reviewing files that changed from the base of the PR and between 116b51b and befb8cd.

📒 Files selected for processing (1)
  • src/adaptors/mystic-finance/index.js

Comment on lines +43 to +48
try {
const apiData = await getData('https://api.mysticfinance.xyz/morphoCache/lite?chainId=14');
if (apiData && apiData.vaults) {
vaultsApiData = apiData.vaults;
}
} catch{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

This API fetch never populates APR data with the current helper.

getData()'s GET path in src/adaptors/utils.js:67-75 does not await axios.get(), so this call resolves to undefined and vaultsApiData stays empty. As written, the reward APR and vaultApr override path below never executes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 43 - 48, The call to
getData(...) returns undefined because getData (in src/adaptors/utils.js) calls
axios.get(...) without awaiting or returning the response body, so the morpho
vaults (vaultsApiData) never get populated; fix getData by awaiting
axios.get(...) and returning the parsed response data (e.g., response.data) so
callers like the getData('https://api.mysticfinance...') in this file receive
the API payload and allow downstream logic (vaultsApiData population, reward APR
and vaultApr override) to run correctly.

Comment on lines +57 to +59
const apiVault = vaultsApiData.find(v => v.vaultAddress.toLowerCase() === vault.address.toLowerCase());
const apyReward = apiVault && apiVault.campaignApr ? apiVault.campaignApr : null;
const vaultApr = apiVault && apiVault.vaultApr ? apiVault.vaultApr : null;
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve zero APRs from the API.

These truthy checks treat 0 as “missing”. If Mystic returns campaignApr: 0 or vaultApr: 0, the adapter drops the reward APR and keeps the fallback ERC4626 APY instead of the API value.

Proposed fix
-    const apiVault = vaultsApiData.find(v => v.vaultAddress.toLowerCase() === vault.address.toLowerCase());
-    const apyReward = apiVault && apiVault.campaignApr ? apiVault.campaignApr : null;
-    const vaultApr = apiVault && apiVault.vaultApr ? apiVault.vaultApr : null;
+    const apiVault = vaultsApiData.find(
+      (v) => v.vaultAddress.toLowerCase() === vault.address.toLowerCase()
+    );
+    const apyReward = apiVault?.campaignApr ?? null;
+    const vaultApr = apiVault?.vaultApr ?? null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const apiVault = vaultsApiData.find(v => v.vaultAddress.toLowerCase() === vault.address.toLowerCase());
const apyReward = apiVault && apiVault.campaignApr ? apiVault.campaignApr : null;
const vaultApr = apiVault && apiVault.vaultApr ? apiVault.vaultApr : null;
const apiVault = vaultsApiData.find(
(v) => v.vaultAddress.toLowerCase() === vault.address.toLowerCase()
);
const apyReward = apiVault?.campaignApr ?? null;
const vaultApr = apiVault?.vaultApr ?? null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/adaptors/mystic-finance/index.js` around lines 57 - 59, The current
assignment for apyReward and vaultApr uses truthy checks that drop valid zero
values (apiVault.campaignApr or apiVault.vaultApr === 0); update the logic in
the block that reads vaultsApiData and sets apiVault, apyReward and vaultApr so
it treats 0 as a valid value by checking explicitly for null/undefined (e.g.,
test apiVault !== null/undefined and apiVault.campaignApr !== null/undefined)
rather than relying on truthiness; ensure apyReward and vaultApr pick the API
numeric value when present (including 0) and only fall back to null/fallback
when truly missing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls implement this fix for vaultApr and apyReward @agbanusi

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@llamatester
Copy link

The mystic-finance-lending adapter exports pools:

Test Suites: 1 passed, 1 total
Tests: 25 passed, 25 total
Snapshots: 0 total
Time: 0.269 s
Ran all test suites.

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬──────────────────────────┬─────────────┬────────────────────┬────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                               │ chain   │ project                  │ symbol      │ tvlUsd             │ apyBase                │ underlyingTokens                                 │ url                                                                                                      │ apyReward          │ rewardTokens                                     │
├─────────┼────────────────────────────────────────────────────┼─────────┼──────────────────────────┼─────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'COREUSDT0' │ 12403583.614093719 │ 4.487870100240151      │ [ '0xe7cd86e13AC4309349F30B3435a9d337750fC82D' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0xe8dd6a1e13244a27bdaa19ccbf33013647c675d1&chainId=14' │ 10.575365228584333 │ [ '0x12e605bc104e93B45e1aD99F9e555f659051c2BB' ] │
│ 1       │ '0x53184adabf312b490bf1ebcfdc896feff6019a14-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'CSXRP'     │ 4414880.728623866  │ 0.00019954933527591904 │ [ '0xAd552A648C74D49E10027AB8a618A3ad4901c5bE' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x53184adabf312b490bf1ebcfdc896feff6019a14&chainId=14' │ 1.500802027401658  │ [ '0x12e605bc104e93B45e1aD99F9e555f659051c2BB' ] │
│ 2       │ '0x1aeada3c251215f1294720b80fcb3d1d005f3585-flare' │ 'Flare' │ 'mystic-finance-lending' │ 'COREWFLR'  │ 555716.4495576153  │ 0.003364863991911875   │ [ '0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d' ] │ 'https://app.mysticfinance.xyz/vault?vaultAddress=0x1aeada3c251215f1294720b80fcb3d1d005f3585&chainId=14' │ 14.821761156673693 │ [ '0x12e605bc104e93B45e1aD99F9e555f659051c2BB' ] │
└─────────┴────────────────────────────────────────────────────┴─────────┴──────────────────────────┴─────────────┴────────────────────┴────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────────────────────────────────────┘

}

if (vaultApr !== null) {
poolData.apyBase = vaultApr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this overwrites the on chain apyBase, we should use onchain figure

@@ -0,0 +1,89 @@
const sdk = require('@defillama/sdk');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove if not used

Copy link
Contributor

@0xkr3p 0xkr3p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @agbanusi thanks for the PR just some minor comments and pls fix code rabbit issues!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants