back to docs
contributions

chainfees-1

My first set of multi-chain fee tracking contributions: 4 chains using Blockscout API, submitted in rapid succession.

  • Type: Chain-level fees
  • Pattern: blockscoutFeeAdapter2 (centralized config)
  • Submitted: January 2-3, 2026
  • Chains: NEO X Mainnet, Bitkub (KUB), Vana, Shibarium
Status

All 4 PRs merged, January 3, 2026

Success rate: 4/4 (100%)

Reviewer: noateden

1. Background story

a. Rapid succession strategy

After completing individual protocol adapters (AquaBank, HunnySwap), I shifted to chain-level fees. I noticed many new chains use Blockscout explorers with the same API structure.

The approach:

  • Research chains with Blockscout explorers
  • Implement one chain at a time
  • Submit PR immediately after testing
  • Move to next chain while previous PR is in review
  • Result: 4 PRs submitted within hours

This wasn’t a planned “batch”. I was researching and implementing simultaneously, submitting each as I completed it.

b. Why this worked

Pattern recognition:

  • DefiLlama has blockscoutFeeAdapter2 helper
  • Same implementation pattern across chains
  • Only need to add config, not write logic
  • Quick to verify and test (~10 min per chain)

Research flow:

1
Find chain with Blockscout explorer

Search for new chains that use Blockscout as their block explorer.

2
Get CoinGecko token ID

Look up the chain’s native token on CoinGecko to get the correct token ID for pricing.

3
Add config to helpers/blockscoutFees.ts

Add the chain configuration with explorer URL and CoinGecko token ID to the centralized config file.

4
Add chain enum to helpers/chains.ts

If the chain doesn’t exist, add it to the chains enum.

5
Create 4-line adapter file

Create the minimal adapter file that uses blockscoutFeeAdapter2 with the chain config.

6
Test locally and submit PR

Run local tests to verify data fetching works, then submit the pull request.

7
Research next chain while waiting

Don’t wait idle. Start researching the next chain while the PR is under review.

2. The chains

a. NEO X Mainnet

Status

PR: #5480

Status: Merged

Merged: January 3, 2026

Implementation:

File: fees/neo-x-mainnet.ts (6 lines)

import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";


export default blockscoutFeeAdapter2(CHAIN.NEO_X_MAINNET);

Chain config added to helpers/blockscoutFees.ts:

[CHAIN.NEO_X_MAINNET]: {
  CGToken: "gas",
  explorer: "https://xexplorer.neo.org/"
},

Chain enum added to helpers/chains.ts:

NEO_X_MAINNET = "neo_x_mainnet",

Test results:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees neo-x-mainnet.ts

🦙 Running NEO-X-MAINNET.TS adapter 🦙
---------------------------------------------------
Start Date:	Fri, 02 Jan 2026 00:00:00 GMT
End Date:	Sat, 03 Jan 2026 00:00:00 GMT
---------------------------------------------------

NEO_X_MAINNET 👇
Daily fees: 3.00
End timestamp: 1767312000 (2026-01-02T00:00:00.000Z)

Issues: None, clean merge

Key notes:

  • NEO X uses “gas” as native token (CoinGecko ID)
  • Blockscout explorer
  • Ultra-clean 4-line implementation

b. Bitkub Chain (KUB)

Status

PR: #5485

Status: Merged (after clarification)

Merged: January 3, 2026

Issue: Chain identifier confusion

Implementation:

File: fees/kub.ts (4 lines)

import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";

export default blockscoutFeeAdapter2(CHAIN.KUB);

Chain config added to helpers/blockscoutFees.ts:

[CHAIN.KUB]: {
  CGToken: 'bitkub-coin',
  explorer: 'https://www.kubscan.com/'
},

Chain enum added to helpers/chains.ts:

KUB = "kub",

The issue:

Reviewer noateden questioned:

“is this chain kub or bitkub? they are two difference chains.”

The problem:

  • DefiLlama has two different chains: kub and bitkub
  • Bitkub Chain rebranded to KUB Chain
  • But in DefiLlama system, both identifiers exist

My response:

