Skip to content

Add SparkDEX V4 adaptor (Flare)#2472

Open
0xNx wants to merge 5 commits intoDefiLlama:masterfrom
SparkDEX:sparkdex-v4-adapter
Open

Add SparkDEX V4 adaptor (Flare)#2472
0xNx wants to merge 5 commits intoDefiLlama:masterfrom
SparkDEX:sparkdex-v4-adapter

Conversation

@0xNx
Copy link
Contributor

@0xNx 0xNx commented Mar 11, 2026

Add SparkDEX V4 adaptor (Flare)

Summary

Adds an adaptor for SparkDEX V4 on Flare (chainId 14). SparkDEX V4 is powered by Algebra Integral v1.2.2 and exposes pool and vault (Steer, Ichi, etc.) APRs via a public API.

Protocol / chain

Data source

  • API: https://api.sparkdex.ai/dex/v4/pools?chainId=14&dex=SparkDEX
  • Data is consumed from the protocol’s public API (pool list, TVL, fee APR, reward APR by type). No on-chain or subgraph calls in this adaptor.

Implementation notes

  1. Pool vs vault APR
    The API returns pools with optional vaults (e.g. Steer, Ichi). For each pool we take the highest APR among the native pool and all its vaults, and use that source’s aprs breakdown for base and reward.

  2. APR types
    The API provides aprs[] with a type field. We map them as:

    • 0 (FEE) → base APY
    • 1 (RFLR) → reward APY, scaled by 50% (early exit penalty, aligned with sparkdex-v3.1)
    • 2–7 (DINERO, PICO, BUGO, SPRK, DELEGATION, CUSDX) → reward APY at 100%
  3. Output
    Each pool is emitted with pool, symbol, project: 'sparkdex-v4', chain: 'flare', tvlUsd, apyBase, underlyingTokens, and when applicable apyReward and rewardTokens: [rFLR].

Testing

From the repo root or from src/adaptors:

cd src/adaptors
npm_config_adapter=sparkdex-v4 npm run test

Or from project root:

npm_config_adapter=sparkdex-v4 npm run test --prefix src/adaptors

All tests (allowed fields, unique pool ids, protocol slug, APY types, etc.) pass.

Checklist

  • New adaptor lives under src/adaptors/sparkdex-v4/
  • Uses project slug sparkdex-v4 (protocol must be listed on DefiLlama TVL)
  • Exposes apy() and url
  • Base APY from fee component; reward APY from incentive types with RFLR at 50%
  • Adaptor test suite passes

Summary by CodeRabbit

  • New Features
    • Added support for SparkDEX v4 liquidity pools with real-time APY/APR calculations.
    • Computes base yields from trading fees and incorporates reward incentives (with partial weighting for a specific reward) into total APY.
    • Selects the best yield source per pool and shows APY breakdown, reward token info, TVL, and token pair details.
    • Ignores invalid/zero‑TVL pools and provides a static pool page link; no historical-rate (timetravel) support.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 11, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f39b2b8a-da2a-4488-90da-1f8f66cd2bd8

📥 Commits

Reviewing files that changed from the base of the PR and between afe4fb2 and f387c7d.

📒 Files selected for processing (1)
  • src/adaptors/sparkdex-v4/index.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/adaptors/sparkdex-v4/index.js

📝 Walkthrough

Walkthrough

Adds a new SparkDEX v4 adapter that fetches pools from V4_POOLS_API (5s timeout), filters pools with token0/token1 and TVL>0, normalizes APR sources (FEE full, RFLR 50%, other rewards full), converts APR→APY, picks best source per pool, and returns pool metadata with apyBase and optional apyReward.

Changes

Cohort / File(s) Summary
SparkDEX V4 Adapter
src/adaptors/sparkdex-v4/index.js
New adapter module. Fetches V4_POOLS_API (5s timeout), validates API shape and pools, filters out pools without token0/token1 or TVL<=0, normalizes APR sources (FEE 100%, RFLR 50%, others 100%), converts APR→APY, compares pool vs vault effective APYs to choose best source, reconstructs apyBase/apyReward and includes rewardTokens when applicable, exports apy() (async), timetravel (false), and url. Returns [] on missing API shape and skips invalid pools.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client as Client
  participant Adapter as Adapter\n(src/adaptors/sparkdex-v4)
  participant V4API as V4_POOLS_API
  Client->>Adapter: call apy()
  Adapter->>V4API: fetch pools (5s timeout)
  V4API-->>Adapter: return chains, pools, vaults
  Adapter->>Adapter: validate/filter pools (token0/token1, TVL>0)
  Adapter->>Adapter: normalize APR sources (FEE 100%, RFLR 50%, others 100%)
  Adapter->>Adapter: convert APR→APY and compute effective APYs
  Adapter->>Adapter: compare pool vs vault APYs, choose best source
  Adapter->>Adapter: build pool metadata (apyBase, apyReward?, rewardTokens?)
  Adapter-->>Client: return array of pool metadata
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble data at the break of day,
I fetch the pools and sort the play,
FEE counted whole, RFLR half a tune,
I pick the best beneath the moon,
Rewards tucked in my hopping spoon.

