2015-01-29 16:05:43 +02:00
|
|
|
/*
|
|
|
|
This file is part of ethereum.js.
|
2015-01-29 13:35:21 +02:00
|
|
|
|
2015-01-29 16:05:43 +02:00
|
|
|
ethereum.js is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
ethereum.js is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
/** @file event.js
|
|
|
|
* @authors:
|
|
|
|
* Marek Kotewicz <marek@ethdev.com>
|
|
|
|
* @date 2014
|
|
|
|
*/
|
2015-01-29 13:35:21 +02:00
|
|
|
|
2015-01-31 02:30:19 +02:00
|
|
|
var abi = require('./abi');
|
2015-01-31 03:54:17 +02:00
|
|
|
var utils = require('./utils');
|
|
|
|
|
2015-02-03 16:08:19 +02:00
|
|
|
/// filter inputs array && returns only indexed (or not) inputs
|
|
|
|
/// @param inputs array
|
|
|
|
/// @param bool if result should be an array of indexed params on not
|
|
|
|
/// @returns array of (not?) indexed params
|
|
|
|
var filterInputs = function (inputs, indexed) {
|
|
|
|
return inputs.filter(function (current) {
|
|
|
|
return current.indexed === indexed;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-01-31 03:54:17 +02:00
|
|
|
var inputWithName = function (inputs, name) {
|
|
|
|
var index = utils.findIndex(inputs, function (input) {
|
2015-01-31 04:42:13 +02:00
|
|
|
return input.name === name;
|
2015-01-31 03:54:17 +02:00
|
|
|
});
|
2015-01-31 04:42:13 +02:00
|
|
|
|
2015-01-31 03:54:17 +02:00
|
|
|
if (index === -1) {
|
2015-01-31 16:22:05 +02:00
|
|
|
console.error('indexed param with name ' + name + ' not found');
|
2015-01-31 04:42:13 +02:00
|
|
|
return undefined;
|
2015-01-31 03:54:17 +02:00
|
|
|
}
|
|
|
|
return inputs[index];
|
|
|
|
};
|
|
|
|
|
2015-01-31 04:42:13 +02:00
|
|
|
var indexedParamsToTopics = function (event, indexed) {
|
|
|
|
// sort keys?
|
|
|
|
return Object.keys(indexed).map(function (key) {
|
2015-02-03 16:08:19 +02:00
|
|
|
var inputs = [inputWithName(filterInputs(event.inputs, true), key)];
|
2015-01-31 04:42:13 +02:00
|
|
|
|
2015-01-31 03:54:17 +02:00
|
|
|
var value = indexed[key];
|
|
|
|
if (value instanceof Array) {
|
2015-01-31 04:42:13 +02:00
|
|
|
return value.map(function (v) {
|
2015-01-31 16:48:49 +02:00
|
|
|
return abi.formatInput(inputs, [v]);
|
2015-01-31 04:42:13 +02:00
|
|
|
});
|
2015-01-31 03:54:17 +02:00
|
|
|
}
|
2015-01-31 16:48:49 +02:00
|
|
|
return abi.formatInput(inputs, [value]);
|
2015-01-31 03:54:17 +02:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-02-03 16:08:19 +02:00
|
|
|
var inputParser = function (address, signature, event) {
|
2015-01-29 13:35:21 +02:00
|
|
|
|
2015-01-31 02:30:19 +02:00
|
|
|
// valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'
|
|
|
|
return function (indexed, options) {
|
2015-01-29 13:35:21 +02:00
|
|
|
var o = options || {};
|
2015-01-31 02:30:19 +02:00
|
|
|
o.address = address;
|
|
|
|
o.topic = [];
|
|
|
|
o.topic.push(signature);
|
2015-01-31 04:42:13 +02:00
|
|
|
if (indexed) {
|
|
|
|
o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));
|
|
|
|
}
|
2015-01-29 13:35:21 +02:00
|
|
|
return o;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-02-03 16:08:19 +02:00
|
|
|
var getArgumentsObject = function (inputs, indexed, notIndexed) {
|
|
|
|
var indexedCopy = indexed.slice();
|
|
|
|
var notIndexedCopy = notIndexed.slice();
|
|
|
|
return inputs.reduce(function (acc, current) {
|
|
|
|
var value;
|
|
|
|
if (current.indexed)
|
|
|
|
value = indexed.splice(0, 1)[0];
|
|
|
|
else
|
|
|
|
value = notIndexed.splice(0, 1)[0];
|
|
|
|
|
|
|
|
acc[current.name] = value;
|
|
|
|
return acc;
|
|
|
|
}, {});
|
|
|
|
};
|
|
|
|
|
|
|
|
var outputParser = function (event) {
|
|
|
|
|
|
|
|
return function (output) {
|
|
|
|
var result = {
|
|
|
|
event: utils.extractDisplayName(event.name),
|
2015-02-03 17:16:38 +02:00
|
|
|
number: output.number,
|
|
|
|
args: {}
|
2015-02-03 16:08:19 +02:00
|
|
|
};
|
2015-02-03 17:16:38 +02:00
|
|
|
|
|
|
|
if (!output.topic) {
|
|
|
|
return result;
|
|
|
|
}
|
2015-02-03 16:08:19 +02:00
|
|
|
|
|
|
|
var indexedOutputs = filterInputs(event.inputs, true);
|
|
|
|
var indexedData = "0x" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join("");
|
|
|
|
var indexedRes = abi.formatOutput(indexedOutputs, indexedData);
|
|
|
|
|
|
|
|
var notIndexedOutputs = filterInputs(event.inputs, false);
|
|
|
|
var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);
|
|
|
|
|
|
|
|
result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-02-03 17:16:38 +02:00
|
|
|
var getMatchingEvent = function (events, payload) {
|
|
|
|
for (var i = 0; i < events.length; i++) {
|
|
|
|
var signature = abi.eventSignatureFromAscii(events[i].name);
|
|
|
|
if (signature === payload.topic[0]) {
|
|
|
|
return events[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-02-03 16:08:19 +02:00
|
|
|
module.exports = {
|
|
|
|
inputParser: inputParser,
|
2015-02-03 17:16:38 +02:00
|
|
|
outputParser: outputParser,
|
|
|
|
getMatchingEvent: getMatchingEvent
|
2015-02-03 16:08:19 +02:00
|
|
|
};
|
2015-01-29 13:35:21 +02:00
|
|
|
|