wtfacademy / wtf-ethers Goto Github PK
View Code? Open in Web Editor NEW我最近在重新学ethers.js,巩固一下细节,也写一个“WTF Ethers.js极简入门”,供小白们使用,每周更新1-3讲。Now supports English! 官网: https://wtf.academy
Home Page: https://wtf.academy
License: Other
我最近在重新学ethers.js,巩固一下细节,也写一个“WTF Ethers.js极简入门”,供小白们使用,每周更新1-3讲。Now supports English! 官网: https://wtf.academy
Home Page: https://wtf.academy
License: Other
大佬们好,19课中订阅的是节点中所有内存池交易,效率太低了,我监控某个地址可能还没遍历到,就已经被打包了,这种方式不太高效,不知道又更好的方案去监控内存池的交易吗?比如我设置过滤条件只拉取特定to地址的交易回来。geth官方节点好像并没有提供这种功能,我尝试了其他更多都是第三方提供的一些增强api。parity节点有类似的功能,但这种节点几乎没有服务商支持,只有自己搭建。各位大佬,有更好的办法吗?
注释错误:
Ethers.js V5 使用 contract.address 获取合约地址
V6使用 contract.target 或 contract.getAddress()获取合约地址
// 3. 用staticCall尝试调用transfer转账10000 DAI,msg.sender为测试钱包地址,交易将失败
console.log("\n3. 用staticCall尝试调用transfer转账1 DAI,msg.sender为测试钱包地址")
const tx2 = await contractDAI.transfer.staticCall("vitalik.eth", ethers.parseEther("10000"), {from: address})
console.log(交易会成功吗?:
, tx)
console.log中的tx应该为tx2
我用的是6.3.0
解决方案:替换成 ethers.Wallet.fromPhrase(mnemonic.phrase)
从归集钱包转账到被归集的钱包地址时,是不是要预留出 gas 消耗的费用,而不是将 balance 全部转给归集地址?
你可以利用下面两种命令,等待合约部署在链上确认,然后再进行交互。
await contract.deployed()
//或者 await contract.deployTransaction.wait()
应该是
await contract.waitForDeployment();
await contract.deployTransaction.wait()
你好,在https://github.com/WTFAcademy/WTFEthers/blob/main/16_MultiCollect/readme.md
这个教程中,在批量归集钱包的ETH代币这部分代码
console.log("\n4. 批量归集20个钱包的ETH") const txSendETH = { to: wallet.address, value: amount } for (let i = 0; i < numWallet; i++) { // 将钱包连接到provider let walletiWithProvider = **wallets[i].connect(provider)** var tx = await walletiWithProvider.sendTransaction(txSendETH) console.log(
第 ${i+1} 个钱包 ${walletiWithProvider.address} ETH 归集开始) } await tx.wait() console.log(
ETH 归集结束)
运行之后,出现报错:
报错信息是:
UnhandledPromiseRejectionWarning: TypeError: wallets[i].connect is not a function
请教一下如何解决?感谢!
现在的Goerli ETH faucet限制很多,但是在Sepolia就很容易获得测试用的ETH。
并且Goerli网络反应慢很多,Sepolia非常快。(都是INFURA节点)
可以考虑把教程中的Goerli换成Sepolia(我可以提PR)。
你好,在https://github.com/WTFAcademy/WTFEthers/blob/main/17_MerkleTree/readme.md 这个文中有一处地方表述有误,
红色框中的变量
第十节文章需要更新的点
原代码:
// 连接以太坊主网
const providerETH = new ethers.providers.JsonRpcProvider(https://mainnet.infura.io/v3/${INFURA_ID}
)
// 连接Goerli测试网
const providerGoerli = new ethers.providers.JsonRpcProvider(https://goerli.infura.io/v3/${INFURA_ID}
)
显示
TypeError: Cannot read properties of undefined (reading 'JsonRpcProvider')
// 连接以太坊主网
const providerETH = new ethers.JsonRpcProvider(
https://mainnet.infura.io/v3/${INFURA_ID}
);
// 连接Goerli测试网
const providerGoerli = new ethers.JsonRpcProvider(
https://goerli.infura.io/v3/${INFURA_ID}
);
成功获取结果
文字内容审核建议:增加代码参考示例官网链接
图片内容审核建议:内容完整,无需调整
interface Temp {
function supportsInterface(bytes4 interfaceId) external pure returns (bool);
}
contract Tmp is Temp {
function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return true;
}
}```
使用:
`
const selectorERC721 = "0x80ac58cd"
const isERC721 = await contractbayc.supportsInterface(selectorERC721)
`
将返回true ,但实际上该合约并不是erc721标准的
Error: ENS name not configured (operation="resolveName("vitalik.eth")", code=UNSUPPORTED_OPERATION, version=providers/5.6.8)
at Logger.makeError (D:\vs\node_modules@ethersproject\logger\lib\index.js:233:21)
at Logger.throwError (D:\vs\node_modules@ethersproject\logger\lib\index.js:242:20)
at FallbackProvider. (D:\vs\node_modules@ethersproject\providers\lib\base-provider.js:1970:36)
at step (D:\vs\node_modules@ethersproject\providers\lib\base-provider.js:48:23)
at Object.next (D:\vs\node_modules@ethersproject\providers\lib\base-provider.js:29:53)
at fulfilled (D:\vs\node_modules@ethersproject\providers\lib\base-provider.js:20:58)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
reason: 'ENS name not configured',
code: 'UNSUPPORTED_OPERATION',
operation: 'resolveName("vitalik.eth")'
}
ERC20Check中的这段话:ERC20标准中只有 transfer(address, uint256) 不包含在 ERC721标准、ERC1155和ERC777标准中。因此如果一个合约包含 transfer(address, uint256) 的选择器,就能确定它是 ERC20 代币合约,而不是其他。
以太坊区块链上的合约有那么多,任何人都可以部署任何合约上去,不能说排除了721/1155/777之外就可以吧,任何其他非erc20合约只要包含transfer(address, uint256) 函数完全有可能,甚至可能是恶意的。这个说法能成立吗?
应为:
if (
ethers.utils.formatEther(balanceETH) > ethers.utils.formatEther(amount) &&
ethers.utils.formatEther(balanceWETH) >= ethers.utils.formatEther(amount)
)
第六节文章需要更新的点
在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
更换RPC节点
更换测试网
更新bytecodeERC20实际数据
第六节代码需要更新的点
更新代码的注释
文字内容审核建议:
文字内容审核建议:
1. 文档中的测试网是Rinkeby,代码中的测试网是Goerli,以代码为标准进行更新
图片内容审核建议:
1.内容完整,无需调整
文字内容审核建议:
1. 实现代码与文章中的代码示例有一些顺序调整,已做文本说明
图片内容审核建议:
1.内容完整,无需调整
ethers.Wallet.fromMnemonic(mnemonic.phrase)在新的api里是ethers.Wallet.fromPhrase(mnemonic.phrase),构造方法改了
报错connect ECONNREFUSED 127.0.0.1:443
错误原因应该是连接不上以太坊主网,端口443返回的错误
一般情况下是自身的网络问题,在网上查询时也是如此。但是我检查过后没有任何问题,最后更换了ethersjs版本到6.11.1解决
const wallet = new ethers.Wallet(privateKey, Provider)
const tx = wallet.getTransactionCount()
const wallet2Mnemonic = Wallet.fromMnemonic(mnemonic)
const wallet2 = wallet2Mnemonic.connect(Provider)
const tx2 = wallet.getTransactionCount()
以上兩種方法皆會返還以下錯誤:
TypeError: wallet.getTransactionCount is not a function
需要將 getTransactionCount() 替換成 getNonce()
第八节文章需要更新的点
在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
BigNumber函数更新为getBigInt
第八节代码需要更新的点
无
请问一下,这一行代码不应该是value
吗?amount
的话,无法取得值。
如果需要我可以提交PR。
https://github.com/thurendous/WTFEthers/blob/1a45850bb1a67dd7061e3b8f9f531adca16d1c1b/07_Event/Event.js#L38
const amount = ethers.utils.formatUnits(ethers.BigNumber.from(transferEvents[0].args["amount"]), "ether");
环境:
Win10
npm 9.5.0
ethers 6.0.5
代码:
const { ethers } = require("ethers"); //如果用import的话,需要改package.json,但本错误仍然不可避免
// const provider = ethers.getDefaultProvider();
const provider = new ethers.JsonRpcProvider("https://1rpc.io/eth");
const main = async () => {
const balance = await provider.getBalance(vitalik.eth
);
console.log(ETH Balance of vitalik: ${ethers.utils.formatEther(balance)} ETH
);
// console.log(ETH Balance of vitalik: ${balance} ETH
); // 这一行可以正常运行
}
main()
报错:
TypeError: Cannot read properties of undefined (reading 'formatEther')
at main (file:///D:/Etherjs/Lesson/L1.js:7:57)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
请教
第一遍看没看明白制定是什么意思,还在想区块高度是可以制定的嘛😅
后来继续看文章后续,发现原来是写错了字。。。
https://github.com/WTFAcademy/WTF-Ethers/blob/main/25_Flashbots/readme.md
【制定】应该是【指定】
第七节文章需要更新的点
在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
更换RPC节点
第七节代码需要更新的点
无
var error = new Error(message);
^
Error: missing response (requestBody="{"method":"eth_getBalance","params":["0x74777aa4d53dea221d77227d11dbbaf04d5459bd","latest"],"id":47,"jsonrpc":"2.0"}", requestMethod="POST", serverError={"errno":-4077,"code":"ECONNRESET","syscall":"read"}, url="https://eth-goerli.alchemyapi.io/v2/GlaeWuylnNM3uuOo-SAwJxuwTdqHaY5l", code=SERVER_ERROR, version=web/5.7.1)
reason: 'missing response',
code: 'SERVER_ERROR',
requestBody: '{"method":"eth_getBalance","params":["0x74777aa4d53dea221d77227d11dbbaf04d5459bd","latest"],"id":47,"jsonrpc":"2.0"}',
requestMethod: 'POST',
serverError: Error: read ECONNRESET
at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20) {
errno: -4077,
code: 'ECONNRESET',
syscall: 'read'
},
url: 'https://eth-goerli.alchemyapi.io/v2/GlaeWuylnNM3uuOo-SAwJxuwTdqHaY5l'
需要先引入 import { formatEther } from 'ethers';
然后直接使用 formatEther(balance)
ethers.Wallet.fromMnemonic(mnemonic.phrase)在新的api里是ethers.Wallet.fromPhrase(mnemonic.phrase),构造方法改了
const numWallet = 20
// 派生路径:m / purpose' / coin_type' / account' / change / address_index
// 我们只需要切换最后一位address_index,就可以从hdNode派生出新钱包
let basePath = "m/44'/60'/0'/0";
let wallets = [];
for (let i = 0; i < numWallet; i++) {
let hdNodeNew = hdNode.derivePath(basePath + "/" + i);
let walletNew = new ethers.Wallet(hdNodeNew.privateKey);
console.log(`第${i+1}个钱包地址: ${walletNew.address}`)
wallets.push(walletNew);
}
这里提示一下报错,路径找了很久都是这个路径
TypeError: cannot derive root path (i.e. path starting with "m/") for a node at non-zero depth 5 (argument="path", value="m/44'/60'/0'/0/0", code=INVALID_ARGUMENT, version=6.11.1)
at makeError (d:\code\mev-bot\node_modules\ethers\lib.commonjs\utils\errors.js:122:21)
at assert (d:\code\mev-bot\node_modules\ethers\lib.commonjs\utils\errors.js:149:15)
at assertArgument (d:\code\mev-bot\node_modules\ethers\lib.commonjs\utils\errors.js:161:5)
at derivePath (d:\code\mev-bot\node_modules\ethers\lib.commonjs\wallet\hdwallet.js:68:39)
at HDNodeWallet.derivePath (d:\code\mev-bot\node_modules\ethers\lib.commonjs\wallet\hdwallet.js:253:16)
at main (d:\code\mev-bot\练习操作\批量钱包.js:20:32)
at Object.<anonymous> (d:\code\mev-bot\练习操作\批量钱包.js:44:1)
at Module._compile (node:internal/modules/cjs/loader:1376:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
at Module.load (node:internal/modules/cjs/loader:1207:32) {
code: 'INVALID_ARGUMENT',
argument: 'path',
value: "m/44'/60'/0'/0/0",
shortMessage: 'cannot derive root path (i.e. path starting with "m/") for a node at non-zero depth 5'
}
但是在 ethers v6版本 derivePath函数中写了这样一个判断
if (components[0] === "m") {
assertArgument(node.depth === 0, `cannot derive root path (i.e. path starting with "m/") for a node at non-zero depth ${ node.depth }`, "path", path);
components.shift();
}
请问这是为什么呢,我是新手刚开始学习,不太懂这个
console.log("\n1. 连接 wss RPC")
// 准备 alchemy API 可以参考https://github.com/AmazingAng/WTFSolidity/blob/main/Topics/Tools/TOOL04_Alchemy/readme.md
const ALCHEMY_MAINNET_WSSURL = 'wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN';
const provider = new ethers.providers.WebSocketProvider(ALCHEMY_MAINNET_WSSURL);
let i =0
provider.on("pending", async (txHash) => {
if (txHash && i < 100) {
// 打印txHash
console.log([${(new Date).toLocaleTimeString()}] 监听Pending交易 ${i}: ${txHash} \r
);
i++
}
});
provider ._websocket.on("error", async () => {
console.log(Unable to connect to ${ep.subdomain} retrying in 3s...
);
setTimeout(listen_address, 3000);
});
provider ._websocket.on("close", async (code) => {
console.log(
Connection lost with code ${code}! Attempting reconnect in 3s...
);
provider ._websocket.terminate();
setTimeout(listen_address, 3000);
});
求问一下,在第19节 Mempool里,如果是在 ethers v5里,以上的 provider ._websocket.on("error", async () => {});代码是可以正常捕获错误,延时后继续推送交易的;
但是在ethers V6里provider 定义变了 const provider = new ethers.WebSocketProvider(ALCHEMY_MAINNET_WSSURL);然后这个捕获异常provider ._websocket.on("error", async () => {})就不能用了,请问V6里捕获websocket error是怎么用的呢?谢谢大佬,往不吝赐教!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.