I write a demo DApp website with this javascript
const web3 = new Web3(ethereum);
const contractAddr = "0x0Aa27e4B13D5c08A8767B36a0ACb76ED4549B7EA";
const abi = ...;
let inst = new web3.eth.Contract(abi, contractAddr);
web3.eth.subscribe('logs', {
address: contractAddr,
}, function (error, result) {
if (!error)
console.log(result);
else
console.log("default:", error);
})
.on("connected", function (subscriptionId) {
console.log(subscriptionId);
})
.on("data", function (log) {
console.log("data:", log);
})
.on("changed", function (log) {
console.log("changed:", log)
}).on("error", function (log) {
console.log("err:", log);
});
In the code I use ethereum
(which is window.ethereum
provided by MetaMask) as the Provider for Web3.js.
My MetaMask is connected to a private blockchain called node1
using Geth on localhost:8545
. In the meantime I have another Geth node called node2
.
At the beginning, node1
and node2
were not connected. I sent and mined a transaction to node1
to the contract at contractAddress
which would emit events and I indeed got console logs in the browser as a result of my subscription to 'logs'.
Then I let node2
mine more blocks than node1
and after that, I connected them. This will trigger node1
chain reorganization. After reorg, the reverted transaction was left in the txPool and I didn't mine any more blocks.
As is specified in web3.js documentation, I expected console.logļ¼"changed:", log)
to be executed but it didn't.
At the same time, I also used low-level Json-rpc method eth_getFilterChanges
and did get a log with "removed": true
field, which means the transaction was indeed reverted.
I think web3.js should have notice this and execute on('changed')
callback. But why does web3.js not work here? Since web3.js cannot subscribe logs directly using HTTP ethereum provider, and MetaMask uses HTTP connection to ethereum, does this problem have something to do with MetaMask?
BTW: I'm using web3.js v1.2.6
Best Answer
for me this did also not work and I do not know why, but I found the following solution using web3.
As web3 from Metamask will be deprecated I get web3 not from Metamask, but through:
web3 = new Web3(Web3.givenProvider);
then setting up the event listener somewhere else later on in the code:
web3.eth.Contract(TokenABI, TokenAddress);
try {
eventHandlerTransfer = await contract.events.Transfer({ fromBlock: 0 }, function (err, data) {
//INFO: your data will be accessable at e.g.
data.returnValues._from
if(err) {
console.log(err);
}
});
}catch (error) {
console.log(error);
}
This is written using "async function() {" style....
Hope this helps. Happy async coding...