# Introduction

WARNING

Available from go-qlc v1.3 and above

From version 1.3 gqlc has experimental support for pub/sub using subscriptions as defined in the JSON-RPC 2.0 specification. This allows clients to wait for events instead of polling for them

It works by subscribing to particular events. The node will return a subscription id. For each event that matches the subscription a notification with relevant data is send together with the subscription id

Example:

// create subscription
>> {"id": 1, "method": "ledger_subscribe", "params": ["newBlock"]}
<< {"jsonrpc":"2.0","id":1,"result":"0xcd0c3e8af590364c09d0fa6a1210faf5"}
// incoming notifications
<< {"jsonrpc":"2.0","method":"ledger_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"type":"State","token":"a7e8fa30c063e96a489a47bc43909505bd86735da4a109dca28be936118a8582",<...>}}}
<< {"jsonrpc":"2.0","method":"ledger_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"type":"State","token":"38b13da6e7425ee4f21194504c9c9ceea0b09f65da3f32bed0c36cbced44ce0b",<...>}}}
// cancel subscription
>> {"id": 1, "method": "ledger_unsubscribe", "params": ["0xcd0c3e8af590364c09d0fa6a1210faf5"]}
<< {"jsonrpc":"2.0","id":1,"result":true}

Notice:

  • subscriptions require a full duplex connection. gqlc offers such connections in the form of websockets and ipc
  • subscriptions are coupled to a connection. If the connection is closed all subscriptions that are created over this connection are removed

# Create subscription

Subscriptions are creates with a regular RPC call with ledger_subscribe as method and the subscription name as first parameter. If successful it returns the subscription id.

  • Parameters:
    • the first one is subscription name, like "balanceChange"
    • others are optional arguments
{
	"id": 1,
	"method": "ledger_subscribe",
	"params": ["balanceChange","qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4"]
}
  • Returns: If successful it returns the subscription id immediately。
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0xe45c66069086940b9f555ebacc95f37e"
}

then client keep listening to the connection, once server publish information, client can read from the connection, as:

  • subscription : subscription id, it is unique to one subscription
  • result : actual subscription info
{
    "jsonrpc":"2.0",
    "method":"ledger_subscription",
    "params":{
        "subscription":"0xe45c66069086940b9f555ebacc95f37e",
        "result":{
            "account":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
            "balance":"60000000000000000",
            "vote":"0",
            "network":"0",
            "storage":"0",
            "oracle":"0",
            "tokens":[{
                "type":"a7e8fa30c063e96a489a47bc43909505bd86735da4a109dca28be936118a8582","header":"5594c690c3618a170a77d2696688f908efec4da2b94363fcb96749516307031d","representative":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4","open":"5594c690c3618a170a77d2696688f908efec4da2b94363fcb96749516307031d",
                "balance":"60000000000000000",
                "account":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
                "modified":1570804479,
                "blockCount":1
            }]
        }
    }
}

# Cancel subscription

There are two ways to cancel subscription

  • if client close the websocket/ipc connection, subscriptions are cancelled immediately

  • a regular RPC call with xxx_unsubscribe as method and the subscription id as first parameter. It returns a bool indicating if the subscription was cancelled successful, detail as follow:

  • Parameters:

    • string , subscription id
{
    "id": 1, 
    "method": "ledger_unsubscribe", 
    "params": ["0xe45c66069086940b9f555ebacc95f37e"]
}
  • Returns: Returns a bool indicating if the subscription was cancelled successful.
{
    "jsonrpc":"2.0",
    "id":1,
    "result":true
}

# Supported subscriptions

# ledger_subscription

# balanceChange

if the balance of a account change, server will publish the newest account info

  • Parameters:

    • string , address
  • Returns:

    • accountInfo newest account info for the address
  • Example:

{
	"id": 1,
	"method": "ledger_subscribe",
	"params": [
        "balanceChange",
        "qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4"
    ]
}
// get response immediately if connect to server successfully  
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0xe45c66069086940b9f555ebacc95f37e"
}
// then get response once server publish infomation
{
    "jsonrpc":"2.0",
    "method":"ledger_subscription",
    "params":{
        "subscription":"0xe45c66069086940b9f555ebacc95f37e",
        "result":{
            "account":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
            "balance":"60000000000000000",
            "vote":"0",
            "network":"0",
            "storage":"0",
            "oracle":"0",
            "tokens":[{
                "type":"a7e8fa30c063e96a489a47bc43909505bd86735da4a109dca28be936118a8582","header":"5594c690c3618a170a77d2696688f908efec4da2b94363fcb96749516307031d","representative":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4","open":"5594c690c3618a170a77d2696688f908efec4da2b94363fcb96749516307031d",
                "balance":"60000000000000000",
                "account":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
                "modified":1570804479,
                "blockCount":1
            }]
        }
    }
}

# newBlock

if there new block stored to the chain, server will publish the new block

  • Parameters: null

  • Returns:

    • block block info
  • Example:

