使用Web3.js监听USDT转账报错:TypeError: Cannot read properties of undefined (reading 'on')
问题:监听以太坊USDT转入时触发TypeError错误
我正在使用Node.js和Web3监听以太坊链上我的USDT ERC20钱包地址的交易,希望在USDT转入钱包时实时记录到账金额。以下是我的代码:
const {Web3} = require('web3'); const USDT_ABI = require('erc-20-abi'); //My QuickNode WSS endpoint const wssProviderUrl = 'wss://thrilling-orbital-lake.quiknode.pro/********/'; // Initialize Web3 with WebSocket provider const web3Client = new Web3(new Web3.providers.WebsocketProvider(wssProviderUrl)); // My wallet address const yourAddress = '0x***********************'; // USDT contract address on Ethereum const USDTContractAddress = '0xdAC17F958D2ee523aeeE4C20C7C1dE6e8FcB49aC'; /// Initialize the USDT contract const USDTContract = new web3Client.eth.Contract(USDT_ABI, USDTContractAddress); // Subscribe to Transfer events to your address USDTContract.events.Transfer({ filter: { to: yourAddress } }) .on('data', (event) => { const amount = event.returnValues.value; console.log(`Received ${web3Client.utils.fromWei(amount, 'mwei')} USDT to your wallet address!`); }) .on('error', (error) => { console.error('Error subscribing to event:', error); });
但我持续遇到如下错误:
.on('error', (error) => { ^ TypeError: Cannot read properties of undefined (reading 'on')
期望代码能在收到代币时记录交易详情,请问该如何修复?
修复方案
这个错误的核心原因是USDTContract.events.Transfer()没有返回预期的可订阅对象,通常由以下问题导致,对应修复方法如下:
1. 替换为USDT专属的Transfer事件ABI
erc-20-abi包的通用ABI可能和USDT合约的实际实现不匹配,直接使用USDT合约的Transfer事件ABI片段即可:
// 移除原有的const USDT_ABI = require('erc-20-abi'); // 手动定义USDT合约的Transfer事件ABI const USDT_ABI = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" } ];
2. 等待WebSocket连接就绪后再订阅事件
Web3的WebSocket连接是异步初始化的,直接调用订阅会因连接未就绪返回undefined。通过监听连接状态,在连接成功后执行订阅:
const {Web3} = require('web3'); // 手动定义USDT的Transfer事件ABI const USDT_ABI = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" } ]; const wssProviderUrl = 'wss://thrilling-orbital-lake.quiknode.pro/********/'; const web3Client = new Web3(new Web3.providers.WebsocketProvider(wssProviderUrl)); const yourAddress = '0x***********************'; const USDTContractAddress = '0xdAC17F958D2ee523aeeE4C20C7C1dE6e8FcB49aC'; // 监听WebSocket连接状态 web3Client.provider.on('connect', () => { console.log('WebSocket连接成功'); // 初始化合约并订阅事件 const USDTContract = new web3Client.eth.Contract(USDT_ABI, USDTContractAddress); USDTContract.events.Transfer({ filter: { to: yourAddress } }) .on('data', (event) => { const amount = event.returnValues.value; console.log(`Received ${web3Client.utils.fromWei(amount, 'mwei')} USDT to your wallet address!`); }) .on('error', (error) => { console.error('订阅事件出错:', error); }); }); web3Client.provider.on('error', (err) => { console.error('WebSocket连接失败:', err); });
3. 适配Web3 v4.x版本的API
如果使用Web3 v4.x,事件订阅需要通过异步的subscribe方法实现:
const {Web3} = require('web3'); const USDT_ABI = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" } ]; const wssProviderUrl = 'wss://thrilling-orbital-lake.quiknode.pro/********/'; const web3Client = new Web3(new Web3.providers.WebsocketProvider(wssProviderUrl)); const yourAddress = '0x***********************'; const USDTContractAddress = '0xdAC17F958D2ee523aeeE4C20C7C1dE6e8FcB49aC'; async function subscribeToUSDTTransfers() { try { const USDTContract = new web3Client.eth.Contract(USDT_ABI, USDTContractAddress); const subscription = await USDTContract.subscribe('Transfer', { filter: { to: yourAddress } }); subscription.on('data', (event) => { const amount = event.returnValues.value; console.log(`Received ${web3Client.utils.fromWei(amount, 'mwei')} USDT to your wallet address!`); }); subscription.on('error', (error) => { console.error('订阅事件出错:', error); }); } catch (err) { console.error('订阅初始化失败:', err); } } web3Client.provider.on('connect', () => { console.log('WebSocket连接成功'); subscribeToUSDTTransfers(); }); web3Client.provider.on('error', (err) => { console.error('WebSocket连接失败:', err); });
4. 校验地址格式
确保yourAddress和USDTContractAddress是有效的以太坊地址(支持全小写或校验和格式),避免因地址格式错误导致订阅逻辑异常。
内容的提问来源于stack exchange,提问作者Anything figures
相关产品推荐
相关产品推荐

