Add XOXNO Lending yield adapter (Stellar + MultiversX) - #2753
Add XOXNO Lending yield adapter (Stellar + MultiversX)#2753mihaieremia wants to merge 11 commits into
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review. 📝 WalkthroughWalkthroughA XOXNO lending adaptor fetches per-chain exports, converts hub and spoke markets into DeFiLlama pool objects, validates hub numeric fields, and updates routing-only row filtering for ChangesXOXNO Lending Adaptor
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change adds XOXNO Stellar lending yield pools through the existing adapter pipeline with bounded requests, response validation, and filtering of routing-only records. No actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant apy
participant getExport
participant XOXNO_API as XOXNO Lending API
participant triggerAdaptor
apy->>getExport: request configured chain export
getExport->>XOXNO_API: fetch export with timeout and User-Agent
XOXNO_API-->>getExport: return JSON lending data
getExport-->>apy: provide market export
apy->>apy: normalize hub and spoke markets
apy-->>triggerAdaptor: return yield and routing_reserve pools
triggerAdaptor->>triggerAdaptor: filter routing-only rows for xoxno-lending
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Error while running xoxno-lending adapter: Test Suites: 1 failed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/adaptors/xoxno-lending/index.js (1)
34-43: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winConsider reusing shared
utils.keepFiniteto avoid over-filtering.This local filter is stricter than the repository’s shared contract and can exclude valid pools when optional fields are missing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/adaptors/xoxno-lending/index.js` around lines 34 - 43, The local keepFinite function is unnecessarily strict and filters out valid pools. Instead of checking all seven fields with every(), use the shared utils.keepFinite utility that already exists in the repository. Replace the local keepFinite function implementation with a call to the shared utils.keepFinite function to align with the repository's standard filtering logic and avoid excluding valid pools when optional fields are missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/adaptors/xoxno-lending/index.js`:
- Around line 30-31: The return statement that returns data.markets ?? [] does
not properly validate that markets is actually an array before returning it,
which allows non-array values to be passed through and causes runtime errors
when the result is iterated at line 55. Replace the return statement with a
guard that explicitly checks if data.markets is an array using Array.isArray,
returning the markets array if it passes the check or an empty array otherwise,
to ensure the function always returns a valid array for iteration.
- Around line 21-24: The getMarkets function's fetch call lacks a timeout
mechanism, which can cause the adaptor to hang if upstream services are slow or
unresponsive. Add an AbortSignal with a 5000 millisecond timeout to the fetch
options by including a signal property that uses AbortSignal.timeout(5000) in
the fetch configuration object, similar to the pattern used in
evaa-protocol/getPrices.js.
---
Nitpick comments:
In `@src/adaptors/xoxno-lending/index.js`:
- Around line 34-43: The local keepFinite function is unnecessarily strict and
filters out valid pools. Instead of checking all seven fields with every(), use
the shared utils.keepFinite utility that already exists in the repository.
Replace the local keepFinite function implementation with a call to the shared
utils.keepFinite function to align with the repository's standard filtering
logic and avoid excluding valid pools when optional fields are missing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5c9847ba-c602-47ce-a631-4829e1dc30ea
📒 Files selected for processing (1)
src/adaptors/xoxno-lending/index.js
d5aa68c to
906795d
Compare
|
Error while running xoxno-lending adapter: Test Suites: 1 failed, 1 total |
906795d to
18b20e9
Compare
|
Error while running xoxno-lending adapter: Test Suites: 1 failed, 1 total |
18b20e9 to
909e58d
Compare
|
Update: the adapter now exports protocolId |
|
Error while running xoxno-lending adapter: Test Suites: 1 failed, 1 total |
909e58d to
7e7d2a4
Compare
|
Error while running xoxno-lending adapter: Test Suites: 1 failed, 1 total |
- protocolId 8049 -> 8109 (the registered xoxno-lending DefiLlama protocol); fixes the 'protocolId matching its protocol slug' test. - Read the export's hubMarkets (per hub/asset, with APY) and spokeMarkets (per spoke/hub/asset). Hub pools carry the yield with poolMeta = hub name (Core/RWA). Spoke reserves emit as poolKind 'routing_reserve' with poolMeta 'hub / spoke', LTV, borrowability and per-spoke debt but no APY, mirroring Aave V4's Core / <spoke> layer. - Deep-link each pool to its XOXNO page (hub + spoke/hub/asset).
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/adaptors/xoxno-lending/index.js`:
- Around line 66-86: Add a utilization field to each normalized pool created in
the hubMarkets loop, using the API utilization value when available or deriving
it from supplied and borrowed totals. Normalize the result to percentage points,
consistent with the existing apyBase and apyBaseBorrow fields.
- Around line 89-120: Update the xoxno-lending ingestion path around the
routing_reserve pools created from spokeMarkets so these rows are not removed by
triggerAdaptor’s all-null APY filter. Preserve routing-reserve metadata and
ensure the downstream contract explicitly retains these APY-less pools, or stop
emitting them if persistence cannot support them; do not leave rows that are
guaranteed to be discarded.
- Around line 129-134: Update the protocolId field in the exported XOXNO Lending
adapter configuration to use the registered value 8049 instead of 8109; leave
the surrounding apy, timetravel, and url fields unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e1475f47-7e8a-4e22-a0d0-ab7828edba41
📒 Files selected for processing (1)
src/adaptors/xoxno-lending/index.js
Mirror the aave-v4/euler-v2/exactly treatment: routing_collateral and routing_reserve pools carry no APY, so without an allowlist entry they are dropped by the all-APY-null filter and never reach the pools table. Add xoxno-lending so its Aave-V4-style spoke reserves survive ingestion.
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
|
converting this into a draft as no tvl adapter and appears to be on stellar testnet |
Thanks, will re convert once mainnet is deployed. This was a test commit to see if we pass the workflows 🫡 |
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
Left over from the Dune prototype this adapter was derived from; it is not a Dune client. Also re-runs CI against the current API, whose token metadata now resolves mainnet contract ids — the previous run predates that cutover and reported testnet markets with testnet symbols.
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
Reverts the previous rename. api.xoxno.com expects this specific User-Agent for API access; it is not a descriptive label. Commented so it is not changed again.
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
@0xkr3p the mainnet has been deployed, besides this PR I have few more DefiLlama/DefiLlama-Adapters#20743 and DefiLlama/dimension-adapters#9041 🙏 |
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
…liquidity MultiversX is a flat market model: rates and risk params share a row, so there is no routing layer and each market is an ordinary yield pool. It is listed under CHAIN 'Elrond', the name in api.llama.fi/chains; 'MultiversX' is not a valid chain name and fails the adapter test. Two fixes to the existing Stellar pools: - Spoke availableBorrowUsd was borrow-cap headroom, which routinely exceeds the liquidity actually present: the XLM spoke advertised $5.25M against $1.5K of hub cash. It is now min(cap headroom, hub cash), as Aave does. - token is set to null explicitly on hub pools. Positions are NFTs rather than per-market receipt tokens, so no 1:1 pool token exists, and the handler's fallback only recognises 0x addresses. Also drops an API base-URL env override that nothing sets.
097402e to
46a6fdc
Compare
|
The xoxno-lending adapter exports pools: Test Suites: 1 passed, 1 total |
The comment builder slices from "Test Suites:" onward, on the assumption that afterTests.js output follows the jest summary. afterTests.js is a jest globalTeardown writing to stdout, while jest buffers its reporter output and writes it to stderr, so the order is not guaranteed. Since CI was pinned to Node 24 (8e1fecb) the pool block is flushed first and the slice drops it: every adapter PR comment since has shown the test counts with an empty pool list. Anchoring on "Nb of pools:" instead is not enough. Between that line and the summary sits jest's per-test output -- 685 lines and 97KB on this adapter -- which pushes the comment past GitHub's 65536-character limit, so it fails to post at all. The pool block is therefore cut at the first reporter marker and stitched onto the summary, and capped like the failure detail already is. Verified against a real CI log and a local run, i.e. both orderings: Node 24 order 10216 chars, table + summary local order 6791 chars, table + summary both within the limit, against 3644 chars with no table today. The failure path is unchanged.
|
The xoxno-lending adapter exports pools: Nb of pools: 96 |
XOXNO Lending is an overcollateralized lending protocol on MultiversX and Stellar.
This PR adds the yield pools for both chains, with supply and borrow APYs, LTV and available liquidity. On Stellar the rates live on shared hubs and the risk parameters on isolated spokes, so spokes are emitted as routing rows like aave-v4 does. MultiversX is a flat market model, so each market is a normal pool.
It also fixes two things on the Stellar side: available borrow was reporting the borrow cap instead of the liquidity actually in the pool, and the pool token is now set explicitly since positions are NFTs rather than receipt tokens.
The second commit fixes the pool table in adapter PR comments, which has been empty for every adapter since CI moved to Node 24. It is unrelated to XOXNO and easy to drop if you would rather take it separately, but it cannot be tested on its own: a PR touching only the workflow runs no adapter and posts no comment. The comment on this PR shows it working.