🚥 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 SparkDEX V4 adaptor (Flare)' is clear, specific, and directly reflects the main change - adding a new adapter module for SparkDEX V4 on the Flare blockchain.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can approve the review once all CodeRabbit's comments are resolved.

Enable the reviews.request_changes_workflow setting to automatically approve the review once all CodeRabbit's comments are resolved.

@llamatester
Copy link

The sparkdex-v4 adapter exports pools:

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

Nb of pools: 53
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬────────────────┬───────────────┬─────────┬────────────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                               │ symbol         │ project       │ chain   │ tvlUsd             │ apyBase              │ underlyingTokens                                                                               │ apyReward          │ rewardTokens                                     │
├─────────┼────────────────────────────────────────────────────┼────────────────┼───────────────┼─────────┼────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0x2a91d9296ee2fe4139b49c7071b2f29f59a9f9ae-flare' │ 'stXRP-FXRP'   │ 'sparkdex-v4' │ 'flare' │ 2355881.9573339345 │ 0.045687722179743595 │ [ '0x4c18ff3c89632c3dd62e796c0afa5c07c4c1b2b3', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 8.865730281327123  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 1       │ '0x927485d88a66253c63af9163dca5f21c25a57393-flare' │ 'FXRP-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1380460.4446634226 │ 13.255150978735841   │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 32.56253674040356  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 2       │ '0x19228319d394d871e78e428286418c5df3b9d857-flare' │ 'WFLR-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1045803.4567700725 │ 10.677477399893021   │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 51.81602164552321  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 3       │ '0x54b971682f4438ebd0c3ff4dcba67fb7e16b9de4-flare' │ 'stFLR-WFLR'   │ 'sparkdex-v4' │ 'flare' │ 692958.4462504846  │ 0.2034682769678664   │ [ '0x0988c6ba244a90c07a917ebe609eb3264be716ff', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 12.549956402760687 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 4       │ '0xdcea6d3d7ca3b67c02d2b242a9037f8afe613c27-flare' │ 'USD₮0-USDC.e' │ 'sparkdex-v4' │ 'flare' │ 583243.3762694156  │ 0.026194993769546038 │ [ '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', '0xfbda5f676cb37624f28265a144a48b0d6e87d3b6' ] │ 33.888551128035715 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 5       │ '0x9f6c46f190351275e47d7ad8d3f2c9487569211e-flare' │ 'WFLR-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 573204.1400307319  │ 3.6628097856606923   │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 21.402259827670036 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 6       │ '0x019b44755d79df3f75611c1c98a60ceba3632fc0-flare' │ 'sFLR-WFLR'    │ 'sparkdex-v4' │ 'flare' │ 510055.5958191749  │ 0.021763068651625694 │ [ '0x12e605bc104e93b45e1ad99f9e555f659051c2bb', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 22.1070317228489   │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 7       │ '0x1e806f18638e2e89ab42e94a9a619ffec203b84b-flare' │ 'WETH-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 495642.64287012344 │ 10.925128720828358   │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │                    │                                                  │
│ 8       │ '0xbfe5eafd86cf270cf0ecca07f4fd0de67ee8bcfb-flare' │ 'WETH-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 313976.0303605732  │ 12.80383081479477    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 54.54286626164377  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 9       │ '0x79af232ae7ccd460439af3515022c10f5509d9f8-flare' │ 'WETH-flrETH'  │ 'sparkdex-v4' │ 'flare' │ 235498.06089874238 │ 0.13348427794785955  │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0x26a1fab310bd080542dc864647d05985360b16a5' ] │ 19.61320002912197  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
└─────────┴────────────────────────────────────────────────────┴────────────────┴───────────────┴─────────┴────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

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

