Skip to main content
This feature is experimental and may change as we iterate.
Privy provides a useAddFunds hook in @privy-io/react-auth that opens a unified funding flow in the Privy modal. Your app can use this hook to let authenticated users fund a destination wallet with fiat, crypto, or both. When both methods are configured, Privy shows a method picker before starting the selected flow. When only one method is configured, Privy starts that flow directly.

Prerequisites

Enable the funding methods your app supports on the Account Funding page in the Privy Dashboard. See the configuration guide for details.

Access the hook

Import and initialize useAddFunds:
import {useAddFunds} from '@privy-io/react-auth';

const {addFunds} = useAddFunds();

Start a unified funding flow

Call addFunds with a destination wallet and at least one funding method config.
await addFunds({
  destination: {
    address: '<wallet_address>',
    chain: 'eip155:8453',
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
  },
  fiat: {
    source: {
      assets: ['usd', 'eur'],
      defaultAsset: 'usd'
    },
    environment: 'production',
    defaultAmount: '50'
  },
  crypto: {}
});
destination.chain accepts a CAIP-2 identifier (for example, eip155:8453 for Base or solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp for Solana mainnet). destination.asset is the token address on that destination chain.

Parameters

addFunds accepts an object with the following fields:
ParameterTypeDescription
destination.addressstringRequired. Wallet address to receive funds.
destination.chain`${string}:${string}`Required. Destination chain in CAIP-2 format.
destination.assetstringRequired. Token address on the destination chain (for example, Base USDC: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913).
fiatAddFundsFiatOptionsRequired unless crypto is provided. Enables fiat funding with the useFiatOnramp flow.
fiat.source.assetsSupportedFiatCurrency[]Optional. The list of fiat source currencies your app allows. Defaults to all supported currencies. When provided, must be non-empty.
fiat.source.defaultAssetSupportedFiatCurrencyOptional. The source currency selected when the flow opens. Falls back to the locale currency, then to the first item in fiat.source.assets.
fiat.environment'sandbox' | 'production'Optional. Onramp environment for provider APIs.
fiat.defaultAmountstringOptional. Initial fiat amount displayed in the amount step.
cryptoAddFundsCryptoOptionsRequired unless fiat is provided. Enables crypto funding with the useDepositAddress flow.
crypto.refundAddressstringOptional. Refund address used if a crypto deposit cannot be completed.
crypto.slippageBpsnumberOptional. Maximum slippage for the crypto deposit route, in basis points.
At least one of fiat or crypto must be provided. Provide both to show the method picker.

Return value

addFunds returns a Promise with one of the following results:
ResultMeaning
{method: 'fiat', status: 'submitted'}The user completed the provider flow, then exited before final confirmation finished in Privy.
{method: 'fiat', status: 'confirmed'}The fiat flow reached provider confirmation, and the user completed the success step.
{method: 'crypto', status: 'completed'}The crypto deposit flow completed successfully.

Error handling

addFunds rejects on invalid configuration or incomplete flows. Common error cases include:
  • destination.address, destination.chain, or destination.asset is missing
  • neither fiat nor crypto is provided
  • fiat.source.assets is empty
  • the user is not authenticated
  • another add funds flow is already in progress
  • the user cancels the flow
  • provider session, quote, or deposit address requests fail
Your app should wrap calls in try/catch and show clear UI feedback.

Complete example

import {useState} from 'react';
import {useAddFunds} from '@privy-io/react-auth';

export const AddFundsButton = ({address}: {address: string}) => {
  const {addFunds} = useAddFunds();
  const [isLoading, setIsLoading] = useState(false);

  const onAddFunds = async () => {
    setIsLoading(true);

    try {
      const result = await addFunds({
        destination: {
          address,
          chain: 'eip155:8453',
          asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
        },
        fiat: {
          source: {
            assets: ['usd', 'eur', 'gbp'],
            defaultAsset: 'usd'
          },
          environment: 'production',
          defaultAmount: '50'
        },
        crypto: {}
      });

      if (result.method === 'fiat') {
        // Handle submitted or confirmed fiat purchases.
      }

      if (result.method === 'crypto') {
        // Handle completed crypto deposits.
      }
    } catch (error) {
      // Show retry UI or an error banner.
      console.error(error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <button type="button" onClick={onAddFunds} disabled={isLoading}>
      {isLoading ? 'Starting funding…' : 'Add funds'}
    </button>
  );
};

Fiat-to-crypto onramps

Fund wallets with fiat via card, Apple Pay, or Google Pay.

Crypto deposit addresses

Fund wallets by letting users transfer crypto from another wallet.