如何使用 Viem 发送交易

  • QuickNode
  • 发布于 2024-08-29 12:54
  • 阅读 37

本文介绍了如何使用Viem库在以太坊或其他EVM兼容区块链上发送交易。内容包括设置项目、执行ETH转账、发送签名交易以及与智能合约交互的详细步骤。

概述

本指南介绍了如何使用 Viem 在以太坊或其他 EVM 兼容的区块链上发送交易。Viem 由 wagmi 的开发者创建,旨在通过提供更直观和高效的开发者体验、更快的执行速度、模块化的 API 和强大的类型支持来解决现有以太坊库的不足。查看他们的 完整文档 以了解所有功能。

我们将通过 Viem 的各种方法发送交易,例如向 vitalik.eth 这样的 ENS 域名转账 ETH,发送签名交易,以及直接与智能合约交互。

如果你对交易有更多兴趣,请查看 我们的其他综合指南

你将完成的任务

  • 设置一个项目,使用 Viem 与以太坊 Sepolia 区块链进行交互
  • 执行一笔交易以转账 ETH,特别关注在以太坊 Sepolia 区块链上向 ENS 域名发送 ETH
  • 向区块链发送签名交易
  • 与智能合约交互

你需要准备的内容

项目先决条件

QuickNode 以太坊端点

确保你有一个 QuickNode 账户,并设置一个以太坊节点端点以与以太坊 Sepolia 区块链通信。此端点将是你通往区块链的网关。在此 注册 免费账户并为以太坊 Sepolia 测试网创建一个端点。

在本指南中,我们将使用 以太坊 Sepolia 测试网。不过,如果你愿意,也可以使用以太坊主网或任何 EVM 兼容的区块链。

以太坊 Sepolia 节点端点

保留 HTTP Provider URL 以备后用。

QuickNode 多链水龙头

你需要一些 ETH 来支付交易中的 gas 费用。

访问 QuickNode 多链水龙头 并连接你的钱包或粘贴你的钱包地址。你需要选择 以太坊 链和 Sepolia 网络,然后请求资金。请注意,使用 EVM 水龙头需要在以太坊主网上有 0.001 ETH 的余额。你还可以通过发推或登录你的 QuickNode 账户来获得奖励!

私钥

私钥对于在将交易发送到区块链之前进行签名至关重要。因此,请从你的钱包(例如 MetaMask、Rabby 等)中获取你的私钥,因为项目中需要它,并且切勿公开分享。

如果你不知道如何获取你的私钥,请点击这里。

本说明适用于 MetaMask

要获取你的私钥:

  • 点击浏览器上的 MetaMask 图标,一个风格化的狐狸头。如果看不到,请检查浏览器的 扩展 页面。
  • 点击 符号,然后点击 账户详情
  • 然后,点击 显示私钥 并按照说明操作。

MetaMask 私钥

开发设置

提示

如果你还没有安装,可以运行以下命令全局安装 TypeScriptts-node,以便在所有项目中使用 TypeScript。

npm install -g typescript
npm install -g ts-node

第一步:创建项目目录

mkdir viem-transaction
cd viem-transaction

第二步:初始化你的项目

npm init -y
tsc -init --resolveJsonModule true

第三步:安装依赖项

为了确保你的项目拥有所需的一切,请运行以下命令。这将添加 viem 用于与以太坊交互,并添加 dotenv 用于管理环境变量。此外,我们还包括 @types/node 以支持 Node.js 项目中的 TypeScript 类型,增强开发体验和类型检查。

npm install viem
npm install --save-dev dotenv @types/node

第四步:环境设置

创建一个 .env 文件来存储敏感信息,如你的钱包私钥和 QuickNode 端点。

echo > .env

然后,用你的代码编辑器修改它。将 YOUR_QUICKNODE_ENDPOINT_URLYOUR_WALLET_PRIVATE_KEY 占位符替换为你的 QuickNode 端点 URL 和你的私钥。

信息

