Skip to main content
POST
eth_call
getValidatorStakers
curl --request POST \
  --url https://api.example.com/eth_call
{
  "result": [
    {}
  ]
}

Overview

Queries the FenineSystem contract to get the list of all delegators staked to a specific validator. The array is returned in proximity order, which is important for the reward distribution mechanism.

Contract Call Details

to
address
required
0x0000000000000000000000000000000000001000 (FenineSystem)
data
bytes
required
Function call data: getValidatorStakers(address)
validator
address
required
The validator address to query

Response

result
address[]
Array of delegator addresses in proximity order (first = deepest in chain)

Examples

const Web3 = require('web3');
const web3 = new Web3('https://rpc.fene.app');

const validatorAddress = '0x1234567890123456789012345678901234567890';

// Using contract instance
const abi = JSON.parse(await web3.getSystemContractABI());
const contract = new web3.eth.Contract(
  abi,
  '0x0000000000000000000000000000000000001000'
);

const stakers = await contract.methods.getValidatorStakers(validatorAddress).call();

console.log('Total delegators:', stakers.length);
console.log('Delegators (proximity order):', stakers);

// First staker is deepest in proximity chain
console.log('Deepest staker (receives rewards from all below):', stakers[0]);
console.log('Latest staker (pays proximity to all above):', stakers[stakers.length - 1]);

Proximity Order Explained

The order matters! This array determines proximity reward distribution.
// Example proximity chain
const stakers = [
  '0xAAAA...', // Position 0 - First staker (deepest)
  '0xBBBB...', // Position 1 - Second staker
  '0xCCCC...', // Position 2 - Third staker
  '0xDDDD...'  // Position 3 - Latest staker
];

// When 0xDDDD claims rewards:
// - 0xCCCC gets Level 1 proximity (7%)
// - 0xBBBB gets Level 2 proximity (5%)
// - 0xAAAA gets Level 3 proximity (4%)

Use Cases

async function getDelegatorList(validatorAddress) {
  const stakers = await contract.methods.getValidatorStakers(validatorAddress).call();
  
  // Get info for each delegator
  const delegatorInfo = await Promise.all(
    stakers.map(async (delegatorAddr, index) => {
      const info = await contract.methods.getDelegatorInfo(
        delegatorAddr,
        validatorAddress
      ).call();
      
      return {
        position: index,
        address: delegatorAddr,
        stake: web3.utils.fromWei(info.stakeAmount, 'ether'),
        pending: web3.utils.fromWei(info.pendingRewards, 'ether'),
        joinedAt: info.joinedAt
      };
    })
  );
  
  return delegatorInfo;
}
async function getMyProximityDepth(myAddress, validatorAddress) {
  const stakers = await contract.methods.getValidatorStakers(validatorAddress).call();
  
  const myIndex = stakers.findIndex(
    addr => addr.toLowerCase() === myAddress.toLowerCase()
  );
  
  if (myIndex === -1) {
    return { isStaked: false };
  }
  
  const uplineCount = myIndex; // How many above me
  const downlineCount = stakers.length - myIndex - 1; // How many below me
  
  return {
    isStaked: true,
    position: myIndex,
    uplineCount,
    downlineCount,
    canReceiveFrom: Math.min(downlineCount, 8), // Max 8 levels
    paysTo: Math.min(uplineCount, 8)
  };
}
async function visualizeProximityChain(validatorAddress) {
  const stakers = await contract.methods.getValidatorStakers(validatorAddress).call();
  
  console.log('Proximity Chain (Top → Bottom):');
  console.log('═'.repeat(50));
  
  for (let i = 0; i < stakers.length; i++) {
    const info = await contract.methods.getDelegatorInfo(
      stakers[i],
      validatorAddress
    ).call();
    
    const indent = '  '.repeat(i);
    console.log(`${indent}${i}. ${stakers[i]}`);
    console.log(`${indent}   Stake: ${web3.utils.fromWei(info.stakeAmount, 'ether')} FEN`);
    
    if (i < stakers.length - 1) {
      console.log(`${indent}   ↓ receives from`);
    }
  }
}

Important Notes

Proximity Position is Fixed: Once a delegator stakes, their position in this array is fixed until they unstake. New delegators are always added to the end.
When a delegator unstakes, they are removed from the array (swap-pop operation), which changes the index of subsequent delegators.

getValidatorInfo

Get validator details including delegator count

getDelegatorInfo

Get specific delegator’s stake info

getProximityConfig

Get proximity reward distribution settings