Web3.js基础

核心知识点讲解

Web3.js简介

Web3.js是一个JavaScript库,用于与以太坊网络进行交互:

  • 连接网络:连接到以太坊主网、测试网或本地网络
  • 账户管理:创建和管理以太坊账户
  • 合约交互:部署和调用智能合约
  • 区块链查询:查询区块、交易和账户信息
  • 事件监听:监听智能合约事件

Web3.js安装与配置

安装方式

# 使用npm安装
npm install web3

# 使用yarn安装
yarn add web3

基本配置

// 引入Web3
const Web3 = require('web3');

// 创建Web3实例
// 连接到本地节点
const web3 = new Web3('http://localhost:8545');

// 连接到Infura节点
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY');

// 连接到MetaMask
if (window.ethereum) {
  const web3 = new Web3(window.ethereum);
  // 请求用户授权
  await window.ethereum.request({ method: 'eth_requestAccounts' });
}

Web3.js核心功能

1. 账户管理

  • 获取账户web3.eth.getAccounts()
  • 创建账户web3.eth.accounts.create()
  • 签名交易web3.eth.accounts.signTransaction()
  • 签名消息web3.eth.accounts.sign()

2. 区块链查询

  • 获取区块web3.eth.getBlock()
  • 获取交易web3.eth.getTransaction()
  • 获取交易收据web3.eth.getTransactionReceipt()
  • 获取账户余额web3.eth.getBalance()

3. 智能合约交互

  • 部署合约new web3.eth.Contract().deploy().send()
  • 调用合约方法contract.methods.methodName().call()
  • 发送交易contract.methods.methodName().send()
  • 监听事件contract.events.EventName()

实用案例分析

连接以太坊网络

// 连接到以太坊网络
const Web3 = require('web3');

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

// 连接到Infura的Sepolia测试网
const web3 = new Web3('https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY');

// 检查连接状态
async function checkConnection() {
  try {
    const networkId = await web3.eth.net.getId();
    console.log('Connected to network:', networkId);
    
    const blockNumber = await web3.eth.getBlockNumber();
    console.log('Current block number:', blockNumber);
    
    return true;
  } catch (error) {
    console.error('Connection error:', error);
    return false;
  }
}

checkConnection();

账户管理

// 账户管理
const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');

// 获取账户
async function getAccounts() {
  try {
    const accounts = await web3.eth.getAccounts();
    console.log('Accounts:', accounts);
    return accounts;
  } catch (error) {
    console.error('Error getting accounts:', error);
    return [];
  }
}

// 创建新账户
function createAccount() {
  const account = web3.eth.accounts.create();
  console.log('New account:', account.address);
  console.log('Private key:', account.privateKey);
  return account;
}

// 获取账户余额
async function getBalance(address) {
  try {
    const balance = await web3.eth.getBalance(address);
    const balanceInEther = web3.utils.fromWei(balance, 'ether');
    console.log('Balance:', balanceInEther, 'ETH');
    return balanceInEther;
  } catch (error) {
    console.error('Error getting balance:', error);
    return '0';
  }
}

// 示例用法
async function main() {
  const accounts = await getAccounts();
  if (accounts.length > 0) {
    await getBalance(accounts[0]);
  }
  const newAccount = createAccount();
  await getBalance(newAccount.address);
}

main();

智能合约交互

// 智能合约交互
const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');

// 合约ABI
const contractABI = [
  {
    "constant": false,
    "inputs": [{"name": "_value", "type": "uint256"}],
    "name": "setValue",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "getValue",
    "outputs": [{"name": "", "type": "uint256"}],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "anonymous": false,
    "inputs": [{"indexed": false, "name": "value", "type": "uint256"}],
    "name": "ValueChanged",
    "type": "event"
  }
];

// 合约地址
const contractAddress = '0x1234567890123456789012345678901234567890';

// 创建合约实例
const contract = new web3.eth.Contract(contractABI, contractAddress);

// 调用合约方法(读取)
async function getContractValue() {
  try {
    const value = await contract.methods.getValue().call();
    console.log('Contract value:', value);
    return value;
  } catch (error) {
    console.error('Error getting contract value:', error);
    return 0;
  }
}

// 发送交易(写入)
async function setContractValue(value) {
  try {
    const accounts = await web3.eth.getAccounts();
    const tx = await contract.methods.setValue(value).send({
      from: accounts[0],
      gas: 1000000
    });
    console.log('Transaction hash:', tx.transactionHash);
    return tx;
  } catch (error) {
    console.error('Error setting contract value:', error);
    return null;
  }
}

// 监听事件
function listenToEvents() {
  contract.events.ValueChanged({},
    function(error, event) {
      if (error) {
        console.error('Event error:', error);
      } else {
        console.log('Event received:', event.returnValues);
      }
    }
  );
}

// 示例用法
async function main() {
  await getContractValue();
  await setContractValue(42);
  await getContractValue();
  listenToEvents();
}

main();

交易操作

// 交易操作
const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');

