Sats Connect - Wallet API for Bitcoin & Stacks
  • Introduction
  • Wallet Providers
    • getInfo
    • getProviders & getProviderById
  • Connecting to the wallet
    • Connect to Xverse Wallet
    • Disconnect from Xverse Wallet
    • Connect to other wallets
      • Manage a user's default wallet
    • [Legacy ⚠️] getAccounts
  • Wallet Methods
    • request methods
    • wallet_getAccount
    • wallet_getNetwork
    • wallet_changeNetwork
    • Xverse Custom Methods
  • Xverse Wallet Permissions
  • Xverse Wallet events
  • BITCOIN METHODS
    • 🟠getAddresses
    • 🟠signMessage
    • 🟠signPsbt
    • 🟠sendTransfer
    • 🟠signMultipleTransactions
    • 🟠getBalance
    • 🎨createInscription
    • 🎨createRepeatInscriptions
    • 🎨ord_getInscriptions
    • 🎨ord_sendInscriptions
    • 🔲runes_getBalance
    • 🔲runes_transfer
    • 🔲Mint Runes
      • runes_estimateMint
      • runes_mint
    • 🔲Etch Runes
      • runes_estimateEtch
      • runes_etch
    • 🔲runes_getOrder
    • 🔲Speed up a Rune Mint or Etch order
      • 🔲runes_estimateRbfOrder
      • 🔲runes_rbfOrder
  • STACKS METHODS
    • 🔴stx_getAccounts
    • 🔴stx_signMessage
    • 🔴stx_signStructuredMessage
    • 🔴stx_transferStx
    • 🔴stx_signTransaction
    • 🔴stx_callContract
    • 🔴stx_deployContract
  • GUIDES
    • Verify Bitcoin message signatures
    • Creating Bitcoin PSBTs
    • 📱Mobile Integration
    • Next.js support
  • RESOURCES
    • App Template
    • Demo App
    • Changelog
    • Github Issues
    • Developer forum
    • BIP322
Powered by GitBook
On this page
  • Creating a transaction with a wrapped-segwit (P2SH-P2WPHK) address
  • Creating a transaction with a native-segwit (P2WPHK) address
  • Creating a transaction with a Taproot (P2TR) address
  1. GUIDES

Creating Bitcoin PSBTs

PreviousVerify Bitcoin message signaturesNextMobile Integration

Last updated 3 months ago

PSBTs or partially signed Bitcoin transactions is a standard that allows unsigned or partially signed transactions to be transported for signing by multiple parties.

Here we will show examples of creating partially signed Bitcoin transactions using the light-weight and audited Bitcoin javascript library .

Creating a transaction with a wrapped-segwit (P2SH-P2WPHK) address

import * as btc from '@scure/btc-signer'
import { hex, base64 } from '@scure/base'

// You can use any public Bitcoin API to retrieve unspent outputs
const output = {
  "tx_hash": "f39d37ec885de70c598648a2f80f103e1cdf34f7021ddfcb22216b7076169226",
  "block_height": 780179,
  "tx_input_n": -1,
  "tx_output_n": 1,
  "value": 300000,
  "ref_balance": 22681,
  "spent": false,
  "confirmations": 123,
  "confirmed": "2023-03-10T10:02:21Z",
  "double_spend": false
}

// in the below, use btc.TEST_NETWORK for testnet/signet or btc.NETWORK for mainnet
const publicKey = hex.encode("02818b7ff740a40f311d002123087053d5d9e0e1546674aedb10e15a5b57fd3985")
const p2wpkh = btc.p2wpkh(publicKey, btc.TEST_NETWORK);
const p2sh = btc.p2sh(p2wpkh, btc.TEST_NETWORK);

tx.addInput({
  txid: output.tx_hash,
  index: output.tx_output_n,
  witnessUtxo: {
    script: p2sh.script,
    amount: BigInt(output.value),
  },
  redeemScript: p2sh.redeemScript,
})

// You can add more inputs here as necessary

