How to listen for new bitcoin blocks

Hello!

For ethereum, you can easily listen for new blocks by doing something like this (using ethers.js):

const provider = new ethers.providers.StaticJsonRpcProvider(quicknodePolygonUrl);
provider.on('block', (block: number) => {
  console.log(`We got a new block! ${block}`);
});

Is there a way to do the same thing with bitcoin?

2 Likes

Hi there, welcome to the forum. There is no direct way of listening for new blocks on Bitcoin using JSON-RPC.

But you can achieve this using QuickAlerts; you just have to create an alert whenever a new block with block number greater than zero is created.

Bitcoin right now is only available on QuickAlerts via REST API. So, first of all, you’ll need to create a destination, check how to create a destination.

You’ll need the destination id from the output of the destination file to deploy a notification. learn how to create a notification

This is how the line number 12-14 would like in the notification file

expression: 'YmxvY2tfbnVtYmVyID4gMA==', //base64 equivalent of block_number > 0
network: 'bitcoin-mainnet',
destinationIds: ['YOUR_DESTINATION_ID_HERE'],

Refer to these videos to learn more about QuickAlerts REST API:

2 Likes

Hi @sahil, thank you for the response!

I am trying it out. I’ve created a destination, and I’m trying to create a webhook like the one you suggested. I’ve tried twice now, with a payload like so:

{
  "destinationIds": ["destination-id-here"],
  "name": "BitCoin Block Notifications", 
  "expression": "YmxvY2tfbnVtYmVyID4gMA==",
  "network": "bitcoin-mainnet"
}

It takes about 10-15 seconds, the first time it returned an Internal Server Error, and the second time it must have timed out, it says “502 Bad Gateway”

1 Like

If you don’t mind, could you post the entire code? and what are you using to create a destination URL?

This is what it looks like:

const response = await fetch('https://api.quicknode.com/quickalerts/rest/v1/notifications', {
  method: 'POST',
  headers: { 'x-api-key': this.config.apiKey },
  body: JSON.stringify({
    name: "BitCoin Block Notifications",
    expression: Buffer.from('block_number > 0').toString('base64'),
    network: 'bitcoin-mainnet',
    destinationIds: ['14f48abf-62a7-4795-8d00-441b540e7ce6'], // this is the real ID
  }),
});

To create the destination url, I’m using ngrok. I’m able to post to the url myself, but I never see a request come in from quicknode. Right now all it’s doing is logging the payload it gets.

I used the following combo and was able to get a notification on new block:

Destination file

var myHeaders = new Headers()
myHeaders.append('accept', 'application/json')
myHeaders.append('Content-Type', 'application/json')
myHeaders.append('x-api-key', 'your_key')

var requestOptions = {
	method: 'POST',
	headers: myHeaders,
	redirect: 'follow',
	body: JSON.stringify({
		name: 'Satoshi txs',
		to_url: 'your_webhook_url', //add /webhook suffix if using ngrok
		webhook_type: 'POST',
		service: 'webhook',
		payload_type: 1,
	}),
}

fetch(
	'https://api.quicknode.com/quickalerts/rest/v1/destinations',
	requestOptions
)
	.then(response => response.text())
	.then(result => console.log(result))
	.catch(error => console.log('error', error))

Notification file

var myHeaders = new Headers()
myHeaders.append('accept', 'application/json')
myHeaders.append('Content-Type', 'application/json')
myHeaders.append('x-api-key', 'your_key')
const encodedExpression = btoa(`block_number > 0`);
var requestOptions = {
	method: 'POST',
	headers: myHeaders,
	redirect: 'follow',
	body: JSON.stringify({
		name: 'BitCoin Block Notifications',
		expression: encodedExpression,
		network: 'bitcoin-mainnet',
		destinationIds: ['your_destination_id'],
	}),
}

fetch(
	'https://api.quicknode.com/quickalerts/rest/v1/notifications',
	requestOptions
)
	.then(response => response.text())
	.then(result => console.log(result))
	.catch(error => console.log('error', error))

@sahil

I’m not sure what was wrong. I tried it again and it worked just fine.

The payload that is received for the block looks different than the payload you get from calling the getblock rpc

The payload looks more like what you get from bb_gettx.

I’m wondering if there’s a way to consolidate this, because if we are listening to the quickalert and miss a webhook, we will have to resync the block. But, the only way to retrieve a block is using getblock, but since the payload is different, it will need to be parsed differently.

Alternatively, we could get all the transaction ids and call bb_gettx on each one, but that sounds pretty expensive.

Is there a way to manually retrieve a bitcoin block payload that looks the same as the one you get from quickalerts? Is there any reason there isn’t a bb_getblock call?

Hey @synic,

I’m glad to see that the alert is working for you.

I tested and saw that, yes, the payload that you get from the is different than getblock. QuickAlerts payload has all the transactions expanded. Something like bb_getblock doesn’t exist right now just because of the demand. But have noted down this feedback, and it will be passed to the relevant team. There is no native RPC that gives you the payload like the QuickAlerts.

Talking about the missed alerts, if there may come a situation when your WebHook goes down for sometime QuickAlerts has exponential retry logic, so it’ll send the payload again. Hope this helps.

Hi @synic,

We listened to your request and created bb_getblock.

So, if you have the QuickNode Blockbook addon you will be able to use bb_getblock and get the same response as QuickAlerts.

2 Likes

Hey Sahil!

Sorry for the late response, have been out of town.

That’s awesome! Thank you very much! I will try it out as soon as I get into the office

Adam

1 Like

Amazing! let me know if I can help anywhere.

Best,
Sahil

1 Like

I’ve tried it out, it mostly seems to work, however, it seems the results are paged (for block 00000000000000000004b85b374521ef8389073eef904d6db7c02acded041966 it returns that the totalPages is 2 and that you’re on page 1), but there doesn’t seem to be a way to retrieve page 2. I’ve tried passing { "page": 2 } as the second argument to the params, but that seems to be ignored (it is also not mentioned in the documentation, so maybe it just hasn’t been implemented)

Unrelated, it seems that the response documentation for bb_gettx is missing the toplevel result object.

1 Like

Hi @synic yes I just checked the backend, looks like the page part is missing from the query string let me add it, will update you as soon as it’s updated and I checked for bb_gettx result object, all the values are mentioned in the documentation, any specific one you’re not seeing in the docs?

Hi Adam,

We’ve implemented the missing paging query param, and now you should be able to query specific pages.

{"method": "bb_getblock", "params": ["00000000000000000004b85b374521ef8389073eef904d6db7c02acded041966", {"page": 2}]}

Looks like it’s working! I’ll let you know if I see anything else!

For the docs, it’s just the toplevel “result” object that’s missing (the API is fine, just the docs are wrong). Here is the documentation for bb_gettx:

The toplevel “result” object is not present, though it’s there in the api response. This is not missing in bb_getblock, for example. Hopefully that makes sense

Obviously not a huge deal, just thought I’d mention it

Thanks for pointing that out, Adam, should be updated now.

1 Like

This is just what I have been looking for. Thans @sahil I’ll try this out too.

1 Like

This was really helpful, was thinking of using Stacks blockchain, as I didn’t know even Bitcoin methods are supported in QuickNode.

Hi @Spectre_7

Both Bitcoin and Stacks are supported on QuickNode :slight_smile: