Skip to content

Linx refactor#17928

Merged
waynebruce0x merged 6 commits intoDefiLlama:mainfrom
RohanNero:linx-refactor
Feb 11, 2026
Merged

Linx refactor#17928
waynebruce0x merged 6 commits intoDefiLlama:mainfrom
RohanNero:linx-refactor

Conversation

@RohanNero
Copy link
Contributor

@RohanNero RohanNero commented Feb 4, 2026

May resolve #17790

  • added borrowed export
  • count supply tvl as loan tokens inside the markets instead of totalSupplyAssets value from market state function call (i.e. totalSupplyAssets - totalBorrowAssets)
  • removed local token mapping object; added tokens to fixBalancesTokens in helper/tokenMapping.js

Summary by CodeRabbit

  • New Features
    • Added support for the Alephium blockchain network.
    • Enabled token balance tracking for wrapped-bitcoin, USD Coin, and Tether on Alephium.
    • Added treasury metrics computation for Alephium, including total value locked (TVL) and borrowed amounts.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds Alephium token address mappings to fixBalancesTokens and a new Linx Alephium adapter implementing tvl and borrowed functions that fetch MARKET_CREATED events, derive markets, and aggregate token balances and borrowings via Alephium node API and contract multicalls.

Changes

Cohort / File(s) Summary
Token Mapping Configuration
projects/helper/tokenMapping.js
Adds alephium entry to fixBalancesTokens with three address→token mappings: wrapped-bitcoin (decimals 8), usd-coin (6), tether (6).
Linx TVL Module
projects/linx/index.js
New Alephium adapter exporting alephium.tvl(api) and alephium.borrowed(api). Implements paginated getEvents, derives markets from MARKET_CREATED events, fetches ALPH vs token balances, and uses contract multicall to compute borrowed amounts; reports via api.add.

Sequence Diagram(s)

sequenceDiagram
    participant Consumer as Consumer/API
    participant Linx as Linx Module
    participant AlephiumAPI as Alephium Node API
    participant SmartContracts as Smart Contracts

    Consumer->>Linx: tvl(api)
    activate Linx
    Linx->>AlephiumAPI: getEvents(MARKET_CREATED_EVENT_INDEX) [paginated]
    AlephiumAPI-->>Linx: market creation events
    Linx->>Linx: derive markets list

    loop for each market
        Linx->>AlephiumAPI: getTokenBalance(contractId, collateralToken)
        AlephiumAPI-->>Linx: collateral balance
        Linx->>AlephiumAPI: getTokenBalance(contractId, loanToken)
        AlephiumAPI-->>Linx: loan balance
    end

    Linx->>Consumer: api.add(tokenId, totalAmount)
    deactivate Linx

    Consumer->>Linx: borrowed(api)
    activate Linx
    Linx->>AlephiumAPI: getEvents(MARKET_CREATED_EVENT_INDEX)
    AlephiumAPI-->>Linx: market creation events

    loop for each market
        Linx->>SmartContracts: contractMultiCall(borrowAssets)
        SmartContracts-->>Linx: borrow amounts per token
    end

    Linx->>Consumer: api.add(tokenId, totalBorrowedAmount)
    deactivate Linx
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Linx refactor #17928 — Adds the same Alephium token mappings in projects/helper/tokenMapping.js and introduces the identical projects/linx/index.js Alephium exports (tvl and borrowed).

Poem

🐇 I hop through nodes and event streams bright,
Three tokens tucked in Alephium's night,
Linx counts vaults with careful cheer,
Balances and borrows now appear,
A rabbit nods — the ledger's right.

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive Title 'Linx refactor' is vague and generic; it does not clearly convey the specific changes made (adding borrowed export, TVL calculation changes, token mapping updates). Use a more descriptive title like 'Linx: Add borrowed export and refactor TVL calculation' to better communicate the main changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed PR description provides specific context for the changes (borrowed export, TVL calculation method, token mapping removal) but does not follow the template structure for new protocol additions.
Linked Issues check ✅ Passed Code changes implement the core requirements from #17790: TVL tracking for Linx on Alephium, token mappings added, and borrowed export added to match the current exports mentioned in reviewer comments.
Out of Scope Changes check ✅ Passed All changes align with linked issue #17790 objectives: token mappings in fixBalancesTokens, new index.js module for Alephium with tvl and borrowed functions, and TVL calculation refactoring as described.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 adapter at projects/linx exports TVL:

alephium                  82.18 k
alephium-borrowed         21.94 k
borrowed                  21.94 k

total                    82.18 k 

@llamabutler
Copy link

The adapter at projects/linx exports TVL:

alephium                  83.67 k
alephium-borrowed         22.75 k
borrowed                  22.75 k

