Skip to content

Prompting users to fund wallets

With funding methods enabled for your app, Privy will prompt users to fund their wallets at two points in their experience:

  1. Manually, when you call Privy's fundWallet method documented below
  2. Automatically, when the user attempts to send a transaction but has insufficient funds

You can also configure the chain, asset, and amount that users should fund their wallets with directly in code.

Manually invoking funding

Once you've enabled a set of funding methods for your app, to invoke the funding flow, use the useFundWallet hook from the Privy as follows:

tsx
import {useFundWallet} from '@privy-io/react-auth';
...
const {fundWallet} = useFundWallet();
await fundWallet('your-wallet-address-here');

Once invoked, the fundWallet method will open a modal that contains a list of funding options the user can take. If only one funding method was enabled for your app, Privy will navigate the user directly to that specific flow.

You can pass additional configurations to the funding flow in the second, optional parameter to fundWallet.

WARNING

Purchases with third-party providers are not always instantaneous, and there may be some time before the user completes their purchase and the funds are available in their wallet.

Automatically invoking funding

With funding methods enabled for your app, if a user attempts to send a transaction but does not have sufficient funds to do so, Privy will show them an "Add funds" button in the transaction modal that enables them to invoke funding flows.

Setting a funding amount in code

Optionally, you can pass in a chain, funding amount, and funding asset to fundWallet to override your Dashboard configuration.

To do so, as the second, optional parameter to fundWallet, pass an object with the following fields:

ParameterTypeDescription
chainChainOptional. A viem/chains object for the network on which users should fund their accounts. Defaults to the network you configured in the Privy Dashboard.
asset'native-currency' | 'USDC' | {erc20: string}Optional. The asset you'd like the user to fund their accounts with. Set 'native-currency' to fund with the chain's native currency (e.g. ETH), 'USDC' to fund with USDC, or a token address in the erc20 field to fund with an arbitrary ERC20. Defaults to 'native-currency'.
amountstringRequired if asset is set, optional otherwise. The amount of the asset to fund as a decimal string. Defaults to the amount you configured in the Privy Dashboard.

As examples, you can configure the chain, asset, and amount to fund like below:

Fund with ETH

tsx
// Replace this with your desired network
import {base} from 'viem/chains'
...
// `fundWallet` from the useFundWallet() hook
fundWallet('your-wallet-address-here', {
  chain: base,
  amount: 0.01 // Since no `asset` is set, defaults to 'native-currency' (ETH)
})

Fund with USDC

tsx
// Replace this with your desired network
import {base} from 'viem/chains'
...
// `fundWallet` from the useFundWallet() hook
fundWallet('your-wallet-address-here', {
  chain: base,
  amount: 15,
  asset: 'USDC'
})

Fund with arbitrary ERC20

tsx
// Replace this with your desired network
import {base} from 'viem/chains'
...
// `fundWallet` from the useFundWallet() hook
fundWallet('your-wallet-address-here', {
  chain: base,
  amount: 30,
  asset: {erc20: '0x0578d8A44db98B23BF096A382e016e29a5Ce0ffe'}
})

Callbacks

To understand when users have gone through a funding flow, you can use the onUserExited callback that can be provided to the useFundWallet hook. The address, chain, fundingMethod, and balance (value of the wallet being funded) are available via the callback, which fires when users exit the funding flow.

For example, if you want to prompt a user to fund their wallet upon logging in for the first time as a part of your onboarding flow:

tsx
const {fundWallet} = useFundWallet({
  onUserExited({balance}) {
    if (balance < 1000n) {
      router.push('/insufficient-funds');
    } else {
      router.push('/dashboard');
    }
  },
});

const {login} = useLogin({
  onComplete(user, isNewUser) {
    if (isNewUser && user.wallet?.walletClientType === 'privy') {
      fundWallet(user.wallet.address);
    } else {
      router.push('/dashboard');
    }
  },
});