`.get()` method calls `dryRun` and `estimateGasPrice`

Version used:

  • @fuel-ts/contract: "^0.94.6"
  • @fuels/connectors": "^0.27.1"
  • @fuels/react": "^0.27.1"
  • fuels: "^0.94.6"

I generated the smart contract types using fuels typegen.

Smart contract reads being executed as follow:

 const marketContract = new Market(
    marketAddress,
    provider
  );

  const { value: marketConfiguration } = await marketContract.functions
    .get_market_configuration()
    .get();

The .get() method executes dryRun and estimateGasPrice as seen in the following screenshot:

This, with the additional problem of requests not being deduplicated for getNodeInfo and getChainInfo, causes a large number of unnecessary requests being made. The initial load of our dapp does 49 requests to the testnet node. We verified that there are not duplicate requests being fired from our own hooks, because of re-renders, etc.

1 Like

Hey @martines3000 :wave:

Don’t suppose you have a minimal reproduction of this issue?

No, the repository is still private, but I can add you if you share your GitHub username.

Github: petertonysmith94

@martines3000 I’m happy to take a look at this issue and see if I can help. Could you add me as well, please?

Github: Torres-ssf

1 Like

@martines3000 Thanks for adding me to the project! I have a few initial observations:

.get() Method

The .get() method should perform a dryRun. This simulates the contract call, allowing us to retrieve the expected response without incurring the cost of a real transaction.

getNodeInfo and getChainInfo

The getNodeInfo and getChainInfo methods of the Provider class are called each time a new Provider instance is created with await Provider.create(url).

So this means that each await Provider.create(url) will trigger these 2 calls.

However, the results are cached within the instance, so there’s no need to fetch this data again for subsequent calls. You can retrieve the cached data using provider.getChain() and provider.getNode().

@martines3000 After accessing your application, I noticed that, on the main page (Dashboard), GraphQL requests are being triggered repeatedly every few seconds, even without any user interaction or a connected wallet.

Specifically, the dryRun (which also triggers estimateGasPrice as a side effect) and balance queries are being sent continuously.

Is there a particular reason why these requests are being made even when there is no activity on the UI?

We had all queries set to refetch on a 10s interval. I changed this couple of hours ago and optimized it to only do this when refetchOnWindowFocus happens and couple of other scenarios.

Is it expected that the .get() requests execute estimateGasPrice and dryRun ?

Here is a partial example of the network tab when I initially load the dapp and connect the wallet. As you can see, each of these methods is calling a read function, but 2 requests are made for each one (ignore the useTotalCollateral, as we do 3 calls here and will be changed to 1 the next time we redeploy the contract).

We also have these requests:


As it can be seen they happen inside the Connectors :sweat_smile:

Is it expected that the .get() requests execute estimateGasPrice and dryRun ?

Yes, this is expected. The .get() method internally performs a dryRun, which allows us to retrieve the contract call response without executing a real transaction and incurring costs. The estimateGasPrice step is necessary because, even during a dryRun, the gas and fees must be accurately estimated to ensure proper validation of the call.

You can use the multiCall feature to execute multiple contract .get() calls within a single dryRun operation:

    // the chain call can be originated for any of the used contracts
    const { value: results } = await contract1
      .multiCall([
        contract1.functions.foo(1336), 
        contract2.functions.bar(1337),
        contract3.functions.baz(1338), 
        contract1.functions.foo_2(1336), 
    ]).get();

The value property will be an array containing the returned values in the same order as the calls were made.

For example, the result of the first contract function (contract1.functions.foo(1336)) will be at index 0, the second function (contract2.functions.bar(1337)) at index 1, and so on.

We also have these requests:

Are those requests getNodeInfo and getChainInfo? Are they happening for every connector instantiation?

1 Like

Thanks for the information.

Using multiCall would require a large refactor and it is also very inconvenient, as we currently have 1 hook for 1 contract call. I appreciate the idea :+1: .

No, the getNodeInfo and getChainInfo only happen for WalletConnect and Solana connectors. WalletConnect one happens multiple times, as seen in the screenshot.

I will also mark you last answer as the solution as it answers my question :100: