xclud / web3dart

Ethereum library, written in Dart.
https://pub.dev/packages/web3dart
MIT License
170 stars 94 forks source link

Transaction seems not completed using Alchemy RPC. #76

Closed RicardoDVS closed 1 year ago

RicardoDVS commented 1 year ago

Hello, I’m kind of new in this blockchain matter, and I'm trying to use Alchemy node and their RPC API to perform some transactions in the blockchain using web3dart lib.

I'm using the web3dart lib v2.5.0 “todos” example and run it in a local Ganache setup and it works great. But when I change the client connection to my Alchemy RPC as follows:

image

When I try to add a new “todo task” the transaction seems to be completed but it gets stuck in a pending state forever and the new “todo task” is not added to the list.

NOTE: Contract is deployed to Polygon Mumbai correctly, I can perform transactions with Remix IDE without any issue to this contract at that testnet.

Here is some output I printed to see which methods are called from the RPC but I cant find the issue:

image

And here you can see the transaction stuck in a pending state:

image

Maybe i'm missing something in the client setup?.

I have been searching for a long time for a similar case but no luck, any help is welcome.

4xMafole commented 1 year ago

I have not tested it out but mostly is likely to be the gas price is low try to increase it. Hope should fix the bug.

4xMafole commented 1 year ago

I have not tested it out but mostly is likely to be the gas price is low try to increase it. Hope should fix the bug.

This didn't help at all, I am still facing a pending transaction and this is day 3. @RicardoDVS did you manage to solve the problem? If so please share.

RicardoDVS commented 1 year ago

@4xMafole Hi thanks for taking the time to check it, and no i haven't found a solution yet so i still have this issue. :/

4xMafole commented 1 year ago

@RicardoDVS hope you are doing well, so actually I think the issue is with the gas fees estimation. Trying to increase or decrease gas fees manually does not solve the issue. As I tried to play around seems the gas price estimations doesn't coincide with the market gas price that's why.

As you can observe on Alchemy mempool most of pending transactions are been dropped.

Let me dig into the package and I will keep you posted.

4xMafole commented 1 year ago

Hi, @RicardoDVS. I would love to see the transaction or how you send the transaction. On my side, I created a custom transaction and sent it and everything worked correctly after playing around with fetchChainIdFromNetworkId and chainId parameters on the Web3Client class and maxGasparameter on the Transactionclass. Example:

   //Creating a transaction
    final Transaction transaction = Transaction(
      ...
      maxGas: 7000000, //Set the gas fees around 6,000,000 to 8,000,000
    );

    //Getting transaction id
    final String transactionId = await web3.client.sendTransaction(
      web3.credentials,
      transaction,
      fetchChainIdFromNetworkId: false, //If true it will use chainId 1, set it to false to use you're network chainId value.
      chainId: 5, //Specify you're network's chain id here. This is goerli testnet chain id
    );

    return transactionId;

Could you give it a try and reach out for feedback on your end?

NB: For faster help and response share you're code where you sign and send the transactions.

RicardoDVS commented 1 year ago

Hello @4xMafole sorry for the delay, hope your doing well in those holidays, here is how i send the transaction originally:

  addTask(String taskNameData) async 
  {
    print(" [dbg] TodoListModel.addTask, $taskNameData ...");
    isLoading = true;
    notifyListeners();

    print(" [dbg] TodoListModel.addTask, sending transaction _createTask...");

    if (_credentials is CustomTransactionSender)
      print(" [dbg] TodoListModel.addTask, CUSTOM CREDENTIALS");
    else
      print(" [dbg] TodoListModel.addTask, NO CUSTOM CREDENTIALS");

    String txn = await _client.sendTransaction(
      _credentials,
      Transaction.callContract(
        contract: _contract,
        function: _createTask,
        parameters: [taskNameData],
        gasPrice: null,
        maxGas: null,
      ),
      chainId: null,
      fetchChainIdFromNetworkId: true,
    );

    print(" [dbg] TodoListModel.addTask, sent transaction: $txn");

    print(" [dbg] TodoListModel.addTask, calling getTodos...");

    await getTodos();
  }

and still not working...

and then i changed it to what you sugest:

  addTask(String taskNameData) async 
  {
    print(" [dbg] TodoListModel.addTask, $taskNameData ...");
    isLoading = true;
    notifyListeners();

    print(" [dbg] TodoListModel.addTask, sending transaction _createTask...");

    if (_credentials is CustomTransactionSender)
      print(" [dbg] TodoListModel.addTask, CUSTOM CREDENTIALS");
    else
      print(" [dbg] TodoListModel.addTask, NO CUSTOM CREDENTIALS");

    String txn = await _client.sendTransaction(
      _credentials,
      Transaction.callContract(
        contract: _contract,
        function: _createTask,
        parameters: [taskNameData],
        //gasPrice: null,
        maxGas: 7000000,
      ),
      chainId: 80001,//mumbai id
      fetchChainIdFromNetworkId: false,
    );

    print(" [dbg] TodoListModel.addTask, sent transaction: $txn");

    print(" [dbg] TodoListModel.addTask, calling getTodos...");

    await getTodos();
  }

  Future<void> init() async 
  {
    print(" [dbg] TodoListModel.init, starts...");

    httpClient = Client();

    print(" [dbg] TodoListModel.init, Using ALCHEMY Node on Polygon Mumbai Blockchain");
    _rpcUrl = "https://polygon-mumbai.g.alchemy.com/v2/[MY_API_KEY_IS_HERE]";
    _wsUrl = "wss://polygon-mumbai.g.alchemy.com/v2/[MY_API_KEY_IS_HERE]";
    _privateKey = "[MY_PROVATE_KEY_IS_HERE]";

    print(" [dbg] TodoListModel.init, Client initiated...");

    await getAbi();
    await getCredentials();
    await getDeployedContract();
  }

