Skip to content

Add Valdora Finance yield adapter#2746

Open
permapod-rsk wants to merge 3 commits into
DefiLlama:masterfrom
permapod-rsk:valdora-finance-yield
Open

Add Valdora Finance yield adapter#2746
permapod-rsk wants to merge 3 commits into
DefiLlama:masterfrom
permapod-rsk:valdora-finance-yield

Conversation

@permapod-rsk

@permapod-rsk permapod-rsk commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added support for the valdora-finance stZIG staking pool on ZIGChain, including full pool analytics.
    • Computes APY from on-chain annual provisions and bonded supply, factoring validator commission and applicable fee/tax parameters.
    • Provides TVL in USD using live ZIG pricing, along with price-per-share and staking pool metadata.
    • Includes a direct link to the staking page for easy access.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new adapter module for valdora-finance is added at src/adaptors/valdora-finance/index.js. It queries ZIGChain LCD data, CosmWasm contract state, and ZIG price data to compute apyBase, tvlUsd, and pricePerShare for a single stZIG pool.

Changes

valdora-finance stZIG Adapter

Layer / File(s) Summary
Configuration constants and LCD/contract helpers
src/adaptors/valdora-finance/index.js
Defines project and chain identifiers, LCD and contract endpoints, staking identifiers, numeric parameters, validator addresses, and the HTTP and CosmWasm query helpers.
Validator commission and stZIG APR computation
src/adaptors/valdora-finance/index.js
Queries validator commission rates in parallel, averages fulfilled responses, fetches annual provisions and bonded supply, and computes apyBase with the configured tax and fee reductions.
Pool valuation and adapter export
src/adaptors/valdora-finance/index.js
Fetches contract funds_raised and total_supply, retrieves ZIG price data, derives tvlUsd and pricePerShare, builds the stZIG pool object, filters finite values, and exports the adapter entrypoint.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • 0xkr3p

Poem

🐇 I hopped through LCD, quick as a breeze,
Counted validator fees and staking trees.
ZIG price sparkled, TVL came to play,
stZIG now hums in a brand-new way.
Tiny paws approve this APY display ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change by adding a new Valdora Finance yield adapter.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions

Copy link
Copy Markdown

The valdora-finance adapter exports pools:

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

Nb of pools: 1
 

