Intro

Let’s take a look a specific use-case. If a user is sending bitcoin to my bitcoin address, how can I keep track the status of the transaction, for example, when the user send the coins and when the transaction gets confirmed? The solution is the system will generate a unique address for every user who is trying to send bitcoin. And the system will listen any transactions in the network, which related to this address.

For listening bitcoin transactions, you will need following tools:

ZeroMQ

When you are running your bitcoin node, you can enable/configure zmq feature. Then you are able to listen to all broadcasted transactions and blocks via the zmq interface.

Config zmq when running your bitcoin node

-zmqpubrawtx=tcp://0.0.0.0:28332
-zmqpubrawblock=tcp://0.0.0.0:28332
-zmqpubhashblock=tcp://0.0.0.0:28332
-zmqpubhashtx=tcp://0.0.0.0:28332

Subscribe transactions and blocks

var zmq = require('zeromq')

function startzmq() {
    var sock = zmq.socket('sub');

    sock.connect('tcp://localhost:28332');
    sock.subscribe('rawtx');
    sock.subscribe('hashblock');

    sock.on('message', function (topic, message) {
        if (topic.toString() === 'hashblock') {
        // There is a new block
        }
                
        if (topic.toString() === 'rawtx') {
            // There is a new message 
        }
    }   
}

Set up bitcoind rpc client

I am using bitcoin-core to set up our bitcoind rpc client. This client will be used to interact with our bitcoind node.

const Client = require('bitcoin-core');

const client = new Client({
    host: <host>,
    port: <port>,
    network: <network>,
    username: <username>,
    password: <password>,
});

exports.client = client;

Persistent layer

We are using redis as a fast, persistent, and easy-to-query storage to keep track of addresses, which are listening to.

var redis = require("redis")
var bluebird = require('bluebird')
bluebird.promisifyAll(redis);

var client = redis.createClient({
        host: <host>,
        port: <port>,
        password: <password>,
    });

client.on('connect', function() {
        console.log('redis connected');
    });
exports.client = client;

Start monitoring now !

Now we can start to check if anyone send coins to a specific address.

For example, let’s say if we want to check if a user sends coins to 1FfmbHfnpaZjKFvyi1okTjJJusN455paPH.

First of all, we need to subscribe rawTx topic, then you will receive all the transactions get broadcasted in the bitcoin network. You will only get the raw transaction hash though.

Secondly, you can use getTransaction(txId) to get the details of a transaction to see if that transaction is sending coins to 1FfmbHfnpaZjKFvyi1okTjJJusN455paPH. This is not the optimized way though. Because your bitcoin node will receive tons of rpc calls for checking every transaction broadcasted to the network. I will post later how we can do an optimization for this.

Then, if we found the txHash is sending coins to this address. Then you can subscribe hashBlock topic to listen if this transaction has been confirmed. you can use getBlock(blockId) to show all transactions in a block, and check if the specific txHash is included in the block.

// check if a txhash is in a block
sock.on('message', function (topic, message) {
    if (topic.toString() === 'hashblock') {
    
    var blockid = message.toString('hex');

    bitcoinClient.getBlock(blockid).then((block) => {
    const txes = block.tx
    for (index = 0; index < txes.length; index++) {
        const txid = txes[index]
        if (txid=='8b81b824f3b638ac46b2b2d719a03dbd436a8c8fe8517310c6576f383c6e0adf') {
        // this tx is confirmed in this block
        
        }
    })
    }
    }).catch((err)=>{
        console.error(err.message)
    })
}

Now if the transaction is found in a block, it will be considered confirmed.

In this post, we have go through how you can leverage zmp and bitcoin rpc API to keep track if a user sends coins to a specific address. Let me know if you have any questions.