Skip to content

add JuiceSwap#2487

Open
eyusufatik wants to merge 1 commit intoDefiLlama:masterfrom
eyusufatik:add-juiceswap
Open

add JuiceSwap#2487
eyusufatik wants to merge 1 commit intoDefiLlama:masterfrom
eyusufatik:add-juiceswap

Conversation

@eyusufatik
Copy link
Contributor

@eyusufatik eyusufatik commented Mar 16, 2026

Adds JuiceSwap on Citrea.

https://juiceswap.com/#/

Summary by CodeRabbit

New Features

  • Added Juiceswap adapter delivering liquidity pool analytics and metrics. Features include Total Value Locked (TVL), Annual Percentage Yield (APY) calculations from trading volume, token metadata (symbols, decimals, USD prices), current reserve data, pool summary information, and convenient links to Juiceswap pool explorer.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

A new Juiceswap adapter implementation is introduced that queries pool data and statistics from Ponder, retrieves on-chain token information via multiCall, fetches token prices, calculates TVL and APY metrics for liquidity pools, and exports these metrics through an apy function.

Changes

Cohort / File(s) Summary
Juiceswap Adapter Implementation
src/adaptors/juiceswap/index.js
New adapter that queries pools and 24h stats via Ponder GraphQL, retrieves token symbols/decimals and pool balances via multiCall, fetches USD prices, and computes pool-level TVL and APY metrics based on 24h volume and pool fees. Exports apy() function and pool explorer URL with timetravel disabled.

Sequence Diagram

sequenceDiagram
    participant Adapter as Adapter<br/>(index.js)
    participant Ponder as Ponder<br/>GraphQL
    participant OnChain as On-Chain<br/>multiCall
    participant PriceAPI as Price<br/>Data
    participant Result as Output

    Adapter->>Ponder: Query pools & 24h stats
    Ponder-->>Adapter: Pool list + volume data
    
    Adapter->>OnChain: Fetch token symbols<br/>& decimals (erc20:*)
    OnChain-->>Adapter: Token metadata
    
    Adapter->>OnChain: Fetch pool reserves<br/>(balanceOf)
    OnChain-->>Adapter: reserve0, reserve1
    
    Adapter->>PriceAPI: Get USD prices<br/>for all tokens
    PriceAPI-->>Adapter: Token prices
    
    Adapter->>Adapter: Calculate TVL<br/>& APY metrics
    
    Adapter->>Result: Output pool data<br/>(address, TVL, APY,<br/>symbol, underlyingTokens)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A juicy new adapter hops into the fold,

Pooling data from chains, both new and old,

With TVL and APY dancing in sight,

Juiceswap's metrics now shimmer so bright! 🥤✨

🚥 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 JuiceSwap' directly reflects the main change—adding a new JuiceSwap adapter to the codebase, which aligns with the PR objective and file implementation.
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
📝 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

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

@llamatester
Copy link

The juiceswap adapter exports pools:

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

Nb of pools: 33
 