🤖 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/sparkdex-v4/index.js`:
- Around line 31-42: getBestAprSource currently compares raw pool.apr and
vault.apr but the emitted yields apply a haircut (e.g., halving RFLR) and a
reward-type mapping, so change the selection to compare the same normalized APR
values you export: compute an effectiveApr for the pool and for each vault by
calling the same APR-normalization function/logic used when emitting yields
(apply the RFLR half, and the reward-type-to-percentage mapping instead of
treating non-FEE/non-RFLR as 100%), then use those effectiveApr values in the
Math.max(...) and in the reduce(...) comparator inside getBestAprSource so the
chosen source matches post-haircut/exported APR; keep the existing type checks
(typeof v.apr === 'number' etc.) when deriving inputs.
- Around line 45-46: The apy function currently calls axios.get(V4_POOLS_API)
without a timeout which can hang; update the request to include an explicit
timeout (e.g., 5000 ms) via axios.get(url, { timeout: <ms> }) or use a shared
axios instance with a default timeout, so the call inside apy rejects on
slow/unresponsive upstreams; modify the apy function's axios.get invocation
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ab5c4cf-ebbe-45ad-ab70-338438871297

📥 Commits

Reviewing files that changed from the base of the PR and between a910f90 and c9a49e8.

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

@llamatester
Copy link

The sparkdex-v4 adapter exports pools:

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

Nb of pools: 53
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬────────────────┬───────────────┬─────────┬────────────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                               │ symbol         │ project       │ chain   │ tvlUsd             │ apyBase              │ underlyingTokens                                                                               │ apyReward          │ rewardTokens                                     │
├─────────┼────────────────────────────────────────────────────┼────────────────┼───────────────┼─────────┼────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0x2a91d9296ee2fe4139b49c7071b2f29f59a9f9ae-flare' │ 'stXRP-FXRP'   │ 'sparkdex-v4' │ 'flare' │ 2362281.733988254  │ 0.04557241949241231  │ [ '0x4c18ff3c89632c3dd62e796c0afa5c07c4c1b2b3', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 8.892084106374554  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 1       │ '0x927485d88a66253c63af9163dca5f21c25a57393-flare' │ 'FXRP-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1381948.3526290802 │ 20.653389951077884   │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 27.47148395453899  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 2       │ '0x19228319d394d871e78e428286418c5df3b9d857-flare' │ 'WFLR-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1054659.9712896876 │ 11.008738213079594   │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 50.92026150298971  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 3       │ '0x54b971682f4438ebd0c3ff4dcba67fb7e16b9de4-flare' │ 'stFLR-WFLR'   │ 'sparkdex-v4' │ 'flare' │ 694597.3465789019  │ 0.04000797913670251  │ [ '0x0988c6ba244a90c07a917ebe609eb3264be716ff', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 13.604218756585528 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 4       │ '0xdcea6d3d7ca3b67c02d2b242a9037f8afe613c27-flare' │ 'USD₮0-USDC.e' │ 'sparkdex-v4' │ 'flare' │ 583243.3720954417  │ 0.012800568860882322 │ [ '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', '0xfbda5f676cb37624f28265a144a48b0d6e87d3b6' ] │ 33.971582734494476 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 5       │ '0x9f6c46f190351275e47d7ad8d3f2c9487569211e-flare' │ 'WFLR-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 575424.3427130019  │ 4.612955331447854    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 20.537766107696132 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 6       │ '0x019b44755d79df3f75611c1c98a60ceba3632fc0-flare' │ 'sFLR-WFLR'    │ 'sparkdex-v4' │ 'flare' │ 511263.6433887799  │ 0.021437049084460646 │ [ '0x12e605bc104e93b45e1ad99f9e555f659051c2bb', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 22.007003322483776 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 7       │ '0x1e806f18638e2e89ab42e94a9a619ffec203b84b-flare' │ 'WETH-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 496904.25449790555 │ 10.925128720828358   │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │                    │                                                  │
│ 8       │ '0xbfe5eafd86cf270cf0ecca07f4fd0de67ee8bcfb-flare' │ 'WETH-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 314782.64057581767 │ 12.80383081479477    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 54.10937370066493  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 9       │ '0x79af232ae7ccd460439af3515022c10f5509d9f8-flare' │ 'WETH-flrETH'  │ 'sparkdex-v4' │ 'flare' │ 237025.73834070071 │ 0.13620499358533156  │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0x26a1fab310bd080542dc864647d05985360b16a5' ] │ 19.35565233636407  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
└─────────┴────────────────────────────────────────────────────┴────────────────┴───────────────┴─────────┴────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

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

♻️ Duplicate comments (1)
src/adaptors/sparkdex-v4/index.js (1)

42-47: ⚠️ Potential issue | 🟠 Major

Restrict reward APR aggregation to the documented 2–7 types.

Lines 42-47 and 104-109 still bucket every non-FEE/non-RFLR entry into otherRewardApr. If SparkDEX adds a new APR type, this adapter will start counting it as a 100% reward in both source selection and emitted apyReward, which breaks the mapping described in this PR.

Suggested fix
+const REWARD_APR_TYPES = new Set([
+  AprTypeId.DINERO,
+  AprTypeId.PICO,
+  AprTypeId.BUGO,
+  AprTypeId.SPRK,
+  AprTypeId.DELEGATION,
+  AprTypeId.CUSDX,
+]);
+
+const splitAprs = (aprs = []) =>
+  aprs.reduce(
+    (acc, a) => {
+      const apr = typeof a.apr === 'number' ? a.apr : 0;
+      if (a.type === AprTypeId.FEE) acc.fee += apr;
+      else if (a.type === AprTypeId.RFLR) acc.rflr += apr;
+      else if (REWARD_APR_TYPES.has(a.type)) acc.other += apr;
+      return acc;
+    },
+    { fee: 0, rflr: 0, other: 0 }
+  );
+
 function getEffectiveTotalApy(source) {
-  const aprs = source.aprs || [];
-  const feeApr = aprs
-    .filter((a) => a.type === AprTypeId.FEE)
-    .reduce((s, a) => s + (a.apr || 0), 0);
-  const rflrApr = aprs
-    .filter((a) => a.type === AprTypeId.RFLR)
-    .reduce((s, a) => s + (a.apr || 0), 0);
-  const otherRewardApr = aprs
-    .filter(
-      (a) =>
-        a.type !== AprTypeId.FEE && a.type !== AprTypeId.RFLR
-    )
-    .reduce((s, a) => s + (a.apr || 0), 0);
+  const { fee: feeApr, rflr: rflrApr, other: otherRewardApr } = splitAprs(
+    source.aprs
+  );
   const apyBase = calculateApy(feeApr);
   const rflrApy = calculateApy(rflrApr);
   const otherRewardApy = calculateApy(otherRewardApr);
@@
-      const feeApr = aprs
-        .filter((a) => a.type === AprTypeId.FEE)
-        .reduce((s, a) => s + (a.apr || 0), 0);
-      const rflrApr = aprs
-        .filter((a) => a.type === AprTypeId.RFLR)
-        .reduce((s, a) => s + (a.apr || 0), 0);
-      const otherRewardApr = aprs
-        .filter(
-          (a) =>
-            a.type !== AprTypeId.FEE && a.type !== AprTypeId.RFLR
-        )
-        .reduce((s, a) => s + (a.apr || 0), 0);
+      const { fee: feeApr, rflr: rflrApr, other: otherRewardApr } =
+        splitAprs(aprs);

Also applies to: 98-109

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

In `@src/adaptors/sparkdex-v4/index.js` around lines 42 - 47, The current
otherRewardApr aggregation (variable otherRewardApr in
src/adaptors/sparkdex-v4/index.js) filters only by excluding AprTypeId.FEE and
AprTypeId.RFLR, which will incorrectly include any future APR types; change the
filter to explicitly include only the documented reward types (the specific
AprTypeId enum values representing the 2–7 reward types used by this adapter)
before summing apr.apr, and apply the same explicit-type whitelist change to the
other identical aggregation block around the 98-109 range so only the documented
reward types contribute to otherRewardApr and emitted apyReward.
🧹 Nitpick comments (1)
src/adaptors/sparkdex-v4/index.js (1)

1-1: Prefer the shared aprToApy helper over a local copy.

src/adaptors/utils.js already exports this conversion. Reusing it here keeps compounding logic aligned with the rest of the adapters and avoids formula drift.

Suggested refactor
 const axios = require('axios');
+const { aprToApy } = require('../utils');
@@
-const calculateApy = (_apr) => {
-  const APR = _apr / 100;
-  const n = 365;
-  const APY = (1 + APR / n) ** n - 1;
-  return APY * 100;
-};
+const calculateApy = aprToApy;

Also applies to: 22-27

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

In `@src/adaptors/sparkdex-v4/index.js` at line 1, Replace the local APR→APY
conversion with the shared helper: remove the local aprToApy implementation in
src/adaptors/sparkdex-v4/index.js (the function around lines 22–27) and instead
import the aprToApy exported from src/adaptors/utils.js, then call that imported
aprToApy wherever the local function was used; ensure the require/import name
matches aprToApy and update any references to the original local function
accordingly.
🤖 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/sparkdex-v4/index.js`:
- Around line 64-67: The current vaultEffectives mapping incorrectly zeroes
vaults based on the legacy top-level v.apr; remove that gate and instead base
the check on the modern breakdown (v.aprs) or simply always call
getEffectiveTotalApy so valid breakdowns aren't ignored. Update the vaults.map
callback (vaultEffectives) to stop checking typeof v.apr and either check for a
present/usable v.aprs (or use getBestAprSource/v.getBestAprSource if available)
before returning 0, otherwise call getEffectiveTotalApy(v) to compute the
effective APY.

