您现在的位置是: 首页 >  学习

以太坊钱包API使用教程:ethers.js和web3.js详解

时间:2025-02-14 23:47:46 分类:学习 浏览:62

以太坊钱包 API 使用教程详解

前言

本文档旨在为开发者提供一份详尽的以太坊钱包 API 使用指南,它将深入探讨常用功能、提供实用的代码示例,并列出关键的注意事项,以协助读者快速掌握以太坊钱包 API 的使用方法,并构建功能强大的、基于以太坊区块链技术的应用程序。本文将着重讲解如何利用当前流行的 JavaScript 库,例如 ethers.js web3.js ,实现与以太坊钱包的无缝交互。具体来说,我们将探讨如何使用这些库来连接钱包、发送交易、读取链上数据、以及监听事件,从而为开发者提供全面的技术支持,助力其高效开发出安全可靠的以太坊应用。

准备工作

在使用以太坊钱包 API 之前,为了确保顺利集成和功能正常运行,需要完成以下准备工作,涉及环境配置、依赖安装和权限设置等多个方面:

  1. 配置开发环境: 搭建稳定、可靠的以太坊开发环境至关重要。这通常包括安装 Node.js (推荐使用 LTS 稳定版本),用于运行 JavaScript 代码和管理项目依赖;同时,选择一款合适的代码编辑器 (如 VS Code, Sublime Text, Atom 等) 以提高开发效率。
