getValidatorStakers
curl --request POST \
--url https://api.example.com/eth_callimport requests
url = "https://api.example.com/eth_call"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/eth_call', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/eth_call",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/eth_call"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/eth_call")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/eth_call")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body{
"result": [
{}
]
}eth_* Methods
getValidatorStakers
Get list of delegators staked to a validator (proximity order)
POST
eth_call
getValidatorStakers
curl --request POST \
--url https://api.example.com/eth_callimport requests
url = "https://api.example.com/eth_call"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/eth_call', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/eth_call",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/eth_call"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/eth_call")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/eth_call")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body{
"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
address
required
0x0000000000000000000000000000000000001000 (FenineSystem)bytes
required
Function call data:
getValidatorStakers(address)address
required
The validator address to query
Response
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]);
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider('https://rpc.fene.app');
const validatorAddress = '0x1234567890123456789012345678901234567890';
const abiJson = await provider.send('fenine_getSystemContractABI', []);
const abi = JSON.parse(abiJson);
const contract = new ethers.Contract(
'0x0000000000000000000000000000000000001000',
abi,
provider
);
const stakers = await contract.getValidatorStakers(validatorAddress);
console.log('Delegators:', stakers);
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('https://rpc.fene.app'))
# You'll need the contract ABI
from web3.contract import Contract
# Get contract instance (assuming you have ABI)
system_contract = w3.eth.contract(
address='0x0000000000000000000000000000000000001000',
abi=system_abi
)
validator_address = '0x1234567890123456789012345678901234567890'
stakers = system_contract.functions.getValidatorStakers(validator_address).call()
print(f'Total delegators: {len(stakers)}')
print(f'Delegators: {stakers}')
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
Display Delegator List
Display Delegator List
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;
}
Calculate Proximity Depth
Calculate Proximity Depth
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)
};
}
Visualize Proximity Chain
Visualize Proximity Chain
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.
Related Methods
getValidatorInfo
Get validator details including delegator count
getDelegatorInfo
Get specific delegator’s stake info
getProximityConfig
Get proximity reward distribution settings
⌘I