Create dev-utils with blockchainLifecycle in it
This commit is contained in:
		
							
								
								
									
										10
									
								
								packages/dev-utils/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								packages/dev-utils/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
Dev utils
 | 
			
		||||
------
 | 
			
		||||
 | 
			
		||||
Dev utils to be shared across 0x projects and packages
 | 
			
		||||
 | 
			
		||||
## Install
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
yarn add @0xproject/dev-utils
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										37
									
								
								packages/dev-utils/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								packages/dev-utils/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "@0xproject/dev-utils",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "description": "0x dev TS utils",
 | 
			
		||||
  "main": "lib/index.js",
 | 
			
		||||
  "types": "lib/index.d.ts",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "tsc",
 | 
			
		||||
    "clean": "shx rm -rf lib",
 | 
			
		||||
    "lint": "tslint --project . 'src/**/*.ts'"
 | 
			
		||||
  },
 | 
			
		||||
  "license": "Apache-2.0",
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "https://github.com/0xProject/0x.js.git"
 | 
			
		||||
  },
 | 
			
		||||
  "bugs": {
 | 
			
		||||
    "url": "https://github.com/0xProject/0x.js/issues"
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://github.com/0xProject/0x.js/packages/dev-utils/README.md",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@0xproject/tslint-config": "^0.2.0",
 | 
			
		||||
    "@types/lodash": "^4.14.86",
 | 
			
		||||
    "npm-run-all": "^4.1.2",
 | 
			
		||||
    "shx": "^0.2.2",
 | 
			
		||||
    "tslint": "5.8.0",
 | 
			
		||||
    "typescript": "~2.6.1",
 | 
			
		||||
    "types-bn": "^0.0.1",
 | 
			
		||||
    "types-ethereumjs-util": "0xProject/types-ethereumjs-util"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "bignumber.js": "~4.1.0",
 | 
			
		||||
    "ethereumjs-util": "^5.1.2",
 | 
			
		||||
    "lodash": "^4.17.4",
 | 
			
		||||
    "request-promise-native": "^1.0.5"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								packages/dev-utils/src/blockchain_lifecycle.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								packages/dev-utils/src/blockchain_lifecycle.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
import {RPC} from './rpc';
 | 
			
		||||
 | 
			
		||||
export class BlockchainLifecycle {
 | 
			
		||||
    private rpc: RPC;
 | 
			
		||||
    private snapshotIdsStack: number[];
 | 
			
		||||
    constructor(url: string) {
 | 
			
		||||
        this.rpc = new RPC(url);
 | 
			
		||||
        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();
 | 
			
		||||
        this.snapshotIdsStack.push(snapshotId);
 | 
			
		||||
    }
 | 
			
		||||
    public async revertAsync(): Promise<void> {
 | 
			
		||||
        const snapshotId = this.snapshotIdsStack.pop() as number;
 | 
			
		||||
        const didRevert = await this.rpc.revertSnapshotAsync(snapshotId);
 | 
			
		||||
        if (!didRevert) {
 | 
			
		||||
            throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public async mineABlock(): Promise<void> {
 | 
			
		||||
        await this.rpc.mineBlockAsync();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								packages/dev-utils/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/dev-utils/src/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
export {RPC} from './rpc';
 | 
			
		||||
export {BlockchainLifecycle} from './blockchain_lifecycle';
 | 
			
		||||
							
								
								
									
										61
									
								
								packages/dev-utils/src/rpc.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/dev-utils/src/rpc.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
import * as ethUtil from 'ethereumjs-util';
 | 
			
		||||
import * as request from 'request-promise-native';
 | 
			
		||||
 | 
			
		||||
export class RPC {
 | 
			
		||||
    private url: string;
 | 
			
		||||
    private port: number;
 | 
			
		||||
    private id: number;
 | 
			
		||||
    constructor(url: string) {
 | 
			
		||||
        this.url = 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								packages/dev-utils/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								packages/dev-utils/tsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "module": "commonjs",
 | 
			
		||||
    "target": "es5",
 | 
			
		||||
    "lib": [ "es2017", "dom"],
 | 
			
		||||
    "outDir": "lib",
 | 
			
		||||
    "sourceMap": true,
 | 
			
		||||
    "declaration": true,
 | 
			
		||||
    "noImplicitAny": true,
 | 
			
		||||
    "strictNullChecks": true
 | 
			
		||||
  },
 | 
			
		||||
  "include": [
 | 
			
		||||
    "./src/**/*",
 | 
			
		||||
    "../../node_modules/types-bn/index.d.ts",
 | 
			
		||||
    "../../node_modules/types-ethereumjs-util/index.d.ts"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								packages/dev-utils/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/dev-utils/tslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": [
 | 
			
		||||
    "@0xproject/tslint-config"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user