The Merkle Service is a Go microservice that accepts transaction IDs and monitors the blockchain for Merkle proofs. When a transaction is confirmed in a block, the service delivers the SPV proof (BUMP format) to a registered callback URL. Clients use it to obtain proofs without running a full node or polling repeatedly.
| Field | Value |
|---|---|
| Format | OpenAPI 3.1 |
| Version | 1.0.0 |
| Status | stable |
| Implementations | @bsv/sdk (client), external Go microservice |
Simplified SPV without full node. Wallets need Merkle proofs to verify transaction inclusion without downloading full blocks. Running a full node is expensive. The Merkle Service monitors the blockchain (either running a node itself or querying public data sources) and delivers proofs to clients on demand.
Callback-based delivery. Instead of polling the service repeatedly ("is my transaction confirmed yet?"), clients register a callback URL once. The service delivers the proof automatically when confirmation occurs, reducing network traffic and latency.
Idempotent registration. Registering the same transaction ID multiple times with the same callback is safe; the service deduplicates internally. This simplifies client logic (no need to track registrations).
Register transaction for monitoring:
Client → Merkle Service POST /watch
Merkle Service (monitoring)
Client (receives callback)
Health check:
GET /health — Returns OK if Merkle Service is connected to blockchain data source (Aerospike)| Method | Path | Purpose | Request | Response |
|---|---|---|---|---|
| POST | /watch | Register transaction for merkle proof | { txid, callbackUrl } | { status: "OK" } |
| GET | /health | Health check | (none) | { status: "OK" } or error |
Request body (POST /watch):
txid: string — Transaction ID (64 hex characters, case-insensitive)callbackUrl: string — HTTPS URL to POST proof to (must be valid HTTPS)Response body (callback POST):
txid: string — Transaction IDmerkleProof: string — BUMP format (Base64 or hex, spec-dependent)blockHeight: number — Block height of confirmationblockHash: string — Block hash (64-char hex)timestamp: number — Block timestamp (Unix seconds)Error responses (400, 404, etc.):
import { Transaction, WhatsOnChain } from '@bsv/sdk'
// Parse an example BEEF transaction that already includes a merkle path.
const tx = Transaction.fromHexBEEF('0100beef01fe87730e000402070282f861969...')
const txid = tx.id('hex')
const chaintracker = new WhatsOnChain()
const onChain = await tx.merklePath.verify(txid, chaintracker)
if (onChain) console.log('This transaction is proven on chain with SPV.')Server-side callback handler:
import { MerklePath, WhatsOnChain } from '@bsv/sdk'
app.post('/merkle-callback', async (req, res) => {
const { txid, merkleProof, blockHeight, blockHash } = req.body
const merklePath = MerklePath.fromHex(merkleProof)
const chaintracker = new WhatsOnChain()
const isValid = await merklePath.verify(txid, chaintracker)
if (isValid) {
await saveMerkleProof({ txid, merkleProof, blockHeight, blockHash })
}
res.json({ status: 'received' })
})Merkle Service conformance is tested in conformance/vectors/merkle/:
| Package | Notes |
|---|---|
| @bsv/sdk | Transaction, MerklePath, and WhatsOnChain helpers for SPV verification |
| @bsv/wallet-toolbox | Integrates Merkle Service for obtaining proofs during transaction confirmation |
| External: Go Merkle Service | Reference implementation (not in ts-stack; run separately) |