Skip to main content

suix_getValidatorsApy

Returns the Annual Percentage Yield (APY) information for all validators in the current epoch on the Sui network.

Overview

The suix_getValidatorsApy method provides comprehensive APY information for all active validators in the current epoch. This data is essential for stakers to make informed decisions about validator selection, staking rewards optimization, and understanding the economic incentives within the Sui network. The APY calculation takes into account validator commission rates, network rewards, and historical performance.

Parameters

This method takes no parameters.

Returns

Returns an array of validator APY objects, one for each active validator in the current epoch.

FieldTypeDescription
addressstringValidator's Sui address
apynumberAnnual Percentage Yield as a decimal (e.g., 0.05 = 5%)

APY Calculation

The APY is calculated based on:

  • Network Rewards: Base rewards distributed to all validators
  • Commission Rate: The percentage the validator takes as commission
  • Pool Performance: Historical performance and uptime of the validator
  • Network Participation: Overall network staking participation rate

Code Examples

# Get APY information for all validators
curl -X POST https://sui-mainnet.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "suix_getValidatorsApy",
"params": [],
"id": 1
}'

Response Example

{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"apy": 0.0543
},
{
"address": "0x1a2b3c4d5e6f789012345678901234567890123456789012345678901234567890",
"apy": 0.0521
},
{
"address": "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55",
"apy": 0.0498
},
{
"address": "0x7f8e9d1a2b3c4e5f6789abcdef0123456789abcdef0123456789abcdef012345",
"apy": 0.0476
},
{
"address": "0x9f234567890abcdef0123456789abcdef0123456789abcdef0123456789abcdef0",
"apy": 0.0455
}
]
}

Common Use Cases

1. Validator Selection for Staking

async function selectBestValidator(stakingAmount, preferences = {}) {
const { maxCommission = 0.08, minPoolSize = 5000000000000 } = preferences;

const validators = await analyzeValidatorRewards();

// Filter and rank validators
const eligibleValidators = validators
.filter(v =>
v.commissionRate <= maxCommission &&
v.stakingPoolSuiBalance >= minPoolSize
)
.sort((a, b) => b.apy - a.apy);

if (eligibleValidators.length === 0) {
throw new Error('No validators meet criteria');
}

const topValidator = eligibleValidators[0];
const expectedReturn = stakingAmount * topValidator.apy;

return {
validator: topValidator,
expectedAnnualReturn: expectedReturn,
ranking: `#1 of ${eligibleValidators.length} eligible validators`,
competitiveAdvantage: topValidator.apy - (eligibleValidators[1]?.apy || 0)
};
}

2. Staking Portfolio Diversification

async function createDiversifiedStakingPortfolio(totalAmount, riskLevel = 'balanced') {
const validators = await analyzeValidatorRewards();

let portfolio = [];

if (riskLevel === 'conservative') {
// Focus on established validators with lower risk
const safeValidators = validators
.filter(v => v.commissionRate <= 0.05 && v.stakingPoolSuiBalance >= 10000000000000)
.sort((a, b) => b.apy - a.apy)
.slice(0, 2);

portfolio = safeValidators.map((v, i) => ({
validator: v,
allocation: i === 0 ? totalAmount * 0.6 : totalAmount * 0.4,
risk: 'Low'
}));

} else if (riskLevel === 'aggressive') {
// Higher APY focus with more risk tolerance
const highYieldValidators = validators
.filter(v => v.apy >= 0.05)
.sort((a, b) => b.apy - a.apy)
.slice(0, 3);

portfolio = highYieldValidators.map((v, i) => ({
validator: v,
allocation: totalAmount / 3,
risk: 'High'
}));

} else { // balanced
const balancedValidators = validators
.filter(v => v.commissionRate <= 0.07 && v.apy >= 0.035)
.sort((a, b) => b.apy - a.apy)
.slice(0, 3);

portfolio = balancedValidators.map((v, i) => ({
validator: v,
allocation: i === 0 ? totalAmount * 0.5 : totalAmount * 0.25,
risk: 'Medium'
}));
}

const totalExpectedReturn = portfolio.reduce(
(sum, p) => sum + (p.allocation * p.validator.apy), 0
);

return {
portfolio,
totalExpectedReturn,
weightedAPY: totalExpectedReturn / totalAmount,
riskLevel
};
}