在十六进制表示法中,0x 前缀用于表示紧随其后的字符代表一个十六进制值。虽然并非所有十六进制字符串都需要以 0x 开头,但在以太坊和许多钱包的上下文中,私钥和其他十六进制值通常以此外的前缀显示以增加清晰度。

如果你的私钥没有以 0x 开头,你应该添加它。否则代码会报错。

QUICKNODE_ENDPOINT = "YOUR_QUICKNODE_ENDPOINT_URL"
PRIVATE_KEY = "YOUR_WALLET_PRIVATE_KEY"

第五步:创建 index.ts 文件

echo > index.ts

发送交易

我们现在将向新创建的 index.ts 文件添加一个脚本,该脚本将通过以下步骤完成发送交易:

  • 设置与 QuickNode 以太坊端点的连接,并使用私钥初始化钱包客户端。
  • 检查发送方的余额,确保其足够支付交易。
  • 设置逻辑以检查余额是否充足,如果充足,脚本将 ENS 名称(vitalik.eth)解析为相应的以太坊地址,并向该地址发送指定数量的 ETH(0.001 ETH)。
  • 成功时记录交易的哈希值,提供已完成交易的区块链参考。

第六步:修改 index.ts 文件

打开 index.ts 文件并添加以下代码:

index.ts

// 导入必要的 Viem 模块和函数
import {
  Address,
  createWalletClient,
  http,
  formatEther,
  parseEther,
  publicActions,
} from "viem";
import { normalize } from "viem/ens"; // 用于 ENS 名称规范化
import { privateKeyToAccount } from "viem/accounts"; // 将私钥转换为账户
import { sepolia } from "viem/chains"; // 参考 Sepolia 测试网络
import dotenv from "dotenv"; // 用于加载环境变量
dotenv.config();

// 从环境变量中获取 QuickNode 端点和私钥
const QUICKNODE_ENDPOINT = process.env.QUICKNODE_ENDPOINT as string;
const PRIVATE_KEY = process.env.PRIVATE_KEY as Address;

// 将私钥转换为账户对象
const account = privateKeyToAccount(PRIVATE_KEY);

// 使用指定的账户、链和 HTTP 传输创建钱包客户端
const walletClient = createWalletClient({
  account,
  chain: sepolia,
  transport: http(QUICKNODE_ENDPOINT),
}).extend(publicActions);

// 定义要发送的 ETH 数量
const ethAmount = parseEther("0.001");

// 检查发送方余额并确保其足够的函数
async function checkBalance() {
  const balanceFrom = await walletClient.getBalance({
    address: account.address,
  });

  if (balanceFrom < ethAmount) {
    throw new Error("Insufficient ETH balance.");
  }

  console.log(
    `The balance of the sender (${account.address}) is: ${formatEther(balanceFrom)} ETH`
  );
}

// 执行交易的主函数
async function main() {
  await checkBalance(); // 首先检查发送方余额

  // 将 ENS 名称解析为以太坊地址
  const ensAddress = await walletClient.getEnsAddress({
    name: normalize("vitalik.eth"),
  });

  // 向解析的 ENS 地址发送交易
  const hash = await walletClient.sendTransaction({
    to: ensAddress,
    value: ethAmount,
  });

  // 记录交易详情
  console.log(
    `The transaction of sending ${formatEther(
      ethAmount
    )} ETH to ${ensAddress} is sent to the blockchain`
  );
  console.log("Transaction hash:", hash);
}

// 执行主函数并处理任何错误
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

如你所见,Viem 和其他类似库(如 ethers.js)简化了以太坊交易中的复杂方面,例如自动估算 gas 费用和管理每笔交易的 nonce 值,使开发者的工作更加轻松。此外,借助浏览器原生的 BigInts、全面的 ABI 工具和完整的 TypeScript 支持,Viem 增强了区块链开发中新手和老手的开发者体验。

第七步:运行 index.ts 文件

修改文件后,我们可以使用以下命令运行脚本文件。

ts-node index.ts

控制台输出应类似于以下内容。因此,通过此脚本,我们成功将所选数量的 ETH 发送到相关地址。

