Skip to content

Bitcoin Chain

The Bitcoin chain implementation in Signet.js provides support for both Bitcoin mainnet and testnet networks, with a focus on P2WPKH (Native SegWit) transactions.

Overview

The Bitcoin implementation allows you to:

  • Generate addresses and public keys
  • Check balances
  • Prepare, sign, and broadcast transactions
  • Work with UTXOs (Unspent Transaction Outputs)

Complete Transaction Example

Below is a complete example of sending a transaction on the Bitcoin network using Signet.js:

import { Bitcoin, BTCRpcAdapters } from 'signet.js'
import { utils } from 'signet.js'
import { createPublicClient, createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { sepolia } from 'viem/chains'
 
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
 
const publicClient = createPublicClient({
  chain: sepolia,
  transport: http(),
})
 
const walletClient = createWalletClient({
  account,
  chain: sepolia,
  transport: http(),
})
 
const chainSigContract = new utils.chains.evm.ChainSignatureContract({
  publicClient,
  walletClient,
  contractAddress: utils.constants.CONTRACT_ADDRESSES.ETHEREUM
    .TESTNET_DEV as `0x${string}`,
})
 
const btcRpcAdapter = new BTCRpcAdapters.Mempool('https://mempool.space/api')
 
const bitcoin = new Bitcoin({
  network: 'testnet',
  contract: chainSigContract,
  btcRpcAdapter,
})
 
const path = 'btc'
const predecessorId = walletClient.account.address
 
const { address: from, publicKey } = await bitcoin.deriveAddressAndPublicKey(
  predecessorId,
  path
)
 
const { balance, decimals } = await bitcoin.getBalance(from)
 
const { transaction, hashesToSign } =
  await bitcoin.prepareTransactionForSigning({
    from,
    to: 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx',
    value: '0.001', // 0.001 BTC
    publicKey,
  })
 
const rsvSignature = await chainSigContract.sign({
  payload: hashesToSign[0],
  path,
  key_version: 0,
})
 
const tx = bitcoin.finalizeTransactionSigning({
  transaction,
  rsvSignatures: [rsvSignature],
})
 
const txHash = await bitcoin.broadcastTx(tx)

Supported Networks

You can use different Bitcoin networks by specifying the network parameter:

import { Bitcoin, BTCRpcAdapters } from 'signet.js'
 
const btcRpcAdapter = new BTCRpcAdapters.Mempool('https://mempool.space/api')
 
// Bitcoin Mainnet
const mainnetBitcoin = new Bitcoin({
  network: 'mainnet',
  contract: chainSigContract,
  btcRpcAdapter,
})
 
// Bitcoin Testnet
const testnetBitcoin = new Bitcoin({
  network: 'testnet',
  contract: chainSigContract,
  btcRpcAdapter,
})
 
// Bitcoin Regtest (for local development)
const regtestBitcoin = new Bitcoin({
  network: 'regtest',
  contract: chainSigContract,
  btcRpcAdapter,
})

RPC Adapter

The RPC adapter is a class that provides an interface for interacting with the Bitcoin network. It handles essential operations such as:

  • Fetching UTXOs (Unspent Transaction Outputs)
  • Retrieving transaction details
  • Getting current network fees
  • Broadcasting transactions
  • Querying address balances

The adapter abstracts away the complexity of different Bitcoin API providers, allowing you to easily switch between services like Mempool.space, BlockCypher, or your own Bitcoin node.

For detailed implementation and configuration options, see the RPC Adapter documentation.

Types

The following types are used on the Bitcoin chain:

import type * as bitcoin from 'bitcoinjs-lib'
 
export interface BTCTransaction {
  vout: Array<{
    scriptpubkey: string
    value: number
  }>
}
 
export interface BTCInput {
  txid: string
  vout: number
  value: number
  scriptPubKey: Buffer
}
 
export type BTCOutput =
  | {
      value: number
    }
  | { address: string; value: number }
  | { script: Buffer; value: number }
 
export type BTCTransactionRequest = {
  publicKey: string
} & (
  | {
      inputs: BTCInput[]
      outputs: BTCOutput[]
      from?: never
      to?: never
      value?: never
    }
  | {
      inputs?: never
      outputs?: never
      from: string
      to: string
      value: string
    }
)
 
export interface BTCUnsignedTransaction {
  psbt: bitcoin.Psbt
  publicKey: string
}
 
export type BTCNetworkIds = 'mainnet' | 'testnet' | 'regtest'