# Funding with `useFunding`

For concepts (sessions, payment methods, statuses) see [Funding](/docs/configuration/funding). This page covers the `useFunding` hook for a bespoke React Native Deposit UI. To skip the SDK entirely, a [hosted deposit page in a WebView](#no-sdk-hosted-deposit-page-in-a-webview) is available as a secondary option.

## Custom UI with `useFunding`

Drive a session yourself with the `useFunding` hook from `@openfort/react-native`. It exposes the session state plus `fund` (create a session and set a payment method in one call), `createSession` (create a session for a destination, to set the payment method later), `payLink`, and `reset`.

```tsx
import { useFunding } from '@openfort/react-native'
import { View, Text, Pressable } from 'react-native'

function Deposit({ walletAddress }: { walletAddress: string }) {
  const { fund, createSession, session, status, loading, error, isAvailable, payLink, reset } = useFunding()

  async function depositFromPolygon() {
    await fund(
      // target — where funds land (USDC on Base)
      { chain: 'eip155:8453', currency: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', address: walletAddress },
      // source — what the user sends (USDC on Polygon)
      { type: 'evm', source: { chain: 'eip155:137', currency: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', amount: '10000000' } }
    )
  }

  if (session?.paymentMethod) {
    return (
      <View>
        <Text>Status: {status}</Text>
        <Text>Send to: {session.paymentMethod.receiverAddress}</Text>
        {/* render session.paymentMethod.addressUri as a QR (e.g. react-native-qrcode-svg),
            or open session.paymentMethod.deeplinks with Linking.openURL */}
      </View>
    )
  }

  return (
    <Pressable onPress={depositFromPolygon} disabled={loading}>
      <Text>{loading ? 'Preparing…' : 'Deposit'}</Text>
    </Pressable>
  )
}
```

The hook returns once a deposit address is available and keeps polling until the session reaches a terminal status (`succeeded`, `bounced`, or `expired`). `fund`'s payment method can source from an EVM wallet (`{ type: 'evm', source }`) or a Solana wallet (`{ type: 'solana', source }`). To fund from a centralized exchange, use `payLink` instead.

On mobile you typically render `session.paymentMethod.receiverAddress` next to a QR code of `session.paymentMethod.addressUri`, and offer `session.paymentMethod.deeplinks` as one-tap buttons that open the user's wallet app via React Native's `Linking.openURL`.

### What `useFunding` returns

| Field | Type | Description |
| --- | --- | --- |
| `session` | `FundingSession \| null` | The current or last session, incl. `paymentMethod` once set. |
| `status` | `SessionStatus \| 'idle'` | Lifecycle status; `'idle'` before the first call. |
| `loading` | `boolean` | True while creating the session and minting the address. |
| `error` | `Error \| null` | The last error, if any. |
| `isAvailable` | `boolean` | True when a funding backend is configured (`fundingBaseUrl` set). |
| `fund(target, paymentMethod)` | `=> Promise<FundingSession>` | Create a session and set a payment method in one call. |
| `createSession(target)` | `=> Promise<FundingSession>` | Create a session for a destination, to set the payment method later. |
| `track(session)` | `=> Promise<FundingSession>` | Attach to a session created elsewhere (its `id` + `clientSecret`) and poll it to a terminal status. |
| `payLink(params)` | `=> Promise<string>` | Resolve a prefilled exchange on-ramp URL (Coinbase / Binance). |
| `reset()` | `=> void` | Clear session state and start over. |

:::tip[Reacting to settlement]
There's no completion callback — drive UI off `status`. It reaches `succeeded` when funds land (or `bounced` / `expired`). For server-side fulfilment, don't rely on the device: use [webhooks](/docs/configuration/webhooks#funding-events).
:::

:::tip
Same‑chain deposits (source chain == destination chain) skip bridging entirely — the hook returns the wallet address directly, so a plain transfer works with no fees.
:::

## No-SDK: hosted deposit page in a WebView

If you'd rather not run any SDK code in your funding screen, open the hosted **deposit send page** inside a WebView. It reads the transfer from its URL and submits it through the wallet provider injected by the in-app browser — no Openfort SDK runs on the page.

Build a [deposit page URL](/docs/configuration/funding#hosted-deposit-page) with the destination address and source-chain params, then render it with [`react-native-webview`](https://github.com/react-native-webview/react-native-webview).

```tsx
import { WebView } from 'react-native-webview'

function DepositWebView({ receiver }: { receiver: string }) {
  const params = new URLSearchParams({
    to: receiver,
    chainId: '42161', // Arbitrum (source chain)
    token: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
    decimals: '6',
    symbol: 'USDC',
    chain: 'Arbitrum',
    amount: '10000000', // base units, user-editable
  })
  const url = `https://deposit.openfort.io?${params.toString()}`

  return <WebView source={{ uri: url }} />
}
```

The page shows the transaction hash on success but does **not** post back into the host app, so don't wait on `onMessage` for completion — track settlement with [Webhooks](/docs/configuration/webhooks#funding-events) or by polling the session through the [REST reference](/docs/configuration/funding/headless).

## Next steps

* Drive funding from a backend or agent with the [JavaScript SDK](/docs/products/embedded-wallet/javascript/signer/funding) or the [REST reference](/docs/configuration/funding/headless).
* Customize or self-host the deposit page — see the [hosted deposit page](/docs/configuration/funding#hosted-deposit-page).
* React to settlement with [Webhooks](/docs/configuration/webhooks#funding-events).

```
```
