The popular Viem + Wagmi frontend setup can be used with Sophon. This section will provide a working PoC repository, relevant code snippets, and some cool gotchas that will help you working with this stack.
Check out our simple PoC repository that demonstrates how to use Viem and Wagmi together with the Paymaster .
Using Viem
with a Paymaster
When building dApps on Sophon, it’s important to correctly integrate our Paymaster to sponsor transactions, especially before $SOPH is distributed.
This guide provides a working pattern, using Viem
and Wagmi
, for sending contract calls with Paymaster support on Sophon.
✅ Working Code Snippet
"use client";
import { getAccount, getPublicClient, switchChain, writeContract } from "@wagmi/core";
import {
Abi,
AbiItemArgs,
Address,
createWalletClient,
custom,
encodeFunctionData,
Hash,
Hex,
} from "viem";
import { Config } from "Wagmi";
import { eip712WalletActions, getGeneralPaymasterInput } from "viem/zksync";
import { sophonTestnet, sophonMainnet } from "viem/chains";
export default async function sendTransaction(
wagmiConfig: Config,
chainId: number,
address: Address,
abi: Abi,
functionName: string,
args: AbiItemArgs,
value?: bigint
): Promise<Hash> {
const account = getAccount(wagmiConfig);
if (!account.address) throw new Error("No account connected.");
if (account.chainId !== chainId) await switchChain(wagmiConfig, { chainId });
const publicClient = getPublicClient(wagmiConfig, { chainId });
if (!publicClient) throw new Error("No public client available.");
const estimateGas = await publicClient.estimateContractGas({
account: account.address,
address,
abi,
functionName,
args,
value,
});
if (chainId === 50104 || chainId === 531050104) {
const walletClient = createWalletClient({
chain: chainId === 50104 ? sophonMainnet : sophonTestnet
transport: custom(window.ethereum!),
}).extend(eip712WalletActions());
const paymaster: Address = "0x98546B226dbbA8230cf620635a1e4ab01F6A99B2";
const paymasterInput: Hex = getGeneralPaymasterInput({
innerInput: "0x",
});
const txData = encodeFunctionData({ abi, functionName, args });
const hash = await walletClient.sendTransaction({
account: account.address,
to: address,
data: txData,
value,
gas: estimateGas,
chain,
paymaster,
paymasterInput,
});
return hash;
}
return await writeContract(wagmiConfig, {
address,
chainId,
abi,
functionName,
args,
value,
gas: estimateGas,
});
}
⚠️ Key Gotchas to Watch Out For
paymasterInput
must be passed, even if it’s an empty 0x
using:
Manually hardcoding paymasterInput = "0x"
will not work.
2. Use zkSync wallet extensions
Extend your wallet client with eip712WalletActions()
to support sendTransaction
with Paymasters.
3. Pre-calculating the nonce is possible, but optional
Based on your personal use-cases, you can pre-calculate nonces, but this is also handled internally by Wagmi’s publicClient
provider wrapper.