Skip to content

add shapeswap v3 yields#2628

Open
DenSmolonski wants to merge 4 commits into
DefiLlama:masterfrom
protofire:shapeswap-yields
Open

add shapeswap v3 yields#2628
DenSmolonski wants to merge 4 commits into
DefiLlama:masterfrom
protofire:shapeswap-yields

Conversation

@DenSmolonski

@DenSmolonski DenSmolonski commented Apr 27, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added Shapeswap v3 APY calculations for liquidity pools, featuring real-time fee earning metrics derived from pool trading volume and total value locked.
  • Improvements

    • Enhanced subgraph infrastructure to support additional query endpoints.

Review Change Stack

@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces Shapeswap v3 adapter support for yield farming data. A subgraph domain whitelist is extended to recognize swap.w3us.site, then a new Shapeswap v3 adapter queries pools, calculates 1-day volume from block snapshots, derives APY from fees and TVL, and returns normalized pool data.

Changes

Shapeswap v3 Protocol Support

Layer / File(s) Summary
Subgraph domain whitelisting
src/adaptors/utils.js
The getLatestBlockSubgraph routing logic now treats swap.w3us.site as a whitelisted subgraph domain for direct query requests.
Shapeswap v3 APY adapter implementation
src/adaptors/shapeswap-v3/index.js
Exports an apy function that queries current and prior block pool snapshots, computes 1-day volume (current volume minus prior volume), derives fee rates from feeTier, calculates per-pool APY as annualized fees scaled by TVL, and returns normalized pool objects with tvl, apyBase, underlying tokens, pool metadata, and landing URLs; includes error handling that falls back to zero prior volume on query failure.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A new v3 adapter hops into view,
Querying pools where the yields ring true,
From prior snapshots to APY's might,
Shapeswap now shines in the yield-server light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add shapeswap v3 yields' directly and clearly describes the main change: introducing Shapeswap v3 yield support via a new adapter module.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/adaptors/shapeswap-v3/index.js

Parsing error: The keyword 'const' is reserved

src/adaptors/utils.js

Parsing error: The keyword 'const' is reserved


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.

@DenSmolonski

Copy link
Copy Markdown
Author

@github-actions

Copy link
Copy Markdown

