Integrations / TypeScript Client
Quai viem Integration
viem works with Quai today through the path most modern dApps already use: an injected EIP-1193 provider. With Pelagus wallet as the transport, viem wallet clients connect accounts and route requests — and the quais SDK covers programmatic transaction flows the node's quai_ namespace requires.
- Works via
- Pelagus injected provider (EIP-1193)
- Chain ID
- 9 (mainnet) · 15000 (Orchard)
- Pair with
- quais SDK for programmatic transactions
- Explorer
- quaiscan.io
How viem fits Quai
Quai's official position is pragmatic: tools like viem, WAGMI, and Ethers work out of the box for web-based dApp development as long as Pelagus wallet is the injected provider. In that architecture, viem's wallet client hands requests to the wallet over EIP-1193, and Pelagus — built for Quai — translates them for the network. Your TypeScript stays viem-flavored: typed, tree-shakeable, modern.
The boundary appears when viem talks to a Quai node directly. A public client over plain HTTP transport issues eth_ namespace calls, but Quai nodes serve quai_ methods across a hierarchy of zone chains with sharded addresses. For those paths — backend scripts, transaction construction outside a wallet, multi-zone routing — the quais SDK (a maintained Ethers v6 fork) is the supported tool, and viem's own viem-to-ethers migration guide maps the concepts almost mechanically.
In practice, teams capture the best of both: viem for the wallet-connected frontend surface, quais for everything that touches the node directly.
Wire viem into a Quai dApp
- 1
Install viem
Standard installation — your existing viem version works.
terminalbash npm install viem - 2
Define the Quai chain
Quai isn't bundled in viem/chains yet, so declare it with defineChain. Use chain ID 9 for mainnet or 15000 for the Orchard testnet.
chains/quai.tstypescript import { defineChain } from "viem"; export const quai = defineChain({ id: 9, name: "Quai Network", nativeCurrency: { name: "Quai", symbol: "QUAI", decimals: 18 }, rpcUrls: { default: { http: ["https://rpc.quai.network/cyprus1"] }, }, blockExplorers: { default: { name: "Quaiscan", url: "https://quaiscan.io" }, }, }); - 3
Create a wallet client over Pelagus
Use custom() transport with the injected window.pelagus provider — the same pattern as custom(window.ethereum) on Ethereum.
terminaltypescript import { createWalletClient, custom } from "viem"; import { quai } from "./chains/quai"; const client = createWalletClient({ chain: quai, transport: custom(window.pelagus), }); const [account] = await client.requestAddresses(); - 4
Add quais for programmatic flows
For transaction construction outside the wallet, backend jobs, or multi-zone routing, install quais alongside viem and let each do what it does best.
terminalbash npm install quais
Where viem earns its place
Modern dApp frontends
Keep viem's typed contract interfaces and composable clients for the user-facing layer, with Pelagus handling Quai-specific signing.
Migrating existing viem apps
A viem codebase reaches Quai by swapping the chain definition and transport — UI logic and types stay intact.
TypeScript-first teams
viem's inference over ABIs keeps end-to-end type safety in the frontend while quais covers node-level operations.
Hybrid stacks
Wallet UX in viem, settlement and indexing in quais — a clean seam that mirrors how the tools are built.
Connect a viem wallet client to Quai
Chain definition plus wallet client over the Pelagus injected provider — the complete connection path for a Quai dApp frontend.
import { createWalletClient, custom, defineChain } from "viem";
export const quai = defineChain({
id: 9,
name: "Quai Network",
nativeCurrency: { name: "Quai", symbol: "QUAI", decimals: 18 },
rpcUrls: { default: { http: ["https://rpc.quai.network/cyprus1"] } },
blockExplorers: { default: { name: "Quaiscan", url: "https://quaiscan.io" } },
});
export async function connect() {
if (typeof window.pelagus === "undefined") {
window.open("https://pelaguswallet.io", "_blank");
throw new Error("Pelagus wallet not installed");
}
const client = createWalletClient({
chain: quai,
transport: custom(window.pelagus),
});
const [account] = await client.requestAddresses();
return { client, account };
}Frequently asked questions
Does viem work with Quai Network?
Yes, for web dApps using Pelagus wallet as the injected provider — viem's wallet client over custom(window.pelagus) connects accounts and routes requests through the wallet. For direct node communication and programmatic transactions, pair it with the quais SDK, since Quai nodes expose a quai_ JSON-RPC namespace.
Can I use viem's public client against Quai RPC endpoints?
Not reliably. Public clients over HTTP transport issue eth_ namespace methods, while Quai nodes serve quai_ methods. Route reads through the Pelagus provider or use quais for direct node queries.
Is there an official Quai chain in viem/chains?
Not yet — define it yourself with defineChain using chain ID 9, the QUAI native currency, and quaiscan.io as the explorer. The snippet on this page is a complete definition you can copy.
How do I migrate fully from viem to quais?
quais is a fork of Ethers v6, so viem's official viem-to-ethers migration guide maps almost one-to-one: publicClient becomes a JsonRpcProvider, walletClient becomes a Wallet or BrowserProvider signer, and getContract becomes new Contract.
Does WAGMI work on Quai?
Like viem, WAGMI functions in the browser when Pelagus is the injected provider, since requests flow through the wallet. Anything beyond wallet-mediated interaction should use the quais SDK.
Bring your viem stack to Quai
One chain definition, one transport swap, and your dApp is talking to a scalable proof-of-work network.