From ea6bda4cbb19db5c716c00a772ef7438efb4f0a3 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 20 Apr 2015 21:59:35 +0200 Subject: [PATCH] event refactor in progress --- lib/web3/contract.js | 102 +++++++++++++++++++++++-------------------- lib/web3/event.js | 93 ++++++++++++++++++++++++++++++++++++++- lib/web3/filter.js | 3 ++ test/contract.js | 3 +- 4 files changed, 151 insertions(+), 50 deletions(-) diff --git a/lib/web3/contract.js b/lib/web3/contract.js index 5a709d9..e24890e 100644 --- a/lib/web3/contract.js +++ b/lib/web3/contract.js @@ -14,9 +14,9 @@ You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** @file contract.js - * @authors: - * Marek Kotewicz +/** + * @file contract.js + * @author Marek Kotewicz * @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; diff --git a/lib/web3/event.js b/lib/web3/event.js index 5d4fe96..f6df1c4 100644 --- a/lib/web3/event.js +++ b/lib/web3/event.js @@ -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 }; diff --git a/lib/web3/filter.js b/lib/web3/filter.js index 43ec3fe..faabfe3 100644 --- a/lib/web3/filter.js +++ b/lib/web3/filter.js @@ -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); }); diff --git a/test/contract.js b/test/contract.js index 88f56ee..3a15c03 100644 --- a/test/contract.js +++ b/test/contract.js @@ -63,7 +63,8 @@ describe('web3.eth.contract', function () { assert.deepEqual(payload.params[0], { topics: [ sha3, - '0x1234567890123456789012345678901234567890' + '0x1234567890123456789012345678901234567890', + null ], address: '0x1234567890123456789012345678901234567890' });