# Bitcoin

## Asigna Bitcoin Connect SDK

The **Asigna SDK** allows you to connect user multisig wallets directly to your Bitcoin application, seamlessly embedding it within the Asigna interface. This SDK provides the full logic required to connect a user's multisig wallet, build, sign, and execute a Partially Signed Bitcoin Transaction (PSBT), as well as sign messages and verify signatures. Within the Asigna SDK, the [BitcoinJS Lib](https://www.npmjs.com/package/bitcoinjs-lib/v/6.0.1) package is used for PSBTs.

## Installation

To install the Bitcoin Connect SDK, run:

```bash
npm install @asigna/btc-connect
```

## Workflow

### 1. Navigate to the Asigna Web Interface

Navigate to the Asigna web interface at <https://btc.asigna.io>.\
If you don’t already have a multisig wallet, create one to connect it to your Bitcoin application on your desired network. Open Apps and click `Add Custom App`.

### 2. Connect Bitcoin Application to the Asigna Multisig

To connect your application (similar to other Bitcoin wallets), use the **`useAsignaConnect`**&#x68;ook:

* **`connect()`** - opens the connection modal:

```javascript
const { connect } = useAsignaConnect();

const asignaAuthRequest = async () => {
  const info = await connect();
  // Save account data to storage
  localStorage.setItem('accountData', info);
  console.log(info);
};
```

* **`disconnect()`** - disconnects the multisig SDK from your application:

```javascript
const { disconnect } = useAsignaConnect();

const disconnectRequest = () => {
  disconnect();
  // Clear connected account data
  localStorage.setItem('accountData', undefined);
  console.log(info);
};
```

### 3. Retrieve Multisig Information

* **`useAsignaAddress`** - returns the connected multisig address:

```javascript
const { asignaAddress } = useAsignaAddress();
```

* **`useAsignaSafeInfo`** - returns connected multisig data:

```javascript
{
  address: string,
  threshold: number,
  multisigType: 'WSH' | 'TAPROOT' | 'HARDWARE_WSH',
  users: [
    {
      address: string;
      publicKey?: string;
      xPub?: string;
      fingerPrint?: string;
      derivation?: string;
    }
  ],
  psbtInputConstructionFields: {
    witnessUtxo: {
      script: Buffer;
    },
    tapLeafScript: [
      {
        leafVersion: number;
        script: Buffer;
        controlBlock: Buffer;
      }
    ],
    witnessScript: {
      script: Buffer,
    }
  }
}
```

**Example:**

```javascript
const { asignaSafeInfo } = useAsignaSafeInfo();
console.log('Connected:', asignaSafeInfo);
```

### 4. UI Modals for Signing PSBT or Messages

To display UI modals for signing a PSBT or message and wait for signatures, use the `<AsignaSignActionModals />` component:

```javascript
// openSignMessage and openSignPsbt calls are async
// You can await them directly in your async functions
// e.g., await openSignMessage(message);

function App() {
  return (
    <div>
      <AsignaSignActionModals
        onSignPsbt={(tx) => {
          console.log('PSBT Signature:', tx);
        }}
        onSignMessage={(signature) => {
          console.log('Message Signature:', signature);
          if (!asignaSafeInfo) return;
          
          console.log(
            'Is valid:', validateMessage(
              message,
              signature,
              asignaSafeInfo.multisigType, 
              asignaSafeInfo.address,
              asignaSafeInfo.users.map((x) => x.publicKey || ''),
              asignaSafeInfo.users.map((x) => x.address), 
              asignaSafeInfo.threshold,
              bitcoin.networks.testnet
            )
          );
        }}
      />
    </div>
  );
}
```

### 5. Sign Messages

Multisig wallets don't have a single private key to sign messages. Therefore, multiple owners must sign, and their signatures are merged for verification.

* **`openSignMessage(message: string)`** - opens the modal to sign a message:

```javascript
const { openSignMessage } = useAsignaConnect();

<div onClick={async () => await openSignMessage(message)}>
  Open Sign Message Modal
</div>
```

