Skip to content

Instantly share code, notes, and snippets.

@corollari
Last active March 2, 2020 14:42
Show Gist options
  • Save corollari/85aaa1d4962d252980d484486390e5c6 to your computer and use it in GitHub Desktop.
Save corollari/85aaa1d4962d252980d484486390e5c6 to your computer and use it in GitHub Desktop.
A publish-subscribe service for the NEO blockchain

The service

We built a publish-subscribe service for NEO that allows anyone to listen for events happening on the blockchain and act on them. The service is based in websockets and can be used by just connecting to the following endpoints:

wss://pubsub.main.neologin.io?channel=events # Events triggered in smart contract executions (final)
wss://pubsub.main.neologin.io?channel=tx # A transaction has entered in the mempool (but may not be inside a block yet)
wss://pubsub.main.neologin.io?channel=block # A block is propagated (not finalized tho)
wss://pubsub.main.neologin.io?channel=consensus # Consensus messages

Note: If you wish to get events from testnet instead of mainnet just replace the main prefix with test, eg: pubsub.test.neologin.io.

Using javascript, you can connect to these endpoints with the following code:

const ws = new WebSocket('wss://pubsub.main.neologin.io/?channel=events')
ws.onmessage = (event) => {
  console.log(event.data);
}

You can also check the state of the service at CoZ Monitor.

Going forward we will continue to host and maintain these servers for the community to use.

Example events

tx

{
   "type":"tx",
   "txID":"cb11e90091069b5086b723326e15181e717343e7be49f90709c934f328beea0d",
   "data":{
      "jsonrpc":"2.0",
      "id":1,
      "result":{
         "txid":"0xcb11e90091069b5086b723326e15181e717343e7be49f90709c934f328beea0d",
         "size":215,
         "type":"ContractTransaction",
         "version":0,
         "attributes":[
            {
               "usage":"Remark",
               "data":"4f3358464f52434c41494d"
            }
         ],
         "vin":[
            {
               "txid":"0x3bd33d4183f9e207be9308b42a489e595a6fe6099f23ac7bfff2ee65a99087a8",
               "vout":0
            }
         ],
         "vout":[
            {
               "n":0,
               "asset":"0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b",
               "value":"254",
               "address":"AXmT1qBWTvzu434eBrVGx9VwvPhLCZapA6"
            }
         ],
         "claims":null,
         "sys_fee":"0",
         "net_fee":"0",
         "scripts":[
            {
               "invocation":"4050e76610d39cdce6b31fd07ad5bb5009bf09966d55fa510d828cb2efcd0b415e3c5700db1ea414695b3f1c1ebc5c3cffbce9792a29463e178d99d88f76468343",
               "verification":"2102f9bec8e6da87dd4af85f76030847e4f0e3ea467ef24f9fd2077c495f6f91b458ac"
            }
         ],
         "script":"",
         "gas":"",
         "blockhash":"",
         "confirmations":0,
         "blocktime":0
      }
   }
}

consensus

{
   "type":"consensus",
   "txID":"95d5855180e77540412f3fb707ed50fed848f9ec7887073513625e1b9ec9fbbb"
}

block

{
   "type":"block",
   "txID":"110603a66d2353271506d255d3204caf330850b58b39950c87282fd7aafb0554"
}

events

{
   "type":"events",
   "txID":"0x92c6e0510d23cb9c12d52f7494e88be07a0bf139c126d8804ed90348714f165c",
   "data":{
      "contract":"0xfde69a7dd2a1c948977fb3ce512158987c0e2197",
      "call":{
         "type":"Array",
         "value":[
            {
               "type":"ByteArray",
               "value":"6f7261636c654f70657261746f72"
            },
            {
               "type":"ByteArray",
               "value":"55d6d86bdec15db437aca45b4e8705333f1fdb07"
            },
            {
               "type":"ByteArray",
               "value":"736e656f5f7072696365"
            },
            {
               "type":"ByteArray",
               "value":""
            },
            {
               "type":"ByteArray",
               "value":"b0273755"
            },
            {
               "type":"Integer",
               "value":"2"
            }
         ]
      }
   }
}

Scalability

We've designed the system to handle high load and be able to scale horizontally. This is possible thanks to an architecture based around a singleton instance of a NEO node that gets all the data which is then relayed to a scalable amount of dynos hosted on heroku which maintain the websockets connections with all the clients and push the data to them, thus we can dynamically scale the amount of dynos on heroku to meet demand.

How does it work

The server captures messages sent through the p2p network that connects all the NEO nodes and relays them to the clients. The events channel is different because instead of deriving the data from the p2p network it gets the events from a node that has the NeoPubSub plugin installed, capturing all the event calls triggered in successful contract executions by transactions that have been included in a final block.

Contributions

  • Forked neo-pub-sub, updated it to work with the current versions of neo nodes (previously it would break because of changes made to neo nodes), extended it to relay events and more. See PR and PR
  • Deployed two public neo-pub-sub servers for everyone to use. These servers are on heroku and will auto-scale to meet demand.
  • Added 2 new full nodes (mainnet & testnet) to the neo network.
  • Wrote a guide on setting up a neo node with a reverse proxy and another one on how to install the NeoPubSub plugin
  • Improved monitor.cityofzion.io by adding support for websockets protocols, fixing it's dependecies and establishing an automated build system for it. See PR
  • Improved the NeoPubSub plugin slightly with several PRs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment