0

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

0

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

| improve this answer | |
  • Thanks for your reply. But Web3.givenProvider still comes from Metamask in my browser. I tried with Web3.givenProvider and it didn't help. I still connot get on("changed") response when chain reorg happens. – Aaron Feb 20 at 3:08
  • Hi Aaron, did you try using the "web3.min.js" inside the index.html ? If not, try this and then web3 should NOT come through Metamask... Best regards! – Tabaluga Feb 29 at 3:30
  • Thanks for advice. But in my case, the web3 needs to come through Metamask to sign transactions. The problem indeed does not exist with ethereum websocket provider directed connected to ethereum node (e.g. Geth). But I need to use Metamask in my DApp. – Aaron Mar 3 at 11:38
  • Hi Aaron, Metamask is stopping the injection of web3 by Q1 2020. see here . I am using Metamask and web3js from web3.min.js. Maybe I am not getting your point, but I get the Metamask confirmations whenever I have to sign e.g. approve or transferfrom etc... – Tabaluga Mar 4 at 12:56
  • Yes I know Metamask is stopping the injection of web3. I didn't use the web3 injected by Metamask. I just used Metamask ethereum provider in official web3.js. Metamask confirmations work as normal, but removed events don't. Thanks for attentation. – Aaron Mar 5 at 3:00
0

I use "contract.events.Transfer({ fromBlock: 0 }, function (err, data) {"
instead of "web3.eth.subscribe('logs', {" ...
in order to be informed about all different events that happen (in this case the Transfer event, but you can also add other events too.)
If there is an error in the transfer for e.g. I receive the error in the catch(error) section.
the "contract is from
contract = new web3.eth.Contract(TokenABI, TokenAddress);
does this work for you? Best regards

| improve this answer | |
  • Sorry, I tried and it didn't work. The callback for new events is working but the callback for removed events is not working. – Aaron Feb 24 at 6:18
  • Hi Aaron, not sure what you mean with "removed events". I guess you mean the events prior to the last/new event right? The {fromBlock: 0} will give you all events since the beginning... If you change the line "data.returnValues._from" to console.log(data.returnValues._from); you will see all your previous events too in the browser console.. I use an array (using push) to store all of these events for later usage.. I hope this was your issue :-) – Tabaluga Feb 28 at 23:20
  • Thanks. The "removed events" I mean is the smart contract events that has been removed due to blockchain reorganization. See decriptions here. The event with removed: true field is what I meant. I have already checked with web3.js developers and that seems to be a implementation issue in Metamask ethereum provider. I will come back to this question after I confirm the issue with Metamask developers. – Aaron Mar 3 at 11:35
  • Hi Aaron! thanks for the info about the removed events. I wasn´t aware of these. Each day I learn something new. That´s great. – Tabaluga Mar 4 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.