为啥我的以太坊“.on”事件监听器停止触发?
Posted
技术标签:
【中文标题】为啥我的以太坊“.on”事件监听器停止触发?【英文标题】:Why Does My Ethereum ".on" Event Listener Stop Firing?为什么我的以太坊“.on”事件监听器停止触发? 【发布时间】:2022-01-16 09:54:40 【问题描述】:我有一个 node.js 服务器,我在其中监听从部署在 Mumbai Polygon 测试网上的 Solidity 智能合约发出的事件。
首先,我使用“web3-providers-ws”节点包创建提供程序,使用 keepalive 和重新连接选项:
let providerNetworkUrl;
let ccggContractAddress;
if (process.env.TESTNET === 'true')
console.log('using mumbai URLs')
// on mumbai
ccggContractAddress = process.env.CCGG_ADDRESS_MUMBAI_TESTNET;
providerNetworkUrl = 'wss://polygon-mumbai.g.alchemy.com/v2/';
else
// on polygon mainnet
ccggContractAddress = process.env.CCGG_ADDRESS_POLYGON_MAINNET;
providerNetworkUrl = 'wss://polygon-mumbai.g.alchemy.com/v2/';
const connectionUrl = providerNetworkUrl + process.env.alchemyApiKey;
console.log('connectionUrl: ', connectionUrl)
// Enable auto reconnection
const options =
clientConfig:
// Useful to keep a connection alive
keepalive: true,
keepaliveInterval: 20 * 60 * 60 * 1000 // keep alive for 20 min
,
// Enable auto reconnection
reconnect:
auto: true,
delay: 1000, // ms
maxAttempts: 10,
onTimeout: false
;
let provider = new ethers.providers.WebSocketProvider(
new Web3WsProvider(connectionUrl, options))
provider.on('end', (e) =>
console.log('provider ended: ' + e);
)
provider.on('error', (e) =>
console.log('provider errored: ' + e);
)
然后我使用 ethers.js 连接到智能合约。
const wallet = new ethers.Wallet(process.env.PRIVATE_WALLET_KEY, provider)
console.log('my address (wallet): ', wallet.address)
const signer = wallet.connect(provider)
const ccggContract = new ethers.Contract(
ccggContractAddress,
ccggAbi,
signer
)
最后我为“GuessSubmitted”事件设置了监听器。
ccggContract.on('GuessSubmitted', async (guess, sender, betSize) =>
console.log('GuessSubmitted')
)
奇怪的是,当我第一次启动它时,一切都很好。节点服务器听到事件,记录“GuessSubmitted”,并处理事件。
但是,几个小时后,或者一夜之间,我去玩游戏,事件在 Solidity 中调度,但节点服务器什么也没听到!!!什么??
在查看了互联网上的其他一些帖子后,我什至设置了这个 ping 函数来保持 websocket 连接处于活动状态,并且我每 15 分钟调用一次:
async function ping()
const now = new Date();
try
console.log('Sending a ping! ' + now.toUTCString());
const blockNum = await provider.send('eth_blockNumber');
console.log('Got blocknum: ', blockNum);
catch (err)
console.log('PING ERROR')
console.log(err)
// ping every 15 min
setInterval(ping, 1000 * 60 * 15);
console.log('provider created.')
奇怪的是,连接似乎并没有真正断开。我从未在日志中看到任何“供应商错误”或“供应商终止”。
日志看起来像这样,每 15 分钟 ping 一次,但再也听不到任何“GuessSubmitted”事件!! ????
我认为问题可能出在我的 eth 连接提供程序上,但我现在已经尝试使用 Alchemy、Infura 和 GetBlock!这个“停止听到事件”问题发生在所有三个问题上,所以我想知道可能是什么问题,如果它是以太坊平台中的一些潜在错误,或者我在代码中犯了一些错误......
谢谢!
【问题讨论】:
又一次发生在我身上!我认为这是以太坊本身的一个**非常**的关键问题!!!遗憾的是它仍然存在这么多问题并且没有解决方案...... ???? 您说“...ping 每 15 分钟一次正常...”,但在您的示例输出中,您只显示“Sending a ping!...”日志消息。没有“Got blocknum:...”日志消息。所以检查很明显,你实际上得到了对你的 ping 请求的响应,对吗? @kaliatech 是的,它每次都显示“pong”日志。 【参考方案1】:如果您查看 web3.js 项目问题,有很多关于断开/关闭/重新连接无法按预期工作的报告:
https://github.com/ChainSafe/web3.js/issues/3927 https://github.com/ethers-io/ethers.js/issues/1053 (不同的项目,但相关的和最近的 cmets 是相关的)没有唯一的解决方案,afaict。正在进行重写以解决一些问题:
https://github.com/ChainSafe/web3.js/issues/4313【讨论】:
我不认为这个问题与“断开/关闭/重新连接”有关,因为我看到了“pong”日志......这是调度solidity事件的侦听器的问题。以上是关于为啥我的以太坊“.on”事件监听器停止触发?的主要内容,如果未能解决你的问题,请参考以下文章
vue-learning:27 - component - 组件三大API之二:event