// Add outputs
const recipient = "tb1pzwa68q3udj0f7g5xtdakgecvf45dvssu66ry7y3at22w7vus20vq3sgw62"
const changeAddress = "2NBfRKCUpafbatj5gV9T82uau3igdSf9BXJ"

tx.addOutputAddress(recipient, BigInt(200000), btc.TEST_NETWORK)
tx.addOutputAddress(changeAddress, BigInt(80000), btc.TEST_NETWORK)

// Generate the base64 encoded PSBT that can be 
// passed to a compatible wallet for signing
const psbt = tx.toPSBT(0)
const psbtB64 = base64.encode(psbt0)

Creating a transaction with a native-segwit (P2WPHK) address

import * as btc from '@scure/btc-signer'
import { hex, base64 } from '@scure/base'

// You can use any public Bitcoin API to retrieve unspent outputs
const output = {
  "tx_hash": "f39d37ec885de70c598648a2f80f103e1cdf34f7021ddfcb22216b7076169226",
  "block_height": 780179,
  "tx_input_n": -1,
  "tx_output_n": 1,
  "value": 300000,
  "ref_balance": 22681,
  "spent": false,
  "confirmations": 123,
  "confirmed": "2023-03-10T10:02:21Z",
  "double_spend": false
}

// in the below, use btc.TEST_NETWORK for testnet/signet or btc.NETWORK for mainnet
const publicKey = hex.encode("02818b7ff740a40f311d002123087053d5d9e0e1546674aedb10e15a5b57fd3985")
const p2wpkh = btc.p2wpkh(publicKey, btc.TEST_NETWORK);

tx.addInput({
  txid: output.tx_hash,
  index: output.tx_output_n,
  witnessUtxo: {
    script: p2wpkh.script,
    amount: BigInt(output.value),
  },
})

// You can add more inputs here as necessary

// Add outputs
const recipient = "tb1pzwa68q3udj0f7g5xtdakgecvf45dvssu66ry7y3at22w7vus20vq3sgw62"
const changeAddress = "tb1q8dq9ql8p7lvh9m5w5njqa2x424fqydw64fxxen"

tx.addOutputAddress(recipient, BigInt(200000), btc.TEST_NETWORK)
tx.addOutputAddress(changeAddress, BigInt(80000), btc.TEST_NETWORK)

// Generate the base64 encoded PSBT that can be 
// passed to a compatible wallet for signing
const psbt = tx.toPSBT(0)
const psbtB64 = base64.encode(psbt0)

Creating a transaction with a Taproot (P2TR) address

import * as btc from '@scure/btc-signer'
import { hex, base64 } from '@scure/base'

// in the below, use btc.TEST_NETWORK for testnet/signet or btc.NETWORK for mainnet
const internalPubKey =
  hex.decode("b9907521ddb85e0e6a37622b7c685efbdc8ae53a334928adbd12cf204ad4e717")
const p2tr = btc.p2tr(internalPubKey, undefined, btc.TEST_NETWORK)

tx.addInput({
  txid: output.tx_hash,
  index: output.tx_output_n,
  witnessUtxo: {
    script: p2tr.script,
    amount: BigInt(output.value),
  },
  tapInternalKey: internalPubKey,
  sighashType: btc.SigHash.ALL
})

// You can add more inputs here as necessary

// Add outputs
const recipient = "tb1pzwa68q3udj0f7g5xtdakgecvf45dvssu66ry7y3at22w7vus20vq3sgw62"
const changeAddress = "2NBfRKCUpafbatj5gV9T82uau3igdSf9BXJ"

tx.addOutputAddress(recipient, BigInt(200000), btc.TEST_NETWORK)
tx.addOutputAddress(changeAddress, BigInt(80000), btc.TEST_NETWORK)

// Generate the base64 encoded PSBT that can be 
// passed to a compatible wallet for signing
const psbt = tx.toPSBT(0)
const psbtB64 = base64.encode(psbt0)

scure-btc-signer