Ich versuche, Ereignisse in meinem Soliditätsvertrag auszulösen, um einige Debug-Informationen in meinen Javascript-Tests auszugeben. Die Ereignisse scheinen jedoch nie erfasst zu werden.
Das ist der relevante Vertragscode:
pragma solidity ^0.4.4;
contract CrowdFunding {
uint public deadline;
event DeadlineSet(uint deadline, uint timeNow);
function withdrawal() returns(bool) {
DeadlineSet(deadline, now);
return true;
}
}
So versuche ich, auf die Ereignisse in meiner JavaScript-Testdatei zu lauschen:
var deadlineSet;
deadlineSet = contractInstance.DeadlineSet({_from:web3.eth.coinbase});
deadlineSet.watch(function(err, result) {
if(err) {
console.log(err);
return;
}
console.log("Deadline " + result.args.deadline);
console.log("Time Now " + result.args.timeNow);
deadlineSet.stopWatching();
});
Meine Tests funktionieren einwandfrei und ich kann Geld an den Vertrag senden und Methoden aufrufen, aber ich sehe nie eine der oben definierten Konsolenausgaben.
Jede Hilfe ist willkommen.
Ich habe festgestellt, dass nicht alle Ereignisse im Truffle-Ausgabefenster angezeigt werden, obwohl sie bei der Ausführung eines Kontrakts möglicherweise korrekt ausgelöst wurden. Ich glaube, das ist immer noch ein Problem
Nachdem ich heute Stunden damit verbracht habe, habe ich eine Lösung gefunden, um zu testen, ob bestimmte Ereignisse ausgelöst werden.
Hier ist mein Beispiel-Trüffel-Javascript-Test:
it("should do something that fires SaleMade", function() {
return myContract
.stockShelf("beer", "wine", {from: sellerAccount})
.then(() => myContract.sell("water", "bread", {from: sellerAccount}))
.then(() => utils.assertEvent(myContract, { event: "SaleMade", logIndex: 1, args: { name: "bread" }}));
}
Das Obige filtert die ausgelösten Ereignisse, die mit dem Filterobjekt übereinstimmen, das an die AssertEvent-Dienstprogrammfunktion übergeben wird, die ich in utils.js im selben Ordner habe. An der Spitze meines Javascript-Tests habe ich erklärt:
var utils = require("./utils.js");
Ein Ausschnitt meiner utils.js-Klasse sieht wie folgt aus:
var _ = require("lodash");
var Promise = require("bluebird");
module.exports = {
assertEvent: function(contract, filter) {
return new Promise((resolve, reject) => {
var event = contract[filter.event]();
event.watch();
event.get((error, logs) => {
var log = _.filter(logs, filter);
if (log) {
resolve(log);
} else {
throw Error("Failed to find filtered event for " + filter.event);
}
});
event.stopWatching();
});
}
}
Dies erfordert andere npm-Pakete, die nicht standardmäßig in Truffle enthalten sind. Standardmäßig enthält Truffle keine npm-Pakete. Ich habe npm eingerichtet und die erforderlichen Pakete wie folgt installiert:
npm init
npm install bluebird --save
npm install lodash --save
BEARBEITEN: Mit testrpc
Anstatt zu loggen , können Sie die von einem Smart Contract ausgegebenen Ereignisse geltend machen:
npm install --save-dev truffle-test-utils
An der Spitze Ihres Tests:
require('truffle-test-utils').init();
Beim Testen, ob ein Ereignis aufgetreten ist:
// Regular call thanks to Truffle
let result = await testedSmartContract.testedFunction();
// Check event
assert.web3Event(result, {
event: 'TestedEvent',
args: {
param_1: 'Some value',
param_2: 0x123456 // No need for toNumber hassle
}
}, 'The event is emitted'
);
Ich weiß, dass diese Lösung nicht genau die richtige Antwort ist, aber dies ist die SO-Seite, die ich gefunden habe, als ich nach einer Möglichkeit gesucht habe, Ereignisse zu testen. Also ich denke das könnte helfen.
Vollständige Offenlegung: Ich bin der Autor dieses Pakets. Sie haben es richtig erraten: Ich habe es geschrieben, weil ich keinen sauberen Weg gefunden habe, es zu tun.
Nach meiner Beobachtung.
Wir müssen eine Weile warten, um das Ergebnis des beobachteten Ereignisses beim ersten Mal zu sehen.
Solidität
contract CrowdFunding {
event DeadlineSet(
address indexed _from,
uint deadline,
uint timeNow
);
uint deadline;
function withdrawal() returns(bool) {
DeadlineSet(msg.sender,deadline,now);
return true;
}
}
Javascript
var abi = /* abi as generated by the compiler */;
var CrowdFunding = web3.eth.contract(abi);
var crowdfunding = CrowdFunding .at("*address*");
var event = CrowdFunding.DeadlineSet({_from:web3.eth.coinbase},{fromBlock: 0, toBlock: 'latest'});
event.watch(function(error, result){
if (!error)
alert("wait for a while, check for block Synchronization or block creation");
console.log(result);
});
Es ist besser, stopwatch() zu verwenden, bevor Sie mit der Überwachung Ihrer Ereignisse beginnen, und nicht in der Überwachung, oder danach könnte die Ereignisüberwachung versehentlich gestoppt werden, bevor sie beginnt.
Probieren Sie den obigen Code aus und teilen Sie das Ergebnis. Überspringen Sie vorerst den TerminDeadlineSet.stopWatching().
Glauben Sie, dass Ihr Filter (dh {_from:web3.eth.coinbase}) nicht funktioniert. Versuch mal ohne. Etwas wie das
var deadlineSet= contractInstance.DeadlineSet({fromBlock: 0, toBlock: 'latest'});
Ein Beispiel auflisten, wie ich es verwendet habe.
Ereignis im Vertrag
event RegisterCandidate(uint256 indexed
eventTimeStamp, address indexed _from, bytes32 indexed _candidateName);
Javascript-Code
var event = contractInstance.RegisterCandidate( {_candidateName: "Abc"}, {fromBlock: 0, toBlock: 'latest'});
event.watch(function(error, response)
{
//once the event has been detected, take actions as desired
var data = 'from: ' + response.args._from+"<br>candidateName: "+web3.toUtf8(response.args._candidateName) +"<br>";
});
Ich habe die Antwort von mkaj verwendet, aber ich denke, es braucht ein paar Korrekturen:
hier :
if (log) {auflösen (log); }
resolve(log) wird immer aufgerufen, weil log ein Array ist, die richtige Prüfung wäre
if (log.length > 0) {
resolve(log);
}
(Das Umbenennen des Protokolls in „filteredLogs“ würde ebenfalls zur Klärung beitragen.)
Kipriz
assertEvent
Benötigt eine leichte Änderung:_.filter()
Gibt ein leeres Array zurück, wenn nichts gefunden wird.if
Ein leeres Array wird in der Anweisung als wahr behandelt . Es sollte seinif (!_.isEmpty(log))
Gagan
TypeError: event.watch is not a function