Receiving ZMQ Notifications#


Receiving notifications from Dash Core is important for a variety of use-cases. Although polling RPCs can be useful, in some scenarios it may be more desirable to have publish-subscribe functionality. Dash Core’s built-in ZeroMQ (ZMQ) support provides the ability to subscribe to block, transaction, and governance related messages.

Further information regarding ZMQ support may be found in the ZMQ API Reference.

Enabling Dash Core ZMQ Notifications#


This requires a Dash Core full node or masternode

In the dash.conf configuration file, add the following ZMQ notifications and assign the address that Dash Core should listen on. The notifications selected here relate to InstantSend and ChainLocks.


Restart the Dash Core node once the configuration file has been updated.

JavaScript Example#

Requires an installation of NodeJS

1. Install ZeroMq#

The JavaScript zeromq package is available from and can be installed from the command line by running:

npm install zeromq@5

🚧 ZeroMQ Version

Version 5 of the zeromq package should be used for compatibility reasons.

2. Subscribe to ZeroMQ Messages#

Create a file with the following contents. Then run it by typing node <your-filename.js> from the command line:

const zmq = require('zeromq');
const sock = zmq.socket('sub');
const zmqPort = 20009;

sock.connect('tcp://' + zmqPort);

// Subscribe to transaction notifications
sock.subscribe('hashtx'); // Note: this will subscribe to hashtxlock also

// Subscribe to InstantSend/ChainLock notifications
sock.subscribe('rawchainlock'); // Note: this will subscribe to rawchainlocksig also
sock.subscribe('rawtxlock'); // Note: this will subscribe to rawtxlocksig also

console.log('Subscriber connected to port %d', zmqPort);

sock.on('message', function(topic, message) {
import binascii
import asyncio
import zmq
import zmq.asyncio
import signal

port = 20009

class ZMQHandler():
    def __init__(self):
        self.loop = asyncio.get_event_loop()
        self.zmqContext = zmq.asyncio.Context()

        self.zmqSubSocket = self.zmqContext.socket(zmq.SUB)
        self.zmqSubSocket.connect("tcp://" % port)

        # Subscribe to transaction notifications
        self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx")

        # Subscribe to InstantSend/ChainLock notifications
        self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtxlock")
        self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashchainlock")
        self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawchainlock")
        self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlock")

        print('Subscriber connected to port {}'.format(port))

    def handle(self) :
        msg = yield from self.zmqSubSocket.recv_multipart()
        topic = msg[0]
        body = msg[1]
        sequence = "Unknown"

        print('Received {} containing:\n{}\n'.format(

        # schedule ourselves to receive the next message

    def start(self):
        self.loop.add_signal_handler(signal.SIGINT, self.stop)

    def stop(self):

daemon = ZMQHandler()

Example Response#

The following response demonstrates the notification provided by Dash Core when it receives a transaction and then receives the associated InstantSend lock. The four notifications represent:

  1. The TXID of the transaction is received (HASHTX) - at this point the transaction is not locked

  2. The TXID of a locked transaction is received (HASHTXLOCK). Since this is the same value as the HASHTX already received, we know that the transaction has now received an InstantSend lock.

  3. The raw transaction (RAWTXLOCK) (this could be decoded using the decoderawtransaction RPC for example)

  4. A combination of the raw transaction and the InstantSend lock signature (RAWTXLOCKSIG)

Received HASHTX containing:

Received HASHTXLOCK containing:

Received RAWTXLOCK containing:
 02000000025a4d18da609107e9ea3dc6 ... 5a32ea917a30147d6c9788ac6ea90400

Received RAWTXLOCKSIG containing:
 02000000025a4d18da609107e9ea3dc6 ... 9e889cee7ba48981ca002e6962a20236