# signPsbt

## Method name

`signPsbt`

## Parameters

<table><thead><tr><th width="169">Parameter</th><th width="348">Description</th><th width="96" data-type="checkbox">Required</th><th width="123">Type</th></tr></thead><tbody><tr><td>hex</td><td>Hex of PSBT payload for signing</td><td>true</td><td>string</td></tr><tr><td>allowedSighash</td><td>Sighash types allowed for signing and finalizing inputs (defaults to type ALL)</td><td>false</td><td>SignatureHash[]</td></tr><tr><td>signAtIndex</td><td>Input index(es) that should be signed (defaults to sign all inputs)</td><td>false</td><td>number | number[]</td></tr><tr><td>network</td><td>Network for signing: <code>mainnet</code>, <code>testnet</code>, <code>signet</code>, <code>sbtcDevenv</code> or <code>devnet</code></td><td>true</td><td>string</td></tr><tr><td>account</td><td>Index of account for signing (defaults to active account)</td><td>false</td><td>uint</td></tr><tr><td>broadcast</td><td>Whether to broadcast upon signing (default <code>false</code>). <code>txid</code>returned on successful broadcast.</td><td>false</td><td>boolean</td></tr></tbody></table>

## Example request

### Sign PSBT

<pre class="language-typescript"><code class="lang-typescript"><strong>interface SignPsbtRequestParams {
</strong>  hex: string;
  allowedSighash?: SignatureHash[];
  signAtIndex?: number | number[];
  network?: NetworkModes;         // default is user's current network
  account?: number;               // default is user's current account
  broadcast?: boolean;            // default is false - finalize/broadcast tx
}

const requestParams: SignPsbtRequestParams = { ...params };

const response = await window.LeatherProvider.request('signPsbt', requestParams);
</code></pre>

### Broadcast PSBT

Our API returns a PSBT back to the app, with the newly applied signatures. If your use-case is to spend the transaction immediately, you'll first need to `finalize` it, then broadcast it to the network.

See this example below how to extract a signed transaction from the PSBT

```typescript
import * as btc from '@scure/btc-signer';
const hex = response.result.hex;
const tx = btc.Transaction.fromPSBT(hexToBytes(hex));
tx.finalize();
await broadcast(tx.hex);
```

### Types and helper functions

```tsx
interface BitcoinNetwork {
  bech32: string;
  pubKeyHash: number;
  scriptHash: number;
  wif: number;
}

const bitcoinTestnet: BitcoinNetwork = {
  bech32: 'tb',
  pubKeyHash: 0x6f,
  scriptHash: 0xc4,
  wif: 0xef,
};

const ecdsaPublicKeyLength = 33;

function ecdsaPublicKeyToSchnorr(pubKey: Uint8Array) {
  if (pubKey.byteLength !== ecdsaPublicKeyLength) throw new Error('Invalid public key length');
  return pubKey.slice(1);
}

function getTaprootPayment(publicKey: Uint8Array) {
  return btc.p2tr(ecdsaPublicKeyToSchnorr(publicKey), undefined, bitcoinTestnet);
}
```

### Helper functions for Native SegWit `PsbtRequestOptions`

```tsx
// Example request options for Native SegWit
function buildNativeSegwitPsbtRequest(pubKey: Uint8Array): PsbtRequestOptions {
  // SegWit pubKey used here is provided through auth response
  const p2wpkh = btc.p2wpkh(pubKey, bitcoinTestnet);

  const tx = new btc.Transaction();

  // Example inputs with included witness
  tx.addInput({
    index: 0,
    txid: '15f34b3bd2aab555a003cd1c6959ac09b36239c6af1cb16ff8198cef64f8db9c',
    witnessUtxo: {
      amount: BigInt(1000),
      script: p2wpkh.script,
    },
  });
  tx.addInput({
    index: 1,
    txid: 'dca5179afaa63eae112d8a97794de2d30dd823315bcabe6d8b8a6b98e3567705',
    witnessUtxo: {
      amount: BigInt(2000),
      script: p2wpkh.script,
    },
  });
  
  // Add outputs and/or other psbt data...

  const psbt = tx.toPSBT();

  // This example is choosing to sign all inputs bc no index(es) are provided
  return { hex: bytesToHex(psbt) };
}
```

### Helper functions for Taproot `PsbtRequestOptions`

```tsx
// Similar example request options for Taproot
function buildTaprootPsbtRequest(pubKey: Uint8Array): PsbtRequestOptions {
  // Taproot pubKey used here is provided through auth response
  const payment = getTaprootPayment(pubKey);

  const tx = new btc.Transaction();

  tx.addInput({
    index: 0,
    tapInternalKey: payment.tapInternalKey,
    txid: '15f34b3bd2aab555a003cd1c6959ac09b36239c6af1cb16ff8198cef64f8db9c',
    witnessUtxo: {
      amount: BigInt(1000),
      script: payment.script,
    },
  });
  tx.addInput({
    index: 1,
    tapInternalKey: payment.tapInternalKey,
    txid: 'dca5179afaa63eae112d8a97794de2d30dd823315bcabe6d8b8a6b98e3567705',
    witnessUtxo: {
      amount: BigInt(2000),
      script: payment.script,
    },
  });
  
  // Add outputs and/or other psbt data...

  const psbt = tx.toPSBT();

  return { hex: bytesToHex(psbt) };
}
```

## Custom scripts

For more complex PSBTs, such as those using custom Bitcoin scripts, we recommend you read the supporting documentation of the `@scure/btc-signer` library.

[Bitcoin script examples →](https://github.com/paulmillr/scure-btc-signer?tab=readme-ov-file#script)

## Debugging

If you're running into issues signing a PSBT with Leather, the best way to debug the problem is to sign it without Leather.

Starting with a test-only mnemonic, drive a BTC address, and try sign the transaction. This helps ensure your PSBT is constructed correctly.

Here's a [Codesandbox with a PSBT debugging environment](https://codesandbox.io/p/sandbox/debug-leather-psbt-signing-x2349s) set up for you to test. When asking for PSBT signing support, provide a test case forked from this.&#x20;

## Preview

<figure><img src="https://2085786563-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F41U87FfDFo2dIKYr0ZNX%2Fuploads%2FxzH4T2l5x5nWpxS0NnFT%2FSCR-20240419-qtxp.png?alt=media&#x26;token=c6d5f052-801d-4e08-afe4-b4bc5e734c1b" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://leather.gitbook.io/developers/bitcoin-methods/signpsbt.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
