Skip to main content

suix_getStakes

Returns the staking information for a given address, including delegated stakes and rewards on the Sui network.

Overview​

The suix_getStakes method provides comprehensive staking information for any Sui address. This includes all active staking positions, delegation details, accumulated rewards, and staking history. The method is essential for tracking staking performance, managing validator delegations, and monitoring staking rewards across the Sui ecosystem.

Parameters​

ParameterTypeRequiredDescription
ownerstringYesThe Sui address to query staking information for

Address Format​

  • Must be a valid 66-character hex string with 0x prefix
  • The address must exist on the Sui network
  • Can query staking information for any address (not just owned)

Returns​

Returns an array of staking objects containing detailed staking information.

FieldTypeDescription
stakingPoolIdstringThe ID of the staking pool object
validatorAddressstringAddress of the validator being delegated to
statusstringCurrent status of the stake (Active, Pending, etc.)
requestEpochstringEpoch when the staking request was made
activeEpochstringEpoch when the stake became active
principalstringOriginal staking amount in MIST
estimatedRewardstringEstimated rewards earned in MIST

Staking Status Types​

  • Active: Stake is currently active and earning rewards
  • Pending: Stake is waiting to become active in the next epoch
  • Unstaking: Stake is being withdrawn
  • Withdrawn: Stake has been fully withdrawn

Code Examples​

# Get staking information for an address
curl -X POST https://sui-mainnet.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "suix_getStakes",
"params": [
"0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
],
"id": 1
}'

Response Example​

{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"stakingPoolId": "0x1234567890abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"validatorAddress": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"status": "Active",
"requestEpoch": "245",
"activeEpoch": "246",
"principal": "5000000000000",
"estimatedReward": "250000000000"
},
{
"stakingPoolId": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"validatorAddress": "0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba",
"status": "Pending",
"requestEpoch": "251",
"activeEpoch": "252",
"principal": "2000000000000",
"estimatedReward": "0"
}
]
}

Common Use Cases​

Staking Dashboard​

class StakingDashboard {
constructor(client) {
this.client = client;
}

async getDashboardData(address) {
const [stakes, validatorAPYs] = await Promise.all([
this.client.getStakes({ owner: address }),
this.client.getValidatorsApy()
]);

const apyMap = validatorAPYs.reduce((acc, v) => {
acc[v.address] = v.apy;
return acc;
}, {});

const dashboard = {
address: address,
totalStakes: stakes.length,
totalPrincipal: 0,
totalRewards: 0,
activeStakes: 0,
pendingStakes: 0,
estimatedYearlyRewards: 0,
validatorPerformance: [],
riskMetrics: {
diversificationScore: 0,
concentrationRisk: 0
}
};

const validatorGroups = {};

stakes.forEach(stake => {
const principal = BigInt(stake.principal);
const reward = BigInt(stake.estimatedReward);
const validatorAPY = apyMap[stake.validatorAddress] || 0;

dashboard.totalPrincipal += Number(principal);
dashboard.totalRewards += Number(reward);

if (stake.status === 'Active') {
dashboard.activeStakes++;
dashboard.estimatedYearlyRewards += Number(principal) * validatorAPY;
} else if (stake.status === 'Pending') {
dashboard.pendingStakes++;
}

// Group by validator
if (!validatorGroups[stake.validatorAddress]) {
validatorGroups[stake.validatorAddress] = {
validator: stake.validatorAddress,
stakes: 0,
totalPrincipal: 0,
totalRewards: 0,
apy: validatorAPY,
status: { Active: 0, Pending: 0, other: 0 }
};
}

const group = validatorGroups[stake.validatorAddress];
group.stakes++;
group.totalPrincipal += Number(principal);
group.totalRewards += Number(reward);
group.status[stake.status] = (group.status[stake.status] || 0) + 1;
});

dashboard.validatorPerformance = Object.values(validatorGroups)
.sort((a, b) => b.totalPrincipal - a.totalPrincipal);

// Calculate risk metrics
const validatorCount = Object.keys(validatorGroups).length;
dashboard.riskMetrics.diversificationScore = validatorCount / stakes.length;

if (dashboard.totalPrincipal > 0) {
const maxValidatorAllocation = Math.max(
...dashboard.validatorPerformance.map(v => v.totalPrincipal)
);
dashboard.riskMetrics.concentrationRisk =
(maxValidatorAllocation / dashboard.totalPrincipal) * 100;
}

// Convert to SUI
dashboard.totalPrincipalSUI = dashboard.totalPrincipal / 1_000_000_000;
dashboard.totalRewardsSUI = dashboard.totalRewards / 1_000_000_000;
dashboard.estimatedYearlyRewardsSUI = dashboard.estimatedYearlyRewards / 1_000_000_000;

return dashboard;
}
}

