You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.3 KiB
194 lines
5.3 KiB
/*
|
|
This file is part of ethereum.js.
|
|
|
|
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
|
|
* @author Marek Kotewicz <marek@ethdev.com>
|
|
* @date 2014
|
|
*/
|
|
|
|
var utils = require('../utils/utils');
|
|
var coder = require('../solidity/coder');
|
|
var web3 = require('../web3');
|
|
var formatters = require('./formatters');
|
|
|
|
/**
|
|
* This prototype should be used to create event filters
|
|
*/
|
|
var SolidityEvent = function (json, address) {
|
|
this._params = json.inputs;
|
|
this._name = utils.transformToFullName(json);
|
|
this._address = address;
|
|
this._anonymous = json.anonymous;
|
|
};
|
|
|
|
/**
|
|
* Should be used to get filtered param types
|
|
*
|
|
* @method types
|
|
* @param {Bool} decide if returned typed should be indexed
|
|
* @return {Array} array of types
|
|
*/
|
|
SolidityEvent.prototype.types = function (indexed) {
|
|
return this._params.filter(function (i) {
|
|
return i.indexed === indexed;
|
|
}).map(function (i) {
|
|
return i.type;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Should be used to get event display name
|
|
*
|
|
* @method displayName
|
|
* @return {String} event display name
|
|
*/
|
|
SolidityEvent.prototype.displayName = function () {
|
|
return utils.extractDisplayName(this._name);
|
|
};
|
|
|
|
/**
|
|
* Should be used to get event type name
|
|
*
|
|
* @method typeName
|
|
* @return {String} event type name
|
|
*/
|
|
SolidityEvent.prototype.typeName = function () {
|
|
return utils.extractTypeName(this._name);
|
|
};
|
|
|
|
/**
|
|
* Should be used to get event signature
|
|
*
|
|
* @method signature
|
|
* @return {String} event signature
|
|
*/
|
|
SolidityEvent.prototype.signature = function () {
|
|
return web3.sha3(web3.fromAscii(this._name)).slice(2);
|
|
};
|
|
|
|
/**
|
|
* Should be used to encode indexed params and options to one final object
|
|
*
|
|
* @method encode
|
|
* @param {Object} indexed
|
|
* @param {Object} options
|
|
* @return {Object} everything combined together and encoded
|
|
*/
|
|
SolidityEvent.prototype.encode = function (indexed, options) {
|
|
indexed = indexed || {};
|
|
options = options || {};
|
|
var result = {};
|
|
|
|
['fromBlock', 'toBlock'].filter(function (f) {
|
|
return options[f] !== undefined;
|
|
}).forEach(function (f) {
|
|
result[f] = utils.toHex(options[f]);
|
|
});
|
|
|
|
result.topics = [];
|
|
|
|
if (!this._anonymous) {
|
|
result.address = this._address;
|
|
result.topics.push('0x' + this.signature());
|
|
}
|
|
|
|
var indexedTopics = this._params.filter(function (i) {
|
|
return i.indexed === true;
|
|
}).map(function (i) {
|
|
var value = indexed[i.name];
|
|
if (value === undefined || value === null) {
|
|
return null;
|
|
}
|
|
|
|
if (utils.isArray(value)) {
|
|
return value.map(function (v) {
|
|
return '0x' + coder.encodeParam(i.type, v);
|
|
});
|
|
}
|
|
return '0x' + coder.encodeParam(i.type, value);
|
|
});
|
|
|
|
result.topics = result.topics.concat(indexedTopics);
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Should be used to decode indexed params and options
|
|
*
|
|
* @method decode
|
|
* @param {Object} data
|
|
* @return {Object} result object with decoded indexed && not indexed params
|
|
*/
|
|
SolidityEvent.prototype.decode = function (data) {
|
|
|
|
data.data = data.data || '';
|
|
data.topics = data.topics || [];
|
|
|
|
var argTopics = this._anonymous ? data.topics : data.topics.slice(1);
|
|
var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join("");
|
|
var indexedParams = coder.decodeParams(this.types(true), indexedData);
|
|
|
|
var notIndexedData = data.data.slice(2);
|
|
var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);
|
|
|
|
var result = formatters.outputLogFormatter(data);
|
|
result.event = this.displayName();
|
|
result.address = data.address;
|
|
|
|
result.args = this._params.reduce(function (acc, current) {
|
|
acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();
|
|
return acc;
|
|
}, {});
|
|
|
|
delete result.data;
|
|
delete result.topics;
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Should be used to create new filter object from event
|
|
*
|
|
* @method execute
|
|
* @param {Object} indexed
|
|
* @param {Object} options
|
|
* @return {Object} filter object
|
|
*/
|
|
SolidityEvent.prototype.execute = function (indexed, options) {
|
|
var o = this.encode(indexed, options);
|
|
var formatter = this.decode.bind(this);
|
|
return web3.eth.filter(o, undefined, undefined, formatter);
|
|
};
|
|
|
|
/**
|
|
* Should be used to attach event to contract object
|
|
*
|
|
* @method attachToContract
|
|
* @param {Contract}
|
|
*/
|
|
SolidityEvent.prototype.attachToContract = function (contract) {
|
|
var execute = this.execute.bind(this);
|
|
var displayName = this.displayName();
|
|
if (!contract[displayName]) {
|
|
contract[displayName] = execute;
|
|
}
|
|
contract[displayName][this.typeName()] = this.execute.bind(this, contract);
|
|
};
|
|
|
|
module.exports = SolidityEvent;
|
|
|
|
|