* **`signMessage(message: string)`** - requests a message signature without waiting for the modal:

```javascript
const { signMessage } = useAsignaConnect();

<div onClick={async () => await signMessage(message)}>
  Sign message without waiting for merged signature
</div>
```

* **`validateMessage`** - validates the message signature using the full multisig construction information:

```javascript
import { validateMessage, useAsignaSafeInfo } from '@asigna/core;

const { asignaSafeInfo } = useAsignaSafeInfo();
const message = 'test message';
const signature = await signMessage(message);

const isValid = validateMessage(
  message,
  signature,
  asignaSafeInfo.multisigType, 
  asignaSafeInfo.address,
  asignaSafeInfo.users.map((x) => x.publicKey || ''),
  asignaSafeInfo.users.map((x) => x.address), 
  asignaSafeInfo.threshold,
  bitcoin.networks.testnet
);
```

### 6. Create Transactions

To create a multisig PSBT, it's crucial to correctly add inputs and calculate fees:

* **`useAsignaFee`** - calculates gas:

```javascript
const { calculateGas } = useAsignaFee();
```

* **`useAsignaInputs`** - maps UTXOs to PSBT inputs based on the multisig type:

```javascript
const { createInput } = useAsignaInputs();
```

**Example:**

```javascript
const { createInput } = useAsignaInputs();
const { calculateGas } = useAsignaFee();
const { asignaAddress } = useAsignaAddress();

function createTx() {
  if (!utxos || !asignaAddress) return;

  const psbt = new bitcoin.Psbt({ network: bitcoin.networks.testnet });
  let totalOutput = 0;

  utxos.forEach((utxo) => {
    const input = createInput(utxo);
    if (!input) return;
    psbt.addInput(input.data);
    totalOutput += input.utxo.satoshis;
  });

  const FEE_RATE = 5;
  const fee = (calculateGas(psbt) || 0) * FEE_RATE;
  const amountToSend = BigNumber(amount).shiftedBy(8);

  psbt.addOutput({ value: amountToSend.toNumber(), address });
  psbt.addOutput({
    value: totalOutput - amountToSend.toNumber() - fee,
    address: asignaAddress
  });

  openSignPsbt(psbt);
}
```

### 7. Sign PSBT

A PSBT requires multiple owner signatures, which may take time. There are two signing options:

* **`signPsbt(psbt: bitcoin.Psbt)`** - creates a transaction for signature gathering in the multisig queue (does not return the signed PSBT):

```javascript
const { signPsbt } = useAsignaConnect();
```

* **`openSignPsbt(psbt: bitcoin.Psbt, options: {execute?: boolean, customBroadcastUrl?: string, onlyFinalize?: boolean})`** - opens a waiting modal until enough signatures are gathered and the signed PSBT is returned to the app. Execute flag can send the transaction to mempool once there's enough signatures gathered and returns the `txId` back to the application. **customBroadcastUrl** overrides the mempool API URL for broadcasting transactions. The **onlyFinalize** flag finalizes the signed PBST but is ignored if execute=true.&#x20;

```javascript
const { openSignPsbt } = useAsignaConnect();
```

This method is recommended when the application needs to retrieve the signed PSBT, otherwise better to use the `signPsbt` approach.

* **`openSignBtcAmount(data: {amountInSats: number, recipient: string, network: string}, execute?: boolean, customBroadcastUrl?: string)`** - opens a waiting modal until enough signatures are gathered and the signed PSBT is returned to the app. The execute flag can send the transaction to the mempool once sufficient signatures are collected, returning the txId to the application. **customBroadcastUrl** overrides the mempool API URL for broadcasting transactions.

```javascript
const { openSignBtcAmount } = useAsignaConnect();
```

The send BTC method is recommended when the application needs to transfer BTC over the network without requiring complex PSBT construction..

### 8. Demo application

A simple app which has all the integration features can be found here:

{% embed url="<https://github.com/Asigna/asigna-btc-connect-demo>" %}

It is also deployed at <https://asigna-btc-connect-demo.vercel.app/>.&#x20;