Staking Rewards Calculator​

class StakingRewardsCalculator {
constructor(client) {
this.client = client;
}

async calculateProjectedRewards(address, projectionPeriods = [30, 90, 365]) {
const stakes = await this.client.getStakes({ owner: address });
const validatorAPYs = await this.client.getValidatorsApy();

const apyMap = validatorAPYs.reduce((acc, v) => {
acc[v.address] = v.apy;
return acc;
}, {});

const projections = {
address: address,
currentStakes: stakes.length,
projectedRewards: [],
byValidator: {}
};

let totalActiveStake = 0;

stakes.forEach(stake => {
if (stake.status === 'Active') {
const principal = Number(stake.principal);
const validatorAPY = apyMap[stake.validatorAddress] || 0;

totalActiveStake += principal;

if (!projections.byValidator[stake.validatorAddress]) {
projections.byValidator[stake.validatorAddress] = {
totalStake: 0,
apy: validatorAPY,
projectedRewards: []
};
}

projections.byValidator[stake.validatorAddress].totalStake += principal;
}
});

// Calculate projections for each period
projectionPeriods.forEach(days => {
let totalProjectedReward = 0;

Object.entries(projections.byValidator).forEach(([validator, data]) => {
const dailyRate = data.apy / 365;
const compoundedReturn = data.totalStake * Math.pow(1 + dailyRate, days);
const projectedReward = compoundedReturn - data.totalStake;

data.projectedRewards.push({
days: days,
projectedReward: projectedReward,
totalValue: compoundedReturn
});

totalProjectedReward += projectedReward;
});

projections.projectedRewards.push({
days: days,
period: this.formatPeriod(days),
totalProjectedReward: totalProjectedReward,
totalProjectedRewardSUI: totalProjectedReward / 1_000_000_000,
effectiveAPY: Math.pow(
(totalActiveStake + totalProjectedReward) / totalActiveStake,
365 / days
) - 1
});
});

projections.currentStakeSUI = totalActiveStake / 1_000_000_000;

return projections;
}

formatPeriod(days) {
if (days < 30) return `${days} days`;
if (days < 365) return `${Math.round(days / 30)} months`;
return `${Math.round(days / 365 * 10) / 10} years`;
}
}

Error Handling​

async function safeGetStakes(address, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const stakes = await client.getStakes({ owner: address });

if (!Array.isArray(stakes)) {
throw new Error('Invalid response format - expected array');
}

return { success: true, data: stakes };

} catch (error) {
console.warn(`Stakes query attempt ${attempt} failed:`, error.message);

if (error.message.includes('Invalid address')) {
return {
success: false,
error: 'INVALID_ADDRESS',
message: 'Invalid Sui address format'
};
}

if (error.message.includes('Address not found')) {
return {
success: false,
error: 'ADDRESS_NOT_FOUND',
message: 'Address has no staking history'
};
}

if (attempt === maxRetries) {
return {
success: false,
error: 'MAX_RETRIES_EXCEEDED',
message: error.message
};
}

await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
}

Best Practices​

  1. Regular Monitoring: Check staking positions regularly to optimize performance
  2. Diversification: Spread stakes across multiple validators to reduce risk
  3. Performance Analysis: Compare validator APYs and adjust allocations accordingly
  4. Risk Management: Monitor concentration risk and maintain appropriate diversification
  5. Epoch Awareness: Understand that staking changes take effect at epoch boundaries
  6. Reward Tracking: Keep track of accumulated rewards for tax and performance analysis

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