• React
  • Prepare Hooks

Prepare Hooks

In previous versions of wagmi, "transactional" hooks such as useSendTransaction and useContractWrite performed potentially long-running asynchronous work. These hooks internally invoke the ethers signer.sendTransaction function that fetches the gas estimate & block number, and resolves an ENS name (if needed) before the transaction gets sent. On a slow network, these asynchronous tasks can take a while.

Performing asynchronous tasks in an event handler (like a button) or in an event that wasn't initiated by the user (like a page load) is not ideal as it can lead to a variety of connected user-experience (UX) related pitfalls (listed below).

Prepare Hooks allow you to eagerly perform this asynchronous work beforehand & generate the parameters required for their paired hook (e.g. usePrepareSendTransaction prepares a request for useSendTransaction).

wagmi currently has the following Prepare Hooks:

UX Pitfalls without Prepare Hooks

You may have noticed one of the following pitfalls when using "transactional" hooks without performing the asynchronous work beforehand.

Slow TTOW (Time To Open Wallet)

Performing long-running async work in between a user interaction (i.e. click handler) and opening the wallet can lead to a slow TTOW (Time To Open Wallet).

Under slow network conditions, it may confuse the end-user as to why the wallet is taking a while to open.

The video below shows the difference between a slow TTOW and a fast TTOW.

iOS App Link Constraints

When using WalletConnect on iOS and triggering a wallet interaction (e.g. when sending a transaction or signing a message), you may experience issues where the native app is not opened as expected and a browser navigation occurs instead (as seen in the above video). For some wallets (e.g. Rainbow) this will present a fallback website, while other wallets (e.g. MetaMask) will redirect to the App Store.

This issue occurs because app links on iOS will only open the native app when the following rules are followed:

  • The wallet interaction must be triggered by a user-initiated event, e.g. in a click handler rather than on page load or in an asynchronous callback.
  • The wallet interaction must be triggered as soon as possible within the event handler. Any preceding asynchronous work (e.g. estimating gas, resolving an ENS name, fetching a nonce) should have already completed before the event handler fires.

No upfront validation

When using "transactional" hooks such as useContractWrite & useSendTransaction, the user will only get feedback on the status of the transaction once they have invoked the click handler.

There are some cases where we can perform upfront validation on a contract or transaction request before the user interacts with the click handler (such as checking if we can still mint on a contract).

See the comparison below for when a user tries to mint a sold out NFT.

Validating after interactionValidating before interaction

By using a Prepare Hook, we can perform this eager validation before the click handler is invoked.

import * as React from 'react'
import { usePrepareContractWrite, useContractWrite } from 'wagmi'
 
export function MintNFT() {
  const { config, error, isError } = usePrepareContractWrite({
    address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
    abi: [
      {
        name: 'mint',
        type: 'function',
        stateMutability: 'nonpayable',
        inputs: [],
        outputs: [],
      },
    ],
    functionName: 'mint',
  })
  const { data, write } = useContractWrite(config)
 
  return (
    <div>
      <button disabled={!write} onClick={() => write()}>
        Mint
      </button>
      {isError && <div>Error: {error.message}</div>}
    </div>
  )
}