Error while running shapeswap-v3 adapter:

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

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬────────────────┬────────────────┬────────────────────┬───────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────────────────────────────────────────────────────────────┬──────────────────────┐
│ (index) │ pool                                               │ chain   │ project        │ symbol         │ tvlUsd             │ apyBase               │ underlyingTokens                                                                               │ poolMeta │ url                                                                     │ volumeUsd1d          │
├─────────┼────────────────────────────────────────────────────┼─────────┼────────────────┼────────────────┼────────────────────┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────────────────────────────────────────────────────────────┼──────────────────────┤
│ 0       │ '0x12a0b5f465bb6533388f8edaae40a033a82f20a4-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 47068.570214315485 │ 6.996620147075848     │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.3%'   │ 'https://shapeswap.com/pool/0x12a0b5f465bb6533388f8edaae40a033a82f20a4' │ 3007.496864434099    │
│ 1       │ '0x882f55d09a543d95dd7bdab7057734df5edad93f-shape' │ 'Shape' │ 'shapeswap-v3' │ 'SHAPE-USDC.E' │ 33429.20162        │ 0                     │ [ '0x360aac543a23dbcefa8049d4c4d8b18da1cca360', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '1%'     │ 'https://shapeswap.com/pool/0x882f55d09a543d95dd7bdab7057734df5edad93f' │ 0                    │
│ 2       │ '0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 256.1204770562666  │ 0.0008270385883989247 │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.01%'  │ 'https://shapeswap.com/pool/0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e' │ 0.058033292549225735 │
└─────────┴────────────────────────────────────────────────────┴─────────┴────────────────┴────────────────┴────────────────────┴───────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────────────────────────────────────────────────────────────┴──────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@github-actions

Copy link
Copy Markdown

Error while running shapeswap-v3 adapter:

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

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬────────────────┬────────────────┬───────────────────┬───────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────────────────────────────────────────────────────────────┬─────────────────────┐
│ (index) │ pool                                               │ chain   │ project        │ symbol         │ tvlUsd            │ apyBase               │ underlyingTokens                                                                               │ poolMeta │ url                                                                     │ volumeUsd1d         │
├─────────┼────────────────────────────────────────────────────┼─────────┼────────────────┼────────────────┼───────────────────┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ 0       │ '0x12a0b5f465bb6533388f8edaae40a033a82f20a4-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 46879.12197941895 │ 8.643600961166518     │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.3%'   │ 'https://shapeswap.com/pool/0x12a0b5f465bb6533388f8edaae40a033a82f20a4' │ 3700.497021004092   │
│ 1       │ '0x882f55d09a543d95dd7bdab7057734df5edad93f-shape' │ 'Shape' │ 'shapeswap-v3' │ 'SHAPE-USDC.E' │ 33052.438288      │ 0                     │ [ '0x360aac543a23dbcefa8049d4c4d8b18da1cca360', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '1%'     │ 'https://shapeswap.com/pool/0x882f55d09a543d95dd7bdab7057734df5edad93f' │ 0                   │
│ 2       │ '0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 256.1204770562666 │ 0.0005383495463990655 │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.01%'  │ 'https://shapeswap.com/pool/0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e' │ 0.03777598428678175 │
└─────────┴────────────────────────────────────────────────────┴─────────┴────────────────┴────────────────┴───────────────────┴───────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────────────────────────────────────────────────────────────┴─────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@github-actions

Copy link
Copy Markdown

Error while running shapeswap-v3 adapter:

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

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬────────────────┬────────────────┬───────────────────┬───────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────────────────────────────────────────────────────────────────────────┬─────────────────────┐
│ (index) │ pool                                               │ chain   │ project        │ symbol         │ tvlUsd            │ apyBase               │ underlyingTokens                                                                               │ poolMeta │ url                                                                                 │ volumeUsd1d         │
├─────────┼────────────────────────────────────────────────────┼─────────┼────────────────┼────────────────┼───────────────────┼───────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ 0       │ '0x12a0b5f465bb6533388f8edaae40a033a82f20a4-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 46879.12197941895 │ 8.643600961166518     │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.3%'   │ 'https://info.shapeswap.xyz/home#/pools/0x12a0b5f465bb6533388f8edaae40a033a82f20a4' │ 3700.497021004092   │
│ 1       │ '0x882f55d09a543d95dd7bdab7057734df5edad93f-shape' │ 'Shape' │ 'shapeswap-v3' │ 'SHAPE-USDC.E' │ 33052.438289      │ 0                     │ [ '0x360aac543a23dbcefa8049d4c4d8b18da1cca360', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '1%'     │ 'https://info.shapeswap.xyz/home#/pools/0x882f55d09a543d95dd7bdab7057734df5edad93f' │ 0                   │
│ 2       │ '0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 256.1204770562666 │ 0.0005383495463990655 │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.01%'  │ 'https://info.shapeswap.xyz/home#/pools/0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e' │ 0.03777598428678175 │
└─────────┴────────────────────────────────────────────────────┴─────────┴────────────────┴────────────────┴───────────────────┴───────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@DenSmolonski

Copy link
Copy Markdown
Author

Hello @bheluga,

Could you please take a look at this PR? The adapter has been merged: DefiLlama/DefiLlama-Adapters#18931

@DenSmolonski

Copy link
Copy Markdown
Author

Hello @bheluga,

Do you have any updates regarding this PR?

@github-actions

Copy link
Copy Markdown

The shapeswap-v3 adapter exports pools:

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

Nb of pools: 3
 

Sample pools:
┌─────────┬────────────────────────────────────────────────────┬─────────┬────────────────┬────────────────┬────────────────────┬───────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┬──────────┬─────────────────────────────────────────────────────────────────────────────────────┬────────────────────┐
│ (index) │ pool                                               │ chain   │ project        │ symbol         │ tvlUsd             │ apyBase       │ underlyingTokens                                                                               │ poolMeta │ url                                                                                 │ volumeUsd1d        │
├─────────┼────────────────────────────────────────────────────┼─────────┼────────────────┼────────────────┼────────────────────┼───────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┼──────────┼─────────────────────────────────────────────────────────────────────────────────────┼────────────────────┤
│ 0       │ '0x12a0b5f465bb6533388f8edaae40a033a82f20a4-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 44543.087592201984 │ 5.00750966349 │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.3%'   │ 'https://info.shapeswap.xyz/home#/pools/0x12a0b5f465bb6533388f8edaae40a033a82f20a4' │ 2036.9857676678803 │
│ 1       │ '0x882f55d09a543d95dd7bdab7057734df5edad93f-shape' │ 'Shape' │ 'shapeswap-v3' │ 'SHAPE-USDC.E' │ 31442.817727       │ 0             │ [ '0x360aac543a23dbcefa8049d4c4d8b18da1cca360', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '1%'     │ 'https://info.shapeswap.xyz/home#/pools/0x882f55d09a543d95dd7bdab7057734df5edad93f' │ 0                  │
│ 2       │ '0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e-shape' │ 'Shape' │ 'shapeswap-v3' │ 'WETH-USDC.E'  │ 255.9285699863982  │ 0             │ [ '0x4200000000000000000000000000000000000006', '0xdb7dd8b00edc5778fe00b2408bf35c7c054f8bbe' ] │ '0.01%'  │ 'https://info.shapeswap.xyz/home#/pools/0x68448eb6ddd779b8b94e2c0d9bd49fb1ac0b128e' │ 0                  │
└─────────┴────────────────────────────────────────────────────┴─────────┴────────────────┴────────────────┴────────────────────┴───────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┴──────────┴─────────────────────────────────────────────────────────────────────────────────────┴────────────────────┘
This adapter contains some pools with <10k TVL, these pools won't be shown in DefiLlama

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
src/adaptors/shapeswap-v3/index.js (2)

30-42: ⚡ Quick win

Add matching TVL filter for consistency.

The priorVolumeQuery lacks the where: { totalValueLockedUSD_gt: "100" } filter present in poolsQuery. This inconsistency means the two queries could return different pool sets, though the fallback logic on line 61 prevents errors. Adding the filter would improve consistency and slightly reduce query overhead.

📋 Suggested fix to align query filters
 const priorVolumeQuery = gql`
   query ($block: Int!) {
     pools(
       first: 1000
       orderBy: totalValueLockedUSD
       orderDirection: desc
       block: { number: $block }
+      where: { totalValueLockedUSD_gt: "100" }
     ) {
       id
       volumeUSD
     }
   }
 `;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/shapeswap-v3/index.js` around lines 30 - 42, The
priorVolumeQuery (GraphQL template literal named priorVolumeQuery) is missing
the same where filter used in poolsQuery; update priorVolumeQuery to include
where: { totalValueLockedUSD_gt: "100" } inside the pools(...) args so both
queries return the same filtered pool set (keep the existing block variable
$block and other args intact) to improve consistency and reduce query load.

82-86: 💤 Low value

Consider clarifying time-travel support status.

The module exports timetravel: false, but the apy function accepts a timestamp parameter (line 44) and passes it to utils.getBlocks, which supports historical queries. This creates a potential inconsistency between the declared capability and the actual implementation.

If historical queries are intentionally disabled due to subgraph reliability or testing concerns, this is fine. Otherwise, consider either setting timetravel: true or removing the timestamp parameter if historical queries aren't supported.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/shapeswap-v3/index.js` around lines 82 - 86, The export declares
timetravel: false while the apy(timestamp) function accepts a timestamp and
calls utils.getBlocks (supporting historical lookups), causing inconsistency;
either change the exported timetravel to true to reflect that apy supports
historical queries, or remove the timestamp parameter and any utils.getBlocks
calls from the apy function so it no longer performs historical queries—locate
the apy function and the module.exports block and update timetravel or strip
timestamp usage accordingly (ensure any callers and tests align with the chosen
behavior).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/adaptors/shapeswap-v3/index.js`:
- Line 61: The calculation for 1-day USD volume uses a wrong fallback: replace
the fallback that uses volumeUsdAll with zero so missing prior data is treated
as priorVolume = 0. Update the expression that computes volumeUsd1d (which
references priorVolumeById, p.id and volumeUsdAll) to use priorVolumeById[p.id]
?? 0 instead of priorVolumeById[p.id] ?? volumeUsdAll so volumeUsd1d =
Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? 0), 0); also review the
related log message about "falling back to zero prior volume" to ensure it
matches the new behavior.

---

Nitpick comments:
In `@src/adaptors/shapeswap-v3/index.js`:
- Around line 30-42: The priorVolumeQuery (GraphQL template literal named
priorVolumeQuery) is missing the same where filter used in poolsQuery; update
priorVolumeQuery to include where: { totalValueLockedUSD_gt: "100" } inside the
pools(...) args so both queries return the same filtered pool set (keep the
existing block variable $block and other args intact) to improve consistency and
reduce query load.
- Around line 82-86: The export declares timetravel: false while the
apy(timestamp) function accepts a timestamp and calls utils.getBlocks
(supporting historical lookups), causing inconsistency; either change the
exported timetravel to true to reflect that apy supports historical queries, or
remove the timestamp parameter and any utils.getBlocks calls from the apy
function so it no longer performs historical queries—locate the apy function and
the module.exports block and update timetravel or strip timestamp usage
accordingly (ensure any callers and tests align with the chosen behavior).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7fb8e7a9-5706-4621-a63e-504944e05bad

📥 Commits

Reviewing files that changed from the base of the PR and between 093b82a and 8b52822.

📒 Files selected for processing (2)
  • src/adaptors/shapeswap-v3/index.js
  • src/adaptors/utils.js

.map((p) => {
const tvlUsd = Number(p.totalValueLockedUSD);
const volumeUsdAll = Number(p.volumeUSD);
const volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? volumeUsdAll), 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Incorrect fallback for missing prior volume data.

When priorVolumeById[p.id] is undefined (pool missing from prior data or prior query failed), the fallback volumeUsdAll causes the calculation to become volumeUsdAll - volumeUsdAll = 0, resulting in zero 1-day volume and zero APY for affected pools.

The error message on line 53 states "falling back to zero prior volume", which suggests the intent is to treat prior volume as 0 (not 1-day volume as 0). This would make 1-day volume equal to current cumulative volume for new pools or when prior data is unavailable.

🐛 Proposed fix to use zero prior volume as fallback
-      const volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? volumeUsdAll), 0);
+      const volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? 0), 0);
📝 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 volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? volumeUsdAll), 0);
const volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id] ?? 0), 0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adaptors/shapeswap-v3/index.js` at line 61, The calculation for 1-day USD
volume uses a wrong fallback: replace the fallback that uses volumeUsdAll with
zero so missing prior data is treated as priorVolume = 0. Update the expression
that computes volumeUsd1d (which references priorVolumeById, p.id and
volumeUsdAll) to use priorVolumeById[p.id] ?? 0 instead of priorVolumeById[p.id]
?? volumeUsdAll so volumeUsd1d = Math.max(volumeUsdAll - (priorVolumeById[p.id]
?? 0), 0); also review the related log message about "falling back to zero prior
volume" to ensure it matches the new behavior.

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.

1 participant