这些天想升级Dapp的时候却发现web3.js包用不了!web3.js一直以来是又大又难装,这下彻底完犊了,用不了了。这时只能启用备用方案:ethers.js
ethers.js更新的挺快,这就6.8的版本啰!
简单对比了下,ethers.js大约是18M, web3.js却有近57M!ethers.js很是小巧灵活。测试了一些写法,感觉还是很丝滑的。而且功能也很全面,爱了!
下载与资源
ethers |
ethers-github |
中文文档 |
安装
npm install ethers --save
// "ethers": "^6.8.0" 18.3M
// cnpm install ethers --save
// yarn add ethers
Gas
一经创建,每笔交易都收取一定数量的 gas ,目的是限制执行交易所需要的工作量和为交易支付手续费。EVM 执行交易时,gas 将按特定规则逐渐耗尽。
gas price 是交易发送者设置的一个值,发送者账户需要预付的手续费= gasPrice * gas 。如果交易执行后还有剩余, gas 会原路返还。
创建providers
ethers是一套和以太坊节点进行通信的API,是对JSON-RPC的封装。如果我们需要基于以太坊来开发去中心化应用,就需要通过ethers来获取节点状态,获取账号信息,调用合约、监听合约事件等等。
智能合约是运行在节点提供的虚拟机上,因此调用智能合约也需要像节点发送请求。
import { ethers } from 'ethers'
// const ethers = require('ethers')
//使用本地节点或是远程节点
const url = "http://127.0.0.1:8545"
//"http://localhost:8545" 会报错
// const url = "https://rpc-mumbai.maticvigil.com"
// const url = "https://rpc.ftm.tools/"
const provider = new ethers.JsonRpcProvider(url)
//交易签名
const signer = await provider.getSigner() //默认地址,一般是第一个
//const signer = await provider.getSigner("0x025C4AB61A50Ce391E9F3cd88a858E5C5ADABaF1") //可以这样指定
//metamask中获取
provider = new ethers.BrowserProvider(window.ethereum)
基本使用
// Look up the current block number
await provider.getBlockNumber()
// 16383845
//获取一个地址或ENS的余额
let addr = "0xf9eFdD67e2C46a8086aed666ea8e294986AB285C"
let balance = await provider.getBalance(addr)
// 100000000000000000000n
//eth转成wei
ethers.parseEther("1.2")
//1200000000000000000n
//wei转成 eth
ethers.formatEther('23')
// 0.000000000000000023
//发送交易
const option = {
to:toAccount,
value: 1500000000, //wei
gas: gas,
gasPrice: gasPrice
}
eg:
const tx = await signer.sendTransaction({
to: "0xf33B812142b8a008cD98ED889605869B31393849",
value: ethers.parseEther("1.0")
})
const receipt = await tx.wait()
console.log(899, receipt)
/*
TransactionReceipt {
provider: JsonRpcProvider {},
to: '0xf33B812142b8a008cD98ED889605869B31393849',
from: '0xf9eFdD67e2C46a8086aed666ea8e294986AB285C',
contractAddress: null,
hash: '0xafac68a6a871424bf2aa4da66b7aed38c379bd335e56f8bfecdea680febac5ed',
index: 0,
blockHash: '0xb5e876eae0264cdfbbb7e8d0e3676ed31abc6121d78fc9080498fea3bdafa3d2',
blockNumber: 1,
logsBloom: '0x0000000....00',
gasUsed: 21000n,
cumulativeGasUsed: 21000n,
gasPrice: 20000000000n,
type: 0,
status: 1,
root: undefined
}
*/
常用方法
1. 单位换算
//eth转成wei
ethers.parseEther("1.2")
//1200000000000000000n
//wei转成 eth
ethers.formatEther('23')
// 0.000000000000000023
//另外一种转换方法
ethers.parseUnits("1.3", 18) // 乘以10**18
//1300000000000000000n
ethers.formatUnits("1300000000000000000", 18) // 除以10**18
//1.3
2. gasLimit
signer.estimateGas(tx)
通过执行一个消息调用来得到交易的 gas 用量, 在此基础上加30000gas
3. GasPrice
await provider.getFeeData() //获取当前gas价格
/*
FeeData {
gasPrice: 20000000000n,
maxFeePerGas: null,
maxPriorityFeePerGas: null
}*/
4. 查找最新区块号
await provider.getBlockNumber()
//2655567
钱包功能
import { ethers } from 'ethers'
import fs from 'fs'
//直接生成私钥和地址
let lbcWallet = ethers.Wallet.createRandom()
lbcWallet.address
// "0x863e27dbD608649d08c69F83ccA51b045721f318"
lbcWallet.privateKey
// "0x8bc29xxxxxxx"
//随机数生成钱包
let random = ethers.randomBytes(32)
console.log(563, random)
let privateKey = Buffer.from(random).toString('hex') //转成16进制
console.log(112, privateKey)
let wallet = new ethers.Wallet(privateKey)
console.log("账号地址: " + wallet.address, wallet)
//生成随机助记词并创建钱包
let mnemonic = ethers.Mnemonic.fromEntropy(ethers.randomBytes(16))
// let mnemonic = ethers.Mnemonic.fromEntropy(ethers.randomBytes(16), "jxxxx") 第二个参数是密码
console.log(1323, mnemonic)
var path = "m/44'/60'/0'/0/0"
// 通过助记词创建钱包
let wallet = ethers.HDNodeWallet.fromMnemonic(mnemonic, path)
console.log("账号地址: " + wallet.address, wallet)
//根据助记词找回钱包信息
let monic = "dinosaur tape orbit chronic private ....."
let mnemonic = ethers.Wallet.fromPhrase(monic)
console.log(566, mnemonic)
let privateKey = mnemonic.privateKey
console.log("钱包私钥:",privateKey)
//根据私钥找回钱包地址
let wallet = new ethers.Wallet(privateKey)
//钱包地址
let address = wallet.address
console.log(156, address)
//生成json钱包文件
let main = async function (){
let random = ethers.randomBytes(32)
let privateKey = Buffer.from(random).toString('hex') //转成16进制
let wallet = new ethers.Wallet(privateKey)
let password = "xxxxx"
let res = await wallet.encrypt(password)
console.log(156, res)
let d = new Date()
let time = d.getTime()
let path = './keystore/' + time + '-' + wallet.address
fs.writeFileSync(path, res)
}
//json文件找回钱包信息
let main2 = async function (){
let res = fs.readFileSync('./keystore/16983xxxxxxxxxxxB2c6', "utf8")
let password = "xxxxxx"
let wallet = await ethers.Wallet.fromEncryptedJson(res, password)
console.log("Address: " + wallet.address, wallet,"privateKey:", wallet.privateKey)
}
与合约交互
//只读方法 (like view and pure)
import { ethers } from 'ethers'
const url = "http://127.0.0.1:8545"
const provider = new ethers.JsonRpcProvider(url)
let abi = [
"function str() view returns (string)",
"function set(uint x)",
"function get()view returns (uint)"
]
//这里的abi相当于接口
// 也可以使用合约的编译abi: import Storage from '@/static/Storage.json' -> Storage.abi
let contractAddr = "0x600a00aE84b896edd9F2732565cf2195d032315E"
let contract = new ethers.Contract(contractAddr, abi, provider)
let str = await contract.get()
console.log(256, str)
//合约的所有方法, signer签名
const url = "http://127.0.0.1:8545"
const contractAddr = "0x600a00aE84b896edd9F2732565cf2195d032315E"
const provider = new ethers.JsonRpcProvider(url)
const signer = await provider.getSigner()
const contract = new ethers.Contract( contractAddr, Storage.abi, signer)
console.log(56, "signer:", signer)
const option = {
}
const tx = await contract.set(996, option)
await tx.wait()
console.log(669, "singen res:", tx)
//合约的所有方法, 也可以连上钱包来实现
import Storage from '@/static/Storage.json'
const url = "http://127.0.0.1:8545"
const contractAddr = "0x600a00aE84b896edd9F2732565cf2195d032315E"
const provider = new ethers.JsonRpcProvider(url)
const contract = new ethers.Contract(contractAddr, Storage.abi, provider)
const PRIVATE_KEY = "0x182xxxxxxxxx"
const wallet = new ethers.Wallet(PRIVATE_KEY, provider)
console.log(56, "wallet:", wallet)
const nonce = await provider.getTransactionCount(wallet.address)
console.log(58, "nonce:", nonce)
const StorageConnected = contract.connect(wallet)
const option = {
nonce
}
const tx = await StorageConnected.set(86394, option)
await tx.wait()
console.log(669, "res:", tx)
ethers的体验相当不错,功能齐全,它的转正也是情理之中啰。