{
    "id":1,
    "method":"ledger_subscribe",
    "params":["newBlock"]
}
// get response immediately if connect to server successfully  
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0xe45c66069086940b9f555ebacc95f37e"
}
// then get response once server publish infomation
{
    "jsonrpc":"2.0",
    "method":"ledger_subscription",
    "params":{
        "subscription":"0x4e6f513c51c6848f830d44ec1ad09d76",
        "result":{
            "type":"State",
            "token":"a7e8fa30c063e96a489a47bc43909505bd86735da4a109dca28be936118a8582","address":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
            "balance":"12180",
            "vote":"0",
            "network":"0",
            "storage":"0",
            "oracle":"0",
            "previous":"8d01d77cea5255cecc3885f0d040e7b641c453f33344738e652b19779bd6f630",
            "link":"51f5d4b6e25d1bbf28f0788d9aec9e2ee1d5d7b5b0082275e2aba033794bc640",
            "message":"0000000000000000000000000000000000000000000000000000000000000000",
            "povHeight":0,
            "timestamp":0,
            "extra":"0000000000000000000000000000000000000000000000000000000000000000",
            "representative":"qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4",
            "work":"0000000000000000",
            "signature":"c98ead9ade5a08cc7084bbe2ed77a4b4ba8492eeb855a6c295cffad23ed8030cf142222b2416eed178c8dc2c389a4f85338b56865fefc669038791547ee8af01"
        }
    }
}

# newPending

if there is a pending transaction of a account, server will publish the pending info

  • Parameters:

    • string , address
  • Returns:

    • pending pending info
  • Example:

{
	"id": 1,
	"method": "ledger_subscribe",
	"params": [
        "newPending",
        "qlc_3hw8s1zubhxsykfsq5x7kh6eyibas9j3ga86ixd7pnqwes1cmt9mqqrngap4"
    ]
}
// get response immediately if connect to server successfully  
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0xe45c66069086940b9f555ebacc95f37e"
}
// then get response once server publish infomation
{
    "jsonrpc":"2.0",
    "method":"ledger_subscription",
    "params":{
        "subscription":"0xe45c66069086940b9f555ebacc95f37e",
        "result":{
            "source": "qlc_36z9ojcgu6891jhcae6jd4a3dmxr8urx55516y4e7rqr9bob8kec1ddpemyt",
            "amount": "30000000000",
            "type": "a7e8fa30c063e96a489a47bc43909505bd86735da4a109dca28be936118a8582",
            "tokenName": "QLC",
            "hash": "dbb764589e9e9e5b5ff7fdb1cf1a6f01e4483d7d376de71736eb4869a361110d",
            "timestamp": 1553225891
        }
    }
}

# pov_subscription

# newBlock

if there new pov block stored to the chain, server will publish the new pov block

  • Parameters: null

  • Returns:

    • block pov block header info
  • Example:

{
    "id":1,
    "method":"pov_subscribe",
    "params":["newBlock"]
}
// get response immediately if connect to server successfully  
{
    "jsonrpc":"2.0",
    "id":1,
    "result":"0x14fddac2289853ad8af1e1f98a3628e"
}
// then get response once server publish infomation
{
    "jsonrpc":"2.0",
    "method":"pov_subscription",
    "params":{
        "subscription":"0x14fddac2289853ad8af1e1f98a3628e",
        "result":{
            "basHdr":{
                "version":536871936,
                "previous":"f8d045c01da1b006e8cd75b41f06dc248005d187593dabe5806659cf3256ce0a",
                "merkleRoot":"6553e616dd738e4ca5524bd1cde99440a296a071d4d52119f9492721839b1f43",
                "timestamp":1572241896,
                "bits":504365052,
                "nonce":0,
                "hash":"da4fbd8c589c8d2834cb324c9b087a2d6bdf6d50cbd8a6d810122fd557095237",
                "height":78
            },
            "auxHdr":{
                "auxMerkleBranch":null,
                "auxMerkleIndex":0,
                "parCoinBaseTx":{
                    "version":1,
                    "txIn":[
                        {
                            "previousOutPoint":{
                                "hash":"0000000000000000000000000000000000000000000000000000000000000000",
                                "index":4294967295
                            },
                            "signatureScript":"e37cb65d183ec09af9bcb908fabe6d6dda4fbd8c589c8d2834cb324c9b087a2d6bdf6d50cbd8a6d810122fd5570952370100000000000000",
                            "sequence":4294967295
                        }
                    ],
                    "txOut":[
                        {
                            "value":1,
                            "pkScript":"51"
                        }
                    ],
                    "lockTime":0
                },
                "parCoinBaseMerkle":null,
                "parMerkleIndex":0,
                "parBlockHeader":{
                    "version":2147483647,
                    "previous":"0000000000000000000000000000000000000000000000000000000000000000",
                    "merkleRoot":"a2fb014f50aeaf2e0ae17f08a67759b8ab39f4a18fc5770bbd24bedc8e991521",
                    "timestamp":1572241896,
                    "bits":0,
                    "nonce":1413080
                },
                "parentHash":"072b492dfe3fbf27e216a15e703dd55b28167a3e8ccd77d6a655dc519defc033"
            },
            "cbtx":{
                "version":1,
                "txIns":[
                    {
                        "prevTxHash":"0000000000000000000000000000000000000000000000000000000000000000",
                        "prevTxIdx":4294967295,
                        "extra":"4e000000000000002f514c432043505520417578504f572f",
                        "sequence":4294967295
                    }
                ],
                "txOuts":[
                    {
                        "value":"456621004",
                        "address":"qlc_1gnqid9up5y998uwig44x1yfrppsdo8f9jfszgqin7pr7ixsyyae1y81w9xp"
                    },
                    {
                        "value":"114155251",
                        "address":"qlc_111111111111111111111111111111111111111111111111111ommygmckp"
                    }
                ],
                "stateHash":"b63f07aacd736c292655c42320feb6510ff8bfb70b05c1376c82be3a705ac3c3",
                "txNum":1,
                "hash":"6553e616dd738e4ca5524bd1cde99440a296a071d4d52119f9492721839b1f43"
            }
        }
    }
}