2017-07-02 17:33:11 +00:00
|
|
|
let http = require('follow-redirects').http;
|
2017-07-05 12:35:51 +00:00
|
|
|
let https = require('follow-redirects').https;
|
2018-07-15 17:43:00 +00:00
|
|
|
const {canonicalHost} = require('./host');
|
2017-12-16 02:53:11 +00:00
|
|
|
|
2018-07-16 16:48:32 +00:00
|
|
|
const balanceRegex = /([0-9]+) ?([a-zA-Z]*)/;
|
|
|
|
|
2017-02-18 19:10:01 +00:00
|
|
|
function joinPath() {
|
2018-06-11 18:36:52 +00:00
|
|
|
const path = require('path');
|
2017-02-18 19:10:01 +00:00
|
|
|
return path.join.apply(path.join, arguments);
|
|
|
|
}
|
|
|
|
|
2018-07-06 08:38:09 +00:00
|
|
|
function dirname() {
|
|
|
|
const path = require('path');
|
|
|
|
return path.dirname.apply(path.dirname, arguments);
|
|
|
|
}
|
|
|
|
|
2017-02-18 19:45:57 +00:00
|
|
|
function filesMatchingPattern(files) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const globule = require('globule');
|
2017-02-19 05:00:01 +00:00
|
|
|
return globule.find(files, {nonull: true});
|
2017-02-18 19:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function fileMatchesPattern(patterns, intendedPath) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const globule = require('globule');
|
2017-02-19 05:00:01 +00:00
|
|
|
return globule.isMatch(patterns, intendedPath);
|
2017-02-18 19:37:07 +00:00
|
|
|
}
|
|
|
|
|
2017-02-18 19:45:57 +00:00
|
|
|
function recursiveMerge(target, source) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const merge = require('merge');
|
2017-02-18 19:45:57 +00:00
|
|
|
return merge.recursive(target, source);
|
|
|
|
}
|
|
|
|
|
2017-02-18 20:27:08 +00:00
|
|
|
function checkIsAvailable(url, callback) {
|
2017-12-05 23:14:46 +00:00
|
|
|
http.get(url, function (_res) {
|
2017-02-19 04:17:43 +00:00
|
|
|
callback(true);
|
2017-12-05 23:14:46 +00:00
|
|
|
}).on('error', function (_res) {
|
2017-02-19 04:17:43 +00:00
|
|
|
callback(false);
|
2017-02-18 20:27:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-16 03:15:24 +00:00
|
|
|
function httpGetRequest(httpObj, url, callback) {
|
|
|
|
httpObj.get(url, function(res) {
|
2017-12-16 03:11:55 +00:00
|
|
|
let body = '';
|
|
|
|
res.on('data', function (d) {
|
|
|
|
body += d;
|
|
|
|
});
|
|
|
|
res.on('end', function () {
|
|
|
|
callback(null, body);
|
|
|
|
});
|
2017-12-16 22:05:37 +00:00
|
|
|
}).on('error', function (err) {
|
|
|
|
callback(err);
|
2017-12-16 03:11:55 +00:00
|
|
|
});
|
2017-04-02 18:40:10 +00:00
|
|
|
}
|
|
|
|
|
2017-12-16 03:15:24 +00:00
|
|
|
function httpGet(url, callback) {
|
|
|
|
httpGetRequest(http, url, callback);
|
|
|
|
}
|
|
|
|
|
2017-07-05 12:35:51 +00:00
|
|
|
function httpsGet(url, callback) {
|
2017-12-16 03:15:24 +00:00
|
|
|
httpGetRequest(https, url, callback);
|
2017-07-05 12:35:51 +00:00
|
|
|
}
|
|
|
|
|
2017-12-31 02:44:59 +00:00
|
|
|
function httpGetJson(url, callback) {
|
|
|
|
httpGetRequest(http, url, function(err, body) {
|
|
|
|
try {
|
|
|
|
let parsed = JSON.parse(body);
|
|
|
|
return callback(err, parsed);
|
|
|
|
} catch(e) {
|
|
|
|
return callback(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-25 07:13:57 +00:00
|
|
|
function httpsGetJson(url, callback) {
|
|
|
|
httpGetRequest(https, url, function(err, body) {
|
|
|
|
try {
|
|
|
|
let parsed = JSON.parse(body);
|
|
|
|
return callback(err, parsed);
|
|
|
|
} catch(e) {
|
|
|
|
return callback(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-07-08 18:24:19 +00:00
|
|
|
function getJson(url, cb) {
|
|
|
|
if (url.indexOf('https') === 0) {
|
|
|
|
return httpsGetJson(url, cb);
|
|
|
|
}
|
|
|
|
httpGetJson(url, cb);
|
|
|
|
}
|
|
|
|
|
2018-06-19 13:24:36 +00:00
|
|
|
function pingEndpoint(host, port, type, protocol, origin, callback) {
|
2018-06-19 13:02:19 +00:00
|
|
|
const options = {
|
|
|
|
protocolVersion: 13,
|
|
|
|
perMessageDeflate: true,
|
|
|
|
origin: origin,
|
|
|
|
host: host,
|
|
|
|
port: port
|
|
|
|
};
|
|
|
|
if (type === 'ws') {
|
|
|
|
options.headers = {
|
|
|
|
'Sec-WebSocket-Version': 13,
|
|
|
|
Connection: 'Upgrade',
|
|
|
|
Upgrade: 'websocket',
|
|
|
|
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
|
|
|
|
Origin: origin
|
|
|
|
};
|
|
|
|
}
|
|
|
|
let req;
|
|
|
|
// remove trailing api key from infura, ie rinkeby.infura.io/nmY8WtT4QfEwz2S7wTbl
|
2018-06-19 13:24:36 +00:00
|
|
|
if (options.host.indexOf('/') > -1){
|
2018-06-19 13:02:19 +00:00
|
|
|
options.host = options.host.split('/')[0];
|
|
|
|
}
|
2018-06-19 13:24:36 +00:00
|
|
|
if (protocol === 'https') {
|
2018-06-19 13:02:19 +00:00
|
|
|
req = require('https').get(options);
|
|
|
|
} else {
|
|
|
|
req = require('http').get(options);
|
|
|
|
}
|
|
|
|
|
|
|
|
req.on('error', (err) => {
|
|
|
|
callback(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
req.on('response', (_response) => {
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
|
|
|
|
req.on('upgrade', (_res, _socket, _head) => {
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-02-18 21:06:39 +00:00
|
|
|
function runCmd(cmd, options) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const shelljs = require('shelljs');
|
2017-03-29 15:37:30 +00:00
|
|
|
let result = shelljs.exec(cmd, options || {silent: true});
|
2017-02-18 21:06:39 +00:00
|
|
|
if (result.code !== 0) {
|
|
|
|
console.log("error doing.. " + cmd);
|
|
|
|
console.log(result.output);
|
|
|
|
if (result.stderr !== undefined) {
|
|
|
|
console.log(result.stderr);
|
|
|
|
}
|
|
|
|
exit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function cd(folder) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const shelljs = require('shelljs');
|
2017-02-18 21:06:39 +00:00
|
|
|
shelljs.cd(folder);
|
|
|
|
}
|
|
|
|
|
2017-02-25 22:34:45 +00:00
|
|
|
function sed(file, pattern, replace) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const shelljs = require('shelljs');
|
2017-02-25 22:34:45 +00:00
|
|
|
shelljs.sed('-i', pattern, replace, file);
|
|
|
|
}
|
|
|
|
|
2017-02-18 21:06:39 +00:00
|
|
|
function exit(code) {
|
|
|
|
process.exit(code);
|
|
|
|
}
|
|
|
|
|
2017-12-16 02:53:11 +00:00
|
|
|
function downloadFile(url, dest, cb) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const o_fs = require('fs-extra');
|
2017-12-16 02:53:11 +00:00
|
|
|
var file = o_fs.createWriteStream(dest);
|
|
|
|
(url.substring(0,5) === 'https' ? https : http).get(url, function(response) {
|
|
|
|
response.pipe(file);
|
|
|
|
file.on('finish', function() {
|
|
|
|
file.close(cb);
|
|
|
|
});
|
|
|
|
}).on('error', function(err) {
|
|
|
|
o_fs.unlink(dest);
|
|
|
|
if (cb) cb(err.message);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-16 17:23:02 +00:00
|
|
|
function extractTar(filename, packageDirectory, cb) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const o_fs = require('fs-extra');
|
|
|
|
const tar = require('tar');
|
2017-12-16 17:23:02 +00:00
|
|
|
o_fs.createReadStream(filename).pipe(
|
|
|
|
tar.x({
|
|
|
|
strip: 1,
|
|
|
|
C: packageDirectory
|
|
|
|
}).on('end', function() {
|
|
|
|
cb();
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-07-09 13:30:27 +00:00
|
|
|
function extractZip(filename, packageDirectory, opts, cb) {
|
2018-07-06 08:38:09 +00:00
|
|
|
const decompress = require('decompress');
|
|
|
|
|
2018-07-09 13:30:27 +00:00
|
|
|
decompress(filename, packageDirectory, opts).then((_files) => {
|
2018-07-06 08:38:09 +00:00
|
|
|
cb();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-12-19 19:07:48 +00:00
|
|
|
function proposeAlternative(word, _dictionary, _exceptions) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const propose = require('propose');
|
2017-12-19 19:07:48 +00:00
|
|
|
let exceptions = _exceptions || [];
|
|
|
|
let dictionary = _dictionary.filter((entry) => {
|
|
|
|
return exceptions.indexOf(entry) < 0;
|
|
|
|
});
|
|
|
|
return propose(word, dictionary, {threshold: 0.3});
|
|
|
|
}
|
|
|
|
|
2018-03-26 18:54:47 +00:00
|
|
|
function pwd() {
|
2018-03-26 19:26:37 +00:00
|
|
|
return process.env.PWD || process.cwd();
|
2018-03-26 18:54:47 +00:00
|
|
|
}
|
|
|
|
|
2018-04-20 13:52:13 +00:00
|
|
|
function getExternalContractUrl(file) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const constants = require('../constants');
|
2018-04-20 13:52:13 +00:00
|
|
|
let url;
|
|
|
|
const RAW_URL = 'https://raw.githubusercontent.com/';
|
|
|
|
const MALFORMED_ERROR = 'Malformed Github URL for ';
|
|
|
|
if (file.startsWith('https://github')) {
|
|
|
|
const match = file.match(/https:\/\/github\.[a-z]+\/(.*)/);
|
|
|
|
if (!match) {
|
|
|
|
console.error(MALFORMED_ERROR + file);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
url = `${RAW_URL}${match[1].replace('blob/', '')}`;
|
|
|
|
} else if (file.startsWith('git')) {
|
|
|
|
// Match values
|
|
|
|
// [0] entire input
|
|
|
|
// [1] git://
|
|
|
|
// [2] user
|
|
|
|
// [3] repository
|
|
|
|
// [4] path
|
|
|
|
// [5] branch
|
|
|
|
const match = file.match(
|
2018-05-31 14:37:40 +00:00
|
|
|
/(git:\/\/)?github\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~?\/&=]+)#?([a-zA-Z0-9\/_.-]*)?/
|
2018-04-20 13:52:13 +00:00
|
|
|
);
|
|
|
|
if (!match) {
|
|
|
|
console.error(MALFORMED_ERROR + file);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let branch = match[5];
|
|
|
|
if (!branch) {
|
|
|
|
branch = 'master';
|
|
|
|
}
|
|
|
|
url = `${RAW_URL}${match[2]}/${match[3]}/${branch}/${match[4]}`;
|
|
|
|
} else if (file.startsWith('http')) {
|
|
|
|
url = file;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
const match = url.match(
|
2018-04-20 16:04:27 +00:00
|
|
|
/\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/
|
2018-04-20 13:52:13 +00:00
|
|
|
);
|
|
|
|
return {
|
|
|
|
url,
|
|
|
|
filePath: constants.httpContractsDirectory + match[1]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-06-08 19:30:20 +00:00
|
|
|
function hexToNumber(hex){
|
2018-06-12 16:06:01 +00:00
|
|
|
const Web3 = require('web3');
|
2018-06-08 19:30:20 +00:00
|
|
|
return Web3.utils.hexToNumber(hex);
|
|
|
|
}
|
|
|
|
|
2018-07-30 19:49:58 +00:00
|
|
|
function isHex(hex){
|
|
|
|
const Web3 = require('web3');
|
|
|
|
return Web3.utils.isHex(hex);
|
|
|
|
}
|
|
|
|
|
2018-06-08 20:34:35 +00:00
|
|
|
function decodeParams(typesArray, hexString){
|
2018-06-12 16:06:01 +00:00
|
|
|
var Web3EthAbi = require('web3-eth-abi');
|
2018-06-08 20:34:35 +00:00
|
|
|
return Web3EthAbi.decodeParameters(typesArray, hexString);
|
|
|
|
}
|
|
|
|
|
2018-05-18 20:51:03 +00:00
|
|
|
function toChecksumAddress(address) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const Web3 = require('web3');
|
2018-05-18 20:51:03 +00:00
|
|
|
return Web3.utils.toChecksumAddress(address);
|
|
|
|
}
|
|
|
|
|
|
|
|
function sha3(arg) {
|
2018-06-11 18:36:52 +00:00
|
|
|
const Web3 = require('web3');
|
2018-05-18 20:51:03 +00:00
|
|
|
return Web3.utils.sha3(arg);
|
|
|
|
}
|
|
|
|
|
2018-07-25 15:05:27 +00:00
|
|
|
function soliditySha3(arg) {
|
|
|
|
const Web3 = require('web3');
|
|
|
|
return Web3.utils.soliditySha3(arg);
|
|
|
|
}
|
|
|
|
|
2018-05-23 13:33:32 +00:00
|
|
|
function normalizeInput(input) {
|
|
|
|
let args = Object.values(input);
|
|
|
|
if (args.length === 0) {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
if (args.length === 1) {
|
|
|
|
if (Array.isArray(args[0])) { return args[0].join(','); }
|
|
|
|
return args[0] || "";
|
|
|
|
}
|
|
|
|
return ('[' + args.map((x) => {
|
|
|
|
if (x === null) { return "null"; }
|
|
|
|
if (x === undefined) { return "undefined"; }
|
|
|
|
if (Array.isArray(x)) { return x.join(','); }
|
|
|
|
return x;
|
|
|
|
}).toString() + ']');
|
|
|
|
}
|
|
|
|
|
2018-06-01 03:12:17 +00:00
|
|
|
/**
|
|
|
|
* Builds a URL
|
|
|
|
*
|
|
|
|
* @param {string} protocol
|
|
|
|
* The URL protocol, defaults to http.
|
|
|
|
* @param {string} host
|
|
|
|
* The URL host, required.
|
|
|
|
* @param {string} port
|
|
|
|
* The URL port, default to empty string.
|
|
|
|
* @returns {string} the constructued URL, with defaults
|
|
|
|
*/
|
|
|
|
function buildUrl (protocol, host, port){
|
|
|
|
if(!host) throw new Error('utils.buildUrl: parameter \'host\' is required');
|
|
|
|
if(port) port = ':' + port;
|
|
|
|
else port = '';
|
|
|
|
return `${protocol || 'http'}://${host}${port}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds a URL
|
|
|
|
*
|
|
|
|
* @param {object} configObj Object containing protocol, host, and port to be used to construct the url.
|
|
|
|
* * protocol {String} (optional) The URL protocol, defaults to http.
|
|
|
|
* * host {String} (required) The URL host.
|
|
|
|
* * port {String} (optional) The URL port, default to empty string.
|
|
|
|
* @returns {string} the constructued URL, with defaults
|
|
|
|
*/
|
|
|
|
function buildUrlFromConfig (configObj){
|
|
|
|
if(!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null');
|
|
|
|
if(!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property');
|
2018-07-15 17:43:00 +00:00
|
|
|
return this.buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port);
|
2018-06-01 03:12:17 +00:00
|
|
|
}
|
|
|
|
|
2018-07-16 16:48:32 +00:00
|
|
|
function getWeiBalanceFromString(balanceString, web3){
|
|
|
|
if(!web3){
|
|
|
|
throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
|
|
|
|
}
|
|
|
|
if (!balanceString) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
const match = balanceString.match(balanceRegex);
|
|
|
|
if (!match) {
|
|
|
|
throw new Error(__('Unrecognized balance string "%s"', balanceString));
|
|
|
|
}
|
|
|
|
if (!match[2]) {
|
|
|
|
return web3.utils.toHex(parseInt(match[1], 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
return web3.utils.toWei(match[1], match[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getHexBalanceFromString(balanceString, web3) {
|
|
|
|
if(!web3){
|
|
|
|
throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
|
|
|
|
}
|
|
|
|
if (!balanceString) {
|
|
|
|
return 0xFFFFFFFFFFFFFFFFFF;
|
|
|
|
}
|
|
|
|
if (web3.utils.isHexStrict(balanceString)) {
|
|
|
|
return balanceString;
|
|
|
|
}
|
|
|
|
const match = balanceString.match(balanceRegex);
|
|
|
|
if (!match) {
|
|
|
|
throw new Error(__('Unrecognized balance string "%s"', balanceString));
|
|
|
|
}
|
|
|
|
if (!match[2]) {
|
|
|
|
return web3.utils.toHex(parseInt(match[1], 10));
|
|
|
|
}
|
|
|
|
|
|
|
|
return web3.utils.toHex(web3.utils.toWei(match[1], match[2]));
|
|
|
|
}
|
|
|
|
|
2018-07-24 12:29:06 +00:00
|
|
|
function compact(array) {
|
|
|
|
return array.filter(n => n);
|
|
|
|
}
|
|
|
|
|
|
|
|
function groupBy(array, key) {
|
|
|
|
return array.reduce(function(rv, x) {
|
|
|
|
(rv[x[key]] = rv[x[key]] || []).push(x);
|
|
|
|
return rv;
|
|
|
|
}, {});
|
|
|
|
}
|
|
|
|
|
|
|
|
function sample(array) {
|
|
|
|
return array[Math.floor(Math.random() * array.length)];
|
|
|
|
}
|
|
|
|
|
|
|
|
function last(array) {
|
|
|
|
return array[array.length - 1];
|
|
|
|
}
|
|
|
|
|
2018-07-27 21:20:36 +00:00
|
|
|
function interceptLogs(consoleContext, logger) {
|
|
|
|
let context = {};
|
|
|
|
context.console = consoleContext;
|
|
|
|
|
|
|
|
context.console.log = function() {
|
|
|
|
logger.info(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
context.console.warn = function() {
|
|
|
|
logger.warn(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
context.console.info = function() {
|
|
|
|
logger.info(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
context.console.debug = function() {
|
|
|
|
// TODO: ue JSON.stringify
|
|
|
|
logger.debug(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
context.console.trace = function() {
|
|
|
|
logger.trace(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
context.console.dir = function() {
|
|
|
|
logger.dir(normalizeInput(arguments));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-02-18 19:10:01 +00:00
|
|
|
module.exports = {
|
2018-07-06 15:06:55 +00:00
|
|
|
joinPath,
|
|
|
|
dirname,
|
|
|
|
filesMatchingPattern,
|
|
|
|
fileMatchesPattern,
|
|
|
|
recursiveMerge,
|
|
|
|
checkIsAvailable,
|
|
|
|
httpGet,
|
|
|
|
httpsGet,
|
|
|
|
httpGetJson,
|
|
|
|
httpsGetJson,
|
2018-07-08 18:24:19 +00:00
|
|
|
getJson,
|
2018-07-06 15:06:55 +00:00
|
|
|
hexToNumber,
|
2018-07-30 19:49:58 +00:00
|
|
|
isHex,
|
2018-06-19 13:02:19 +00:00
|
|
|
pingEndpoint,
|
2018-07-06 15:06:55 +00:00
|
|
|
decodeParams,
|
|
|
|
runCmd,
|
2017-02-18 21:06:39 +00:00
|
|
|
cd: cd,
|
2017-02-25 22:34:45 +00:00
|
|
|
sed: sed,
|
2017-12-16 02:53:11 +00:00
|
|
|
exit: exit,
|
2018-07-06 15:06:55 +00:00
|
|
|
downloadFile,
|
|
|
|
extractTar,
|
|
|
|
extractZip,
|
|
|
|
proposeAlternative,
|
2018-04-20 13:52:13 +00:00
|
|
|
pwd: pwd,
|
2018-05-18 20:51:03 +00:00
|
|
|
getExternalContractUrl,
|
2018-07-06 15:06:55 +00:00
|
|
|
toChecksumAddress,
|
|
|
|
sha3,
|
2018-07-25 15:05:27 +00:00
|
|
|
soliditySha3,
|
2018-06-01 03:12:17 +00:00
|
|
|
normalizeInput,
|
|
|
|
buildUrl,
|
2018-07-16 16:48:32 +00:00
|
|
|
buildUrlFromConfig,
|
|
|
|
getWeiBalanceFromString,
|
2018-07-24 12:29:06 +00:00
|
|
|
getHexBalanceFromString,
|
|
|
|
compact,
|
|
|
|
groupBy,
|
|
|
|
sample,
|
2018-07-27 21:20:36 +00:00
|
|
|
last,
|
|
|
|
interceptLogs
|
2017-02-18 19:10:01 +00:00
|
|
|
};
|