Sample pools:
┌─────────┬──────────────────────────────────────────────────────────────────────────────────────┬────────────┬───────────────────┬─────────┬────────────────────┬───────────────────┬──────────────────┬─────────────────────────────────────────────────────────────────────────────┬───────────────────┬─────────────────────────────────┐
│ (index) │ pool                                                                                 │ chain      │ project           │ symbol  │ tvlUsd             │ apyBase           │ underlyingTokens │ searchTokenOverride                                                         │ isIntrinsicSource │ url                             │
├─────────┼──────────────────────────────────────────────────────────────────────────────────────┼────────────┼───────────────────┼─────────┼────────────────────┼───────────────────┼──────────────────┼─────────────────────────────────────────────────────────────────────────────┼───────────────────┼─────────────────────────────────┤
│ 0       │ 'coin.zig109f7g2rzl2aqee7z6gffn8kfe9cpqx0mjkk7ethmx8m2hq4xpe9snmaam2.stzig-zigchain' │ 'ZIGChain' │ 'valdora-finance' │ 'stZIG' │ 10719528.007030064 │ 6.335761012421651 │ [ 'uzig' ]       │ 'coin.zig109f7g2rzl2aqee7z6gffn8kfe9cpqx0mjkk7ethmx8m2hq4xpe9snmaam2.stzig' │ true              │ 'https://valdora.finance/stake' │
└─────────┴──────────────────────────────────────────────────────────────────────────────────────┴────────────┴───────────────────┴─────────┴────────────────────┴───────────────────┴──────────────────┴─────────────────────────────────────────────────────────────────────────────┴───────────────────┴─────────────────────────────────┘

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/valdora-finance/index.js`:
- Around line 30-37: The Promise.all call in the commissions calculation causes
the entire operation to fail if any single validator request fails. Replace
Promise.all with Promise.allSettled to gracefully handle individual validator
failures, then filter the results to extract only the fulfilled promises' values
before calculating the average in the reduce function. This way, transient
errors from individual validator endpoints won't cause the entire APY pipeline
to fail.
🪄 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: 6a3d7850-77e9-4199-82ef-3c4c3f41456b

📥 Commits

Reviewing files that changed from the base of the PR and between fa55861 and 5585c5a.

📒 Files selected for processing (1)
  • src/adaptors/valdora-finance/index.js

Comment thread src/adaptors/valdora-finance/index.js Outdated
@permapod-rsk

Copy link
Copy Markdown
Contributor Author

@bheluga can you please review this commit ? I'm not sure if the symbol should be the liquid staking asset (stZIG) or the native coin (Zig).

underlyingTokens: ['uzig'],
searchTokenOverride: STZIG_DENOM,
isIntrinsicSource: true,
url: 'https://valdora.finance/stake',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

add pricePerShare field

const ZIG_PRICE_KEY = 'zigchain:uzig';
const DECIMALS = 1e6;

const VALIDATORS = [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should these be hardcoded or can we get dynamically to ensure they stay up to date?

Comment thread src/adaptors/valdora-finance/index.js Outdated
const bondedZig = Number(stakingPool.pool?.bonded_tokens || 0) / DECIMALS;

if (!bondedZig) return 0;
return (annualProvisionsZig / bondedZig) * (1 - averageCommission) * 100;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should the 10% performance fee and 2% community tax be deducted or is 6.34% the APR the user will receive?

@0xkr3p

0xkr3p commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@bheluga can you please review this commit ? I'm not sure if the symbol should be the liquid staking asset (stZIG) or the native coin (Zig).

hi @permapod-rsk - yes should be stZIG

- Switch to Promise.allSettled for validator commission fetching so that
  a single unresponsive validator does not abort the entire APY pipeline;
  failed results are filtered out and the average is computed over the
  remaining ones (returns 0 if all fail)
- Deduct the 10% performance fee and the 2% community tax from the APR
  formula; the displayed APY now reflects net yield for the staker
- Add pricePerShare field by querying the exchange_rate from the staker
  contract, covering the stZIG→ZIG conversion ratio for liquid assets
- Validator addresses remain hardcoded for now: the chain does not expose
  a public endpoint to enumerate Valdora's curated validator set
The contract does not expose an exchange_rate query endpoint,
causing HTTP 500 errors. Compute pricePerShare from
funds_raised / total_supply instead.
@github-actions

Copy link
Copy Markdown

The valdora-finance adapter exports pools:

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

Nb of pools: 1
 

Sample pools:
┌─────────┬──────────────────────────────────────────────────────────────────────────────────────┬────────────┬───────────────────┬─────────┬───────────────────┬───────────────────┬────────────────────┬──────────────────┬─────────────────────────────────────────────────────────────────────────────┬───────────────────┬─────────────────────────────────┐
│ (index) │ pool                                                                                 │ chain      │ project           │ symbol  │ tvlUsd            │ apyBase           │ pricePerShare      │ underlyingTokens │ searchTokenOverride                                                         │ isIntrinsicSource │ url                             │
├─────────┼──────────────────────────────────────────────────────────────────────────────────────┼────────────┼───────────────────┼─────────┼───────────────────┼───────────────────┼────────────────────┼──────────────────┼─────────────────────────────────────────────────────────────────────────────┼───────────────────┼─────────────────────────────────┤
│ 0       │ 'coin.zig109f7g2rzl2aqee7z6gffn8kfe9cpqx0mjkk7ethmx8m2hq4xpe9snmaam2.stzig-zigchain' │ 'ZIGChain' │ 'valdora-finance' │ 'stZIG' │ 9811121.647473194 │ 5.648854418840675 │ 1.0556333543473073 │ [ 'uzig' ]       │ 'coin.zig109f7g2rzl2aqee7z6gffn8kfe9cpqx0mjkk7ethmx8m2hq4xpe9snmaam2.stzig' │ true              │ 'https://valdora.finance/stake' │
└─────────┴──────────────────────────────────────────────────────────────────────────────────────┴────────────┴───────────────────┴─────────┴───────────────────┴───────────────────┴────────────────────┴──────────────────┴─────────────────────────────────────────────────────────────────────────────┴───────────────────┴─────────────────────────────────┘

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/valdora-finance/index.js`:
- Around line 78-81: The balance handling in the Valdora Finance adaptor is
defaulting missing contract values into valid-looking numbers, which can mask
bad responses. In the logic around the fundsRaised and totalSupply calculations,
validate that `fundsRaised.funds_raised` and `totalSupply.total_supply` are
present, numeric, and positive before computing `tvlUsd` and `pricePerShare`; if
either value is missing or malformed, return null/skip instead of falling back
to 0 or 1. Update the checks in the `index.js` flow so downstream ingestion
never receives a fabricated positive ratio from `pricePerShare`.
🪄 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: b691f0fa-5e3a-4f96-b374-cacf61434620

