Skip to content

feat(napier): add dexs volume adapter + rewrite fees adapter to API-based#6065

Open
amrrobb wants to merge 6 commits intoDefiLlama:masterfrom
napierfi:feat/napier-uniswap-v4
Open

feat(napier): add dexs volume adapter + rewrite fees adapter to API-based#6065
amrrobb wants to merge 6 commits intoDefiLlama:masterfrom
napierfi:feat/napier-uniswap-v4

Conversation

@amrrobb
Copy link

@amrrobb amrrobb commented Mar 5, 2026

Summary

Linear: NAP-2375 — DefiLlama Dashboard Enhancement

Fees adapter (fees/napier/index.ts) — Rewrite to API-based

  • Replace on-chain event tracking with pre-computed dailyFeeInUsd from napier-api
  • Remove all ABI definitions, BigNumber dependency, complex on-chain fee parsing
  • 1 API call per chain, sum daily fees across all markets
  • Fee split between curator (supply side) and protocol based on fee distribution ratios
  • Treasury reward token tracking via addTokensReceived

Dexs adapter (dexs/napier/index.ts) — New production adapter

  • On-chain volume tracking via swap events (24h/7d/30d/cumulative)
  • Curve AMM (TwoCrypto) pools: TokenExchange events
  • Napier AMM (TokiHook/Uniswap V4) pools: HookSwap events (filtered by poolId)
  • Pool addresses and types fetched dynamically from napier-api

Methodology

Fees:

Total fees including AMM trading fees (from Napier AMM/TokiHook swaps), rehypothecation yield (LP capital deployed into ERC-4626 vaults), and PT/YT fees (issuance, redemption, performance). Fee rates are defined per market by curators.

Revenue:

Governed by two fee distribution ratios:

  • LP–Curator Fee Distribution Ratio (%) — applies to AMM trading fees, defined per market by curators
  • Curator–Protocol/DAO Fee Distribution Ratio (%) — defined by Napier governance

Volume:

Aggregates trading volume from Napier AMM pools by tracking on-chain swap events. Supports Curve AMM (TwoCrypto) and Napier AMM (TokiHook/Uniswap V4) pools.

Supported chains (both adapters)

Ethereum, Base, Sonic, Arbitrum, Optimism, Fraxtal, Mantle, BSC, Polygon, Avalanche, HyperEVM

Test plan

  • Fees adapter tested against staging and production API
  • Dexs adapter tested — correctly returns 0 when no active swaps exist (all current markets are matured)
  • All chains handle gracefully when no markets exist

Summary by CodeRabbit

  • New Features

    • Added Napier Finance fees adapter with per-chain fee, revenue, and treasury reward handling.
    • Added Napier Finance DEX volume adapter aggregating on-chain swap volumes across chains.
    • Added staging adapters for Napier fee and volume integrations.
  • Chores

    • Removed legacy Napier adapter implementation.
  • Refactor

    • Reorganized Napier integrations into clear per-chain fetch workflows and standardized methodology.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removed the legacy Napier fees adapter and added new primary and staging Napier fees and volume adapters that fetch market data from Napier APIs, read on‑chain TokenExchange/HookSwap events, convert token amounts using decimals, and return aggregated daily fees, revenues, and volumes.

Changes

Cohort / File(s) Summary
Fees adapter — primary
fees/napier/index.ts
Added a multi‑chain fees adapter (v2). Fetches /v1/market?chainIds=<chain>, sums dailyFeeInUsd, dailyCuratorFeeInUsd, dailyProtocolFeeInUsd (positive only), deduplicates underlyingRewards[].rewardToken.address and calls addTokensReceived for treasury receipts, returns { dailyFees, dailyRevenue, dailySupplySideRevenue, timestamp }, includes methodology and chainConfig.
Fees adapter — staging
fees/napier/index.staging.ts
Added staging fees adapter targeting https://api-staging.napier.finance. Same aggregation logic as primary, with per‑chain start dates (Ethereum, Arbitrum), reward token dedupe, and tolerant error handling for markets fetch.
Volume adapter — primary
dexs/napier/index.ts
Added volume adapter that queries Napier API for markets, builds pool -> Market and poolId -> Market mappings, collects Curve TwoCrypto pools and TokiHook singleton, fetches TokenExchange and HookSwap logs, converts raw amounts using token decimals to asset terms, and aggregates dailyVolume. Exports multi‑chain SimpleAdapter with methodology and chainConfig.
Volume adapter — staging
dexs/napier/index.staging.ts
Added staging volume adapter pointing at staging API. Discovers staging markets, maps pools and poolIds, fetches TokenExchange and HookSwap logs, converts amounts via decimals ratio, aggregates dailyVolume, and exports per‑chain adapter with start dates for ETH/ARB.
Removed legacy module & exports
fees/napier.ts
Deleted the legacy Napier fees adapter file and its exported types (including FetchMarketsResult) and default export.
Shared concerns / constants
* (e.g., NAPIER_API_URL, ABIs, chainConfig, methodology)
Introduced ABIs for TokenExchange/HookSwap, primary/staging API base URLs, token‑decimal conversion math, treasury handling via addTokensReceived, and mapping construction — review mapping correctness, decimal math, and error handling paths.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Adapter as Napier Adapter
  participant API as Napier API
  participant Chain as Blockchain RPC
  participant Conv as TokenConversion
  participant Acc as Aggregator

  Adapter->>API: GET /v1/market?chainIds=<chain>
  API-->>Adapter: markets + metrics (dailyFeeInUsd, curator/protocol, underlyingRewards)
  Adapter->>Chain: getLogs(TokenExchange) for Curve pools
  Adapter->>Chain: getLogs(HookSwap) for TokiHook contract
  Chain-->>Adapter: event logs (amounts, poolId, token indexes)
  Adapter->>Conv: convert raw amounts using token decimals (assetDecimals/targetDecimals)
  Conv-->>Adapter: normalized asset amounts (USD via market metrics)
  Adapter->>Acc: increment dailyFees, dailySupplySideRevenue, dailyRevenue, dailyVolume
  Adapter-->>Client: return { timestamp: options.startOfDay, dailyFees/dailyRevenue/dailySupplySideRevenue/dailyVolume }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through APIs, logs, and bytes,
