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
These snippets are TypeScript. Run any of them with no separate build step using tsx (Node 18+):
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