and it also stucks on pending status as you can see in the polygonscan pool: https://mumbai.polygonscan.com/tx/0x12a9625a51ae22d91ed34781e75592b1b7a20d8646f7387d4e4ea0e2345c0df2

tried maxGas set to: 6500000, 7000000, 8000000...

same stuck issue :/

but...

If i use the Goerli Network it works!!! :o

  addTask(String taskNameData) async 
  {
    print(" [dbg] TodoListModel.addTask, $taskNameData ...");
    isLoading = true;
    notifyListeners();

    print(" [dbg] TodoListModel.addTask, sending transaction _createTask...");

    if (_credentials is CustomTransactionSender)
      print(" [dbg] TodoListModel.addTask, CUSTOM CREDENTIALS");
    else
      print(" [dbg] TodoListModel.addTask, NO CUSTOM CREDENTIALS");

    String txn = await _client.sendTransaction(
      _credentials,
      Transaction.callContract(
        contract: _contract,
        function: _createTask,
        parameters: [taskNameData],
        //gasPrice: null,
        maxGas: 8000000,
      ),
      chainId: 5,
      fetchChainIdFromNetworkId: false,
    );

    print(" [dbg] TodoListModel.addTask, sent transaction: $txn");

    print(" [dbg] TodoListModel.addTask, calling getTodos...");

    await getTodos();
  }

  Future<void> init() async 
  {
    print(" [dbg] TodoListModel.init, starts...");

    httpClient = Client();

    print(" [dbg] TodoListModel.init, Using Node on Goerli Blockchain");
    _rpcUrl = "https://eth-goerli.g.alchemy.com/v2/[MY_GOERLI_API_KEY]";
    _wsUrl = "wss://eth-goerli.g.alchemy.com/v2/[MY_GOERLI_API_KEY]";
    _privateKey = "[MY_PRIVATE_KEY_HERE]";

    _client = Web3Client(_rpcUrl, httpClient, socketConnector: () 
    {
      print("    [dbg] TodoListModel.init, socketConnector...");
      IOWebSocketChannel socket = IOWebSocketChannel.connect(_wsUrl);
      return socket.cast<String>();
    });

    print(" [dbg] TodoListModel.init, Client initiated...");

    await getAbi();
    await getCredentials();
    await getDeployedContract();
  }
4xMafole commented 1 year ago

Hello, @RicardoDVS. As you guessed I was on holiday. Yer, I am back now let's get back to bug fixing.

Problem So before tackling the problem you must understand it and why it happens.

Eg: You always pay $3 for pizza and also you're willing to pay no more than $3.5. If the price of pizza goes beyond the limit price of $3.5, you are ready to wait for the price to drop down below or close to $3.5 hence pending/waiting. If you have no time then you need to increase your limit price to match the current pizza price. This scenario applies the same to this bug we are facing.

Solution Increase your gas maximum price.

Testable I tested the transaction signing using the following code, and everything worked properly. Here is the transaction used with the below code (https://mumbai.polygonscan.com/tx/0xa822cac0c4d99ece9a6f06f4e9481efa0fabee2e35b974a804546a8e0ae0c0f1)

 //Creating a transaction
   final Transaction transaction = Transaction(
     ...
     maxGas: 7000000, //Keep increasing the gas price if transaction is **pending**
   );

   //Getting transaction id
   final String transactionId = await web3.client.sendTransaction(
     web3.credentials,
     transaction,
     fetchChainIdFromNetworkId: false, //If true it will use chainId 1, set it to false to use you're network chainId value.
     chainId: 80001, //Specify you're network's chain id here. This is Mumbai polygon testnet chain id
   );

   return transactionId;

Suggestion: I think the gas price on the days you tested was aggressive on the polygon network.

RicardoDVS commented 1 year ago

Hello @4xMafole I keep trying increasing the maxGas but it still doesnt work, i dont know if im allowed to upload some of my code files here in a zip file so you can helpme to spot the issue or if there is another way i can share you my code.

Thanks for the help.

4xMafole commented 1 year ago

Create a repository on your account and share with me a link.

Upload your code on your github account.

RicardoDVS commented 1 year ago

Hello @4xMafole here are my code files https://github.com/RicardoDVS/web3-todo-list/tree/main/lib

4xMafole commented 1 year ago

Is it private? Because, I can't access it.

RicardoDVS commented 1 year ago

already sent you the invite.

RicardoDVS commented 1 year ago

Finally after some researching, I found the problem was my wallet, I just created a new wallet and tried my code at it was and it worked without any issues, thanks to @4xMafole for bringing me up with some useful test samples and bringing ideas on solving this issue.