Wie bekomme ich die Daten der letzten 10 Blöcke über web3.js?

Wie kann ich die neuesten 10 Blockdaten abrufen, indem ich web3.js verwende, wie es die meisten Block-Explorer tun?

Antworten (6)

Es gibt einige Probleme mit der akzeptierten Antwort:

  1. wie @Lam-Le erwähnt, .getBlock()und .getBlockNumber()beide asynchron sind. Wenn also während der Schleife ein neuer Block erstellt wird, erhalten Sie nicht nur nicht mehr die "neuesten" Blöcke, sondern Sie haben auch Duplikate.
  2. die Schleife erzeugt eine unverhältnismäßig große Menge an Netzwerkanfragen (2 x i+1).

Um das erste Problem zu lösen, müssen Sie einen Verweis auf die neueste Blocknummer beibehalten:

const latest = await web3.eth.getBlockNumber()

Um die Anzahl der Netzwerkanfragen web3 zu reduzieren, können Sie BatchRequests verwenden .

const batch = new web3.eth.BatchRequest()
batch.add(web3.eth.getBlock.request(blockNumber, callback))
batch.execute()

requestBeachten Sie, dass Sie die spezielle Methode verwenden müssen, um die Argumente an die Funktion zu übergeben .

Wenn Sie sie zusammenfügen, können Sie die letzten n Blöcke abrufen mit:

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()
Ihr Link zu BatchRequests ist jetzt 404.

Verwenden Sie web3.eth.getBlockmitweb3.eth.blockNumber

for (var i=0; i < 10; i++) {
  console.log(web3.eth.getBlock(web3.eth.blockNumber - i));
}

BEARBEITEN: für web3.js 1.0+ sollte der Körper der Schleife sein:

web3.eth.getBlock(web3.eth.blockNumber - i).then(console.log)

( Beispiel )

sollte web3.eth.blockNumberin der lokalen Variablen zwischengespeichert werden, bevor eine Schleife für den Fall eines neuen eingehenden Blocks ausgeführt wird
Wenn ein neuer Block auftaucht, ist möglicherweise auch mehr Logik wünschenswert, da die Daten nicht mehr die "aktuellsten" sind. Aber positiv bewertet, guter Punkt von @LamLe.
getBlock ist asynchron, Sie sollten dies auf die async-Funktion setzen, bevor Sie es in console.log einfügen
@Rafid danke, ich habe mit einem Beispiel für web3.js 1.0+ aktualisiert

Es gibt die Filterfunktionalität , die in der web3.js-Bibliothek verfügbar ist, die sehr gut dokumentiert ist. Es ist genau für diesen Zweck konzipiert.

Es lohnt sich auch, sich die JSONRPC- Dokumentation anzusehen, um zu verstehen, wie diese Funktionalität hinter den Kulissen funktioniert.

Kopieren/Einfügen aus den Dokumenten mit einer leichten Änderung:

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();

getBlockNumberSie können (letzte Blocknummer abrufen) und kombinieren getBlock. Da beide Funktionen asynchron sind, verwenden wir Promise.thenund async/await. Vollständiger 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');
});

du könntest auch machen:

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)));

und fahren Sie dann fort, die Blockinformationen aus dem Blockarray zu dekonstruieren. Ich habe festgestellt, dass die Verwendung von Promise.all viel schneller und einfacher zu verwalten ist.

Warum nur 10. Mit diesem NodeJS-Code können Sie die neuesten N-Blöcke-Informationen erhalten:

    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)

Hinweis : Vergessen Sie nicht, die RPC-Provider linkzweite Codezeile oben zu ändern.

RPC-Anbieterliste verschiedener Blockchains https://github.com/arddluma/awesome-list-rpc-nodes-providers

REFERENZDOKUMENTE https://web3js.readthedocs.io/en/v1.7.3/web3-eth.html#