LibChain Docs Lib Testnet

Build

Build a dApp

Connect browser wallets with EIP-6963, switch them to Lib Testnet, read balances and send transactions with viem or ethers, or drop in Reown AppKit.

A LibChain dApp is an Ethereum dApp pointed at chain 54210. This page covers the pieces you'll write: finding wallets, connecting, switching network, reading and writing.

#1. Find the user's wallets

Use EIP-6963 discovery rather than window.ethereum: several wallets can be installed at once, and each announces itself with a name and icon. Lib Wallet announces itself this way.

TypeScript
type Announced = { info: { uuid: string; name: string; icon: string; rdns: string }; provider: any }

const wallets = new Map<string, Announced>()
window.addEventListener('eip6963:announceProvider', (e: any) => {
  wallets.set(e.detail.info.uuid, e.detail)
})
window.dispatchEvent(new Event('eip6963:requestProvider'))

#2. Connect and switch to Lib Testnet

TypeScript
const LIB = {
  chainId: '0xd3c2',
  chainName: 'Lib Testnet',
  nativeCurrency: { name: 'Lib Test Coin', symbol: 'tLIB', decimals: 18 },
  rpcUrls: ['https://rpc-testnet.libchain.tech'],
  blockExplorerUrls: ['https://testnet.libchain.tech'],
}

async function connect(provider: any) {
  const [account] = await provider.request({ method: 'eth_requestAccounts' })
  try {
    await provider.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: LIB.chainId }] })
  } catch (e: any) {
    if (e.code !== 4902) throw e // 4902: the wallet doesn't know the chain yet
    await provider.request({ method: 'wallet_addEthereumChain', params: [LIB] })
  }
  return account as string
}

Listen for accountsChanged and chainChanged on the provider and update your UI when they fire.

#3. Read and write

TypeScript
import { createPublicClient, createWalletClient, custom, http, parseEther, formatEther } from 'viem'
import { libTestnet } from './chains' // see Network details

const client = createPublicClient({ chain: libTestnet, transport: http() })
const wallet = createWalletClient({ chain: libTestnet, transport: custom(provider) })

const balance = await client.getBalance({ address: account })
console.log(formatEther(balance), 'tLIB')

const hash = await wallet.sendTransaction({ account, to: '0xRecipient', value: parseEther('1') })
const receipt = await client.waitForTransactionReceipt({ hash }) // final in its block
TypeScript
import { BrowserProvider, JsonRpcProvider, parseEther, formatEther } from 'ethers'

const reader = new JsonRpcProvider('https://rpc-testnet.libchain.tech', 54210, { staticNetwork: true })
const signer = await new BrowserProvider(provider).getSigner()

console.log(formatEther(await reader.getBalance(await signer.getAddress())), 'tLIB')

const tx = await signer.sendTransaction({ to: '0xRecipient', value: parseEther('1') })
const receipt = await tx.wait() // one confirmation is final

Read through the public RPC (http() or JsonRpcProvider) and only use the wallet's provider to sign. That keeps reads fast and keeps working when the wallet is locked.

#4. Call a contract

TypeScript
import { parseAbi } from 'viem'

const abi = parseAbi([
  'function balanceOf(address) view returns (uint256)',
  'function deposit() payable',
])

const wrapped = await client.readContract({ address: '0x87052f1f17b2b4054b014e93e53d6ce6dc912bda', abi, functionName: 'balanceOf', args: [account] })
await wallet.writeContract({ account, address: '0x87052f1f17b2b4054b014e93e53d6ce6dc912bda', abi, functionName: 'deposit', value: parseEther('0.5') })

#Using wagmi

wagmi.ts
import { createConfig, http } from 'wagmi'
import { injected } from 'wagmi/connectors'
import { libTestnet } from './chains'

export const config = createConfig({
  chains: [libTestnet],
  connectors: [injected()],
  transports: { [libTestnet.id]: http() },
})

#A ready-made connect modal

Reown AppKit gives you a connect modal with browser wallets and WalletConnect for phones. It's what Lib Explorer and LibChain Hub use. Pass the Lib Testnet chain from viem's defineChain (or AppKit's own defineChain) and your own Reown project ID, and add your domain to the project's allowlist in the Reown dashboard.

#UX that fits LibChain

  • Show lib1, accept both. Display addresses in lib1 form and accept lib1 or 0x in inputs. See lib1 in your app.
  • Mark success at the receipt. There's nothing to wait for after it. See Blocks and finality.
  • Say it's testnet. Label balances as test coins with no value.
  • Link to the explorer. https://testnet.libchain.tech/tx/<hash> and https://testnet.libchain.tech/address/<address>.
Updated 5 November 2026LibChain Docs · Lib Testnet