Skip to main content

Documentation Index

Fetch the complete documentation index at: https://seilabs-docs-evm-fixes-hardhat-v3.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

viem Quickstart

This example shows how to use viem with Sei outside of a React context — in a Node.js script, CLI tool, or backend service. For React apps, see wagmi and the frontend guide.

Install

npm install viem
These snippets are TypeScript. Run any of them with no separate build step using tsx (Node 18+):
npx tsx script.ts

Public Client

A public client handles all read-only operations.
import { createPublicClient, http } from 'viem';
import { sei } from 'viem/chains';

const client = createPublicClient({
  chain: sei,
  transport: http(),
});
To use a custom RPC endpoint, pass the URL to http():
const client = createPublicClient({
  chain: sei,
  transport: http('https://evm-rpc.sei-apis.com'),
});

Reading Chain Data

This is the first milestone — it needs no private key.
import { formatEther } from 'viem';

// Any valid Sei EVM address — swap in your own
const address = '0x0000000000000000000000000000000000000000';

const blockNumber = await client.getBlockNumber(); // bigint
console.log('Block number:', blockNumber);

const balance = await client.getBalance({ address }); // bigint, wei
console.log('Balance (SEI):', formatEther(balance));

const nonce = await client.getTransactionCount({ address }); // number
console.log('Nonce:', nonce);
You’re done when you see:
Block number: 148203117n
Balance (SEI): 12.5
Nonce: 7
The exact numbers are illustrative — your block number and balance will differ. Note the trailing n: getBlockNumber() and getBalance() return bigint, while getTransactionCount() returns a number.

Wallet Client

A wallet client handles signing and broadcasting transactions.
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sei } from 'viem/chains';

const account = privateKeyToAccount('0xYourPrivateKey');

const walletClient = createWalletClient({
  account,
  chain: sei,
  transport: http(),
});
For browser use, replace http() with custom(window.ethereum) and call walletClient.getAddresses() to get the connected account.

Sending a Transaction

Next step — this requires a funded account; get testnet SEI from the faucet.
import { parseEther } from 'viem';

const hash = await walletClient.sendTransaction({
  to: '0xRecipient',
  value: parseEther('1'),
});

const receipt = await client.waitForTransactionReceipt({ hash });
// receipt is final immediately — Sei has instant finality

Reading a Contract

import { parseAbi } from 'viem';

const abi = parseAbi(['function balanceOf(address owner) view returns (uint256)']);

const balance = await client.readContract({
  address: '0xTokenAddress',
  abi,
  functionName: 'balanceOf',
  args: ['0xYourAddress'],
});

Writing to a Contract

const hash = await walletClient.writeContract({
  address: '0xTokenAddress',
  abi,
  functionName: 'transfer',
  args: ['0xRecipient', 1_000_000n],
});

const receipt = await client.waitForTransactionReceipt({ hash });

Simulating Before Writing

const { result } = await client.simulateContract({
  address: '0xTokenAddress',
  abi,
  functionName: 'transfer',
  args: ['0xRecipient', 1_000_000n],
  account,
});

// If simulation succeeds, execute it
const hash = await walletClient.writeContract(result);

Estimating Gas

Always use estimateGas rather than hard-coding values. SSTORE costs on Sei are governance-adjustable.
const gas = await client.estimateGas({
  account,
  to: '0xContractAddress',
  data: '0xCalldata',
});

Next Steps