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

Overview

Queries the FenineSystem contract to get the current epoch number. Epochs are periods of 200 blocks where validator set updates and reward distributions occur.

Contract Call Details

to
address
required
0x0000000000000000000000000000000000001000 (FenineSystem)
data
bytes
required
Function call: getCurrentEpoch()

Response

result
uint256
Current epoch number (0-indexed)

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 epoch = await contract.methods.getCurrentEpoch().call();
console.log('Current epoch:', epoch);

// Also calculate manually from block number
const currentBlock = await web3.eth.getBlockNumber();
const EPOCH_BLOCKS = 200;
const calculatedEpoch = Math.floor(currentBlock / EPOCH_BLOCKS);

console.log('Block:', currentBlock);
console.log('Calculated epoch:', calculatedEpoch);
console.log('Match:', epoch == calculatedEpoch);

Epoch Calculation

You can also calculate the epoch from the current block number:
const currentBlock = await web3.eth.getBlockNumber();
const EPOCH_BLOCKS = 200;

const currentEpoch = Math.floor(currentBlock / EPOCH_BLOCKS);
const blockInEpoch = currentBlock % EPOCH_BLOCKS;
const blocksUntilNextEpoch = EPOCH_BLOCKS - blockInEpoch;

console.log({
  currentBlock,
  currentEpoch,
  blockInEpoch,
  blocksUntilNextEpoch,
  estimatedTimeUntilNext: (blocksUntilNextEpoch * 3 / 60).toFixed(1) + ' minutes'
});

Use Cases

async function monitorEpochTransitions() {
  let lastEpoch = await contract.methods.getCurrentEpoch().call();
  
  setInterval(async () => {
    const currentEpoch = await contract.methods.getCurrentEpoch().call();
    
    if (currentEpoch != lastEpoch) {
      console.log('='.repeat(50));
      console.log('NEW EPOCH:', currentEpoch);
      console.log('='.repeat(50));
      
      // Fetch updated data
      const validators = await contract.methods.getActiveValidators().call();
      const totalStake = await contract.methods.totalNetworkStake().call();
      
      console.log('Active validators:', validators.length);
      console.log('Total stake:', web3.utils.fromWei(totalStake, 'ether'), 'FEN');
      
      lastEpoch = currentEpoch;
      
      // Trigger your application logic
      // e.g., refresh dashboard, recalculate rewards, etc.
    }
  }, 3000); // Check every block (~3s)
}
async function getTimeUntilNextEpoch() {
  const currentBlock = await web3.eth.getBlockNumber();
  const EPOCH_BLOCKS = 200;
  const BLOCK_TIME = 3; // seconds
  
  const currentEpoch = Math.floor(currentBlock / EPOCH_BLOCKS);
  const blockInEpoch = currentBlock % EPOCH_BLOCKS;
  const blocksRemaining = EPOCH_BLOCKS - blockInEpoch;
  
  const secondsRemaining = blocksRemaining * BLOCK_TIME;
  const minutesRemaining = secondsRemaining / 60;
  
  return {
    currentEpoch,
    currentBlock,
    blockInEpoch: `${blockInEpoch}/${EPOCH_BLOCKS}`,
    progress: ((blockInEpoch / EPOCH_BLOCKS) * 100).toFixed(1) + '%',
    blocksRemaining,
    timeRemaining: {
      seconds: secondsRemaining,
      minutes: minutesRemaining.toFixed(1),
      formatted: `${Math.floor(minutesRemaining)}m ${secondsRemaining % 60}s`
    }
  };
}
async function buildEpochHistory(epochCount = 10) {
  const currentEpoch = await contract.methods.getCurrentEpoch().call();
  const currentBlock = await web3.eth.getBlockNumber();
  
  const history = [];
  
  for (let i = 0; i < epochCount; i++) {
    const epoch = parseInt(currentEpoch) - i;
    if (epoch < 0) break;
    
    const epochStartBlock = epoch * 200;
    const epochEndBlock = epochStartBlock + 199;
    
    // Get block timestamps (if needed)
    // const startBlockData = await web3.eth.getBlock(epochStartBlock);
    
    history.push({
      epoch,
      startBlock: epochStartBlock,
      endBlock: epochEndBlock,
      isComplete: currentBlock > epochEndBlock,
      isCurrent: epoch == currentEpoch
    });
  }
  
  return history;
}
async function scheduleAtNextEpoch(callback) {
  const currentBlock = await web3.eth.getBlockNumber();
  const EPOCH_BLOCKS = 200;
  
  const nextEpochBlock = Math.ceil(currentBlock / EPOCH_BLOCKS) * EPOCH_BLOCKS;
  const blocksToWait = nextEpochBlock - currentBlock;
  
  console.log(`Waiting ${blocksToWait} blocks until next epoch...`);
  console.log(`Estimated time: ${(blocksToWait * 3 / 60).toFixed(1)} minutes`);
  
  // Subscribe to new blocks
  const subscription = web3.eth.subscribe('newBlockHeaders');
  
  subscription.on('data', async (blockHeader) => {
    if (blockHeader.number >= nextEpochBlock) {
      console.log('Next epoch reached!');
      subscription.unsubscribe();
      await callback();
    }
  });
  
  return subscription;
}

// Usage
await scheduleAtNextEpoch(async () => {
  console.log('Refreshing validator data...');
  const validators = await contract.methods.getActiveValidators().call();
  console.log('Updated validators:', validators);
});

Epoch Information

async function getFullEpochInfo() {
  const [currentEpoch, currentBlock, constants] = await Promise.all([
    contract.methods.getCurrentEpoch().call(),
    web3.eth.getBlockNumber(),
    web3.getContractConstants()
  ]);
  
  const EPOCH_BLOCKS = constants.blockEpoch;
  const blockInEpoch = currentBlock % EPOCH_BLOCKS;
  const epochStartBlock = Math.floor(currentBlock / EPOCH_BLOCKS) * EPOCH_BLOCKS;
  const epochEndBlock = epochStartBlock + EPOCH_BLOCKS - 1;
  const nextEpochBlock = epochEndBlock + 1;
  
  return {
    current: {
      epoch: currentEpoch,
      block: currentBlock
    },
    thisEpoch: {
      startBlock: epochStartBlock,
      endBlock: epochEndBlock,
      currentBlock: blockInEpoch,
      progress: ((blockInEpoch / EPOCH_BLOCKS) * 100).toFixed(1) + '%'
    },
    nextEpoch: {
      epoch: parseInt(currentEpoch) + 1,
      startBlock: nextEpochBlock,
      blocksUntil: nextEpochBlock - currentBlock,
      estimatedTime: ((nextEpochBlock - currentBlock) * 3 / 60).toFixed(1) + ' minutes'
    }
  };
}

getContractConstants

Get EPOCH_BLOCKS constant (200)

getNextEpochReward

Get reward pool for next epoch

updateValidatorCandidates

System TX at epoch boundary