Accessing Ethereum Archive Nodes with Infura
Archive nodes are particular nodes on the Ethereum network that store historical blockchain data. Because they offer this historical information, they are helpful when you need to audit past transaction history or gather data. Services like Etherscan and Dune Analytics use archive nodes, but anyone can run one themselves.
In this article, we will review the different types of Ethereum nodes, dive deeper into archive nodes, and introduce the new archive node capabilities of Infura.
We'll then walk through a real-world project to show how to connect the Infura API and web3.js to a pre-built React frontend. Once complete, the user will be able to query an archive node for some statistics for a given Ethereum wallet address.
What are Ethereum Nodes?
In simple terms, a node is just a connection point in a network. However, in the case of Ethereum, different types of nodes hold various responsibilities to the network.
The Ethereum blockchain operates on what is called the Ethereum Virtual Machine (EVM), which is a decentralized global computer. Nodes, in this case, provide the processing power for this computer. They serve requested data, create and validate blocks, store transaction data or smart contract code, and much more. Anyone with the required hardware can download an Ethereum client and spin up their own node to participate in the network. This also prevents a single entity from controlling the entire network and contributes to Ethereum's decentralization.
There are four main types of Ethereum nodes, each contributing to the network differently. Together they relay information to other nodes, verify transactions and the EVM state, and provide the infrastructure needed to keep the Ethereum network operating efficiently. They communicate with one another to ensure they all agree on the state of the network. Therefore, having more nodes makes the network more robust and resilient to attacks.
Types of Ethereum Nodes
There are different types of nodes. They vary in features and hardware requirements. Let's check them out one by one.
Full Node
Full nodes verify transactions and EVM state, validate blocks, launch and execute smart contract code, and can serve network data when requested. They also store the state of the Ethereum blockchain up to the most recent 128 blocks but can build an archive of historical states on demand.
Mining Node
A Mining node is a node running a mining client. It's commonly known as a miner. In its present state, Ethereum provides consensus through the proof-of-work algorithm.
To summarize: a mining node competes in a computation race with other mining nodes to create the next block. Once created, the new block is broadcast to the network to be verified by other nodes and appended to the end of the blockchain.
Light Node
A light node is a node that only contains block header data such as the previous block's hash and a timestamp rather than the block data in its entirety. They make on-demand requests to full nodes and only validate certain pieces of the state as required by their users.
Example uses are checking balances, verifying if the network confirmed a transaction, checking event logs, and doing other light-duty tasks. Lower-capacity devices, such as mobile phones or Raspberry Pis, can run light nodes efficiently.
Archive Node
An archive node is a node running in archive mode. It contains all the same data as the full node and all the historical state data of the entire blockchain since the Genesis Block. We'll focus on archive nodes for the remainder of this article.
More on Archive Nodes
Although full nodes can rebuild historical blockchain state data, this process is slow and inefficient. Depending on the use case, this data may need to be served up quickly.
This is where archive Nodes come in. Because archive nodes contain historical data from the very first block, they can easily trace any arbitrary transaction at any time.
Why Access an Archive Node?
If there is information you need to get from the Ethereum blockchain before the most recent 128 blocks, an archive node is the most efficient way to get it. This information may include account balances, smart contract code, transaction counts, or the value at a particular storage position. They also enable the testing of smart contract code without creating a transaction on the blockchain.
Specs to Run an Archive Node
Running your own node means having more control of the information you share with the blockchain. You can create more secure and private decentralized apps (DApps), and your addresses and balances won't leak to random nodes on the network. Running an archive node also means quick access to historical blockchain data without signing up for third-party services.
These are the specifications you would need to be able to run your own Ethereum archive node:
- A CPU with at least four cores
- 16 GB or more of RAM
- An SSD drive with at least 6 TB of space
- At least 25 MBit/s bandwidth
As you can see, the requirements to spin up an archive node make it reasonably accessible. Not exactly cheap, but still within reach to an individual. It does require some technical know-how and constant upkeep, though. If you don't have the time, drive, or equipment to run your own, a node provider is a great alternative.
Archive Node Providers
Node Providers make it simple for anyone to access and interact with the Ethereum blockchain through their easy-to-use APIs. You need to create a new project and call JSON RPC methods with their URL.
Use Cases
Depending on the type of project you are building, several different technologies you could connect to a node provider.
Truffle/Hardhat
If you are writing smart contracts that interact with historical data, a development suite such as Truffle or Hardhat would fit your needs. They both have an assortment of built-in tools that make the entire development lifecycle for your DApp much easier. Connecting to an Archive Node, in this case, is as easy as setting your provided API URL endpoint as a variable to be used in your frontend code.
Ganache
If you need quick access to an archive node for local development or testing, Truffle offers a personal blockchain that accomplishes this nicely. This blockchain is called Ganache. As of Ganache version 7.0, spinning up a local instance of the Ethereum blockchain with archive access is as simple as one command:
"`bash ganache --fork
You could then interact with it similarly as above, using the URL: `http://localhost:8545`, or whatever you set the port to.
#### Direct Integration
If you don't require a suite of blockchain tools, you can use your node provider URL directly in your frontend code and connect it with a JavaScript library such as ethers.js or web3.js. This is the option we will explore in the project below.
## The Project
As mentioned at the start of this article, we will be making a simple "Year in Review" type app to display some wallet statistics from 2021. We will clone a pre-built frontend, so all we have to worry about is querying an archive node and then displaying the data nicely.
#### What We Will Learn
* How to get an Infura API URL with archive access
* How to gather archive data using an Infura API URL and web3.js
* The JavaScript required to collect the data from the blockchain
* How to put the data together to display it nicely in the app
#### What is Needed to Complete the Project
* [An Infura account](https://infura.io/)
* [Git](https://git-scm.com/downloads)
* [Node / npm](https://nodejs.org/en/)
* [A code editor](https://code.visualstudio.com/)
#### Additional Resources
* [Infura docs](https://docs.infura.io/infura)
* [Web3.js docs](https://web3js.readthedocs.io/en/v1.7.0/web3.html)
### The Infura API URL
The first step in our project is to set up our Infura account and acquire our API endpoint URL. Head to https://infura.io/ and either create a new account or log in.
Create a new project to get the API endpoint URL we will need later in our project.
![The Infura project dashboard where we get the RPC endpoint URL](https://cdn.hashnode.com/res/hashnode/image/upload/v1653934864152/jo7aeAjbt.jpg align=" center")
Since archive access is now free for all users, we don't need to complete any other steps with our Infura account.
With that out of the way, let's start working on the frontend!
### The Frontend
We will be building on top of a pre-made React frontend for the rest of this project. If you've never used React before, that's okay. We will be walking through the rest of the steps together.
We will use Git and the node package manager (npm) to install the project. To see if they are already installed, we can check the version numbers in the command line:
"`bash
npm --version
"`bash git --version
If they still need to be installed on your machine, you can get them at the following links:
* Node / npm: [https://nodejs.org/en/](https://nodejs.org/en/)
* Git: [https://git-scm.com/downloads](https://git-scm.com/downloads)
Once installed, we are ready to start working on the rest of the project:
1. In the command line, navigate to the folder you would like to work out of and clone the repository for our project:
"`bash
git clone https://github.com/paul-mcaviney/archive-node-project-frontend.git
Change directories into the new project folder and install the required dependencies: cd archive-node-project-frontend
"`bash npm i ```
After the dependencies finish installing, let's run the project to make sure it's working correctly so far:
"`bash npm start ```
If we installed everything correctly, we would have a frontend running on
http://localhost:3000
that looks like this:![The frontend for our React project. A user inputs an Ethereum wallet address to receive statistics from 2021](https://cdn.hashnode.com/res/hashnode/image/upload/v1653935017102/Wll8hPJjR.jpg align=" center")
There's a text field we will use to enter a wallet address. Clicking the "Submit" button takes us to our results page. We can also return to the input page from here by pressing the "Enter New Address" button.
We need to install one more dependency before we start coding. We will be using web3.js to access an archive node with our Infura URL. To install web3.js, type the following command in the directory for our project:
"`bash npm install web3 ```
We will do all of our coding in the
App.js
file under thesrc
folder. The first bit of code we need to write is to import web3.js to our project and connect it to our Infura URL. Under the import statements and before theApp
function, add the following code:const Web3 = require('web3'); const infuraURL = 'YOUR_INFURA_URL_HERE'; const web3 = new Web3(new Web3.providers.HttpProvider(infuraURL));
Note: Do not upload this project to a public repository without first hiding your actual Infura URL. You can use environment variables for this.
We'll use the
useState
React hook to update our UI. You'll notice it's already imported at the top of our file. Next, let's add some React state variables to make it easier to display the data we gather from our archive node. Under the results state variable, add the following:const [address, setAddress] = useState(''); const [currentBalance, setCurrentBalance] = useState(0); const [startOfYearBalance, setStartOfYearBalance] = useState(0); const [endOfYearBalance, setEndOfYearBalance] = useState(0); const [balanceDifference, setBalanceDifference] = useState(0); const [transactionCount, setTransactionCount] = useState(0);
Now, we need to update the
handleInput
function to assign the user input to our address state variable instead of logging the comment:const handleInput = event => { setAddress(event.target.value); };
Note: You'll notice we didn't put any checks here to make sure what the user inputs is actually an Ethereum wallet address. This is for the sake of keeping this tutorial simple. You will want to handle this differently if deploying publicly.
The last bit of JavaScript is an asynchronous function that will gather the data from the archive node, convert it to more readable values, and set our state variables. Under the comment that says, "Your JavaScript code will go here," type the following code:
// Access and process data from Ethereum blockchain const accessEthereum = async () => { // 2021 Start and End Block variables const START_2021_BLOCK = 11565019; const END_2021_BLOCK = 13916165; // Get current balance of address const balance = await web3.eth.getBalance(address); // Convert balance from wei to ETH and set state variable setCurrentBalance(await web3.utils.fromWei(balance.toString(), 'ether')); // Get wallet balance at the start of 2021 (Block #11565019) const startBalance = await web3.eth.getBalance(address, START_2021_BLOCK); // Get wallet balance at the end of 2021 (Block #13916165) const endBalance = await web3.eth.getBalance(address, END_2021_BLOCK); // Convert startBalance to ETH and set state variable const startBalanceAsETH = await web3.utils.fromWei(startBalance.toString(), 'ether'); setStartOfYearBalance(startBalanceAsETH); // Convert endBalance to ETH and set state variable const endBalanceAsETH = await web3.utils.fromWei(endBalance.toString(), 'ether'); setEndOfYearBalance(endBalanceAsETH); // Set balanceDifference from start to end of 2021 setBalanceDifference(endBalanceAsETH - startBalanceAsETH); // Get transaction count at start of 2021 (Block #11565019) let startTransactions = await web3.eth.getTransactionCount(address, START_2021_BLOCK); // Get transaction count at end of 2021 (Block #13916165) let endTransactions = await web3.eth.getTransactionCount(address, END_2021_BLOCK); // Set total transaction count in 2021 setTransactionCount(endTransactions - startTransactions); // Received results, condition met to show them on screen setResults(true); };
Moving on to the HTML, the first thing we need to do is replace the button function with the new one we just wrote. Change the function call for the button under the "Change this button function" comment:
<button onClick={accessEthereum} className='form-button' type='submit' name='submit' id='submit'>
The final bit of code we need is the HTML that will display the data we gathered from our Archive Node. In the return statement, scroll down to the comment that says "Your HTML code will go here" and add the following:
<h3>{address}</h3> <p className='result-heading'>Current Balance</p> <p>{currentBalance} ETH</p> <p className='result-heading'>Start of 2021 Balance</p> <p>{startOfYearBalance} ETH</p> <p className='result-heading'>End of 2021 Balance</p> <p>{endOfYearBalance} ETH</p> <p className='result-heading'>Difference from Start of 2021</p> <p>{balanceDifference} ETH</p> <p className='result-heading'>Number of transactions in 2021</p> <p>{transactionCount}</p> <br />
To see the complete project code, check out this Github repository.
Now, let's test our app and see if it works! First, start the app:
"`bash npm start ```
Enter an Ethereum wallet address to the text field and hit "Submit." If you don't have a wallet address active in 2021, you can use Vitalik's.
![The results from querying an archive node for wallet stats for 2021](https://cdn.hashnode.com/res/hashnode/image/upload/v1653935901369/IVXnHTr79.jpg align=" left")
Awesome! Our results are displayed correctly, and we can see all the activity of the wallet address in 2021!
Conclusion
By following this tutorial, you accessed the data on an Archive Node using your Infura API endpoint URL, then displayed it nicely in a simple "ETH Year in Review"-app.
An archive node must access data from the Ethereum blockchain before the most recent 128 blocks. They store all historical state data from the first block and serve it up much more quickly and efficiently than a full node. Now that Infura offers free archive node access to all users gathering historical blockchain data has never been easier!