Viem 是一个 Ethereum 的 TypeScript 接口,提供用于与 Ethereum 交互的低级无状态原语。
当您复制 Public RPC 时,可以使用标准 RPC 方法与 Virtual Environments 交互,
以及当您复制 Admin RPC 时,可以使用 Node RPC 上可用的自定义方法。
Code samples: Using Viem with Virtual Environments
定义自定义链
创建一个 tenderly.config.ts 文件,并使用 defineChain 创建一个链对象。
如果您在创建 Virtual Environment 期间指定了唯一的 Chain ID,您需要创建一个新的链对象,并将 id 设置为您选择的值。
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,
},
},
});
为自定义 RPC 方法定义 Viem actions
为自定义 RPC 方法(例如 tenderly_setBalance、tenderly_setErc20Balance 和 simulate)定义 Viem actions。
例如,以下文件定义了一个 tenderlySetBalance action,它会调用 tenderly_setBalance。
您可以在这里找到更多 actions:
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,
});
}
调用标准和自定义 RPC 方法
在此示例中,您可以看到如何:
- 调用 Viem 的
createPublicClient 并传入以下参数:
chain:设置为我们在上一步中定义的 vMainnet
transport:对 http 的一次调用,设置为 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;
});
使用 viem 模拟交易
要使用 Virtual Environment 的 Simulation RPC 方法,只需 request 一次对 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));
使用 Viem 追踪交易
使用 tenderly_traceTransaction 获取完全解码的交易跟踪。
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("=======================================================");