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

# Funding flows

> Let users buy crypto with fiat by generating a hosted on-ramp URL for their wallet.

## Prerequisites

Before this page: a connected wallet (see [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets)) or an embedded wallet. On-ramp providers must be enabled for your environment in the Dynamic dashboard.

## What you'll build

A **funding** flow lets a user top up their wallet with crypto bought using fiat. Dynamic generates a hosted on-ramp URL for a provider — you open it, and the provider handles KYC, payment, and delivery straight to the user's wallet address.

This page covers two providers: **MoonPay** and **Coinbase**. Both follow the same shape — build a request from the user's wallet, get a URL, open it.

## Funding with MoonPay

`getMoonPayUrl` returns a hosted widget URL for the wallet's address and chain. Optionally list supported tokens first with `getMoonPayCurrencies`.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import { getMoonPayUrl, type WalletAccount } from '@dynamic-labs-sdk/client';

    async function fundWithMoonPay(walletAccount: WalletAccount) {
      const url = await getMoonPayUrl({
        chain: walletAccount.chain,
        walletAddress: walletAccount.address,
        token: 'USDC',
      });

      window.open(url, '_blank', 'noopener');
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { type WalletAccount } from '@dynamic-labs-sdk/client';
    import { useGetMoonPayUrl } from '@dynamic-labs-sdk/react-hooks';

    function FundWithMoonPay({ walletAccount }: { walletAccount: WalletAccount }) {
      // useGetMoonPayUrl is a query hook -- it fetches as soon as the params are
      // available, not on click. Open the already-fetched URL when clicked.
      const { data: url, isLoading } = useGetMoonPayUrl({
        chain: walletAccount.chain,
        walletAddress: walletAccount.address,
        token: 'USDC',
      });

      return (
        <button
          type="button"
          onClick={() => url && window.open(url, '_blank', 'noopener')}
          disabled={isLoading || !url}
        >
          Add funds
        </button>
      );
    }
    ```
  </Tab>
</Tabs>

## Funding with Coinbase

`getCoinbaseBuyUrl` returns `{ url }` for the hosted Coinbase Onramp widget. Pass the destination address and the networks you support.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"system"}
    import { getCoinbaseBuyUrl, type WalletAccount } from '@dynamic-labs-sdk/client';

    async function fundWithCoinbase(walletAccount: WalletAccount) {
      const { url } = await getCoinbaseBuyUrl({
        destinationAddress: walletAccount.address,
        networks: ['ethereum'],
        assets: ['USDC'],
      });

      window.open(url, '_blank', 'noopener');
    }
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { type WalletAccount } from '@dynamic-labs-sdk/client';
    import { useGetCoinbaseBuyUrl } from '@dynamic-labs-sdk/react-hooks';

    function FundWithCoinbase({ walletAccount }: { walletAccount: WalletAccount }) {
      // useGetCoinbaseBuyUrl is a query hook too -- same pattern as MoonPay above.
      const { data, isLoading } = useGetCoinbaseBuyUrl({
        destinationAddress: walletAccount.address,
        networks: ['ethereum'],
        assets: ['USDC'],
      });

      return (
        <button
          type="button"
          onClick={() => data?.url && window.open(data.url, '_blank', 'noopener')}
          disabled={isLoading || !data?.url}
        >
          Buy with Coinbase
        </button>
      );
    }
    ```
  </Tab>
</Tabs>

<Note>
  Delivery is asynchronous — the provider credits the wallet after the user finishes payment and KYC in the hosted widget. Poll [token balances](/docs/javascript/building-ui/token-balances-display) or refresh on return to reflect the new funds.
</Note>

## Handling errors

| Situation              | What to do                                                                                       |
| ---------------------- | ------------------------------------------------------------------------------------------------ |
| No connected wallet    | Prompt the user to connect a wallet before funding.                                              |
| Provider not enabled   | Enable the on-ramp provider for your environment in the dashboard; the request fails until then. |
| User closed the widget | No funds were moved — leave the "add funds" entry point available to retry.                      |

## See also

* [Token balances & display](/docs/javascript/building-ui/token-balances-display) — reflect newly funded balances
* [Connecting external wallets](/docs/javascript/building-ui/connecting-external-wallets) — get a wallet to fund
* [Building a swap UI](/docs/javascript/building-ui/swap-ui) — convert funds once they arrive
