Documentation Index
Fetch the complete documentation index at: https://seilabs-docs-evm-reference-and-sei-js-examples.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Action required: IBC assets on Sei will become inaccessible If you hold USDC.n (USDC via Noble), USDT.kava (Kava USDT), Wormhole-bridged tokens, or any other IBC asset on Sei, you must swap, migrate, or bridge out before the governance proposal to disable inbound/outbound IBC transfers passes and is activated to avoid permanent loss of access. After this, Sei will no longer support IBC bridging of assets from Cosmos-based chains to and from Sei Network. Consult the SIP-03 Migration Guide for the full list of affected assets, required actions, and supported routes. For USDC.n specifically, see: Holders of USDC.n Need to Swap or Migrate.
Reading and writing ERC-721 NFTs on Sei with viem and ethers
Documentation Index
Fetch the complete documentation index at: https://seilabs-docs-evm-reference-and-sei-js-examples.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
import { createPublicClient, createWalletClient, http, parseAbi } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sei } from '@sei-js/precompiles/viem';
const client = createPublicClient({ chain: sei, transport: http() });
const account = privateKeyToAccount('0xYourPrivateKey');
const walletClient = createWalletClient({ account, chain: sei, transport: http() });
const ERC721_ABI = parseAbi([
'function name() view returns (string)',
'function symbol() view returns (string)',
'function totalSupply() view returns (uint256)',
'function balanceOf(address owner) view returns (uint256)',
'function ownerOf(uint256 tokenId) view returns (address)',
'function tokenURI(uint256 tokenId) view returns (string)',
'function getApproved(uint256 tokenId) view returns (address)',
'function isApprovedForAll(address owner, address operator) view returns (bool)',
'function approve(address to, uint256 tokenId)',
'function setApprovalForAll(address operator, bool approved)',
'function transferFrom(address from, address to, uint256 tokenId)',
'function safeTransferFrom(address from, address to, uint256 tokenId)',
'event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)',
'event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)',
]);
const NFT = '0xNFTContractAddress';
const tokenId = 1n;
const [owner, uri, approved] = await Promise.all([
client.readContract({ address: NFT, abi: ERC721_ABI, functionName: 'ownerOf', args: [tokenId] }),
client.readContract({ address: NFT, abi: ERC721_ABI, functionName: 'tokenURI', args: [tokenId] }),
client.readContract({ address: NFT, abi: ERC721_ABI, functionName: 'getApproved', args: [tokenId] }),
]);
const balance = await client.readContract({
address: NFT,
abi: ERC721_ABI,
functionName: 'balanceOf',
args: ['0xOwnerAddress'],
});
const hash = await walletClient.writeContract({
address: NFT,
abi: ERC721_ABI,
functionName: 'safeTransferFrom',
args: [account.address, '0xRecipient', 1n],
});
const receipt = await client.waitForTransactionReceipt({ hash });
const hash = await walletClient.writeContract({
address: NFT,
abi: ERC721_ABI,
functionName: 'approve',
args: ['0xOperatorAddress', 1n],
});
// Grant operator approval
const hash = await walletClient.writeContract({
address: NFT,
abi: ERC721_ABI,
functionName: 'setApprovalForAll',
args: ['0xOperatorAddress', true],
});
// Revoke
const revokeHash = await walletClient.writeContract({
address: NFT,
abi: ERC721_ABI,
functionName: 'setApprovalForAll',
args: ['0xOperatorAddress', false],
});
const unwatch = client.watchContractEvent({
address: NFT,
abi: ERC721_ABI,
eventName: 'Transfer',
onLogs: (logs) => {
logs.forEach(({ args }) => {
console.log(`Token ${args.tokenId}: ${args.from} → ${args.to}`);
});
},
});
// Stop watching
unwatch();