Viem is a TypeScript Interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
You can interact with Virtual Environments 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.
Code samples: Using Viem with Virtual Environments
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 Environment creation, you need to create a new chain object and set the id to your chosen value.
virtual-environments/src/tenderly.config.ts
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:
Viem actions for custom RPC methods
virtual-environments/src/viem-tenderly-actions.ts
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 to vMainnet we defined in the previous step
transport: either a call to http, and set to https RPC URL.
virtual-environments/src/viem-call-balance-top-up.ts
(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 Environment’s Simulation RPC methods, simply request to make the call to tenderly_simulateTransaction:
virtual-environments/src/viem-call-simulate.ts
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.
node/samples/viem/2-transaction-trace.ts
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("=======================================================");