How can I get latest 10 block data by using web3.js like most block explorer does?
6 Answers
There are a few issues with the accepted answer:
- as @Lam-Le mentions,
.getBlock()
and.getBlockNumber()
are both asynchronous so if a new block is created during the loop not only will you no longer obtain the 'latest' blocks but you will also have duplicates. - the loop creates an disproportionate amount of network request (2 x i+1).
To solve the first concern you must keep a reference to the latest blockNumber:
const latest = await web3.eth.getBlockNumber()
In order to reduce the amount of network request web3 you can use BatchRequests.
const batch = new web3.eth.BatchRequest()
batch.add(web3.eth.getBlock.request(blockNumber, callback))
batch.execute()
Notice that in order to pass the arguments to the function, you need to use the special request
method.
Putting them together, you can retrieve the last n blocks with:
const latest = await web3.eth.getBlockNumber()
const blockNumbers = _range(latest - n, latest + 1, 1)
const batch = new web3.eth.BatchRequest()
blockNumbers.forEach((blockNumber) => {
batch.add(
web3.eth.getBlock.request(blockNumber, storeLocalCopy)
)
})
batch.execute()
Use web3.eth.getBlock
with web3.eth.blockNumber
for (var i=0; i < 10; i++) {
console.log(web3.eth.getBlock(web3.eth.blockNumber - i));
}
EDIT: for web3.js 1.0+ the loop's body should be:
web3.eth.getBlock(web3.eth.blockNumber - i).then(console.log)
(example)
-
5should cache
web3.eth.blockNumber
in local variable before looping in case new incoming block– Lam LeCommented Aug 21, 2018 at 7:16 -
1If a new block appears, more logic may also be desired because the data is no longer the "latest". But upvoted, good point by @LamLe.– eth ♦Commented Sep 11, 2018 at 11:26
-
getBlock is asynchronous, you should put that on async function before putting it in console.log– RafidCommented Sep 1, 2019 at 17:56
-
There is the filter functionality available within the web3.js library that is extremely well documented. It is designed for exactly that purpose.
It is also worth looking at the JSONRPC documentation to understand how this functionality works behind the scenes.
Copy/paste from the docs with a slight modification:
var filter = web3.eth.filter({toBlock:'latest'});
filter.watch(function (error, log) {
console.log(log); // {"address":"0x0000000000000000000000000000000000000000", "data":"0x0000000000000000000000000000000000000000000000000000000000000000", ...}
});
// get all past logs again.
var myResults = filter.get(function(error, logs){ ... });
...
// stops and uninstalls the filter
filter.stopWatching();
You can combine getBlockNumber
(retrieve latest block number) and getBlock
. Since both function are asynchronous we will use Promise.then
and async/await
.
Full Code in NodeJs
var http = require('http');
var Web3 = require('web3');
var w3 = new Web3("ws://localhost:8546");
async function queryBlock(i){
var json = await w3.eth.getBlock(i);
return json;
}
var server = http.createServer((req,res)=>{
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
var blocks = [];
w3.eth.getBlockNumber().then((n) =>{
console.log(n);
for(i = 0; i < n; i++)
blocks.push(queryBlock(i));
Promise.all(blocks).then((value)=>{
res.end(JSON.stringify(value));
});
});
});
server.listen(8080, () => {
console.log('alhamdulillah');
});
you could also do:
const latest = await web3.eth.getBlockNumber()
const blockNumbers = _range(latest - n, latest + 1, 1);
const blocks = await Promise.all(blockNumbers.map(n => provider.eth.getBlock(n)));
and then proceed to deconstruct the blockinformation from the blocks array. I found that going with Promise.all is much faster and easier to manage.
Why only 10. You can get latest N blocks info with this NodeJS code:
const Web3 = require("web3")
const web3 = new Web3("https://rpc-provider.........")
async function GetLastNBlocks(n) {
latestBlock=await web3.eth.getBlockNumber()
for (let i = 0; i < n; i++) {
web3.eth.getBlock(latestBlock-i).then((err,data)=>{
console.log(latestBlock-i,data,err,"\n")
})
}
}
GetLastNBlocks(10)
note : don't forgot to change RPC-Provider link
on 2nd line of code above.
RPC providers list of different blockchains https://github.com/arddluma/awesome-list-rpc-nodes-providers
REFERENC DOCS https://web3js.readthedocs.io/en/v1.7.3/web3-eth.html#