Merge branch 'development' into convertScriptsToTs
* development: (71 commits) Transform input data before encoding for callAsync and getABIEncodedTransactionData Update coverage badge to show development coverage Configure post build hook Notify coveralls after all tasks have finished Address feedback Revert "Report all coverage reports together" Separate published packages and typescript typings on README Report all coverage reports together Add other statement types Properly and consistently parse ENV vars Add forgotten file Start using solidity-parser-antlr Fix the default always overriding to address Submit a TD PR Add an explanatory comment for making ranges unique Fix a typo in handling env variables Introduce TESTRPC_FIRST_ADDRESS Make BlockchainLifecycle accept only web3Wrapper Fix comments Fix deployer CHANGELOG ... # Conflicts: # README.md # packages/deployer/package.json # packages/subproviders/src/globals.d.ts # yarn.lock
This commit is contained in:
@@ -1,21 +1,22 @@
|
||||
import { RPC } from './rpc';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BlockchainLifecycle {
|
||||
private _rpc: RPC;
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _snapshotIdsStack: number[];
|
||||
constructor() {
|
||||
this._rpc = new RPC();
|
||||
constructor(web3Wrapper: Web3Wrapper) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._snapshotIdsStack = [];
|
||||
}
|
||||
// TODO: In order to run these tests on an actual node, we should check if we are running against
|
||||
// TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
|
||||
public async startAsync(): Promise<void> {
|
||||
const snapshotId = await this._rpc.takeSnapshotAsync();
|
||||
const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
|
||||
this._snapshotIdsStack.push(snapshotId);
|
||||
}
|
||||
public async revertAsync(): Promise<void> {
|
||||
const snapshotId = this._snapshotIdsStack.pop() as number;
|
||||
const didRevert = await this._rpc.revertSnapshotAsync(snapshotId);
|
||||
const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
|
||||
if (!didRevert) {
|
||||
throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export const constants = {
|
||||
RPC_URL: 'http://localhost:8545',
|
||||
RPC_PORT: 8545,
|
||||
GAS_ESTIMATE: 1000000,
|
||||
GAS_ESTIMATE: 5000000,
|
||||
TESTRPC_FIRST_ADDRESS: '0x5409ed021d9299bf6814279a6a1411a7e866a631',
|
||||
};
|
||||
|
||||
22
packages/dev-utils/src/coverage.ts
Normal file
22
packages/dev-utils/src/coverage.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { CoverageSubprovider } from '@0xproject/sol-cov';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
let coverageSubprovider: CoverageSubprovider;
|
||||
|
||||
export const coverage = {
|
||||
getCoverageSubproviderSingleton(): CoverageSubprovider {
|
||||
if (_.isUndefined(coverageSubprovider)) {
|
||||
coverageSubprovider = coverage._getCoverageSubprovider();
|
||||
}
|
||||
return coverageSubprovider;
|
||||
},
|
||||
_getCoverageSubprovider(): CoverageSubprovider {
|
||||
const artifactsPath = './src/artifacts';
|
||||
const contractsPath = './src/contracts';
|
||||
const networkId = 50;
|
||||
const defaultFromAddress = constants.TESTRPC_FIRST_ADDRESS;
|
||||
return new CoverageSubprovider(artifactsPath, contractsPath, networkId, defaultFromAddress);
|
||||
},
|
||||
};
|
||||
24
packages/dev-utils/src/env.ts
Normal file
24
packages/dev-utils/src/env.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as process from 'process';
|
||||
|
||||
export enum EnvVars {
|
||||
SolidityCoverage = 'SOLIDITY_COVERAGE',
|
||||
VerboseGanache = 'VERBOSE_GANACHE',
|
||||
}
|
||||
|
||||
export const env = {
|
||||
parseBoolean(key: string): boolean {
|
||||
let isTrue: boolean;
|
||||
const envVarValue = process.env[key];
|
||||
if (envVarValue === 'true') {
|
||||
isTrue = true;
|
||||
} else if (envVarValue === 'false' || _.isUndefined(envVarValue)) {
|
||||
isTrue = false;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Failed to parse ENV variable ${key} as boolean. Please make sure it's either true or false. Defaults to false`,
|
||||
);
|
||||
}
|
||||
return isTrue;
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
export { RPC } from './rpc';
|
||||
export { BlockchainLifecycle } from './blockchain_lifecycle';
|
||||
export { web3Factory } from './web3_factory';
|
||||
export { constants as devConstants } from './constants';
|
||||
export { coverage } from './coverage';
|
||||
export { env, EnvVars } from './env';
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as request from 'request-promise-native';
|
||||
|
||||
import { constants } from './constants';
|
||||
|
||||
export class RPC {
|
||||
private _url: string;
|
||||
private _id: number;
|
||||
constructor() {
|
||||
this._url = constants.RPC_URL;
|
||||
this._id = 0;
|
||||
}
|
||||
public async takeSnapshotAsync(): Promise<number> {
|
||||
const method = 'evm_snapshot';
|
||||
const params: any[] = [];
|
||||
const payload = this._toPayload(method, params);
|
||||
const snapshotIdHex = await this._sendAsync(payload);
|
||||
const snapshotId = ethUtil.bufferToInt(ethUtil.toBuffer(snapshotIdHex));
|
||||
return snapshotId;
|
||||
}
|
||||
public async revertSnapshotAsync(snapshotId: number): Promise<boolean> {
|
||||
const method = 'evm_revert';
|
||||
const params = [snapshotId];
|
||||
const payload = this._toPayload(method, params);
|
||||
const didRevert = await this._sendAsync(payload);
|
||||
return didRevert;
|
||||
}
|
||||
public async increaseTimeAsync(time: number) {
|
||||
const method = 'evm_increaseTime';
|
||||
const params = [time];
|
||||
const payload = this._toPayload(method, params);
|
||||
return this._sendAsync(payload);
|
||||
}
|
||||
public async mineBlockAsync(): Promise<void> {
|
||||
const method = 'evm_mine';
|
||||
const params: any[] = [];
|
||||
const payload = this._toPayload(method, params);
|
||||
await this._sendAsync(payload);
|
||||
}
|
||||
private _toPayload(method: string, params: any[] = []): string {
|
||||
const payload = JSON.stringify({
|
||||
id: this._id,
|
||||
method,
|
||||
params,
|
||||
});
|
||||
this._id += 1;
|
||||
return payload;
|
||||
}
|
||||
private async _sendAsync(payload: string): Promise<any> {
|
||||
const opts = {
|
||||
method: 'POST',
|
||||
uri: this._url,
|
||||
body: payload,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
};
|
||||
const bodyString = await request(opts);
|
||||
const body = JSON.parse(bodyString);
|
||||
return body.result;
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,14 @@
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider } from '@0xproject/subproviders';
|
||||
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider, GanacheSubprovider } from '@0xproject/subproviders';
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
import * as process from 'process';
|
||||
|
||||
import { constants } from './constants';
|
||||
import { coverage } from './coverage';
|
||||
import { env, EnvVars } from './env';
|
||||
|
||||
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
|
||||
// because they are using the wrong XHR package.
|
||||
@@ -17,24 +22,52 @@ import { constants } from './constants';
|
||||
// tslint:disable-next-line:ordered-imports
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export interface Web3Config {
|
||||
hasAddresses?: boolean; // default: true
|
||||
shouldUseInProcessGanache?: boolean; // default: false
|
||||
}
|
||||
|
||||
export const web3Factory = {
|
||||
create(hasAddresses: boolean = true): Web3 {
|
||||
const provider = this.getRpcProvider(hasAddresses);
|
||||
create(config: Web3Config = {}): Web3 {
|
||||
const provider = this.getRpcProvider(config);
|
||||
const web3 = new Web3();
|
||||
web3.setProvider(provider);
|
||||
return web3;
|
||||
},
|
||||
getRpcProvider(hasAddresses: boolean = true): Web3.Provider {
|
||||
getRpcProvider(config: Web3Config = {}): Web3.Provider {
|
||||
const provider = new ProviderEngine();
|
||||
const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage);
|
||||
if (isCoverageEnabled) {
|
||||
provider.addProvider(coverage.getCoverageSubproviderSingleton());
|
||||
}
|
||||
const hasAddresses = _.isUndefined(config.hasAddresses) || config.hasAddresses;
|
||||
if (!hasAddresses) {
|
||||
provider.addProvider(new EmptyWalletSubprovider());
|
||||
}
|
||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
|
||||
provider.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}),
|
||||
);
|
||||
const logger = {
|
||||
log: (arg: any) => {
|
||||
fs.appendFileSync('ganache.log', `${arg}\n`);
|
||||
},
|
||||
};
|
||||
const shouldUseInProcessGanache = !!config.shouldUseInProcessGanache;
|
||||
if (shouldUseInProcessGanache) {
|
||||
provider.addProvider(
|
||||
new GanacheSubprovider({
|
||||
logger,
|
||||
verbose: env.parseBoolean(EnvVars.SolidityCoverage),
|
||||
port: 8545,
|
||||
networkId: 50,
|
||||
mnemonic: 'concert load couple harbor equip island argue ramp clarify fence smart topic',
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
provider.addProvider(
|
||||
new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}),
|
||||
);
|
||||
}
|
||||
provider.start();
|
||||
return provider;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user