Sample pools:
┌─────────┬─────────────────────────────────────────────────────┬──────────┬─────────────┬─────────────────┬────────────────────┬───────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ pool                                                │ chain    │ project     │ symbol          │ tvlUsd             │ apyBase               │ underlyingTokens                                                                               │ url                                                                                               │
├─────────┼─────────────────────────────────────────────────────┼──────────┼─────────────┼─────────────────┼────────────────────┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0       │ '0x8f6f3457df6ae573b1cb9cb5e0942d9e31b43479-citrea' │ 'Citrea' │ 'juiceswap' │ 'WCBTC-SYBTC'   │ 435339.2174178423  │ 0.0015099262695377567 │ [ '0x3100000000000000000000000000000000000006', '0x384157027b1cdeac4e26e3709667bb28735379bb' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x8f6F3457DF6aE573B1cB9cb5E0942d9e31B43479' │
│ 1       │ '0x69ccca6988395db4ced6f7f1cbe0cc1783567c7b-citrea' │ 'Citrea' │ 'juiceswap' │ 'SVJUSD-WCBTC'  │ 187707.58492746262 │ 6.0057268388397675    │ [ '0x1b70ae756b1089cc5948e4f8a2ad498df30e897d', '0x3100000000000000000000000000000000000006' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x69Ccca6988395Db4cEd6f7F1cBe0CC1783567c7B' │
│ 2       │ '0x57a2c0270ed7aa047285fc54a0355787826ff655-citrea' │ 'Citrea' │ 'juiceswap' │ 'CTUSD-USDC.E'  │ 2691.4973285419446 │ 18.933892945731877    │ [ '0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d', '0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x57a2c0270ED7Aa047285FC54A0355787826fF655' │
│ 3       │ '0x57de4ce63291ac85e5c3c95bfaa1782bbc275559-citrea' │ 'Citrea' │ 'juiceswap' │ 'WCBTC-SYBTC'   │ 283.33461740064274 │ 0.045342160120098826  │ [ '0x3100000000000000000000000000000000000006', '0x384157027b1cdeac4e26e3709667bb28735379bb' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x57dE4Ce63291AC85E5c3c95BfaA1782Bbc275559' │
│ 4       │ '0x61d0da317ca56e74cbb032e90c0439c67f92f0eb-citrea' │ 'Citrea' │ 'juiceswap' │ 'CTUSD-USDC.E'  │ 143.34582277220744 │ 0                     │ [ '0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d', '0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x61d0dA317CA56e74cBB032e90c0439c67F92F0eB' │
│ 5       │ '0xb02e86a9befdcd3bc1628014663f418047ec3884-citrea' │ 'Citrea' │ 'juiceswap' │ 'WCBTC-CTUSD'   │ 120.96383402854752 │ 1.1048014030860296    │ [ '0x3100000000000000000000000000000000000006', '0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0xB02e86A9BEfDcd3Bc1628014663F418047eC3884' │
│ 6       │ '0x26bdf3981424b2097c525f2afeb4e0062a347f0d-citrea' │ 'Citrea' │ 'juiceswap' │ 'SVJUSD-WCBTC'  │ 91.52002082875228  │ 0.0246049889984597    │ [ '0x1b70ae756b1089cc5948e4f8a2ad498df30e897d', '0x3100000000000000000000000000000000000006' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x26BDF3981424B2097C525f2AFeb4E0062A347F0D' │
│ 7       │ '0x25c28437d4b416a2f7bc2cfe6f8c8991ed4986b8-citrea' │ 'Citrea' │ 'juiceswap' │ 'WCBTC-CTUSD'   │ 51.295924180745004 │ 0.733841875912341     │ [ '0x3100000000000000000000000000000000000006', '0x8d82c4e3c936c7b5724a382a9c5a4e6eb7ab6d5d' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0x25c28437d4B416a2f7bc2cFe6f8c8991ed4986B8' │
│ 8       │ '0xd77f369715e227b93d48b09066640f46f0b01b29-citrea' │ 'Citrea' │ 'juiceswap' │ 'WCBTC-USDC.E'  │ 51.09350115364338  │ 1.1763711187781178    │ [ '0x3100000000000000000000000000000000000006', '0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0xD77f369715E227B93D48b09066640F46F0B01b29' │
│ 9       │ '0xbdd8d4cc1c5960322f88bc264b8089663a9bb6e2-citrea' │ 'Citrea' │ 'juiceswap' │ 'USDT.E-USDC.E' │ 42.70457067671818  │ 0.017952209834922725  │ [ '0x9f3096bac87e7f03dc09b0b416eb0df837304dc4', '0xe045e6c36cf77faa2cfb54466d71a3aef7bbe839' ] │ 'https://juiceswap.com/#/explore/pools/citrea_mainnet/0xbdd8d4cC1C5960322F88Bc264B8089663a9BB6e2' │
└─────────┴─────────────────────────────────────────────────────┴──────────┴─────────────┴─────────────────┴────────────────────┴───────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────┘
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.

🧹 Nitpick comments (2)
src/adaptors/juiceswap/index.js (2)

55-55: Add an early return for empty pool sets.

If the pool query returns no items, we can skip multicalls and price fetches entirely. This reduces upstream load and avoids unnecessary external-call failure surface.

Suggested fast-path
   const pools = poolsData.pools.items;
+  if (!pools.length) return [];

Also applies to: 61-99

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

In `@src/adaptors/juiceswap/index.js` at line 55, The result handling should
short-circuit when the pool query returns no items: after assigning const pools
= poolsData.pools.items, add an early return when pools is falsy or length===0
to skip the subsequent multicall and price-fetch logic and return an appropriate
empty result (e.g., [] or the function's empty-response shape). Apply the same
fast-path check to the other similar block in this file around the
multicall/price-fetch sequence so you avoid unnecessary external calls and
downstream errors.

13-13: Avoid silent truncation when query results hit the 1000 cap.

Both datasets are hard-capped at 1000, and the adapter currently continues silently if that cap is reached. That can underreport pools/stats without any signal.

Suggested guard (fail loudly when cap is hit)
   const pools = poolsData.pools.items;
+  if (pools.length === 1000) {
+    throw new Error('JuiceSwap pools query reached limit=1000; add pagination before continuing');
+  }
   const statsMap = Object.fromEntries(
     statsData.poolStats.items.map((s) => [s.poolAddress.toLowerCase(), s])
   );
+  if (statsData.poolStats.items.length === 1000) {
+    throw new Error('JuiceSwap stats query reached limit=1000; add pagination before continuing');
+  }

Also applies to: 28-28, 55-58

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

In `@src/adaptors/juiceswap/index.js` at line 13, The GraphQL query uses a hard
limit of 1000 on "pools" (pools(where: { chainId: $chainId }, limit: 1000)),
which can silently truncate results; update the adapter to detect when the
returned array length equals 1000 and fail loudly (throw or log an error and
stop) so callers are alerted to truncation. Apply the same guard for the other
capped queries in this file (the other occurrences of limit: 1000 around the
pools/stat collection and the block that processes query results) by checking
the corresponding response arrays before continuing and surfacing a clear error
mentioning the query name (e.g., "pools") and chainId so the issue can be
investigated.
🤖 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/juiceswap/index.js`:
- Line 55: The result handling should short-circuit when the pool query returns
no items: after assigning const pools = poolsData.pools.items, add an early
return when pools is falsy or length===0 to skip the subsequent multicall and
price-fetch logic and return an appropriate empty result (e.g., [] or the
function's empty-response shape). Apply the same fast-path check to the other
similar block in this file around the multicall/price-fetch sequence so you
avoid unnecessary external calls and downstream errors.
- Line 13: The GraphQL query uses a hard limit of 1000 on "pools" (pools(where:
{ chainId: $chainId }, limit: 1000)), which can silently truncate results;
update the adapter to detect when the returned array length equals 1000 and fail
loudly (throw or log an error and stop) so callers are alerted to truncation.
Apply the same guard for the other capped queries in this file (the other
occurrences of limit: 1000 around the pools/stat collection and the block that
processes query results) by checking the corresponding response arrays before
continuing and surfacing a clear error mentioning the query name (e.g., "pools")
and chainId so the issue can be investigated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0bf4cef9-4870-4764-b48a-be4587817c15

📥 Commits

Reviewing files that changed from the base of the PR and between 0e09631 and 1eb0249.

📒 Files selected for processing (1)
  • src/adaptors/juiceswap/index.js

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.

2 participants