Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.

Improve 'blockchain.header.subscribe' notification documentation #21

Open
dagurval opened this issue Aug 18, 2020 · 2 comments
Open

Improve 'blockchain.header.subscribe' notification documentation #21

dagurval opened this issue Aug 18, 2020 · 2 comments

Comments

@dagurval
Copy link
Owner

The initial response and notification differ,

The inital response looks something like this

{"id":1073741824,"jsonrpc":"2.0","result":{"height":648871,"hex":"000000209309beb3a16731c9182fe34354c89451daf42e941310e80200000000000000008cfcc285727beec64d7299952a53a9e8cfd600b45d941a5d054bcaeb5318476d25b23b5fc8f8021885139c63"}}

While a notification looks something like this

{"jsonrpc":"2.0","method":"blockchain.headers.subscribe","params":[{"height":648875,"hex":"0000c0205c818c9b25da6ddf115b731257684350fedd0352adc879020000000000000000f3982d3a8acd68aef9f645cc9c6c4fda961dcd10cab647c0e68d668604c12e17d9b33b5ffdf202180a6a8912"}]}

This is not clear in the documentation.

Electron Cash handles this by "rewriting" the response
https://github.com/Electron-Cash/Electron-Cash/blob/master/lib/network.py#L875

                # Rewrite response shape to match subscription request response
                method = response.get('method')
                params = response.get('params')
                k = self.get_index(method, params)
                if method == 'blockchain.headers.subscribe':
                    response['result'] = params[0]
                    response['params'] = []
                elif method == 'blockchain.scripthash.subscribe':
                    response['params'] = [params[0]]  # addr
                    response['result'] = params[1]
                callbacks = self.subscriptions.get(k, [])
@monsterbitar
Copy link

I have also found myself working around this in my code:

// If we received an array of exactly one block header..
if(Array.isArray(data) && data.length === 1)
{
	// Store the block hash and height.
	await this.setBlock(data[0].height, Buffer.from(data[0].hex, 'hex'));
}
// ..if we received a single block header..
else
{
	// Store the block hash and height.
	await this.setBlock(data.height, Buffer.from(data.hex, 'hex'));
}

@dagurval
Copy link
Owner Author

dagurval commented Aug 18, 2020

While we're sharing workarounds, here's mine in Kotlin 😂

            try {
                try {
                    // First response is wrapped in 'result', so use HeaderReply
                    val parsed = json.parse(HeaderReply.serializer(), it)
                    val header = BlockHeader.fromHex(parsed.result.hex)
                    header.height = parsed.result.height
                    callback(header)
                }
                catch (e: MissingFieldException) {
                    // Other responses are wrapped in params, use 'HeaderNotification'
                    val parsed = json.parse(HeaderNotification.serializer(), it)
                    val header = BlockHeader.fromHex(parsed.params.last().hex)
                    header.height = parsed.params.last().height
                    callback(header)
                }
            }
            catch (e: Exception) {
                LogIt.warning("Error when handling block header notification: $e")
            }

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants