Every day is bringing us closer to the genesis of ETH 2.0 Phase 0. Major multi-client testnet efforts are well underway with the current witti testnet and the upcoming altona testnet.  Interest and participation in staking on these testnets continues to rise, with over 65% of all respondents planning to stake their ETH, according to a new Ethereum 2.0 Report.

One of the most basic needs for those staking on ETH 2.0 will be monitoring the balance of their validators. It is crucial to know if they are accruing the rewards that are expected. Of course there are several great block explorers available where you can see this information, but in this post, we will show how you can query it programmatically with the Infura ETH 2.0 Beacon Chain API.

The ability to query your balance programmatically is important because it enables you to easily take action on the data.  You might want to write a program that monitors the balance and sends you a text message if it unexpectedly drops!

Let's take a look how to accomplish this in a simple typescript program.


First we will import the axios library and create an HTTP client with some basic defaults, loading our Infura project ID from an environment variable:

import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://witti.infura.io/',
  auth: {
    username: process.env.INFURA_PROJECT_ID,
    password: '',
  },
});

We define some helpful constants related to the basic parameters of the network.  The first two will help us calculate the current epoch, and the last helps us convert a gwei balance to the more familiar eth unit:

const SECONDS_PER_SLOT = 12;
const SLOTS_PER_EPOCH = 32;
const GWEI_PER_ETH = 1000000000;

Then we will query the genesis for the network, and use it to calculate the current epoch:

(async () => {
  let response = await instance.get('node/genesis_time')
  const genesisTime = response.data;

  const now = Math.floor(Date.now() / 1000)
  const currentEpoch = Math.floor((now - genesisTime) / (SECONDS_PER_SLOT * SLOTS_PER_EPOCH))

Using that, we can then query for the current balance of a validator (here using the public key of the highest balance validator on the network at time of writing):

    response = await instance.post('beacon/validators', {
    epoch: currentEpoch.toString(),
    pubkeys: ["0xb0bfa93603f81ecaf3c450b793e71f7372822cd2002534364493e4e497fb5df16d252ae2fdc6bbc0e74d849f918db393"],
  });

  const balanceGwei = response.data[0].balance;
  const balance = balanceGwei / GWEI_PER_ETH;
  
  console.log(`You have ${balance} Ξ2.0`);
})();

When we run the full program, we will see an output like:

You have 32.500178823 Ξ2.0

Now we can expand the program to do something useful with the information!

For convenience, here is the full program in one snippet:

import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://witti.infura.io/',
  auth: {
    username: process.env.INFURA_PROJECT_ID,
    password: '',
  },
});

const SECONDS_PER_SLOT = 12;
const SLOTS_PER_EPOCH = 32;
const GWEI_PER_ETH = 1000000000;

(async () => {
  let response = await instance.get('node/genesis_time')
  const genesisTime = response.data;

  const now = Math.floor(Date.now() / 1000)
  const currentEpoch = Math.floor((now - genesisTime) / (SECONDS_PER_SLOT * SLOTS_PER_EPOCH))

  response = await instance.post('beacon/validators', {
    epoch: currentEpoch.toString(),
    pubkeys: ["0xb0bfa93603f81ecaf3c450b793e71f7372822cd2002534364493e4e497fb5df16d252ae2fdc6bbc0e74d849f918db393"],
  });

  const balanceGwei = response.data[0].balance;
  const balance = balanceGwei / GWEI_PER_ETH;
  
  console.log(`You have ${balance} Ξ2.0`);
})();

In preparation for the launch of Ethereum 2.0, we’ve planned a limited time private beta release of Infura’s Eth2 Beacon Chain API. If you would like access, apply now and register your interest. Documentation will be sent out directly to users who are accepted into the beta.

We greatly value all our testers. It’s your feedback that will help us refine our Eth2 Beacon Chain API, ensuring that the final product is as relevant and performant as possible, before making it more widely available.