📥 Commits

Reviewing files that changed from the base of the PR and between 13e7291 and d0409e4.

📒 Files selected for processing (1)
  • src/adaptors/valdora-finance/index.js

Comment on lines +78 to +81
const fundsRaisedValue = Number(fundsRaised.funds_raised || 0);
const totalSupplyValue = Number(totalSupply.total_supply || 1);
const tvlUsd = (fundsRaisedValue / DECIMALS) * zigPrice;
const pricePerShare = fundsRaisedValue / totalSupplyValue;

@coderabbitai coderabbitai Bot Jun 27, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate contract balances instead of defaulting missing values.

totalSupply.total_supply || 1 can publish a bogus positive pricePerShare when the contract response is missing or malformed, and fundsRaised.funds_raised || 0 can silently turn bad data into zero TVL. Since downstream only nulls non-finite/non-positive pricePerShare, this bad ratio can survive ingestion.

Suggested fix
-  const fundsRaisedValue = Number(fundsRaised.funds_raised || 0);
-  const totalSupplyValue = Number(totalSupply.total_supply || 1);
+  const fundsRaisedValue = Number(fundsRaised.funds_raised);
+  const totalSupplyValue = Number(totalSupply.total_supply);
+
+  if (!Number.isFinite(fundsRaisedValue) || fundsRaisedValue < 0) {
+    throw new Error('Invalid funds_raised contract response');
+  }
+
+  if (!Number.isFinite(totalSupplyValue) || totalSupplyValue <= 0) {
+    throw new Error('Invalid total_supply contract response');
+  }
+
   const tvlUsd = (fundsRaisedValue / DECIMALS) * zigPrice;
   const pricePerShare = fundsRaisedValue / totalSupplyValue;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fundsRaisedValue = Number(fundsRaised.funds_raised || 0);
const totalSupplyValue = Number(totalSupply.total_supply || 1);
const tvlUsd = (fundsRaisedValue / DECIMALS) * zigPrice;
const pricePerShare = fundsRaisedValue / totalSupplyValue;
const fundsRaisedValue = Number(fundsRaised.funds_raised);
const totalSupplyValue = Number(totalSupply.total_supply);
if (!Number.isFinite(fundsRaisedValue) || fundsRaisedValue < 0) {
throw new Error('Invalid funds_raised contract response');
}
if (!Number.isFinite(totalSupplyValue) || totalSupplyValue <= 0) {
throw new Error('Invalid total_supply contract response');
}
const tvlUsd = (fundsRaisedValue / DECIMALS) * zigPrice;
const pricePerShare = fundsRaisedValue / totalSupplyValue;
🤖 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/valdora-finance/index.js` around lines 78 - 81, The balance
handling in the Valdora Finance adaptor is defaulting missing contract values
into valid-looking numbers, which can mask bad responses. In the logic around
the fundsRaised and totalSupply calculations, validate that
`fundsRaised.funds_raised` and `totalSupply.total_supply` are present, numeric,
and positive before computing `tvlUsd` and `pricePerShare`; if either value is
missing or malformed, return null/skip instead of falling back to 0 or 1. Update
the checks in the `index.js` flow so downstream ingestion never receives a
fabricated positive ratio from `pricePerShare`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

gm @permapod-rsk, can you fix this issue pls? falling back to these can ingest incorrect values

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@0xkr3p Agreed — those fallbacks can mask malformed contract responses and produce a bogus pricePerShare.

@permapod-rsk please update this so funds_raised and total_supply are validated explicitly before computing tvlUsd / pricePerShare, and skip or throw on invalid values instead of defaulting to 0 / 1.

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