I provided evidence of the rebranding:

“Bitkub Chain is now KUB Chain due to rebranding”

Reference: https://support.bitkub.com/hc/en-us/articles/9687614585113-Bitkub-Chain-is-now-KUB-Chain

Resolution:

  • Used CHAIN.KUB identifier
  • CoinGecko token: bitkub-coin
  • Explorer: kubscan.com (not bkcscan.com)
  • Maintained backward compatibility

Test results:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees kub.ts

🦙 Running KUB.TS adapter 🦙
---------------------------------------------------
Start Date:	Fri, 02 Jan 2026 00:00:00 GMT
End Date:	Sat, 03 Jan 2026 00:00:00 GMT
---------------------------------------------------

error fetching block Error: Last block for kub is 6366 minutes behind
[... RPC provider warnings ...]

KUB 👇
Daily fees: 230.00
End timestamp: 1767312000 (2026-01-02T00:00:00.000Z)

Despite RPC warnings, fee data was successfully fetched from Blockscout API.

Key Learning:

When chains rebrand:

1
Check if old identifier exists

Search DefiLlama’s codebase to see if the old chain identifier is still being used.

2
Verify which identifier to use

Determine whether to use the old identifier, new identifier, or if both are maintained separately.

3
Provide documentation links

Include official documentation or announcements about the rebranding to support your decision.

4. Verify CoinGecko token ID matches the chain

c. Vana

Status

PR: #5486

Status: Merged

Merged: January 3, 2026

Implementation:

File: fees/vana.ts (4 lines)

import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";

export default blockscoutFeeAdapter2(CHAIN.VANA);

Chain config added to helpers/blockscoutFees.ts:

[CHAIN.VANA]: {
  CGToken: 'vana',
  explorer: 'https://vanascan.io/'
},

Test results:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees vana.ts

🦙 Running VANA.TS adapter 🦙
---------------------------------------------------
Start Date:	Fri, 02 Jan 2026 00:00:00 GMT
End Date:	Sat, 03 Jan 2026 00:00:00 GMT
---------------------------------------------------

VANA 👇
Daily fees: 9.00
End timestamp: 1767312000 (2026-01-02T00:00:00.000Z)

Issues: None, clean merge

Key notes:


d. Shibarium

Status

PR: #5487

Status: Merged

Merged: January 3, 2026

Implementation:

File: fees/shibarium.ts (4 lines)

import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";

export default blockscoutFeeAdapter2(CHAIN.SHIBARIUM);

Chain config added to helpers/blockscoutFees.ts:

[CHAIN.SHIBARIUM]: {
  CGToken: 'bone-shibaswap',
  explorer: 'https://shibariumscan.io/'
},

Test Results:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees shibarium.ts

🦙 Running SHIBARIUM.TS adapter 🦙
---------------------------------------------------
Start Date:	Fri, 02 Jan 2026 00:00:00 GMT
End Date:	Sat, 03 Jan 2026 00:00:00 GMT
---------------------------------------------------

SHIBARIUM 👇
Daily fees: 4.00
End timestamp: 1767312000 (2026-01-02T00:00:00.000Z)

Issues: None, clean merge

Key notes:

  • Shibarium is Shiba Inu’s L2 chain
  • Uses shibariumscan.io (Blockscout)
  • CoinGecko token ID: bone-shibaswap (BONE token)
  • Standard implementation

3. The common pattern

a. blockscoutFeeAdapter2 structure

All 4 chains use the same ultra-clean pattern:

Step 1: Create adapter file (4 lines!)

// fees/{chain}.ts
import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";

export default blockscoutFeeAdapter2(CHAIN.{CHAIN_NAME});

Step 2: Add config to helpers/blockscoutFees.ts

[CHAIN.{CHAIN_NAME}]: {
  CGToken: '{coingecko-id}',
  explorer: 'https://{explorer-url}/'
},

Step 3: Add chain enum to helpers/chains.ts

{CHAIN_NAME} = "{chain_name}",

That’s it! 3 steps, minimal code.

b. How blockscoutFeeAdapter2 works