total                    83.67 k 

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@projects/linx/index.js`:
- Around line 14-26: The loop in getEvents can hang if the API returns a
nextStart that doesn't advance or returns empty events; after each fetch (in
getEvents) add explicit guards: if response.events is empty break; if
response.nextStart is undefined break; and if response.nextStart <= start break;
optionally also add a safety counter (e.g., maxIterations) to force-break after
N iterations to protect against API bugs. Ensure you reference and update the
local start variable only when nextStart is a valid, strictly greater value.
🧹 Nitpick comments (2)
projects/linx/index.js (2)

54-62: Consider caching token balances per market to avoid duplicate RPC calls.
Right now, getTokensBalance can be called twice per market (collateral + loan). A per-market cache reduces network overhead.

♻️ Example refactor
 async function tvl(api) {
     const markets = await getMarkets();
     for (const market of markets) {
-        const collateral = await getTokenBalance(market.contractId, market.collateralTokenId);
-        const loanBalance = await getTokenBalance(market.contractId, market.loanTokenId);
+        const contractAddress = alephium.addressFromContractId(market.contractId);
+        const [alphBalance, tokensBalance] = await Promise.all([
+            alephium.getAlphBalance(contractAddress),
+            alephium.getTokensBalance(contractAddress),
+        ]);
+        const getBalance = (tokenId) =>
+            tokenId === ALPH_TOKEN_ID
+                ? BigInt(alphBalance.balance)
+                : BigInt(tokensBalance.find(b => b.tokenId === tokenId)?.balance ?? 0);
+        const collateral = getBalance(market.collateralTokenId);
+        const loanBalance = getBalance(market.loanTokenId);
         api.add(market.collateralTokenId, collateral);
         api.add(market.loanTokenId, loanBalance);
     }
 }

64-76: Batch multicalls for improved node efficiency.
Currently calling contractMultiCall once per market. Batching all calls (as shown in alphpad and alphbanx adapters) reduces node requests. The hardcoded group: 0 and MARKET_METHOD_INDEX are consistent with Alephium adapter patterns and appear correct, but confirm the method index matches the Linx contract ABI if the contract is updated.

♻️ Example batching approach
 async function borrowed(api) {
     const markets = await getMarkets();
-    for (const market of markets) {
-        const state = await alephium.contractMultiCall([{
-            group: 0,
-            address: config.linx,
-            methodIndex: MARKET_METHOD_INDEX,
-            args: [{ type: "ByteVec", value: market.marketId }]
-        }]);
-        const borrowAssets = BigInt(state[0].returns[2].value);
-        api.add(market.loanTokenId, borrowAssets);
-    }
+    const calls = markets.map(market => ({
+        group: 0,
+        address: config.linx,
+        methodIndex: MARKET_METHOD_INDEX,
+        args: [{ type: "ByteVec", value: market.marketId }],
+    }));
+    const states = await alephium.contractMultiCall(calls);
+    states.forEach((state, i) => {
+        const borrowAssets = BigInt(state.returns[2].value);
+        api.add(markets[i].loanTokenId, borrowAssets);
+    });
 }

Comment on lines +14 to +26
async function getEvents(contractAddress) {
let events = [];
let start = 0;
const limit = 100;

while (true) {
const response = await get(`${config.nodeApiHost}/events/contract/${contractAddress}?start=${start}&limit=${limit}`);
events = events.concat(response.events);
if (!response.events.length || response.nextStart === undefined) break;
start = response.nextStart;
}
return events;
}
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

Add a pagination safety guard to prevent infinite loops.
If nextStart fails to advance (API bug or edge case), the loop never terminates. Guard against nextStart <= start and missing events.

🔧 Suggested fix
     while (true) {
         const response = await get(`${config.nodeApiHost}/events/contract/${contractAddress}?start=${start}&limit=${limit}`);
-        events = events.concat(response.events);
-        if (!response.events.length || response.nextStart === undefined) break;
-        start = response.nextStart;
+        const nextStart = response?.nextStart;
+        const pageEvents = response?.events ?? [];
+        events = events.concat(pageEvents);
+        if (!pageEvents.length || nextStart === undefined || nextStart <= start) break;
+        start = nextStart;
     }
🤖 Prompt for AI Agents
In `@projects/linx/index.js` around lines 14 - 26, The loop in getEvents can hang
if the API returns a nextStart that doesn't advance or returns empty events;
after each fetch (in getEvents) add explicit guards: if response.events is empty
break; if response.nextStart is undefined break; and if response.nextStart <=
start break; optionally also add a safety counter (e.g., maxIterations) to
force-break after N iterations to protect against API bugs. Ensure you reference
and update the local start variable only when nextStart is a valid, strictly
greater value.

@llamabutler
Copy link

The adapter at projects/linx exports TVL:

alephium                  287.69 k
alephium-borrowed         56.90 k
borrowed                  56.90 k

total                    287.69 k 

@llamabutler
Copy link

The adapter at projects/linx exports TVL:

alephium                  287.69 k
alephium-borrowed         56.90 k
borrowed                  56.90 k

total                    287.69 k 

@waynebruce0x waynebruce0x merged commit 2119b5a into DefiLlama:main Feb 11, 2026
1 of 2 checks passed
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.

4 participants