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

# Sign a Partially Signed Bitcoin Transaction (PSBT)

# Guide to Creating a Partially Signed Bitcoin Transaction (PSBT) for Developers

This guide will walk you through the steps to create and sign a Partially Signed Bitcoin Transaction (PSBT) using a combination of JavaScript libraries and React components. The provided code example is comprehensive, but we'll break it down step-by-step to ensure you understand each part.

## Table of Contents

1. [Understanding Partially Signed Bitcoin Transactions (PSBT)](#1-understanding-partially-signed-bitcoin-transactions-psbt)
2. [Step-by-Step Guide](#2-step-by-step-guide)
   * [Step 1: Import Necessary Libraries and Functions](#step-1-import-necessary-libraries-and-functions)
   * [Step 2: Initialize the ECC Library](#step-2-initialize-the-ecc-library)
   * [Step 3: Define Constants and Helper Functions](#step-3-define-constants-and-helper-functions)
   * [Step 4: Generate the PSBT](#step-4-generate-the-psbt)
   * [Step 5: Create the SignMessageViaTransaction Component](#step-5-create-the-signmessageviatransaction-component)
   * [Step 6: Create the Main Component](#step-6-create-the-main-component)
3. [Full Code Example](#3-full-code-example)

***

## 1. Understanding Partially Signed Bitcoin Transactions (PSBT)

A Partially Signed Bitcoin Transaction (PSBT) is a standard format for handling Bitcoin transactions that require multiple signatures or other complex signing workflows. PSBTs enable the separation of transaction creation and signing, allowing for more flexible and secure transaction management.

### Key Features of PSBT

* **Interoperability**: PSBTs can be used across different wallets and software.
* **Flexibility**: Allows for multiple parties to contribute signatures to a single transaction.
* **Security**: Enhances security by enabling hardware wallets and other secure devices to sign transactions without exposing private keys.

***

## 2. Step-by-Step Guide to Creating a PSBT

This section provides a detailed step-by-step guide to creating a PSBT using the `bitcoinjs-lib` library in JavaScript. We'll break down each part of the provided code example and explain what it does.

### Step 1: Import Necessary Libraries and Functions

First, we import the necessary libraries and helper functions for working with Bitcoin transactions, data conversions, hashing, elliptic curve cryptography, and React components.

* **bitcoinjs-lib**: A popular JavaScript library for working with Bitcoin transactions.
* **@stacks/common**: Provides utility functions for handling data conversions.
* **@noble/hashes/sha256**: Implements the SHA-256 hashing algorithm.
* **@bitcoinerlab/secp256k1**: Provides elliptic curve cryptography functions for Bitcoin.
* **@dynamic-labs/sdk-react-core**: Provides context for accessing wallet information.
* **@dynamic-labs/wallet-connector-core**: Checks if the wallet connector is a Bitcoin connector.
* **useState**: A React hook for managing state in a functional component.

```javascript
import { DynamicWidget, useDynamicContext } from "@dynamic-labs/sdk-react-core";
import { isBitcoinWallet } from '@dynamic-labs/bitcoin';

import * as bitcoin from 'bitcoinjs-lib';
import { hexToBytes, utf8ToBytes } from '@stacks/common';
import { sha256 } from '@noble/hashes/sha256';
import ecc from '@bitcoinerlab/secp256k1';
import { useState } from "react";
```

### Step 2: Initialize the ECC Library

Before we can work with elliptic curve cryptography (ECC) functions in Bitcoin transactions, we need to initialize the ECC library. This step is crucial for enabling cryptographic operations such as signing and verifying transactions.

**bitcoin.initEccLib(ecc);**

* **Purpose**: The `bitcoinjs-lib` library relies on an ECC library to perform cryptographic operations. By default, `bitcoinjs-lib` does not include an ECC library to keep the core library lightweight and modular. We need to explicitly provide an ECC implementation.
* **Library Used**: In this example, we use the `@bitcoinerlab/secp256k1` library, which is an implementation of the secp256k1 elliptic curve, commonly used in Bitcoin.
* **Initialization**: We pass the `ecc` object from the `@bitcoinerlab/secp256k1` library to the `bitcoin.initEccLib` function to initialize the ECC library. This allows `bitcoinjs-lib` to use the ECC functions provided by the `@bitcoinerlab/secp256k1` library.

```javascript
bitcoin.initEccLib(ecc);
```

### Step 3: Define Constants and Helper Functions

Next, we define some constants and helper functions that will be used throughout the process. These include a message tag for BIP-322, a hashed version of this tag, and values for a dummy transaction input.

#### BIP-322 Message Tag and Hash

**BIP-322** is a Bitcoin Improvement Proposal that defines a standard way to sign and verify arbitrary messages using Bitcoin keys. To ensure the message being signed is unique and recognizable as a BIP-322 message, a specific tag (`bip322MessageTag`) is used. This tag is hashed twice using SHA-256 to create a unique identifier (`messageTagHash`).

```javascript
const bip322MessageTag = 'BIP0322-signed-message';

const messageTagHash = Uint8Array.from([
  ...sha256(utf8ToBytes(bip322MessageTag)),
  ...sha256(utf8ToBytes(bip322MessageTag)),
]);
```

#### Dummy Transaction Input Values

The `bip322TransactionToSignValues` object contains placeholder values for a previous transaction output. These values are used to construct a virtual transaction that is not actually spending real Bitcoins but is required to prepare the PSBT.

* **prevoutHash**: A 32-byte array of zeros, representing the hash of a non-existent previous transaction.
* **prevoutIndex**: Set to `0xffffffff`, a special value indicating that this is not a real transaction output.
* **sequence**: Set to `0`, indicating the sequence number of the transaction input.

```javascript
export const bip322TransactionToSignValues = {
  prevoutHash: hexToBytes('0000000000000000000000000000000000000000000000000000000000000000'),
  prevoutIndex: 0xffffffff,
  sequence: 0,
};
```

#### Hashing the BIP-322 Message

The `hashBip322Message` function takes a message (as a `Uint8Array` or a string) and hashes it using the SHA-256 algorithm, along with the `messageTagHash`. This ensures that the message is uniquely identified as a BIP-322 message.

```javascript
export function hashBip322Message(message) {
  return sha256(
    Uint8Array.from([...messageTagHash, ...(isString(message) ? utf8ToBytes(message) : message)])
  );
}

function isString(value) {
  return typeof value === 'string';
}
```

### Step 4: Generate the PSBT

The `generatePsbt` function creates a Partially Signed Bitcoin Transaction (PSBT) using the provided address and message.

#### Step-by-Step Explanation:

1. **Generate Script**: Convert the Bitcoin address into a scriptPubKey. This script is used to determine the conditions under which the Bitcoin can be spent.
2. **Hash the Message**: Hash the message using the BIP-322 message hash function. This ensures the message is uniquely identified and securely hashed.
3. **Create ScriptSig**: Create the scriptSig with the hashed message. The scriptSig is part of the transaction input and contains the conditions required to spend the UTXO.
4. **Virtual Transaction**: Create a virtual transaction to spend, setting the necessary inputs and outputs. This virtual transaction simulates spending a UTXO without actually spending real Bitcoins.
5. **Create PSBT**: Create a PSBT object and add the necessary inputs and outputs. This PSBT will be signed by the wallet.

```javascript
const generatePsbt = (address, message) => {
  const { prevoutHash, prevoutIndex, sequence } = bip322TransactionToSignValues;

  // Generate the script for the given address
  const script = bitcoin.address.toOutputScript(
    address,
    bitcoin.networks.bitcoin
  );

  // Hash the message
  const hash = hashBip322Message(message);

  // Create the scriptSig with the hashed message
  const commands = [0, Buffer.from(hash)];
  const scriptSig = bitcoin.script.compile(commands);

  // Create a virtual transaction to spend
  const virtualToSpend = new bitcoin.Transaction();
  virtualToSpend.version = 0;
  virtualToSpend.addInput(Buffer.from(prevoutHash), prevoutIndex, sequence, scriptSig);
  virtualToSpend.addOutput(script, 0);

  // Create the PSBT
  const virtualToSign = new bitcoin.Psbt({ network: bitcoin.networks.bitcoin });
  virtualToSign.setVersion(0);
  const prevTxHash = virtualToSpend.getHash();
  const prevOutIndex = 0;
  const toSignScriptSig = bitcoin.script.compile([bitcoin.script.OPS.OP_RETURN]);
  try {
    virtualToSign.addInput({
      hash: prevTxHash,
      index: prevOutIndex,
      sequence: 0,
      witnessUtxo: { script, value: 0 },
    });
  } catch (e) {
    console.log(e);
    throw e;
  }



 virtualToSign.addOutput({ script: toSignScriptSig, value: 0 });
  return virtualToSign.toBase64();
}
```

### Step 5: Create the SignMessageViaTransaction Component

The `SignMessageViaTransaction` component handles the interaction with the wallet to sign the PSBT.

#### Step-by-Step Explanation:

1. **useDynamicContext**: Hook to access the primary wallet from the context. This provides information about the connected wallet.
2. **useState**: React hook to manage the message state. This allows us to keep track of the message that we want to sign.
3. **Check Wallet Connector**: Ensure the wallet connector supports Bitcoin. If the wallet does not support Bitcoin, we return `null` and do not render the component.
4. **signMessageViaTransaction**: Function to generate the PSBT, request the wallet to sign it, and handle the signed PSBT. This function includes:
   * **Get Address**: Get the Bitcoin address from the wallet.
   * **Generate PSBT**: Call the `generatePsbt` function to create the PSBT.
   * **Sign PSBT**: Request the wallet to sign the PSBT using the provided parameters.
   * **Handle Signed PSBT**: Log the signed PSBT or handle any errors that occur during signing.

```javascript
const SignMessageViaTransaction = () => {
  const { primaryWallet } = useDynamicContext();
  const [message, setMessage] = useState('Hello World');

  if (!isBitcoinWallet(primaryWallet)) return null;

  const signMessageViaTransaction = async () => {
    // Get the Bitcoin address from the wallet
    const address = await primaryWallet.getAddress();

    // Generate the PSBT
    const psbt = generatePsbt(address, message);

    // Define the parameters for signing the PSBT
    const params = {
      allowedSighash: [1], // Only allow SIGHASH_ALL
      unsignedPsbtBase64: psbt, // The unsigned PSBT in Base64 format
      signature: [{
        address, // The address that is signing
        signingIndexes: [0] // The index of the input being signed
      }]
    };

    try {
      // Request the wallet to sign the PSBT
      const signedPsbt = await primaryWallet.signPsbt(params);
      console.log(signedPsbt); // Log the signed PSBT
    } catch (e) {
      console.log(e); // Handle any errors that occur during signing
    }
  }

  return (
    <div>
      <button onClick={signMessageViaTransaction}>Sign Transaction Via Message</button>
    </div>
  )
}
```

### Step 6: Create the Main Component

The `Main` component renders the `DynamicWidget` for wallet connection and the `SignMessageViaTransaction` component.

#### Step-by-Step Explanation:

1. **DynamicWidget**: This component handles the wallet connection UI, allowing users to connect their wallets.
2. **SignMessageViaTransaction**: This component handles the signing of the PSBT via the connected wallet.

```javascript
const Main = () => {
  return (
    <div className="min-h-screen bg-gradient-to-b from-gray-900 to-black flex flex-col items-center justify-center text-white">
      <DynamicWidget />
      <SignMessageViaTransaction />
    </div>
  );
}

export default Main;
```

***

## Full Code Example

Here is the full code example that incorporates all the steps explained above:

```javascript
import { DynamicWidget, useDynamicContext } from "@dynamic-labs/sdk-react-core";
import { isBitcoinWallet } from '@dynamic-labs/bitcoin';

import * as bitcoin from 'bitcoinjs-lib';
import { hexToBytes, utf8ToBytes } from '@stacks/common';
import { sha256 } from '@noble/hashes/sha256';
import ecc from '@bitcoinerlab/secp256k1';
import { useState } from "react";

bitcoin.initEccLib(ecc);

function isString(value) {
  return typeof value === 'string';
}

const bip322MessageTag = 'BIP0322-signed-message';

const messageTagHash = Uint8Array.from([
  ...sha256(utf8ToBytes(bip322MessageTag)),
  ...sha256(utf8ToBytes(bip322MessageTag)),
]);

export const bip322TransactionToSignValues = {
  prevoutHash: hexToBytes('0000000000000000000000000000000000000000000000000000000000000000'),
  prevoutIndex: 0xffffffff,
  sequence: 0,
};

export function hashBip322Message(message) {
  return sha256(
    Uint8Array.from([...messageTagHash, ...(isString(message) ? utf8ToBytes(message) : message)])
  );
}

const generatePsbt = (address, message) => {
  const { prevoutHash, prevoutIndex, sequence } = bip322TransactionToSignValues;

  // Generate the script for the given address
  const script = bitcoin.address.toOutputScript(
    address,
    bitcoin.networks.bitcoin
  );

  // Hash the message
  const hash = hashBip322Message(message);

  // Create the scriptSig with the hashed message
  const commands = [0, Buffer.from(hash)];
  const scriptSig = bitcoin.script.compile(commands);

  // Create a virtual transaction to spend
  const virtualToSpend = new bitcoin.Transaction();
  virtualToSpend.version = 0;
  virtualToSpend.addInput(Buffer.from(prevoutHash), prevoutIndex, sequence, scriptSig);
  virtualToSpend.addOutput(script, 0);

  // Create the PSBT
  const virtualToSign = new bitcoin.Psbt({ network: bitcoin.networks.bitcoin });
  virtualToSign.setVersion(0);
  const prevTxHash = virtualToSpend.getHash();
  const prevOutIndex = 0;
  const toSignScriptSig = bitcoin.script.compile([bitcoin.script.OPS.OP_RETURN]);

  try {
    virtualToSign.addInput({
      hash: prevTxHash,
      index: prevOutIndex,
      sequence: 0,
      witnessUtxo: { script, value: 0 },
    });
  } catch (e) {
    console.log(e);
    throw e;
  }

  virtualToSign.addOutput({ script: toSignScriptSig, value: 0 });
  return virtualToSign.toBase64();
}

const SignMessageViaTransaction = () => {
  const { primaryWallet } = useDynamicContext();
  const [message, setMessage] = useState('Hello World');

  if (!isBitcoinWallet(primaryWallet)) {
    return null;
  }

  const signMessageViaTransaction = async () => {
    // Get the Bitcoin address from the wallet
    const address = await primaryWallet.address;

    // Generate the PSBT
    const psbt = generatePsbt(address, message);

    // Define the parameters for signing the PSBT
    const params = {
      allowedSighash: [1], // Only allow SIGHASH_ALL
      unsignedPsbtBase64: psbt, // The unsigned PSBT in Base64 format
      signature: [{
        address, // The address that is signing
        signingIndexes: [0] // The index of the input being signed
      }]
    };

    try {
      // Request the wallet to sign the PSBT
      const signedPsbt = await primaryWallet.signPsbt(params);
      console.log(signedPsbt); // Log the signed PSBT
    } catch (e) {
      console.log(e); // Handle any errors that occur during signing
    }
  }

  return (
    <div>
      <button onClick={signMessageViaTransaction}>Sign Transaction Via Message</button>
    </div>
  )
}

const Main = () => {
  return (
    <div className="min-h-screen bg-gradient-to-b from-gray-900 to-black flex flex-col items-center justify-center text-white">
      <DynamicWidget />
      <SignMessageViaTransaction />
    </div>
  );
}

export default Main;
```
