'/feed' API

The /feed websocket API allows for faster synchronization on initalization (msgpack with less redundant data compared to wallet api), and "push" updates instead of polling. New block arrivals, new received/spent transactions, and reorgs are all pushed to the client in real-time. This should provide an enterprise-like experience where the (usually mobile) client is seamlessly synchronized with monerod (but only if monero-lws-daemon is using ZMQ PUB/SUB from monerod).

Basics

The client initiates a /feed websocket connection, then the LWS server sends the entire tx history, and then finally sends a continous stream of updates from monerod (ZMQ PUB mempool+blocks messages) to the client.

Flow

Handshake

The client must attempt a websocket "upgrade" connection to /feed. The initial handshake must have a HTTP/1.1 field, Sec-WebSocket-Protocol, which is set to msgpack or json:

Sec-WebSocket-Protocol: lws.feed.v0.msgpack
Sec-WebSocket-Protocol: lws.feed.v0.json

This parameter signals the protocol version and payload type. All message payloads must match the type set in the header. Msgpack is recommended as both serialization and de-serialization is faster, and the messages are more compact (especially since binary crypto blobs are not encoded as hex).

Synchronization

After the websocket handshake, the client must send a login message, and the server must respond with a tx-sync message OR error message. An error message signals the websocket is now in the "terminated" state, a tx-sync message indicates that server is now ready to send real-time updates. In either case, the client shall not send any further data - the server will terminate the connection if this is not followed.

Updates

After the tx-sync, the server will then push blocks, mempool, warning, or error messages until the stream is terminated. An error message indicates the stream is immediately terminated, whereas the other messages indicate a valid stream where clients should expected further messages.

Message Format

Every message has a prefix before the msgpack/json payload that indicates the type. Current valid prefixes are login:, tx-sync:, blocks:, mempool:, warning:, and error:. The login: prefix is from the client, and the remainder are sent by the server. The root type of every payload is an object. As an example, a client login message (in the json sub-protocol), will look like:

login:{
  "account":{
    "address": "47nPhxp2cJeKN2NjamupNUNA13XgzcYPzQBCzzsKcj717s8M2UpFVmmdwSuYwgyy8kPDwU7hpEqTTDvfe5LAb9Aj6nwmEzf",
    "view_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
  }
}

This format (with prefixes) allows for single-pass DOMless parsing.

login

Messages of this type are sent (only) by the client. The message contains proof the client has authority to receives updates for a given primary address, along with optional restrictions on data sent/pushed by the server.

schema

Example

login:{
   "account":{
    "address": "47nPhxp2cJeKN2NjamupNUNA13XgzcYPzQBCzzsKcj717s8M2UpFVmmdwSuYwgyy8kPDwU7hpEqTTDvfe5LAb9Aj6nwmEzf",
    "view_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
  },
  "tx_sync": false,
  "receives_only": true
}

tx-sync

Messages of this type are sent only by the server, and only in response to a successful login: command from the client. The message contains everything needed for the client to have a full tx synchronization with the backend (unless the client requested no transactions).

schema

Example

tx_sync:{
  "scanned_block_height": 10,
  "blockchain_height": 10,
  "lookahead_fail": 5,
  "lookahead": {"maj_i": 50, "min_i": 200 },
  "transactions": [
    {
      "hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
      "prefix_hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
      "timestamp": 0,
      "fee": 0,
      "unlock_time": 0,
      "mixin": 0,
      "payment_id": "ee171270296bbc26",
      "coinbase": true,
      "mempool": true,
      "receives": [
        {
          "id": {"legacy": {"amount": 0, "index": 0}},
          "amount": 0,
          "public_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "index": 0,
          "tx_pub_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "rct": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "recipient": {"maj_i": 1, "min_i": 1}
        }
      ],
      "spends": [
        {
          "id": {"unified": 0},
          "key_image": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
        }
      ]
    }
  ]
}

blocks

Messages of this type are sent only by the server when a new block has been scanned on the account. If another block was added to the Monero chain, this message type is not sent until a new block has been scanned against the account. This will also give real-time updates when account is scanning historical blocks (although the server can choose to group/aggregate messages to reduce total number of messages).

schema

Example

blocks:{
  "scan_start": 150,
  "scan_end": 151,
  "blockchain_height": 151,
  "lookahead_fail": 0,
  "lookahead": {"maj_i": 50, "min_i": 200 },
  "transactions": [
    {
      "hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
      "prefix_hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
      "timestamp": 0,
      "fee": 0,
      "unlock_time": 0,
      "mixin": 0,
      "payment_id": "ee171270296bbc26",
      "coinbase": true,
      "receives": [
        {
          "id": {"legacy": {"amount": 0, "index": 0}},
          "amount": 0,
          "public_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "index": 0,
          "tx_pub_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "rct": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
          "recipient": {"maj_i": 1, "min_i": 1}
        }
      ],
      "spends": [
        {
          "id": {"unified": 0},
          "key_image": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
        }
      ]
    }
  ]
}

mempool

If the account scanner has caught-up with the most recent block, the server may send received outputs that are still in the mempool. These outputs will be re-sent in the blocks: message in a transaction; the ID numbers for outputs are not assigned until the transaction is included in a block. Spends are assumed to be under the control of the client, and are not sent in mempool messages.

schema

Full Example

mempool:{
  "hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
  "prefix_hash": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
  "timestamp": 0,
  "fee": 0,
  "unlock_time": 0,
  "mixin": 0,
  "payment_id": "ee171270296bbc26",
  "amount": 0,
  "public_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
  "tx_pub_key": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205",
  "index": 0,
  "recipient": {"maj_i": 1, "min_i": 1},
  "rct": "ee171270296bbc26d5be4455b6313e1a2086a92080e205f77d6f861f8e5fd205"
}

warning

The primary purpose of this message type is to alert the client that the server has detected a block re-organization. The rollback point is transmitted in the message, and the client is expected to rollback transactions that are part of the re-organization. Other events, such as lost connection to monerod are also sent as warnings. Most other events will be error.

schema

Example

warning:{
  "msg": "Descriptive warning message",
  "code": 4,
  "counter": 10,
  "height": 1000
}

Codes

  unspecified_error = 0,
  account_not_found = 1,
  bad_address = 2,
  bad_view_key = 3,
  blockchain_reorg = 4,
  daemon_unresponsive = 5,
  parse_error = 6,
  protocol_error = 7,
  queue_error = 8,
  schema_error = 9

error

Servers will send an error of this type when the websocket must be closed; no further messages are to be sent after sending this type. The codes sent in this message type are identical to the ones specified aboved for warning messages.

schema

Example

error:{
  "msg": "Descriptive error message",
  "code": 8
}