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

# Create BTC Wallet

> Learn how to create and manage Bitcoin server wallets with Dynamic's Node SDK

## Overview

This guide walks you through creating Bitcoin wallets using Dynamic's Node SDK. You'll learn how to set up different threshold signature schemes, choose address types, and understand the security implications for Bitcoin blockchain operations.

## Prerequisites

Before you begin, make sure you have:

* [Set up your Dynamic project](https://docs.dynamic.xyz/docs/node/quickstart.md)
* [Created an authenticated client](https://docs.dynamic.xyz/docs/node/quickstart.md)
* [Enabled Bitcoin chain in your console](https://console.dynamic.xyz/dashboard/chains-and-networks)

## Step 1: Choose Your Security Model

Dynamic supports two threshold signature schemes for Bitcoin wallets:

### TWO\_OF\_TWO (Recommended for most use cases)

* **Security**: Highest, requiring both your server and Dynamic's infrastructure
* **Availability**: Lower, because both parties must be online
* **Use case**: High-value transactions, maximum security

### TWO\_OF\_THREE

* **Security**: High, requiring 2 out of 3 shares
* **Availability**: Medium, because it can tolerate one party being offline
* **Use case**: Balanced security and availability

## Step 2: Choose Your Address Type

Bitcoin supports multiple address types:

### Native SegWit (P2WPKH)

* **Prefix**: `bc1q...`
* **Algorithm**: ECDSA
* **Benefits**: Lower transaction fees, widely supported
* **Use case**: General purpose, most applications (recommended)

### Taproot (P2TR)

* **Prefix**: `bc1p...`
* **Algorithm**: Schnorr (BIP-340)
* **Benefits**: Enhanced privacy, smart contract capabilities
* **Use case**: Advanced applications, privacy-focused

## Step 3: Create Your First Bitcoin Wallet

Here's a complete example of creating a Bitcoin wallet:

```typescript theme={"system"}
import { DynamicBtcWalletClient } from '@dynamic-labs-wallet/node-btc';
import { ThresholdSignatureScheme } from '@dynamic-labs-wallet/node';
import { BitcoinAddressType } from '@dynamic-labs-wallet/core';

// Create authenticated client
export const authenticatedBtcClient = async () => {
  const client = new DynamicBtcWalletClient({
    environmentId: process.env.DYNAMIC_ENVIRONMENT_ID!,
  });

  await client.authenticateApiToken(process.env.DYNAMIC_AUTH_TOKEN!);
  return client;
};

export const createBtcWallet = async ({
  thresholdSignatureScheme = ThresholdSignatureScheme.TWO_OF_TWO,
  addressType = BitcoinAddressType.NATIVE_SEGWIT,
  password,
  onError,
}: {
  thresholdSignatureScheme?: ThresholdSignatureScheme;
  addressType?: BitcoinAddressType;
  password: string;
  onError?: (error: Error) => void;
}) => {
  const btcClient = await authenticatedBtcClient();

  const wallet = await btcClient.createWalletAccount({
    thresholdSignatureScheme,
    password,
    onError,
    backUpToDynamic: true,
    bitcoinConfig: {
      addressType,
    },
  });

  return {
    walletMetadata: wallet.walletMetadata,
    publicKeyHex: wallet.publicKeyHex,
    rawPublicKey: wallet.rawPublicKey,
    externalServerKeyShares: wallet.externalServerKeyShares,
  };
};

// Usage example - Native SegWit wallet
const segwitWallet = await createBtcWallet({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  addressType: BitcoinAddressType.NATIVE_SEGWIT,
  password: process.env.WALLET_PASSWORD!,
  onError: (error: Error) => {
    console.error('BTC wallet creation error:', error.message);
  },
});

console.log('Native SegWit wallet created:', segwitWallet.walletMetadata.accountAddress);
// Output: bc1q...

// Usage example - Taproot wallet
const taprootWallet = await createBtcWallet({
  addressType: BitcoinAddressType.TAPROOT,
  password: process.env.WALLET_PASSWORD!,
});

console.log('Taproot wallet created:', taprootWallet.walletMetadata.accountAddress);
// Output: bc1p...
```

> [!NOTE]
>
> A `password` is required when `backUpToDynamic` is `true`. You need the same password for every later signing or export call.

> [!NOTE]
>
> `walletMetadata.accountAddress` is always the wallet's mainnet address (`bc1q...` or `bc1p...`), even if you plan to use the wallet on testnet. Keep the full `walletMetadata` object: you pass it to `signMessage`, `signTransaction` and `exportPrivateKey`. To get the testnet address, see [Step 6](#step-6-derive-the-bitcoin-address).

## Step 4: Handle Errors Gracefully

Always implement proper error handling for Bitcoin wallet creation:

```typescript theme={"system"}
try {
  const wallet = await createBtcWallet({
    thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
    addressType: BitcoinAddressType.NATIVE_SEGWIT,
    password: process.env.WALLET_PASSWORD!,
    onError: (error: Error) => {
      console.error('Wallet creation error:', error.message);
    },
  });
  console.log('BTC wallet created successfully:', wallet.walletMetadata.accountAddress);
} catch (error) {
  const message = error instanceof Error ? error.message : String(error);
  if (message.includes('invalid session')) {
    console.error('Invalid session ID - please re-authenticate');
  } else {
    console.error('BTC wallet creation failed:', message);
  }
}
```

## Step 5: Store Wallet Information Securely

After creating a Bitcoin wallet, you'll receive important information that should be stored securely:

```typescript theme={"system"}
const wallet = await btcClient.createWalletAccount({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  password: process.env.WALLET_PASSWORD!,
  backUpToDynamic: true,
  bitcoinConfig: {
    addressType: BitcoinAddressType.NATIVE_SEGWIT,
  },
});

// Store these securely in your database
const walletData = {
  walletMetadata: wallet.walletMetadata,
  publicKeyHex: wallet.publicKeyHex,
  createdAt: new Date().toISOString(),
};

// With backUpToDynamic: true, Dynamic holds the encrypted key share backup.
// If you set backUpToDynamic: false, also store wallet.externalServerKeyShares,
// encrypted, and never in plain text.
```

Store the full `walletMetadata` object, not only the address. Signing needs its derivation path and address type.

## Step 6: Derive the Bitcoin Address

Use `deriveAccountAddress()` to get the address for a specific network from the wallet's public key. The `network` parameter is required:

```typescript theme={"system"}
import { BitcoinAddressType, BitcoinNetwork } from '@dynamic-labs-wallet/core';

const { accountAddress: mainnetAddress } = btcClient.deriveAccountAddress({
  rawPublicKey: wallet.rawPublicKey,
  addressType: BitcoinAddressType.NATIVE_SEGWIT,
  network: BitcoinNetwork.MAINNET,
});
// bc1q... (same as wallet.walletMetadata.accountAddress)

const { accountAddress: testnetAddress } = btcClient.deriveAccountAddress({
  rawPublicKey: wallet.rawPublicKey,
  addressType: BitcoinAddressType.NATIVE_SEGWIT,
  network: BitcoinNetwork.TESTNET,
});
// tb1q... (fund this address from a testnet faucet)
```

## Best Practices

1. **Password Security**: Use strong, unique passwords for each Bitcoin wallet
2. **Error Handling**: Always handle potential errors during wallet creation with the `onError` callback
3. **Monitoring**: Log wallet creation events for audit purposes
4. **Backup Strategy**: Implement secure backup strategies for key shares with `backUpToDynamic: true`
5. **Address Type Selection**: Choose Native SegWit for most use cases; use Taproot for advanced privacy needs

## Bitcoin-Specific Considerations

### Address Type Selection

| Type | Enum Value | Best For |
| - | - | - |
| Native SegWit | `BitcoinAddressType.NATIVE_SEGWIT` | General use, lower fees |
| Taproot | `BitcoinAddressType.TAPROOT` | Privacy, smart contracts |

### Network Support

> [!NOTE]
>
> The SDK supports both **Bitcoin Mainnet** and **Testnet**. Use `BitcoinNetwork.MAINNET` for production and `BitcoinNetwork.TESTNET` for development and testing.
>
> You choose the network per call: `signMessage`, `signTransaction` and `deriveAccountAddress` all require a `network` argument. Creating a wallet does not depend on the network. See [Working with testnet](https://docs.dynamic.xyz/docs/node/btc/example-usage.md#working-with-testnet).

### Satoshis

Bitcoin uses **satoshis** as the smallest unit: `1 BTC = 100,000,000 satoshis`.

## Next Steps

Now that you've created a Bitcoin wallet, you can:

* [Sign Bitcoin transactions](https://docs.dynamic.xyz/docs/node/btc/sign-transactions.md)
* [Sign Bitcoin messages](https://docs.dynamic.xyz/docs/node/btc/sign-messages.md)
* [Import existing Bitcoin private keys](https://docs.dynamic.xyz/docs/node/btc/import-private-keys.md)
* [Use imported Bitcoin wallets](https://docs.dynamic.xyz/docs/node/btc/use-imported-wallets.md)


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