event refactor in progress

This commit is contained in:
Marek Kotewicz 2015-04-20 21:59:35 +02:00
parent 99a3696e51
commit ea6bda4cbb
4 changed files with 151 additions and 50 deletions

View File

@ -14,9 +14,9 @@
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 contract.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
/**
* @file contract.js
* @author Marek Kotewicz <marek@ethdev.com>
* @date 2014
*/
@ -27,23 +27,9 @@ var solUtils = require('../solidity/utils');
var eventImpl = require('./event');
var signature = require('./signature');
var SolidityFunction = require('./function');
var SolidityEvent = eventImpl.SolidityEvent;
var addFunctionRelatedPropertiesToContract = function (contract) {
contract.call = function (options) {
contract._isTransaction = false;
contract._options = options;
return contract;
};
contract.sendTransaction = function (options) {
contract._isTransaction = true;
contract._options = options;
return contract;
};
};
var addFunctionsToContract = function (contract, desc, address) {
var addFunctionsToContract = function (contract, desc) {
desc.filter(function (json) {
return json.type === 'function';
}).map(function (json) {
@ -71,34 +57,41 @@ var addEventRelatedPropertiesToContract = function (contract, desc, address) {
};
var addEventsToContract = function (contract, desc, address) {
// create contract events
solUtils.filterEvents(desc).forEach(function (e) {
var impl = function () {
var params = Array.prototype.slice.call(arguments);
var sign = signature.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, sign, e);
var o = event.apply(null, params);
var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
return web3.eth.filter(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event
impl._isEvent = true;
var displayName = utils.extractDisplayName(e.name);
var typeName = utils.extractTypeName(e.name);
if (contract[displayName] === undefined) {
contract[displayName] = impl;
}
contract[displayName][typeName] = impl;
desc.filter(function (json) {
return json.type === 'event';
}).map(function (json) {
return new SolidityEvent(json, address);
}).forEach(function (e) {
e.attachToContract(contract);
});
// create contract events
//solUtils.filterEvents(desc).forEach(function (e) {
//var impl = function () {
//var params = Array.prototype.slice.call(arguments);
//var sign = signature.eventSignatureFromAscii(e.name);
//var event = eventImpl.inputParser(address, sign, e);
//var o = event.apply(null, params);
//var outputFormatter = function (data) {
//var parser = eventImpl.outputParser(e);
//return parser(data);
//};
//return web3.eth.filter(o, undefined, undefined, outputFormatter);
//};
//// this property should be used by eth.filter to check if object is an event
//impl._isEvent = true;
//var displayName = utils.extractDisplayName(e.name);
//var typeName = utils.extractTypeName(e.name);
//if (contract[displayName] === undefined) {
//contract[displayName] = impl;
//}
//contract[displayName][typeName] = impl;
//});
};
@ -145,6 +138,8 @@ var Contract = function (abi, options) {
});
this.address = '';
this._isTransaction = null;
this._options = {};
if (utils.isAddress(options)) {
this.address = options;
} else { // is an object!
@ -156,11 +151,22 @@ var Contract = function (abi, options) {
this.address = web3.eth.sendTransaction(options);
}
addFunctionRelatedPropertiesToContract(this);
addFunctionsToContract(this, abi, this.address);
addFunctionsToContract(this, abi);
addEventRelatedPropertiesToContract(this, abi, this.address);
addEventsToContract(this, abi, this.address);
};
Contract.prototype.call = function (options) {
this._isTransaction = false;
this._options = options;
return this;
};
Contract.prototype.sendTransaction = function (options) {
this._isTransaction = true;
this._options = options;
return this;
};
module.exports = contract;

View File

@ -23,6 +23,8 @@
var abi = require('../solidity/abi');
var utils = require('../utils/utils');
var signature = require('./signature');
var coder = require('../solidity/coder');
var web3 = require('../web3');
/// filter inputs array && returns only indexed (or not) inputs
/// @param inputs array
@ -128,11 +130,100 @@ var getMatchingEvent = function (events, payload) {
}
return undefined;
};
//////////
var SolidityEvent = function (json, address) {
this._params = json.inputs;
this._name = json.name;
this._address = address;
};
SolidityEvent.prototype.types = function (indexed) {
return this._params.filter(function (i) {
return i.indexed === indexed;
}).map(function (i) {
return i.type;
});
};
SolidityEvent.prototype.displayName = function () {
return utils.extractDisplayName(this._name);
};
SolidityEvent.prototype.typeName = function () {
return utils.extractTypeName(this._name);
};
SolidityEvent.prototype.signature = function () {
return web3.sha3(web3.fromAscii(this._name)).slice(2);
};
SolidityEvent.prototype.encode = function (indexed, options) {
indexed = indexed || {};
options = options || {};
options.address = this._address;
options.topics = options.topics || [];
options.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) {
return '0x' + coder.encodeParam(i.type, value);
}
return null;
});
options.topics = options.topics.concat(indexedTopics);
return options;
};
SolidityEvent.prototype.decode = function (data) {
var result = {
event: this.displayName(),
number: data.number,
hash: data.hash,
args: {}
};
data.data = data.data || '';
var indexedData = data.topics.slice(1).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);
result.args = this._params.reduce(function (acc, current) {
acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();
return acc;
}, {});
return result;
};
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);
};
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 = {
inputParser: inputParser,
outputParser: outputParser,
getMatchingEvent: getMatchingEvent
getMatchingEvent: getMatchingEvent,
SolidityEvent: SolidityEvent
};

View File

@ -42,6 +42,9 @@ var getOptions = function (options) {
// make sure topics, get converted to hex
options.topics = options.topics || [];
options.topics = options.topics.map(function(topic){
if (topic === null) {
return null;
}
return utils.toHex(topic);
});

View File

@ -63,7 +63,8 @@ describe('web3.eth.contract', function () {
assert.deepEqual(payload.params[0], {
topics: [
sha3,
'0x1234567890123456789012345678901234567890'
'0x1234567890123456789012345678901234567890',
null
],
address: '0x1234567890123456789012345678901234567890'
});