Fetching pools by day and swaps by nights,
Converting decimals, tallying fees,
Rewards and volumes danced on the breeze,
A tiny rabbit cheers these adapter flights ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main changes: adding a dexs volume adapter and rewriting the fees adapter to use API-based approach, which aligns with the changeset.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering the rewrite of fees adapter, addition of dexs adapter, supported chains, and test plan, despite the repository template being for new protocol listings.

✏️ 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.

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 03:03:53 GMT
End Date:	Thu, 05 Mar 2026 03:03:53 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs fraxtal Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs arbitrum Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs sonic Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs optimism Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs mantle Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs hyperliquid Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs avax Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs base Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs bsc Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain       | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---         | ---        | ---           | ---                       | ---       
ethereum    | 0.00       | 0.00          | 0.00                      | 28/2/2024 
base        | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic       | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal     | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc         | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon     | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax        | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate   | 0.00       | 0.00          | 0.00                      |           

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 `@fees/napier/index.ts`:
- Around line 43-48: The current try/catch around the axios.get call swallows
failures and only logs a warning, which can allow invalid/partial metrics to be
emitted; in the catch block for the axios.get<Market[]>(url) call (the code that
assigns markets), rethrow the error (or throw a new Error with context) after
logging so the function fails closed—include options.api.chainId and the
original error message in the thrown error to preserve context; this ensures any
caller of the markets fetch path receives the failure instead of proceeding with
an empty/partial markets array.
- Around line 63-72: The code calls addTokensReceived even when rewardTokens is
empty which can trigger unnecessary indexer queries; update the block around
rewardTokens (computed from markets.flatMap(...)) to check if
rewardTokens.length === 0 and skip calling addTokensReceived (e.g., set
dailyRevenue to an empty/default value) instead of invoking addTokensReceived
with an empty tokens array; ensure you still reference
chainConfig[chain].treasury when needed and only call addTokensReceived when
rewardTokens.length > 0.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 064bf9f4-249d-4aef-8392-78b6e0d82213

📥 Commits

Reviewing files that changed from the base of the PR and between 7a21705 and 3229bc4.

📒 Files selected for processing (2)
  • fees/napier.ts
  • fees/napier/index.ts
💤 Files with no reviewable changes (1)
  • fees/napier.ts

@amrrobb amrrobb changed the title Rewrite Napier fees adapter to API-based feat(napier): add dexs volume adapter + rewrite fees adapter to API-based Mar 5, 2026
@amrrobb
Copy link
Author

amrrobb commented Mar 5, 2026

Addressed CodeRabbit review feedback:

  1. Error handling: API failures now throw instead of silently returning zero metrics. This prevents publishing misleading zero-fee data.

  2. Empty reward tokens guard: addTokensReceived is now skipped when no reward tokens exist, avoiding unnecessary indexer queries.

  3. Zero fees in llamabutler test: The dailyFeeInUsd field is computed from the last completed day's pool stats (using normalizedDayTimestamp guard). If the test ran on a day boundary with no completed stats, zeros are the expected result. This matches the same pattern used for volumeInUsd.

Also added: dexs/napier/index.ts — production volume adapter tracking on-chain swap events (Curve TokenExchange + TokiHook HookSwap) across all 11 chains.

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 03:47:13 GMT
End Date:	Thu, 05 Mar 2026 03:47:13 GMT
---------------------------------------------------

chain       | Daily volume | Start Time
---         | ---          | ---       
ethereum    | 0.00         | 28/2/2024 
base        | 0.00         | 27/2/2024 
sonic       | 0.00         | 7/3/2024  
arbitrum    | 0.00         | 11/3/2024 
optimism    | 0.00         | 11/3/2024 
fraxtal     | 0.00         | 11/3/2024 
mantle      | 0.00         | 11/3/2024 
bsc         | 0.00         | 11/3/2024 
polygon     | 0.00         | 12/3/2024 
avax        | 0.00         | 12/3/2024 
hyperliquid | 0.00         | 13/3/2024 
Aggregate   | 0.00         |           

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 03:48:28 GMT
End Date:	Thu, 05 Mar 2026 03:48:28 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain       | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---         | ---        | ---           | ---                       | ---       
ethereum    | 0.00       | 0.00          | 0.00                      | 28/2/2024 
base        | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic       | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal     | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc         | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon     | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax        | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate   | 0.00       | 0.00          | 0.00                      |           

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: 3

🧹 Nitpick comments (1)
dexs/napier/index.ts (1)

123-125: Consider using 10n ** BigInt(decimals) instead of BigInt(10 ** decimals) for clearer intent and to avoid unnecessary number coercion.

While testing shows BigInt(10 ** decimals) produces correct results for typical token decimals (6, 8, 18), the alternative pattern 10n ** BigInt(decimals) is more explicit about working directly with bigints and is a clearer code style. This pattern is used at lines 124 and 156.

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

