> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposit modal

> Let users fund wallets with fiat or crypto from a Privy modal in React or React Native

export const ChainIdentifier = () => <>
    Chain alias or CAIP-2 identifier, such as <code>base</code> or <code>eip155:8453</code>.
  </>;

export const AssetIdentifier = () => <>
    Asset alias or token contract address, such as <code>usdc</code> or{' '}
    <code>0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913</code>.
  </>;

<View title="React" icon="react">
  Privy provides a `useDepositFunds` hook in `@privy-io/react-auth` that opens a funding modal.

  Your app can use this hook to let authenticated users fund a destination wallet with fiat, crypto, or both. A crypto-only call opens the crypto deposit flow directly. A call that includes fiat shows a method picker first.

  ## Prerequisites

  For fiat, enable card and bank funding methods on the [Account Funding](https://dashboard.privy.io/apps?page=funding) page. See the [deposit configuration guide](/financial-flows/deposits/configuration).

  For crypto, enable swaps and app-pays gas sponsorship as described in [crypto deposit setup](/wallets/funding/crypto-deposits/setup). Crypto deposits require a Privy wallet. The hook builds the [create-deposit-account](/wallets/funding/crypto-deposits/create-deposit-account) request and signs it with the user's signer.

  ## Access the hook

  Import and initialize `useDepositFunds`:

  ```tsx {skip-check} theme={"system"}
  import {useDepositFunds} from '@privy-io/react-auth';

  const {depositFunds} = useDepositFunds();
  ```

  ## Start a deposit flow

  Call `depositFunds` with a destination and at least one funding method.

  ```tsx {skip-check} theme={"system"}
  await depositFunds({
    destination: {
      asset: 'pathusd',
      chain: 'tempo'
    },
    crypto: {
      source: {
        mode: 'all'
      },
      depositAddressStrategy: 'prefer_destination'
    }
  });
  ```

  The crypto-only call opens the crypto deposit modal. The user picks a source token and network. Privy then creates a [deposit account](/wallets/funding/crypto-deposits/create-deposit-account) and shows the address with an indicative quote. This example prefers reusing the destination wallet address where eligible; omit `depositAddressStrategy` to use a dedicated deposit address.

  <Note>
    `destination.chain` and `destination.asset` accept aliases or raw identifiers. Omit
    `destination.wallet` to use the user's first embedded wallet on that chain.
  </Note>

  Pass both `fiat` and `crypto` to show a method picker:

  ```tsx {skip-check} theme={"system"}
  await depositFunds({
    destination: {
      asset: 'usdc',
      chain: 'tempo'
    },
    fiat: {
      source: {
        assets: ['usd', 'eur'],
        defaultAsset: 'usd'
      },
      environment: 'production',
      defaultAmount: '50'
    },
    crypto: {
      source: {
        mode: 'all'
      }
    }
  });
  ```

  ## Parameters

  `depositFunds` accepts an object with the following fields:

  <ParamField body="destination" type="object" required>
    Wallet and asset that receive the funds.

    <Expandable title="properties" defaultOpen>
      <ParamField body="destination.asset" type="string" required>
        <AssetIdentifier />
      </ParamField>

      <ParamField body="destination.chain" type="string" required>
        <ChainIdentifier /> Must match the destination wallet's `chain_type` for crypto deposits.
      </ParamField>

      <ParamField body="destination.wallet" type="string">
        Privy wallet ID or linked wallet address. When omitted, Privy uses the user's first embedded
        wallet on `destination.chain`. Crypto deposits require a Privy wallet. Fiat needs a resolvable
        address.
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField body="crypto" type="object">
    Enables the crypto deposit flow. Required unless `fiat` is provided. Pass `{source: {mode:
          'all'}}` to accept every supported source.

    <Expandable title="properties" defaultOpen>
      <ParamField body="crypto.source" type="object">
        Assets the modal lets the user send. Defaults to `{mode: 'all'}`.

        <Expandable title="properties" defaultOpen>
          <ParamField body="crypto.source.mode" type="'all' | 'include' | 'exclude'" required>
            `include` accepts only the listed assets. `exclude` accepts all except the listed assets.
            `all` accepts every supported source.
          </ParamField>

          <ParamField body="crypto.source.values" type="object[]">
            Asset specs for `include` and `exclude`. Omit when `mode` is `all`.

            <Expandable title="properties" defaultOpen>
              <ParamField body="crypto.source.values.asset" type="string">
                <AssetIdentifier />
              </ParamField>

              <ParamField body="crypto.source.values.chain" type="string">
                <ChainIdentifier /> Omit to match every supported chain for that asset.
              </ParamField>
            </Expandable>
          </ParamField>
        </Expandable>
      </ParamField>

      <ParamField body="crypto.slippageBps" type="number">
        Maximum slippage tolerance for the deposit route, in basis points. If omitted, Privy uses the
        default for the route.
      </ParamField>

      <ParamField body="crypto.depositAddressStrategy" type="'dedicated' | 'prefer_destination' | 'require_destination'">
        How Privy chooses a crypto deposit address. Defaults to `dedicated`. Use `prefer_destination` to
        reuse an eligible destination wallet address for its chain family, falling back to a dedicated
        address otherwise. Use `require_destination` to fail instead of falling back for that family.
        Reusing the destination replaces all automations attached to that wallet.
        See [deposit address behavior](/wallets/funding/crypto-deposits/create-deposit-account#deposit-address-behavior)
        for eligibility and automation attachment effects.
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField body="fiat" type="object">
    Enables fiat funding with the card and bank onramp flow. Required unless `crypto` is provided.

    <Expandable title="properties" defaultOpen>
      <ParamField body="fiat.source.assets" type="SupportedFiatCurrency[]">
        Fiat source currencies your app allows. Defaults to all [supported
        currencies](#supported-fiat-currencies). When provided, must be non-empty.
      </ParamField>

      <ParamField body="fiat.source.defaultAsset" type="SupportedFiatCurrency">
        Source currency selected when the flow opens. Falls back to the locale currency, then to the
        first item in `fiat.source.assets`.
      </ParamField>

      <ParamField body="fiat.environment" type="'sandbox' | 'production'">
        Onramp environment for provider APIs.
      </ParamField>

      <ParamField body="fiat.defaultAmount" type="string">
        Initial fiat amount displayed in the amount step.
      </ParamField>
    </Expandable>
  </ParamField>

  At least one of `fiat` or `crypto` must be provided.

  ## Supported fiat currencies

  Once enabled in the Privy Dashboard, fiat onramps support USD, EUR, AUD, and BRL through Stripe and MoonPay. To unlock the full list of 50+ currencies below, open the [Funding page](https://dashboard.privy.io/apps?page=funding), click **Configure** on Meld, and complete its KYB. Meld adds card, bank transfer, and local payment coverage across 100+ countries.

  `SupportedFiatCurrency` accepts any of the following lowercase ISO 4217 codes.

  <Accordion title="Full list of supported currencies">
    | Code | Currency |
    | - | - |
    | `usd` | US Dollar |
    | `eur` | Euro |
    | `gbp` | British Pound |
    | `mxn` | Mexican Peso |
    | `brl` | Brazilian Real |
    | `cny` | Chinese Yuan |
    | `jpy` | Japanese Yen |
    | `inr` | Indian Rupee |
    | `cad` | Canadian Dollar |
    | `krw` | South Korean Won |
    | `aud` | Australian Dollar |
    | `idr` | Indonesian Rupiah |
    | `sar` | Saudi Riyal |
    | `try` | Turkish Lira |
    | `chf` | Swiss Franc |
    | `twd` | New Taiwan Dollar |
    | `sek` | Swedish Krona |
    | `ngn` | Nigerian Naira |
    | `pln` | Polish Zloty |
    | `ars` | Argentine Peso |
    | `aed` | UAE Dirham |
    | `thb` | Thai Baht |
    | `zar` | South African Rand |
    | `dkk` | Danish Krone |
    | `egp` | Egyptian Pound |
    | `myr` | Malaysian Ringgit |
    | `sgd` | Singapore Dollar |
    | `cop` | Colombian Peso |
    | `php` | Philippine Peso |
    | `clp` | Chilean Peso |
    | `bdt` | Bangladeshi Taka |
    | `vnd` | Vietnamese Dong |
    | `czk` | Czech Koruna |
    | `ils` | Israeli Shekel |
    | `hkd` | Hong Kong Dollar |
    | `nzd` | New Zealand Dollar |
    | `pkr` | Pakistani Rupee |
    | `ron` | Romanian Leu |
    | `kzt` | Kazakhstani Tenge |
    | `nok` | Norwegian Krone |
    | `huf` | Hungarian Forint |
    | `uah` | Ukrainian Hryvnia |
    | `kwd` | Kuwaiti Dinar |
    | `qar` | Qatari Riyal |
    | `etb` | Ethiopian Birr |
    | `mad` | Moroccan Dirham |
    | `bgn` | Bulgarian Lev |
    | `kes` | Kenyan Shilling |
    | `npr` | Nepalese Rupee |
  </Accordion>

  <Note>
    Reach out to [sales@privy.io](mailto:sales@privy.io) with any questions about pricing or
    additional geographic coverage.
  </Note>

  ## Return value

  `depositFunds` returns a Promise with one of the following results:

  | Result | Meaning |
  | - | - |
  | `{method: 'fiat', status: 'submitted'}` | The user completed the provider flow, then exited before Privy finished confirmation. |
  | `{method: 'fiat', status: 'confirmed'}` | The fiat flow reached provider confirmation, and the user completed the success step. |
  | `{method: 'crypto', status: 'address_shown'}` | The user viewed the crypto deposit address and closed the modal. |
  | `{method: 'crypto', status: 'completed'}` | Privy detected the crypto deposit and finished the flow. |

  ## Error handling

  `depositFunds` rejects on invalid configuration or incomplete flows. Common error cases include:

  * the call omits `destination.chain` or `destination.asset`
  * the call omits both `fiat` and `crypto`
  * the call sends an empty `fiat.source.assets` list
  * the user has no authenticated session
  * `destination.wallet` is not a Privy wallet on a crypto call
  * another funding flow is already in progress
  * the user cancels the flow
  * swaps or app-pays gas sponsorship are not enabled
  * no source tokens match `crypto.source`
  * `crypto.depositAddressStrategy` is `require_destination` and the destination wallet was exported
  * provider session, quote, or deposit account requests fail

  Your app should wrap calls in `try/catch` and show clear UI feedback.

  ## Complete example

  ```tsx {skip-check} theme={"system"}
  import {useState} from 'react';
  import {useDepositFunds} from '@privy-io/react-auth';

  export const DepositFundsButton = ({walletId}: {walletId: string}) => {
    const {depositFunds} = useDepositFunds();
    const [isLoading, setIsLoading] = useState(false);

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

      try {
        const result = await depositFunds({
          destination: {
            wallet: walletId,
            asset: 'usdc',
            chain: 'tempo'
          },
          fiat: {
            source: {
              assets: ['usd', 'eur', 'gbp'],
              defaultAsset: 'usd'
            },
            environment: 'production',
            defaultAmount: '50'
          },
          crypto: {
            source: {
              mode: 'all'
            }
          }
        });

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

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

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

  ## Stripe Embedded Components onramp

  Privy supports [Stripe's Embedded Components for Crypto Onramp](https://docs.stripe.com/crypto/onramp/embedded-components) as a payment option within the deposit modal's fiat flow. Stripe provides an embedded UX that handles payment processing, KYC via [Link](https://link.com/), and crypto delivery directly to the user's wallet.

  <Info>Requires `@privy-io/react-auth` version **3.33.1** or later.</Info>

  Install the `@stripe/crypto` package as a required dependency:

  ```bash theme={"system"}
  pnpm install @stripe/crypto
  ```

  Supported payment methods include credit, debit, Apple Pay, Google Pay, and ACH (US only). Supported destination currencies include OUSD on Tempo, Base, Ethereum, and Solana, USDC.e on Tempo, USDC on Base, Solana, Ethereum, Arbitrum, and Polygon, and USDT on Ethereum. Available in the US (excluding New York) and the EU.

  <Card title="Stripe docs" icon="stripe" href="https://docs.stripe.com/crypto/onramp/embedded-components">
    Official Stripe Embedded Components onramp documentation
  </Card>

  ### Test in sandbox mode

  Pass `fiat.environment: 'sandbox'` to `depositFunds` to run the flow against Stripe's test environment. No real funds move, and you can complete an end-to-end purchase with the test values below.

  | Field | Test value |
  | - | - |
  | Onramp amount | Less than \$200 |
  | Phone number | A US or EU phone number |
  | Phone verification code | `000000` |
  | Card number | `4242 4242 4242 4242` |
  | CVC | Any three digits |
  | Expiry date | Any date in the future |

  Set `destination.chain` to a mainnet chain. Stripe's onramp does not support testnets, so testnet chains fail even in sandbox mode.

  | Chain | Mainnet CAIP-2 |
  | - | - |
  | Tempo | `eip155:4217` |
  | Base | `eip155:8453` |
  | Solana | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` |
  | Ethereum | `eip155:1` |
  | Arbitrum | `eip155:42161` |
  | Polygon | `eip155:137` |
</View>

<View title="React Native" icon="react">
  <Tip>
    Make sure `<PrivyElements />` is mounted first, by following [this
    guide](/authentication/user-authentication/ui-component).
  </Tip>

  Privy provides `useFundWallet` and `useFundSolanaWallet` hooks in `@privy-io/expo/ui` that start a card-based fiat onramp flow in the Privy modal on React Native.

  Your app can use these hooks to let authenticated users buy crypto via MoonPay or Coinbase. `useFundWallet` funds EVM wallets, and `useFundSolanaWallet` funds Solana wallets.

  ## Start a fiat onramp flow

  <Tabs>
    <Tab title="EVM">
      Use `useFundWallet` to fund an EVM wallet. Call `fundWallet` with the destination address, chain, amount, and optional asset configuration.

      ```tsx theme={"system"}
      import {useFundWallet} from '@privy-io/expo/ui';
      import {base} from 'viem/chains';

      const {fundWallet} = useFundWallet();

      await fundWallet({
        address: '<wallet_address>',
        chain: base,
        amount: '50',
        asset: 'USDC'
      });
      ```

      ### Parameters

      | Parameter | Type | Description |
      | - | - | - |
      | `address` | `string` | Required. The destination wallet address to fund. |
      | `chain` | [`Chain`](https://viem.sh/docs/chains/introduction) | Optional. A `viem/chains` object for the network on which to fund. Defaults to the chain configured in the Dashboard. |
      | `asset` | `'native-currency'` \| `'USDC'` \| `{tokenAddress: string}` | Optional. The asset to fund with. Defaults to `'native-currency'`. |
      | `amount` | `string` | Required if `asset` is set, optional otherwise. The amount to fund as a decimal string. |
      | `defaultPaymentMethod` | `'card'` \| `'exchange'` | Optional. Skip payment method selection and trigger the specified flow directly. |
      | `card.preferredProvider` | `'coinbase'` \| `'moonpay'` | Optional. The preferred card onramp provider. |
      | `moonpay.useSandbox` | `boolean` | Optional. Use MoonPay sandbox mode for testing. |
      | `moonpay.uiConfig.accentColor` | `string` | Optional. Accent color for the MoonPay UI (hex value). |
      | `moonpay.uiConfig.theme` | `'light'` \| `'dark'` | Optional. Theme for the MoonPay UI. |
    </Tab>

    <Tab title="Solana">
      Use `useFundSolanaWallet` to fund a Solana wallet. Call `fundWallet` with the destination address, cluster, and amount.

      ```tsx theme={"system"}
      import {useFundSolanaWallet} from '@privy-io/expo/ui';

      const {fundWallet} = useFundSolanaWallet();

      await fundWallet({
        address: '<wallet_address>',
        cluster: {name: 'mainnet-beta'},
        amount: '1',
        asset: 'native-currency'
      });
      ```

      ### Parameters

      | Parameter | Type | Description |
      | - | - | - |
      | `address` | `string` | Required. The destination Solana wallet address to fund. |
      | `cluster` | `SolanaCluster` | Optional. The Solana cluster to fund on. Defaults to `mainnet-beta`. |
      | `asset` | `'native-currency'` \| `'USDC'` | Optional. The asset to fund with. Defaults to `'native-currency'`. |
      | `amount` | `string` | Required if `asset` is set, optional otherwise. The amount to fund as a decimal string. |
      | `defaultPaymentMethod` | `'card'` \| `'exchange'` | Optional. Skip payment method selection and trigger the specified flow directly. |
      | `card.preferredProvider` | `'coinbase'` \| `'moonpay'` | Optional. The preferred card onramp provider. |
      | `moonpay.useSandbox` | `boolean` | Optional. Use MoonPay sandbox mode for testing. |
      | `moonpay.uiConfig.accentColor` | `string` | Optional. Accent color for the MoonPay UI (hex value). |
      | `moonpay.uiConfig.theme` | `'light'` \| `'dark'` | Optional. Theme for the MoonPay UI. |
    </Tab>
  </Tabs>

  <Info>
    The React Native fiat onramp supports MoonPay and Coinbase as card providers. Stripe, Meld, and
    the multi-provider routing available in the React `useDepositFunds` flow are not yet supported on
    React Native.
  </Info>
</View>

## Related

<CardGroup cols={2}>
  <Card title="Crypto deposits" icon="arrow-right-to-bracket" href="/wallets/funding/crypto-deposits/overview">
    Persistent deposit addresses, setup, and headless React or React Native.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.