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

# Using Bitcoin Wallets

> Sign messages, send Bitcoin, and work with PSBTs from a React Native client

Bitcoin is exposed as a first-class module on the headless React Native client — `dynamicClient.bitcoin` — alongside `dynamicClient.wallets`, `dynamicClient.auth`, and the chain extensions. There is no separate `BitcoinExtension` to install: the module ships with `@dynamic-labs/client` and routes all calls through the embedded WebView, which already includes the Bitcoin wallet connectors and a `BitcoinController` that handles the bridge messages.

## Checking if a wallet is a Bitcoin wallet

```ts React Native theme={"system"}
import { dynamicClient } from '<path to client file>';

const wallet = dynamicClient.wallets.primary;
if (!wallet || wallet.chain !== 'BTC') {
  throw new Error('This wallet is not a Bitcoin wallet');
}
```

`wallet.chain` returns one of `'EVM' | 'SOL' | 'BTC' | 'SUI' | 'TON'`, so you can branch on it generically. To list every Bitcoin wallet the user has connected:

```ts React Native theme={"system"}
const btcWallets = dynamicClient.wallets.userWallets.filter(
  (w) => w.chain === 'BTC',
);
```

## Configuring the client

Bitcoin support is enabled the moment you create the client; no extension is required. You may optionally pass `bitcoinNetworks` to override the dashboard network list (custom entries win on `chainId` conflicts).

<CodeGroup>
  ```ts dynamicClient.ts theme={"system"}
  import { createClient } from '@dynamic-labs/client';
  import { ReactNativeExtension } from '@dynamic-labs/react-native-extension';
  import { WebExtension } from '@dynamic-labs/web-extension';

  export const dynamicClient = createClient({
    environmentId: 'YOUR-ENVIRONMENT-ID',
    appName: 'Your App',
    appLogoUrl: 'https://your-domain.com/logo.png',
  })
    .extend(ReactNativeExtension({ appOrigin: 'https://your-domain.com' }))
    .extend(WebExtension({}));
  ```

  ```ts dynamicClient.ts (custom Bitcoin network) theme={"system"}
  import { createClient } from '@dynamic-labs/client';
  import { ReactNativeExtension } from '@dynamic-labs/react-native-extension';
  import { WebExtension } from '@dynamic-labs/web-extension';

  export const dynamicClient = createClient({
    environmentId: 'YOUR-ENVIRONMENT-ID',
    bitcoinNetworks: [
      {
        chainId: 0,
        networkId: 0,
        name: 'Bitcoin Mainnet',
        rpcUrls: ['https://your-bitcoin-rpc.example.com'],
        nativeCurrency: { name: 'Bitcoin', symbol: 'BTC', decimals: 8 },
        blockExplorerUrls: ['https://mempool.space'],
      },
    ],
  })
    .extend(ReactNativeExtension({ appOrigin: 'https://your-domain.com' }))
    .extend(WebExtension({}));
  ```
</CodeGroup>

## The `dynamicClient.bitcoin` module

Every method takes a `walletId` (string) — typically read from `wallet.id` of a wallet you've already filtered by `chain === 'BTC'`.

| Method               | Purpose                                                             |
| -------------------- | ------------------------------------------------------------------- |
| `signMessage`        | Sign a message using ECDSA or BIP-322.                              |
| `signPsbt`           | Sign a single PSBT (BIP-174).                                       |
| `signPsbts`          | Sign a batch of PSBTs in one call.                                  |
| `sendBitcoin`        | High-level transfer (build, sign, broadcast in one step).           |
| `buildPsbt`          | Build an unsigned PSBT for a transfer; sign and broadcast yourself. |
| `sendRawTransaction` | Broadcast an already-signed raw transaction hex.                    |
| `getBalance`         | Returns the wallet's balance in satoshis (as a string).             |

## Sign a message

`signMessage` accepts a `protocol` (`'ecdsa' | 'bip322-simple'`) and an `addressType` (`'payment' | 'ordinals'`). When omitted, the connector chooses sensible defaults.

```ts React Native theme={"system"}
const wallet = dynamicClient.wallets.userWallets.find((w) => w.chain === 'BTC');
if (!wallet) throw new Error('No Bitcoin wallet');

const { signature } = await dynamicClient.bitcoin.signMessage({
  walletId: wallet.id,
  message: 'Hello, Bitcoin!',
  protocol: 'bip322-simple',
  addressType: 'payment',
});
```

## Get balance

```ts React Native theme={"system"}
const wallet = dynamicClient.wallets.userWallets.find((w) => w.chain === 'BTC');
if (!wallet) throw new Error('No Bitcoin wallet');

const { balance } = await dynamicClient.bitcoin.getBalance({
  walletId: wallet.id,
});

// balance is a satoshi-denominated string. Convert to BTC for display:
const btc = Number(balance) / 1e8;
```

## Embedded vs external Bitcoin wallets

Connecting a Bitcoin wallet works the same as any other chain — once you've enabled Bitcoin connectors in the dashboard, users see them in the auth flow. You do not need to install or import `@dynamic-labs/bitcoin` in the React Native app; the connectors live inside the WebView SDK.

* **Embedded (MPC) Bitcoin wallets** — derived from the same root entropy as the user's other embedded wallets, but with a Bitcoin-specific derived key. The private key is never reconstructed in your app; signing happens through the MPC ceremony.
* **External Bitcoin wallets** — Phantom, Unisat, Xverse (sats-connect), OKX, OneKey, MagicEden, Bitget, Binance, Oyl, plus a fallback connector. The signing protocol depends on the connector — `signMessage`'s `protocol` parameter respects what the underlying wallet supports.

A single user session can hold multiple wallets across chains. Filter by `wallet.chain` to find the right one.

## Examples

* [Send Bitcoin](/react-native/wallets/using-wallets/bitcoin/send-bitcoin) — high-level transfer using `dynamicClient.bitcoin.sendBitcoin`.
* [Sign and broadcast a PSBT](/react-native/wallets/using-wallets/bitcoin/sign-psbt) — work with PSBTs directly via `buildPsbt`, `signPsbt`, `signPsbts`, and `sendRawTransaction`.
