以太坊钱包API使用教程:ethers.js和web3.js详解
以太坊钱包 API 使用教程详解
前言
本文档旨在为开发者提供一份详尽的以太坊钱包 API 使用指南,它将深入探讨常用功能、提供实用的代码示例,并列出关键的注意事项,以协助读者快速掌握以太坊钱包 API 的使用方法,并构建功能强大的、基于以太坊区块链技术的应用程序。本文将着重讲解如何利用当前流行的 JavaScript 库,例如
ethers.js
和
web3.js
,实现与以太坊钱包的无缝交互。具体来说,我们将探讨如何使用这些库来连接钱包、发送交易、读取链上数据、以及监听事件,从而为开发者提供全面的技术支持,助力其高效开发出安全可靠的以太坊应用。
准备工作
在使用以太坊钱包 API 之前,为了确保顺利集成和功能正常运行,需要完成以下准备工作,涉及环境配置、依赖安装和权限设置等多个方面:
- 配置开发环境: 搭建稳定、可靠的以太坊开发环境至关重要。这通常包括安装 Node.js (推荐使用 LTS 稳定版本),用于运行 JavaScript 代码和管理项目依赖;同时,选择一款合适的代码编辑器 (如 VS Code, Sublime Text, Atom 等) 以提高开发效率。
ethers.js
和 web3.js
是两个最常用的选择。本文将分别介绍它们的用法。可以通过 npm 安装它们:
bash npm install ethers npm install web3
使用
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 费用。