Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors not caught in 4.x #6500

Closed
trystendsmyth opened this issue Oct 11, 2023 · 9 comments · Fixed by #6623
Closed

Errors not caught in 4.x #6500

trystendsmyth opened this issue Oct 11, 2023 · 9 comments · Fixed by #6623
Assignees
Labels
4.x 4.0 related Bug Addressing a bug Estimate Investigate

Comments

@trystendsmyth
Copy link

trystendsmyth commented Oct 11, 2023

The following test code was written to demonstrate the observed issue.

import Web3 from "web3";

const web3 = new Web3(<RPCPROVIDER_HERE>);
const contract = new web3.eth.Contract(<ABI_HERE>, <ADDRESS_HERE>);
const accounts = await web3.eth.requestAccounts();
const fee = await contract.methods.fee().call();

try {
  await contract.methods
    .put([0], [0], [0xf])
    .send({
      from: accounts[0],
      value: fee
    })
    .on("transactionHash", (hash) => {
      console.log("Transaction hash:", hash);
    })
    .on("error", (err) => {
      console.log("on error:", err);
    })
    .then((receipt) => {
      console.log("Transaction receipt:", receipt);
    })
    .catch((error) => {
      console.log("Transaction ERROR:");
      console.error(error);
    });
} catch (e) {
  console.log("If nothing else, his should be invoked.");
  console.error(e);
}
});

Expected behavior

In 1.x OR 4.x versions of Web3.js, errors should be caught by either the on('error') or the catch.

Actual behavior

In 1.x, when there is (for instance) an "insufficient funds" error, it is caught by the on('error') handler.
In 4.x, errors are not caught by the handler or catch, and cause the application to crash.

Steps to reproduce the behavior

  1. Run code as in the example code above with Web3.js 4.1.2
  2. Force an error by trying to send unavailable funds
  3. Observe that error is not caught

Environment

Node 18
Web3.js 4.1.2
MacOS
Chrome

@Muhammad-Altabba
Copy link
Contributor

Hello @trystendsmyth ,
Thank you for your question.

Actually, contract.methods.put(...).send(...) returns Web3PromiEvent object. And here is how you can register to its events and await for it:

  const methodPutPromiEvent = contract.methods
    .put([0], [0], [0xf])
    .send({
      from: accounts[0],
      value: fee
    });

    methodPutPromiEvent.on("transactionHash", (hash) => {
      console.log("Transaction hash:", hash);
    }).on(...)...

   await methodPutPromiEvent;

Please, close this issue if this resolved your problem.

@trystendsmyth
Copy link
Author

@Muhammad-Altabba in my example, I'm am already awaiting the promise and registering events to it as you're suggesting. However, I tried your approach of awaiting the promise after setting registering events, but unfortunately that didn't make a difference. Also, as I mentioned, my example works on 1.x - is there a substantial way that this promise event handling changed?

@jdevcs jdevcs added 4.x 4.0 related Investigate labels Oct 16, 2023
@am-hernandez
Copy link

Hi @jdevcs ,

I am having the exact same experience as @trystendsmyth . How should errors be handled in this case with version 4+?

I have a codesandbox demo where this behavior is replicated. Note that the sending event is triggered and logs to console, but the error event is skipped.

After making the call I see polling is happening, and after a while the catch is reached and the error is logged from there:

TransactionBlockTimeoutError: Transaction started at 5947380 but was not mined within 50 blocks. Please make sure your transaction was properly sent and there no pervious pending transaction for the same account. However, be aware that it might still be mined!
Transaction Hash: not available

To recap, the error Error forwarded from node: insufficient funds for gas * price + value is logged to console right away as an uncaught exception. This occurs after the sending event. After some time the catch error is also logged. Is this the expected behavior?

Thank you!

@jdevcs
Copy link
Contributor

jdevcs commented Oct 30, 2023

@am-hernandez Thanks, we will fix it. cc: @mconnelly8