In `@dexs/napier/index.ts` around lines 123 - 125, Replace the expressions that
compute 10^decimals via BigInt(10 ** decimals) with the clearer bigint-native
form 10n ** BigInt(decimals); specifically update the computation of assetAmount
(which uses targetAmount, assetDecimals and targetDecimals) and the similar
expression used elsewhere around the dailyVolume.add call so they use 10n **
BigInt(assetDecimals) and 10n ** BigInt(targetDecimals) respectively to avoid
intermediate Number coercion and express intent plainly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dexs/napier/index.ts`:
- Around line 28-40: The code currently uses TOKI_HOOK_ADDRESSES zero-address
placeholders and silently skips processing when a hook is unset; instead, in the
block that examines TOKI_HOOK_ADDRESSES (where poolIdToMarket is consulted), add
a validation: for the current chainId look up TOKI_HOOK_ADDRESSES[chainId] and
if poolIdToMarket.size > 0 and the address is missing or the zero-address (e.g.
"0x0000000000000000000000000000000000000000"), throw or exit with an explicit
error (do not continue silently). Update the logic that previously
returned/continued on unset hook (the code around the current skip at the
poolIdToMarket check) to perform this fail-closed validation so volume is not
dropped silently.
- Around line 71-75: The current branch treats any non-"TOKI_HOOK" pool as a
Curve pool, causing unknown/new pool types to be misclassified; change the
conditional around market.pool.poolType so you only push poolAddress into
tokiPools when poolType === "TOKI_HOOK" and into curvePools only when poolType
matches the explicit Curve type/constant (e.g., "CURVE" or the codebase's Curve
enum value), and otherwise skip the pool (do not push) and emit a warning/log
that includes market.pool.poolType and poolAddress so unknown types are
discoverable; update the block referencing market.pool.poolType, tokiPools,
curvePools, and poolAddress accordingly.

In `@fees/napier/index.ts`:
- Line 45: The code currently masks malformed API responses by setting markets =
Array.isArray(res.data) ? res.data : [] which can emit incorrect zero metrics;
change this to validate that res.data is an array and if not, throw or return an
error (or log and exit) instead of defaulting to [] — update the assignment
around markets and the API response handling for res.data so schema mismatches
produce an explicit error path (e.g., throw new Error or return a failed result)
to fail closed when the payload is not an array.

---

Nitpick comments:
In `@dexs/napier/index.ts`:
- Around line 123-125: Replace the expressions that compute 10^decimals via
BigInt(10 ** decimals) with the clearer bigint-native form 10n **
BigInt(decimals); specifically update the computation of assetAmount (which uses
targetAmount, assetDecimals and targetDecimals) and the similar expression used
elsewhere around the dailyVolume.add call so they use 10n **
BigInt(assetDecimals) and 10n ** BigInt(targetDecimals) respectively to avoid
intermediate Number coercion and express intent plainly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87779093-3060-4d99-baa9-ae3d68f96d56

📥 Commits

Reviewing files that changed from the base of the PR and between 3229bc4 and 1d951fe.

📒 Files selected for processing (2)
  • dexs/napier/index.ts
  • fees/napier/index.ts

Comment on lines +28 to +40
const TOKI_HOOK_ADDRESSES: Record<number, string> = {
1: "0x0000000000000000000000000000000000000000", // Ethereum - TODO: populate
8453: "0x0000000000000000000000000000000000000000", // Base - TODO: populate
146: "0x0000000000000000000000000000000000000000", // Sonic - TODO: populate
42161: "0xd4234A3D471159E03501fcC2fFD61aAf43FE1888", // Arbitrum
10: "0x0000000000000000000000000000000000000000", // Optimism - TODO: populate
252: "0x0000000000000000000000000000000000000000", // Fraxtal - TODO: populate
5000: "0x0000000000000000000000000000000000000000", // Mantle - TODO: populate
56: "0x0000000000000000000000000000000000000000", // BSC - TODO: populate
137: "0x0000000000000000000000000000000000000000", // Polygon - TODO: populate
43114: "0x0000000000000000000000000000000000000000", // Avalanche - TODO: populate
999: "0x0000000000000000000000000000000000000000", // HyperEVM - TODO: populate
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not silently skip TOKI volume when hook address is unset.

Lines 28-40 contain zero-address placeholders, and Lines 140-143 skip processing in that case. If TOKI pools exist, volume is dropped without signal. Fail closed when poolIdToMarket.size > 0 but hook address is missing/zero.

Suggested fix
+    const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
     const tokiHookAddress = TOKI_HOOK_ADDRESSES[options.api.chainId!];
 
-    if (tokiHookAddress && tokiHookAddress !== "0x0000000000000000000000000000000000000000" && poolIdToMarket.size > 0) {
+    if (poolIdToMarket.size > 0 && (!tokiHookAddress || tokiHookAddress === ZERO_ADDRESS)) {
+      throw new Error(`Missing TOKI_HOOK address for chainId ${options.api.chainId} with active TOKI pools`);
+    }
+
+    if (tokiHookAddress && tokiHookAddress !== ZERO_ADDRESS && poolIdToMarket.size > 0) {

Also applies to: 140-143

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

In `@dexs/napier/index.ts` around lines 28 - 40, The code currently uses
TOKI_HOOK_ADDRESSES zero-address placeholders and silently skips processing when
a hook is unset; instead, in the block that examines TOKI_HOOK_ADDRESSES (where
poolIdToMarket is consulted), add a validation: for the current chainId look up
TOKI_HOOK_ADDRESSES[chainId] and if poolIdToMarket.size > 0 and the address is
missing or the zero-address (e.g. "0x0000000000000000000000000000000000000000"),
throw or exit with an explicit error (do not continue silently). Update the
logic that previously returned/continued on unset hook (the code around the
current skip at the poolIdToMarket check) to perform this fail-closed validation
so volume is not dropped silently.

@amrrobb amrrobb marked this pull request as draft March 5, 2026 07:12
@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 04:48:39 GMT
End Date:	Thu, 05 Mar 2026 04:48:39 GMT
---------------------------------------------------

chain       | Daily volume | Start Time
---         | ---          | ---       
ethereum    | 0.00         | 28/2/2024 
base        | 0.00         | 27/2/2024 
sonic       | 0.00         | 7/3/2024  
arbitrum    | 0.00         | 11/3/2024 
optimism    | 0.00         | 11/3/2024 
fraxtal     | 0.00         | 11/3/2024 
mantle      | 0.00         | 11/3/2024 
bsc         | 0.00         | 11/3/2024 
polygon     | 0.00         | 12/3/2024 
avax        | 0.00         | 12/3/2024 
hyperliquid | 0.00         | 13/3/2024 
Aggregate   | 0.00         |           

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 04:49:53 GMT
End Date:	Thu, 05 Mar 2026 04:49:53 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain       | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---         | ---        | ---           | ---                       | ---       
ethereum    | 0.00       | 0.00          | 0.00                      | 28/2/2024 
base        | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic       | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal     | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc         | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon     | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax        | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate   | 0.00       | 0.00          | 0.00                      |           

@amrrobb
Copy link
Author

amrrobb commented Mar 5, 2026

Linear: NAP-2375 — DefiLlama Dashboard Enhancement

Related PRs:

This PR covers two adapters:

  • Fees — API-based, reads dailyFeeInUsd from napier-api. Covers AMM trading fees + PT/YT fees (issuance, redemption, performance). Rehypothecation yield intentionally excluded from fees — see NAP-2375 comment for reasoning.
  • Dexs — On-chain swap events for volume tracking (24h/7d/30d/cumulative aggregated by DefiLlama). Supports both Curve TwoCrypto and TokiHook/Uniswap V4 pools.

Draft until napier-api deploys dailyFeeInUsd fields and active markets exist for volume data.

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 06:28:03 GMT
End Date:	Thu, 05 Mar 2026 06:28:03 GMT
---------------------------------------------------

chain       | Daily volume | Start Time
---         | ---          | ---       
ethereum    | 0.00         | 28/2/2024 
base        | 0.00         | 27/2/2024 
sonic       | 0.00         | 7/3/2024  
arbitrum    | 0.00         | 11/3/2024 
optimism    | 0.00         | 11/3/2024 
fraxtal     | 0.00         | 11/3/2024 
mantle      | 0.00         | 11/3/2024 
bsc         | 0.00         | 11/3/2024 
polygon     | 0.00         | 12/3/2024 
avax        | 0.00         | 12/3/2024 
hyperliquid | 0.00         | 13/3/2024 
Aggregate   | 0.00         |           

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 04 Mar 2026 06:29:00 GMT
End Date:	Thu, 05 Mar 2026 06:29:00 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain       | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---         | ---        | ---           | ---                       | ---       
ethereum    | 0.00       | 0.00          | 0.00                      | 28/2/2024 
base        | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic       | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism    | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal     | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc         | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon     | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax        | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate   | 0.00       | 0.00          | 0.00                      |           

@amrrobb amrrobb marked this pull request as ready for review March 19, 2026 07:13
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (4)
fees/napier/index.ts (1)

42-45: ⚠️ Potential issue | 🟠 Major

Reject malformed market payloads.

Line 45 still treats a non-array /v1/market response as “no markets”, which will publish zero fees instead of failing. Please throw on schema mismatch the same way the catch path does.

Suggested fix
-    let markets: Market[];
+    let markets: Market[];
     try {
-      const res = await axios.get<Market[]>(url);
-      markets = Array.isArray(res.data) ? res.data : [];
+      const res = await axios.get<unknown>(url);
+      if (!Array.isArray(res.data)) {
+        throw new Error(
+          `Napier API returned non-array payload for chain ${chain} (chainId ${options.api.chainId})`
+        );
+      }
+      markets = res.data as Market[];
     } catch (e: any) {
       throw new Error(`Napier API fetch failed for chain ${chain} (chainId ${options.api.chainId}): ${e?.message ?? e}`);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fees/napier/index.ts` around lines 42 - 45, The try block that fetches