3. Yield Farming Strategy Optimization

async function optimizeYieldStrategy(availableAmount, targetAPY = 0.05) {
const validators = await analyzeValidatorRewards();

// Find validators that meet or exceed target APY
const qualifyingValidators = validators
.filter(v => v.apy >= targetAPY)
.sort((a, b) => {
// Sort by APY but consider commission as secondary factor
const apyDiff = b.apy - a.apy;
if (Math.abs(apyDiff) < 0.005) { // If APY is similar (within 0.5%)
return a.commissionRate - b.commissionRate; // Prefer lower commission
}
return apyDiff;
});

if (qualifyingValidators.length === 0) {
return {
feasible: false,
message: `No validators currently offer ${targetAPY * 100}% APY or higher`,
bestAvailable: Math.max(...validators.map(v => v.apy))
};
}

// Calculate optimal allocation
const strategy = {
feasible: true,
validators: qualifyingValidators.slice(0, 5), // Top 5 options
recommendation: {
primaryValidator: qualifyingValidators[0],
allocation: availableAmount,
expectedReturn: availableAmount * qualifyingValidators[0].apy,
riskAssessment: assessValidatorRisk(qualifyingValidators[0])
},
alternatives: qualifyingValidators.slice(1, 4).map(v => ({
validator: v,
apyDifference: qualifyingValidators[0].apy - v.apy,
commissionAdvantage: v.commissionRate - qualifyingValidators[0].commissionRate
}))
};

return strategy;
}

4. Performance Benchmarking

async function benchmarkValidatorPerformance() {
const validators = await analyzeValidatorRewards();

const benchmark = {
networkAverage: validators.reduce((sum, v) => sum + v.apy, 0) / validators.length,
topQuartile: validators.sort((a, b) => b.apy - a.apy)[Math.floor(validators.length * 0.25)].apy,
median: validators.sort((a, b) => b.apy - a.apy)[Math.floor(validators.length * 0.5)].apy,
bottomQuartile: validators.sort((a, b) => b.apy - a.apy)[Math.floor(validators.length * 0.75)].apy
};

// Categorize validators
const categorized = {
topPerformers: validators.filter(v => v.apy >= benchmark.topQuartile).length,
aboveAverage: validators.filter(v => v.apy > benchmark.networkAverage && v.apy < benchmark.topQuartile).length,
belowAverage: validators.filter(v => v.apy < benchmark.networkAverage && v.apy > benchmark.bottomQuartile).length,
underperformers: validators.filter(v => v.apy <= benchmark.bottomQuartile).length
};

return {
benchmark,
categorized,
analysis: {
competitionLevel: benchmark.topQuartile - benchmark.bottomQuartile,
networkHealth: benchmark.networkAverage > 0.04 ? 'Healthy' : 'Needs Attention',
diversityScore: (benchmark.topQuartile - benchmark.bottomQuartile) / benchmark.networkAverage
}
};
}

APY Considerations

Understanding APY Calculations

  1. Base Network Rewards: Fundamental rewards distributed to all validators
  2. Commission Impact: Higher commission reduces delegator APY
  3. Performance Factors: Uptime and participation affect actual returns
  4. Network Participation: Total staking ratio influences individual rewards

Risk Factors

function assessValidatorRisk(validator) {
const risks = [];
const score = { low: 0, medium: 0, high: 0 };

// Commission risk
if (validator.commissionRate > 0.1) {
risks.push('High commission rate');
score.high += 2;
} else if (validator.commissionRate > 0.05) {
risks.push('Moderate commission rate');
score.medium += 1;
} else {
score.low += 1;
}

// Pool size risk
if (validator.stakingPoolSuiBalance < 1000000000000) {
risks.push('Small staking pool');
score.high += 1;
} else if (validator.stakingPoolSuiBalance < 5000000000000) {
score.medium += 1;
} else {
score.low += 1;
}

// APY sustainability risk
if (validator.apy > 0.08) {
risks.push('Unusually high APY');
score.high += 1;
} else if (validator.apy < 0.03) {
risks.push('Below average APY');
score.medium += 1;
} else {
score.low += 1;
}

const totalScore = score.high * 3 + score.medium * 2 + score.low * 1;
const maxScore = 3 * 3; // 3 factors * max weight
const riskLevel = totalScore <= maxScore * 0.33 ? 'Low' :
totalScore <= maxScore * 0.66 ? 'Medium' : 'High';

return {
level: riskLevel,
factors: risks,
score: totalScore,
recommendation: riskLevel === 'Low' ? 'Recommended for conservative stakers' :
riskLevel === 'Medium' ? 'Suitable for balanced portfolios' :
'Only for risk-tolerant stakers'
};
}