// 发送ETH
async function sendEther(from, to, amount) {
  try {
    const tx = await web3.eth.sendTransaction({
      from: from,
      to: to,
      value: web3.utils.toWei(amount, 'ether'),
      gas: 21000
    });
    console.log('Transaction hash:', tx.transactionHash);
    return tx;
  } catch (error) {
    console.error('Error sending ether:', error);
    return null;
  }
}

// 估算Gas
async function estimateGas(from, to, amount) {
  try {
    const gas = await web3.eth.estimateGas({
      from: from,
      to: to,
      value: web3.utils.toWei(amount, 'ether')
    });
    console.log('Estimated gas:', gas);
    return gas;
  } catch (error) {
    console.error('Error estimating gas:', error);
    return 21000; // 默认值
  }
}

// 获取Gas价格
async function getGasPrice() {
  try {
    const gasPrice = await web3.eth.getGasPrice();
    const gasPriceInGwei = web3.utils.fromWei(gasPrice, 'gwei');
    console.log('Gas price:', gasPriceInGwei, 'Gwei');
    return gasPriceInGwei;
  } catch (error) {
    console.error('Error getting gas price:', error);
    return '0';
  }
}

// 示例用法
async function main() {
  const accounts = await web3.eth.getAccounts();
  if (accounts.length >= 2) {
    const from = accounts[0];
    const to = accounts[1];
    const amount = '0.01';
    
    await getGasPrice();
    await estimateGas(from, to, amount);
    await sendEther(from, to, amount);
    
    // 检查余额
    const balanceFrom = await web3.eth.getBalance(from);
    const balanceTo = await web3.eth.getBalance(to);
    console.log('Balance from:', web3.utils.fromWei(balanceFrom, 'ether'), 'ETH');
    console.log('Balance to:', web3.utils.fromWei(balanceTo, 'ether'), 'ETH');
  }
}

main();

区块链查询

// 区块链查询
const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');

// 获取区块信息
async function getBlock(blockNumber) {
  try {
    const block = await web3.eth.getBlock(blockNumber);
    console.log('Block:', block);
    return block;
  } catch (error) {
    console.error('Error getting block:', error);
    return null;
  }
}

// 获取交易信息
async function getTransaction(txHash) {
  try {
    const tx = await web3.eth.getTransaction(txHash);
    console.log('Transaction:', tx);
    return tx;
  } catch (error) {
    console.error('Error getting transaction:', error);
    return null;
  }
}

// 获取交易收据
async function getTransactionReceipt(txHash) {
  try {
    const receipt = await web3.eth.getTransactionReceipt(txHash);
    console.log('Transaction receipt:', receipt);
    return receipt;
  } catch (error) {
    console.error('Error getting transaction receipt:', error);
    return null;
  }
}

// 获取链上信息
async function getChainInfo() {
  try {
    const networkId = await web3.eth.net.getId();
    const chainId = await web3.eth.getChainId();
    const blockNumber = await web3.eth.getBlockNumber();
    
    console.log('Network ID:', networkId);
    console.log('Chain ID:', chainId);
    console.log('Current block:', blockNumber);
    
    return {
      networkId,
      chainId,
      blockNumber
    };
  } catch (error) {
    console.error('Error getting chain info:', error);
    return null;
  }
}

// 示例用法
async function main() {
  await getChainInfo();
  const latestBlock = await web3.eth.getBlockNumber();
  await getBlock(latestBlock);
  
  // 假设我们有一个交易哈希
  // const txHash = '0x1234567890123456789012345678901234567890123456789012345678901234';
  // await getTransaction(txHash);
  // await getTransactionReceipt(txHash);
}

main();

实践练习

  1. 连接以太坊网络

    • 安装Web3.js库
    • 连接到本地Ganache节点
    • 连接到Infura的测试网络
    • 检查连接状态和网络信息
  2. 账户管理

    • 获取现有账户
    • 创建新账户
    • 检查账户余额
    • 发送ETH到另一个账户
  3. 智能合约交互

    • 部署一个简单的智能合约
    • 调用合约的读取方法
    • 调用合约的写入方法
    • 监听合约事件
  4. 交易操作

    • 估算交易Gas
    • 获取当前Gas价格
    • 发送交易并获取交易收据
    • 验证交易是否成功
  5. 区块链查询

    • 获取最新区块信息
    • 查询指定交易的详细信息
    • 分析区块中的交易
    • 监控网络状态

总结

Web3.js是Web3前端开发的核心库之一,它提供了与以太坊网络交互的完整功能。通过Web3.js,开发者可以:

  • 连接到以太坊网络:无论是主网、测试网还是本地网络
  • 管理账户:创建账户、签名交易、检查余额
  • 与智能合约交互:部署合约、调用方法、监听事件
  • 查询区块链数据:获取区块、交易和网络信息

在实际开发中,Web3.js通常与前端框架(如React、Vue)结合使用,构建去中心化应用(DApp)。它是连接用户与区块链的桥梁,使前端应用能够与智能合约和区块链数据进行交互。

通过本集的学习,你应该能够理解Web3.js的基本使用方法和核心功能,为开发Web3前端应用打下基础。

« 上一篇 高级Solidity特性 下一篇 » Ethers.js基础