@am-hernandez
Copy link

Hi @jdevcs ,

Would you please let us know if there is an ETA for this resolution?

Thank you.

@jdevcs
Copy link
Contributor

jdevcs commented Nov 20, 2023

Hi @am-hernandez its on top of list for next sprint starting tomorrow. cc: @mconnelly8

@mconnelly8 mconnelly8 added Bug Addressing a bug Estimate labels Nov 20, 2023
@avkos avkos self-assigned this Nov 22, 2023
@avkos avkos mentioned this issue Nov 24, 2023
17 tasks
@avkos
Copy link
Contributor

avkos commented Nov 24, 2023

I investigated it didn't fully reproduce a problem. I've found and fix a problem with catching TransactionPollingTimeoutError.

@am-hernandez - your code doesn't have try-catch structure - that's why it fails
@trystendsmyth - your code works and error catches in on error and in try-catch

Also, I've added tests to check some cases that you described:

  1. send tokens from the account that does not have ether
  2. send tokens from the account that does not have ether
  3. send ether from the account that does not have ether
  4. send and wait timeout

@am-hernandez ,@trystendsmyth Please check these code examples and if you still have a problem please give me steps to reproduce.

Thank you, guys, again for your contribution

@avkos
Copy link
Contributor

avkos commented Nov 24, 2023

@trystendsmyth I've checked your code again and run it locally with web3js provider

import {Web3} from 'web3'

const rpcUrl = "https://mainnet.base.org/";
const web3 = new Web3(rpcUrl);

const abi = [
    {
        inputs: [],
        name: "fee",
        outputs: [
            {
                internalType: "uint256",
                name: "",
                type: "uint256",
            },
        ],
        stateMutability: "view",
        type: "function",
    },
    {
        inputs: [
            {
                internalType: "uint8[]",
                name: "tileIndexes",
                type: "uint8[]",
            },
            {
                internalType: "uint8[]",
                name: "tileBufferIndexes",
                type: "uint8[]",
            },
            {
                internalType: "uint8[]",
                name: "values",
                type: "uint8[]",
            },
        ],
        name: "put",
        outputs: [],
        stateMutability: "payable",
        type: "function",
    },
];

const contract = new web3.eth.Contract(
    abi,
    "0x44fE343FCE6458da253e700ceE0a55449aEa8E18",
);

const test = async () => {
    const account = await web3.eth.accounts.create();
    const fee = await contract.methods.fee().call();
    console.log(`Fetched fee ${fee}`);

    // @ts-ignore
    const web3PromiEvent = contract.methods.put([0], [0], [0xf]).send({
        from: account.address,
        // @ts-ignore
        value: fee,
    });

    web3PromiEvent
        .on("sending", (sending) => {
            console.log("sending:", sending);
        })
        .on("sent", (sent) => {
            console.log("sending:", sent);
        })
        .on("transactionHash", (hash) => {
            console.log("Transaction hash:", hash);
        })
        .on("error", (err) => {
            console.log("on error:", err);
        }).then((receipt) => {
        console.log("Transaction receipt:", receipt);
    }).catch((error) => {
        console.log("Transaction ERROR:");
        console.error(error);
    })
    
}

test()

and it works. So looks like the problem inside magic.rpcProvider

@avkos avkos closed this as completed Nov 28, 2023
@avkos avkos reopened this Nov 28, 2023
@trystendsmyth
Copy link
Author

@trystendsmyth I've checked your code again and run it locally with web3js provider
and it works. So looks like the problem inside magic.rpcProvider

@avkos in my example, I'm not referencing any single provider. However even if I was, I'm not sure I see how that would prevent error catching in contract.methods? I updated to 4.2.2, which is your latest version, and I'm still not getting the error catching you're verifying. Is there a different version you would suggest I test against? Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x 4.0 related Bug Addressing a bug Estimate Investigate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants