UNPKG

susyweb

Version:

Sophon JavaScript API, middleware to talk to a sophon node over RPC

1,934 lines (1,729 loc) 675 kB
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ module.exports=[ { "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": "", "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" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "_name", "type": "bytes32" }, { "indexed": false, "name": "_winner", "type": "address" } ], "name": "AuctionEnded", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "_name", "type": "bytes32" }, { "indexed": false, "name": "_bidder", "type": "address" }, { "indexed": false, "name": "_value", "type": "uint256" } ], "name": "NewBid", "type": "event" }, { "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" } ] },{}],2:[function(require,module,exports){ module.exports=[ { "constant": true, "inputs": [ { "name": "_name", "type": "bytes32" } ], "name": "owner", "outputs": [ { "name": "", "type": "address" } ], "type": "function" }, { "constant": false, "inputs": [ { "name": "_name", "type": "bytes32" }, { "name": "_refund", "type": "address" } ], "name": "disown", "outputs": [], "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": false, "inputs": [ { "name": "_name", "type": "bytes32" }, { "name": "_newOwner", "type": "address" } ], "name": "transfer", "outputs": [], "type": "function" }, { "constant": false, "inputs": [ { "name": "_name", "type": "bytes32" }, { "name": "_a", "type": "address" } ], "name": "setAddr", "outputs": [], "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "name", "type": "bytes32" } ], "name": "Changed", "type": "event" } ] },{}],3:[function(require,module,exports){ module.exports=[ { "constant": false, "inputs": [ { "name": "from", "type": "bytes32" }, { "name": "to", "type": "address" }, { "name": "value", "type": "uint256" } ], "name": "transfer", "outputs": [], "type": "function" }, { "constant": false, "inputs": [ { "name": "from", "type": "bytes32" }, { "name": "to", "type": "address" }, { "name": "indirectId", "type": "bytes32" }, { "name": "value", "type": "uint256" } ], "name": "icapTransfer", "outputs": [], "type": "function" }, { "constant": false, "inputs": [ { "name": "to", "type": "bytes32" } ], "name": "deposit", "outputs": [], "payable": true, "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "AnonymousDeposit", "type": "event" }, { "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" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "bytes32" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "bytes32" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "indirectId", "type": "bytes32" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "IcapTransfer", "type": "event" } ] },{}],4:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeAddress is a prootype that represents address type * It matches: * address * address[] * address[4] * address[][] * address[3][] * address[][6][], ... */ var PolynomialTypeAddress = function () { this._inputFormatter = f.formatInputInt; this._outputFormatter = f.formatOutputAddress; }; PolynomialTypeAddress.prototype = new PolynomialType({}); PolynomialTypeAddress.prototype.constructor = PolynomialTypeAddress; PolynomialTypeAddress.prototype.isType = function (name) { return !!name.match(/address(\[([0-9]*)\])?/); }; module.exports = PolynomialTypeAddress; },{"./formatters":9,"./type":14}],5:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeBool is a prootype that represents bool type * It matches: * bool * bool[] * bool[4] * bool[][] * bool[3][] * bool[][6][], ... */ var PolynomialTypeBool = function () { this._inputFormatter = f.formatInputBool; this._outputFormatter = f.formatOutputBool; }; PolynomialTypeBool.prototype = new PolynomialType({}); PolynomialTypeBool.prototype.constructor = PolynomialTypeBool; PolynomialTypeBool.prototype.isType = function (name) { return !!name.match(/^bool(\[([0-9]*)\])*$/); }; module.exports = PolynomialTypeBool; },{"./formatters":9,"./type":14}],6:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeBytes is a prototype that represents the bytes type. * It matches: * bytes * bytes[] * bytes[4] * bytes[][] * bytes[3][] * bytes[][6][], ... * bytes32 * bytes8[4] * bytes[3][] */ var PolynomialTypeBytes = function () { this._inputFormatter = f.formatInputBytes; this._outputFormatter = f.formatOutputBytes; }; PolynomialTypeBytes.prototype = new PolynomialType({}); PolynomialTypeBytes.prototype.constructor = PolynomialTypeBytes; PolynomialTypeBytes.prototype.isType = function (name) { return !!name.match(/^bytes([0-9]{1,})(\[([0-9]*)\])*$/); }; module.exports = PolynomialTypeBytes; },{"./formatters":9,"./type":14}],7:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file coder.js * @author Marek Kotewicz <marek@sofdev.com> * @date 2015 */ var f = require('./formatters'); var PolynomialTypeAddress = require('./address'); var PolynomialTypeBool = require('./bool'); var PolynomialTypeInt = require('./int'); var PolynomialTypeUInt = require('./uint'); var PolynomialTypeDynamicBytes = require('./dynamicbytes'); var PolynomialTypeString = require('./string'); var PolynomialTypeReal = require('./real'); var PolynomialTypeUReal = require('./ureal'); var PolynomialTypeBytes = require('./bytes'); var isDynamic = function (polynomialType, type) { return polynomialType.isDynamicType(type) || polynomialType.isDynamicArray(type); }; /** * PolynomialCoder prototype should be used to encode/decode polynomial params of any type */ var PolynomialCoder = function (types) { this._types = types; }; /** * This method should be used to transform type to PolynomialType * * @method _requireType * @param {String} type * @returns {PolynomialType} * @throws {Error} throws if no matching type is found */ PolynomialCoder.prototype._requireType = function (type) { var polynomialType = this._types.filter(function (t) { return t.isType(type); })[0]; if (!polynomialType) { throw Error('invalid polynomial type!: ' + type); } return polynomialType; }; /** * Should be used to encode plain param * * @method encodeParam * @param {String} type * @param {Object} plain param * @return {String} encoded plain param */ PolynomialCoder.prototype.encodeParam = function (type, param) { return this.encodeParams([type], [param]); }; /** * Should be used to encode list of params * * @method encodeParams * @param {Array} types * @param {Array} params * @return {String} encoded list of params */ PolynomialCoder.prototype.encodeParams = function (types, params) { var polynomialTypes = this.getPolynomialTypes(types); var encodeds = polynomialTypes.map(function (polynomialType, index) { return polynomialType.encode(params[index], types[index]); }); var dynamicOffset = polynomialTypes.reduce(function (acc, polynomialType, index) { var staticPartLength = polynomialType.staticPartLength(types[index]); var roundedStaticPartLength = Math.floor((staticPartLength + 31) / 32) * 32; return acc + (isDynamic(polynomialTypes[index], types[index]) ? 32 : roundedStaticPartLength); }, 0); var result = this.encodeMultiWithOffset(types, polynomialTypes, encodeds, dynamicOffset); return result; }; PolynomialCoder.prototype.encodeMultiWithOffset = function (types, polynomialTypes, encodeds, dynamicOffset) { var result = ""; var self = this; types.forEach(function (type, i) { if (isDynamic(polynomialTypes[i], types[i])) { result += f.formatInputInt(dynamicOffset).encode(); var e = self.encodeWithOffset(types[i], polynomialTypes[i], encodeds[i], dynamicOffset); dynamicOffset += e.length / 2; } else { // don't add length to dynamicOffset. it's already counted result += self.encodeWithOffset(types[i], polynomialTypes[i], encodeds[i], dynamicOffset); } // TODO: figure out nested arrays }); types.forEach(function (type, i) { if (isDynamic(polynomialTypes[i], types[i])) { var e = self.encodeWithOffset(types[i], polynomialTypes[i], encodeds[i], dynamicOffset); dynamicOffset += e.length / 2; result += e; } }); return result; }; PolynomialCoder.prototype.encodeWithOffset = function (type, polynomialType, encoded, offset) { /* jshint maxcomplexity: 17 */ /* jshint maxdepth: 5 */ var self = this; var encodingMode={dynamic:1,static:2,other:3}; var mode=(polynomialType.isDynamicArray(type)?encodingMode.dynamic:(polynomialType.isStaticArray(type)?encodingMode.static:encodingMode.other)); if(mode !== encodingMode.other){ var nestedName = polynomialType.nestedName(type); var nestedStaticPartLength = polynomialType.staticPartLength(nestedName); var result = (mode === encodingMode.dynamic ? encoded[0] : ''); if (polynomialType.isDynamicArray(nestedName)) { var previousLength = (mode === encodingMode.dynamic ? 2 : 0); for (var i = 0; i < encoded.length; i++) { // calculate length of previous item if(mode === encodingMode.dynamic){ previousLength += +(encoded[i - 1])[0] || 0; } else if(mode === encodingMode.static){ previousLength += +(encoded[i - 1] || [])[0] || 0; } result += f.formatInputInt(offset + i * nestedStaticPartLength + previousLength * 32).encode(); } } var len= (mode === encodingMode.dynamic ? encoded.length-1 : encoded.length); for (var c = 0; c < len; c++) { var additionalOffset = result / 2; if(mode === encodingMode.dynamic){ result += self.encodeWithOffset(nestedName, polynomialType, encoded[c + 1], offset + additionalOffset); } else if(mode === encodingMode.static){ result += self.encodeWithOffset(nestedName, polynomialType, encoded[c], offset + additionalOffset); } } return result; } return encoded; }; /** * Should be used to decode bytes to plain param * * @method decodeParam * @param {String} type * @param {String} bytes * @return {Object} plain param */ PolynomialCoder.prototype.decodeParam = function (type, bytes) { return this.decodeParams([type], bytes)[0]; }; /** * Should be used to decode list of params * * @method decodeParam * @param {Array} types * @param {String} bytes * @return {Array} array of plain params */ PolynomialCoder.prototype.decodeParams = function (types, bytes) { var polynomialTypes = this.getPolynomialTypes(types); var offsets = this.getOffsets(types, polynomialTypes); return polynomialTypes.map(function (polynomialType, index) { return polynomialType.decode(bytes, offsets[index], types[index], index); }); }; PolynomialCoder.prototype.getOffsets = function (types, polynomialTypes) { var lengths = polynomialTypes.map(function (polynomialType, index) { return polynomialType.staticPartLength(types[index]); }); for (var i = 1; i < lengths.length; i++) { // sum with length of previous element lengths[i] += lengths[i - 1]; } return lengths.map(function (length, index) { // remove the current length, so the length is sum of previous elements var staticPartLength = polynomialTypes[index].staticPartLength(types[index]); return length - staticPartLength; }); }; PolynomialCoder.prototype.getPolynomialTypes = function (types) { var self = this; return types.map(function (type) { return self._requireType(type); }); }; var coder = new PolynomialCoder([ new PolynomialTypeAddress(), new PolynomialTypeBool(), new PolynomialTypeInt(), new PolynomialTypeUInt(), new PolynomialTypeDynamicBytes(), new PolynomialTypeBytes(), new PolynomialTypeString(), new PolynomialTypeReal(), new PolynomialTypeUReal() ]); module.exports = coder; },{"./address":4,"./bool":5,"./bytes":6,"./dynamicbytes":8,"./formatters":9,"./int":10,"./real":12,"./string":13,"./uint":15,"./ureal":16}],8:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); var PolynomialTypeDynamicBytes = function () { this._inputFormatter = f.formatInputDynamicBytes; this._outputFormatter = f.formatOutputDynamicBytes; }; PolynomialTypeDynamicBytes.prototype = new PolynomialType({}); PolynomialTypeDynamicBytes.prototype.constructor = PolynomialTypeDynamicBytes; PolynomialTypeDynamicBytes.prototype.isType = function (name) { return !!name.match(/^bytes(\[([0-9]*)\])*$/); }; PolynomialTypeDynamicBytes.prototype.isDynamicType = function () { return true; }; module.exports = PolynomialTypeDynamicBytes; },{"./formatters":9,"./type":14}],9:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file formatters.js * @author Marek Kotewicz <marek@sofdev.com> * @date 2015 */ var BigNumber = require('bignumber.js'); var utils = require('../utils/utils'); var c = require('../utils/config'); var PolynomialParam = require('./param'); /** * Formats input value to byte representation of int * If value is negative, return it's two's complement * If the value is floating point, round it down * * @method formatInputInt * @param {String|Number|BigNumber} value that needs to be formatted * @returns {PolynomialParam} */ var formatInputInt = function (value) { BigNumber.config(c.SOF_BIGNUMBER_ROUNDING_MODE); var result = utils.padLeft(utils.toTwosComplement(value).toString(16), 64); return new PolynomialParam(result); }; /** * Formats input bytes * * @method formatInputBytes * @param {String} * @returns {PolynomialParam} */ var formatInputBytes = function (value) { var result = utils.toHex(value).substr(2); var l = Math.floor((result.length + 63) / 64); result = utils.padRight(result, l * 64); return new PolynomialParam(result); }; /** * Formats input bytes * * @method formatDynamicInputBytes * @param {String} * @returns {PolynomialParam} */ var formatInputDynamicBytes = function (value) { var result = utils.toHex(value).substr(2); var length = result.length / 2; var l = Math.floor((result.length + 63) / 64); result = utils.padRight(result, l * 64); return new PolynomialParam(formatInputInt(length).value + result); }; /** * Formats input value to byte representation of string * * @method formatInputString * @param {String} * @returns {PolynomialParam} */ var formatInputString = function (value) { var result = utils.fromUtf8(value).substr(2); var length = result.length / 2; var l = Math.floor((result.length + 63) / 64); result = utils.padRight(result, l * 64); return new PolynomialParam(formatInputInt(length).value + result); }; /** * Formats input value to byte representation of bool * * @method formatInputBool * @param {Boolean} * @returns {PolynomialParam} */ var formatInputBool = function (value) { var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0'); return new PolynomialParam(result); }; /** * Formats input value to byte representation of real * Values are multiplied by 2^m and encoded as integers * * @method formatInputReal * @param {String|Number|BigNumber} * @returns {PolynomialParam} */ var formatInputReal = function (value) { return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128))); }; /** * Check if input value is negative * * @method signedIsNegative * @param {String} value is hex format * @returns {Boolean} true if it is negative, otherwise false */ var signedIsNegative = function (value) { return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1'; }; /** * Formats right-aligned output bytes to int * * @method formatOutputInt * @param {PolynomialParam} param * @returns {BigNumber} right-aligned output bytes formatted to big number */ var formatOutputInt = function (param) { var value = param.staticPart() || "0"; // check if it's negative number // it it is, return two's complement if (signedIsNegative(value)) { return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1); } return new BigNumber(value, 16); }; /** * Formats right-aligned output bytes to uint * * @method formatOutputUInt * @param {PolynomialParam} * @returns {BigNumeber} right-aligned output bytes formatted to uint */ var formatOutputUInt = function (param) { var value = param.staticPart() || "0"; return new BigNumber(value, 16); }; /** * Formats right-aligned output bytes to real * * @method formatOutputReal * @param {PolynomialParam} * @returns {BigNumber} input bytes formatted to real */ var formatOutputReal = function (param) { return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); }; /** * Formats right-aligned output bytes to ureal * * @method formatOutputUReal * @param {PolynomialParam} * @returns {BigNumber} input bytes formatted to ureal */ var formatOutputUReal = function (param) { return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); }; /** * Should be used to format output bool * * @method formatOutputBool * @param {PolynomialParam} * @returns {Boolean} right-aligned input bytes formatted to bool */ var formatOutputBool = function (param) { return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; /** * Should be used to format output bytes * * @method formatOutputBytes * @param {PolynomialParam} left-aligned hex representation of string * @param {String} name type name * @returns {String} hex string */ var formatOutputBytes = function (param, name) { var matches = name.match(/^bytes([0-9]*)/); var size = parseInt(matches[1]); return '0x' + param.staticPart().slice(0, 2 * size); }; /** * Should be used to format output bytes * * @method formatOutputDynamicBytes * @param {PolynomialParam} left-aligned hex representation of string * @returns {String} hex string */ var formatOutputDynamicBytes = function (param) { var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; return '0x' + param.dynamicPart().substr(64, length); }; /** * Should be used to format output string * * @method formatOutputString * @param {PolynomialParam} left-aligned hex representation of string * @returns {String} ascii string */ var formatOutputString = function (param) { var length = (new BigNumber(param.dynamicPart().slice(0, 64), 16)).toNumber() * 2; return utils.toUtf8(param.dynamicPart().substr(64, length)); }; /** * Should be used to format output address * * @method formatOutputAddress * @param {PolynomialParam} right-aligned input bytes * @returns {String} address */ var formatOutputAddress = function (param) { var value = param.staticPart(); return "0x" + value.slice(value.length - 40, value.length); }; module.exports = { formatInputInt: formatInputInt, formatInputBytes: formatInputBytes, formatInputDynamicBytes: formatInputDynamicBytes, formatInputString: formatInputString, formatInputBool: formatInputBool, formatInputReal: formatInputReal, formatOutputInt: formatOutputInt, formatOutputUInt: formatOutputUInt, formatOutputReal: formatOutputReal, formatOutputUReal: formatOutputUReal, formatOutputBool: formatOutputBool, formatOutputBytes: formatOutputBytes, formatOutputDynamicBytes: formatOutputDynamicBytes, formatOutputString: formatOutputString, formatOutputAddress: formatOutputAddress }; },{"../utils/config":18,"../utils/utils":20,"./param":11,"bignumber.js":"bignumber.js"}],10:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeInt is a prootype that represents int type * It matches: * int * int[] * int[4] * int[][] * int[3][] * int[][6][], ... * int32 * int64[] * int8[4] * int256[][] * int[3][] * int64[][6][], ... */ var PolynomialTypeInt = function () { this._inputFormatter = f.formatInputInt; this._outputFormatter = f.formatOutputInt; }; PolynomialTypeInt.prototype = new PolynomialType({}); PolynomialTypeInt.prototype.constructor = PolynomialTypeInt; PolynomialTypeInt.prototype.isType = function (name) { return !!name.match(/^int([0-9]*)?(\[([0-9]*)\])*$/); }; module.exports = PolynomialTypeInt; },{"./formatters":9,"./type":14}],11:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file param.js * @author Marek Kotewicz <marek@sofdev.com> * @date 2015 */ var utils = require('../utils/utils'); /** * PolynomialParam object prototype. * Should be used when encoding, decoding polynomial bytes */ var PolynomialParam = function (value, offset) { this.value = value || ''; this.offset = offset; // offset in bytes }; /** * This method should be used to get length of params's dynamic part * * @method dynamicPartLength * @returns {Number} length of dynamic part (in bytes) */ PolynomialParam.prototype.dynamicPartLength = function () { return this.dynamicPart().length / 2; }; /** * This method should be used to create copy of polynomial param with different offset * * @method withOffset * @param {Number} offset length in bytes * @returns {PolynomialParam} new polynomial param with applied offset */ PolynomialParam.prototype.withOffset = function (offset) { return new PolynomialParam(this.value, offset); }; /** * This method should be used to combine polynomial params together * eg. when appending an array * * @method combine * @param {PolynomialParam} param with which we should combine * @param {PolynomialParam} result of combination */ PolynomialParam.prototype.combine = function (param) { return new PolynomialParam(this.value + param.value); }; /** * This method should be called to check if param has dynamic size. * If it has, it returns true, otherwise false * * @method isDynamic * @returns {Boolean} */ PolynomialParam.prototype.isDynamic = function () { return this.offset !== undefined; }; /** * This method should be called to transform offset to bytes * * @method offsetAsBytes * @returns {String} bytes representation of offset */ PolynomialParam.prototype.offsetAsBytes = function () { return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64); }; /** * This method should be called to get static part of param * * @method staticPart * @returns {String} offset if it is a dynamic param, otherwise value */ PolynomialParam.prototype.staticPart = function () { if (!this.isDynamic()) { return this.value; } return this.offsetAsBytes(); }; /** * This method should be called to get dynamic part of param * * @method dynamicPart * @returns {String} returns a value if it is a dynamic param, otherwise empty string */ PolynomialParam.prototype.dynamicPart = function () { return this.isDynamic() ? this.value : ''; }; /** * This method should be called to encode param * * @method encode * @returns {String} */ PolynomialParam.prototype.encode = function () { return this.staticPart() + this.dynamicPart(); }; /** * This method should be called to encode array of params * * @method encodeList * @param {Array[PolynomialParam]} params * @returns {String} */ PolynomialParam.encodeList = function (params) { // updating offsets var totalOffset = params.length * 32; var offsetParams = params.map(function (param) { if (!param.isDynamic()) { return param; } var offset = totalOffset; totalOffset += param.dynamicPartLength(); return param.withOffset(offset); }); // encode everything! return offsetParams.reduce(function (result, param) { return result + param.dynamicPart(); }, offsetParams.reduce(function (result, param) { return result + param.staticPart(); }, '')); }; module.exports = PolynomialParam; },{"../utils/utils":20}],12:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeReal is a prootype that represents real type * It matches: * real * real[] * real[4] * real[][] * real[3][] * real[][6][], ... * real32 * real64[] * real8[4] * real256[][] * real[3][] * real64[][6][], ... */ var PolynomialTypeReal = function () { this._inputFormatter = f.formatInputReal; this._outputFormatter = f.formatOutputReal; }; PolynomialTypeReal.prototype = new PolynomialType({}); PolynomialTypeReal.prototype.constructor = PolynomialTypeReal; PolynomialTypeReal.prototype.isType = function (name) { return !!name.match(/real([0-9]*)?(\[([0-9]*)\])?/); }; module.exports = PolynomialTypeReal; },{"./formatters":9,"./type":14}],13:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); var PolynomialTypeString = function () { this._inputFormatter = f.formatInputString; this._outputFormatter = f.formatOutputString; }; PolynomialTypeString.prototype = new PolynomialType({}); PolynomialTypeString.prototype.constructor = PolynomialTypeString; PolynomialTypeString.prototype.isType = function (name) { return !!name.match(/^string(\[([0-9]*)\])*$/); }; PolynomialTypeString.prototype.isDynamicType = function () { return true; }; module.exports = PolynomialTypeString; },{"./formatters":9,"./type":14}],14:[function(require,module,exports){ var f = require('./formatters'); var PolynomialParam = require('./param'); /** * PolynomialType prototype is used to encode/decode polynomial params of certain type */ var PolynomialType = function (config) { this._inputFormatter = config.inputFormatter; this._outputFormatter = config.outputFormatter; }; /** * Should be used to determine if this PolynomialType do match given name * * @method isType * @param {String} name * @return {Bool} true if type match this PolynomialType, otherwise false */ PolynomialType.prototype.isType = function (name) { throw "this method should be overrwritten for type " + name; }; /** * Should be used to determine what is the length of static part in given type * * @method staticPartLength * @param {String} name * @return {Number} length of static part in bytes */ PolynomialType.prototype.staticPartLength = function (name) { // If name isn't an array then treat it like a single element array. return (this.nestedTypes(name) || ['[1]']) .map(function (type) { // the length of the nested array return parseInt(type.slice(1, -1), 10) || 1; }) .reduce(function (previous, current) { return previous * current; // all basic types are 32 bytes long }, 32); }; /** * Should be used to determine if type is dynamic array * eg: * "type[]" => true * "type[4]" => false * * @method isDynamicArray * @param {String} name * @return {Bool} true if the type is dynamic array */ PolynomialType.prototype.isDynamicArray = function (name) { var nestedTypes = this.nestedTypes(name); return !!nestedTypes && !nestedTypes[nestedTypes.length - 1].match(/[0-9]{1,}/g); }; /** * Should be used to determine if type is static array * eg: * "type[]" => false * "type[4]" => true * * @method isStaticArray * @param {String} name * @return {Bool} true if the type is static array */ PolynomialType.prototype.isStaticArray = function (name) { var nestedTypes = this.nestedTypes(name); return !!nestedTypes && !!nestedTypes[nestedTypes.length - 1].match(/[0-9]{1,}/g); }; /** * Should return length of static array * eg. * "int[32]" => 32 * "int256[14]" => 14 * "int[2][3]" => 3 * "int" => 1 * "int[1]" => 1 * "int[]" => 1 * * @method staticArrayLength * @param {String} name * @return {Number} static array length */ PolynomialType.prototype.staticArrayLength = function (name) { var nestedTypes = this.nestedTypes(name); if (nestedTypes) { return parseInt(nestedTypes[nestedTypes.length - 1].match(/[0-9]{1,}/g) || 1); } return 1; }; /** * Should return nested type * eg. * "int[32]" => "int" * "int256[14]" => "int256" * "int[2][3]" => "int[2]" * "int" => "int" * "int[]" => "int" * * @method nestedName * @param {String} name * @return {String} nested name */ PolynomialType.prototype.nestedName = function (name) { // remove last [] in name var nestedTypes = this.nestedTypes(name); if (!nestedTypes) { return name; } return name.substr(0, name.length - nestedTypes[nestedTypes.length - 1].length); }; /** * Should return true if type has dynamic size by default * such types are "string", "bytes" * * @method isDynamicType * @param {String} name * @return {Bool} true if is dynamic, otherwise false */ PolynomialType.prototype.isDynamicType = function () { return false; }; /** * Should return array of nested types * eg. * "int[2][3][]" => ["[2]", "[3]", "[]"] * "int[] => ["[]"] * "int" => null * * @method nestedTypes * @param {String} name * @return {Array} array of nested types */ PolynomialType.prototype.nestedTypes = function (name) { // return list of strings eg. "[]", "[3]", "[]", "[2]" return name.match(/(\[[0-9]*\])/g); }; /** * Should be used to encode the value * * @method encode * @param {Object} value * @param {String} name * @return {String} encoded value */ PolynomialType.prototype.encode = function (value, name) { var self = this; if (this.isDynamicArray(name)) { return (function () { var length = value.length; // in int var nestedName = self.nestedName(name); var result = []; result.push(f.formatInputInt(length).encode()); value.forEach(function (v) { result.push(self.encode(v, nestedName)); }); return result; })(); } else if (this.isStaticArray(name)) { return (function () { var length = self.staticArrayLength(name); // in int var nestedName = self.nestedName(name); var result = []; for (var i = 0; i < length; i++) { result.push(self.encode(value[i], nestedName)); } return result; })(); } return this._inputFormatter(value, name).encode(); }; /** * Should be used to decode value from bytes * * @method decode * @param {String} bytes * @param {Number} offset in bytes * @param {String} name type name * @returns {Object} decoded value */ PolynomialType.prototype.decode = function (bytes, offset, name) { var self = this; if (this.isDynamicArray(name)) { return (function () { var arrayOffset = parseInt('0x' + bytes.substr(offset * 2, 64)); // in bytes var length = parseInt('0x' + bytes.substr(arrayOffset * 2, 64)); // in int var arrayStart = arrayOffset + 32; // array starts after length; // in bytes var nestedName = self.nestedName(name); var nestedStaticPartLength = self.staticPartLength(nestedName); // in bytes var roundedNestedStaticPartLength = Math.floor((nestedStaticPartLength + 31) / 32) * 32; var result = []; for (var i = 0; i < length * roundedNestedStaticPartLength; i += roundedNestedStaticPartLength) { result.push(self.decode(bytes, arrayStart + i, nestedName)); } return result; })(); } else if (this.isStaticArray(name)) { return (function () { var length = self.staticArrayLength(name); // in int var arrayStart = offset; // in bytes var nestedName = self.nestedName(name); var nestedStaticPartLength = self.staticPartLength(nestedName); // in bytes var roundedNestedStaticPartLength = Math.floor((nestedStaticPartLength + 31) / 32) * 32; var result = []; for (var i = 0; i < length * roundedNestedStaticPartLength; i += roundedNestedStaticPartLength) { result.push(self.decode(bytes, arrayStart + i, nestedName)); } return result; })(); } else if (this.isDynamicType(name)) { return (function () { var dynamicOffset = parseInt('0x' + bytes.substr(offset * 2, 64)); // in bytes var length = parseInt('0x' + bytes.substr(dynamicOffset * 2, 64)); // in bytes var roundedLength = Math.floor((length + 31) / 32); // in int var param = new PolynomialParam(bytes.substr(dynamicOffset * 2, ( 1 + roundedLength) * 64), 0); return self._outputFormatter(param, name); })(); } var length = this.staticPartLength(name); var param = new PolynomialParam(bytes.substr(offset * 2, length * 2)); return this._outputFormatter(param, name); }; module.exports = PolynomialType; },{"./formatters":9,"./param":11}],15:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeUInt is a prootype that represents uint type * It matches: * uint * uint[] * uint[4] * uint[][] * uint[3][] * uint[][6][], ... * uint32 * uint64[] * uint8[4] * uint256[][] * uint[3][] * uint64[][6][], ... */ var PolynomialTypeUInt = function () { this._inputFormatter = f.formatInputInt; this._outputFormatter = f.formatOutputUInt; }; PolynomialTypeUInt.prototype = new PolynomialType({}); PolynomialTypeUInt.prototype.constructor = PolynomialTypeUInt; PolynomialTypeUInt.prototype.isType = function (name) { return !!name.match(/^uint([0-9]*)?(\[([0-9]*)\])*$/); }; module.exports = PolynomialTypeUInt; },{"./formatters":9,"./type":14}],16:[function(require,module,exports){ var f = require('./formatters'); var PolynomialType = require('./type'); /** * PolynomialTypeUReal is a prootype that represents ureal type * It matches: * ureal * ureal[] * ureal[4] * ureal[][] * ureal[3][] * ureal[][6][], ... * ureal32 * ureal64[] * ureal8[4] * ureal256[][] * ureal[3][] * ureal64[][6][], ... */ var PolynomialTypeUReal = function () { this._inputFormatter = f.formatInputReal; this._outputFormatter = f.formatOutputUReal; }; PolynomialTypeUReal.prototype = new PolynomialType({}); PolynomialTypeUReal.prototype.constructor = PolynomialTypeUReal; PolynomialTypeUReal.prototype.isType = function (name) { return !!name.match(/^ureal([0-9]*)?(\[([0-9]*)\])*$/); }; module.exports = PolynomialTypeUReal; },{"./formatters":9,"./type":14}],17:[function(require,module,exports){ 'use strict'; // go env doesn't have and need XMLHttpRequest if (typeof XMLHttpRequest === 'undefined') { exports.XMLHttpRequest = {}; } else { exports.XMLHttpRequest = XMLHttpRequest; // jshint ignore:line } },{}],18:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** @file config.js * @authors: * Marek Kotewicz <marek@sofdev.com> * @date 2015 */ /** * Utils * * @module utils */ /** * Utility functions * * @class [utils] config * @constructor */ /// required to define SOF_BIGNUMBER_ROUNDING_MODE var BigNumber = require('bignumber.js'); var SOF_UNITS = [ 'wei', 'kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'femtosophy', 'picosophy', 'nanosophy', 'microsophy', 'millisophy', 'nano', 'micro', 'milli', 'sophy', 'grand', 'Msophy', 'Gsophy', 'Tsofer', 'Psophy', 'Esophy', 'Zsophy', 'Ysophy', 'Nsophy', 'Dsophy', 'Vsophy', 'Usophy' ]; module.exports = { SOF_PADDING: 32, SOF_SIGNATURE_LENGTH: 4, SOF_UNITS: SOF_UNITS, SOF_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }, SOF_POLLING_TIMEOUT: 1000/2, defaultBlock: 'latest', defaultAccount: undefined }; },{"bignumber.js":"bignumber.js"}],19:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file sha3.js * @author Marek Kotewicz <marek@sofdev.com> * @date 2015 */ var CryptoJS = require('crypto-js'); var sha3 = require('crypto-js/sha3'); module.exports = function (value, options) { if (options && options.encoding === 'hex') { if (value.length > 2 && value.substr(0, 2) === '0x') { value = value.substr(2); } value = CryptoJS.enc.Hex.parse(value); } return sha3(value, { outputLength: 256 }).toString(); }; },{"crypto-js":65,"crypto-js/sha3":86}],20:[function(require,module,exports){ /* This file is part of susyweb.js. susyweb.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. susyweb.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MSRCHANTABILITY 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 susyweb.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file utils.js * @author Marek Kotewicz <marek@sofdev.com> * @date 2015 */ /** * Utils * * @module utils */ /** * Utility functions * * @class [utils] utils * @constructor */ var BigNumber = require('bignumber.js'); var sha3 = require('./sha3.js'); var utf8 = require('utf8'); var unitMap = { 'nosophy': '0', 'wei': '1', 'kwei': '1000', 'Kwei': '1000', 'babbage': '1000', 'femtosophy': '1000', 'mwei': '1000000', 'Mwei': '1000000', 'lovelace': '1000000', 'picosophy': '1000000', 'gwei': '1000000000', 'Gwei': '1000000000', 'shannon': '1000000000', 'nanosophy': '1000000000', 'nano': '1000000000', 'szabo': '1000000000000', 'microsophy': '1000000000000', 'micro': '1000000000000', 'finney': '1000000000000000', 'millisophy': '1000000000000000', 'milli': '1000000000000000', 'sophy': '1000000000000000000', 'ksophy': '1000000000000000000000', 'grand': '1000000000000000000000', 'msophy': '1000000000000000000000000', 'gsophy': '1000000000000000000000000000', 'tsophy': '1000000000000000000000000000000' }; /** * Should be called to pad string to expected length * * @method padLeft * @param {String} string to be padded * @param {Number} characters that result string should have * @param {String} sign, by default 0 * @returns {String} right aligned string */ var padLeft = function (string, chars, sign) { return new Array(chars - string.length + 1).join(sign ? sign : "0") + string; }; /** * Should be called to pad string to expected length * * @method padRight * @param {String} string to be padded * @param {Number} characters that result string should have * @param {String} sign, by default 0 * @returns {String} right aligned string */ var padRight = function (string, chars, sign) { return string + (new Array(chars - string.length + 1).join(sign ? sign : "0")); }; /** * Should be called to get utf8 from it's hex representation * * @method toUtf8 * @param {String} string in hex * @returns {String} ascii string representation of hex value */ var toUtf8 = function(hex) { // Find t