Was ist der richtige Weg, um auf das Mining einer Transaktion zu warten und die Ergebnisse zu erhalten? [Duplikat]

Ich verwende React, um das Frontend für meine dApp zu schreiben, und tue dies, um den Status von React über einen asynchronen sendTransactionAufruf zu aktualisieren (zu versuchen):

var thisJS = this
web3.eth.sendTransaction({from: adminAccount, to: contractAddress, value: web3.toWei(funds,"ether")}, function(error, result) {
  if (error) {
    console.error(error)
  } else {
    console.log("Send transaction successful " + result)
    const contractFunds = web3.fromWei(web3.eth.getBalance(contractAddress),"ether").toString()
    thisJS.setState({contractFunds: contractFunds})
  }
})    

Das scheint nicht ganz so zu funktionieren, wie ich gehofft hatte, da der Reaktionsaufruf setState(oft) nicht die neuen Gelder an der Vertragsadresse widerspiegelt. Ich muss etwas falsch machen - was ist der richtige Weg, um auf das Mining der Transaktion zu warten, damit ich den Status von React korrekt aktualisieren kann?

Verwandt, aber nicht ganz dasselbe, glaube ich, da es sich um die Reorganisation der Kette handelt, nicht um die Überwachung von Standardblöcken
Das Problem ist, dass der Callback zu sendTransaction aufgerufen wird, sobald die Transaktion erfolgreich übermittelt wurde. Es muss nicht abgebaut werden. Sobald die Transaktion abgebaut ist, müssen Sie setState aufrufen, um zu aktualisieren, ist abgebaut.

Antworten (3)

Verwenden Sie einen Filter , um nach Änderungen zu suchen. In diesem Fall könnten Sie zum Beispiel:

web3.eth.filter('latest', function(error, result){
  if (!error) {
    thisJS.setState({contractFunds:
        web3.fromWei(web3.eth.getBalance(contractAddress),"ether").toString()})
  } else {
    console.error(error)
  }
});

Hinweis: Sie werden wahrscheinlich .stopWatchingirgendwann (wahrscheinlich in componentWillUnmount())

Ui - danke! Das sieht vielversprechend aus - ich sollte wahrscheinlich loslaufen und die Dokumente lesen, bevor ich etwas kommentiere, aber ist "neueste" ein Standardereignis, das dem neuesten Block entspricht?
Yup - hätte auf jeden Fall dem von Ihnen angegebenen Link folgen sollen: Die Zeichenfolge "latest" oder "pending", um auf Änderungen im letzten Block zu achten . Klasse - danke nochmal!

Ich habe einen Gist erstellt , der den Knoten abfragt, bis die Transaktion abgebaut wurde:

web3.eth.getTransactionReceiptMined = Funktion (txnHash, Intervall) {
    var transactionReceiptAsync;
    Intervall = Intervall ? Intervall: 500;
    transactionReceiptAsync = function(txnHash, auflösen, ablehnen) {
        Versuchen {
            var Empfang = web3.eth.getTransactionReceipt (txnHash);
            if (Empfang == null) {
                setTimeout(Funktion () {
                    transactionReceiptAsync(txnHash, auflösen, ablehnen);
                }, Intervall);
            } anders {
                lösen (Empfang);
            }
        } Fang(e) {
            ablehnen (e);
        }
    };

    if (Array.isArray(txnHash)) {
        var verspricht = [];
        txnHash.forEach(Funktion (einTxHash) {
            Promises.push (web3.eth.getTransactionReceiptMined (oneTxHash, Intervall));
        });
        return Promise.all (Versprechen);
    } anders {
        return new Promise(function (auflösen, ablehnen) {
                transactionReceiptAsync(txnHash, auflösen, ablehnen);
            });
    }
};

Wenn es länger als 50 Blöcke dauert, ist mir jedoch aufgefallen, dass es fehlschlägt.

Dem Vorschlag von Derek Tiffany folgend, kam ich auf die folgende Antwort.

Zuerst richte ich einen Filter für den neuesten Block ein:

const latestFilter = web3.eth.filter('latest')

Dann erhalte ich den Transaktions-Hash und setState auf diesen Hash:

const tx = web3.eth.sendTransaction({from: adminAccount, to: contractAddress, value: web3.toWei(funds,"ether")})
this.setState({txHash: tx})

Schließlich drehe ich eine Uhr für den Filter auf und versuche, den Transaktionshash meines Zustands abzugleichen. Wenn ich eine Übereinstimmung erhalte, aktualisiere ich den Status entsprechend:

_latestBlock() {
    const thisJs = this
    const filter = this.state.latest
    const web3 = this.state.web3
    const contractAddress = this.state.contractAddress
    const adminAccount = this.state.account 

    filter.watch(function (error, result) {
      if (error) {
        console.error(error)
      } else {
        let thisTx = thisJs.state.txHash 
        console.log("State transaction " + thisTx)
        const block = web3.eth.getBlock(result, true)
        let transactions = block.transactions
        for(let i = 0; i < transactions.length; i++)
        {
          console.log("block transaction " + transactions[i].hash)
          if( thisTx == transactions[i].hash ){
            console.log("Got match!")
            const contractFunds = web3.fromWei(web3.eth.getBalance(contractAddress),"ether").toString()
            thisJs.setState({contractFunds: contractFunds})
            break
          }
        }
      }
    })
} 

Bisher scheint es gut zu funktionieren...

Ich verstehe nicht, warum Sie const LatestFilter = web3.eth.filter('latest') gemacht haben, da Sie das Ergebnis nicht verwenden?
Hallo @PhillipGibb - oops, ich glaube, da fehlt ein Schritt! Es ist dies: this.state = { Latest: LatestFilter }