Centralized configuration approach:

  • Explorer URLs stored in one place (helpers/blockscoutFees.ts)
  • CoinGecko token mappings centralized
  • Adapter files are ultra-clean (4 lines!)

How it works internally:

1
Read config from chainConfigMap

The adapter reads the chain’s explorer URL and CoinGecko token ID from the centralized config.

2
Construct API URL

Builds the Blockscout API endpoint: {explorer}/api?module=stats&action=totalfees&date={date}

3
Fetch daily fee data

Makes a request to the Blockscout JSON API to get the day’s total fees.

4
Convert from wei to token units

Divides the raw wei value by 1e18 to get the actual token amount.

5
Convert to USD using CoinGecko

Fetches the token price from CoinGecko and calculates the USD value.

6
Return dailyFees and dailyRevenue

Returns the final metrics in the standardized format.

The API endpoint:

https://{explorer}/api?module=stats&action=totalfees&date=2026-01-05

Returns JSON like:

{
  "message": "OK",
  "result": "3311212584000000000",
  "status": "1"
}

The result is total fees in wei (smallest unit).

c. Why I chose this pattern

Simple and fast:

  • Only 4 lines per adapter
  • Just add chain config once
  • No need to look up API URLs every time
  • Quick to verify and test

Why Blockscout specifically:

  • Many new chains use Blockscout explorers
  • All have the same API endpoint structure
  • Easy to identify (Blockscout branding in footer)
  • Reliable fee data already aggregated via API

The workflow is quick:

1
Find chain with Blockscout

Search for chains using Blockscout explorers. Time: ~2 minutes

2
Get CoinGecko token ID

Look up the native token on CoinGecko. Time: ~1 minute

3
Add config + create adapter

Add chain config and create the 4-line adapter file. Time: ~5 minutes

4
Test locally

Run the test suite to verify data fetching. Time: ~2 minutes

5
Submit PR

Push changes and create pull request. Time: ~1 minute

Total: ~10 minutes per chain. That’s why I could do 4 chains in a few hours.

d. When to use this pattern

Perfect for:

  • Chain has Blockscout explorer
  • Explorer has /api?module=stats&action=totalfees endpoint
  • Standard fee tracking (no custom logic needed)
  • Chain already on CoinGecko with known ID

How to identify Blockscout chains:

1
Visit chain's explorer

Navigate to the blockchain explorer website.

2
Check footer for Blockscout branding

Scroll to the bottom and look for “Powered by Blockscout” or similar branding.

3
Test the API endpoint

Try accessing: {explorer}/api?module=stats&action=totalfees&date={today}

4
Verify JSON response

If JSON returns with a result field containing fee data → use blockscoutFeeAdapter2

Example Blockscout URLs:

4. Submission results

a. Timeline

January 2-3, 2026:

  • Researching chains with Blockscout
  • Implemented first chain → submitted PR #5480 (NEO X)
  • While waiting, researched next chain
  • Implemented second chain → submitted PR #5485 (KUB)
  • Continued pattern for remaining 2 chains
  • All submitted within hours of each other
  • llamabutler ran automated tests on each

January 3, 2026:

  • Reviewer noateden checked all 4 PRs
  • Raised question on Bitkub chain identifier
  • I clarified with documentation
  • All 4 PRs merged same day

b. Efficiency metrics

MetricResult
PRs submitted4
Time windowSeveral hours (sequential)
PRs merged4/4 (100%)
Issues found1 (Bitkub identifier clarification)
Time to merge~1 day
Lines of code per adapter4-6 lines
Total lines added~24 lines for 4 chains

Key insight: Rapid succession works when:

  • Pattern is proven (blockscoutFeeAdapter2)
  • Implementation is ultra-simple (~10 min each)
  • Can research and code simultaneously
  • Submit as you go, don’t wait

5. Comparison with previous contributions

a. Individual vs rapid succession

Previous (Individual):

  • AquaBank: Custom wallet tracking, 3 commits
  • HunnySwap: DEX fees, folder issue, refactored
  • OpenTrade: Multi-chain vaults, 3 issues fixed
  • One at a time, wait for merge before next

