Overview
Queries the FenineSystem contract to get the current proximity (referral) reward distribution configuration, including the total allocation and per-level distribution.
Contract Call Details
0x0000000000000000000000000000000000001000 (FenineSystem)
Function call: getProximityConfig()
Response
Total proximity allocation in basis points (e.g., 3000 = 30%)
Number of proximity levels (always 8)
Per-level distribution in basis points
Default: [700, 500, 400, 350, 300, 250, 250, 250] = [7%, 5%, 4%, 3.5%, 3%, 2.5%, 2.5%, 2.5%]
Examples
const Web3 = require ( 'web3' );
const web3 = new Web3 ( 'https://rpc.fene.app' );
const abi = JSON . parse ( await web3 . getSystemContractABI ());
const contract = new web3 . eth . Contract (
abi ,
'0x0000000000000000000000000000000000001000'
);
const config = await contract . methods . getProximityConfig (). call ();
console . log ( 'Proximity Configuration:' );
console . log ( '═' . repeat ( 50 ));
console . log ( 'Total allocation:' , config . totalBps / 100 , '%' );
console . log ( 'Depth:' , config . depth , 'levels' );
console . log ( ' \n Per-Level Distribution:' );
for ( let i = 0 ; i < config . depth ; i ++ ) {
console . log ( `Level ${ i + 1 } : ${ config . rewardBps [ i ] / 100 } %` );
}
// Calculate what's left for delegator
const delegatorBase = 10000 - config . totalBps ; // 100% - proximity
console . log ( ' \n Delegator base share:' , delegatorBase / 100 , '%' );
Default Configuration
{
totalBps : 3000 , // 30% total
depth : 8 , // 8 levels
rewardBps : [
700 , // Level 1: 7% (closest upline)
500 , // Level 2: 5%
400 , // Level 3: 4%
350 , // Level 4: 3.5%
300 , // Level 5: 3%
250 , // Level 6: 2.5%
250 , // Level 7: 2.5%
250 // Level 8: 2.5% (deepest upline)
]
}
Understanding Proximity Distribution
When a delegator claims rewards, a portion is distributed to their uplines (previous delegators to the same validator).
Example Flow
// Delegator claims 100 FEN in rewards
const claimAmount = 100 ;
const config = await contract . methods . getProximityConfig (). call ();
// Proximity distribution (30% of 100 = 30 FEN)
const proximityPool = claimAmount * ( config . totalBps / 10000 ); // 30 FEN
// Per-level distribution
const distributions = config . rewardBps . map (( bps , i ) => ({
level: i + 1 ,
uplineReceives: claimAmount * ( bps / 10000 ),
percentage: bps / 100
}));
console . log ( 'When claiming 100 FEN:' );
distributions . forEach ( d => {
console . log ( `Level ${ d . level } upline receives: ${ d . uplineReceives } FEN ( ${ d . percentage } %)` );
});
// Delegator base (70% of 100 = 70 FEN + residual bonuses)
const delegatorBase = claimAmount * (( 10000 - config . totalBps ) / 10000 );
console . log ( `Delegator base: ${ delegatorBase } FEN (70%)` );
Use Cases
Calculate Proximity Earnings
async function calculateProximityEarnings ( myPosition , delegatorsBelowMe ) {
const config = await contract . methods . getProximityConfig (). call ();
// Assume each delegator below me claims 100 FEN
const avgClaim = 100 ;
let myEarnings = 0 ;
for ( let i = 0 ; i < Math . min ( delegatorsBelowMe , config . depth ); i ++ ) {
const level = i ; // 0-indexed from my perspective
if ( level < config . depth ) {
const earning = avgClaim * ( config . rewardBps [ level ] / 10000 );
myEarnings += earning ;
}
}
return {
delegatorsBelowMe ,
avgClaimPerDelegator: avgClaim ,
totalProximityEarnings: myEarnings . toFixed ( 2 ) + ' FEN' ,
perDelegator: ( myEarnings / delegatorsBelowMe ). toFixed ( 2 ) + ' FEN'
};
}
async function visualizeProximityDistribution () {
const config = await contract . methods . getProximityConfig (). call ();
console . log ( 'Proximity Reward Distribution' );
console . log ( '═' . repeat ( 60 ));
console . log ( `Total allocated to uplines: ${ config . totalBps / 100 } %` );
console . log ( `Delegator base (before residual): ${ ( 10000 - config . totalBps ) / 100 } %` );
console . log ( ' \n ' + '─' . repeat ( 60 ));
let cumulative = 0 ;
for ( let i = 0 ; i < config . depth ; i ++ ) {
const pct = config . rewardBps [ i ] / 100 ;
cumulative += config . rewardBps [ i ];
const bar = '█' . repeat ( Math . floor ( pct * 2 ));
console . log ( `Level ${ i + 1 } : ${ pct } % \t ${ bar } ` );
}
console . log ( '─' . repeat ( 60 ));
console . log ( `Total: ${ cumulative / 100 } %` );
console . log ( ' \n Note: Ineligible upline rewards are split 50/50' );
console . log ( ' between claimer and validator (as bonus)' );
}
async function monitorConfigChanges () {
let lastConfig = await contract . methods . getProximityConfig (). call ();
setInterval ( async () => {
const currentConfig = await contract . methods . getProximityConfig (). call ();
if ( currentConfig . totalBps != lastConfig . totalBps ) {
console . log ( '⚠️ Proximity config changed!' );
console . log ( 'Old total:' , lastConfig . totalBps / 100 , '%' );
console . log ( 'New total:' , currentConfig . totalBps / 100 , '%' );
// Notify users, update UI, etc.
lastConfig = currentConfig ;
}
}, 60000 ); // Check every minute
}
Build Earnings Calculator
async function buildEarningsCalculator (
myStake ,
myPosition ,
totalDelegatorsBelow ,
avgMonthlyClaimsPerDelegator
) {
const config = await contract . methods . getProximityConfig (). call ();
// Direct staking rewards (validator share)
const vaInfo = await contract . methods . getValidatorInfo ( validatorAddress ). call ();
const commission = vaInfo . commissionRate / 10000 ;
const myDirectYield = myStake * 0.05 * ( 1 - commission ); // Assume 5% APY base
// Proximity earnings
let monthlyProximity = 0 ;
for ( let i = 0 ; i < Math . min ( totalDelegatorsBelow , config . depth ); i ++ ) {
const levelEarning = avgMonthlyClaimsPerDelegator * ( config . rewardBps [ i ] / 10000 );
monthlyProximity += levelEarning ;
}
return {
staking: {
stake: myStake + ' FEN' ,
monthlyDirect: myDirectYield . toFixed ( 2 ) + ' FEN' ,
annualDirect: ( myDirectYield * 12 ). toFixed ( 2 ) + ' FEN'
},
proximity: {
position: myPosition ,
delegatorsBelow: totalDelegatorsBelow ,
monthlyProximity: monthlyProximity . toFixed ( 2 ) + ' FEN' ,
annualProximity: ( monthlyProximity * 12 ). toFixed ( 2 ) + ' FEN'
},
combined: {
monthlyTotal: ( myDirectYield + monthlyProximity ). toFixed ( 2 ) + ' FEN' ,
annualTotal: (( myDirectYield + monthlyProximity ) * 12 ). toFixed ( 2 ) + ' FEN' ,
effectiveAPY: ((( myDirectYield + monthlyProximity ) * 12 / myStake ) * 100 ). toFixed ( 2 ) + '%'
}
};
}
Admin Configuration
Only the contract admin can change proximity configuration via setProximityConfig(). Maximum total allocation is 87% (8700 basis points) to protect delegators.
Residual Distribution
If uplines are ineligible (insufficient stake, unstaking, or stake too new), their rewards don’t disappear:
// Residual split:
// - 50% returned to claimer (bonus)
// - 50% to validator
getEstimatedDelegatorReward See proximity effect on rewards
getValidatorStakers See proximity chain order
setProximityConfig Admin function to update config