The balance of the sender (0x58D09ecd499A1d6F2a0269f361Ee6DbbaBa44eF8) is: 0.377012589826602656 ETH
The transaction of sending 0.001 ETH to 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 is sent to the blockchain
Transaction hash: 0x253e555ed304c8b238b68587ddf4f65d42705f0e7ee3295ed8a5c56586bc113b

你可以访问 Etherscan Sepolia 区块浏览器,并搜索交易哈希以获取交易详情。

其他发送交易的方式

除了前面展示的发送交易方法外,Viem 还支持低级别操作和修改区块链状态的智能合约交互。以下是简要概述:

使用 Viem 发送原始交易

sendRawTransaction 方法是直接与以太坊区块链交互的方式,允许开发者在发送交易之前手动签名和序列化交易。它类似于低级别的 eth_sendRawTransaction RPC 调用,提供了一种手把手的区块链交互方式。

发送原始交易

  // 发送交易
  // const hash = await walletClient.sendTransaction({
  //   to: ensAddress,
  //   value: ethAmount,
  // });

  // 发送原始交易
  const request = await walletClient.prepareTransactionRequest({
    to: ensAddress,
    value: ethAmount,
  });

  const serializedTransaction = await walletClient.signTransaction(request);
  const hash = await walletClient.sendRawTransaction({ serializedTransaction });

使用 Viem 与智能合约交互

对于那些希望与智能合约交互的人,Viem 的 simulateContractwriteContract 方法简化了过程。这些方法抽象了在向智能合约函数发起交易调用时的一些复杂性。在内部,writeContract 方法调用 sendTransaction 操作并传递 ABI 编码的数据。

在执行合约交互之前,最好先进行模拟。Viem 提供了一个 simulateContract 函数用于此目的。由于 writeContract 默认不模拟交易,因此首先使用 simulateContract 可以帮助识别潜在错误。

与智能合约交互

  // 合约详情:Sepolia 测试网络上的 WETH 合约
  const contractAddress = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14";
  const contractABI = [\
    {\
      constant: false,\
      inputs: [],\
      name: "deposit",\
      outputs: [],\
      payable: true,\
      stateMutability: "payable",\
      type: "function",\
    },\
  ];

  const { request } = await walletClient.simulateContract({
    account,
    address: contractAddress,
    abi: contractABI,
    functionName: "deposit",
    value: parseEther("0.001"),
    // args: [arg1, arg2, ...]
  });
  await walletClient.writeContract(request);

其他参数

虽然本指南解释了发送交易的各种方法,但 Viem 允许指定 datagasPricenonce 等附加参数,以根据特定需求或网络条件微调你的交易。

  • data:包含字节码(例如智能合约调用)或给接收方的消息的参数。
  • gasPrice:每单位 gas 的价格(以 gwei 为单位),仅适用于 传统交易
  • maxFeePerGas:每单位 gas 的总费用(以 wei 为单位),包括 maxPriorityFeePerGas,仅适用于 EIP-1559(Type2)交易
  • maxPriorityFeePerGas:每单位 gas 的最大优先费用(以 wei 为单位),仅适用于 EIP-1559(Type2)交易
  • nonce:表示钱包中交易序列的唯一数字。

有关这些交易参数的更深入探讨,请查看我们的 什么是以太坊交易? 指南。此外,查看 sendTransaction 文档以获取方法参数的详尽列表。

结论

通过遵循本指南,你已经学会了使用 Viem 库在以太坊区块链上发送交易的基本知识。Viem 的设计理念强调易用性,同时不牺牲功能或灵活性,使其成为希望简化工作流程的以太坊开发者的绝佳选择。

订阅我们的 新闻通讯 以获取更多关于 Web3 和区块链的文章和指南。如果你有任何问题或需要进一步帮助,请随时加入我们的 Discord 服务器或使用下面的表单提供反馈。通过关注我们的 Twitter (@QuickNode) 和 Telegram 公告频道 获取最新动态。

其他资源

我们 ❤️ 反馈!

让我们知道 如果你有任何反馈或新主题的请求。我们很乐意听取你的意见。

  • 原文链接: quicknode.com/guides/eth...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。