El analizador de eventos en web3 proporciona una buena funcionalidad de análisis de eventos, y lo uso para registrar todos los eventos en un archivo, pero es muy difícil de usar para buscar eventos individuales para una transacción en particular para pruebas automatizadas porque induce un error innecesario y difícil. para administrar el aspecto de concurrencia cuando no es necesario que haya uno.
Cuando obtengo el resultado de una transacción con web3, tengo el recibo de la transacción a mano y ese es el momento perfecto para examinar el resultado sincrónicamente y aplicar los criterios de prueba de aprobación/rechazo.
Me gustaría analizar la sección de registro del recibo pero no puedo encontrar una función en web3 para hacerlo. ¿Existe?
Haga esto: necesitará extraer el código de web3, y funciona mejor si su interfaz está empaquetada usando algo como webpack o browserify:
var SolidityCoder = require("web3/lib/solidity/coder.js");
var log = receipt.logs[0];
var data = SolidityCoder.decodeParams(["string", "uint"], log.data.replace("0x", ""));
En este caso, estamos decodificando datos de registro que contienen dos variables, una de tipo cadena y otra de tipo uint.
EDITAR:
Si tiene el ABI disponible, puede detectar qué evento está relacionado con ese ABI:
var SolidityCoder = require("web3/lib/solidity/coder.js");
// You might want to put the following in a loop to handle all logs in this receipt.
var log = receipt.logs[0];
var event = null;
for (var i = 0; i < abi.length; i++) {
var item = abi[i];
if (item.type != "event") continue;
var signature = item.name + "(" + item.inputs.map(function(input) {return input.type;}).join(",") + ")";
var hash = web3.sha3(signature);
if (hash == log.topics[0]) {
event = item;
break;
}
}
if (event != null) {
var inputs = event.inputs.map(function(input) {return input.type;});
var data = SolidityCoder.decodeParams(inputs, log.data.replace("0x", ""));
// Do something with the data. Depends on the log and what you're using the data for.
}
SolidityCoder.decodeParams(["string", "uint"], log.data.replace("0x", ""));
los parámetros cuando el tipo de entrada de nuestra función es una matriz como esta function newObject(bytes32 _id, uint256 number_of_sub_states, bytes32[10] sub_states_types, bytes32[10] sub_states_values, address _owner)
:? Gracias.var SolidityCoder = require("web3/lib/solidity/coder.js");
, recibo este error: Error: Cannot find module 'web3/lib/solidity/coder.js'
¿Sabe cuál es el motivo? Gracias.Ahora puede utilizar la web3.eth.abi.decodeLog
función (web3 1.0).
Ejemplo de la documentación:
web3.eth.abi.decodeLog([{
type: 'string',
name: 'myString'
},{
type: 'uint256',
name: 'myNumber',
indexed: true
},{
type: 'uint8',
name: 'mySmallNumber',
indexed: true
}],
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000748656c6c6f252100000000000000000000000000000000000000000000000000',
['0x000000000000000000000000000000000000000000000000000000000000f310', '0x0000000000000000000000000000000000000000000000000000000000000010']);
> Result {
'0': 'Hello%!',
'1': '62224',
'2': '16',
myString: 'Hello%!',
myNumber: '62224',
mySmallNumber: '16'
}
Tim:
Muchas gracias por el puntero. Me obligaste a comprender finalmente algunas de las partes internas de web3.js.
Encontré una forma más limpia de hacer esto que cubre todos los casos de esquina del formato de mensaje de registro bastante complicado (por ejemplo, indexación). Acabo de usar SolidityEvent de web3 para hacer el trabajo ya probado por mí.
A continuación se muestra el código. Tengo este código en github , incluido el código de prueba .
// XXX move this to a hook function
var SolidityEvent = require("web3/lib/web3/event.js");
Pudding.logParser = function (logs, abi) {
// pattern similar to lib/web3/contract.js: addEventsToContract()
var decoders = abi.filter(function (json) {
return json.type === 'event';
}).map(function(json) {
// note first and third params required only by enocde and execute;
// so don't call those!
return new SolidityEvent(null, json, null);
});
return logs.map(function (log) {
return decoders.find(function(decoder) {
return (decoder.signature() == log.topics[0].replace("0x",""));
}).decode(log);
})
}
Para web3.js 1.0 use lo siguiente:
contractInstance.inputs = [{"indexed": false, "name": "_id", "type": "uint256"}]; //event abi
contractInstance._decodeEventABI({data: '0x0'}); //event raw data
producción
{
returnValues:
Result {
'0': '1',
_id: '1',
},
raw: {
data: '0x0'
}
}
Una vez que tenga el recibo de la transacción ( tr
), sabrá el número de bloque de la transacción ( tr.blockNumber
). Por lo tanto, puede hacer lo siguiente:
myContract.MyEvent (
{},
{fromBlock: tr.blockNumber, toBlock: tr.blockNumber}).
get ().
filter (function (e) {
return e.transactionHash == tr.transactionHash
});
Esto devolverá una matriz de todos los eventos de tipo MyEvent
generados por contrato myContract
en transacción referidos por recibo de transacción tr
.
Con web3.js 0.20.6.
$ node
> var AllEvents = require('web3/lib/web3/allevents')
undefined
> var decodeEventsForContract = (C, tr) => {
const ae = new AllEvents(C._web3, C.abi, C.address);
// ae.decode mutates the args, so we deep copy
return JSON.parse(JSON.stringify(tr))
.logs
.filter(l => l.address === C.address)
.map(l => ae.decode(l));
}
undefined
> decodeEventsForContract(MyTokenContract, txreceipt);
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0xbc68d5ddc391fab84cd633a77dbc815cbc42546a13de9d123f7a5b820faa3cb4',
blockHash: '0xb604998aa0b6bece492530c9cbab494349a31b18a34067f225e1b59613952051',
blockNumber: 21,
address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
type: 'mined',
event: 'Transfer',
args:
{ from: '0x0000000000000000000000000000000000000000',
to: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
value: [BigNumber] } },
{ logIndex: 1,
transactionIndex: 0,
transactionHash: '0xbc68d5ddc391fab84cd633a77dbc815cbc42546a13de9d123f7a5b820faa3cb4',
blockHash: '0xb604998aa0b6bece492530c9cbab494349a31b18a34067f225e1b59613952051',
blockNumber: 21,
address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
type: 'mined',
event: 'Mint',
args:
{ to: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
value: [BigNumber],
minter: '0x627306090abab3a6e1400e9345bc60c78a8bef57' } } ]
pablo s