第2节:Provider 与 Signer

小白入门:https://github.com/dukedaily/solidity-expert ,欢迎star转发,文末加V入群。

职场进阶: https://dukeweb3.com

Provider 提供"读"的能力,Signer 提供"写"的能力。本节覆盖三类 Provider、Signer 的两种来源,以及 v6 中必须掌握的 bigint 语义。

三类 Provider

JsonRpcProvider —— 后端 / 脚本常用

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://eth.llamarpc.com");

const block = await provider.getBlockNumber();
console.log("当前块:", block);

BrowserProvider —— 前端 dApp

浏览器环境,接 MetaMask / Rabby / OKX Wallet:

const provider = new ethers.BrowserProvider(window.ethereum);

// 请求钱包连接
await provider.send("eth_requestAccounts", []);

// 获取当前账户 Signer
const signer = await provider.getSigner(); // v6: async
const addr = await signer.getAddress();

v6 重要变化provider.getSigner() 在 BrowserProvider 下返回 Promise(v5 是同步)。

WebSocketProvider —— 订阅事件

const ws = new ethers.WebSocketProvider(
  "wss://eth-mainnet.g.alchemy.com/v2/<KEY>",
);

ws.on("block", (n) => console.log("new block:", n));

两种 Signer 来源

Wallet(脚本端)

从私钥构造,常用于后端脚本、部署、bot:

const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

const addr = await wallet.getAddress();
const bal = await provider.getBalance(addr);

BrowserProvider.getSigner()(前端)

由浏览器钱包(MetaMask 等)代为管理密钥,如上一节示例。

bigint 是 v6 的通行货币

v6 不再使用 BigNumber,所有金额、block number、nonce 都用原生 bigint

const wei = await provider.getBalance(addr);
// wei 的类型是 bigint,不是 BigNumber

const ethValue = ethers.formatEther(wei); // 字符串 "1.234"
const weiValue = ethers.parseEther("1.0"); // 1000000000000000000n

// 运算直接用 bigint 语法
const twice = wei * 2n;
const half = wei / 2n;

bigint 与 number 不能混用,1n + 1 会抛 TypeError。需要显式转换:

const { chainId } = await provider.getNetwork();
const id = Number(chainId); // chainId 本身是 bigint

小结

Provider 读、Signer 写、bigint 算。下一节把三者组合起来读合约。