Viem
Viem is a TypeScript Interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
You can interact with Virtual TestNets using the standard RPC methods when you copy the Public RPC, as well as custom methods available on Node RPC when you copy the Admin RPC.
Define a custom chain
Create a file tenderly.config.ts
and use defineChain
to create a chain object.
If you specified a unique Chain ID during Virtual TestNet creation, you need to create a new chain object and set the id
to your chosen value.
import { defineChain } from 'viem';
import path from 'path';
export const vMainnet = defineChain({
id: 73571,
name: 'Virtual Ethereum Mainnet',
nativeCurrency: { name: 'vEther', symbol: 'vETH', decimals: 18 },
rpcUrls: {
default: { http: [process.env.TENDERLY_VIRTUAL_MAINNET_RPC!] },
},
blockExplorers: {
default: {
name: 'Tenderly Explorer',
url: process.env.TENDERLY_VIRTUAL_MAINNET_EXPLORER!
},
},
contracts: {
ensRegistry: {
address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
},
ensUniversalResolver: {
address: '0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da',
blockCreated: 16773775,
},
multicall3: {
address: '0xca11bde05977b3631167028862be2a173976ca11',
blockCreated: 14353601,
},
},
});
Define Viem actions for custom RPC methods
Define Viem actions for custom RPC methods, such as tenderly_setBalance
tenderly_setErc20Balance
, and simulate
.
For example, the following file defines a tenderlySetBalance
action that will invoke tenderly_setBalance
.
You can find more actions here:
import { Client, Hex } from 'viem';
type TSetBalanceParams = [addresses: Hex[], value: Hex];
export async function tenderlySetBalance(client: Client, params: TSetBalanceParams) {
return client.request<{
method: 'tenderly_setBalance',
Parameters: TSetBalanceParams,
ReturnType: Hex
}>({
method: 'tenderly_setBalance',
params: params,
});
}
Call standard and custom RPC methods
In this example, you can see how to:
- Call Viem’s
createPublicClient
and pass the following arguments: chain
: set tovMainnet
we defined in the previous steptransport
: either a call tohttp
, and set tohttps
RPC URL.
import { createPublicClient, http } from "viem";
import { vMainnet } from "./tenderly.config";
import { tenderlySetBalance, tenderlySetErc20Balance } from "./viem-tenderly-actions";
(async () => {
const client = createPublicClient({
chain: vMainnet,
transport: http(vMainnet.rpcUrls.default.http[0]),
});
console.log("Block Number", await client.getBlockNumber());
console.log("Chain", await client.getChainId());
const balanceTxs = await Promise.all([
tenderlySetBalance(client, [
["0x0d2026b3EE6eC71FC6746ADb6311F6d3Ba1C000B", "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"],
"0xDE0B6B3A7640000"
]),
tenderlySetErc20Balance(client, [
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
"0x40BdB4497614bAe1A67061EE20AAdE3c2067AC9e",
"0xDE0B6B3A7640000"
]),
// USDT
tenderlySetErc20Balance(client, [
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
"0x40BdB4497614bAe1A67061EE20AAdE3c2067AC9e",
"0xDE0B6B3A7640000"
]),
tenderlySetErc20Balance(client, [
"0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE",
"0x40BdB4497614bAe1A67061EE20AAdE3c2067AC9e",
"0xDE0B6B3A7640000"
]),
]);
console.log(
"ETH balance, DAI and ShibaInu topups",
balanceTxs.map(txHash => `${(vMainnet.blockExplorers.default.url)}/tx/${txHash}`));
})().catch(e => {
console.error(e);
process.exitCode = 1;
});
Simulate transactions using viem
To use Virtual TestNet’s Simulation RPC methods, simply request
to make the call to tenderly_simulateTransaction
:
import { createPublicClient, http } from "viem";
import { vMainnet } from "./tenderly.config";
const client = createPublicClient({
chain: vMainnet,
transport: http(vMainnet.rpcUrls.default[0])
});
const simulation = await client.request({
method: "tenderly_simulateTransaction",
params: [
// transaction object
{
from: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
to: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
gas: "0x0",
gasPrice: "0x0",
value: "0x0",
data: "0xa9059cbb00000000000000000000000020a5814b73ef3537c6e099a0d45c798f4bd6e1d60000000000000000000000000000000000000000000000000000000000000001",
},
// the block
"latest",
],
});
console.log("Trace");
console.log(JSON.stringify(simulation.trace, null, 2));
console.log("Logs");
console.log(JSON.stringify(simulation.logs, null, 2));
console.log("Asset Changes");
console.log(JSON.stringify(simulation.assetChanges, null, 2));
console.log("Balance Changes");
console.log(JSON.stringify(simulation.balanceChanges, null, 2));
Trace transactions using Viem
Use tenderly_traceTransaction
to get fully decoded transaction trace.
const txTrace = await client.request({
method: "tenderly_traceTransaction",
params: [
// transaction hash
"0x6b2264fa8e28a641d834482d250080b39cbbf39251344573c7504d6137c4b793"
],
});
console.log("Logs");
console.log(JSON.stringify(txTrace.logs, null, 2));
console.log("=======================================================");
console.log("Asset Changes");
console.log(JSON.stringify(txTrace.assetChanges, null, 2));
console.log("=======================================================");
console.log("Balance Changes");
console.log(JSON.stringify(txTrace.balanceChanges, null, 2));
console.log("=======================================================");