Rust: Talk to the Ethereum Blockchain
Rust is amazing and with the web3 crate, you can talk to the Ethereum blockchain.
Photo by Shubham Dhage on Unsplash
Objective
In this tutorial, we will connect to an Ethereum node (provided by infura) using the web3 crate and fetch the ether balance of a particular address.
But wait, what is Infura and why do we need access to an Ethereum node?
You can think of the Ethereum Blockchain as many computers (or nodes) connected to each other. Now, to talk to the blockchain you will need access to one of these nodes, won't you?
But, Running a node is not always feasible for everyone. Enter Infura, which provides access to an Ethereum node using its APIs.
GitHub repo containing all the code
Find the code here: https://github.com/codetit4n/rust-web3-basics
You can star/fork this over github.
Dependencies needed
The dependencies we need for this are:
web3 crate: For web3 interactions.
tokio crate: For async code.
dotenv crate: For handling environment variables.
Setting up environment variables
Now create a .env file which will have 2 environment variables:
INFURA_WSS: This will have the web socket URL from Infura. It will look something like "wss://mainnet.infura.io/ws/v3<API_KEY>". Here replace API_KEY will be your API key generated by Infura. This will give us access to an ethereum node.
ACCOUNT_ADDRESS: Here put any ethereum account address for which you want to fetch the balance.
For reference: https://github.com/codetit4n/rust-web3-basics/blob/master/.env.example
Importing types for handling web3 data
use web3::types::{H160, U256};
Here we are importing H160 and U256 types from the web3 crate.
The H160 type will be used for Ethereum addresses and U256 for 256-bit unsigned integers.
Code walkthrough
The code looks like:
use std::env;
use std::str::FromStr;
use web3::types::{H160, U256};
#[tokio::main]
async fn main() -> web3::Result<()> {
dotenv::dotenv().ok();
let websocket = web3::transports::WebSocket::new(&env::var("INFURA_WSS").unwrap()).await?;
let web3s = web3::Web3::new(websocket);
let account = H160::from_str(&env::var("ACCOUNT_ADDRESS").unwrap());
let balance = web3s.eth().balance(account.unwrap(), None).await?;
println!("Wei balance of {:?}: {:?} wei", account.unwrap(), balance);
let wei_conv: U256 = U256::exp10(18);
println!(
"ETH balance of {:?}: {} ETH",
account.unwrap(),
balance.checked_div(wei_conv).unwrap()
);
Ok(())
}
After setting up tokio and dotenv, I have created connection with the Ethereum Blockchain like this:
let websocket = web3::transports::WebSocket::new(&env::var("INFURA_WSS").unwrap()).await?;
Here, note we are taking the wss link from the .env file and also using await since this will be an asynchronous connection.
Next, create a web3 instance using the websocket:
let web3s = web3::Web3::new(websocket);
Get the account from the environment variables:
let account = H160::from_str(&env::var("ACCOUNT_ADDRESS").unwrap());
Now, fetch the balance using the web3 instance like:
let balance = web3s.eth().balance(account.unwrap(), None).await?;
This will give the balance in wei.
Now, lets convert this to ether. Since:
$$1 ETH = 10^{18} wei$$
We can get this value in rust using:
let wei_conv: U256 = U256::exp10(18);
Now, we will divide the wei balance by this number to get the approximate ether balance:
println!(
"ETH balance of {:?}: {} ETH",
account.unwrap(),
balance.checked_div(wei_conv).unwrap()
);
This will print the approximate ETH balance.
Output
Run the code using
cargo run
Thanks!