Skip to main content

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',
});