安装 Node.js 和 npm: 确保你的开发环境中已安装 Node.js 和 npm(Node Package Manager)。可以从 Node.js 官网下载并安装最新版本。
  • 选择并安装 JavaScript 库: 选择一个合适的以太坊 JavaScript 库。ethers.jsweb3.js 是两个最常用的选择。本文将分别介绍它们的用法。可以通过 npm 安装它们:

    bash npm install ethers npm install web3

  • 拥有一个以太坊钱包: 你需要一个以太坊钱包来测试你的代码。常用的以太坊钱包包括 MetaMask、Trust Wallet 等。确保钱包已连接到正确的网络(例如:主网、测试网)。
  • 使用 ethers.js 与以太坊钱包交互

    ethers.js 是一个功能强大且轻量级的 JavaScript 库,专为简化与以太坊区块链及其生态系统的交互而设计。 它通过提供一组直观且易于使用的 API,显著降低了开发者与以太坊网络交互的复杂性。 ethers.js 支持多种以太坊操作,涵盖从基本的账户管理到复杂的智能合约交互。

    利用 ethers.js ,开发者可以轻松执行以下关键任务:

    • 管理以太坊账户: ethers.js 允许开发者生成新的以太坊地址,导入现有账户(通过私钥或助记词),并安全地管理这些账户。 这使得开发者能够代表用户执行交易,而无需将用户的私钥暴露给应用程序。
    • 签名交易: 创建和签名交易是与以太坊区块链交互的核心部分。 ethers.js 提供了安全且高效的方式来构建和签名交易,确保交易的完整性和真实性。 这包括发送以太币、调用智能合约函数以及部署新的智能合约。
    • 查询区块链信息: ethers.js 提供了丰富的 API 来查询以太坊区块链的各种信息。 开发者可以使用它来获取账户余额、交易历史、区块数据、智能合约状态等。 这对于构建需要实时区块链数据的应用程序至关重要。
    • 与智能合约交互: ethers.js 极大地简化了与智能合约的交互。 开发者可以使用它来连接到现有的智能合约,调用合约函数,监听合约事件,并处理返回的数据。 它支持 ABI (Application Binary Interface),这是一种描述智能合约接口的标准格式。
    • 提供者 (Provider) 支持: ethers.js 使用Provider抽象来与以太坊网络交互。它支持多种Provider,包括连接到本地以太坊节点(如 Ganache 或 Geth)、Infura、Alchemy等第三方Provider,以及浏览器内置的钱包(如 MetaMask)。

    总而言之, ethers.js 为开发者提供了一个全面且易于使用的工具集,用于构建各种以太坊应用程序,从简单的钱包到复杂的去中心化应用 (DApp)。 其模块化的设计、详细的文档和活跃的社区使其成为以太坊开发的首选库之一。

    1. 连接以太坊网络

    要与以太坊区块链交互,第一步是建立连接。这通常通过创建一个 Provider 实例来实现。 Provider 充当你的应用程序和以太坊节点之间的桥梁,负责处理所有底层通信细节,例如发送交易和查询链上数据。

    ethers.js 库提供了一系列 Provider 实现,允许你连接到不同的以太坊网络和节点。以下代码展示了如何使用 ethers.js 连接到以太坊网络:

    
    const { ethers } = require("ethers");
    

    连接到公共以太坊网络 (Infura):

    Infura 是一个托管的以太坊节点基础设施服务,它允许你无需运行自己的节点即可连接到以太坊网络。要使用 Infura,你需要在 Infura 网站上创建一个帐户并创建一个项目。然后,你可以使用你的项目 ID 来创建一个 InfuraProvider 实例。以下代码展示了如何连接到 Infura 上的 Goerli 测试网:

    
    // 连接到 Infura 的 Goerli 测试网
    const provider = new ethers.providers.InfuraProvider("goerli", "YOUR_INFURA_PROJECT_ID");
    

    请务必将 YOUR_INFURA_PROJECT_ID 替换为你在 Infura 上创建的实际项目 ID。Goerli 是一个用于测试目的的公共测试网络。其他常用的测试网络包括 Sepolia 和 Holesky。

    连接到本地 Ganache 节点:

    Ganache 是一个流行的本地以太坊模拟器,它允许你在本地开发和测试你的智能合约,而无需与公共以太坊网络交互。要使用 Ganache,你需要下载并安装 Ganache 应用程序。然后,你可以使用 JsonRpcProvider 连接到 Ganache 节点。默认情况下,Ganache 在 http://localhost:8545 上运行。以下代码展示了如何连接到本地 Ganache 节点:

    
    // 或者连接到本地 Ganache 节点
    // const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
    

    验证连接:

    一旦你创建了一个 Provider 实例,你可以使用 getNetwork() 方法来验证你是否已成功连接到以太坊网络。 getNetwork() 方法返回一个包含有关网络的元数据的对象,例如网络的名称和链 ID。以下代码展示了如何使用 getNetwork() 方法来验证连接:

    
    async function checkConnection() {
      const network = await provider.getNetwork();
      console.log("连接到网络:", network.name);
    }
    
    checkConnection();
    

    运行此代码将在控制台中打印连接到的网络的名称。如果连接成功,你应该看到类似 "连接到网络: goerli" 或 "连接到网络: ganache" 的消息。

    2. 获取钱包实例

    与以太坊区块链交互,需要一个 Signer 实例。 Signer 对象代表一个拥有以太坊私钥的账户,具备对交易进行签名的能力,这是与区块链进行价值转移和状态变更操作的核心。

    对于使用 MetaMask 或 Trust Wallet 等浏览器扩展钱包的情况,可以通过浏览器提供的 window.ethereum 对象来获取 Signer 。该对象是一个以太坊提供者 API,允许网页应用程序请求用户授权并与以太坊网络进行交互。

    javascript

    async function getSigner() {
      // 检查 MetaMask 是否安装
      if (typeof window.ethereum !== 'undefined') {
        try {
          // 请求用户授权,允许应用访问用户账户
          await window.ethereum.request({ method: 'eth_requestAccounts' });
    
          // 创建 Web3Provider 实例,连接到以太坊网络
          const provider = new ethers.providers.Web3Provider(window.ethereum);
    
          // 获取 Signer 对象,用于签名交易
          const signer = provider.getSigner();
    
          // 获取 Signer 关联的以太坊地址
          const address = await signer.getAddress();
          console.log("钱包地址:", address);
    
          return signer;
    
        } catch (error) {
          console.error("获取 Signer 失败:", error);
          return null;
        }
    
      } else {
        console.log("请安装 MetaMask 或其他兼容的 Web3 钱包!");
        return null;
      }
    }
    
    getSigner();
    

    如果选择使用私钥直接创建 Signer 实例,可以使用 ethers.Wallet 类。 需要注意的是,**强烈建议不要在客户端代码中硬编码私钥,这会带来严重的安全风险。** 应该使用更安全的方式管理私钥,例如使用环境变量、密钥管理服务或硬件钱包。

    javascript

    // 注意:请勿直接在代码中硬编码私钥!使用环境变量或更安全的方式管理。
    const privateKey = "YOUR_PRIVATE_KEY"; // 替换为你的私钥
    // 使用 provider 连接到以太坊网络 (例如,Infura, Alchemy)
    const provider = new ethers.providers.JsonRpcProvider("YOUR_INFURA_ENDPOINT"); // 替换为你的Infura或Alchemy端点
    
    const wallet = new ethers.Wallet(privateKey, provider);
    
    console.log("钱包地址:", wallet.address);
    

    ethers.Wallet 构造函数需要私钥和 provider 作为参数。Provider 用于与以太坊网络进行通信,例如查询余额、发送交易等。可以根据需求选择不同的 provider,例如 Infura、Alchemy 或本地节点。

    警告: 永远不要将私钥存储在客户端代码中。这会导致严重的安全风险。

    3. 查询账户余额

    为了获取特定以太坊账户的ETH余额,可以使用 ethers.js 库提供的 getBalance() 方法。该方法允许你查询任何公开可见的以太坊地址的余额。

    getBalance() 方法接收一个参数:你想要查询余额的以太坊地址字符串。该方法会返回一个 Promise,Promise resolve 的结果是一个 BigNumber 对象,表示该地址的余额,单位是 Wei (以太坊的最小单位)。

    通常,我们需要将 Wei 转换为更易读的 Ether 单位。ethers.js 提供了 ethers.utils.formatEther() 工具函数来完成这个转换。该函数接收一个 BigNumber 类型的 Wei 值作为输入,并返回一个表示 Ether 值的字符串。

    JavaScript 示例代码:

    
    async function getBalance(address) {
      try {
        const balance = await provider.getBalance(address);
        const balanceInEther = ethers.utils.formatEther(balance);
        console.log("账户余额:", balanceInEther, "ETH");
        return balanceInEther; // 返回余额,方便后续使用
      } catch (error) {
        console.error("获取余额时发生错误:", error);
        return null; // 发生错误时返回 null 或其他适当的值
      }
    }
    

    这段代码定义了一个名为 getBalance() 的异步函数。该函数接收一个以太坊地址作为参数,并尝试获取该地址的余额。代码使用了 try...catch 块来处理可能发生的错误,例如网络连接问题或无效的地址。如果获取余额成功,它会将余额从 Wei 转换为 Ether,并在控制台中打印出来。getBalance 函数同时也返回余额值,这使得你可以在其他函数或组件中使用这个余额信息。

    使用示例:

    
    getBalance("0xYOUR_ADDRESS"); // 将 "0xYOUR_ADDRESS" 替换为你想要查询的以太坊地址
    

    请确保将 "0xYOUR_ADDRESS" 替换为你实际想要查询的以太坊地址。例如,如果你想查询地址 0xf39Fd6e51Ec51ac49Bca5Eef34E881F6f7542A8 的余额,你应该这样调用函数:

    
    getBalance("0xf39Fd6e51Ec51ac49Bca5Eef34E881F6f7542A8");
    

    注意: 在实际应用中,请务必妥善处理潜在的错误情况。例如,可以添加错误处理机制来捕获和处理无效地址或网络连接问题。请确保你的 provider 对象已正确配置,以便连接到以太坊网络。

    4. 发送交易

    可以使用 sendTransaction() 方法从已连接的以太坊账户发送交易到另一个账户。发送交易前,务必构建一个包含必要参数的交易对象。

    javascript async function sendTransaction(signer, recipient, amount) { // 将要发送的以太币数量转换为 Wei,这是以太坊中最小的面额单位。 const amountInEther = ethers.utils.parseEther(amount);

    // 构造交易对象,包含目标地址、发送的 Wei 值、Gas 上限和 Gas 价格。 const transaction = { to: recipient, // 接收者的以太坊地址。 value: amountInEther, // 要发送的以太币数量,以 Wei 为单位。 gasLimit: 21000, // Gas 上限,表示愿意为交易支付的最大 Gas 数量。基本的 ETH 转账通常需要 21000 Gas,复杂的智能合约交互可能需要更多。 gasPrice: ethers.utils.parseUnits('10', 'gwei'), // Gas 价格,表示为每单位 Gas 支付的费用,单位为 Gwei。根据网络拥塞情况调整此值。 };

    try { // 使用 signer 对象发送交易,signer 对象代表具有私钥的账户,用于签署交易。 const txResponse = await signer.sendTransaction(transaction); console.log("交易已发送,交易哈希:", txResponse.hash);

    // 等待交易被确认,即被矿工打包到区块中。
    const receipt = await txResponse.wait();
    console.log("交易已确认,区块号:", receipt.blockNumber);
    

    } catch (error) { // 捕获并记录发送交易过程中发生的任何错误。 console.error("交易失败:", error); } }

    // 示例:调用 sendTransaction 函数,使用先前获取的 signer 对象,将 0.001 个以太币发送到指定的接收者地址。 getSigner().then(signer => { if (signer) { sendTransaction(signer, "0xRECIPIENT_ADDRESS", "0.001"); // 替换为接收者地址和金额 } });

    请务必将 0xRECIPIENT_ADDRESS 替换为实际接收者的以太坊地址,并将 "0.001" 替换为希望发送的以太币数量。注意,实际交易费用会根据网络状况波动,需要有足够的余额支付 Gas 费用。

    5. 与智能合约交互

    可以使用 ethers.Contract 类与部署在区块链上的智能合约进行交互。要实现交互,需要提供两个关键信息:智能合约的 ABI (Application Binary Interface) 和合约部署的地址。ABI 描述了合约的接口,包括函数签名、输入参数和输出参数,使得 JavaScript 代码能够理解和调用合约函数。合约地址是在区块链上唯一标识合约的位置。

    以下是一个示例,展示了如何使用 ethers.Contract 类与智能合约交互:

    
    const contractAddress = "YOUR_CONTRACT_ADDRESS"; // 替换为你的合约地址
    const contractABI = [
      // 合约 ABI (JSON 格式)
      {
        "constant": true,
        "inputs": [],
        "name": "totalSupply",
        "outputs": [
          {
            "name": "",
            "type": "uint256"
          }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
      },
      // ... 其他合约函数定义,例如:
      // {
      //   "constant": false,
      //   "inputs": [
      //     {
      //       "name": "_to",
      //       "type": "address"
      //     },
      //     {
      //       "name": "_value",
      //       "type": "uint256"
      //     }
      //   ],
      //   "name": "transfer",
      //   "outputs": [
      //     {
      //       "name": "",
      //       "type": "bool"
      //     }
      //   ],
      //   "payable": false,
      //   "stateMutability": "nonpayable",
      //   "type": "function"
      // }
    ];
    

    上面的代码片段定义了 contractAddress contractABI 变量。务必将 YOUR_CONTRACT_ADDRESS 替换为实际的智能合约地址,并将 contractABI 替换为合约的完整 ABI。 ABI 通常是一个 JSON 格式的数组,可以从 Remix IDE、Hardhat 或 Foundry 等开发工具中获取。

    下一步是创建一个函数,该函数使用 ethers.Contract 类与合约交互。此函数需要一个 signer 对象,该对象表示拥有私钥的以太坊账户,用于签署交易。

    
    async function interactWithContract(signer) {
      const contract = new ethers.Contract(contractAddress, contractABI, signer);
    
      try {
        // 调用合约的 totalSupply 函数
        const totalSupply = await contract.totalSupply();
        console.log("Total Supply:", totalSupply.toString());
    
        // 调用合约的其他函数,例如:
        // const transaction = await contract.transfer("0x...", 100);
        // await transaction.wait(); // 等待交易被确认
        // console.log("Transfer successful!");
    
      } catch (error) {
        console.error("与合约交互失败:", error);
      }
    }
    

    在此示例中, interactWithContract 函数首先使用合约地址、ABI 和 signer 创建一个 ethers.Contract 对象。然后,它调用合约的 totalSupply 函数,该函数返回代币的总供应量。该函数还展示了如何调用合约的其他函数,例如 transfer 函数,该函数需要指定接收者地址和转账金额。

    调用合约的“view”或“pure”函数(只读取链上数据,不修改状态)不需要 gas 费用,因为它们不会改变区块链的状态。调用修改状态的函数(例如 "transfer")会创建一个交易,需要 gas 费用才能执行。 transaction.wait() 方法用于等待交易被矿工确认并添加到区块链中。

    需要获取一个 signer 对象并调用 interactWithContract 函数:

    
    // 示例
    getSigner().then(signer => {
      if (signer) {
        interactWithContract(signer);
      }
    });
    

    getSigner() 函数应该返回一个 ethers.Signer 对象。这可以通过多种方式实现,例如使用 MetaMask 等浏览器扩展程序,或使用 Infura 等远程节点。

    请确保已安装 ethers 库: npm install ethers yarn add ethers 。 请务必处理交易失败的情况,例如 gas 不足或合约执行错误。 推荐使用try...catch 块来捕获和处理潜在的错误。

    使用 web3.js 与以太坊钱包交互

    web3.js 是一个功能强大的 JavaScript 库,被广泛应用于以太坊区块链的交互。它为开发者提供了一整套工具,简化了与以太坊网络的通信过程。通过 web3.js ,开发者可以轻松连接到本地或远程的以太坊节点,进而实现与区块链的各种交互操作。

    web3.js 的核心功能包括但不限于:

    • 连接以太坊节点: 通过 HTTP、WebSocket 或 IPC 等多种协议连接到以太坊节点,建立与区块链的通信通道。这使得应用程序能够访问区块链数据并执行交易。
    • 发送交易: 创建、签名和广播以太坊交易,包括发送 ETH、调用智能合约函数等。 web3.js 提供了交易构建和签名功能,简化了交易流程。
    • 与智能合约交互: 部署新的智能合约,或者与已部署的智能合约进行交互。 通过智能合约的 ABI (Application Binary Interface), web3.js 可以将合约函数映射为 JavaScript 函数,方便调用。
    • 读取区块链数据: 查询区块链上的各种数据,例如账户余额、区块信息、交易详情、智能合约状态等。开发者可以利用这些数据构建各种应用,例如区块链浏览器、钱包等。
    • 事件监听: 监听智能合约发出的事件,实现实时响应。 这对于构建需要对链上事件做出反应的应用程序非常有用,例如 DeFi 应用。

    使用 web3.js 需要开发者对以太坊区块链的基本概念,如账户、交易、gas 等,有一定的了解。 还需要熟悉 JavaScript 编程,以及异步编程模型 (例如 Promises 和 async/await),才能充分利用 web3.js 的强大功能。

    1. 连接以太坊网络

    与以太坊区块链进行交互的第一步是建立连接。这通常涉及创建一个 Web3 实例,该实例充当你的应用程序和以太坊节点之间的桥梁。 Web3 是一个封装了与以太坊交互所需功能的 JavaScript 库,提供了诸如发送交易、查询链上数据等方法。

    使用 Web3 库之前,需要先进行安装。可以使用 npm 或者 yarn:

    npm install web3

    或者

    yarn add web3

    安装完成后,就可以在你的 JavaScript 代码中引入并使用它了。

    代码示例:

    javascript const Web3 = require('web3');

    连接到以太坊网络有多种方式。一种常见的方式是通过 Infura,它是一个托管的以太坊节点服务,允许你无需运行自己的节点即可与以太坊网络交互。另一种方式是连接到本地运行的 Ganache 节点,Ganache 是一个用于本地以太坊开发的模拟器,可以用来测试你的智能合约和应用程序。

    连接到 Infura 的 Goerli 测试网的示例:

    javascript // 连接到 Infura 的 Goerli 测试网 const web3 = new Web3(new Web3.providers.HttpProvider('https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID'));

    请务必将 YOUR_INFURA_PROJECT_ID 替换为你自己在 Infura 上创建的项目 ID。每个 Infura 项目都有唯一的 ID,用于身份验证和跟踪使用情况。

    连接到本地 Ganache 节点的示例:

    javascript // 或者连接到本地 Ganache 节点 const web3 = new Web3('http://localhost:8545');

    Ganache 默认在 http://localhost:8545 端口上运行。如果你的 Ganache 节点运行在不同的端口上,请相应地修改 URL。

    为了验证连接是否成功,可以编写一个简单的函数来获取当前连接的网络 ID:

    javascript async function checkConnection() { const networkId = await web3.eth.net.getId(); console.log("连接到网络:", networkId); }

    web3.eth.net.getId() 方法返回一个 Promise,该 Promise resolve 为当前连接的网络的 ID。例如,Goerli 测试网的 ID 是 5,主网的 ID 是 1。

    调用 checkConnection() 函数来测试连接:

    javascript checkConnection();

    如果连接成功,控制台将输出类似以下内容:

    连接到网络: 5

    这意味着你已成功连接到 Goerli 测试网。

    2. 获取账户

    在Web3环境中,访问用户拥有的以太坊账户是与区块链交互的关键步骤。如果用户使用的是 MetaMask 或类似的浏览器插件钱包,可以通过 window.ethereum 对象与钱包进行交互,从而获取账户地址。

    使用 JavaScript 代码片段,可以异步地获取用户授权并检索账户地址。下面的代码展示了如何检测 window.ethereum 对象是否存在,请求用户授权访问其账户,以及获取账户列表中的第一个地址。

    async function getAccounts() {
      if (typeof window.ethereum !== 'undefined') {
        try {
          // 请求用户授权,允许 DApp 访问用户的以太坊账户
          await window.ethereum.request({ method: 'eth_requestAccounts' });
    
          // 使用 Web3.js 库获取账户列表
          const web3 = new Web3(window.ethereum);
          const accounts = await web3.eth.getAccounts();
    
          // 通常使用第一个账户作为当前用户的地址
          const address = accounts[0];
          console.log("钱包地址:", address);
    
          return address;
        } catch (error) {
          // 处理获取账户过程中可能出现的错误,例如用户拒绝授权
          console.error("获取账户失败:", error);
          return null;
        }
      } else {
        // 提示用户安装 MetaMask 或其他兼容的 Web3 钱包
        console.log("请安装 MetaMask!");
        return null;
      }
    }

    调用 getAccounts() 函数会触发 MetaMask 弹窗,请求用户授权。授权后,函数会返回用户的以太坊地址。如果用户拒绝授权或发生其他错误,函数会返回 null 并输出错误信息。

    请确保已经引入 Web3.js 库,例如通过 CDN 引入: <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script> 。 这段代码仅适用于现代浏览器和支持 Web3 的环境。老旧浏览器可能不支持 window.ethereum 对象。

    示例调用:

    getAccounts();
    

    3. 查询账户余额

    使用 web3.eth.getBalance() 方法可以查询指定以太坊账户的余额。该方法需要一个以太坊地址作为参数,并返回该地址的余额,单位为 Wei。Wei 是以太坊中最小的货币单位,1 ETH = 10^18 Wei。

    为了方便显示和使用,通常需要将 Wei 转换为 ETH。可以使用 web3.utils.fromWei() 方法将 Wei 转换为 ETH 或其他更大的单位(如 Gwei)。

    以下 JavaScript 代码示例演示了如何使用 web3.eth.getBalance() 方法查询账户余额,并将结果转换为 ETH 后在控制台中输出:

    
    async function getBalance(address) {
      try {
        const balanceInWei = await web3.eth.getBalance(address);
        const balanceInEther = web3.utils.fromWei(balanceInWei, 'ether');
        console.log("账户余额:", balanceInEther, "ETH");
      } catch (error) {
        console.error("获取账户余额失败:", error);
      }
    }
    

    上述代码定义了一个名为 getBalance() 的异步函数,该函数接受一个以太坊地址作为参数。函数内部使用 web3.eth.getBalance() 方法获取指定地址的余额,并将结果存储在 balanceInWei 变量中。随后,使用 web3.utils.fromWei() 方法将 balanceInWei 转换为 ETH,并将结果存储在 balanceInEther 变量中。使用 console.log() 方法将账户余额输出到控制台。为了处理潜在的错误,代码包含了一个 try...catch 块,用于捕获并记录任何发生的错误。

    为了调用 getBalance() 函数,需要先获取一个以太坊地址。以下代码示例演示了如何使用 web3.eth.getAccounts() 方法获取当前连接的以太坊账户地址,并将其传递给 getBalance() 函数:

    
    web3.eth.getAccounts()
      .then(accounts => {
        if (accounts.length > 0) {
          const address = accounts[0]; // 使用第一个账户地址
          getBalance(address);
        } else {
          console.log("没有可用的以太坊账户。");
        }
      })
      .catch(error => {
        console.error("获取账户列表失败:", error);
      });
    

    该代码首先调用 web3.eth.getAccounts() 方法来获取所有可用的以太坊账户。 getAccounts() 方法返回一个 Promise 对象,该 Promise 对象 resolve 时会返回一个包含账户地址的数组。然后,检查返回的数组是否为空。如果数组不为空,则提取第一个账户地址并将其传递给 getBalance() 函数。如果数组为空,则在控制台中输出一条消息,指示没有可用的以太坊账户。同样,为了处理潜在的错误,代码包含了一个 catch 块,用于捕获并记录任何发生的错误。

    请注意,上述代码假定用户已经连接到了一个以太坊节点,并且已经设置了 web3 对象。如果 web3 对象未定义,则需要先创建一个 web3 实例并将其连接到以太坊节点。

    4. 发送交易

    可以使用 web3.eth.sendTransaction() 方法向以太坊网络发送交易。该方法允许你从一个账户向另一个账户转移以太币或其他符合 ERC-20 标准的代币,并执行智能合约中的函数。

    示例代码:

    
    async function sendTransaction(fromAddress, recipient, amount) {
      // 将以太币数量转换为 Wei (最小单位)
      const amountInWei = web3.utils.toWei(amount, 'ether');
    
      // 构建交易对象
      const transaction = {
        from: fromAddress,  // 发送者地址
        to: recipient,      // 接收者地址
        value: amountInWei, // 发送的 Wei 数量
        gas: 21000,        // Gas 限制 (单位: gas)。 根据交易复杂性调整。
        gasPrice: web3.utils.toWei('10', 'gwei'), // Gas 价格 (单位: gwei)。影响交易被矿工打包的速度。
        nonce: await web3.eth.getTransactionCount(fromAddress), // Nonce 值,防止重放攻击
        data: '0x' // 交易附带的数据。 如果是调用智能合约函数,这里存放函数签名和参数。
      };
    
      try {
        // 使用 MetaMask 或其他 Web3 提供商签名并发送交易
        const txResponse = await web3.eth.sendTransaction(transaction);
        console.log("交易已发送,交易哈希:", txResponse.transactionHash);
        console.log("交易详情:", txResponse); //输出完整的交易回执信息
      } catch (error) {
        console.error("交易失败:", error);
        console.error("错误详情:", error.message); // 打印更详细的错误信息,便于调试
      }
    }
    
    // 获取账户并发送交易的示例
    getAccounts().then(address => {
      if (address) {
        sendTransaction(address, "0xRECIPIENT_ADDRESS", "0.001"); // 替换为实际接收者地址和金额
      }
    });
    

    重要提示:

    • 请将 0xRECIPIENT_ADDRESS 替换为实际接收者的以太坊地址。
    • "0.001" 替换为要发送的以太币数量 (单位: 以太币)。
    • 务必确保你的 MetaMask 扩展程序已连接到正确的网络(例如:主网、Ropsten、Rinkeby、Goerli)。
    • 账户中需要有足够的以太币来支付 gas 费用。
    • gas 属性指定了交易执行的最大 gas 消耗量。 对于简单的以太币转账,21000 gas 通常足够。 对于更复杂的智能合约调用,可能需要更高的 gas 限制。
    • gasPrice 属性指定了你愿意为每个 gas 支付的价格。 较高的 gas 价格通常意味着交易会被更快地打包进区块。 可以使用 web3.eth.getGasPrice() 方法获取当前建议的 gas 价格。
    • nonce 属性是发送者地址的交易计数。 确保 nonce 值正确,以防止交易被错误地排序或被拒绝。
    • data 字段用于携带交易数据,例如调用智能合约函数时的函数签名和参数。 对于简单的以太币转账, data 字段通常为空 ( '0x' )。

    请注意,发送交易是一个异步操作。 sendTransaction() 方法会返回一个 Promise,该 Promise 在交易被提交到区块链后解析。 你可以使用 .then() .catch() 方法来处理交易成功或失败的情况。

    5. 与智能合约交互

    Web3.js 提供了强大的工具,允许你通过 Contract 对象与部署在区块链上的智能合约进行交互。交互过程的关键在于拥有目标合约的应用二进制接口(ABI)以及合约在区块链上的具体地址。

    为了演示,假设你有一个已经部署的智能合约。你需要先获取合约的 ABI 和地址,才能使用 Web3.js 与之通信。以下代码展示了如何声明合约地址和 ABI:

    
    const contractAddress = "YOUR_CONTRACT_ADDRESS"; // 替换为你的合约地址,例如:"0xAb8483F64d9C6d1EcF9Ca6214af9769d0E6D8544"
    const contractABI = [
      // 合约 ABI (JSON 格式) - 这是合约接口的描述,定义了合约中可用的函数及其参数
      {
        "constant": true,
        "inputs": [],
        "name": "totalSupply",
        "outputs": [
          {
            "name": "",
            "type": "uint256"
          }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
      },
      // ... 其他合约函数,例如:
      // {
      //   "constant": false,
      //   "inputs": [
      //     {
      //       "name": "_to",
      //       "type": "address"
      //     },
      //     {
      //       "name": "_value",
      //       "type": "uint256"
      //     }
      //   ],
      //   "name": "transfer",
      //   "outputs": [
      //     {
      //       "name": "",
      //       "type": "bool"
      //     }
      //   ],
      //   "payable": false,
      //   "stateMutability": "nonpayable",
      //   "type": "function"
      // }
    ];
    

    接下来,创建一个异步函数来执行与合约的交互。此函数接收一个 fromAddress 参数,该参数指定交易的发起者地址。在函数内部,使用 web3.eth.Contract 构造函数创建一个新的合约实例。构造函数需要 ABI、合约地址以及一个包含 from 属性的选项对象。

    
    async function interactWithContract(fromAddress) {
      const contract = new web3.eth.Contract(contractABI, contractAddress, { from: fromAddress });
    
      try {
        // 调用合约的 totalSupply 函数 -  这是一个只读函数,不修改区块链状态
        const totalSupply = await contract.methods.totalSupply().call();
        console.log("Total Supply:", totalSupply);
    
        // 调用其他合约函数...例如 transfer 函数,该函数会修改区块链状态,需要发送交易
        // const transaction = await contract.methods.transfer("0x...", 100).send({ gas: 100000 });
        // console.log("Transaction Hash:", transaction.transactionHash);
    
      } catch (error) {
        console.error("与合约交互失败:", error);
      }
    }
    

    获取用户账户地址并调用 interactWithContract 函数。 getAccounts 函数应该是一个已经定义的函数,用于从 Web3 提供者(例如 MetaMask)获取可用的以太坊账户地址。

    
    getAccounts().then(address => {
      if (address) {
        interactWithContract(address);
      }
    });
    

    务必将代码中的 YOUR_CONTRACT_ADDRESS 替换为你的实际智能合约地址,并且确保 contractABI 与你的合约接口定义匹配。对于状态修改函数(例如 transfer ),需要使用 send() 方法并提供足够的 gas 限制。请记住,每次调用 send() 方法都会创建一个新的交易,并且需要消耗 gas 费用。

    文章版权声明:除非注明,否则均为链链通原创文章,转载或复制请以超链接形式并注明出处。
    相关推荐