Best Practices

1. Regular Monitoring

// Monitor APY changes to optimize staking positions
const monitoringStrategy = {
frequency: 'daily', // Check APY daily
threshold: 0.005, // 0.5% change triggers review
rebalanceThreshold: 0.01, // 1% difference triggers rebalancing

async checkAndRebalance(currentStaking) {
const currentValidators = await getValidatorsApy();

for (const stake of currentStaking) {
const currentAPY = currentValidators.find(v => v.address === stake.validator)?.apy;
const bestAPY = Math.max(...currentValidators.map(v => v.apy));

if (bestAPY - currentAPY >= this.rebalanceThreshold) {
console.log(`Consider rebalancing from ${stake.validator} (${currentAPY*100:.2f}%) to better option`);
}
}
}
};

2. Diversification Strategy

const diversificationRules = {
maxAllocationPerValidator: 0.4, // Max 40% in one validator
minValidators: 3, // Spread across at least 3 validators
commissionSpread: 0.03, // Vary commission rates by max 3%

validatePortfolio(portfolio) {
const totalAllocation = portfolio.reduce((sum, p) => sum + p.allocation, 0);

return {
diversified: portfolio.length >= this.minValidators,
concentrationRisk: portfolio.some(p => p.allocation / totalAllocation > this.maxAllocationPerValidator),
commissionVariance: Math.max(...portfolio.map(p => p.validator.commissionRate)) -
Math.min(...portfolio.map(p => p.validator.commissionRate))
};
}
};

3. Performance Tracking

// Track actual vs expected performance
class PerformanceTracker {
constructor() {
this.stakingHistory = [];
}

recordStaking(validatorAddress, amount, expectedAPY) {
this.stakingHistory.push({
validator: validatorAddress,
amount: amount,
expectedAPY: expectedAPY,
startDate: Date.now(),
actualReturns: []
});
}

updateReturns(validatorAddress, actualReturn, period) {
const staking = this.stakingHistory.find(s => s.validator === validatorAddress);
if (staking) {
staking.actualReturns.push({
period: period,
return: actualReturn,
date: Date.now()
});
}
}

calculatePerformanceMetrics(validatorAddress) {
const staking = this.stakingHistory.find(s => s.validator === validatorAddress);
if (!staking || staking.actualReturns.length === 0) return null;

const actualAPY = staking.actualReturns[staking.actualReturns.length - 1].return / staking.amount;
const variance = actualAPY - staking.expectedAPY;

return {
expectedAPY: staking.expectedAPY,
actualAPY: actualAPY,
variance: variance,
performance: variance > 0.005 ? 'Outperforming' :
variance < -0.005 ? 'Underperforming' : 'On Track'
};
}
}

Error Handling

async function robustGetValidatorsApy(retries = 3) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const apyData = await client.getValidatorsApy();

if (!apyData || apyData.length === 0) {
throw new Error('No APY data returned');
}

return { success: true, data: apyData };
} catch (error) {
console.warn(`APY fetch attempt ${attempt} failed:`, error.message);

if (attempt === retries) {
return {
success: false,
error: error.message,
fallback: 'Use cached data or default to manual validator selection'
};
}

await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}

Notes

  • APY values are estimates based on current network conditions and historical performance
  • Commission rates affect the actual APY received by delegators
  • Network rewards fluctuate based on overall network activity and participation
  • Validator performance can impact actual returns compared to estimated APY
  • Pool size and stability should be considered alongside APY for risk assessment
  • APY calculations typically assume compound interest and consistent performance

Need help? Contact our support team or check the Sui documentation.