Skip to main content

Use Viem

In this tutorial, you'll send a transaction of 0.001 ETH from one account to another using the Viem TypeScript library.

Prerequisites

info

Use MetaMask or similar to create an Ethereum account for testing.

Steps

1. Select your network and verify funds

  • Sepolia - To use the Sepolia testnet, ensure that your account has Sepolia ETH. You can use the MetaMask faucet to add more funds.

  • Alternative network - To use an alternative network, ensure that your account has testnet ETH for that network.

    note

    When using an alternative network, update the chain name in the script (in Step 6) with the alternative network name from the Viem supported chains list.

2. Create a project directory

Create a new directory for your project using the command line:

mkdir infura

Change into the new directory:

cd infura

3. Initialize the project

Create a package.json file with default values:

npm init -y

Generate a tsconfig.json file, which is used to configure TypeScript compiler options:

tsc --init --resolveJsonModule true

4. Install the required packages

Install the required packages in the project directory.

npm i viem
npm install -D tslib @types/node

5. Create a config.ts file

Create a config.ts file in your project directory to store the private key of the sending account:

config.ts
import { privateKeyToAccount } from "viem/accounts"
export const account = privateKeyToAccount("<PRIVATE-KEY>")

In the config.ts file, replace <PRIVATE-KEY> with the private key of your Ethereum account. A transaction must be signed with the sender's private key. Make sure that you prefix the private key value with 0x. The private key you export from MetaMask isn't prefixed with 0x.

danger

Never disclose your private key. Anyone with your private keys can steal the assets controlled by those keys.

6. Create a sendTransaction.ts file

In the project directory, create a sendTransaction.ts file, which configures and sends the transaction. For example:

import { http, createWalletClient, parseEther } from "viem"
import { sepolia } from "viem/chains"
import { account } from "./config"

// Create a wallet client to interact with Ethereum accounts.
const walletClient = createWalletClient({
chain: sepolia,
transport: http("https://sepolia.infura.io/v3/<YOUR-API-KEY>")
})

async function sendTx() {
// Create and send the transaction object.
const hash = await walletClient.sendTransaction({
account,
to: "0xc2CB3fb3924b8DE3A63C1da570a8dBaf2a533eA7",
value : parseEther ("0.001")
})

console.log("Mining transaction... ")
console.log(`Tx mined in https://sepolia.etherscan.io/tx/${hash}`)
}

sendTx()

In the sendTransaction.ts file:

  • Update the chain name if you're using an alternative network.
  • Replace <YOUR-API-KEY> with your Infura API key.
  • Update the to account in the code if you wish to send test ETH to an account of your choice.

7. Execute the transaction

To execute the transaction, run:

ts-node sendTransaction.ts
note

ts-node is a TypeScript execution engine for Node.js. It allows you to run TypeScript files without manually compiling them into JavaScript first.

An alternative way to execute your transaction using Node.js is to compile your sendTransaction.ts file to JavaScript first, and then run the compiled JavaScript file:

tsc sendTransaction.ts
node sendTransaction.js

You can also run the TypeScript file, sendTransaction.ts, directly from your code development environment (such as VS Code) without using ts-node or pre-compiling to JavaScript. The following is an example output:

Mining transcation...
Tx mined https://sepolia.etherscan.io/tx/0x310588719e733118f50c0a1608e13b4e8bd5eb5891d546d89795c2041833abb6

You can search for the transaction on a block explorer such as Sepolia Etherscan.

8. (Optional) Fine tune the transaction details

Viem automatically determines the gas limit and fees. If you want to change the default values, update the sendTransaction method to include an estimateGas result (gasLimit) and the maxFeePerGas and maxPriorityFeePerGas parameters.

To do this you will also need to declare an httpClient to interface with JSON-RPC methods like eth_estimateGas.

The following is a full code overview:

import { http, createWalletClient, createPublicClient, parseEther, parseGwei } from "viem"
import { sepolia } from "viem/chains"
import { account } from "./config"

// Create a wallet client to interact with Ethereum accounts.
const walletClient = createWalletClient({
chain: sepolia,
transport: http("https://sepolia.infura.io/v3/<YOUR-API-KEY>")
})

// Create a public client to interact with JSON-RPC API methods.
const httpClient = createPublicClient({
chain: sepolia,
transport: http("https://sepolia.infura.io/v3/<YOUR-API-KEY>"),
})

async function sendTx() {
// Estimate gas limit.
const limit = await httpClient.estimateGas({
account,
to: "0xc2CB3fb3924b8DE3A63C1da570a8dBaf2a533eA7",
value: parseEther("0.001")
})

// Create and send the transaction object.
const hash = await walletClient.sendTransaction({
account,
to: "0xc2CB3fb3924b8DE3A63C1da570a8dBaf2a533eA7",
value : parseEther ("0.001"),
maxFeePerGas: parseGwei("20"),
maxPriorityFeePerGas: parseGwei ("2"),
gas: limit,
})

console.log("Mining transaction... ")
console.log(`Tx: https://sepolia.etherscan.io/tx/${hash}`)

}

sendTx()