A front end needs the deployed address and ABI to build a contract instance, then calls read (`view`) functions freely and prompts the user's wallet to sign write (state-changing) transactions.
import { createPublicClient, http, getContract } from "viem";
const contract = getContract({
address: "0xYourContract",
abi: vyperAbi,
client: publicClient,
});
const rate = await contract.read.rate();Writes go through the user's wallet (e.g. MetaMask) so they can review gas cost and the exact calldata before signing — the dApp never has custody of the user's private key.