Анализатор событий в web3 обеспечивает удобную функциональность анализа событий, и я использую его для записи всех событий в файл, но его очень сложно использовать для просмотра отдельных событий для конкретной транзакции для автоматического тестирования, поскольку он вызывает ненужные и сложные для управления аспектом параллелизма, когда он не нужен.
Когда я получаю результат транзакции с помощью web3, у меня на руках есть квитанция о транзакции, и это идеальное время для синхронной проверки результата и применения критериев проверки «пройдено/не пройдено».
Я хотел бы проанализировать раздел журнала квитанции, но не могу найти функцию в web3 для этого. Он существует?
Сделайте это: вам нужно будет получить код из web3, и это работает лучше всего, если ваш интерфейс связан с помощью чего-то вроде webpack или browserify:
var SolidityCoder = require("web3/lib/solidity/coder.js");
var log = receipt.logs[0];
var data = SolidityCoder.decodeParams(["string", "uint"], log.data.replace("0x", ""));
В этом случае мы декодируем данные журнала, которые содержат две переменные: одну строкового типа и одну типа uint.
РЕДАКТИРОВАТЬ:
Если у вас есть доступный ABI, вы можете определить, какое событие связано с этим 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", ""));
параметры, когда тип ввода нашей функции представляет собой массив, подобный этому: function newObject(bytes32 _id, uint256 number_of_sub_states, bytes32[10] sub_states_types, bytes32[10] sub_states_values, address _owner)
? Спасибо.var SolidityCoder = require("web3/lib/solidity/coder.js");
я получаю эту ошибку: Error: Cannot find module 'web3/lib/solidity/coder.js'
Вы знаете, в чем причина? Спасибо.Теперь вы можете использовать эту web3.eth.abi.decodeLog
функцию (web3 1.0).
Пример из документации:
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'
}
Тим:
Большое спасибо за указатель. Вы заставили меня, наконец, понять некоторые внутренности web3.js.
Я нашел более чистый способ сделать это, который охватывает все крайние случаи на самом деле довольно сложного формата сообщений журнала (например, индексация). Я только что использовал SolidityEvent из web3, чтобы сделать за меня уже проверенную работу.
Ниже приведен код. У меня есть этот код на github , включая тестовый код .
// 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);
})
}
Для web3.js 1.0 используйте следующее:
contractInstance.inputs = [{"indexed": false, "name": "_id", "type": "uint256"}]; //event abi
contractInstance._decodeEventABI({data: '0x0'}); //event raw data
выход
{
returnValues:
Result {
'0': '1',
_id: '1',
},
raw: {
data: '0x0'
}
}
Получив квитанцию о транзакции ( tr
), вы знаете номер блока транзакции ( tr.blockNumber
). Итак, вы можете сделать следующее:
myContract.MyEvent (
{},
{fromBlock: tr.blockNumber, toBlock: tr.blockNumber}).
get ().
filter (function (e) {
return e.transactionHash == tr.transactionHash
});
Это вернет массив всех событий типа MyEvent
, сгенерированного контрактом myContract
в транзакции, на которую ссылается квитанция транзакции tr
.
С 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' } } ]
Пол С