Chain Fees Set 1 (Rapid Succession):

  • 4 chains, same pattern
  • Research → Implement → Submit → Repeat
  • Don’t wait for merge, keep moving
  • Ultra-clean code (4 lines per adapter)
  • All merged same day

b. Evolution

Individual complex protocols (slow, many iterations)
              ↓
Recognizing patterns
              ↓
Rapid succession (research + implement simultaneously)

This shows:

  • Pattern recognition (blockscoutFeeAdapter2)
  • Efficient workflow (don’t wait for reviews)
  • Understanding of what’s “safe to submit rapidly”

6. Key learnings

a. When to submit rapidly

Good for rapid succession:

  • Same implementation pattern
  • Ultra-low complexity (~4 lines per adapter)
  • Independent changes (no conflicts)
  • Proven helper (already used successfully)

Don’t submit rapidly:

  • Different patterns per PR
  • Complex implementations
  • Untested approaches
  • High risk of issues

The workflow:

  1. Research chain A → Implement → Test → Submit PR
  2. While PR in review, research chain B
  3. Implement chain B → Test → Submit PR
  4. Repeat, don’t wait for merges
  5. Respond to questions as they come

b. Chain identifier verification

Key lesson from Bitkub:

Always verify:

  1. Does chain exist in helpers/chains.ts?
  2. Are there multiple similar identifiers? (kub vs bitkub)
  3. Has chain rebranded recently?
  4. Which identifier does DefiLlama use?
  5. What’s the correct CoinGecko token ID?

How to check:

# Search existing chains
grep -r "CHAIN.KUB" helpers/chains.ts
grep -r "CHAIN.BITKUB" helpers/chains.ts

# Check live data
https://defillama.com/chain/{chain-name}

# Verify CoinGecko ID
https://www.coingecko.com/en/coins/{token-id}

c. Documentation matters

When reviewer questions your choice:

  • Provide official documentation
  • Link to rebranding announcements
  • Reference existing usage in codebase
  • Don’t just assert without evidence

My Bitkub response was effective because:

  • Quoted official support article
  • Explained rebranding clearly
  • Showed why KUB was correct choice

d. CoinGecko token IDs

Key mappings learned:

ChainNative TokenCoinGecko ID
NEO XGASgas
KUBKUBbitkub-coin
VanaVANAvana
ShibariumBONEbone-shibaswap

How to find CoinGecko ID:

  1. Go to https://www.coingecko.com
  2. Search for chain’s native token
  3. Check URL: /en/coins/{this-is-the-id}
  4. Use that ID in config

7. Technical details

a. The blockscoutFeeAdapter2 helper

Internal structure (simplified):

export function blockscoutFeeAdapter2(chain: CHAIN) {
  const config = chainConfigMap[chain];

  return {
    fetch: async (options) => {
      const dateString = options.dateString; // e.g., "2026-01-05"
      const url = `${config.explorer}api?module=stats&action=totalfees&date=${dateString}`;

      const response = await httpGet(url);
      const feesInWei = response.result; // e.g., "3311212584000000000"
      const feesInTokens = feesInWei / 1e18; // Convert from wei

      const tokenPrice = await getCoinGeckoPrice(config.CGToken, dateString);
      const usdValue = feesInTokens * tokenPrice;

      return {
        dailyFees: usdValue,
        dailyRevenue: usdValue,
      };
    }
  };
}

The chainConfigMap:

const chainConfigMap: Record<CHAIN, ChainConfig> = {
  [CHAIN.NEO_X_MAINNET]: {
    CGToken: "gas",
    explorer: "https://xexplorer.neo.org/"
  },
  [CHAIN.KUB]: {
    CGToken: 'bitkub-coin',
    explorer: 'https://www.kubscan.com/'
  },
  // ... more chains
};

b. Adding new chains, step by step

1. Find chain with Blockscout:

  • Visit explorer
  • Look for Blockscout branding
  • Test API endpoint: /api?module=stats&action=totalfees&date={date}

2. Get CoinGecko token ID:

  • Search token on CoinGecko
  • Note the ID from URL

