Skip to content

feat: add notional exponent#2306

Open
jeffywu wants to merge 2 commits intoDefiLlama:masterfrom
notional-finance:feat/add-notional-exponent
Open

feat: add notional exponent#2306
jeffywu wants to merge 2 commits intoDefiLlama:masterfrom
notional-finance:feat/add-notional-exponent

Conversation

@jeffywu
Copy link
Contributor

@jeffywu jeffywu commented Jan 28, 2026

Summary by CodeRabbit

  • New Features
    • Added Notional Exponent as a supported yield data source, providing APY rates and vault details across multiple blockchains.
    • Standardized vault data (symbols, tokens, URLs, TVL, base APY, rewards) for consistent display.
    • Robust error handling and input validation for more reliable data feeding.
    • Timetravel support disabled for this source; APY is provided as the primary output.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

Adds a new notional-exponent adapter module that fetches yield data from https://yields.notional.finance/fetchYields, validates and transforms vault entries into standardized adapter objects, normalizes chain names, and exports the apy function with timetravel disabled.

Changes

Cohort / File(s) Summary
New Notional-Exponent Adapter
src/adaptors/notional-exponent/index.js
New adapter that fetches yields from an external API, performs input validation and error handling, maps vault entries to standardized fields (pool, chain normalized, project, symbol, underlyingTokens, poolMeta, url, tvlUsd, apyBase, rewardTokens), and exports timetravel = false and apy = main. Reviewers should focus on fetch error handling, response schema validation, and chain normalization logic.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client/Collector
  participant Adapter as Notional-Exponent Adapter
  participant API as yields.notional.finance
  Client->>Adapter: invoke apy()
  Adapter->>API: GET /fetchYields
  API-->>Adapter: JSON payload (vaults[])
  Adapter->>Adapter: validate & transform entries
  Adapter-->>Client: standardized adapter array
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • 0xkr3p

Poem

🐰 I hopped to the yields with a curious twitch,
Fetched vaults from the web in a single stitch.
I normalized chains and tidied each line,
Packaged the data — neat, small, and fine.
Happy carrots for maps, rewards, and TVL shine! 🥕✨

🚥 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 'feat: add notional exponent' directly and clearly describes the main change - adding a new adapter for the Notional Exponent protocol.
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 docstrings

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.

@llamatester
Copy link

Error while running notional-exponent adapter:

Test Suites: 1 failed, 1 total
Tests: 1 failed, 17 passed, 18 total
Snapshots: 0 total
Time: 0.291 s
Ran all test suites.

Nb of pools: 2
 

Sample pools:
┌─────────┬──────────────────────────────────────────────────────┬────────────┬─────────────────────┬────────────────┬──────────────────────────────────────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┬───────────┬────────────────────┬──────────────┐
│ (index) │ pool                                                 │ chain      │ project             │ symbol         │ underlyingTokens                                 │ poolMeta                  │ url                                                                                 │ tvlUsd    │ apyBase            │ rewardTokens │
├─────────┼──────────────────────────────────────────────────────┼────────────┼─────────────────────┼────────────────┼──────────────────────────────────────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┼───────────┼────────────────────┼──────────────┤
│ 0       │ '0x94f6cb4fae0eb3fa74e9847dff2ff52fd5ec7e6e-mainnet' │ 'ethereum' │ 'notional-exponent' │ 'n-st-mHYPER'  │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Notional Exponent Vault' │ 'https://notional.finance/vault/mainnet/0x94f6cb4fae0eb3fa74e9847dff2ff52fd5ec7e6e' │ 33.385576 │ 13.56031448407846  │ []           │
│ 1       │ '0x091356e6793a0d960174eaab4d470e39a99dd673-mainnet' │ 'ethereum' │ 'notional-exponent' │ 'n-st-mAPOLLO' │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Notional Exponent Vault' │ 'https://notional.finance/vault/mainnet/0x091356e6793a0d960174eaab4d470e39a99dd673' │ 27.442641 │ 34.825193052681016 │ []           │
└─────────┴──────────────────────────────────────────────────────┴────────────┴─────────────────────┴────────────────┴──────────────────────────────────────────────────┴───────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┴───────────┴────────────────────┴──────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama
}

Copy link

@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

🤖 Fix all issues with AI agents
In `@src/adaptors/notional-exponent/index.js`:
- Around line 3-21: The main function should robustly handle network and data
errors: wrap the fetch/parse/map logic in a try/catch, use an AbortController to
add a timeout on the fetch call, check response.ok before calling
response.json() and throw a descriptive error if not ok, validate that the
parsed vaults is an array with Array.isArray(vaults) before calling vaults.map()
(return an empty array or throw a clear error if it’s not), and ensure any
thrown errors are surfaced or logged so callers of main receive a predictable
failure mode; update the function referenced as main, the fetch call, the
response.ok check, and the vaults.map usage accordingly.

