Integration Examples
Practical patterns for wiring Elysium reads into React applications.
These examples show how to integrate Elysium reads into React and Next.js applications. The chain access is real and runnable. Where Sigil parsing appears, it uses the draft parser from Reading Sigils.
Latest block in React
A small hook built on SWR and viem. SWR handles caching, deduplication and polling.
'use client'
import useSWR from 'swr'
import { publicClient } from '@/lib/client'
export function useLatestBlock(refreshInterval = 5000) {
return useSWR(
'elysium:latest-block',
() => publicClient.getBlock({ blockTag: 'latest' }),
{ refreshInterval },
)
}Look up a transaction
A client component that reads a transaction and its receipt by hash and shows whether its input parses as a draft envelope.
'use client'
import { useState } from 'react'
import useSWR from 'swr'
import { isHash, type Hash } from 'viem'
import { publicClient } from '@/lib/client'
import { parseSigil } from '@/lib/parse-sigil'
async function lookup(hash: Hash) {
const [tx, receipt] = await Promise.all([
publicClient.getTransaction({ hash }),
publicClient.getTransactionReceipt({ hash }),
])
return { tx, receipt, envelope: parseSigil(tx.input) }
}
export function TransactionLookup() {
const [hash, setHash] = useState('')
const valid = isHash(hash)
const { data, error, isLoading } = useSWR(valid ? ['tx', hash] : null, () => lookup(hash as Hash))
return (
<div>
<label htmlFor="tx-hash">Transaction hash</label>
<input id="tx-hash" value={hash} onChange={(e) => setHash(e.target.value.trim())} />
{isLoading && <p>Loading…</p>}
{error && <p>Transaction not found on Elysium Testnet.</p>}
{data && (
<dl>
<dt>Status</dt>
<dd>{data.receipt.status}</dd>
<dt>Block</dt>
<dd>{data.receipt.blockNumber.toString()}</dd>
<dt>Draft envelope</dt>
<dd>{data.envelope ? JSON.stringify(data.envelope) : 'None'}</dd>
</dl>
)}
</div>
)
}Server-side reads in Next.js
Reading on the server keeps provider API keys out of the browser. Store the endpoint in an environment variable and create the client in server code only.
import 'server-only'
import { createPublicClient, http } from 'viem'
import { elysiumTestnet } from './elysium'
export const serverClient = createPublicClient({
chain: elysiumTestnet,
transport: http(process.env.ELYSIUM_RPC_URL),
})If ELYSIUM_RPC_URL is unset, viem falls back to the chain's default public RPC.
Serializing bigint values
viem returns block numbers, balances and gas values as bigint. JSON.stringify cannot serialize bigint, so convert values to strings before returning them from an API, as in the route above.
Switching the connected wallet
When an application needs the user on Elysium Testnet, request a switch and fall back to adding the chain if the wallet does not know it.
import 'viem/window'
import { createWalletClient, custom, SwitchChainError } from 'viem'
import { elysiumTestnet } from '@/lib/elysium'
const walletClient = createWalletClient({ transport: custom(window.ethereum!) })
try {
await walletClient.switchChain({ id: elysiumTestnet.id })
} catch (error) {
if (error instanceof SwitchChainError || (error as { code?: number }).code === 4902) {
await walletClient.addChain({ chain: elysiumTestnet })
} else {
throw error
}
}