3. Add chain enum:

// helpers/chains.ts
export enum CHAIN {
  // ... existing
  YOUR_CHAIN = "your_chain",
}

4. Add config:

// helpers/blockscoutFees.ts
[CHAIN.YOUR_CHAIN]: {
  CGToken: 'your-coingecko-id',
  explorer: 'https://your-explorer.com/'
},

5. Create adapter:

// fees/your-chain.ts
import { blockscoutFeeAdapter2 } from "../helpers/blockscoutFees";
import { CHAIN } from "../helpers/chains";

export default blockscoutFeeAdapter2(CHAIN.YOUR_CHAIN);

6. Test locally:

pnpm test fees your-chain

7. Submit PR!

8. Statistics

a. Rapid succession performance

Submission efficiency:

  • 4 adapters written and submitted within hours
  • Average ~10 minutes per adapter (research + implement)
  • 100% merge rate
  • 1 clarification needed (25% question rate)

Code efficiency:

  • ~4-6 lines per adapter file
  • ~1 line per chain config
  • ~1 line per chain enum
  • Total: ~24 lines for 4 chains
  • Reused pattern: blockscoutFeeAdapter2

Workflow efficiency:

  • Research while waiting for reviews
  • Submit as you complete (don’t batch)
  • Parallel research + sequential submission

b. Chain coverage added

After this set, DefiLlama now tracks fees for:

  • NEO X Mainnet (gas token)
  • KUB Chain (bitkub-coin)
  • Vana (vana token)
  • Shibarium (bone-shibaswap)

All now visible on DefiLlama’s chain dashboards!

9. Resources

a. PRs

b. Chain explorers

c. Documentation

10. Key takeaways

a. What worked well

  1. Pattern recognition. Identified blockscoutFeeAdapter2 helper
  2. Ultra-clean code. 4 lines per adapter
  3. Rapid succession. Submitted in hours, all merged same day
  4. Centralized config. Explorer URLs and tokens in one place
  5. Quick clarification. Responded to Bitkub question with docs

b. What I learned

  1. blockscoutFeeAdapter2 pattern. Cleaner than etherscanFeeAdapter
  2. Chain identifiers matter. Check for rebranding and duplicates
  3. CoinGecko ID verification. Critical for USD conversion
  4. Rapid succession works. When pattern is proven and simple

c. Process improvements

Before rapid submissions:

  • Verify chain identifier doesn’t conflict
  • Check for rebranding history
  • Get correct CoinGecko token ID
  • Test API endpoint manually
  • Run local test before submitting

d. The pattern

Identify Blockscout chains
       ↓
Research chain A → Add config → Create adapter → Test → Submit
       ↓
Research chain B (while A in review) → Add config → Create adapter → Test → Submit
       ↓
Research chain C (while A,B in review) → Add config → Create adapter → Test → Submit
       ↓
Respond quickly to questions
       ↓
All merged efficiently

Not batch. A continuous flow of research → implement → submit.

11. Comparison with previous contributions

This is my first rapid succession submission. Previously:

  • All contributions were individual
  • Each PR had unique implementation
  • Waited for merge before next contribution

Chain Fees Set 1:

  • 4 PRs submitted within hours (one after another)
  • Same ultra-clean pattern across all
  • Don’t wait. Submit and move to next
  • 100% success rate

Key difference: Moving from “wait for review” to “continuous flow of research + submit.”

This shows growth from:

  • Contributor → executing individual tasks, waiting for feedback
  • Pattern recognizer → identifying reusable approaches (blockscoutFeeAdapter2)
  • Efficient contributor → continuous research & submission flow

First multi-chain rapid submission: 100% success

All 4 chain fee adapters merged in one day with minimal review needed. This demonstrates:

  • Pattern recognition ability (blockscoutFeeAdapter2)
  • Efficient workflow (research while waiting)
  • Ultra-clean code (4 lines per adapter)
  • Quick response to clarifications

From individual protocols (wait for merge) to rapid succession (research + submit continuously). This is what efficient contribution workflow looks like!

Command Palette
Search for a command to run...