merged develop

This commit is contained in:
Fabian Vogelsteller 2015-06-09 12:56:05 +02:00
commit bd6d9ba5b2
24 changed files with 1131 additions and 451 deletions

261
dist/web3-light.js vendored
View File

@ -800,11 +800,19 @@ var BigNumber = require('bignumber.js');
var ETH_UNITS = [
'wei',
'Kwei',
'kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'femtoether',
'picoether',
'nanoether',
'microether',
'milliether',
'nano',
'micro',
'milli',
'ether',
'grand',
'Mether',
@ -825,7 +833,7 @@ module.exports = {
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000,
ETH_POLLING_TIMEOUT: 1000/2,
defaultBlock: 'latest',
defaultAccount: undefined
};
@ -914,12 +922,20 @@ var unitMap = {
'wei': '1',
'kwei': '1000',
'ada': '1000',
'femtoether': '1000',
'mwei': '1000000',
'babbage': '1000000',
'picoether': '1000000',
'gwei': '1000000000',
'shannon': '1000000000',
'nanoether': '1000000000',
'nano': '1000000000',
'szabo': '1000000000000',
'microether': '1000000000000',
'micro': '1000000000000',
'finney': '1000000000000000',
'milliether': '1000000000000000',
'milli': '1000000000000000',
'ether': '1000000000000000000',
'kether': '1000000000000000000000',
'grand': '1000000000000000000000',
@ -1125,13 +1141,14 @@ var getValueOfUnit = function (unit) {
* Takes a number of wei and converts it to any other ether unit.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether
@ -1151,13 +1168,14 @@ var fromWei = function(number, unit) {
* Takes a number of a unit and converts it to wei.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether
@ -1475,8 +1493,7 @@ web3.eth.filter = function (fil, eventParams, options, formatter) {
return fil(eventParams, options);
}
// what outputLogFormatter? that's wrong
//return new Filter(fil, watches.eth(), formatters.outputLogFormatter);
// output logs works for blockFilter and pendingTransaction filters?
return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);
};
/*jshint maxparams:3 */
@ -1531,6 +1548,23 @@ Object.defineProperty(web3.eth, 'defaultAccount', {
}
});
// EXTEND
web3._extend = function(extension){
/*jshint maxcomplexity: 6 */
if(extension.property && !web3[extension.property])
web3[extension.property] = {};
setupMethods(web3[extension.property] || web3, extension.methods || []);
setupProperties(web3[extension.property] || web3, extension.properties || []);
};
web3._extend.formatters = formatters;
web3._extend.utils = utils;
web3._extend.Method = require('./web3/method');
web3._extend.Property = require('./web3/property');
/// setups all api methods
setupProperties(web3, web3Properties);
setupMethods(web3.net, net.methods);
@ -1543,7 +1577,7 @@ setupMethods(web3.shh, shh.methods);
module.exports = web3;
},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){
},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":22,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -2437,21 +2471,36 @@ var getOptions = function (options) {
};
};
var Filter = function (options, methods, formatter) {
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
/**
Adds the callback and sets up the methods, to iterate over the results.
@method getLogsAtStart
@param {Object} self
@param {funciton}
*/
var getLogsAtStart = function(self, callback){
// call getFilterLogs for the first watch callback start
if (!utils.isString(self.options)) {
self.get(function (err, messages) {
// don't send all the responses to all the watches again... just to self one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.formatter = formatter;
this.filterId = this.implementation.newFilter(this.options);
});
}
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
var self = this;
/**
Adds the callback and sets up the methods, to iterate over the results.
@method pollFilter
@param {Object} self
*/
var pollFilter = function(self) {
var onMessage = function (error, messages) {
if (error) {
@ -2468,29 +2517,55 @@ Filter.prototype.watch = function (callback) {
});
};
// call getFilterLogs on start
if (!utils.isString(this.options)) {
this.get(function (err, messages) {
// don't send all the responses to all the watches again... just to this one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
});
}
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
}, this.filterId, onMessage, this.stopWatching.bind(this));
method: self.implementation.poll.call,
params: [self.filterId],
}, self.filterId, onMessage, self.stopWatching.bind(self));
};
var Filter = function (options, methods, formatter) {
var self = this;
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.pollFilters = [];
this.formatter = formatter;
this.implementation.newFilter(this.options, function(error, id){
if(error) {
self.callbacks.forEach(function(callback){
callback(error);
});
} else {
self.filterId = id;
// get filter logs at start
self.callbacks.forEach(function(callback){
getLogsAtStart(self, callback);
});
pollFilter(self);
}
});
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
if(this.filterId) {
getLogsAtStart(this, callback);
pollFilter(this);
}
return this;
};
Filter.prototype.stopWatching = function () {
RequestManager.getInstance().stopPolling(this.filterId);
this.implementation.uninstallFilter(this.filterId);
// remove filter async
this.implementation.uninstallFilter(this.filterId, function(){});
this.callbacks = [];
};
@ -2512,6 +2587,8 @@ Filter.prototype.get = function (callback) {
return self.formatter ? self.formatter(log) : log;
});
}
return this;
};
module.exports = Filter;
@ -2609,7 +2686,9 @@ var inputTransactionFormatter = function (options){
* @returns {Object} transaction
*/
var outputTransactionFormatter = function (tx){
if(tx.blockNumber !== null)
tx.blockNumber = utils.toDecimal(tx.blockNumber);
if(tx.transactionIndex !== null)
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.nonce = utils.toDecimal(tx.nonce);
tx.gas = utils.toDecimal(tx.gas);
@ -2632,6 +2711,7 @@ var outputBlockFormatter = function(block) {
block.gasUsed = utils.toDecimal(block.gasUsed);
block.size = utils.toDecimal(block.size);
block.timestamp = utils.toDecimal(block.timestamp);
if(block.number !== null)
block.number = utils.toDecimal(block.number);
block.difficulty = utils.toBigNumber(block.difficulty);
@ -2659,8 +2739,11 @@ var outputLogFormatter = function(log) {
return null;
}
if(log.blockNumber !== null)
log.blockNumber = utils.toDecimal(log.blockNumber);
if(log.transactionIndex !== null)
log.transactionIndex = utils.toDecimal(log.transactionIndex);
if(log.logIndex !== null)
log.logIndex = utils.toDecimal(log.logIndex);
return log;
@ -2763,6 +2846,7 @@ module.exports = {
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
var formatters = require('./formatters');
var sha3 = require('../utils/sha3');
/**
@ -2786,6 +2870,12 @@ SolidityFunction.prototype.extractCallback = function (args) {
}
};
SolidityFunction.prototype.extractDefaultBlock = function (args) {
if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {
return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!
}
};
/**
* Should be used to create payload from arguments
*
@ -2837,15 +2927,17 @@ SolidityFunction.prototype.unpackOutput = function (output) {
SolidityFunction.prototype.call = function () {
var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });
var callback = this.extractCallback(args);
var defaultBlock = this.extractDefaultBlock(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload);
var output = web3.eth.call(payload, defaultBlock);
return this.unpackOutput(output);
}
var self = this;
web3.eth.call(payload, function (error, output) {
web3.eth.call(payload, defaultBlock, function (error, output) {
callback(error, self.unpackOutput(output));
});
};
@ -2964,7 +3056,7 @@ SolidityFunction.prototype.attachToContract = function (contract) {
module.exports = SolidityFunction;
},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9}],19:[function(require,module,exports){
},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -3002,6 +3094,7 @@ HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -3045,6 +3138,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
};
request.open('POST', this.host, true);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -3730,9 +3824,9 @@ var RequestManager = function (provider) {
arguments.callee._singletonInstance = this;
this.provider = provider;
this.polls = [];
this.polls = {};
this.timeout = null;
this.poll();
this.isPolling = false;
};
/**
@ -3827,6 +3921,11 @@ RequestManager.prototype.sendBatch = function (data, callback) {
*/
RequestManager.prototype.setProvider = function (p) {
this.provider = p;
if(this.provider && !this.isPolling) {
this.poll();
this.isPolling = true;
}
};
/*jshint maxparams:4 */
@ -3843,7 +3942,7 @@ RequestManager.prototype.setProvider = function (p) {
* @todo cleanup number of params
*/
RequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {
this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
this.polls['poll_'+ pollId] = {data: data, id: pollId, callback: callback, uninstall: uninstall};
};
/*jshint maxparams:3 */
@ -3854,24 +3953,21 @@ RequestManager.prototype.startPolling = function (data, pollId, callback, uninst
* @param {Number} pollId
*/
RequestManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
delete this.polls['poll_'+ pollId];
};
/**
* Should be called to reset polling mechanism of request manager
* Should be called to reset the polling mechanism of the request manager
*
* @method reset
*/
RequestManager.prototype.reset = function () {
this.polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
this.polls = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
this.polls[key].uninstall();
}
}
this.polls = {};
if (this.timeout) {
clearTimeout(this.timeout);
@ -3886,9 +3982,10 @@ RequestManager.prototype.reset = function () {
* @method poll
*/
RequestManager.prototype.poll = function () {
/*jshint maxcomplexity: 6 */
this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);
if (!this.polls.length) {
if (this.polls === {}) {
return;
}
@ -3897,9 +3994,20 @@ RequestManager.prototype.poll = function () {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {
return data.data;
}));
var pollsData = [];
var pollsKeys = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
pollsData.push(this.polls[key].data);
pollsKeys.push(key);
}
}
if (pollsData.length === 0) {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(pollsData);
var self = this;
this.provider.sendAsync(payload, function (error, results) {
@ -3913,8 +4021,15 @@ RequestManager.prototype.poll = function () {
}
results.map(function (result, index) {
result.callback = self.polls[index].callback;
var key = pollsKeys[index];
// make sure the filter is still installed after arrival of the request
if(self.polls[key]) {
result.callback = self.polls[key].callback;
return result;
} else
return false;
}).filter(function (result) {
return (!result) ? false : true;
}).filter(function (result) {
var valid = Jsonrpc.getInstance().isValidResponse(result);
if (!valid) {
@ -4130,11 +4245,11 @@ var eth = function () {
switch(type) {
case 'latest':
args.pop();
args.shift();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
args.shift();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

261
dist/web3.js vendored
View File

@ -800,11 +800,19 @@ var BigNumber = require('bignumber.js');
var ETH_UNITS = [
'wei',
'Kwei',
'kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'femtoether',
'picoether',
'nanoether',
'microether',
'milliether',
'nano',
'micro',
'milli',
'ether',
'grand',
'Mether',
@ -825,7 +833,7 @@ module.exports = {
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000,
ETH_POLLING_TIMEOUT: 1000/2,
defaultBlock: 'latest',
defaultAccount: undefined
};
@ -914,12 +922,20 @@ var unitMap = {
'wei': '1',
'kwei': '1000',
'ada': '1000',
'femtoether': '1000',
'mwei': '1000000',
'babbage': '1000000',
'picoether': '1000000',
'gwei': '1000000000',
'shannon': '1000000000',
'nanoether': '1000000000',
'nano': '1000000000',
'szabo': '1000000000000',
'microether': '1000000000000',
'micro': '1000000000000',
'finney': '1000000000000000',
'milliether': '1000000000000000',
'milli': '1000000000000000',
'ether': '1000000000000000000',
'kether': '1000000000000000000000',
'grand': '1000000000000000000000',
@ -1125,13 +1141,14 @@ var getValueOfUnit = function (unit) {
* Takes a number of wei and converts it to any other ether unit.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether
@ -1151,13 +1168,14 @@ var fromWei = function(number, unit) {
* Takes a number of a unit and converts it to wei.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether
@ -1475,8 +1493,7 @@ web3.eth.filter = function (fil, eventParams, options, formatter) {
return fil(eventParams, options);
}
// what outputLogFormatter? that's wrong
//return new Filter(fil, watches.eth(), formatters.outputLogFormatter);
// output logs works for blockFilter and pendingTransaction filters?
return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);
};
/*jshint maxparams:3 */
@ -1531,6 +1548,23 @@ Object.defineProperty(web3.eth, 'defaultAccount', {
}
});
// EXTEND
web3._extend = function(extension){
/*jshint maxcomplexity: 6 */
if(extension.property && !web3[extension.property])
web3[extension.property] = {};
setupMethods(web3[extension.property] || web3, extension.methods || []);
setupProperties(web3[extension.property] || web3, extension.properties || []);
};
web3._extend.formatters = formatters;
web3._extend.utils = utils;
web3._extend.Method = require('./web3/method');
web3._extend.Property = require('./web3/property');
/// setups all api methods
setupProperties(web3, web3Properties);
setupMethods(web3.net, net.methods);
@ -1543,7 +1577,7 @@ setupMethods(web3.shh, shh.methods);
module.exports = web3;
},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){
},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":10,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":22,"./web3/net":24,"./web3/property":25,"./web3/requestmanager":27,"./web3/shh":28,"./web3/watches":30}],10:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -2437,21 +2471,36 @@ var getOptions = function (options) {
};
};
var Filter = function (options, methods, formatter) {
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
/**
Adds the callback and sets up the methods, to iterate over the results.
@method getLogsAtStart
@param {Object} self
@param {funciton}
*/
var getLogsAtStart = function(self, callback){
// call getFilterLogs for the first watch callback start
if (!utils.isString(self.options)) {
self.get(function (err, messages) {
// don't send all the responses to all the watches again... just to self one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.formatter = formatter;
this.filterId = this.implementation.newFilter(this.options);
});
}
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
var self = this;
/**
Adds the callback and sets up the methods, to iterate over the results.
@method pollFilter
@param {Object} self
*/
var pollFilter = function(self) {
var onMessage = function (error, messages) {
if (error) {
@ -2468,29 +2517,55 @@ Filter.prototype.watch = function (callback) {
});
};
// call getFilterLogs on start
if (!utils.isString(this.options)) {
this.get(function (err, messages) {
// don't send all the responses to all the watches again... just to this one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
});
}
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
}, this.filterId, onMessage, this.stopWatching.bind(this));
method: self.implementation.poll.call,
params: [self.filterId],
}, self.filterId, onMessage, self.stopWatching.bind(self));
};
var Filter = function (options, methods, formatter) {
var self = this;
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.pollFilters = [];
this.formatter = formatter;
this.implementation.newFilter(this.options, function(error, id){
if(error) {
self.callbacks.forEach(function(callback){
callback(error);
});
} else {
self.filterId = id;
// get filter logs at start
self.callbacks.forEach(function(callback){
getLogsAtStart(self, callback);
});
pollFilter(self);
}
});
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
if(this.filterId) {
getLogsAtStart(this, callback);
pollFilter(this);
}
return this;
};
Filter.prototype.stopWatching = function () {
RequestManager.getInstance().stopPolling(this.filterId);
this.implementation.uninstallFilter(this.filterId);
// remove filter async
this.implementation.uninstallFilter(this.filterId, function(){});
this.callbacks = [];
};
@ -2512,6 +2587,8 @@ Filter.prototype.get = function (callback) {
return self.formatter ? self.formatter(log) : log;
});
}
return this;
};
module.exports = Filter;
@ -2609,7 +2686,9 @@ var inputTransactionFormatter = function (options){
* @returns {Object} transaction
*/
var outputTransactionFormatter = function (tx){
if(tx.blockNumber !== null)
tx.blockNumber = utils.toDecimal(tx.blockNumber);
if(tx.transactionIndex !== null)
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.nonce = utils.toDecimal(tx.nonce);
tx.gas = utils.toDecimal(tx.gas);
@ -2632,6 +2711,7 @@ var outputBlockFormatter = function(block) {
block.gasUsed = utils.toDecimal(block.gasUsed);
block.size = utils.toDecimal(block.size);
block.timestamp = utils.toDecimal(block.timestamp);
if(block.number !== null)
block.number = utils.toDecimal(block.number);
block.difficulty = utils.toBigNumber(block.difficulty);
@ -2659,8 +2739,11 @@ var outputLogFormatter = function(log) {
return null;
}
if(log.blockNumber !== null)
log.blockNumber = utils.toDecimal(log.blockNumber);
if(log.transactionIndex !== null)
log.transactionIndex = utils.toDecimal(log.transactionIndex);
if(log.logIndex !== null)
log.logIndex = utils.toDecimal(log.logIndex);
return log;
@ -2763,6 +2846,7 @@ module.exports = {
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
var formatters = require('./formatters');
var sha3 = require('../utils/sha3');
/**
@ -2786,6 +2870,12 @@ SolidityFunction.prototype.extractCallback = function (args) {
}
};
SolidityFunction.prototype.extractDefaultBlock = function (args) {
if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {
return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!
}
};
/**
* Should be used to create payload from arguments
*
@ -2837,15 +2927,17 @@ SolidityFunction.prototype.unpackOutput = function (output) {
SolidityFunction.prototype.call = function () {
var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });
var callback = this.extractCallback(args);
var defaultBlock = this.extractDefaultBlock(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload);
var output = web3.eth.call(payload, defaultBlock);
return this.unpackOutput(output);
}
var self = this;
web3.eth.call(payload, function (error, output) {
web3.eth.call(payload, defaultBlock, function (error, output) {
callback(error, self.unpackOutput(output));
});
};
@ -2964,7 +3056,7 @@ SolidityFunction.prototype.attachToContract = function (contract) {
module.exports = SolidityFunction;
},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9}],19:[function(require,module,exports){
},{"../solidity/coder":1,"../utils/sha3":6,"../utils/utils":7,"../web3":9,"./formatters":17}],19:[function(require,module,exports){
/*
This file is part of ethereum.js.
@ -3002,6 +3094,7 @@ HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -3045,6 +3138,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
};
request.open('POST', this.host, true);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -3730,9 +3824,9 @@ var RequestManager = function (provider) {
arguments.callee._singletonInstance = this;
this.provider = provider;
this.polls = [];
this.polls = {};
this.timeout = null;
this.poll();
this.isPolling = false;
};
/**
@ -3827,6 +3921,11 @@ RequestManager.prototype.sendBatch = function (data, callback) {
*/
RequestManager.prototype.setProvider = function (p) {
this.provider = p;
if(this.provider && !this.isPolling) {
this.poll();
this.isPolling = true;
}
};
/*jshint maxparams:4 */
@ -3843,7 +3942,7 @@ RequestManager.prototype.setProvider = function (p) {
* @todo cleanup number of params
*/
RequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {
this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
this.polls['poll_'+ pollId] = {data: data, id: pollId, callback: callback, uninstall: uninstall};
};
/*jshint maxparams:3 */
@ -3854,24 +3953,21 @@ RequestManager.prototype.startPolling = function (data, pollId, callback, uninst
* @param {Number} pollId
*/
RequestManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
delete this.polls['poll_'+ pollId];
};
/**
* Should be called to reset polling mechanism of request manager
* Should be called to reset the polling mechanism of the request manager
*
* @method reset
*/
RequestManager.prototype.reset = function () {
this.polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
this.polls = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
this.polls[key].uninstall();
}
}
this.polls = {};
if (this.timeout) {
clearTimeout(this.timeout);
@ -3886,9 +3982,10 @@ RequestManager.prototype.reset = function () {
* @method poll
*/
RequestManager.prototype.poll = function () {
/*jshint maxcomplexity: 6 */
this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);
if (!this.polls.length) {
if (this.polls === {}) {
return;
}
@ -3897,9 +3994,20 @@ RequestManager.prototype.poll = function () {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {
return data.data;
}));
var pollsData = [];
var pollsKeys = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
pollsData.push(this.polls[key].data);
pollsKeys.push(key);
}
}
if (pollsData.length === 0) {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(pollsData);
var self = this;
this.provider.sendAsync(payload, function (error, results) {
@ -3913,8 +4021,15 @@ RequestManager.prototype.poll = function () {
}
results.map(function (result, index) {
result.callback = self.polls[index].callback;
var key = pollsKeys[index];
// make sure the filter is still installed after arrival of the request
if(self.polls[key]) {
result.callback = self.polls[key].callback;
return result;
} else
return false;
}).filter(function (result) {
return (!result) ? false : true;
}).filter(function (result) {
var valid = Jsonrpc.getInstance().isValidResponse(result);
if (!valid) {
@ -4130,11 +4245,11 @@ var eth = function () {
switch(type) {
case 'latest':
args.pop();
args.shift();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
args.shift();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:

20
dist/web3.js.map vendored

File diff suppressed because one or more lines are too long

6
dist/web3.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -11,92 +11,193 @@
var from = web3.eth.coinbase;
web3.eth.defaultAccount = from;
/*
window.onload = function () {
var abi = [{
"anonymous" : false,
"inputs" : [
{
"indexed" : true,
"name" : "from",
"type" : "address"
},
{
"indexed" : true,
"name" : "to",
"type" : "bytes32"
},
{
"indexed" : false,
"name" : "value",
"type" : "uint256"
}
],
"name" : "Deposit",
"type" : "event"
}];
var nameregAbi = [
{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},
{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},
{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},
{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}
];
var ExchangeInterface = web3.eth.contract(abi).at(web3.eth.namereg.addr('XROO'));
var filter = ExchangeInterface.Deposit({}, {fromBlock: 0});
filter.watch(function (err, event) {
console.log(event);
displayDeposit("block: " + event.blockNumber + " user: " + event.args._id + "\nvalue : " + event.args._value.toString(10));
});
var depositAbi = [{"constant":false,"inputs":[{"name":"name","type":"bytes32"}],"name":"deposit","outputs":[],"type":"function"}];
var Namereg = web3.eth.contract(nameregAbi);
var Deposit = web3.eth.contract(depositAbi);
var namereg = web3.eth.namereg;
var deposit;
var iban;
function validateNamereg() {
var address = document.getElementById('namereg').value;
var ok = /^(0x)?[0-9a-f]{40}$/.test(address) || address === 'default';
if (ok) {
namereg = address === 'default' ? web3.eth.namereg : Namereg.at(address);
document.getElementById('nameregValidation').innerText = 'ok!';
} else {
document.getElementById('nameregValidation').innerText = 'namereg address is incorrect!';
}
return ok;
};
*/
function displayDeposit(text) {
var node = document.createElement('li');
var textnode = document.createTextNode(text);
node.appendChild(textnode);
document.getElementById('deposits').appendChild(node);
function onNameregKeyUp() {
updateIBAN(validateNamereg());
onExchangeKeyUp();
};
function validateExchange() {
var exchange = document.getElementById('exchange').value;
var ok = /^[0-9A-Z]{4}$/.test(exchange);
if (ok) {
var address = namereg.addr(exchange);
deposit = Deposit.at(address);
document.getElementById('exchangeValidation').innerText = 'ok! address of exchange: ' + address;
} else {
document.getElementById('exchangeValidation').innerText = 'exchange id is incorrect';
}
return ok;
};
function onExchangeKeyUp() {
updateIBAN(validateExchange());
};
function validateClient() {
var client = document.getElementById('client').value;
var ok = /^[0-9A-Z]{9}$/.test(client);
if (ok) {
document.getElementById('clientValidation').innerText = 'ok!';
} else {
document.getElementById('clientValidation').innerText = 'client id is incorrect';
}
return ok;
};
function onClientKeyUp() {
updateIBAN(validateClient());
};
function validateValue() {
try {
var value = document.getElementById('value').value;
var bnValue = new BigNumber(value);
document.getElementById('valueValidation').innerText = bnValue.toString(10);
return true;
} catch (err) {
document.getElementById('valueValidation').innerText = 'Value is incorrect, cannot parse';
return false;
}
};
function onValueKeyUp() {
validateValue();
};
function validateIBAN() {
var iban = document.getElementById('iban').value;
if (!web3.isIBAN(iban)) {
return document.getElementById('ibanValidation').innerText = 'IBAN number is incorrect';
return document.getElementById('ibanValidation').innerText = ' - IBAN number is incorrect';
}
var institution = iban.substr(7, 4);
var address = web3.eth.namereg.addr(institution);
document.getElementById('ibanValidation').innerText = 'IBAN number correct, exchange address: ' + address;
document.getElementById('ibanValidation').innerText = ' - IBAN number correct';
};
function updateIBAN(ok) {
var exchangeId = document.getElementById('exchange').value;
var clientId = document.getElementById('client').value;
iban = 'XE' + '00' + 'ETH' + exchangeId + clientId;
document.getElementById('iban').innerText = iban;
validateIBAN();
};
function transfer() {
var value = new BigNumber(document.getElementById('value').value);
var iban = document.getElementById('iban').value;
web3.eth.sendIBANTransaction(from, iban, value);
var exchange = document.getElementById('exchange').value;
var client = document.getElementById('client').value;
deposit.deposit(client, {value: value});
displayTransfer("deposited client's " + client + " funds " + value.toString(10) + " to exchange " + exchange);
};
function displayTransfer(text) {
var node = document.createElement('li');
var textnode = document.createTextNode(text);
node.appendChild(textnode);
document.getElementById('transfers').appendChild(node);
}
</script>
</head>
<body>
<h1>ICAP</h1>
<h3>Transfer</h3>
<h1>ICAP transfer</h1>
<div>
<text>Destination IBAN (eg. XE81ETHXROOGAVOFYORK): </text>
<input type="text" id="iban" onkeyup='validateIBAN()'></input>
<text id="ibanValidation"></text>
<h4>namereg address</h4>
</div>
<div>
<text>Value: </text>
<input type="text" id="value" onkeyup='validateValue()'></input>
<text>eg. 0x436474facc88948696b371052a1befb801f003ca or 'default')</text>
</div>
<div>
<input type="text" id="namereg" onkeyup='onNameregKeyUp()' value="default"></input>
<text id="nameregValidation"></text>
</div>
<div>
<h4>exchange identifier</h4>
</div>
<div>
<text>eg. WYWY</text>
</div>
<div>
<input type="text" id="exchange" onkeyup='onExchangeKeyUp()'></input>
<text id="exchangeValidation"></text>
</div>
<div>
<h4>client identifier</h4>
</div>
<div>
<text>eg. GAVOFYORK</text>
</div>
<div>
<input type="text" id="client" onkeyup='onClientKeyUp()'></input>
<text id="clientValidation"></text>
</div>
<div>
<h4>value</h4>
</div>
<div>
<text>eg. 100</text>
</div>
<div>
<input type="text" id="value" onkeyup='onValueKeyUp()'></input>
<text id="valueValidation"></text>
</div>
<div>&nbsp;</div>
<div>
<text>IBAN: </text>
<text id="iban"></text>
<text id="ibanValidation"></text>
</div>
<div>&nbsp;</div>
<div>
<button id="transfer" type="button" onClick="transfer()">Transfer!</button>
<text id="transferValidation"></text>
</div>
<div>
<h4>transfers</h4>
</div>
<div>
<ul id='transfers'></ul>
</div>
<h3 style="visibility: hidden;">"XREG" Exchange deposits</h3>
<ul style="visibility: hidden;" id="deposits"></ul>
</body>
</html>

View File

@ -38,11 +38,19 @@ var BigNumber = require('bignumber.js');
var ETH_UNITS = [
'wei',
'Kwei',
'kwei',
'Mwei',
'Gwei',
'szabo',
'finney',
'femtoether',
'picoether',
'nanoether',
'microether',
'milliether',
'nano',
'micro',
'milli',
'ether',
'grand',
'Mether',
@ -63,7 +71,7 @@ module.exports = {
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
ETH_POLLING_TIMEOUT: 1000,
ETH_POLLING_TIMEOUT: 1000/2,
defaultBlock: 'latest',
defaultAccount: undefined
};

View File

@ -39,12 +39,20 @@ var unitMap = {
'wei': '1',
'kwei': '1000',
'ada': '1000',
'femtoether': '1000',
'mwei': '1000000',
'babbage': '1000000',
'picoether': '1000000',
'gwei': '1000000000',
'shannon': '1000000000',
'nanoether': '1000000000',
'nano': '1000000000',
'szabo': '1000000000000',
'microether': '1000000000000',
'micro': '1000000000000',
'finney': '1000000000000000',
'milliether': '1000000000000000',
'milli': '1000000000000000',
'ether': '1000000000000000000',
'kether': '1000000000000000000000',
'grand': '1000000000000000000000',
@ -250,13 +258,14 @@ var getValueOfUnit = function (unit) {
* Takes a number of wei and converts it to any other ether unit.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether
@ -276,13 +285,14 @@ var fromWei = function(number, unit) {
* Takes a number of a unit and converts it to wei.
*
* Possible units are:
* - kwei/ada
* - mwei/babbage
* - gwei/shannon
* - szabo
* - finney
* - ether
* - kether/grand/einstein
* SI Short SI Full Effigy Other
* - kwei femtoether ada
* - mwei picoether babbage
* - gwei nanoether shannon nano
* - -- microether szabo micro
* - -- milliether finney milli
* - ether -- --
* - kether einstein grand
* - mether
* - gether
* - tether

View File

@ -93,8 +93,7 @@ web3.eth.filter = function (fil, eventParams, options, formatter) {
return fil(eventParams, options);
}
// what outputLogFormatter? that's wrong
//return new Filter(fil, watches.eth(), formatters.outputLogFormatter);
// output logs works for blockFilter and pendingTransaction filters?
return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);
};
/*jshint maxparams:3 */
@ -149,6 +148,23 @@ Object.defineProperty(web3.eth, 'defaultAccount', {
}
});
// EXTEND
web3._extend = function(extension){
/*jshint maxcomplexity: 6 */
if(extension.property && !web3[extension.property])
web3[extension.property] = {};
setupMethods(web3[extension.property] || web3, extension.methods || []);
setupProperties(web3[extension.property] || web3, extension.properties || []);
};
web3._extend.formatters = formatters;
web3._extend.utils = utils;
web3._extend.Method = require('./web3/method');
web3._extend.Property = require('./web3/property');
/// setups all api methods
setupProperties(web3, web3Properties);
setupMethods(web3.net, net.methods);

View File

@ -74,21 +74,36 @@ var getOptions = function (options) {
};
};
var Filter = function (options, methods, formatter) {
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
/**
Adds the callback and sets up the methods, to iterate over the results.
@method getLogsAtStart
@param {Object} self
@param {funciton}
*/
var getLogsAtStart = function(self, callback){
// call getFilterLogs for the first watch callback start
if (!utils.isString(self.options)) {
self.get(function (err, messages) {
// don't send all the responses to all the watches again... just to self one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.formatter = formatter;
this.filterId = this.implementation.newFilter(this.options);
});
}
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
var self = this;
/**
Adds the callback and sets up the methods, to iterate over the results.
@method pollFilter
@param {Object} self
*/
var pollFilter = function(self) {
var onMessage = function (error, messages) {
if (error) {
@ -105,29 +120,55 @@ Filter.prototype.watch = function (callback) {
});
};
// call getFilterLogs on start
if (!utils.isString(this.options)) {
this.get(function (err, messages) {
// don't send all the responses to all the watches again... just to this one
if (err) {
callback(err);
}
messages.forEach(function (message) {
callback(null, message);
});
});
}
RequestManager.getInstance().startPolling({
method: this.implementation.poll.call,
params: [this.filterId],
}, this.filterId, onMessage, this.stopWatching.bind(this));
method: self.implementation.poll.call,
params: [self.filterId],
}, self.filterId, onMessage, self.stopWatching.bind(self));
};
var Filter = function (options, methods, formatter) {
var self = this;
var implementation = {};
methods.forEach(function (method) {
method.attachToObject(implementation);
});
this.options = getOptions(options);
this.implementation = implementation;
this.callbacks = [];
this.pollFilters = [];
this.formatter = formatter;
this.implementation.newFilter(this.options, function(error, id){
if(error) {
self.callbacks.forEach(function(callback){
callback(error);
});
} else {
self.filterId = id;
// get filter logs at start
self.callbacks.forEach(function(callback){
getLogsAtStart(self, callback);
});
pollFilter(self);
}
});
};
Filter.prototype.watch = function (callback) {
this.callbacks.push(callback);
if(this.filterId) {
getLogsAtStart(this, callback);
pollFilter(this);
}
return this;
};
Filter.prototype.stopWatching = function () {
RequestManager.getInstance().stopPolling(this.filterId);
this.implementation.uninstallFilter(this.filterId);
// remove filter async
this.implementation.uninstallFilter(this.filterId, function(){});
this.callbacks = [];
};
@ -149,6 +190,8 @@ Filter.prototype.get = function (callback) {
return self.formatter ? self.formatter(log) : log;
});
}
return this;
};
module.exports = Filter;

View File

@ -89,7 +89,9 @@ var inputTransactionFormatter = function (options){
* @returns {Object} transaction
*/
var outputTransactionFormatter = function (tx){
if(tx.blockNumber !== null)
tx.blockNumber = utils.toDecimal(tx.blockNumber);
if(tx.transactionIndex !== null)
tx.transactionIndex = utils.toDecimal(tx.transactionIndex);
tx.nonce = utils.toDecimal(tx.nonce);
tx.gas = utils.toDecimal(tx.gas);
@ -112,6 +114,7 @@ var outputBlockFormatter = function(block) {
block.gasUsed = utils.toDecimal(block.gasUsed);
block.size = utils.toDecimal(block.size);
block.timestamp = utils.toDecimal(block.timestamp);
if(block.number !== null)
block.number = utils.toDecimal(block.number);
block.difficulty = utils.toBigNumber(block.difficulty);
@ -139,8 +142,11 @@ var outputLogFormatter = function(log) {
return null;
}
if(log.blockNumber !== null)
log.blockNumber = utils.toDecimal(log.blockNumber);
if(log.transactionIndex !== null)
log.transactionIndex = utils.toDecimal(log.transactionIndex);
if(log.logIndex !== null)
log.logIndex = utils.toDecimal(log.logIndex);
return log;

View File

@ -23,6 +23,7 @@
var web3 = require('../web3');
var coder = require('../solidity/coder');
var utils = require('../utils/utils');
var formatters = require('./formatters');
var sha3 = require('../utils/sha3');
/**
@ -46,6 +47,12 @@ SolidityFunction.prototype.extractCallback = function (args) {
}
};
SolidityFunction.prototype.extractDefaultBlock = function (args) {
if (args.length > this._inputTypes.length && !utils.isObject(args[args.length -1])) {
return formatters.inputDefaultBlockNumberFormatter(args.pop()); // modify the args array!
}
};
/**
* Should be used to create payload from arguments
*
@ -97,15 +104,17 @@ SolidityFunction.prototype.unpackOutput = function (output) {
SolidityFunction.prototype.call = function () {
var args = Array.prototype.slice.call(arguments).filter(function (a) {return a !== undefined; });
var callback = this.extractCallback(args);
var defaultBlock = this.extractDefaultBlock(args);
var payload = this.toPayload(args);
if (!callback) {
var output = web3.eth.call(payload);
var output = web3.eth.call(payload, defaultBlock);
return this.unpackOutput(output);
}
var self = this;
web3.eth.call(payload, function (error, output) {
web3.eth.call(payload, defaultBlock, function (error, output) {
callback(error, self.unpackOutput(output));
});
};

View File

@ -35,6 +35,7 @@ HttpProvider.prototype.send = function (payload) {
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));
@ -78,6 +79,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) {
};
request.open('POST', this.host, true);
request.setRequestHeader('Content-type','application/json');
try {
request.send(JSON.stringify(payload));

View File

@ -43,9 +43,9 @@ var RequestManager = function (provider) {
arguments.callee._singletonInstance = this;
this.provider = provider;
this.polls = [];
this.polls = {};
this.timeout = null;
this.poll();
this.isPolling = false;
};
/**
@ -140,6 +140,11 @@ RequestManager.prototype.sendBatch = function (data, callback) {
*/
RequestManager.prototype.setProvider = function (p) {
this.provider = p;
if(this.provider && !this.isPolling) {
this.poll();
this.isPolling = true;
}
};
/*jshint maxparams:4 */
@ -156,7 +161,7 @@ RequestManager.prototype.setProvider = function (p) {
* @todo cleanup number of params
*/
RequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {
this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
this.polls['poll_'+ pollId] = {data: data, id: pollId, callback: callback, uninstall: uninstall};
};
/*jshint maxparams:3 */
@ -167,24 +172,21 @@ RequestManager.prototype.startPolling = function (data, pollId, callback, uninst
* @param {Number} pollId
*/
RequestManager.prototype.stopPolling = function (pollId) {
for (var i = this.polls.length; i--;) {
var poll = this.polls[i];
if (poll.id === pollId) {
this.polls.splice(i, 1);
}
}
delete this.polls['poll_'+ pollId];
};
/**
* Should be called to reset polling mechanism of request manager
* Should be called to reset the polling mechanism of the request manager
*
* @method reset
*/
RequestManager.prototype.reset = function () {
this.polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
this.polls = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
this.polls[key].uninstall();
}
}
this.polls = {};
if (this.timeout) {
clearTimeout(this.timeout);
@ -199,9 +201,10 @@ RequestManager.prototype.reset = function () {
* @method poll
*/
RequestManager.prototype.poll = function () {
/*jshint maxcomplexity: 6 */
this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);
if (!this.polls.length) {
if (this.polls === {}) {
return;
}
@ -210,9 +213,20 @@ RequestManager.prototype.poll = function () {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {
return data.data;
}));
var pollsData = [];
var pollsKeys = [];
for (var key in this.polls) {
if (this.polls.hasOwnProperty(key)) {
pollsData.push(this.polls[key].data);
pollsKeys.push(key);
}
}
if (pollsData.length === 0) {
return;
}
var payload = Jsonrpc.getInstance().toBatchPayload(pollsData);
var self = this;
this.provider.sendAsync(payload, function (error, results) {
@ -226,8 +240,15 @@ RequestManager.prototype.poll = function () {
}
results.map(function (result, index) {
result.callback = self.polls[index].callback;
var key = pollsKeys[index];
// make sure the filter is still installed after arrival of the request
if(self.polls[key]) {
result.callback = self.polls[key].callback;
return result;
} else
return false;
}).filter(function (result) {
return (!result) ? false : true;
}).filter(function (result) {
var valid = Jsonrpc.getInstance().isValidResponse(result);
if (!valid) {

View File

@ -29,11 +29,11 @@ var eth = function () {
switch(type) {
case 'latest':
args.pop();
args.shift();
this.params = 0;
return 'eth_newBlockFilter';
case 'pending':
args.pop();
args.shift();
this.params = 0;
return 'eth_newPendingTransactionFilter';
default:

View File

@ -66,7 +66,7 @@ describe('web3.eth.contract', function () {
provider.injectValidation(function (payload) {
if (step === 0) {
step = 1;
provider.injectResult(3);
provider.injectResult('0x3');
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, 'eth_newFilter');
assert.deepEqual(payload.params[0], {
@ -105,7 +105,7 @@ describe('web3.eth.contract', function () {
'0000000000000000000000000000000000000000000000000000000000000008'
}]]);
var r = payload.filter(function (p) {
return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === 3;
return p.jsonrpc === '2.0' && p.method === 'eth_getFilterChanges' && p.params[0] === '0x3';
});
assert.equal(r.length > 0, true);
}
@ -114,7 +114,8 @@ describe('web3.eth.contract', function () {
var contract = web3.eth.contract(desc).at(address);
var res = 0;
contract.Changed({from: address}).watch(function(err, result) {
var event = contract.Changed({from: address});
event.watch(function(err, result) {
assert.equal(result.args.from, address);
assert.equal(result.args.amount, 1);
assert.equal(result.args.t1, 1);
@ -133,6 +134,7 @@ describe('web3.eth.contract', function () {
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)'
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
@ -147,6 +149,28 @@ describe('web3.eth.contract', function () {
assert.deepEqual(new BigNumber(0x32), r);
});
it('should call constant function with default block', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)'
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: '0x' + sha3(signature).slice(0, 8) + '0000000000000000000000001234567890123456789012345678901234567890',
to: address
}, '0xb']);
});
var contract = web3.eth.contract(desc).at(address);
var r = contract.balance(address, 11);
assert.deepEqual(new BigNumber(0x32), r);
});
it('should sendTransaction to contract function', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
@ -218,6 +242,31 @@ describe('web3.eth.contract', function () {
});
it('should explicitly make a call with optional params and defaultBlock', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);
web3.reset();
provider.injectResult('0x0000000000000000000000000000000000000000000000000000000000000032');
var signature = 'balance(address)';
var address = '0x1234567890123456789012345678901234567890';
provider.injectValidation(function (payload) {
assert.equal(payload.method, 'eth_call');
assert.deepEqual(payload.params, [{
data: '0x' + sha3(signature).slice(0, 8) + '0000000000000000000000001234567890123456789012345678901234567890',
to: address,
from: address,
gas: '0xc350'
}, '0xb']);
});
var contract = web3.eth.contract(desc).at(address);
var r = contract.balance.call(address, {from: address, gas: 50000}, 11);
assert.deepEqual(new BigNumber(0x32), r);
});
it('should sendTransaction with optional params', function () {
var provider = new FakeHttpProvider();
web3.setProvider(provider);

View File

@ -8,38 +8,72 @@ describe('formatters', function () {
it('should return the correct value', function () {
assert.deepEqual(formatters.outputBlockFormatter({
hash: '0x34234kjh23kj4234',
parentHash: '0x34234kjh23kj4234',
miner: '0x34234kjh23kj4234',
stateRoot: '0x34234kjh23kj4234',
sha3Uncles: '0x34234kjh23kj4234',
bloom: '0x34234kjh23kj4234',
hash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: '0xdcc6960376d6c6dea93647383ffb245cfced97cf',
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: '0x3e8',
totalDifficulty: '0x3e8',
number: '0x3e8',
gasLimit: '0x3e8',
gasUsed: '0x3e8',
timestamp: '0x3e8',
extraData: '0x34234kjh23kj4234',
nonce: '0x34234kjh23kj4234',
children: ['0x34234kjh23kj4234'],
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
size: '0x3e8'
}), {
hash: '0x34234kjh23kj4234',
parentHash: '0x34234kjh23kj4234',
miner: '0x34234kjh23kj4234',
stateRoot: '0x34234kjh23kj4234',
sha3Uncles: '0x34234kjh23kj4234',
bloom: '0x34234kjh23kj4234',
hash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: '0xdcc6960376d6c6dea93647383ffb245cfced97cf',
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: new BigNumber(1000),
totalDifficulty: new BigNumber(1000),
number: 1000,
gasLimit: 1000,
gasUsed: 1000,
timestamp: 1000,
extraData: '0x34234kjh23kj4234',
nonce: '0x34234kjh23kj4234',
children: ['0x34234kjh23kj4234'],
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
size: 1000
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputBlockFormatter({
hash: null,
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: null,
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: '0x3e8',
totalDifficulty: '0x3e8',
number: null,
gasLimit: '0x3e8',
gasUsed: '0x3e8',
timestamp: '0x3e8',
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: null,
size: '0x3e8'
}), {
hash: null,
parentHash: '0x83ffb245cfced97ccc5c75253d6960376d6c6dea93647397a543a72fdaea5265',
miner: null,
stateRoot: '0x54dda68af07643f68739a6e9612ad157a26ae7e2ce81f77842bb5835fbcde583',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
bloom: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
difficulty: new BigNumber(1000),
totalDifficulty: new BigNumber(1000),
number: null,
gasLimit: 1000,
gasUsed: 1000,
timestamp: 1000,
extraData: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
nonce: null,
size: 1000
});
});

View File

@ -9,17 +9,37 @@ describe('formatters', function () {
transactionIndex: '0x3e8',
logIndex: '0x3e8',
blockNumber: '0x3e8',
transactionHash: '0x7b2274657374223a2274657374227d',
blockHash: '0x7b2274657374223a2274657374227d',
data: '0x7b2274657374223a2274657374227d',
transactionHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
blockHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
}), {
transactionIndex: 1000,
logIndex: 1000,
blockNumber: 1000,
transactionHash: '0x7b2274657374223a2274657374227d',
blockHash: '0x7b2274657374223a2274657374227d',
data: '0x7b2274657374223a2274657374227d',
transactionHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
blockHash: '0xd6960376d6c6dea93647383ffb245cfced97ccc5c7525397a543a72fdaea5265',
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputLogFormatter({
transactionIndex: null,
logIndex: null,
blockNumber: null,
transactionHash: null,
blockHash: null,
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
}), {
transactionIndex: null,
logIndex: null,
blockNumber: null,
transactionHash: null,
blockHash: null,
data: '0x7b2274657374223a2274657374227',
topics: ['0x68656c6c6f','0x6d79746f70696373']
});
});

View File

@ -7,7 +7,7 @@ describe('formatters', function () {
it('should return the correct value', function () {
assert.deepEqual(formatters.outputTransactionFormatter({
input: '0x34234kjh23kj4234',
input: '0x3454645634534',
from: '0x00000',
to: '0x00000',
value: '0x3e8',
@ -16,9 +16,9 @@ describe('formatters', function () {
nonce: '0xb',
transactionIndex: '0x1',
blockNumber: '0x3e8',
blockHash: '0x34234bf23bf4234'
blockHash: '0xc9b9cdc2092a9d6589d96662b1fd6949611163fb3910cf8a173cd060f17702f9'
}), {
input: '0x34234kjh23kj4234',
input: '0x3454645634534',
from: '0x00000',
to: '0x00000',
value: new BigNumber(1000),
@ -26,9 +26,36 @@ describe('formatters', function () {
gasPrice: new BigNumber(1000),
nonce: 11,
blockNumber: 1000,
blockHash: '0x34234bf23bf4234',
blockHash: '0xc9b9cdc2092a9d6589d96662b1fd6949611163fb3910cf8a173cd060f17702f9',
transactionIndex: 1
});
});
it('should return the correct value, when null values are present', function () {
assert.deepEqual(formatters.outputTransactionFormatter({
input: '0x3454645634534',
from: '0x00000',
to: null,
value: '0x3e8',
gas: '0x3e8',
gasPrice: '0x3e8',
nonce: '0xb',
transactionIndex: null,
blockNumber: null,
blockHash: null
}), {
input: '0x3454645634534',
from: '0x00000',
to: null,
value: new BigNumber(1000),
gas: 1000,
gasPrice: new BigNumber(1000),
nonce: 11,
blockNumber: null,
blockHash: null,
transactionIndex: null
});
});
});
});

View File

@ -15,11 +15,21 @@ FakeHttpProvider2.prototype.injectResultList = function (list) {
FakeHttpProvider2.prototype.getResponse = function () {
var result = this.resultList[this.counter];
this.counter++;
// add fallback result value
if(!result)
result = {
result: undefined
};
if (result.type === 'batch') {
this.injectBatchResults(result.result);
} else {
this.injectResult(result.result);
}
this.counter = 0;
return this.response;
};

View File

@ -6,6 +6,9 @@ var FakeXMLHttpRequest = function () {
this.readyState = 4;
this.onreadystatechange = null;
this.async = false;
this.headers = {
'Content-Type': 'text/plain'
};
};
FakeXMLHttpRequest.prototype.open = function (method, host, async) {
@ -15,6 +18,10 @@ FakeXMLHttpRequest.prototype.open = function (method, host, async) {
this.async = async;
};
FakeXMLHttpRequest.prototype.setRequestHeader = function(name, value) {
this.headers[name] = value;
};
FakeXMLHttpRequest.prototype.send = function (payload) {
assert.equal(typeof payload, 'string');
if (this.async) {

View File

@ -19,6 +19,14 @@ describe('lib/utils/utils', function () {
assert.equal(utils.toWei(1, 'gether'), '1000000000000000000000000000');
assert.equal(utils.toWei(1, 'tether'), '1000000000000000000000000000000');
assert.equal(utils.toWei(1, 'kwei'), utils.toWei(1, 'femtoether'));
assert.equal(utils.toWei(1, 'babbage'), utils.toWei(1, 'picoether'));
assert.equal(utils.toWei(1, 'shannon'), utils.toWei(1, 'nanoether'));
assert.equal(utils.toWei(1, 'szabo'), utils.toWei(1, 'microether'));
assert.equal(utils.toWei(1, 'finney'), utils.toWei(1, 'milliether'));
assert.equal(utils.toWei(1, 'milli'), utils.toWei(1, 'milliether'));
assert.equal(utils.toWei(1, 'milli'), utils.toWei(1000, 'micro'));
assert.throws(function () {utils.toWei(1, 'wei1');}, Error);
});
});

76
test/web3.extend.js Normal file
View File

@ -0,0 +1,76 @@
var chai = require('chai');
var assert = chai.assert;
var FakeHttpProvider = require('./helpers/FakeHttpProvider');
var web3 = require('../lib/web3');
var tests = [{
properties: [new web3._extend.Property({
name: 'gasPrice',
getter: 'eth_gasPrice',
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
},{
methods: [new web3._extend.Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [web3._extend.utils.toAddress, web3._extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
},{
property: 'admin',
properties: [new web3._extend.Property({
name: 'gasPrice',
getter: 'eth_gasPrice',
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})],
methods: [new web3._extend.Method({
name: 'getBalance',
call: 'eth_getBalance',
params: 2,
inputFormatter: [web3._extend.utils.toAddress, web3._extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3._extend.formatters.outputBigNumberFormatter
})]
}];
describe('web3', function () {
describe('_extend', function () {
tests.forEach(function (test, index) {
it('test no: ' + index, function () {
web3._extend(test);
if(test.properties)
test.properties.forEach(function(property){
var provider = new FakeHttpProvider();
web3.setProvider(provider);
provider.injectResult('');
provider.injectValidation(function (payload) {
assert.equal(payload.jsonrpc, '2.0');
assert.equal(payload.method, property.getter);
});
if(test.property) {
assert.isObject(web3[test.property][property.name]);
assert.isFunction(web3[test.property]['get'+ property.name.charAt(0).toUpperCase() + property.name.slice(1)]);
} else {
assert.isObject(web3[property.name]);
assert.isFunction(web3['get'+ property.name.charAt(0).toUpperCase() + property.name.slice(1)]);
}
});
if(test.methods)
test.methods.forEach(function(property){
if(test.property)
assert.isFunction(web3[test.property][property.name]);
else
assert.isFunction(web3[property.name]);
});
});
});
});
});