markets using axios.get(url) assigns an empty array when res.data is not an
array, which masks schema errors and results in publishing zero fees; instead
validate the response and throw on mismatch. In the try block where you call
axios.get<Market[]>(url) and set markets, check Array.isArray(res.data) and if
false throw an Error (include context like the url and typeof res.data) so the
catch path handles it the same way as network/errors; update the logic around
the markets variable (and any callers expecting Market[]) to rely on the thrown
error rather than silently using an empty array.
fees/napier/index.staging.ts (2)

54-63: ⚠️ Potential issue | 🟠 Major

Skip the treasury transfer scan when rewardTokens is empty.

addTokensReceived still runs with tokens: [], which can trigger an unnecessary indexer lookup before it bails out. The production adapter already guards this case.

Suggested fix
     const rewardTokens = [...new Set(
       markets.flatMap((m) =>
         (m.metrics?.underlyingRewards ?? []).map((r: any) => r.rewardToken.address)
       )
     )];
-    const dailyRevenue = await addTokensReceived({
-      options,
-      target: chainConfig[chain].treasury,
-      tokens: rewardTokens,
-    });
+    let dailyRevenue = createBalances();
+    if (rewardTokens.length > 0) {
+      dailyRevenue = await addTokensReceived({
+        options,
+        target: chainConfig[chain].treasury,
+        tokens: rewardTokens,
+      });
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fees/napier/index.staging.ts` around lines 54 - 63, The code calls
addTokensReceived with an empty tokens array causing an unnecessary indexer
lookup; before invoking addTokensReceived in the block that computes
dailyRevenue, check that rewardTokens (derived from markets.flatMap(...) and
used as tokens) is non-empty and only call addTokensReceived when
rewardTokens.length > 0, otherwise skip the treasury transfer scan or set
dailyRevenue to a default value; update the logic around rewardTokens /
addTokensReceived (referencing rewardTokens, addTokensReceived, markets,
chainConfig, chain) so the production guard for an empty token list is mirrored
here.

34-40: ⚠️ Potential issue | 🟠 Major

Fail closed in staging too.

Lines 37-40 still convert broken staging responses into a valid-looking zero day. That hides API regressions and can leave this adapter emitting partial data after the treasury scan.

Suggested fix
-    let markets: Market[] = [];
+    let markets: Market[];
     try {
-      const res = await axios.get<Market[]>(url);
-      markets = Array.isArray(res.data) ? res.data : [];
+      const res = await axios.get<unknown>(url);
+      if (!Array.isArray(res.data)) {
+        throw new Error(
+          `Napier staging API returned non-array payload for chain ${chain} (chainId ${options.api.chainId})`
+        );
+      }
+      markets = res.data as Market[];
     } catch (e: any) {
-      console.warn(`Failed to fetch markets for chain ${options.api.chainId}: ${e.message}`);
+      throw new Error(
+        `Napier staging API fetch failed for chain ${chain} (chainId ${options.api.chainId}): ${e?.message ?? e}`
+      );
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fees/napier/index.staging.ts` around lines 34 - 40, The current staging
adapter swallows errors and converts bad/empty responses into an empty markets
array (variables: markets, axios.get<Market[]>(url), options.api.chainId), which
masks API regressions; change the behavior so that on any non-array response or
axios error you fail closed by throwing a descriptive error (including the
chainId and the raw response/error) instead of assigning an empty array — locate
the axios.get call and the markets assignment in index.staging.ts and replace
the silent warn+empty-array path with a thrown error so upstream/CI can detect
the failure.
dexs/napier/index.ts (1)

53-63: ⚠️ Potential issue | 🟠 Major

Handle unsupported or incomplete pool metadata explicitly.

This else sends every non-TOKI_HOOK market down the Curve path, including unknown poolTypes and TOKI_HOOK entries missing poolId. Those pools then get parsed with the wrong ABI. The staging adapter duplicates the same branch.

Suggested fix
-    if (market.pool.poolType === "TOKI_HOOK" && market.pool.poolId) {
-      tokiHookAddress = poolAddress;
-      poolIdToMarket.set(market.pool.poolId.toLowerCase(), market);
-    } else {
-      curvePools.push(poolAddress);
-    }
+    if (market.pool.poolType === "TOKI_HOOK") {
+      if (!market.pool.poolId) {
+        throw new Error(`Missing poolId for TOKI_HOOK market ${market.metadata.address} on chainId ${api.chainId}`);
+      }
+      tokiHookAddress = poolAddress;
+      poolIdToMarket.set(market.pool.poolId.toLowerCase(), market);
+    } else if (market.pool.poolType === "CURVE_TWO_CRYPTO") {
+      curvePools.push(poolAddress);
+    } else {
+      continue;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dexs/napier/index.ts` around lines 53 - 63, The code is incorrectly treating
any non-TOKI_HOOK market as a Curve pool, which misroutes unknown poolType
values and TOKI_HOOK entries missing poolId into curvePools; update the logic in
the loop that uses poolToMarket, curvePools, poolIdToMarket and tokiHookAddress
to explicitly handle supported poolType values (e.g., check for "CURVE" before
pushing to curvePools), separately handle TOKI_HOOK cases that lack poolId (skip
and/or log an error) and add a fallback path for unknown poolType that does not
assume Curve ABI (e.g., skip or record as unsupported), so only truly Curve
markets are parsed with the Curve ABI and TOKI_HOOK mappings only get set when
poolId exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dexs/napier/index.ts`:
- Around line 42-45: In fetchMarkets(async function), validate the API response
before iterating: check Array.isArray(res.data) (the value used by the for
(const market of res.data) loop) and fail-closed if it’s not an array — e.g.,
log an error or throw so malformed responses don’t silently iterate as
strings/iterables and produce zero volume; update the code around the axios.get
call and the loop to perform this guard and handle the invalid payload
deterministically.

In `@fees/napier/index.ts`:
- Around line 95-96: Update the methodology text in the fees/napier adapter by
removing the phrase about "rehypothecation yield" from the Fees description;
edit the export/object property named Fees (and ensure UserFees remains
unchanged) so the Fees string only lists AMM trading fees and PT/YT fees
(issuance, redemption, performance) to match the adapter's actual calculations
and avoid mentioning rehypothecation yield.

---

Duplicate comments:
In `@dexs/napier/index.ts`:
- Around line 53-63: The code is incorrectly treating any non-TOKI_HOOK market
as a Curve pool, which misroutes unknown poolType values and TOKI_HOOK entries
missing poolId into curvePools; update the logic in the loop that uses
poolToMarket, curvePools, poolIdToMarket and tokiHookAddress to explicitly
handle supported poolType values (e.g., check for "CURVE" before pushing to
curvePools), separately handle TOKI_HOOK cases that lack poolId (skip and/or log
an error) and add a fallback path for unknown poolType that does not assume
Curve ABI (e.g., skip or record as unsupported), so only truly Curve markets are
parsed with the Curve ABI and TOKI_HOOK mappings only get set when poolId
exists.

In `@fees/napier/index.staging.ts`:
- Around line 54-63: The code calls addTokensReceived with an empty tokens array
causing an unnecessary indexer lookup; before invoking addTokensReceived in the
block that computes dailyRevenue, check that rewardTokens (derived from
markets.flatMap(...) and used as tokens) is non-empty and only call
addTokensReceived when rewardTokens.length > 0, otherwise skip the treasury
transfer scan or set dailyRevenue to a default value; update the logic around
rewardTokens / addTokensReceived (referencing rewardTokens, addTokensReceived,
markets, chainConfig, chain) so the production guard for an empty token list is
mirrored here.
- Around line 34-40: The current staging adapter swallows errors and converts
bad/empty responses into an empty markets array (variables: markets,
axios.get<Market[]>(url), options.api.chainId), which masks API regressions;
change the behavior so that on any non-array response or axios error you fail
closed by throwing a descriptive error (including the chainId and the raw
response/error) instead of assigning an empty array — locate the axios.get call
and the markets assignment in index.staging.ts and replace the silent
warn+empty-array path with a thrown error so upstream/CI can detect the failure.

In `@fees/napier/index.ts`:
- Around line 42-45: The try block that fetches markets using axios.get(url)
assigns an empty array when res.data is not an array, which masks schema errors
and results in publishing zero fees; instead validate the response and throw on
mismatch. In the try block where you call axios.get<Market[]>(url) and set
markets, check Array.isArray(res.data) and if false throw an Error (include
context like the url and typeof res.data) so the catch path handles it the same
way as network/errors; update the logic around the markets variable (and any
callers expecting Market[]) to rely on the thrown error rather than silently
using an empty array.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f97e4bed-1886-4d69-a948-a20819becd57

📥 Commits

Reviewing files that changed from the base of the PR and between 1d951fe and fcb347b.

📒 Files selected for processing (4)
  • dexs/napier/index.staging.ts
  • dexs/napier/index.ts
  • fees/napier/index.staging.ts
  • fees/napier/index.ts

amrrobb added 5 commits March 19, 2026 21:30
Replace on-chain event tracking with pre-computed dailyFeeInUsd from
napier-api market list. Removes all ABI definitions, BigNumber deps,
and complex on-chain fee parsing in favor of a single API call per chain.

- Sum dailyFeeInUsd across all markets for daily fees
- Split into curator (supply side) and protocol revenue
- Keep addTokensReceived for reward token protocol revenue
- Support all 11 chains (ETH, Base, Sonic, ARB, OP, Frax, Mantle, BSC, Polygon, Avax, HyperEVM)
- Add production dexs/napier/index.ts for on-chain volume tracking
  (Curve TokenExchange + TokiHook HookSwap events, all 11 chains)
- Fix fees adapter: throw on API failure instead of silently returning zeros
- Fix fees adapter: skip addTokensReceived when no reward tokens exist
@amrrobb amrrobb force-pushed the feat/napier-uniswap-v4 branch from fcb347b to b7356cb Compare March 19, 2026 14:30
@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 18 Mar 2026 12:00:56 GMT
End Date:	Thu, 19 Mar 2026 12:00:56 GMT
---------------------------------------------------

chain         | Daily volume | Start Time
---           | ---          | ---       
ethereum      | 0.00         | 28/2/2024 
base          | 0.00         | 27/2/2024 
sonic         | 0.00         | 7/3/2024  
arbitrum      | 0.00         | 11/3/2024 
optimism      | 0.00         | 11/3/2024 
fraxtal       | 0.00         | 11/3/2024 
mantle        | 0.00         | 11/3/2024 
bsc           | 0.00         | 11/3/2024 
polygon       | 0.00         | 12/3/2024 
avax          | 0.00         | 12/3/2024 
hyperliquid   | 0.00         | 13/3/2024 
plume_mainnet | 0.00         | 13/3/2024 
Aggregate     | 0.00         |           

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 18 Mar 2026 12:02:13 GMT
End Date:	Thu, 19 Mar 2026 12:02:13 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain         | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---           | ---        | ---           | ---                       | ---       
ethereum      | 1.00       | 0.00          | 1.00                      | 28/2/2024 
base          | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic         | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal       | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle        | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc           | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon       | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax          | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid   | 0.00       | 0.00          | 0.00                      | 13/3/2024 
plume_mainnet | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate     | 1.00       | 0.00          | 1.00                      |           

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (3)
dexs/napier/index.ts (3)

120-137: ⚠️ Potential issue | 🟠 Major

Fail closed when TOKI pools were discovered but no hook address was resolved.

If poolIdToMarket.size > 0 and tokiHookAddress is null, this branch silently drops all TOKI volume for the chain and returns zeroes. That should be an explicit error, not a quiet skip.

Suggested fix
-    if (tokiHookAddress && poolIdToMarket.size > 0) {
+    if (poolIdToMarket.size > 0 && !tokiHookAddress) {
+      throw new Error(`Missing TOKI hook address for chainId ${options.api.chainId}`);
+    }
+
+    if (tokiHookAddress && poolIdToMarket.size > 0) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dexs/napier/index.ts` around lines 120 - 137, The code silently skips
processing when poolIdToMarket.size > 0 but tokiHookAddress is falsy; change
this to fail loudly by checking if (poolIdToMarket.size > 0 && !tokiHookAddress)
and then throw or log and throw an explicit error (e.g., include chain/context)
instead of continuing; update the logic around tokiHookAddress, getLogs, and the
TOKI_HOOK_ABI.hookSwapEvent handling so TOKI volume is not dropped silently and
ensure callers of this function can catch/handle the thrown error rather than
returning zeroes from dailyVolume.add.

58-63: ⚠️ Potential issue | 🟠 Major

Don't route every non-TOKI market through the Curve decoder.

This else also catches TOKI_HOOK entries missing poolId and any future/unknown poolType, then parses them with the Curve ABI. Only enqueue explicit CURVE_TWO_CRYPTO pools; skip or fail on anything else.

Suggested fix
-    if (market.pool.poolType === "TOKI_HOOK" && market.pool.poolId) {
+    if (market.pool.poolType === "TOKI_HOOK") {
+      if (!market.pool.poolId) {
+        throw new Error(`Missing poolId for TOKI_HOOK market ${market.metadata.address} on chainId ${api.chainId}`);
+      }
       tokiHookAddress = poolAddress;
       poolIdToMarket.set(market.pool.poolId.toLowerCase(), market);
-    } else {
+    } else if (market.pool.poolType === "CURVE_TWO_CRYPTO") {
       curvePools.push(poolAddress);
+    } else {
+      continue;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dexs/napier/index.ts` around lines 58 - 63, The current branch routes any
non-TOKI_HOOK market (including TOKI_HOOK without poolId and unknown types) into
curvePools; change the logic so only explicit CURVE_TWO_CRYPTO pools are pushed
to curvePools: keep the TOKI_HOOK branch as is (market.pool.poolType ===
"TOKI_HOOK" && market.pool.poolId) to set tokiHookAddress and poolIdToMarket,
add an else if that checks market.pool.poolType === "CURVE_TWO_CRYPTO" to push
poolAddress onto curvePools, and for any other poolType (including TOKI_HOOK
missing poolId or unknown types) skip or log a warning instead of enqueuing for
Curve decoding.

42-45: ⚠️ Potential issue | 🟠 Major

Guard the market API payload before iterating it.

axios.get<Market[]> is only a compile-time hint. If the API returns a non-array payload on an error path, this loop can either iterate garbage or fail mid-scan and publish misleading volume data. Fail closed before entering the loop.

Suggested fix
-  const res = await axios.get<Market[]>(url);
+  const res = await axios.get<unknown>(url);
+  if (!Array.isArray(res.data)) {
+    throw new Error(`Napier API returned a non-array market payload for chainId ${api.chainId}`);
+  }
@@
-  for (const market of res.data) {
+  for (const market of res.data as Market[]) {

Also applies to: 53-53

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

In `@dexs/napier/index.ts` around lines 42 - 45, fetchMarkets currently assumes
axios.get<Market[]> returns an array; validate the payload before iterating by
checking Array.isArray(res.data) (and optionally that each item has required
Market fields) inside fetchMarkets (and the similar call at the other site), and
if the check fails log the error/context and return an empty array or throw to
"fail closed" instead of proceeding; update code around the axios.get<Market[]>
call in fetchMarkets to perform this guard and handle the bad-response path
consistently.
🧹 Nitpick comments (1)
dexs/napier/index.ts (1)

147-160: Consider sharing Napier chain start dates with the fees adapter.

This table is duplicated in fees/napier/index.ts:102-151. Extracting a common Napier chain config would reduce drift the next time a chain or backfill date changes.

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

In `@dexs/napier/index.ts` around lines 147 - 160, The chainConfig object is
duplicated between dexs' Napier and fees' Napier; extract this map into a single
exported constant (e.g., NAPIER_CHAIN_CONFIG) in a small shared module (e.g.,
napierConfig) and replace the local chainConfig declarations in both dexs' and
fees' Napier code with imports of that exported constant; update references to
use the shared symbol (chainConfig or NAPIER_CHAIN_CONFIG) so future
chain/start-date changes are made in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@dexs/napier/index.ts`:
- Around line 120-137: The code silently skips processing when
poolIdToMarket.size > 0 but tokiHookAddress is falsy; change this to fail loudly
by checking if (poolIdToMarket.size > 0 && !tokiHookAddress) and then throw or
log and throw an explicit error (e.g., include chain/context) instead of
continuing; update the logic around tokiHookAddress, getLogs, and the
TOKI_HOOK_ABI.hookSwapEvent handling so TOKI volume is not dropped silently and
ensure callers of this function can catch/handle the thrown error rather than
returning zeroes from dailyVolume.add.
- Around line 58-63: The current branch routes any non-TOKI_HOOK market
(including TOKI_HOOK without poolId and unknown types) into curvePools; change
the logic so only explicit CURVE_TWO_CRYPTO pools are pushed to curvePools: keep
the TOKI_HOOK branch as is (market.pool.poolType === "TOKI_HOOK" &&
market.pool.poolId) to set tokiHookAddress and poolIdToMarket, add an else if
that checks market.pool.poolType === "CURVE_TWO_CRYPTO" to push poolAddress onto
curvePools, and for any other poolType (including TOKI_HOOK missing poolId or
unknown types) skip or log a warning instead of enqueuing for Curve decoding.
- Around line 42-45: fetchMarkets currently assumes axios.get<Market[]> returns
an array; validate the payload before iterating by checking
Array.isArray(res.data) (and optionally that each item has required Market
fields) inside fetchMarkets (and the similar call at the other site), and if the
check fails log the error/context and return an empty array or throw to "fail
closed" instead of proceeding; update code around the axios.get<Market[]> call
in fetchMarkets to perform this guard and handle the bad-response path
consistently.

---

Nitpick comments:
In `@dexs/napier/index.ts`:
- Around line 147-160: The chainConfig object is duplicated between dexs' Napier
and fees' Napier; extract this map into a single exported constant (e.g.,
NAPIER_CHAIN_CONFIG) in a small shared module (e.g., napierConfig) and replace
the local chainConfig declarations in both dexs' and fees' Napier code with
imports of that exported constant; update references to use the shared symbol
(chainConfig or NAPIER_CHAIN_CONFIG) so future chain/start-date changes are made
in one place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 029610cb-d2ee-4bcb-86e7-fc520a2fe004

📥 Commits

Reviewing files that changed from the base of the PR and between fcb347b and b7356cb.

📒 Files selected for processing (2)
  • dexs/napier/index.staging.ts
  • dexs/napier/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • dexs/napier/index.staging.ts

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts dexs napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 18 Mar 2026 12:40:12 GMT
End Date:	Thu, 19 Mar 2026 12:40:12 GMT
---------------------------------------------------

chain         | Daily volume | Start Time
---           | ---          | ---       
ethereum      | 0.00         | 28/2/2024 
base          | 0.00         | 27/2/2024 
sonic         | 0.00         | 7/3/2024  
arbitrum      | 0.00         | 11/3/2024 
optimism      | 0.00         | 11/3/2024 
fraxtal       | 0.00         | 11/3/2024 
mantle        | 0.00         | 11/3/2024 
bsc           | 0.00         | 11/3/2024 
polygon       | 0.00         | 12/3/2024 
avax          | 0.00         | 12/3/2024 
hyperliquid   | 0.00         | 13/3/2024 
plume_mainnet | 0.00         | 13/3/2024 
Aggregate     | 0.00         |           

@llamabutler
Copy link

The napier adapter exports:

> adapters@1.0.0 test
> ts-node --transpile-only cli/testAdapter.ts fees napier

🦙 Running NAPIER adapter 🦙
---------------------------------------------------
Start Date:	Wed, 18 Mar 2026 12:41:24 GMT
End Date:	Thu, 19 Mar 2026 12:41:24 GMT
---------------------------------------------------

Token transfers: Failed to use indexer, falling back to logs polygon Llama Indexer URL/api key is not set
Token transfers: Failed to use indexer, falling back to logs ethereum Llama Indexer URL/api key is not set
chain         | Daily fees | Daily revenue | Daily supply side revenue | Start Time
---           | ---        | ---           | ---                       | ---       
ethereum      | 1.00       | 0.00          | 1.00                      | 28/2/2024 
base          | 0.00       | 0.00          | 0.00                      | 27/2/2024 
sonic         | 0.00       | 0.00          | 0.00                      | 7/3/2024  
arbitrum      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
optimism      | 0.00       | 0.00          | 0.00                      | 11/3/2024 
fraxtal       | 0.00       | 0.00          | 0.00                      | 11/3/2024 
mantle        | 0.00       | 0.00          | 0.00                      | 11/3/2024 
bsc           | 0.00       | 0.00          | 0.00                      | 11/3/2024 
polygon       | 0.00       | 0.00          | 0.00                      | 12/3/2024 
avax          | 0.00       | 0.00          | 0.00                      | 12/3/2024 
hyperliquid   | 0.00       | 0.00          | 0.00                      | 13/3/2024 
plume_mainnet | 0.00       | 0.00          | 0.00                      | 13/3/2024 
Aggregate     | 1.00       | 0.00          | 1.00                      |           

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 (3)
fees/napier/index.ts (2)

105-159: Move Config type definition before its usage.

The Config type is defined at lines 156-159 but referenced at line 105. While TypeScript hoisting makes this work, placing type definitions before their usage improves readability.

Suggested reordering
+type Config = {
+  treasury: string;
+  start: string;
+};
+
 const chainConfig: Record<Chain, Config> = {
   [CHAIN.ETHEREUM]: {
   // ...
 };
-
-type Config = {
-  treasury: string;
-  start: string;
-};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fees/napier/index.ts` around lines 105 - 159, The Config type is declared
after it's used in the chainConfig declaration; move the type declaration for
Config above the chainConfig constant so the type is defined before being
referenced (ensure the type name remains Config and update only ordering,
leaving chainConfig and CHAIN entries unchanged).

56-63: dailySupplySideRevenue should check curatorFee > 0 for consistency.

The PR summary states "sum of dailyCuratorFeeInUsd only when positive", but the code adds curatorFee whenever fee > 0 without checking curatorFee's sign. This could add zero or negative values to dailySupplySideRevenue.

Suggested fix
     for (const market of markets) {
       const fee = Number(market.metrics?.dailyFeeInUsd ?? 0);
       const curatorFee = Number(market.metrics?.dailyCuratorFeeInUsd ?? 0);
       if (fee > 0) {
         dailyFees.addUSDValue(fee);
-        dailySupplySideRevenue.addUSDValue(curatorFee);
+      }
+      if (curatorFee > 0) {
+        dailySupplySideRevenue.addUSDValue(curatorFee);
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fees/napier/index.ts` around lines 56 - 63, The loop currently adds
curatorFee to dailySupplySideRevenue whenever fee > 0, but the requirement is to
sum dailyCuratorFeeInUsd only when it's positive; update the logic in the loop
that iterates over markets (where fee = Number(market.metrics?.dailyFeeInUsd ??
0) and curatorFee = Number(market.metrics?.dailyCuratorFeeInUsd ?? 0)) to only
call dailySupplySideRevenue.addUSDValue(curatorFee) when curatorFee > 0 (in
addition to the existing fee > 0 check), ensuring both
dailyFees.addUSDValue(fee) and dailySupplySideRevenue.addUSDValue(curatorFee)
respect their own positivity checks.
dexs/napier/index.ts (1)

103-116: Consider edge case: both sold_id and bought_id could theoretically be 1n.

The logic assumes exactly one of sold_id or bought_id equals 1n (the target token index). If the Curve pool configuration allows swapping target token for itself (unlikely but worth confirming), both conditions could match and targetAmount would use tokensSold.

The current logic is likely correct for Napier's Curve pool configuration. If you want to be defensive:

         let targetAmount: bigint;
         if (soldId === 1n) {
           targetAmount = tokensSold;
-        } else if (boughtId === 1n) {
+        } else if (boughtId === 1n && soldId !== 1n) {
           targetAmount = tokensBought;
         } else {
           continue;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dexs/napier/index.ts` around lines 103 - 116, The code assumes exactly one of
soldId or boughtId equals 1n; make this defensive by handling the case where
both equal 1n explicitly: update the targetAmount assignment in the block that
uses soldId, boughtId, tokensSold, and tokensBought so that if both soldId ===
1n && boughtId === 1n you choose a deterministic behavior (e.g., set
targetAmount = tokensSold or skip the entry), otherwise keep the existing
branches; then continue converting targetAmount to assetAmount and calling
dailyVolume.add as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@dexs/napier/index.ts`:
- Around line 103-116: The code assumes exactly one of soldId or boughtId equals
1n; make this defensive by handling the case where both equal 1n explicitly:
update the targetAmount assignment in the block that uses soldId, boughtId,
tokensSold, and tokensBought so that if both soldId === 1n && boughtId === 1n
you choose a deterministic behavior (e.g., set targetAmount = tokensSold or skip
the entry), otherwise keep the existing branches; then continue converting
targetAmount to assetAmount and calling dailyVolume.add as before.

In `@fees/napier/index.ts`:
- Around line 105-159: The Config type is declared after it's used in the
chainConfig declaration; move the type declaration for Config above the
chainConfig constant so the type is defined before being referenced (ensure the
type name remains Config and update only ordering, leaving chainConfig and CHAIN
entries unchanged).
- Around line 56-63: The loop currently adds curatorFee to
dailySupplySideRevenue whenever fee > 0, but the requirement is to sum
dailyCuratorFeeInUsd only when it's positive; update the logic in the loop that
iterates over markets (where fee = Number(market.metrics?.dailyFeeInUsd ?? 0)
and curatorFee = Number(market.metrics?.dailyCuratorFeeInUsd ?? 0)) to only call
dailySupplySideRevenue.addUSDValue(curatorFee) when curatorFee > 0 (in addition
to the existing fee > 0 check), ensuring both dailyFees.addUSDValue(fee) and
dailySupplySideRevenue.addUSDValue(curatorFee) respect their own positivity
checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e385c25d-2895-4268-b606-e2c556d499af

📥 Commits

Reviewing files that changed from the base of the PR and between b7356cb and ce3ad62.

📒 Files selected for processing (2)
  • dexs/napier/index.ts
  • fees/napier/index.ts

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