Coder Social home page Coder Social logo

wtfacademy / wtf-ethers Goto Github PK

View Code? Open in Web Editor NEW
2.7K 2.7K 433.0 19.7 MB

我最近在重新学ethers.js,巩固一下细节,也写一个“WTF Ethers.js极简入门”,供小白们使用,每周更新1-3讲。Now supports English! 官网: https://wtf.academy

Home Page: https://wtf.academy

License: Other

JavaScript 89.28% HTML 4.20% CSS 0.21% Solidity 6.31%
ethereum ethers ethersjs javascript nodejs solidity typescript web3

wtf-ethers's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wtf-ethers's Issues

ethers第19课mempool交易可以设置过滤条件监控吗?

大佬们好,19课中订阅的是节点中所有内存池交易,效率太低了,我监控某个地址可能还没遍历到,就已经被打包了,这种方式不太高效,不知道又更好的方案去监控内存池的交易吗?比如我设置过滤条件只拉取特定to地址的交易回来。geth官方节点好像并没有提供这种功能,我尝试了其他更多都是第三方提供的一些增强api。parity节点有类似的功能,但这种节点几乎没有服务商支持,只有自己搭建。各位大佬,有更好的办法吗?

06_DeployContract 注释错误

注释错误:
Ethers.js V5 使用 contract.address 获取合约地址
V6使用 contract.target 或 contract.getAddress()获取合约地址

11_StaticCall 部分代码有误

// 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

16_批量归集 gas 消耗问题

从归集钱包转账到被归集的钱包地址时,是不是要预留出 gas 消耗的费用,而不是将 balance 全部转给归集地址?

23FrontRun的这张图疑似有问题

Alice和Bob都是GP1和t1吗?
另外一个问题,如果晚来者(t值较大)出价更高(GP更高),那么是不是价高者有优先权?
还有,如果价低者的Gas总值比价高者的高,那么谁有优先权呢?
image

playcode编译报错:RangeError: Potential infinite loop: exceeded 1500 iterations

第一个例子在playcode中运行时就报错了,如果引入cdn上的ethers资源,就会提示如下错误,可是demo中并没有循环。难道你们的电脑都是OK的吗?

RangeError: Potential infinite loop: exceeded 1500 iterations.
    at unsafe_atob (<anonymous>:7743:34)
    at read_compressed_payload (<anonymous>:7732:41)
    at <anonymous>:7877:11
    at mn (<anonymous>:16:5455)

image

wallets[i].connect is not a function

你好,在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到Sepolia

现在的Goerli ETH faucet限制很多,但是在Sepolia就很容易获得测试用的ETH。
并且Goerli网络反应慢很多,Sepolia非常快。(都是INFURA节点)

可以考虑把教程中的Goerli换成Sepolia(我可以提PR)。

教程10审核

第十节文章需要更新的点

  1. 在首栏信息介绍的Github链接需要更新
  2. 需要对于教程版本进行说明
  3. 代码参考链接需要更新
    第十节代码需要更新的点
  4. 同步代码的注释

ethers 是不是代码更新了,还是我写错了?

原代码:
// 连接以太坊主网
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}
);
成功获取结果

第十讲审核结果

文字内容审核建议:增加代码参考示例官网链接
图片内容审核建议:内容完整,无需调整

12_ERC721Check 不应用这种方案判断是否是erc721


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标准的

ENS

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")'
}

关于erc20标准的确立

ERC20Check中的这段话:ERC20标准中只有 transfer(address, uint256) 不包含在 ERC721标准、ERC1155和ERC777标准中。因此如果一个合约包含 transfer(address, uint256) 的选择器,就能确定它是 ERC20 代币合约,而不是其他。
以太坊区块链上的合约有那么多,任何人都可以部署任何合约上去,不能说排除了721/1155/777之外就可以吧,任何其他非erc20合约只要包含transfer(address, uint256) 函数完全有可能,甚至可能是恶意的。这个说法能成立吗?

教程6审核

第六节文章需要更新的点

在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
更换RPC节点
更换测试网
更新bytecodeERC20实际数据

第六节代码需要更新的点
更新代码的注释

第十一讲审核结果

文字内容审核建议:

  1. 十一讲关注CallStatic函数,增加了同样的用于分析的两个函数信息,开拓学习思路
  2. 增加代码参考示例官网链接
    图片内容审核建议:内容完整,无需调整

第十三讲审核结果

文字内容审核建议:

1. 文档中的测试网是Rinkeby,代码中的测试网是Goerli,以代码为标准进行更新

图片内容审核建议:

1.内容完整,无需调整

第十二讲审核结果

文字内容审核建议:

1. 实现代码与文章中的代码示例有一些顺序调整,已做文本说明

图片内容审核建议:

1.内容完整,无需调整

fromMnemonic已经找不到了

ethers.Wallet.fromMnemonic(mnemonic.phrase)在新的api里是ethers.Wallet.fromPhrase(mnemonic.phrase),构造方法改了

第一节 getDefaultProvider连接不上

报错connect ECONNREFUSED 127.0.0.1:443
错误原因应该是连接不上以太坊主网,端口443返回的错误
一般情况下是自身的网络问题,在网上查询时也是如此。但是我检查过后没有任何问题,最后更换了ethersjs版本到6.11.1解决

ethersJS V6版本中,已經不支持getTransactionCount方法

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()

教程8审核

第八节文章需要更新的点

在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
BigNumber函数更新为getBigInt

第八节代码需要更新的点

07Event解析后的事件是个数组,不是key-value

使用contract.queryFilter得到的args是个数组,不是key-value,但是如果按照key-value的方式取值,也是没问题的,难道是console面板打印的问题?
image
image

环境信息:sepolia测试网
合约地址:0x2d0339D0244A0085C1d7398c16449a2d39c97E38
ethers版本:6.7

太难了,用Vscode卡住了

环境:
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)

请教

教程7审核

第七节文章需要更新的点

在首栏信息介绍的Github链接需要更新
需要对于教程版本进行说明
更换RPC节点

第七节代码需要更新的点

ethers 第十五课,跑了好几篇,都报错,有知道什么原因么?

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'

Uncaught SyntaxError: Cannot use import statement outside a module"

报错Uncaught SyntaxError: Cannot use import statement outside a module"
或者 SyntaxError: The requested module 'ethers' does not provide an export named 'ethers'
就是这两个报错,请大神帮忙,怎么才能运行起来,因为这一课没法用那个在线编辑器,已经半天了还是运行不起来,求大神帮帮我
)JMQCII X04D2Q}M3UFBL@O

fromMnemonic已经找不到了

ethers.Wallet.fromMnemonic(mnemonic.phrase)在新的api里是ethers.Wallet.fromPhrase(mnemonic.phrase),构造方法改了

在14批量生成钱包章节中 base地址问题

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();
    }

请问这是为什么呢,我是新手刚开始学习,不太懂这个

19节mempool中,如有用ethers v6版本, 捕获 websocket异常是如何处理呢?

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是怎么用的呢?谢谢大佬,往不吝赐教!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.