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

# Hosted wallet connections

> Send users to a connect page for a wallet address, or run it headless on native platforms to also sign messages and transactions.

> [!NOTE]
>
> This is an enterprise-only feature. Please [contact us](https://www.dynamic.xyz/book-a-call) to enable.

This is the hosted form factor of [Fireblocks Flow](https://docs.dynamic.xyz/docs/flow/overview.md)'s wallet connector, built on the Dynamic SDK. Instead of building a wallet picker yourself, you send users to a connect page with a catalog of 800+ **external wallets** (for example MetaMask or Phantom), plus manual address entry.

For the choice between this and [native](https://docs.dynamic.xyz/docs/external-wallets/native.md) connection, see [Connections](https://docs.dynamic.xyz/docs/flow/connections.md).

> [!TIP]
>
> Dynamic hosts a ready-to-use instance at `https://connect.dynamicauth.com/`. Deploying your own instance on a custom domain is also supported, and is arranged as part of enabling the feature. See the [live demo](https://connections.dynamic.dev/).

## Redirect or headless

> [card] Redirect (basic)
>
> Open the connect page with a `redirect_uri`. The user connects a wallet (or pastes an address) and it redirects back with the public address. Address-only: no signature or transaction.

> [card] Headless
>
> iOS, Android, and Flutter. Render your own native wallet list backed by a hidden web view running the Dynamic SDK. After connecting, you can also sign messages and transactions over the same bridge. Your app links no wallet SDK.

> [!NOTE]
>
> Already building with the React, React Native, or JavaScript SDK? Use the SDK directly for full wallet state (balances, embedded wallets, signing APIs). See [Embedded Wallets](https://docs.dynamic.xyz/docs/embedded-wallets/mpc/overview.md).

## When to use this

Reach for it when you want a wallet address (and optionally signing) without adding the Dynamic SDK to every client:

* **You want a hosted picker.** Link out to one page instead of building and maintaining a wallet list per platform.
* **You can't add a third-party SDK.** On iOS, Android, and Flutter, **headless** mode runs the wallet list and connection logic behind a hidden web view, so your app links no wallet SDK. After connect, you can also sign messages and transactions through that same bridge.

## How it works

Every platform follows the same redirect contract for the basic flow:

**1. Open the connect page**

Open it with a `redirect_uri` you control, and an optional `nonce`. The platform guides under **Implement** show the URL assembly for each platform.

| Parameter | Required | Description |
| - | - | - |
| `redirect_uri` | Yes | Where to send the user back after they connect. Either an `http(s)` URL you control, or your app's custom scheme (e.g. `myapp://wallet-callback`) for native integrations. Alias: `redirect_url`. |
| `nonce` | No | An opaque value echoed back unchanged so you can correlate the response to the request. If you don't send one, none is returned. |
| `environmentId` | No | Dynamic environment ID to use instead of the page's build-time default. Must be a UUID. Invalid values are ignored with a console warning, and the page falls back to its build-time default. For headless, set this before `prewarm()` / `connect()`. |
| `theme` | No | UI theme: `light` or `dark`. Defaults to `light` when absent or invalid. Visible flow only. |
| `locale` | No | UI locale: `en_US`, `es_LA`, `es_CO`, or `tl_PH`. Defaults to `en_US`. Visible flow only. |
| `networks` | No | Comma-separated networks the user may connect on, as [CAIP-2](https://docs.dynamic.xyz/docs/connections/caip-2.md) ids (e.g. `networks=eip155:137,solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`). Only wallets that can connect on those chains are offered, and manual entry is limited to them. Console network keys (e.g. `polygon`) are still accepted but deprecated. Entries resolve against the environment's enabled networks, or a built-in list when the environment does not enable them; unrecognized entries are ignored, and with none recognized there is no restriction. A convenience filter, not enforcement. Visible flow only. |

**2. The user connects**

The user searches Dynamic's catalog of 800+ wallets, or pastes an address manually.

**3. Read the result on your redirect**

It redirects back to your `redirect_uri` with the result appended as query parameters:

| Parameter | Description |
| - | - |
| `address` | The connected wallet's public address. |
| `chain` | The chain family the address belongs to: `evm`, `solana`, or `bitcoin`. |
| `walletName` | Display name of the wallet (e.g. `MetaMask`). Empty for a manually-entered address. |
| `walletImage` | Icon URL for the wallet. Empty for a manually-entered address. |
| `networkId` | The [CAIP-2](https://docs.dynamic.xyz/docs/connections/caip-2.md) id of the network the wallet is on (e.g. `eip155:137`), or the network picked for a manually entered address. EVM wallets report one. Solana wallets do only through WalletConnect and MetaMask, and Bitcoin wallets never do. Omitted when the wallet reports none (embedded wallets and Phantom's redirect never send one) or when the network has no CAIP-2 id. |
| `nonce` | The exact nonce you passed in, present only if you sent one. |

In headless mode the same id arrives as `networkId` on the `connected` bridge message instead of a redirect param.

## Network fields

Two fields carry a network, and they mean different things.

| Field | Meaning | Example | When present |
| - | - | - | - |
| `networkId` | The [CAIP-2](https://docs.dynamic.xyz/docs/connections/caip-2.md) id of the network the wallet is on. | `eip155:137`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | On the redirect URL and on the headless `connected` message. Omitted when it cannot be determined. Solana reports it only for WalletConnect and MetaMask, and Bitcoin never does. |
| `network` | The Phantom Solana session cluster a connection is bound to. It is not a CAIP-2 id. | `mainnet-beta`, `devnet` | Only on the headless `connected` message, and only for Phantom connects. Never on the redirect URL. |

Read `networkId` to learn which network the wallet is on. Use `network` only to lock a Solana send screen to the cluster a Phantom session will sign for.

Pick your platform for the full integration guide (including copy-paste harness sources):

> [card] [Web](https://docs.dynamic.xyz/docs/connections/web.md)
>
> Link to the hosted page and read the result on your redirect.

> [card] [iOS (basic)](https://docs.dynamic.xyz/docs/connections/ios.md)
>
> Present it in `ASWebAuthenticationSession`.

> [card] [iOS (headless)](https://docs.dynamic.xyz/docs/connections/ios-headless.md)
>
> Native list via a hidden web view. Connect and sign over the bridge.

> [card] [Android (basic)](https://docs.dynamic.xyz/docs/connections/android.md)
>
> Present it in a Chrome Custom Tab.

> [card] [Android (headless)](https://docs.dynamic.xyz/docs/connections/android-headless.md)
>
> Native list via a hidden WebView. Connect and sign over the bridge.

> [card] [React Native](https://docs.dynamic.xyz/docs/connections/react-native.md)
>
> Present it with `expo-web-browser`.

> [card] [Flutter (basic)](https://docs.dynamic.xyz/docs/connections/flutter.md)
>
> Present it with `flutter_web_auth_2`.

> [card] [Flutter (headless)](https://docs.dynamic.xyz/docs/connections/flutter-headless.md)
>
> Native list + message signing and EVM, Solana, and Bitcoin sends, plus Bitcoin PSBT signing, via a hidden WebViewWidget.

Connections can also move funds out of a user's exchange account, or read what they hold there, without connecting a wallet at all. See [Fund from an exchange](https://docs.dynamic.xyz/docs/connections/fund-from-exchange.md).

## Securing the redirect

`redirect_uri` is caller-supplied, so an `http(s)` target is an open-redirect surface. Lock it down before exposing this to untrusted callers.

> [!WARNING]
>
> Set `NEXT_PUBLIC_CONNECT_ALLOWED_REDIRECT_HOSTS` to the `http(s)` hosts you accept: bare hostnames, comma-separated, no scheme, no path, no wildcards. Left unset, any host is accepted (with a console warning) so existing integrations keep working.

* **Exact hostname match.** `example.com` does not match `sub.example.com`. Port is ignored.
* **Rebuild to apply.** Next.js inlines `NEXT_PUBLIC_*` variables at build time, so changing this needs a rebuild and redeploy. Setting it in a hosting console alone does nothing.
* **Custom app schemes are never host-filtered.** Their "host" is a callback name interpreted by your native app, not a network address.

A handful of schemes that can hand off to another app or a browser-internal page are always refused, even in permissive mode: `javascript:`, `data:`, `intent:`, `android-app:`, `market:`, `content:`, `chrome:`, `ftp:`, and similar. A refused value falls back to the same-origin `/callback` page and logs a warning. If your callback never fires, check the browser console first.


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