Estoy tratando de desencadenar eventos en mi contrato de solidez para generar información de depuración en mis pruebas de JavaScript. Sin embargo, los eventos parecen nunca quedar atrapados.
Ese es el código de contrato relevante:
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;
}
}
Así es como trato de escuchar los eventos en mi archivo de prueba de JavaScript:
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();
});
Mis pruebas funcionan bien y puedo enviar dinero al contrato y llamar a los métodos, pero nunca veo ninguna de las salidas de la consola definidas anteriormente.
Cualquier ayuda es apreciada.
Descubrí que no todos los eventos se muestran en la ventana de salida de la trufa, aunque es posible que se hayan disparado correctamente con la ejecución de un contrato. Creo que esto sigue siendo un problema.
Después de pasar horas en esto hoy, se me ocurrió una solución para probar que se disparan eventos específicos.
Aquí está mi prueba de javascript de trufa de ejemplo:
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" }}));
}
Lo anterior filtra los eventos activados que coinciden con el objeto de filtro pasado a la función de utilidad assertEvent que tengo en utils.js en la misma carpeta. En la parte superior de mi prueba de javascript he declarado:
var utils = require("./utils.js");
Un fragmento de mi clase utils.js es el siguiente:
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();
});
}
}
Esto requiere otros paquetes npm que no se incluyen con truffle de manera predeterminada. Por defecto, truffle no incluye paquetes npm. Configuré npm e instalé los paquetes necesarios como este:
npm init
npm install bluebird --save
npm install lodash --save
EDITAR: Usando testrpc
En lugar de iniciar sesión , puede afirmar los eventos emitidos por un contrato inteligente:
npm install --save-dev truffle-test-utils
En la parte superior de su prueba:
require('truffle-test-utils').init();
Al probar que ocurrió un evento:
// 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'
);
Sé que esta solución no es exactamente la respuesta correcta, pero esta es la página SO que encontré cuando buscaba una forma de probar eventos. Así que creo que eso podría ayudar.
Divulgación completa: soy el autor de este paquete. Adivinaste bien: lo escribí porque no encontré la manera limpia de hacerlo.
Según mi observación.
Tenemos que esperar un momento para ver el resultado del evento visto por primera vez.
Solidez
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 mejor usar el cronómetro() antes de comenzar a ver sus eventos y no en el reloj o después de eso, podría detener accidentalmente el reloj del evento antes de que comience.
Pruebe el código anterior y comparta el resultado. omita la fecha límiteSet.stopWatching() por ahora.
Cree que su filtro (es decir, {_from:web3.eth.coinbase}) no funciona. Pruébalo sin él. Algo como esto
var deadlineSet= contractInstance.DeadlineSet({fromBlock: 0, toBlock: 'latest'});
Enumerando un ejemplo de cómo lo he usado.
Evento en Contrato
event RegisterCandidate(uint256 indexed
eventTimeStamp, address indexed _from, bytes32 indexed _candidateName);
Código JavaScript
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>";
});
He usado la respuesta de mkaj, pero creo que necesita un par de correcciones:
aquí :
si (registro) { resolver (registro); }
resolve(log) siempre se llama porque log es una matriz, la verificación correcta sería
if (log.length > 0) {
resolve(log);
}
(Cambiar el nombre del registro a filteredLogs también ayudaría a aclararlo)
Kipriz
assertEvent
necesita una ligera modificación:_.filter()
devuelve una matriz vacía si no se encuentra nada. La matriz vacía se trata como verdadera en laif
declaración. Debería haberif (!_.isEmpty(log))
Gagan
TypeError: event.watch is not a function