BlockReq
Back to all articles

Rpc Tutorials

Using BlockReq RPC with viem

Set up viem public clients for BlockReq Ethereum and Base RPC endpoints with clear chain matching and timeout boundaries.

BlockReq EngineeringJuly 1, 20266 min read

Using BlockReq RPC with viem

viem separates chain metadata from the transport that talks to JSON-RPC. That split is useful with BlockReq because you can make endpoint selection explicit and keep the client type-safe.

pnpm add viem
export BLOCKREQ_ETH_RPC_URL="https://ethereum-rpc.blockreq.com/v1/rpc/public"
export BLOCKREQ_BASE_RPC_URL="https://base-rpc.blockreq.com/v1/rpc/public"

Start with a public client for read-only JSON-RPC calls. Match the chain value to the BlockReq endpoint you pass into http.

import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";

const rpcUrl = process.env.BLOCKREQ_ETH_RPC_URL;

if (!rpcUrl) {
  throw new Error("BLOCKREQ_ETH_RPC_URL is required");
}

export const ethereumClient = createPublicClient({
  chain: mainnet,
  transport: http(rpcUrl, {
    timeout: 10_000,
  }),
});

const chainId = await ethereumClient.getChainId();
const blockNumber = await ethereumClient.getBlockNumber();

console.log({ chainId, blockNumber });

Use a second client for Base instead of swapping only the URL. This makes the chain id expectation obvious in code review.

import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

const rpcUrl = process.env.BLOCKREQ_BASE_RPC_URL;

if (!rpcUrl) {
  throw new Error("BLOCKREQ_BASE_RPC_URL is required");
}

export const baseClient = createPublicClient({
  chain: base,
  transport: http(rpcUrl),
});

Contract reads

For contract reads, keep ABIs small and colocated with the code path that needs them. The example below reads ERC-20 metadata through a normal eth_call.

const erc20Abi = [
  {
    type: "function",
    name: "decimals",
    stateMutability: "view",
    inputs: [],
    outputs: [{ type: "uint8" }],
  },
] as const;

const decimals = await ethereumClient.readContract({
  address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  abi: erc20Abi,
  functionName: "decimals",
});

console.log({ decimals });

Production guardrails

Check getChainId during startup or health checks when a service is configured dynamically. If you use WebSocket subscriptions, use a WSS endpoint that is meant for subscriptions and verify the route supports the subscription method you need. Do not assume HTTP endpoints support subscription behavior.