Overview
Calculates estimated rewards for a delegator, showing the breakdown before proximity distribution , after proximity , and after tax . This is a preview function - it doesn’t modify state.
Contract Call Details
0x0000000000000000000000000000000000001000 (FenineSystem)
Function call: getEstimatedDelegatorReward(address,address)
Response
Raw pending rewards before any deductions (wei)
Rewards after proximity distribution, including any bonus from ineligible uplines (wei)
Final amount delegator will receive after tax deduction (wei)
Examples
const Web3 = require ( 'web3' );
const web3 = new Web3 ( 'https://rpc.fene.app' );
const delegatorAddress = '0x1111111111111111111111111111111111111111' ;
const validatorAddress = '0x2222222222222222222222222222222222222222' ;
const abi = JSON . parse ( await web3 . getSystemContractABI ());
const contract = new web3 . eth . Contract (
abi ,
'0x0000000000000000000000000000000000001000'
);
const estimate = await contract . methods . getEstimatedDelegatorReward (
delegatorAddress ,
validatorAddress
). call ();
console . log ( 'Reward Breakdown:' );
console . log ( '═' . repeat ( 50 ));
console . log ( `Pending (raw): ${ web3 . utils . fromWei ( estimate . pending , 'ether' ) } FEN` );
console . log ( `After proximity: ${ web3 . utils . fromWei ( estimate . afterProximity , 'ether' ) } FEN` );
console . log ( `After tax (final): ${ web3 . utils . fromWei ( estimate . afterTax , 'ether' ) } FEN` );
// Calculate deductions
const proximityDeduction = BigInt ( estimate . pending ) - BigInt ( estimate . afterProximity );
const taxDeduction = BigInt ( estimate . afterProximity ) - BigInt ( estimate . afterTax );
console . log ( ' \n Deductions:' );
console . log ( `Proximity paid: ${ web3 . utils . fromWei ( proximityDeduction . toString (), 'ether' ) } FEN` );
console . log ( `Tax paid: ${ web3 . utils . fromWei ( taxDeduction . toString (), 'ether' ) } FEN` );
// Calculate percentages
if ( BigInt ( estimate . pending ) > 0 n ) {
const proximityPct = Number ( proximityDeduction * 100 n / BigInt ( estimate . pending ));
const taxPct = Number ( taxDeduction * 100 n / BigInt ( estimate . afterProximity ));
const finalPct = Number ( BigInt ( estimate . afterTax ) * 100 n / BigInt ( estimate . pending ));
console . log ( ' \n Percentages:' );
console . log ( `Proximity: ${ proximityPct . toFixed ( 1 ) } %` );
console . log ( `Tax: ${ taxPct . toFixed ( 1 ) } %` );
console . log ( `You keep: ${ finalPct . toFixed ( 1 ) } %` );
}
Reward Calculation Flow
Raw Pending Rewards (100%)
↓
Proximity Distribution (~30%)
├─> Level 1-8 uplines (if eligible)
└─> Residual split (50% back to claimer, 50% to validator)
↓
After Proximity (~70% + bonuses)
↓
Tax Deduction (10% default)
├─> Burn share
└─> Dev share
↓
Final Amount (~63% + bonuses)
Use Cases
async function shouldClaim ( delegatorAddress , validatorAddress , minAmount ) {
const estimate = await contract . methods . getEstimatedDelegatorReward (
delegatorAddress ,
validatorAddress
). call ();
const finalAmount = parseFloat ( web3 . utils . fromWei ( estimate . afterTax , 'ether' ));
if ( finalAmount < minAmount ) {
return {
shouldClaim: false ,
reason: `Amount too small ( ${ finalAmount . toFixed ( 4 ) } FEN < ${ minAmount } FEN)` ,
estimate
};
}
// Check gas cost vs reward
const gasPrice = await web3 . eth . getGasPrice ();
const estimatedGas = 300000 ; // Claim typically costs ~300k gas
const gasCostWei = BigInt ( gasPrice ) * BigInt ( estimatedGas );
if ( BigInt ( estimate . afterTax ) < gasCostWei ) {
return {
shouldClaim: false ,
reason: 'Gas cost exceeds reward' ,
gasCost: web3 . utils . fromWei ( gasCostWei . toString (), 'ether' )
};
}
return {
shouldClaim: true ,
finalAmount ,
estimate
};
}
Display Reward Breakdown UI
async function getRewardBreakdownUI ( delegatorAddress , validatorAddress ) {
const estimate = await contract . methods . getEstimatedDelegatorReward (
delegatorAddress ,
validatorAddress
). call ();
if ( estimate . pending == 0 ) {
return { hasRewards: false };
}
const pending = parseFloat ( web3 . utils . fromWei ( estimate . pending , 'ether' ));
const afterProximity = parseFloat ( web3 . utils . fromWei ( estimate . afterProximity , 'ether' ));
const afterTax = parseFloat ( web3 . utils . fromWei ( estimate . afterTax , 'ether' ));
return {
hasRewards: true ,
breakdown: {
gross: pending . toFixed ( 4 ),
proximityPaid: ( pending - afterProximity ). toFixed ( 4 ),
netBeforeTax: afterProximity . toFixed ( 4 ),
taxPaid: ( afterProximity - afterTax ). toFixed ( 4 ),
youReceive: afterTax . toFixed ( 4 )
},
percentages: {
proximityRate: (( pending - afterProximity ) / pending * 100 ). toFixed ( 1 ),
taxRate: (( afterProximity - afterTax ) / afterProximity * 100 ). toFixed ( 1 ),
finalYield: ( afterTax / pending * 100 ). toFixed ( 1 )
}
};
}
async function calculateAPY ( delegatorAddress , validatorAddress ) {
const dcInfo = await contract . methods . getDelegatorInfo (
delegatorAddress ,
validatorAddress
). call ();
if ( dcInfo . status != 1 ) {
return { error: 'Not actively staking' };
}
const estimate = await contract . methods . getEstimatedDelegatorReward (
delegatorAddress ,
validatorAddress
). call ();
// Calculate time staked
const currentBlock = await web3 . eth . getBlockNumber ();
const blocksStaked = currentBlock - dcInfo . joinedAt ;
const daysStaked = ( blocksStaked * 3 ) / ( 60 * 60 * 24 );
if ( daysStaked < 1 ) {
return { error: 'Need at least 1 day of data' };
}
const stake = parseFloat ( web3 . utils . fromWei ( dcInfo . stakeAmount , 'ether' ));
const rewards = parseFloat ( web3 . utils . fromWei ( estimate . afterTax , 'ether' ));
// Daily return
const dailyReturn = rewards / daysStaked ;
const dailyYield = ( dailyReturn / stake ) * 100 ;
// Annualized
const apr = dailyYield * 365 ;
const apy = ( Math . pow ( 1 + dailyYield / 100 , 365 ) - 1 ) * 100 ;
return {
stake ,
rewards ,
daysStaked: daysStaked . toFixed ( 1 ),
dailyReturn: dailyReturn . toFixed ( 4 ),
dailyYield: dailyYield . toFixed ( 2 ) + '%' ,
apr: apr . toFixed ( 2 ) + '%' ,
apy: apy . toFixed ( 2 ) + '%'
};
}
Understanding the Numbers
Pending Rewards : The raw amount before any deductions. This is what you “earned” in theory.
After Proximity : After paying rewards to your uplines (max 8 levels). You may get bonuses if uplines are ineligible.
After Tax : The final amount you’ll receive. Tax typically includes burn (network deflation) and dev share.
Notes
This is an estimate . Actual rewards when claiming may differ slightly due to:
Additional rewards accumulated between estimation and claim
Changes in proximity configuration
Changes in tax rate
Use this before claiming to:
Decide if it’s worth claiming (vs gas costs)
Show users what they’ll receive
Calculate yields and APY
Build reward calculators
getDelegatorInfo Get delegator stake info
getProximityConfig See proximity distribution settings
claimDelegatorReward Claim rewards (transaction)