A WebSocket connection should be created with the Blocknative service at wss://api.blocknative.com/v0
. A successful connection will receive a response object that contains a status parameter with a value of 'ok'
.
The following parameters are required for all messages that are sent to the Blocknative service:
parameter | type | description |
| string | an ISO string date of when the message is being sent |
| string | your API key |
| string | a version string usually used by the Blocknative SDK, but any version string can be used |
| object | object specifying a the |
| string | blockchain name, valid values are |
| string | blockchain network, valid values for support systems are: Ethereum - Bitcoin - |
{"timeStamp": "2021-01-01T00:00:00.000Z","dappId": "<YOUR_API_KEY>","version": "1","blockchain": {"system": "ethereum""network": "main"}// ...rest of the message specific parameter}
Once a connection has been created with the Blocknative WebSocket service, an initialization message must be sent before any other messages so that the API key can be validated.
You API Key is created/managed from the Mempool Explorer account management page at https://explorer.blocknative.com/account. Note that API Key is called dappId
in the Blocknative websocket protocol.
{"categoryCode": "initialize","eventCode": "checkDappId",// ...rest of the required parameters}​
You can subscribe to receive transaction state change events by either watching a transaction hash/id or an address.
// subscribe{"categoryCode": "activeTransaction","eventCode": "txSent","transaction": {"hash": "0x0b4c94c414f71ddd5e7a625fcaa83ff1f93e9a7ca37e0f577b488ac8fd786655"}// ...rest of the required parameters}​// unsubscribe{"categoryCode": "activeTransaction","eventCode": "unwatch","transaction": {"hash": "0x0b4c94c414f71ddd5e7a625fcaa83ff1f93e9a7ca37e0f577b488ac8fd786655"}// ...rest of the required parameters}
// subscribe{"categoryCode": "activeTransaction","eventCode": "txSent","transaction": {"txid": "edbd572eb93f54099c0c64781e5fb09b8b4d89f80229b1af3c293d3356ca9f71"}// ...rest of the required parameters}​// unsubscribe{"categoryCode": "activeTransaction","eventCode": "unwatch","transaction": {"txid": "edbd572eb93f54099c0c64781e5fb09b8b4d89f80229b1af3c293d3356ca9f71"}// ...rest of the required parameters}
// subscribe{"categoryCode": "accountAddress","eventCode": "watch","account": {"address": "0xf5b5bd85157587771db6d49315b1712201569bdd"}// ...rest of the required parameters}​// unsubscribe{"categoryCode": "accountAddress","eventCode": "unwatch","account": {"address": "0xf5b5bd85157587771db6d49315b1712201569bdd"}// ...rest of the required parameters}
A configuration can be sent to the service to filter and/or decode transactions.
Transaction decoding is only available for Ethereum transactions
{"categoryCode": "configs","eventCode": "put","config": {"scope": "0xf5b5bd85157587771db6d49315b1712201569bdd","filters": [{"contractCall.methodName":"transfer"}],"abi": [{"constant": false,"inputs": [{ "name": "newOwner", "type": "address" }],"name": "setOwner","outputs": [],"payable": false,"stateMutability": "nonpayable","type": "function"}],"watchAddress": true}// ...rest of the required parameters}
parameter | type | description |
| string | A valid Ethereum address or |
| string[] | An array of valid filters. The Blocknative service uses |
| string[] | A valid JSON ABI that will be used to decode input data for transactions that occur on the contract address defined in |
| boolean | defines whether the service should automatically watch the address as defined in |
In the event of a WebSocket connection drop, no state is persisted between connections, so upon reconnection there will need to be logic defined that will:
Send an initialization message
Send all previously subscribed addresses, transactions and configs
Each message sent to the service will receive an echo of that message back, this echo may be ignored for most purposes.
Every payload contains an eventCode
parameter in the event
object which indicates the type of event. Detailed documentation for event codes can be found in the here.
{"version":0,"serverVersion":"0.85.8","timeStamp":"2021-01-06T01:25:24.716Z","connectionId":"49babf8c03a18ca8577b8dc42e4ab9e8cbdf3148d4b4b1e311f54f24c19e0e57","status":"ok","event":{"timeStamp":"2021-01-06T01:25:24.716Z","categoryCode":"activeAddress","eventCode":"txConfirmed","dappId":"<DAPP ID>","blockchain":{"system":"ethereum","network":"main"},"transaction":{"status":"confirmed","monitorId":"GETH_1_F_PROD","monitorVersion":"0.77.3","timePending":"5482902","blocksPending":410,"hash":"0x045fbad4090a25fc8267cf80f0f095a202cdac465d534e4c942b2068086e9aa3","from":"0xbA99926Be550865a956febAF4A747FFA0648797A","to":"0x111111125434b319222CdBf8C261674aDB56F3ae","value":"0","gas":324499,"gasPrice":"61000000000","nonce":179,"blockHash":"0x543bd57151cb7ab3024a18a459844790278861c712e9e4b58e1939a207e9fb82","blockNumber":11598068,"transactionIndex":307,"input": "0x34b0793b000000000000000...","gasUsed":"138022","asset":"ETH","watchedAddress":"0x111111125434b319222cdbf8c261674adb56f3ae","direction":"incoming","counterparty":"0xbA99926Be550865a956febAF4A747FFA0648797A"}}}​
If the transaction event is linked to an address subscription it will have the following properties that are unique to address subscriptions:
| type | description |
| string | the address subscription that this transaction is linked to, allowing you to match the transaction to a subscription |
| string | a value of |
| string | the counter-party to the watched address |
Transactions with a status of confirmed
will have the following additional properties that are not included in other statuses:
| type | description |
| string | the time, in milliseconds, the transaction was pending before being included in a block |
| string | the number of blocks the transaction was pending before being included in a block |
| string | the hash of the block containing the confirmed (or failed) transaction |
| number | the number of the block containing the confirmed (or failed) transaction |
| string | the amount of gas used to confirm (or fail) the transaction |
Transactions that have been replaced and have a status of speedup
or cancel
will have the following additional properties that are not included in other statuses:
| type | description |
| string | the hash of the transaction that is being replaced |
{"version":0,"serverVersion":"0.85.8","timeStamp":"2021-01-06T01:25:24.716Z","connectionId":"49babf8c03a18ca8577b8dc42e4ab9e8cbdf3148d4b4b1e311f54f24c19e0e57","status":"ok","event":{"timeStamp":"2021-01-06T01:25:24.716Z","categoryCode":"activeAddress","eventCode":"txConfirmed","dappId":"<DAPP ID>","blockchain":{"system":"ethereum","network":"main"},"transaction":{txid: "5d7bab0b34eb623fb344264a9801c8655bbee85f7e55f2c6fcca813487d57164"inputs: [{address: "13kj3N13dhTLJcKfxs8KchbDN3pQBKcWLK", value: "0.0016"}]outputs: [{address: "3LGrysb8jWcvdzQaZCVYoPbgJ1Puf2FmnJ", value: "0.0001524"},{address: "1BABaiprMpm3Lmm3zuMhQs5gaGtjjguVBA", value: "0.00123649"}],netBalanceChanges: [{address: "13kj3N13dhTLJcKfxs8KchbDN3pQBKcWLK", delta: "-0.0016"},{address: "3LGrysb8jWcvdzQaZCVYoPbgJ1Puf2FmnJ", delta: "0.0001524"},{address: "1BABaiprMpm3Lmm3zuMhQs5gaGtjjguVBA", delta: "0.00123649"}]fee: "0.00021111"status: "confirmed",system: "bitcoin",network: "main",timePending: "542538",timeStamp: "2021-01-07T01:03:34.521Z",txid: "5d7bab0b34eb623fb344264a9801c8655bbee85f7e55f2c6fcca813487d57164",watchedAddress: "13kj3N13dhTLJcKfxs8KchbDN3pQBKcWLK",rawTransaction: <RAW BITCOIN TRANSACTION>,timePending: "542538",blockHeight: "664885",blockHash: "5d7bab0b34eb623fb344264a9801c8655bbee85f7e55f2c6fcca813487d57164",}}}
Errors from the service are returned as messages with a status
= 'error'
and a reason string explaining the error.
Websocket payload is too large (60,000 bytes):
{//...other paramsstatus: 'error',reason: 'message too large'}
API key (dappId
) parameter is missing:
{//...other paramsstatus: 'error',reason: 'missing dappId'}
API key (dappId
) is invalid:
{//...other paramsstatus: 'error',reason: '<DAPP-ID> is not a valid API key'}
Attempt to watch an invalid address:
Address validity is based on the specific blockchain system
used (bitcoin or ethereum).
{//...other params"status":"error","reason":"(string `address`) 0 is an invalid address in object `account` in object `websocket-event`"}
Amount of messages has exceeded limit, see Rate Limits section below.
{//...other paramsstatus: 'error',reason: 'ratelimit',retryMs: 1000,blockedMsg: <Message that was blocked>}
Exceeded daily event limit for your API key, see Rate Limits section below.
{//...other paramsstatus: 'error',reason: 'You have reached your event rate limit for today. See account.blocknative.com for details.'}
IP has been rate limited, see Rate Limits section below.
{//...other paramsstatus: 'error',reason: 'IP ratelimited**'**}
Error received for using incorrect API version.
{//...other paramsstatus: 'error',message: 'api version not supported',}
Daily per API key event rate limits that apply to Webhook events also apply to WebSocket events. Details on those limits can be found here.
The Blocknative service also limits how many messages can be sent over a duration of time, limiting to 50 messages per second.
A strategy that the Blocknative SDK uses to handle these limits is to create a message queue that processes messages and ensures that messages are spaced adequately. This can be especially important to implement when re-sending addresses to be subscribed after a connection dropout.
If a rate limit error message is received you can use the retryMs
parameter to wait for that time period to continue sending messages. If a message was blocked due to a rate limit it will be included in the payload in the blockedMsg
parameter so you can re-send that message after the retry delay, ensuring that no messages are dropped.