---

Duplicate comments:
In `@src/adaptors/sparkdex-v4/index.js`:
- Around line 42-47: The current otherRewardApr aggregation (variable
otherRewardApr in src/adaptors/sparkdex-v4/index.js) filters only by excluding
AprTypeId.FEE and AprTypeId.RFLR, which will incorrectly include any future APR
types; change the filter to explicitly include only the documented reward types
(the specific AprTypeId enum values representing the 2–7 reward types used by
this adapter) before summing apr.apr, and apply the same explicit-type whitelist
change to the other identical aggregation block around the 98-109 range so only
the documented reward types contribute to otherRewardApr and emitted apyReward.

---

Nitpick comments:
In `@src/adaptors/sparkdex-v4/index.js`:
- Line 1: Replace the local APR→APY conversion with the shared helper: remove
the local aprToApy implementation in src/adaptors/sparkdex-v4/index.js (the
function around lines 22–27) and instead import the aprToApy exported from
src/adaptors/utils.js, then call that imported aprToApy wherever the local
function was used; ensure the require/import name matches aprToApy and update
any references to the original local function accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c08868b3-fb89-4c45-a70a-f7a14c91f77e

📥 Commits

Reviewing files that changed from the base of the PR and between c9a49e8 and 2e43fad.

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

@llamatester
Copy link

The sparkdex-v4 adapter exports pools:

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

Nb of pools: 53
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬────────────────┬───────────────┬─────────┬────────────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────────────────────────────────────┐
│ (index) │ pool                                               │ symbol         │ project       │ chain   │ tvlUsd             │ apyBase              │ underlyingTokens                                                                               │ apyReward          │ rewardTokens                                     │
├─────────┼────────────────────────────────────────────────────┼────────────────┼───────────────┼─────────┼────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────────────────────────────────────┤
│ 0       │ '0x2a91d9296ee2fe4139b49c7071b2f29f59a9f9ae-flare' │ 'stXRP-FXRP'   │ 'sparkdex-v4' │ 'flare' │ 2362281.733988254  │ 0.04557241949241231  │ [ '0x4c18ff3c89632c3dd62e796c0afa5c07c4c1b2b3', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 8.892084106374554  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 1       │ '0x927485d88a66253c63af9163dca5f21c25a57393-flare' │ 'FXRP-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1381948.3526290802 │ 20.653389951077884   │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 27.47148395453899  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 2       │ '0x19228319d394d871e78e428286418c5df3b9d857-flare' │ 'WFLR-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1054659.9712896876 │ 11.008738213079594   │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 50.92026150298971  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 3       │ '0x54b971682f4438ebd0c3ff4dcba67fb7e16b9de4-flare' │ 'stFLR-WFLR'   │ 'sparkdex-v4' │ 'flare' │ 694597.3465789019  │ 0.04000797913670251  │ [ '0x0988c6ba244a90c07a917ebe609eb3264be716ff', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 13.604218756585528 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 4       │ '0xdcea6d3d7ca3b67c02d2b242a9037f8afe613c27-flare' │ 'USD₮0-USDC.e' │ 'sparkdex-v4' │ 'flare' │ 583243.3720954417  │ 0.012800568860882322 │ [ '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', '0xfbda5f676cb37624f28265a144a48b0d6e87d3b6' ] │ 33.971582734494476 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 5       │ '0x9f6c46f190351275e47d7ad8d3f2c9487569211e-flare' │ 'WFLR-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 575424.3427130019  │ 4.612955331447854    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 20.537766107696132 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 6       │ '0x019b44755d79df3f75611c1c98a60ceba3632fc0-flare' │ 'sFLR-WFLR'    │ 'sparkdex-v4' │ 'flare' │ 511263.6433887799  │ 0.021437049084460646 │ [ '0x12e605bc104e93b45e1ad99f9e555f659051c2bb', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 22.007003322483776 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 7       │ '0x1e806f18638e2e89ab42e94a9a619ffec203b84b-flare' │ 'WETH-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 496904.25449790555 │ 10.925128720828358   │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │                    │                                                  │
│ 8       │ '0xbfe5eafd86cf270cf0ecca07f4fd0de67ee8bcfb-flare' │ 'WETH-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 314782.64057581767 │ 12.80383081479477    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 54.10937370066493  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
│ 9       │ '0x79af232ae7ccd460439af3515022c10f5509d9f8-flare' │ 'WETH-flrETH'  │ 'sparkdex-v4' │ 'flare' │ 237025.73834070071 │ 0.13620499358533156  │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0x26a1fab310bd080542dc864647d05985360b16a5' ] │ 19.35565233636407  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ] │
└─────────┴────────────────────────────────────────────────────┴────────────────┴───────────────┴─────────┴────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

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 @0xNx, thanks for the PR. A couple of minor issues:

  • Can you get TVL / APY from onchain?
  • Use native APY instead of the getBestAprSource pls as this can be misleading to users
  • Add informative comment regarding 50% penalty to rFLR

1, add utils.keepFinite
2, add other rewards types
3, show only native APY
4, Add informative comment regarding rFLR APY ratio
@llamatester
Copy link

The sparkdex-v4 adapter exports pools:

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

Nb of pools: 54
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬────────────────┬───────────────┬─────────┬────────────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                               │ symbol         │ project       │ chain   │ tvlUsd             │ apyBase              │ underlyingTokens                                                                               │ apyReward          │ rewardTokens                                                                                   │
├─────────┼────────────────────────────────────────────────────┼────────────────┼───────────────┼─────────┼────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x2a91d9296ee2fe4139b49c7071b2f29f59a9f9ae-flare' │ 'stXRP-FXRP'   │ 'sparkdex-v4' │ 'flare' │ 3631548.824582199  │ 0.04450781439087059  │ [ '0x4c18ff3c89632c3dd62e796c0afa5c07c4c1b2b3', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 3.1315107945317555 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 1       │ '0x927485d88a66253c63af9163dca5f21c25a57393-flare' │ 'FXRP-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1648617.7330848856 │ 10.134155563086056   │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 18.962950002410373 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 2       │ '0x19228319d394d871e78e428286418c5df3b9d857-flare' │ 'WFLR-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1360214.8195071663 │ 6.082825263918146    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 31.956634924168355 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 3       │ '0xdcea6d3d7ca3b67c02d2b242a9037f8afe613c27-flare' │ 'USD₮0-USDC.e' │ 'sparkdex-v4' │ 'flare' │ 1237876.0965524565 │ 0.012132791584540392 │ [ '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', '0xfbda5f676cb37624f28265a144a48b0d6e87d3b6' ] │ 9.421284205252256  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 4       │ '0x54b971682f4438ebd0c3ff4dcba67fb7e16b9de4-flare' │ 'stFLR-WFLR'   │ 'sparkdex-v4' │ 'flare' │ 767043.1886232394  │ 0.13592574757435028  │ [ '0x0988c6ba244a90c07a917ebe609eb3264be716ff', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 9.445665652620683  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 5       │ '0x019b44755d79df3f75611c1c98a60ceba3632fc0-flare' │ 'sFLR-WFLR'    │ 'sparkdex-v4' │ 'flare' │ 734842.0492730717  │ 0.04925360018395164  │ [ '0x12e605bc104e93b45e1ad99f9e555f659051c2bb', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 11.34793652379933  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 6       │ '0x9f6c46f190351275e47d7ad8d3f2c9487569211e-flare' │ 'WFLR-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 638442.6554941073  │ 3.354537447327388    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 18.940411896311105 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 7       │ '0x1e806f18638e2e89ab42e94a9a619ffec203b84b-flare' │ 'WETH-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 477401.49366973806 │ 3.748801172438232    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │                    │                                                                                                │
│ 8       │ '0xbfe5eafd86cf270cf0ecca07f4fd0de67ee8bcfb-flare' │ 'WETH-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 321635.1763112632  │ 7.285352894000363    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 22.852343963146417 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 9       │ '0x79af232ae7ccd460439af3515022c10f5509d9f8-flare' │ 'WETH-flrETH'  │ 'sparkdex-v4' │ 'flare' │ 251978.41332097232 │ 0.09204088243919273  │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0x26a1fab310bd080542dc864647d05985360b16a5' ] │ 15.644368002477393 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
└─────────┴────────────────────────────────────────────────────┴────────────────┴───────────────┴─────────┴────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@0xNx
Copy link
Contributor Author

0xNx commented Mar 18, 2026

hey @0xNx, thanks for the PR. A couple of minor issues:

  • Can you get TVL / APY from onchain?
  • Use native APY instead of the getBestAprSource pls as this can be misleading to users
  • Add informative comment regarding 50% penalty to rFLR

Resolved review comments in commit: afe4fb2

1, add utils.keepFinite
2, add other rewards types
3, show only native APY
4, Add informative comment regarding rFLR APY ratio

For this comment: Can you get TVL / APY from onchain
As the rewards APY need retrieve from API, so the logic is not changed. The rewards are calculated by the SparkDEX by accumulate the position amount, holding time, in-range time for each user by a backend process, so it has to be retrieve from the API.

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/sparkdex-v4/index.js (1)

30-33: Consider consolidating the duplicated rFLR rationale comment.

The same explanation appears twice; keeping a single source-of-truth comment near RFLR_APY_RATIO reduces drift risk.

Also applies to: 79-82

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

In `@src/adaptors/sparkdex-v4/index.js` around lines 30 - 33, Consolidate the
duplicated rFLR rationale by keeping the explanatory comment only next to the
constant RFLR_APY_RATIO and removing the repeated copy elsewhere; ensure the
retained comment explains the 1*100% + 11*50% over 12 months calculation and the
resulting 13/24 ratio so future readers see the single source of truth tied to
RFLR_APY_RATIO, and delete the other instance (the comment duplicate near the
later block) to avoid drift.
🤖 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/sparkdex-v4/index.js`:
- Around line 30-33: Consolidate the duplicated rFLR rationale by keeping the
explanatory comment only next to the constant RFLR_APY_RATIO and removing the
repeated copy elsewhere; ensure the retained comment explains the 1*100% +
11*50% over 12 months calculation and the resulting 13/24 ratio so future
readers see the single source of truth tied to RFLR_APY_RATIO, and delete the
other instance (the comment duplicate near the later block) to avoid drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0676a776-fe61-43f3-aaf3-0194e0c238ec

📥 Commits

Reviewing files that changed from the base of the PR and between ba103aa and afe4fb2.

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

@llamatester
Copy link

The sparkdex-v4 adapter exports pools:

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

Nb of pools: 54
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬────────────────┬───────────────┬─────────┬────────────────────┬──────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                               │ symbol         │ project       │ chain   │ tvlUsd             │ apyBase              │ underlyingTokens                                                                               │ apyReward          │ rewardTokens                                                                                   │
├─────────┼────────────────────────────────────────────────────┼────────────────┼───────────────┼─────────┼────────────────────┼──────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x2a91d9296ee2fe4139b49c7071b2f29f59a9f9ae-flare' │ 'stXRP-FXRP'   │ 'sparkdex-v4' │ 'flare' │ 3631548.824582199  │ 0.04450781439087059  │ [ '0x4c18ff3c89632c3dd62e796c0afa5c07c4c1b2b3', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 3.1315107945317555 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 1       │ '0x927485d88a66253c63af9163dca5f21c25a57393-flare' │ 'FXRP-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1648617.7330848856 │ 10.134155563086056   │ [ '0xad552a648c74d49e10027ab8a618a3ad4901c5be', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 18.962950002410373 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 2       │ '0x19228319d394d871e78e428286418c5df3b9d857-flare' │ 'WFLR-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 1360214.8195071663 │ 6.082825263918146    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 31.956634924168355 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 3       │ '0xdcea6d3d7ca3b67c02d2b242a9037f8afe613c27-flare' │ 'USD₮0-USDC.e' │ 'sparkdex-v4' │ 'flare' │ 1237876.0965524565 │ 0.012132791584540392 │ [ '0xe7cd86e13ac4309349f30b3435a9d337750fc82d', '0xfbda5f676cb37624f28265a144a48b0d6e87d3b6' ] │ 9.421284205252256  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 4       │ '0x54b971682f4438ebd0c3ff4dcba67fb7e16b9de4-flare' │ 'stFLR-WFLR'   │ 'sparkdex-v4' │ 'flare' │ 767043.1886232394  │ 0.13592574757435028  │ [ '0x0988c6ba244a90c07a917ebe609eb3264be716ff', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 9.445665652620683  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 5       │ '0x019b44755d79df3f75611c1c98a60ceba3632fc0-flare' │ 'sFLR-WFLR'    │ 'sparkdex-v4' │ 'flare' │ 734842.0492730717  │ 0.04925360018395164  │ [ '0x12e605bc104e93b45e1ad99f9e555f659051c2bb', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │ 11.34793652379933  │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 6       │ '0x9f6c46f190351275e47d7ad8d3f2c9487569211e-flare' │ 'WFLR-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 638442.6554941073  │ 3.354537447327388    │ [ '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │ 18.940411896311105 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e', '0x1d80c49bbbcd1c0911346656b529df9e5c2f783d' ] │
│ 7       │ '0x1e806f18638e2e89ab42e94a9a619ffec203b84b-flare' │ 'WETH-FXRP'    │ 'sparkdex-v4' │ 'flare' │ 477401.49366973806 │ 3.748801172438232    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xad552a648c74d49e10027ab8a618a3ad4901c5be' ] │                    │                                                                                                │
│ 8       │ '0xbfe5eafd86cf270cf0ecca07f4fd0de67ee8bcfb-flare' │ 'WETH-USD₮0'   │ 'sparkdex-v4' │ 'flare' │ 321635.1763112632  │ 7.285352894000363    │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0xe7cd86e13ac4309349f30b3435a9d337750fc82d' ] │ 22.852343963146417 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
│ 9       │ '0x79af232ae7ccd460439af3515022c10f5509d9f8-flare' │ 'WETH-flrETH'  │ 'sparkdex-v4' │ 'flare' │ 251978.41332097232 │ 0.09204088243919273  │ [ '0x1502fa4be69d526124d453619276faccab275d3d', '0x26a1fab310bd080542dc864647d05985360b16a5' ] │ 15.644368002477393 │ [ '0x26d460c3Cf931Fb2014FA436a49e3Af08619810e' ]                                               │
└─────────┴────────────────────────────────────────────────────┴────────────────┴───────────────┴─────────┴────────────────────┴──────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@0xkr3p
Copy link
Contributor

0xkr3p commented Mar 18, 2026

hey @0xNx, thanks for the PR. A couple of minor issues:

  • Can you get TVL / APY from onchain?
  • Use native APY instead of the getBestAprSource pls as this can be misleading to users
  • Add informative comment regarding 50% penalty to rFLR

Resolved review comments in commit: afe4fb2

1, add utils.keepFinite 2, add other rewards types 3, show only native APY 4, Add informative comment regarding rFLR APY ratio

For this comment: Can you get TVL / APY from onchain As the rewards APY need retrieve from API, so the logic is not changed. The rewards are calculated by the SparkDEX by accumulate the position amount, holding time, in-range time for each user by a backend process, so it has to be retrieve from the API.

Ok so the rewards APY needs to use the API but how about TVL and Native APY, can we get those from onchain?

@0xNx
Copy link
Contributor Author

0xNx commented Mar 18, 2026

hey @0xNx, thanks for the PR. A couple of minor issues:

  • Can you get TVL / APY from onchain?
  • Use native APY instead of the getBestAprSource pls as this can be misleading to users
  • Add informative comment regarding 50% penalty to rFLR

Resolved review comments in commit: afe4fb2
1, add utils.keepFinite 2, add other rewards types 3, show only native APY 4, Add informative comment regarding rFLR APY ratio
For this comment: Can you get TVL / APY from onchain As the rewards APY need retrieve from API, so the logic is not changed. The rewards are calculated by the SparkDEX by accumulate the position amount, holding time, in-range time for each user by a backend process, so it has to be retrieve from the API.

Ok so the rewards APY needs to use the API but how about TVL and Native APY, can we get those from onchain?

Yes, both TVL and native APY (fee APY) can be obtained on-chain. TVL is straightforward, while the fee calculation is a bit less efficient, as it requires querying swap event logs from the last 24 hours.
So I would suggest TVL from onchain, APY still from the API call.

Please let me know how you think.

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