parent
2d55e3398b
commit
9a54458f3a
@ -1,129 +0,0 @@ |
||||
/* eslint no-extend-native: "warn" */ |
||||
let fs = require('./fs') |
||||
var async = require('async') |
||||
var path = require('path') |
||||
let RemixCompiler = require('remix-solidity').Compiler |
||||
|
||||
String.prototype.regexIndexOf = function (regex, startpos) { |
||||
var indexOf = this.substring(startpos || 0).search(regex) |
||||
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf |
||||
} |
||||
|
||||
function writeTestAccountsContract (accounts) { |
||||
var testAccountContract = require('../sol/tests_accounts.sol.js') |
||||
var body = 'address[' + accounts.length + '] memory accounts;' |
||||
if (!accounts.length) body += ';' |
||||
else { |
||||
accounts.map((address, index) => { |
||||
body += `\naccounts[${index}] = ${address};\n` |
||||
}) |
||||
} |
||||
return testAccountContract.replace('>accounts<', body) |
||||
} |
||||
|
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
||||
|
||||
// TODO: replace this with remix's own compiler code
|
||||
function compileFileOrFiles (filename, isDirectory, opts, cb) { |
||||
let compiler |
||||
let accounts = opts.accounts || [] |
||||
const sources = { |
||||
'tests.sol': { content: require('../sol/tests.sol.js') }, |
||||
'remix_tests.sol': { content: require('../sol/tests.sol.js') }, |
||||
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) } |
||||
} |
||||
const filepath = (isDirectory ? filename : path.dirname(filename)) |
||||
// TODO: for now assumes filepath dir contains all tests, later all this
|
||||
// should be replaced with remix's & browser solidity compiler code
|
||||
|
||||
// This logic is wrong
|
||||
// We should only look into current file if a full file name with path is given
|
||||
// We should only walk through directory if a directory name is passed
|
||||
try { |
||||
// walkSync only if it is a directory
|
||||
fs.walkSync(filepath, foundpath => { |
||||
// only process .sol files
|
||||
if (foundpath.split('.').pop() === 'sol') { |
||||
let c = fs.readFileSync(foundpath).toString() |
||||
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
||||
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
||||
if (foundpath.indexOf('_test.sol') > 0 && c.regexIndexOf(s) < 0) { |
||||
c = includeTestLibs.concat(c) |
||||
} |
||||
sources[foundpath] = { content: c } |
||||
} |
||||
}) |
||||
} catch (e) { |
||||
throw e |
||||
} finally { |
||||
async.waterfall([ |
||||
function loadCompiler (next) { |
||||
compiler = new RemixCompiler() |
||||
compiler.onInternalCompilerLoaded() |
||||
// compiler.event.register('compilerLoaded', this, function (version) {
|
||||
next() |
||||
// });
|
||||
}, |
||||
function doCompilation (next) { |
||||
compiler.event.register('compilationFinished', this, function (success, data, source) { |
||||
next(null, data) |
||||
}) |
||||
compiler.compile(sources, filepath) |
||||
} |
||||
], function (err, result) { |
||||
let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') |
||||
if (errors.length > 0) { |
||||
if (!isBrowser) require('signale').fatal(errors) |
||||
return cb(new Error('errors compiling')) |
||||
} |
||||
cb(err, result.contracts) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
function compileContractSources (sources, importFileCb, opts, cb) { |
||||
let compiler, filepath |
||||
let accounts = opts.accounts || [] |
||||
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
|
||||
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { |
||||
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') } |
||||
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) } |
||||
} |
||||
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
||||
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
||||
for (let file in sources) { |
||||
const c = sources[file].content |
||||
if (file.indexOf('_test.sol') > 0 && c && c.regexIndexOf(s) < 0) { |
||||
sources[file].content = includeTestLibs.concat(c) |
||||
} |
||||
} |
||||
|
||||
async.waterfall([ |
||||
function loadCompiler (next) { |
||||
compiler = new RemixCompiler(importFileCb) |
||||
compiler.onInternalCompilerLoaded() |
||||
// compiler.event.register('compilerLoaded', this, function (version) {
|
||||
next() |
||||
// });
|
||||
}, |
||||
function doCompilation (next) { |
||||
compiler.event.register('compilationFinished', this, function (success, data, source) { |
||||
next(null, data) |
||||
}) |
||||
compiler.compile(sources, filepath) |
||||
} |
||||
], function (err, result) { |
||||
let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') |
||||
if (errors.length > 0) { |
||||
if (!isBrowser) require('signale').fatal(errors) |
||||
return cb(new Error('errors compiling')) |
||||
} |
||||
cb(err, result.contracts) |
||||
}) |
||||
} |
||||
|
||||
module.exports = { |
||||
compileFileOrFiles: compileFileOrFiles, |
||||
compileContractSources: compileContractSources |
||||
} |
@ -0,0 +1,127 @@ |
||||
/* eslint no-extend-native: "warn" */ |
||||
let fs = require('../src/fs') |
||||
var async = require('async') |
||||
var path = require('path') |
||||
let RemixCompiler = require('remix-solidity').Compiler |
||||
|
||||
|
||||
function regexIndexOf (inputString, regex, startpos = 0) { |
||||
var indexOf = inputString.substring(startpos).search(regex) |
||||
return (indexOf >= 0) ? (indexOf + (startpos)) : indexOf |
||||
} |
||||
|
||||
function writeTestAccountsContract (accounts) { |
||||
var testAccountContract = require('../sol/tests_accounts.sol.js') |
||||
var body = 'address[' + accounts.length + '] memory accounts;' |
||||
if (!accounts.length) body += ';' |
||||
else { |
||||
accounts.map((address, index) => { |
||||
body += `\naccounts[${index}] = ${address};\n` |
||||
}) |
||||
} |
||||
return testAccountContract.replace('>accounts<', body) |
||||
} |
||||
|
||||
var userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
||||
var isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
||||
|
||||
// TODO: replace this with remix's own compiler code
|
||||
export function compileFileOrFiles (filename, isDirectory, opts, cb) { |
||||
let compiler |
||||
let accounts = opts.accounts || [] |
||||
const sources = { |
||||
'tests.sol': { content: require('../sol/tests.sol.js') }, |
||||
'remix_tests.sol': { content: require('../sol/tests.sol.js') }, |
||||
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) } |
||||
} |
||||
const filepath = (isDirectory ? filename : path.dirname(filename)) |
||||
// TODO: for now assumes filepath dir contains all tests, later all this
|
||||
// should be replaced with remix's & browser solidity compiler code
|
||||
|
||||
// This logic is wrong
|
||||
// We should only look into current file if a full file name with path is given
|
||||
// We should only walk through directory if a directory name is passed
|
||||
try { |
||||
// walkSync only if it is a directory
|
||||
fs.walkSync(filepath, foundpath => { |
||||
// only process .sol files
|
||||
if (foundpath.split('.').pop() === 'sol') { |
||||
let c = fs.readFileSync(foundpath).toString() |
||||
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
||||
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
||||
if (foundpath.indexOf('_test.sol') > 0 && regexIndexOf(c, s) < 0) { |
||||
c = includeTestLibs.concat(c) |
||||
} |
||||
sources[foundpath] = { content: c } |
||||
} |
||||
}) |
||||
} catch (e) { |
||||
throw e |
||||
} finally { |
||||
async.waterfall([ |
||||
function loadCompiler (next) { |
||||
compiler = new RemixCompiler() |
||||
compiler.onInternalCompilerLoaded() |
||||
// compiler.event.register('compilerLoaded', this, function (version) {
|
||||
next() |
||||
// });
|
||||
}, |
||||
function doCompilation (next) { |
||||
// @ts-ignore
|
||||
compiler.event.register('compilationFinished', this, function (success, data, source) { |
||||
next(null, data) |
||||
}) |
||||
compiler.compile(sources, filepath) |
||||
} |
||||
], function (err, result) { |
||||
let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') |
||||
if (errors.length > 0) { |
||||
if (!isBrowser) require('signale').fatal(errors) |
||||
return cb(new Error('errors compiling')) |
||||
} |
||||
cb(err, result.contracts) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
export function compileContractSources (sources, importFileCb, opts, cb) { |
||||
let compiler, filepath |
||||
let accounts = opts.accounts || [] |
||||
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
|
||||
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { |
||||
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') } |
||||
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) } |
||||
} |
||||
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
||||
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
||||
for (let file in sources) { |
||||
const c = sources[file].content |
||||
if (file.indexOf('_test.sol') > 0 && c && regexIndexOf(c, s) < 0) { |
||||
sources[file].content = includeTestLibs.concat(c) |
||||
} |
||||
} |
||||
|
||||
async.waterfall([ |
||||
function loadCompiler (next) { |
||||
compiler = new RemixCompiler(importFileCb) |
||||
compiler.onInternalCompilerLoaded() |
||||
// compiler.event.register('compilerLoaded', this, function (version) {
|
||||
next() |
||||
// });
|
||||
}, |
||||
function doCompilation (next) { |
||||
// @ts-ignore
|
||||
compiler.event.register('compilationFinished', this, function (success, data, source) { |
||||
next(null, data) |
||||
}) |
||||
compiler.compile(sources, filepath) |
||||
} |
||||
], function (err, result) { |
||||
let errors = (result.errors || []).filter((e) => e.type === 'Error' || e.severity === 'error') |
||||
if (errors.length > 0) { |
||||
if (!isBrowser) require('signale').fatal(errors) |
||||
return cb(new Error('errors compiling')) |
||||
} |
||||
cb(err, result.contracts) |
||||
}) |
||||
} |
@ -1,113 +0,0 @@ |
||||
var async = require('async') |
||||
var remixLib = require('remix-lib') |
||||
|
||||
function deployAll (compileResult, web3, callback) { |
||||
let compiledObject = {} |
||||
let contracts = {} |
||||
let accounts = [] |
||||
|
||||
async.waterfall([ |
||||
function getAccountList (next) { |
||||
web3.eth.getAccounts((_err, _accounts) => { |
||||
accounts = _accounts |
||||
next() |
||||
}) |
||||
}, |
||||
function getContractData (next) { |
||||
for (let contractFile in compileResult) { |
||||
for (let contractName in compileResult[contractFile]) { |
||||
let contract = compileResult[contractFile][contractName] |
||||
|
||||
const className = contractName |
||||
const filename = contractFile |
||||
|
||||
let abi = contract.abi |
||||
let code = contract.evm.bytecode.object |
||||
|
||||
compiledObject[className] = {} |
||||
compiledObject[className].abi = abi |
||||
compiledObject[className].code = code |
||||
compiledObject[className].filename = filename |
||||
compiledObject[className].className = className |
||||
compiledObject[className].raw = contract |
||||
|
||||
if (contractFile.indexOf('_test.sol') >= 0) { |
||||
compiledObject[className].isTest = true |
||||
} |
||||
} |
||||
} |
||||
next() |
||||
}, |
||||
function determineContractsToDeploy (next) { |
||||
let contractsToDeploy = ['Assert'] |
||||
let allContracts = Object.keys(compiledObject) |
||||
|
||||
for (let contractName of allContracts) { |
||||
if (contractName === 'Assert') { |
||||
continue |
||||
} |
||||
if (compiledObject[contractName].isTest) { |
||||
contractsToDeploy.push(contractName) |
||||
} |
||||
} |
||||
next(null, contractsToDeploy) |
||||
}, |
||||
function deployContracts (contractsToDeploy, next) { |
||||
var deployRunner = (deployObject, contractObject, contractName, filename, callback) => { |
||||
deployObject.estimateGas().then((gasValue) => { |
||||
deployObject.send({ |
||||
from: accounts[0], |
||||
gas: Math.ceil(gasValue * 1.2) |
||||
}).on('receipt', function (receipt) { |
||||
contractObject.options.address = receipt.contractAddress |
||||
contractObject.options.from = accounts[0] |
||||
contractObject.options.gas = 5000 * 1000 |
||||
compiledObject[contractName].deployedAddress = receipt.contractAddress |
||||
|
||||
contracts[contractName] = contractObject |
||||
contracts[contractName].filename = filename |
||||
|
||||
callback(null, { result: { createdAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM
|
||||
}).on('error', function (err) { |
||||
console.error(err) |
||||
callback(err) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
async.eachOfLimit(contractsToDeploy, 1, function (contractName, index, nextEach) { |
||||
let contract = compiledObject[contractName] |
||||
let encodeDataFinalCallback = (error, contractDeployData) => { |
||||
if (error) return nextEach(error) |
||||
try { |
||||
let contractObject = new web3.eth.Contract(contract.abi) |
||||
let deployObject = contractObject.deploy({arguments: [], data: '0x' + contractDeployData.dataHex}) |
||||
deployRunner(deployObject, contractObject, contractName, contract.filename, (error) => { nextEach(error) }) |
||||
} catch (e) { |
||||
throw e |
||||
} |
||||
} |
||||
|
||||
let encodeDataStepCallback = (msg) => { console.dir(msg) } |
||||
|
||||
let encodeDataDeployLibraryCallback = (libData, callback) => { |
||||
let abi = compiledObject[libData.data.contractName].abi |
||||
let code = compiledObject[libData.data.contractName].code |
||||
let libraryObject = new web3.eth.Contract(abi) |
||||
let deployObject = libraryObject.deploy({arguments: [], data: '0x' + code}) |
||||
deployRunner(deployObject, libraryObject, libData.data.contractName, contract.filename, callback) |
||||
} |
||||
|
||||
let funAbi = null // no need to set the abi for encoding the constructor
|
||||
let params = '' // we suppose that the test contract does not have any param in the constructor
|
||||
remixLib.execution.txFormat.encodeConstructorCallAndDeployLibraries(contractName, contract.raw, compileResult, params, funAbi, encodeDataFinalCallback, encodeDataStepCallback, encodeDataDeployLibraryCallback) |
||||
}, function () { |
||||
next(null, contracts) |
||||
}) |
||||
} |
||||
], callback) |
||||
} |
||||
|
||||
module.exports = { |
||||
deployAll: deployAll |
||||
} |
@ -0,0 +1,109 @@ |
||||
var async = require('async') |
||||
var remixLib = require('remix-lib') |
||||
|
||||
export function deployAll (compileResult, web3, callback) { |
||||
let compiledObject = {} |
||||
let contracts = {} |
||||
let accounts = [] |
||||
|
||||
async.waterfall([ |
||||
function getAccountList (next) { |
||||
web3.eth.getAccounts((_err, _accounts) => { |
||||
accounts = _accounts |
||||
next() |
||||
}) |
||||
}, |
||||
function getContractData (next) { |
||||
for (let contractFile in compileResult) { |
||||
for (let contractName in compileResult[contractFile]) { |
||||
let contract = compileResult[contractFile][contractName] |
||||
|
||||
const className = contractName |
||||
const filename = contractFile |
||||
|
||||
let abi = contract.abi |
||||
let code = contract.evm.bytecode.object |
||||
|
||||
compiledObject[className] = {} |
||||
compiledObject[className].abi = abi |
||||
compiledObject[className].code = code |
||||
compiledObject[className].filename = filename |
||||
compiledObject[className].className = className |
||||
compiledObject[className].raw = contract |
||||
|
||||
if (contractFile.indexOf('_test.sol') >= 0) { |
||||
compiledObject[className].isTest = true |
||||
} |
||||
} |
||||
} |
||||
next() |
||||
}, |
||||
function determineContractsToDeploy (next) { |
||||
let contractsToDeploy = ['Assert'] |
||||
let allContracts = Object.keys(compiledObject) |
||||
|
||||
for (let contractName of allContracts) { |
||||
if (contractName === 'Assert') { |
||||
continue |
||||
} |
||||
if (compiledObject[contractName].isTest) { |
||||
contractsToDeploy.push(contractName) |
||||
} |
||||
} |
||||
next(null, contractsToDeploy) |
||||
}, |
||||
function deployContracts (contractsToDeploy, next) { |
||||
var deployRunner = (deployObject, contractObject, contractName, filename, callback) => { |
||||
deployObject.estimateGas().then((gasValue) => { |
||||
deployObject.send({ |
||||
from: accounts[0], |
||||
gas: Math.ceil(gasValue * 1.2) |
||||
}).on('receipt', function (receipt) { |
||||
contractObject.options.address = receipt.contractAddress |
||||
contractObject.options.from = accounts[0] |
||||
contractObject.options.gas = 5000 * 1000 |
||||
compiledObject[contractName].deployedAddress = receipt.contractAddress |
||||
|
||||
contracts[contractName] = contractObject |
||||
contracts[contractName].filename = filename |
||||
|
||||
callback(null, { result: { createdAddress: receipt.contractAddress } }) // TODO this will only work with JavaScriptV VM
|
||||
}).on('error', function (err) { |
||||
console.error(err) |
||||
callback(err) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
async.eachOfLimit(contractsToDeploy, 1, function (contractName, index, nextEach) { |
||||
let contract = compiledObject[contractName] |
||||
let encodeDataFinalCallback = (error, contractDeployData) => { |
||||
if (error) return nextEach(error) |
||||
try { |
||||
let contractObject = new web3.eth.Contract(contract.abi) |
||||
let deployObject = contractObject.deploy({arguments: [], data: '0x' + contractDeployData.dataHex}) |
||||
deployRunner(deployObject, contractObject, contractName, contract.filename, (error) => { nextEach(error) }) |
||||
} catch (e) { |
||||
throw e |
||||
} |
||||
} |
||||
|
||||
let encodeDataStepCallback = (msg) => { console.dir(msg) } |
||||
|
||||
let encodeDataDeployLibraryCallback = (libData, callback) => { |
||||
let abi = compiledObject[libData.data.contractName].abi |
||||
let code = compiledObject[libData.data.contractName].code |
||||
let libraryObject = new web3.eth.Contract(abi) |
||||
let deployObject = libraryObject.deploy({arguments: [], data: '0x' + code}) |
||||
deployRunner(deployObject, libraryObject, libData.data.contractName, contract.filename, callback) |
||||
} |
||||
|
||||
let funAbi = null // no need to set the abi for encoding the constructor
|
||||
let params = '' // we suppose that the test contract does not have any param in the constructor
|
||||
remixLib.execution.txFormat.encodeConstructorCallAndDeployLibraries(contractName, contract.raw, compileResult, params, funAbi, encodeDataFinalCallback, encodeDataStepCallback, encodeDataDeployLibraryCallback) |
||||
}, function () { |
||||
next(null, contracts) |
||||
}) |
||||
} |
||||
], callback) |
||||
} |
@ -1,58 +0,0 @@ |
||||
var gray = require('ansi-gray') |
||||
const winston = require('winston') |
||||
var timestamp = require('time-stamp') |
||||
var supportsColor = require('color-support') |
||||
|
||||
function hasFlag (flag) { |
||||
return ((typeof (process) !== 'undefined') && (process.argv.indexOf('--' + flag) !== -1)) |
||||
} |
||||
|
||||
function addColor (str) { |
||||
if (hasFlag('no-color')) { |
||||
return str |
||||
} |
||||
|
||||
if (hasFlag('color')) { |
||||
return gray(str) |
||||
} |
||||
|
||||
if (supportsColor()) { |
||||
return gray(str) |
||||
} |
||||
|
||||
return str |
||||
} |
||||
function getTimestamp () { |
||||
return '[' + addColor(timestamp('HH:mm:ss')) + ']' |
||||
} |
||||
// create winston logger format
|
||||
const logFmt = winston.format.printf((info) => { |
||||
return `${getTimestamp()} ${info.level}: ${info.message}` |
||||
}) |
||||
|
||||
class Log { |
||||
constructor () { |
||||
this.logger = winston.createLogger({ |
||||
level: 'error', |
||||
transports: [new winston.transports.Console()], |
||||
format: winston.format.combine( |
||||
winston.format.colorize({ all: true }), |
||||
logFmt |
||||
) |
||||
}) |
||||
} |
||||
setVerbosity (v) { |
||||
this.logger.configure({ |
||||
level: v, |
||||
transports: [new winston.transports.Console()], |
||||
format: winston.format.combine( |
||||
winston.format.colorize({ all: true }), |
||||
logFmt |
||||
) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
module.exports = { |
||||
Log |
||||
} |
@ -0,0 +1,57 @@ |
||||
var gray = require('ansi-gray') |
||||
const winston = require('winston') |
||||
var timestamp = require('time-stamp') |
||||
var supportsColor = require('color-support') |
||||
|
||||
function hasFlag (flag) { |
||||
return ((typeof (process) !== 'undefined') && (process.argv.indexOf('--' + flag) !== -1)) |
||||
} |
||||
|
||||
function addColor (str) { |
||||
if (hasFlag('no-color')) { |
||||
return str |
||||
} |
||||
|
||||
if (hasFlag('color')) { |
||||
return gray(str) |
||||
} |
||||
|
||||
if (supportsColor()) { |
||||
return gray(str) |
||||
} |
||||
|
||||
return str |
||||
} |
||||
function getTimestamp () { |
||||
return '[' + addColor(timestamp('HH:mm:ss')) + ']' |
||||
} |
||||
// create winston logger format
|
||||
const logFmt = winston.format.printf((info) => { |
||||
return `${getTimestamp()} ${info.level}: ${info.message}` |
||||
}) |
||||
|
||||
class Log { |
||||
logger: any; |
||||
constructor () { |
||||
this.logger = winston.createLogger({ |
||||
level: 'error', |
||||
transports: [new winston.transports.Console()], |
||||
format: winston.format.combine( |
||||
winston.format.colorize({ all: true }), |
||||
logFmt |
||||
) |
||||
}) |
||||
} |
||||
setVerbosity (v) { |
||||
this.logger.configure({ |
||||
level: v, |
||||
transports: [new winston.transports.Console()], |
||||
format: winston.format.combine( |
||||
winston.format.colorize({ all: true }), |
||||
logFmt |
||||
) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
export = Log |
Loading…
Reference in new issue