> ## 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.

# Headless deposit addresses

> Deprecated useDepositAddress hook for custom deposit address UI in React and React Native

> [!WARNING]
>
> `useDepositAddress` is deprecated. Use
> [`useHeadlessCryptoDeposit`](https://docs.privy.io/wallets/funding/crypto-deposits/create-deposit-account) instead.

**React**

## Overview

The `useDepositAddress` hook from `@privy-io/react-auth/hooks` provides stateless helpers for building a fully custom deposit address UI. This hook does not render the Privy modal — your app controls the entire user experience.

## Access the hook

```tsx theme={"system"}
import {useDepositAddress} from '@privy-io/react-auth/hooks';

const {getConfig, generateDepositAddress, getDeposit, waitForDeposit, waitForCompletion} =
  useDepositAddress();
```

## Methods

| Method | Description |
| - | - |
| `getConfig` | Fetches supported currencies and chains |
| `generateDepositAddress` | Creates a deposit quote with a unique deposit address |
| `getDeposit` | Fetches enriched order details by order ID |
| `waitForDeposit` | Polls until funds are received at the deposit address |
| `waitForCompletion` | Polls an order until it reaches a terminal status |

## Step 1: Load deposit configuration

Call `getConfig` to fetch the available currencies and chains:

```tsx theme={"system"}
const config = await getConfig();
```

The returned `DepositConfig` object contains:

* `currencies` — an array of supported tokens with their chain availability
* `chains` — a record keyed by caip2 with chain metadata

### Config shape

```tsx theme={"system"}
type DepositConfig = {
  currencies: Array<{
    symbol: string;
    name: string;
    logoURI: string;
    chains: Array<{caip2: string; address: string; decimals: number}>;
  }>;
  chains: Record<
    string,
    {chainId: number; caip2: string; displayName: string; iconUrl: string; vmType: string}
  >;
};
```

### Example config response

```json theme={"system"}
{
  "currencies": [
    {
      "symbol": "USDC",
      "name": "USD Coin",
      "logoURI": "https://assets.privy.io/tokens/usdc.png",
      "chains": [
        {
          "caip2": "eip155:8453",
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "decimals": 6
        },
        {
          "caip2": "eip155:1",
          "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
          "decimals": 6
        },
        {
          "caip2": "eip155:4217",
          "address": "0x20c000000000000000000000b9537d11c60e8b50",
          "decimals": 6
        }
      ]
    },
    {
      "symbol": "ETH",
      "name": "Ethereum",
      "logoURI": "https://assets.privy.io/tokens/eth.png",
      "chains": [
        {
          "caip2": "eip155:8453",
          "address": "0x0000000000000000000000000000000000000000",
          "decimals": 18
        },
        {
          "caip2": "eip155:1",
          "address": "0x0000000000000000000000000000000000000000",
          "decimals": 18
        }
      ]
    }
  ],
  "chains": {
    "eip155:8453": {
      "chainId": 8453,
      "caip2": "eip155:8453",
      "displayName": "Base",
      "iconUrl": "https://assets.privy.io/chains/base.png",
      "vmType": "evm"
    },
    "eip155:1": {
      "chainId": 1,
      "caip2": "eip155:1",
      "displayName": "Ethereum",
      "iconUrl": "https://assets.privy.io/chains/ethereum.png",
      "vmType": "evm"
    },
    "eip155:4217": {
      "chainId": 4217,
      "caip2": "eip155:4217",
      "displayName": "Tempo",
      "iconUrl": "https://assets.privy.io/chains/tempo.png",
      "vmType": "evm"
    }
  }
}
```

### Using the config

Use the config to build chain and currency selectors in your UI:

```tsx theme={"system"}
function getChainsForDisplay(config: DepositConfig) {
  return Object.values(config.chains).map((chain) => ({
    caip2: chain.caip2,
    displayName: chain.displayName,
    iconUrl: chain.iconUrl
  }));
}

function getCurrenciesForChain(config: DepositConfig, caip2: string) {
  return config.currencies
    .filter((currency) => currency.chains.some((c) => c.caip2 === caip2))
    .map((currency) => {
      const chainInfo = currency.chains.find((c) => c.caip2 === caip2)!;
      return {symbol: currency.symbol, name: currency.name, address: chainInfo.address};
    });
}
```

## Step 2: Generate a deposit address

Call `generateDepositAddress` with the source and destination details:

```tsx theme={"system"}
const quote = await generateDepositAddress({
  sourceChain: 'eip155:1',
  sourceCurrency: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  destinationChain: 'eip155:8453',
  destinationCurrency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
  destinationAddress: '0x1234...abcd'
});
```

The returned `DepositAddressQuote` includes `id`, `deposit_address`, `indicative_rate`, `time_estimate_seconds`, and `created_at`.

> [!NOTE]
>
> Deposit addresses can be reused. If a user sends funds to the same deposit address again, Privy
> routes the new deposit using the same source token, source chain, and destination settings.

### Parameters

**sourceChain** `string` *required*

CAIP-2 identifier for the source chain (e.g. `eip155:1` for Ethereum).

**sourceCurrency** `string` *required*

Token contract address on the source chain.

**destinationChain** `string` *required*

CAIP-2 identifier for the destination chain (e.g. `eip155:8453` for Base).

**destinationCurrency** `string` *required*

Token contract address on the destination chain.

**destinationAddress** `string` *required*

Wallet address to receive the deposited funds.

**refundAddress** `string`

Refund address on the source chain. If not provided, Privy resolves one automatically from the
user's linked wallets or creates an embedded wallet.

**slippageBps** `number`

Slippage tolerance in basis points. Uses the default for the route if not provided.

## Step 3: Display the deposit address

Once you have the quote, display `quote.deposit_address` to the user. The user sends funds to this address from the source chain. You can also show `quote.indicative_rate` and `quote.time_estimate_seconds` to set expectations.

## Step 4: Poll for deposit and completion

### Wait for the deposit

After the user sends funds, call `waitForDeposit` to poll until the deposit is detected:

```tsx theme={"system"}
const result = await waitForDeposit({
  depositAddressId: quote.id,
  quoteCreatedAt: quote.created_at
});

if (result.status === 'success') {
  console.log('Order detected:', result.order.id);
}
```

**depositAddressId** `string` *required*

The quote ID returned as `DepositAddressQuote.id`.

**quoteCreatedAt** `string` *required*

The quote creation timestamp returned as `DepositAddressQuote.created_at`.

**signal** `AbortSignal`

Optional abort signal to cancel polling.

**pollIntervalMs** `number`

Optional polling interval override in milliseconds.

**timeoutMs** `number`

Optional polling timeout override in milliseconds.

### Polling return type

Both `waitForDeposit` and `waitForCompletion` return a `DepositAddressPollingResult`:

```tsx theme={"system"}
type DepositAddressPollingResult =
  | {status: 'success'; order: DepositAddressOrder}
  | {status: 'aborted'; error?: Error}
  | {status: 'timeout'; error?: Error};

type DepositAddressOrder = {
  id: string;
  source_chain: string;
  source_currency: string;
  source_amount: string;
  depositor_address: string;
  destination_chain: string;
  destination_currency: string;
  destination_amount: string | null;
  status: 'executing' | 'completed' | 'refunded' | 'failed';
  tracking_url: string;
  created_at: string;
  updated_at: string;
};
```

When `status` is `'completed'`, `destination_amount` contains the delivered amount. For all other statuses, `destination_amount` is `null`.

### Wait for order completion

Once a deposit order is detected, poll until it reaches a terminal status (`completed`, `refunded`, or `failed`):

```tsx theme={"system"}
const finalResult = await waitForCompletion({
  orderId: result.order.id
});

if (finalResult.status === 'success' && finalResult.order.status === 'completed') {
  console.log('Deposit delivered:', finalResult.order.destination_amount);
}
```

**orderId** `string` *required*

The deposit address order ID.

**signal** `AbortSignal`

Optional abort signal to cancel polling.

**pollIntervalMs** `number`

Optional polling interval override in milliseconds.

**timeoutMs** `number`

Optional polling timeout override in milliseconds.

### Fetch order details

Call `getDeposit` to fetch the full `DepositAddressOrder` for a given order at any time:

```tsx theme={"system"}
const order = await getDeposit({orderId: 'order_abc123'});
```

**orderId** `string` *required*

The deposit address order ID (returned as `order.id` from `waitForDeposit` or
`waitForCompletion`).

Returns a `DepositAddressOrder` with the order's current status, source and destination details, amounts, and a `tracking_url` for external tracking.

## Full example

```tsx theme={"system"}
import {useState} from 'react';
import {
  useDepositAddress,
  type DepositAddressQuote,
  type DepositConfig
} from '@privy-io/react-auth/hooks';

function getCurrenciesForChain(config: DepositConfig, caip2: string) {
  return config.currencies
    .filter((currency) => currency.chains.some((c) => c.caip2 === caip2))
    .map((currency) => {
      const chainInfo = currency.chains.find((c) => c.caip2 === caip2)!;
      return {symbol: currency.symbol, address: chainInfo.address};
    });
}

function CustomDepositFlow() {
  const {getConfig, generateDepositAddress, waitForDeposit, waitForCompletion} =
    useDepositAddress();

  const [config, setConfig] = useState<DepositConfig | null>(null);
  const [quote, setQuote] = useState<DepositAddressQuote | null>(null);
  const [status, setStatus] = useState<string>('idle');

  const handleLoadConfig = async () => {
    const result = await getConfig();
    setConfig(result);
  };

  const handleDeposit = async () => {
    const newQuote = await generateDepositAddress({
      sourceChain: 'eip155:1',
      sourceCurrency: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      destinationChain: 'eip155:8453',
      destinationCurrency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      destinationAddress: '0x1234...abcd'
    });
    setQuote(newQuote);
    setStatus('awaiting_deposit');

    const orderResult = await waitForDeposit({
      depositAddressId: newQuote.id,
      quoteCreatedAt: newQuote.created_at
    });
    setStatus('processing');

    const finalResult = await waitForCompletion({
      orderId: orderResult.order.id
    });
    setStatus(finalResult.order.status);
  };

  return (
    <div>
      {!config && <button onClick={handleLoadConfig}>Load config</button>}
      {config && !quote && (
        <div>
          <p>
            Available chains:{' '}
            {Object.values(config.chains)
              .map((c) => c.displayName)
              .join(', ')}
          </p>
          <button onClick={handleDeposit}>Start deposit</button>
        </div>
      )}
      {quote && (
        <div>
          <p>
            Send funds to: <code>{quote.deposit_address}</code>
          </p>
          <p>Estimated time: ~{Math.round(quote.time_estimate_seconds / 60)} min</p>
          <p>Status: {status}</p>
        </div>
      )}
    </div>
  );
}
```

## Related

> **[Headless crypto deposits](https://docs.privy.io/wallets/funding/crypto-deposits/create-deposit-account.md)**
>
> Replacement hook: `useHeadlessCryptoDeposit`

> **[Deposits overview](https://docs.privy.io/financial-flows/deposits/overview.md)**
>
> All available methods for funding wallets.

**React Native**

## Overview

The `useDepositAddress` hook from `@privy-io/expo` provides stateless helpers for building a fully custom deposit address flow in React Native. Your app controls the entire user experience — there is no modal or prebuilt UI.

## Access the hook

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

const {getConfig, generateDepositAddress, getDeposit, waitForDeposit, waitForCompletion} =
  useDepositAddress();
```

## Methods

| Method | Description |
| - | - |
| `getConfig` | Fetches supported currencies and chains |
| `generateDepositAddress` | Creates a deposit quote with a unique deposit address |
| `getDeposit` | Fetches enriched order details by order ID |
| `waitForDeposit` | Polls until funds are received at the deposit address |
| `waitForCompletion` | Polls an order until it reaches a terminal status |

## Step 1: Load deposit configuration

Call `getConfig` to fetch the available currencies and chains:

```tsx theme={"system"}
const config = await getConfig();
```

The returned `DepositConfig` object contains:

* `currencies` — an array of supported tokens with their chain availability
* `chains` — a record keyed by caip2 with chain metadata

### Config shape

```tsx theme={"system"}
type DepositConfig = {
  currencies: Array<{
    symbol: string;
    name: string;
    logoURI: string;
    chains: Array<{caip2: string; address: string; decimals: number}>;
  }>;
  chains: Record<
    string,
    {chainId: number; caip2: string; displayName: string; iconUrl: string; vmType: string}
  >;
};
```

### Example config response

```json theme={"system"}
{
  "currencies": [
    {
      "symbol": "USDC",
      "name": "USD Coin",
      "logoURI": "https://assets.privy.io/tokens/usdc.png",
      "chains": [
        {
          "caip2": "eip155:8453",
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "decimals": 6
        },
        {
          "caip2": "eip155:1",
          "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
          "decimals": 6
        },
        {
          "caip2": "eip155:4217",
          "address": "0x20c000000000000000000000b9537d11c60e8b50",
          "decimals": 6
        }
      ]
    },
    {
      "symbol": "ETH",
      "name": "Ethereum",
      "logoURI": "https://assets.privy.io/tokens/eth.png",
      "chains": [
        {
          "caip2": "eip155:8453",
          "address": "0x0000000000000000000000000000000000000000",
          "decimals": 18
        },
        {
          "caip2": "eip155:1",
          "address": "0x0000000000000000000000000000000000000000",
          "decimals": 18
        }
      ]
    }
  ],
  "chains": {
    "eip155:8453": {
      "chainId": 8453,
      "caip2": "eip155:8453",
      "displayName": "Base",
      "iconUrl": "https://assets.privy.io/chains/base.png",
      "vmType": "evm"
    },
    "eip155:1": {
      "chainId": 1,
      "caip2": "eip155:1",
      "displayName": "Ethereum",
      "iconUrl": "https://assets.privy.io/chains/ethereum.png",
      "vmType": "evm"
    },
    "eip155:4217": {
      "chainId": 4217,
      "caip2": "eip155:4217",
      "displayName": "Tempo",
      "iconUrl": "https://assets.privy.io/chains/tempo.png",
      "vmType": "evm"
    }
  }
}
```

### Using the config

Use the config to build chain and currency selectors in your UI:

```tsx theme={"system"}
function getChainsForDisplay(config: DepositConfig) {
  return Object.values(config.chains).map((chain) => ({
    caip2: chain.caip2,
    displayName: chain.displayName,
    iconUrl: chain.iconUrl
  }));
}

function getCurrenciesForChain(config: DepositConfig, caip2: string) {
  return config.currencies
    .filter((currency) => currency.chains.some((c) => c.caip2 === caip2))
    .map((currency) => {
      const chainInfo = currency.chains.find((c) => c.caip2 === caip2)!;
      return {symbol: currency.symbol, name: currency.name, address: chainInfo.address};
    });
}
```

## Step 2: Generate a deposit address

Call `generateDepositAddress` with the source and destination details:

```tsx theme={"system"}
const quote = await generateDepositAddress({
  sourceChain: 'eip155:1',
  sourceCurrency: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  destinationChain: 'eip155:8453',
  destinationCurrency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
  destinationAddress: '0x1234...abcd'
});
```

The returned `DepositAddressQuote` includes `id`, `deposit_address`, `indicative_rate`, `time_estimate_seconds`, and `created_at`.

> [!NOTE]
>
> Deposit addresses can be reused. If a user sends funds to the same deposit address again, Privy
> routes the new deposit using the same source token, source chain, and destination settings.

### Parameters

**sourceChain** `string` *required*

CAIP-2 identifier for the source chain (e.g. `eip155:1` for Ethereum).

**sourceCurrency** `string` *required*

Token contract address on the source chain.

**destinationChain** `string` *required*

CAIP-2 identifier for the destination chain (e.g. `eip155:8453` for Base).

**destinationCurrency** `string` *required*

Token contract address on the destination chain.

**destinationAddress** `string` *required*

Wallet address to receive the deposited funds.

**refundAddress** `string`

Refund address on the source chain. If not provided, Privy resolves one automatically from the
user's linked wallets or creates an embedded wallet.

**slippageBps** `number`

Slippage tolerance in basis points. Uses the default for the route if not provided.

## Step 3: Display the deposit address

Once you have the quote, display `quote.deposit_address` to the user. The user sends funds to this address from the source chain. You can also show `quote.indicative_rate` and `quote.time_estimate_seconds` to set expectations.

## Step 4: Poll for deposit and completion

### Wait for the deposit

After the user sends funds, call `waitForDeposit` to poll until the deposit is detected:

```tsx theme={"system"}
const result = await waitForDeposit({
  depositAddressId: quote.id,
  quoteCreatedAt: quote.created_at
});

if (result.status === 'success') {
  console.log('Order detected:', result.order.id);
}
```

**depositAddressId** `string` *required*

The quote ID returned as `DepositAddressQuote.id`.

**quoteCreatedAt** `string` *required*

The quote creation timestamp returned as `DepositAddressQuote.created_at`.

**signal** `AbortSignal`

Optional abort signal to cancel polling.

**pollIntervalMs** `number`

Optional polling interval override in milliseconds.

**timeoutMs** `number`

Optional polling timeout override in milliseconds.

### Polling return type

Both `waitForDeposit` and `waitForCompletion` return a `DepositAddressPollingResult`:

```tsx theme={"system"}
type DepositAddressPollingResult =
  | {status: 'success'; order: DepositAddressOrder}
  | {status: 'aborted'; error?: Error}
  | {status: 'timeout'; error?: Error};

type DepositAddressOrder = {
  id: string;
  source_chain: string;
  source_currency: string;
  source_amount: string;
  depositor_address: string;
  destination_chain: string;
  destination_currency: string;
  destination_amount: string | null;
  status: 'executing' | 'completed' | 'refunded' | 'failed';
  tracking_url: string;
  created_at: string;
  updated_at: string;
};
```

When `status` is `'completed'`, `destination_amount` contains the delivered amount. For all other statuses, `destination_amount` is `null`.

### Wait for order completion

Once a deposit order is detected, poll until it reaches a terminal status (`completed`, `refunded`, or `failed`):

```tsx theme={"system"}
const finalResult = await waitForCompletion({
  orderId: result.order.id
});

if (finalResult.status === 'success' && finalResult.order.status === 'completed') {
  console.log('Deposit delivered:', finalResult.order.destination_amount);
}
```

**orderId** `string` *required*

The deposit address order ID.

**signal** `AbortSignal`

Optional abort signal to cancel polling.

**pollIntervalMs** `number`

Optional polling interval override in milliseconds.

**timeoutMs** `number`

Optional polling timeout override in milliseconds.

### Fetch order details

Call `getDeposit` to fetch the full `DepositAddressOrder` for a given order at any time:

```tsx theme={"system"}
const order = await getDeposit({orderId: 'order_abc123'});
```

**orderId** `string` *required*

The deposit address order ID (returned as `order.id` from `waitForDeposit` or
`waitForCompletion`).

Returns a `DepositAddressOrder` with the order's current status, source and destination details, amounts, and a `tracking_url` for external tracking.

## Full example

```tsx theme={"system"}
import {useState} from 'react';
import {View, Text, Pressable} from 'react-native';
import {useDepositAddress, type DepositAddressQuote, type DepositConfig} from '@privy-io/expo';

function getCurrenciesForChain(config: DepositConfig, caip2: string) {
  return config.currencies
    .filter((currency) => currency.chains.some((c) => c.caip2 === caip2))
    .map((currency) => {
      const chainInfo = currency.chains.find((c) => c.caip2 === caip2)!;
      return {symbol: currency.symbol, address: chainInfo.address};
    });
}

function CustomDepositFlow() {
  const {getConfig, generateDepositAddress, waitForDeposit, waitForCompletion} =
    useDepositAddress();

  const [config, setConfig] = useState<DepositConfig | null>(null);
  const [quote, setQuote] = useState<DepositAddressQuote | null>(null);
  const [status, setStatus] = useState<string>('idle');

  const handleLoadConfig = async () => {
    const result = await getConfig();
    setConfig(result);
  };

  const handleDeposit = async () => {
    const newQuote = await generateDepositAddress({
      sourceChain: 'eip155:1',
      sourceCurrency: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
      destinationChain: 'eip155:8453',
      destinationCurrency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      destinationAddress: '0x1234...abcd'
    });
    setQuote(newQuote);
    setStatus('awaiting_deposit');

    const orderResult = await waitForDeposit({
      depositAddressId: newQuote.id,
      quoteCreatedAt: newQuote.created_at
    });
    setStatus('processing');

    const finalResult = await waitForCompletion({
      orderId: orderResult.order.id
    });
    setStatus(finalResult.order.status);
  };

  return (
    <View>
      {!config && (
        <Pressable onPress={handleLoadConfig}>
          <Text>Load config</Text>
        </Pressable>
      )}
      {config && !quote && (
        <View>
          <Text>
            Available chains:{' '}
            {Object.values(config.chains)
              .map((c) => c.displayName)
              .join(', ')}
          </Text>
          <Pressable onPress={handleDeposit}>
            <Text>Start deposit</Text>
          </Pressable>
        </View>
      )}
      {quote && (
        <View>
          <Text>Send funds to: {quote.deposit_address}</Text>
          <Text>Estimated time: ~{Math.round(quote.time_estimate_seconds / 60)} min</Text>
          <Text>Status: {status}</Text>
        </View>
      )}
    </View>
  );
}
```

## Related

> **[Headless crypto deposits](https://docs.privy.io/wallets/funding/crypto-deposits/create-deposit-account.md)**
>
> Replacement hook: `useHeadlessCryptoDeposit`

> **[Deposits overview](https://docs.privy.io/financial-flows/deposits/overview.md)**
>
> All available methods for funding wallets.
