Viem
Overview
Viem is a high-performance, TypeScript-first Ethereum development library, providing robust tools for interacting with blockchains, smart contracts, and accounts. It offers first-class support for chains implemented on the OP Stack, including Soneium Minato.
Install
To install Viem, run the following command:
$ pnpm i viem
Setting Up the Client & Transport
To begin using Viem, set up your client and transport mechanism as shown below:
import { createPublicClient, http } from 'viem';
import { soneiumMinato } from "viem/chains";
const publicClient = createPublicClient({
chain: soneiumMinato,
transport: http(),
});
Reading Data from Soneium Minato
You can use the Public Client to read data from Soneium Minato using Public Actions.
Public Action is an action that maps one-to-one with a "public" Ethereum RPC method (eth_blockNumber
, eth_getBalance
, etc). They are used with a Public Client.
For instance, to get the balance of a specific wallet address, you can use the getBalance
method:
import { publicClient } from './client'
const balance = await publicClient.getBalance({
address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
})
console.log(balance); // 10000000000000000000000n (wei)
Writing Data to Soneium Minato
To send transactions or interact with accounts, you need to create a Wallet Client using createWalletClient
. This allows you to manage accounts, sign messages, and execute transactions via Wallet Actions.
The createWalletClient
function sets up a Wallet Client with a given Transport.
Here’s how to set up a Wallet Client:
import { createWalletClient, custom } from 'viem'
import { soneiumMinato } from "viem/chains";
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
const walletClient = createWalletClient({
account,
chain: soneiumMinato,
transport: custom(window.ethereum),
});
// Example of sending a transaction
walletClient.sendTransaction({ ... });
Interacting with Smart contracts
Viem allows you to interact with smart contracts in a type-safe way by creating a Contract Instance with a specific ABI and contract address. The instance is created using the getContract
function.
Below is an example of interacting with an ERC20 contract on Soneium Minato:
import { getContract, erc20Abi } from 'viem';
import { publicClient } from './client';
import { USDC_ADDRESS, SENDER_ADDRESS, SPENDER_ADDRESS } from './config'
const contract = getContract({
address: USDC_ADDRESS,
abi: erc20Abi,
client: publicClient,
});
// Read the value from the contract
const allowance = await contract.read.allowance([SENDER_ADDRESS, SPENDER_ADDRESS]);
// Send contract function
const amount = "1000000";
const txParam = {
account: SENDER_ADDRESS,
address: USDC_ADDRESS,
abi: erc20Abi,
functionName: "approve",
args: [SPENDER_ADDRESS, amount],
};
const { request } = await publicClient.simulateContract({
...txParam,
});
const hash = await walletClient.writeContract(request);
Getting Started with OP Stack
Viem simplifies interacting with OP Stack features, allowing developers to extend their Client with OP Stack Actions.
1. Extend Client with the OP Stack
You can extend the Public Client with OP Stack Actions (Read more):
import { createPublicClient, http } from 'viem';
import { soneiumMinato } from "viem/chains";
import { publicActionsL2 } from 'viem/op-stack';
const publicClient = createPublicClient({
chain: soneiumMinato,
transport: http(),
}).extend(publicActionsL2());
2. Consume OP Stack Actions
With your OP Stack Client ready, you can now interact with OP Stack-specific actions, such as estimating the total gas required for contract execution:
import { createPublicClient, http } from 'viem';
import { soneiumMinato } from "viem/chains";
import { publicActionsL2 } from 'viem/op-stack';
import { SENDER_ADDRESS, CONTRACT_ADDRESS } from './config'
import { tokenAbi } from './abi'
const publicClient = createPublicClient({
chain: soneiumMinato,
transport: http(),
}).extend(publicActionsL2());
const gas = await publicClient.estimateContractTotalGas({
account: SENDER_ADDRESS,
address: CONTRACT_ADDRESS,
abi: tokenAbi,
functionName: 'mint',
});