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'
});