> For the complete documentation index, see [llms.txt](https://docs.stacks.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stacks.co/more-guides/verify-bitcoin-transactions-clarity.md).

# Verifying Bitcoin Transactions in Clarity

Trustlessly validate Bitcoin data on-chain.

<div data-with-frame="true"><figure><img src="https://284917788-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZz9BLmTU9oydDpL3qiUh%2Fuploads%2F3min6R8RyLETkoawFvsf%2Fbitcoin-clarity.png?alt=media&amp;token=f353204f-715c-4546-90a2-f69f9c5fe1d2" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Contracts on Clarity 6 (Epoch 4.0 and later) can use the native `get-bitcoin-tx-output?` and `verify-merkle-proof` with no external dependency; see [Native verification in Clarity 6](#native-verification-in-clarity-6). Contracts on earlier Clarity versions, and existing integrations, use `clarity-bitcoin-lib-v7` at `SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.clarity-bitcoin-lib-v7`, which the rest of this guide walks through.
{% endhint %}

## Intro

One of the unique features of the Stack chain and the Clarity language is that it allows for using read-only functions to trustlessly validate on-chain Bitcoin activity from Clarity smart contracts. This enables developers to build applications that **react to real Bitcoin activity** — such as deposits, transfers, and proofs of inclusion — without relying on off-chain indexers or oracles. In this guide, you’ll learn how to verify Bitcoin transactions in Clarity and safely bridge Bitcoin state into on-chain logic.

> *Knowledge of Bitcoin state: has knowledge of the full Bitcoin state; it can trustlessly read*\
> \&#xNAN;*Bitcoin transactions and state changes and execute smart contracts triggered by Bitcoin*\
> \&#xNAN;*transactions. The Bitcoin read functionality helps to keep the decentralized peg state*\
> \&#xNAN;*consistent with BTC locked on Bitcoin L1, amongst other things. **- Stacks Whitepaper***

### tl;dr

* We'll be using a popular smart contract `clarity-bitcoin-lib` to verify bitcoin transactions on-chain in Clarity.
* Allows contracts to enforce logic based on Bitcoin events—deposits, withdrawals, lockups, or multisig activity.
* Powers designs like wrapped assets, and deposits that mint or unlock value only after provable Bitcoin transactions.

### Steps

* Fetch bitcoin transaction metadata: block height and header, transaction hex, and the transaction's merkle proof of inclusion.
* Pass in transaction metadata as arguments to `clarity-bitcoin-lib` contract's `was-tx-mined-compact` read-only function.
* Returns `(ok <txid>)` if the proof checks out and the transaction is indeed mined in the specified Bitcoin block.

### Key Tools To Use

* [Clarity Bitcoin library](https://github.com/friedger/clarity-bitcoin): A Clarity library for parsing Bitcoin transactions and verifying Merkle proofs.
* [mempool.space APIs](https://mempool.space/docs/api/rest): Bitcoin explorer APIs used to fetch bitcoin transaction metadata.
* [Bitcoin Transaction Proof](https://github.com/kenrogers/bitcoin-tx-proof) \[optional]: A TypeScript library for generating Bitcoin transaction proofs, including witness data and merkle proofs.
* [Clarity Bitcoin Client](https://github.com/BigMarketDao/clarity-bitcoin-client) \[optional]: Clarity Bitcoin Client is an open-source TypeScript library for interacting with the `clarity-bitcoin-lib` contract on Stacks.

***

## Native verification in Clarity 6

The native path uses these functions:

| Function                                                                     | Does                                                                                                                         | Returns                                                                                                                                                  |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `(get-bitcoin-tx-output? tx-bytes vout)`                                     | Parses a serialized Bitcoin transaction, witness data included, and returns one output plus the canonical txid               | `(ok {script: (buff 1024), amount: uint, txid: (buff 32)})`, or `(err u1)` bad bytes, `(err u2)` `vout` out of range, `(err u3)` script over 1,024 bytes |
| `(verify-merkle-proof leaf-hash root-hash tx-index tx-count sibling-hashes)` | Checks a Bitcoin merkle inclusion proof with double SHA-256 and the odd-row duplication rule; `tx-count` pins the tree shape | `true` for a valid proof, `false` for anything else                                                                                                      |
| `(get-burn-block-info? header-hash height)`                                  | The hash of the Bitcoin block the Stacks chain recorded at `height`                                                          | `(some (buff 32))`, or `none` for a height the chain has not processed                                                                                   |

All 32-byte hashes go in internal byte order, the reverse of what block explorers display. The `txid` from `get-bitcoin-tx-output?` is already internal, so it feeds `verify-merkle-proof` directly. Transactions up to 1,048,576 bytes are accepted, against `(buff 4096)` for `was-tx-mined-compact`, and witness data does not have to be stripped first.

A read-only function that returns an output once it is proven to be in the Bitcoin block at `height`:

{% code title="btc-inclusion.clar" %}

```clarity
;; Clarinet.toml: clarity_version = 6, epoch = "latest"
(define-constant ERR_BAD_HEADER (err u100))
(define-constant ERR_HEADER_NOT_IN_CHAIN (err u101))
(define-constant ERR_TX_NOT_IN_BLOCK (err u102))

;; Errors u1 to u3 pass through from get-bitcoin-tx-output?.
(define-read-only (get-mined-output
    (height uint)
    (header (buff 80))
    (tx (buff 4096)) ;; raise this bound for larger transactions; the native accepts up to 1,048,576 bytes
    (vout uint)
    (tx-index uint)
    (tx-count uint)
    (siblings (list 24 (buff 32))))
  (let (
      (output (try! (get-bitcoin-tx-output? tx vout)))
      ;; Bytes 36 to 67 of an 80-byte header hold the merkle root, in internal byte order.
      (merkle-root (unwrap! (as-max-len? (unwrap! (slice? header u36 u68) ERR_BAD_HEADER) u32)
        ERR_BAD_HEADER)))
    ;; The header has to be the one the Stacks node recorded at that Bitcoin height.
    ;; pox-5 exposes this check as a read-only function.
    (asserts!
      (contract-call? 'SP000000000000000000002Q6VF78.pox-5 verify-block-header header height)
      ERR_HEADER_NOT_IN_CHAIN)
    ;; The txid has to hash up to that merkle root.
    (asserts!
      (verify-merkle-proof (get txid output) merkle-root tx-index tx-count siblings)
      ERR_TX_NOT_IN_BLOCK)
    (ok output)))
```

{% endcode %}

`verify-block-header` in pox-5 compares `(get-burn-block-info? header-hash height)` with the reversed double SHA-256 of the header you pass ([pox-5.clar L3663-L3671](https://github.com/stacks-network/stacks-core/blob/10474cdec9f9c0bdf05841b58cffc89cdad87a9b/stackslib/src/chainstate/stacks/boot/pox-5.clar#L3663-L3671)). Calling it saves you the byte-reversal helper. Everything else is the two Clarity 6 natives. Clarinet v3.24.1 rewrites `'SP000000000000000000002Q6VF78.pox-5` to its simnet twin in your sources, so `clarinet check` and your tests run against the bundled `pox-5` without editing the principal.

On the client, the same [mempool.space](https://mempool.space) endpoints as in the walkthrough supply the inputs, plus `tx_count` from the block:

{% code title="verify-native.ts" %}

```typescript
import { fetchCallReadOnlyFunction, bufferCV, uintCV, listCV, cvToString } from "@stacks/transactions"
import { hexToBytes } from "@stacks/common"
import mempoolJS from "@mempool/mempool.js"

const { bitcoin: { transactions, blocks } } = mempoolJS({ hostname: "mempool.space" })

const txid = "fb88309b4041f76bea0c196633c768dca82bb0dd424cbfe19be38569007f92d9"
const vout = 0

// The full transaction, witness data included. get-bitcoin-tx-output? strips it itself.
const txHex = await transactions.getTxHex({ txid })
// For this txid: block_height 928198, pos 3, 12 sibling hashes
const { block_height, merkle, pos } = await transactions.getTxMerkleProof({ txid })
const blockHash = await blocks.getBlockHeight({ height: block_height })
const blockHeader = await blocks.getBlockHeader({ hash: blockHash })
// tx_count 3684 for block 928198; ceil(log2(3684)) = 12, matching the proof length
const { tx_count } = await blocks.getBlock({ hash: blockHash })

const functionArgs = [
  uintCV(block_height),
  bufferCV(hexToBytes(blockHeader)),
  bufferCV(hexToBytes(txHex)),
  uintCV(vout),
  uintCV(pos),
  uintCV(tx_count),
  // mempool.space returns display-order hashes; the contract wants internal byte order
  listCV(merkle.map((h) => bufferCV(hexToBytes(h).reverse()))),
]

const result = await fetchCallReadOnlyFunction({
  contractAddress: "<deployer-address>", // placeholder: the address you deployed btc-inclusion.clar from
  contractName: "btc-inclusion",
  functionName: "get-mined-output",
  functionArgs,
  network: "mainnet",
  senderAddress: "SP1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRCBGD7R",
})

console.log(cvToString(result))
// (ok (tuple (amount u...) (script 0x...) (txid 0x...))) when the output is in block 928198
```

{% endcode %}

`height` has to be a Bitcoin height the Stacks chain has processed: at or after 666,050, the first burnchain block, and at or below the current `burn-block-height`. For an earlier or later height `get-burn-block-info?` returns `none` and the call fails with `ERR_HEADER_NOT_IN_CHAIN (u101)`.

This is the pattern pox-5 runs on every `register-for-bond` with native BTC lockups: `get-bitcoin-tx-output?` on the lockup transaction, `verify-block-header` on the supplied header, `verify-merkle-proof` on the txid, with its own error codes `ERR_INVALID_BTC_HEADER (u40)` and `ERR_INVALID_MERKLE_PROOF (u41)`. The staking SDK builds those proof arguments for you; see [buildLockProof](/reference/stacks.js/stacks-bitcoin-staking/proof/buildlockproof.md) and [Opening a bond position](/operate/protocol-bonds/opening-a-bond-position.md).

***

## Complete Code

If you want to jump straight to the full implementation, the complete working code used in this guide is shown below.

{% tabs %}
{% tab title="Main" %}
The below consists of the main client side code of preparing the bitcoin transaction metadata and passing them into a contract call to the `clarity-bitcoin-lib` contract.

{% code expandable="true" %}

```typescript
import {
  fetchCallReadOnlyFunction,
  bufferCV,
  uintCV,
  tupleCV,
  listCV,
  cvToString,
} from "@stacks/transactions"
import { hexToBytes } from "@stacks/common"
import { getTxHex, getTxMerkleProof, getBlkHeader, removeWitnessData } from "./fetch-bitcoin-data.js"

// Data of read-only function of below clarity-bitcoin-lib contract:
const contractAddress = "SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9"
const contractName = "clarity-bitcoin-lib-v7"
const functionName = "was-tx-mined-compact"

// Fetching btc tx metadata. You can replace this with any bitcoin transaction id.
let txid = "fb88309b4041f76bea0c196633c768dca82bb0dd424cbfe19be38569007f92d9"

// Fetching and returning non-witness tx hex
let fullTxHex = await getTxHex(txid)
let txHex = removeWitnessData(fullTxHex)
let { block_height, merkle, pos } = await getTxMerkleProof(txid)
let { blockHeader } = await getBlkHeader(block_height)

let txIndex = pos
let hashes = merkle.map(hash => bufferCV(hexToBytes(hash).reverse()))
let treeDepth = merkle.length

// Preparing arguments for clarity function call
let functionArgs = [
  // (height)
  uintCV(block_height),
  // (tx)
  bufferCV(Buffer.from(txHex, "hex")),
  // (header)
  bufferCV(Buffer.from(blockHeader, "hex")),
  // (proof)
  tupleCV({
    "tx-index": uintCV(txIndex),
    hashes: listCV(hashes),
    "tree-depth": uintCV(treeDepth)
  })
]

// Calling clarity read-only function
let result = await fetchCallReadOnlyFunction({
  contractAddress,
  contractName,
  functionName,
  functionArgs,
  network: 'mainnet',
  // this could be any principal address
  senderAddress: 'SP1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRCBGD7R'
})

// Logging results
console.log("Full tx hex: ", fullTxHex)
console.log("Non-witness tx hex: ", txHex)
console.log("Block height: ", block_height)
console.log("Block header: ", blockHeader)
console.log("Merkle proof hashes: ", merkle)
console.log("Transaction index in block: ", txIndex)
console.log("Merkle tree depth: ", treeDepth)
console.log("Was the transaction mined (from clarity-bitcoin)? ")
console.log(cvToString(result))
```

{% endcode %}
{% endtab %}

{% tab title="Helpers" %}
Helper functions to fetch the bitcoin transaction metadata from an explorer's API.

{% code title="fetch-bitcoin-data.js" expandable="true" %}

```typescript
import mempoolJS from "@mempool/mempool.js"
import { Transaction } from "bitcoinjs-lib"

// https://www.npmjs.com/package/@mempool/mempool.js
const {
  bitcoin: { transactions, blocks }
} = mempoolJS({
  hostname: "mempool.space"
})

export const getTxHex = async (txid: string) => {
  // Using mempool.space's GET /api/tx/:txid/hex
  const txHex = await transactions.getTxHex({ txid })

  return txHex
}

export const getTxMerkleProof = async (txid: string) => {
  // Using mempool.space's GET /api/tx/:txid/merkle-proof
  const { block_height, merkle, pos } = await transactions.getTxMerkleProof({ txid })

  return { block_height, merkle, pos }
}

export const getBlkHeader = async (height: number) => {
  // Using mempool.space's GET /api/block-height/:height
  let blockHash = await blocks.getBlockHeight({ height })

  // Using mempool.space's GET /api/block/:hash/header
  const blockHeader = await blocks.getBlockHeader({ hash: blockHash })

  return { blockHash, blockHeader }
}

// Function to remove witness data from a Bitcoin transaction hex
// `was-tx-mined-compact` requires non-witness transaction format
export const removeWitnessData = (txHex: string) => {
  const tx = Transaction.fromHex(txHex)

  if (!tx.hasWitnesses()) {
    return txHex
  }

  // Create a new empty transaction
  const newTx = new Transaction()

  // Copy version from original transaction
  newTx.version = tx.version

  // Copy inputs from original transaction
  tx.ins.forEach(input => {
    newTx.addInput(input.hash, input.index, input.sequence, input.script)
  })

  // Copy outputs from original transaction
  tx.outs.forEach(output => {
    newTx.addOutput(output.script, output.value)
  })

  // Copy locktime from original transaction
  newTx.locktime = tx.locktime

  return newTx.toHex()
}
```

{% endcode %}
{% endtab %}

{% tab title="Clarity Contract Preview" %}
This is a snippet of the contract function we invoke to verify a bitcoin transaction.

{% code title="clarity-bitcoin-lib.clar" expandable="true" %}

```clarity
;; --snip--

(define-read-only (was-tx-mined-compact
    (height uint)
    (tx (buff 4096))
    (header (buff 80))
    (proof {
      tx-index: uint,
      hashes: (list 14 (buff 32)),
      tree-depth: uint,
    })
  )
  (let ((block (unwrap! (parse-block-header header) (err ERR-BAD-HEADER))))
    (was-tx-mined-internal height tx header (get merkle-root block) proof)
  )
)

;; --snip--
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

## Walkthrough

{% stepper %}
{% step %}

#### Fetch bitcoin transaction metadata

Using mempool.space's APIs and with a bitcoin txid, fetch the required bitcoin transaction metadata needed for Clarity.

* Fetches the transaction hex
* Fetches the transaction merkle proof
* Fetches the block header
* Removes witness data from transaction hex

{% code title="fetch-bitcoin-data.ts" expandable="true" %}

```typescript
import mempoolJS from "@mempool/mempool.js"
import { Transaction } from "bitcoinjs-lib"

// https://www.npmjs.com/package/@mempool/mempool.js
const {
  bitcoin: { transactions, blocks }
} = mempoolJS({
  hostname: "mempool.space"
})

export const getTxHex = async (txid: string) => {
  // Using mempool.space's GET /api/tx/:txid/hex
  const txHex = await transactions.getTxHex({ txid })

  return txHex
}

export const getTxMerkleProof = async (txid: string) => {
  // Using mempool.space's GET /api/tx/:txid/merkle-proof
  const { block_height, merkle, pos } = await transactions.getTxMerkleProof({ txid })

  return { block_height, merkle, pos }
}

export const getBlkHeader = async (height: number) => {
  // Using mempool.space's GET /api/block-height/:height
  let blockHash = await blocks.getBlockHeight({ height })

  // Using mempool.space's GET /api/block/:hash/header
  const blockHeader = await blocks.getBlockHeader({ hash: blockHash })

  return { blockHash, blockHeader }
}

// Function to remove witness data from a Bitcoin transaction hex
// `was-tx-mined-compact` requires non-witness transaction format
export const removeWitnessData = (txHex: string) => {
  const tx = Transaction.fromHex(txHex)

  if (!tx.hasWitnesses()) {
    return txHex
  }

  // Create a new empty transaction
  const newTx = new Transaction()

  // Copy version from original transaction
  newTx.version = tx.version

  // Copy inputs from original transaction
  tx.ins.forEach(input => {
    newTx.addInput(input.hash, input.index, input.sequence, input.script)
  })

  // Copy outputs from original transaction
  tx.outs.forEach(output => {
    newTx.addOutput(output.script, output.value)
  })

  // Copy locktime from original transaction
  newTx.locktime = tx.locktime

  return newTx.toHex()
}
```

{% endcode %}

<details>

<summary>Are there libraries to help with fetching of the bitcoin transaction metadata?</summary>

There sure are. Here are two community-built libraries that can abstract away some of the complexities with gathering the bitcoin transaction metadata.

* [**Bitcoin Transaction Proof**](https://github.com/kenrogers/bitcoin-tx-proof) - A TypeScript library for generating Bitcoin transaction proofs, including witness data and merkle proofs.
* [**Clarity Bitcoin Client**](https://github.com/BigMarketDao/clarity-bitcoin-client) - A TypeScript library for interacting with the clarity-bitcoin-lib contract on Stacks.

</details>

<details>

<summary>Don't have a bitcoin transaction id?</summary>

Learn how to create and broadcast a bitcoin transaction on the frontend [here](/more-guides/verify-bitcoin-transactions-clarity/creating-btc-tx.md).

</details>
{% endstep %}

{% step %}

#### Prepare metadata as Clarity arguments

Let's circle back to the `was-tx-mined-compact` function of the `clarity-bitcoin-lib` contract for a second and analyze the order/type of parameters.

You can see that it intakes the parameters with a certain typing and order:

* `(height uint)` the block height you are looking to verify the transaction within
* `(tx (buff 1024))` the raw transaction hex of the transaction you are looking to verify
* `(header (buff 80))` the block header of the block
* `(proof { tx-index: uint, hashes: (list 14 (buff 32)), tree-depth: uint})` a merkle proof formatted as a Clarity tuple

In short, the `was-tx-mined-compact` function takes the block height, the transaction hex, the block header, and a merkle proof, and determines that:

* the block header corresponds to the block that was mined at the given Bitcoin height
* the transaction's merkle proof links it to the block header's merkle root.

{% hint style="info" %}
The current version of the `clarity-bitcoin-lib` is version 7. Click [here](https://explorer.hiro.so/txid/0xe433b35e95acfd24595e601860b4240cfaacd689ae7e7938a80c5505f186516b) for the deployed mainnet contract.
{% endhint %}

{% code title="clarity-bitcoin-lib.clar" %}

```clarity
;; --snip--

(define-read-only (was-tx-mined-compact
    (height uint)
    (tx (buff 4096))
    (header (buff 80))
    (proof {
      tx-index: uint,
      hashes: (list 14 (buff 32)),
      tree-depth: uint,
    })
  )
  (let ((block (unwrap! (parse-block-header header) (err ERR-BAD-HEADER))))
    (was-tx-mined-internal height tx header (get merkle-root block) proof)
  )
)

;; --snip--
```

{% endcode %}

So after you've fetched the bitcoin tx metadata and have removed the witness data from the original transaction hex, let's go ahead and prepare the metadata into its Clarity parameter values.

{% code expandable="true" %}

```typescript
import {
  fetchCallReadOnlyFunction,
  bufferCV,
  uintCV,
  tupleCV,
  listCV,
  cvToString,
} from "@stacks/transactions"
import { hexToBytes } from "@stacks/common"
import { getTxHex, getTxMerkleProof, getBlkHeader, removeWitnessData } from "./fetch-bitcoin-data.js"

// Data of read-only function of below clarity-bitcoin-lib contract:
const contractAddress = "SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9"
const contractName = "clarity-bitcoin-lib-v7"
const functionName = "was-tx-mined-compact"

// Fetching btc tx metadata. You can replace this with any bitcoin transaction id.
let txid = "fb88309b4041f76bea0c196633c768dca82bb0dd424cbfe19be38569007f92d9"

// Fetching and returning non-witness tx hex
let fullTxHex = await getTxHex(txid)
let txHex = removeWitnessData(fullTxHex)
let { block_height, merkle, pos } = await getTxMerkleProof(txid)
let { blockHeader } = await getBlkHeader(block_height)

let txIndex = pos
let hashes = merkle.map(hash => bufferCV(hexToBytes(hash).reverse()))
let treeDepth = merkle.length

// Preparing arguments for clarity function call
let functionArgs = [
  // (height)
  uintCV(block_height),
  // (tx)
  bufferCV(Buffer.from(txHex, "hex")),
  // (header)
  bufferCV(Buffer.from(blockHeader, "hex")),
  // (proof)
  tupleCV({
    "tx-index": uintCV(txIndex),
    hashes: listCV(hashes),
    "tree-depth": uintCV(treeDepth)
  })
]
```

{% endcode %}

<details>

<summary>What is the purpose of the merkle proof?</summary>

A Merkle proof is a mathematically efficient and compact manner to prove that a transaction is included in a block in the Bitcoin blockchain.

**How transactions are combined into the Merkle root**

Transactions in a block are hashed and paired, then the hashes of the pairs are hashed and paired, and so on until a single hash remains — this is called the Merkle root.

**Merkle root in the block header**

The Merkle root is included in the block header. By providing the hashes that lead from a transaction's hash up to the Merkle root, along with the block header, one can prove that the transaction is included in that block.

**Merkle proof (Merkle path)**

The hashes that connect a transaction to the Merkle root are called the Merkle proof or Merkle path. By providing the Merkle proof along with the transaction hash and block header, anyone can verify that the transaction is part of that block.

**Efficient decentralized verification**

This allows for efficient decentralized verification of transactions without having to download the entire blockchain. One only needs the transaction hash, Merkle proof, and block header to verify.

</details>

<details>

<summary>Why are we removing the witness data from the original tx hex?</summary>

The `clarity-bitcoin-lib` contract's `was-tx-mined-compact` function only accepts a non-witness transaction hex. Usually only legacy bitcoin transactions are deemed as non-witness transactions. The contract also has a dedicated function for bitcoin transactions with witness data called `was-segwit-tx-mined-compact` .

But you could still verify any transaction type in `was-tx-mined-compact` by simply removing the witness data from the original tx hex.

</details>
{% endstep %}

{% step %}

#### Invoke \`was-tx-mined-compact\` function

Construct a read-only function call, pass in the contract call options, and await the results. If the bitcoin transaction in question is indeed mined in an existing Bitcoin block, the contract will return a response that looks like:

`(ok 0xfb88309b4041f76bea0c196633c768dca82bb0dd424cbfe19be38569007f92d9)`

You'll see your exact bitcoin txid returned wrapped in an `ok` response.

{% code expandable="true" %}

```typescript
// --snip--

// Calling clarity read-only function
let result = await fetchCallReadOnlyFunction({
  contractAddress,
  contractName,
  functionName,
  functionArgs,
  network: 'mainnet',
  // this could be any principal address
  senderAddress: 'SP1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRCBGD7R'
})

// Logging results
console.log("Full tx hex: ", fullTxHex)
console.log("Non-witness tx hex: ", txHex)
console.log("Block height: ", block_height)
console.log("Block header: ", blockHeader)
console.log("Merkle proof hashes: ", merkle)
console.log("Transaction index in block: ", txIndex)
console.log("Merkle tree depth: ", treeDepth)
console.log("Was the transaction mined (from clarity-bitcoin)? ")
console.log(cvToString(result))
```

{% endcode %}
{% endstep %}
{% endstepper %}

That's the end-to-end flow: fetch the bitcoin transaction metadata and its merkle proof, prepare and assemble the data for the contract's read-only function call, and finally call the Clarity contract function that verifies inclusion in a Bitcoin block.

***

## Example Usage

Here are some example projects/contracts that would leverage the `clarity-bitcoin-lib` contract in their own code.

#### Square Runes

A Clarity implementation for parsing Bitcoin Runes protocol data. Check out the project repo [here](https://github.com/Rapha-btc/square-runes).

<pre class="language-clarity" data-title="runes-capsule-v0.clar" data-expandable="true"><code class="lang-clarity">;; --snip--

;; Main entry point: Process a Runes deposit with full merkle proof verification
(define-public (process-deposit
    (height uint)
    (wtx {
      version: (buff 4),
      ins: (list 50 { outpoint: { hash: (buff 32), index: (buff 4) }, scriptSig: (buff 1376), sequence: (buff 4) }),
      outs: (list 50 { value: (buff 8), scriptPubKey: (buff 1376) }),
      locktime: (buff 4),
    })
    (witness-data (buff 1650))
    (header (buff 80))
    (tx-index uint)
    (tree-depth uint)
    (wproof (list 14 (buff 32)))
    (witness-merkle-root (buff 32))
    (witness-reserved-value (buff 32))
    (ctx (buff 4096))
    (cproof (list 14 (buff 32)))
    (mom-token &#x3C;sr-trait>)
  )
  (let (
      ;; Build full tx buffer
      (tx-buff (contract-call?
        'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.bitcoin-helper-wtx-v2
        concat-wtx wtx witness-data
      ))
    )
    ;; Verify tx was mined on Bitcoin
    (match (contract-call?
<strong>      'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.clarity-bitcoin-lib-v7
</strong>      was-segwit-tx-mined-compact height tx-buff header tx-index tree-depth
      wproof witness-merkle-root witness-reserved-value ctx cproof
    )
      btc-tx-id (process-verified-deposit btc-tx-id tx-buff height mom-token)
      error (err (* error u1000)) ;; ERR-TX-NOT-MINED
    )
  )
)

;; --snip--
</code></pre>

***

## Additional Resources

* \[[Hiro YT](https://youtu.be/mPba9vJEDlc?si=wTCqweRWWFP-jyCJ)] Bitcoin Enabled NFT - Stacks NFTs Minted By Bitcoin Transactions
* \[[Hiro Blog](https://www.hiro.so/blog/how-to-use-bitcoin-data-in-clarity-unit-tests)] How to Use Bitcoin Data in Clarity Unit Tests


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.stacks.co/more-guides/verify-bitcoin-transactions-clarity.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