Comment on lines 3 to 21
const main = async () => {
const response = await fetch('https://yields.notional.finance/fetchYields')
const vaults = await response.json();

return vaults.map(({vaultAddress, chain, symbol, apyBase, tvlUSD, underlying, poolMeta, rewardTokens}) => {
return {
pool: `${vaultAddress}-${chain}`,
chain: chain === 'mainnet' ? 'ethereum' : chain,
project,
symbol,
underlyingTokens: underlying,
poolMeta,
url: `https://notional.finance/vault/${chain}/${vaultAddress}`,
tvlUsd: tvlUSD,
apyBase: apyBase,
rewardTokens: rewardTokens,
};
})
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling for fetch and response validation.

The adapter lacks error handling which could cause failures:

  1. No response.ok check before parsing JSON
  2. No validation that vaults is an array before calling .map()
  3. No timeout on the fetch request
🛡️ Proposed fix with error handling
 const main = async () => {
-  const response = await fetch('https://yields.notional.finance/fetchYields')
-  const vaults = await response.json();
+  const response = await fetch('https://yields.notional.finance/fetchYields');
+  if (!response.ok) {
+    throw new Error(`Failed to fetch yields: ${response.status}`);
+  }
+  const vaults = await response.json();
+  if (!Array.isArray(vaults)) {
+    throw new Error('Invalid response: expected an array of vaults');
+  }

   return vaults.map(({vaultAddress, chain, symbol, apyBase, tvlUSD, underlying, poolMeta, rewardTokens}) => {
📝 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 main = async () => {
const response = await fetch('https://yields.notional.finance/fetchYields')
const vaults = await response.json();
return vaults.map(({vaultAddress, chain, symbol, apyBase, tvlUSD, underlying, poolMeta, rewardTokens}) => {
return {
pool: `${vaultAddress}-${chain}`,
chain: chain === 'mainnet' ? 'ethereum' : chain,
project,
symbol,
underlyingTokens: underlying,
poolMeta,
url: `https://notional.finance/vault/${chain}/${vaultAddress}`,
tvlUsd: tvlUSD,
apyBase: apyBase,
rewardTokens: rewardTokens,
};
})
};
const main = async () => {
const response = await fetch('https://yields.notional.finance/fetchYields');
if (!response.ok) {
throw new Error(`Failed to fetch yields: ${response.status}`);
}
const vaults = await response.json();
if (!Array.isArray(vaults)) {
throw new Error('Invalid response: expected an array of vaults');
}
return vaults.map(({vaultAddress, chain, symbol, apyBase, tvlUSD, underlying, poolMeta, rewardTokens}) => {
return {
pool: `${vaultAddress}-${chain}`,
chain: chain === 'mainnet' ? 'ethereum' : chain,
project,
symbol,
underlyingTokens: underlying,
poolMeta,
url: `https://notional.finance/vault/${chain}/${vaultAddress}`,
tvlUsd: tvlUSD,
apyBase: apyBase,
rewardTokens: rewardTokens,
};
})
};
🤖 Prompt for AI Agents
In `@src/adaptors/notional-exponent/index.js` around lines 3 - 21, The main
function should robustly handle network and data errors: wrap the
fetch/parse/map logic in a try/catch, use an AbortController to add a timeout on
the fetch call, check response.ok before calling response.json() and throw a
descriptive error if not ok, validate that the parsed vaults is an array with
Array.isArray(vaults) before calling vaults.map() (return an empty array or
throw a clear error if it’s not), and ensure any thrown errors are surfaced or
logged so callers of main receive a predictable failure mode; update the
function referenced as main, the fetch call, the response.ok check, and the
vaults.map usage accordingly.

@llamatester
Copy link

The notional-exponent adapter exports pools:

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

Nb of pools: 1
 

Sample pools:
┌─────────┬──────────────────────────────────────────────────────┬────────────┬─────────────────────┬────────────────┬──────────────────────────────────────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┬──────────────┬───────────────────┬──────────────┐
│ (index) │ pool                                                 │ chain      │ project             │ symbol         │ underlyingTokens                                 │ poolMeta                  │ url                                                                                 │ tvlUsd       │ apyBase           │ rewardTokens │
├─────────┼──────────────────────────────────────────────────────┼────────────┼─────────────────────┼────────────────┼──────────────────────────────────────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┼──────────────┼───────────────────┼──────────────┤
│ 0       │ '0x091356e6793a0d960174eaab4d470e39a99dd673-mainnet' │ 'ethereum' │ 'notional-exponent' │ 'n-st-mAPOLLO' │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Notional Exponent Vault' │ 'https://notional.finance/vault/mainnet/0x091356e6793a0d960174eaab4d470e39a99dd673' │ 196975.88084 │ 54.12686386984866 │ []           │
└─────────┴──────────────────────────────────────────────────────┴────────────┴─────────────────────┴────────────────┴──────────────────────────────────────────────────┴───────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┴──────────────┴───────────────────┴──────────────┘

@llamatester
Copy link

The notional-exponent adapter exports pools:

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

Nb of pools: 1
 

Sample pools:
┌─────────┬──────────────────────────────────────────────────────┬────────────┬─────────────────────┬────────────────┬──────────────────────────────────────────────────┬───────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┬───────────────┬───────────────────┬──────────────┐
│ (index) │ pool                                                 │ chain      │ project             │ symbol         │ underlyingTokens                                 │ poolMeta                  │ url                                                                                 │ tvlUsd        │ apyBase           │ rewardTokens │
├─────────┼──────────────────────────────────────────────────────┼────────────┼─────────────────────┼────────────────┼──────────────────────────────────────────────────┼───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┼───────────────┼───────────────────┼──────────────┤
│ 0       │ '0x091356e6793a0d960174eaab4d470e39a99dd673-mainnet' │ 'ethereum' │ 'notional-exponent' │ 'n-st-mAPOLLO' │ [ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' ] │ 'Notional Exponent Vault' │ 'https://notional.finance/vault/mainnet/0x091356e6793a0d960174eaab4d470e39a99dd673' │ 313200.274103 │ 36.27695470187227 │ []           │
└─────────┴──────────────────────────────────────────────────────┴────────────┴─────────────────────┴────────────────┴──────────────────────────────────────────────────┴───────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┴───────────────┴───────────────────┴──────────────┘

@slasher125
Copy link
Collaborator

hi,

  • tvl should be computed via sdk
  • as for the apy, we dont show leveraged values, so that needs to be modified too,

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