Use Geth for contract tests
This commit is contained in:
		@@ -200,7 +200,8 @@ export class ZeroEx {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public async awaitTransactionMinedAsync(
 | 
					    public async awaitTransactionMinedAsync(
 | 
				
			||||||
        txHash: string,
 | 
					        txHash: string,
 | 
				
			||||||
        pollingIntervalMs: number = 1000,
 | 
					        // TODO(albrow): Change this back to 1000
 | 
				
			||||||
 | 
					        pollingIntervalMs: number = 100,
 | 
				
			||||||
        timeoutMs?: number,
 | 
					        timeoutMs?: number,
 | 
				
			||||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
					    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
				
			||||||
        // Hack: Get Web3Wrapper from ContractWrappers
 | 
					        // Hack: Get Web3Wrapper from ContractWrappers
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								packages/contracts/test/utils/assertions.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								packages/contracts/test/utils/assertions.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import * as chai from 'chai';
 | 
				
			||||||
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { constants } from '../../util/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const expect = chai.expect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// throws if the given promise does not reject with one of two expected error
 | 
				
			||||||
 | 
					// messages.
 | 
				
			||||||
 | 
					export const expectRevertOrAlwaysFailingTransaction = <T>(p: Promise<T>) => {
 | 
				
			||||||
 | 
					    return expect(p)
 | 
				
			||||||
 | 
					        .to.be.rejected()
 | 
				
			||||||
 | 
					        .then(e => {
 | 
				
			||||||
 | 
					            expect(e).to.satisfy(
 | 
				
			||||||
 | 
					                (err: Error) =>
 | 
				
			||||||
 | 
					                    _.includes(err.message, constants.REVERT) ||
 | 
				
			||||||
 | 
					                    _.includes(err.message, constants.ALWAYS_FAILING_TRANSACTION),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,6 +1,17 @@
 | 
				
			|||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
					import { Web3Wrapper } from '@0xproject/web3-wrapper';
 | 
				
			||||||
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
import * as Web3 from 'web3';
 | 
					import * as Web3 from 'web3';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum NodeType {
 | 
				
			||||||
 | 
					    Geth = 'GETH',
 | 
				
			||||||
 | 
					    Ganache = 'GANACHE',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// These are unique identifiers contained in the response of the
 | 
				
			||||||
 | 
					// web3_clientVersion call.
 | 
				
			||||||
 | 
					const GETH_VERSION_ID = 'Geth';
 | 
				
			||||||
 | 
					const GANACHE_VERSION_ID = 'EthereumJS TestRPC';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class BlockchainLifecycle {
 | 
					export class BlockchainLifecycle {
 | 
				
			||||||
    private _web3Wrapper: Web3Wrapper;
 | 
					    private _web3Wrapper: Web3Wrapper;
 | 
				
			||||||
    private _snapshotIdsStack: number[];
 | 
					    private _snapshotIdsStack: number[];
 | 
				
			||||||
@@ -8,17 +19,47 @@ export class BlockchainLifecycle {
 | 
				
			|||||||
        this._web3Wrapper = web3Wrapper;
 | 
					        this._web3Wrapper = web3Wrapper;
 | 
				
			||||||
        this._snapshotIdsStack = [];
 | 
					        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> {
 | 
					    public async startAsync(): Promise<void> {
 | 
				
			||||||
        const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
 | 
					        const nodeType = await this._getNodeTypeAsync();
 | 
				
			||||||
        this._snapshotIdsStack.push(snapshotId);
 | 
					        switch (nodeType) {
 | 
				
			||||||
 | 
					            case NodeType.Ganache:
 | 
				
			||||||
 | 
					                const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
 | 
				
			||||||
 | 
					                this._snapshotIdsStack.push(snapshotId);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case NodeType.Geth:
 | 
				
			||||||
 | 
					                const blockNumber = await this._web3Wrapper.getBlockNumberAsync();
 | 
				
			||||||
 | 
					                this._snapshotIdsStack.push(blockNumber);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new Error(`Unknown node type: ${nodeType}`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public async revertAsync(): Promise<void> {
 | 
					    public async revertAsync(): Promise<void> {
 | 
				
			||||||
        const snapshotId = this._snapshotIdsStack.pop() as number;
 | 
					        const nodeType = await this._getNodeTypeAsync();
 | 
				
			||||||
        const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
 | 
					        switch (nodeType) {
 | 
				
			||||||
        if (!didRevert) {
 | 
					            case NodeType.Ganache:
 | 
				
			||||||
            throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
 | 
					                const snapshotId = this._snapshotIdsStack.pop() as number;
 | 
				
			||||||
 | 
					                const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
 | 
				
			||||||
 | 
					                if (!didRevert) {
 | 
				
			||||||
 | 
					                    throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case NodeType.Geth:
 | 
				
			||||||
 | 
					                const blockNumber = this._snapshotIdsStack.pop() as number;
 | 
				
			||||||
 | 
					                await this._web3Wrapper.setHeadAsync(blockNumber);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new Error(`Unknown node type: ${nodeType}`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private async _getNodeTypeAsync(): Promise<NodeType> {
 | 
				
			||||||
 | 
					        const version = await this._web3Wrapper.getNodeVersionAsync();
 | 
				
			||||||
 | 
					        if (_.includes(version, GETH_VERSION_ID)) {
 | 
				
			||||||
 | 
					            return NodeType.Geth;
 | 
				
			||||||
 | 
					        } else if (_.includes(version, GANACHE_VERSION_ID)) {
 | 
				
			||||||
 | 
					            return NodeType.Ganache;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            throw new Error(`Unknown client version: ${version}`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ export const web3Factory = {
 | 
				
			|||||||
        if (!hasAddresses) {
 | 
					        if (!hasAddresses) {
 | 
				
			||||||
            provider.addProvider(new EmptyWalletSubprovider());
 | 
					            provider.addProvider(new EmptyWalletSubprovider());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
 | 
					        // provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
 | 
				
			||||||
        const logger = {
 | 
					        const logger = {
 | 
				
			||||||
            log: (arg: any) => {
 | 
					            log: (arg: any) => {
 | 
				
			||||||
                fs.appendFileSync('ganache.log', `${arg}\n`);
 | 
					                fs.appendFileSync('ganache.log', `${arg}\n`);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								packages/devnet/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								packages/devnet/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					FROM alpine:3.7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN \
 | 
				
			||||||
 | 
					  apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
 | 
				
			||||||
 | 
					  # TODO(albrow): Change the Git URL and branch once we have all relvant PRs
 | 
				
			||||||
 | 
					  # merged to upstream.
 | 
				
			||||||
 | 
					  git clone --depth 1 --branch sethead-txpool-fix https://github.com/0xProject/go-ethereum && \
 | 
				
			||||||
 | 
					  (cd go-ethereum && make geth) && \
 | 
				
			||||||
 | 
					  cp go-ethereum/build/bin/geth /geth && \
 | 
				
			||||||
 | 
					  apk del go git make gcc musl-dev linux-headers && \
 | 
				
			||||||
 | 
					  rm -rf /go-ethereum && rm -rf /var/cache/apk/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN mkdir ~/devnet
 | 
				
			||||||
 | 
					WORKDIR ~/devnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY genesis.json .
 | 
				
			||||||
 | 
					COPY node0/ ./node0
 | 
				
			||||||
 | 
					COPY run.sh .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN /geth --datadir node0/ init genesis.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 8501
 | 
				
			||||||
 | 
					EXPOSE 30310
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRYPOINT ./run.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO(albrow): Send a single transaction to increment the block number from 0
 | 
				
			||||||
 | 
					# to 1. This seems to prevent bugs in the tests. (There's probably something
 | 
				
			||||||
 | 
					# Geth doesn't like about getting reset back to block 0).
 | 
				
			||||||
							
								
								
									
										75
									
								
								packages/devnet/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								packages/devnet/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					## 0x Devnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A private, single-node PoA Ethereum network for testing purposes only. It uses
 | 
				
			||||||
 | 
					Geth and the PoA implementation called "Clique".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The devnet requires Docker to run (the latest version is recommended).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the package root directory, run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					docker build -t 0x-devnet .
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To start the network, run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					docker run -it --rm -p 8501:8501 0x-devnet
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Depending on your OS and how you installed docker, you may need to prefix any
 | 
				
			||||||
 | 
					docker commands with `sudo`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Docker container exposes the JSON RPC API at port 8501, and this is the
 | 
				
			||||||
 | 
					primary way you are expected to interact with the devnet. The following
 | 
				
			||||||
 | 
					endpoints are supported: `personal,db,eth,net,web3,txpool,miner,debug`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can stop the network with `docker stop` and it will automatically clean up
 | 
				
			||||||
 | 
					after itself. (`docker stop` typically requires you to use `docker ps` to find
 | 
				
			||||||
 | 
					the name of the currently running container).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The devnet network only has a single node and using PoA instead of PoW. That
 | 
				
			||||||
 | 
					means that one node, called the "sealer", is the ultimate authority for
 | 
				
			||||||
 | 
					validating transactions and adding new blocks to the chain. Since there is no
 | 
				
			||||||
 | 
					PoW it also means that mining does not require significant computational
 | 
				
			||||||
 | 
					resources. You can learn more about PoA and the Geth-specific implementation
 | 
				
			||||||
 | 
					called "Clique" in [EIP-225](https://github.com/ethereum/EIPs/issues/225).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The address of the "sealer" is `0xe8816898d851d5b61b7f950627d04d794c07ca37`. The
 | 
				
			||||||
 | 
					password associated with the account is "password" and the (encrypted) private
 | 
				
			||||||
 | 
					keys are visible in the **node0/keystore** directory. This account is already
 | 
				
			||||||
 | 
					"unlocked" in the Geth node by default, so you can do things like sign and send
 | 
				
			||||||
 | 
					transactions from this account using the JSON RPC endpoints directly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are also a number of other addresses that have hard-coded starting
 | 
				
			||||||
 | 
					balances for testing purposes. You can see the details in the **genesis.json**
 | 
				
			||||||
 | 
					file. All of these accounts are also unlocked by default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Mining
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The node will automatically (nearly instantly) mine a block whenever new
 | 
				
			||||||
 | 
					transactions are added to the transaction pool. If there are no transactions in
 | 
				
			||||||
 | 
					the pool, it will wait.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To stop mining, use the
 | 
				
			||||||
 | 
					[`miner.stop`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_stop)
 | 
				
			||||||
 | 
					method.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To start mining again, you can use the
 | 
				
			||||||
 | 
					[`miner.start`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_start)
 | 
				
			||||||
 | 
					JSON RPC method.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Contributing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We strongly recommend that the community help us make improvements and determine
 | 
				
			||||||
 | 
					the future direction of the protocol. To report bugs within this package, please
 | 
				
			||||||
 | 
					create an issue in this repository.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting
 | 
				
			||||||
 | 
					started.
 | 
				
			||||||
							
								
								
									
										61
									
								
								packages/devnet/genesis.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/devnet/genesis.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "config": {
 | 
				
			||||||
 | 
					        "chainId": 50,
 | 
				
			||||||
 | 
					        "homesteadBlock": 1,
 | 
				
			||||||
 | 
					        "eip150Block": 2,
 | 
				
			||||||
 | 
					        "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					        "eip155Block": 3,
 | 
				
			||||||
 | 
					        "eip158Block": 3,
 | 
				
			||||||
 | 
					        "byzantiumBlock": 4,
 | 
				
			||||||
 | 
					        "clique": {
 | 
				
			||||||
 | 
					            "period": 0,
 | 
				
			||||||
 | 
					            "epoch": 30000
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nonce": "0x0",
 | 
				
			||||||
 | 
					    "timestamp": "0x5af1ffac",
 | 
				
			||||||
 | 
					    "extraData":
 | 
				
			||||||
 | 
					        "0x0000000000000000000000000000000000000000000000000000000000000000e8816898d851d5b61b7f950627d04d794c07ca370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					    "gasLimit": "0x47b760",
 | 
				
			||||||
 | 
					    "difficulty": "0x1",
 | 
				
			||||||
 | 
					    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					    "coinbase": "0x0000000000000000000000000000000000000000",
 | 
				
			||||||
 | 
					    "alloc": {
 | 
				
			||||||
 | 
					        "0xe8816898d851d5b61b7f950627d04d794c07ca37": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x5409ed021d9299bf6814279a6a1411a7e866a631": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x6ecbe1db9ef729cbe972c83fb886247691fb6beb": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0xe36ea790bc9d7ab70c55260c66d52b1eca985f84": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0xe834ec434daba538cd1b9fe1582052b880bd7e63": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x78dc5d2d739606d31509c31d654056a45185ecb6": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x06cef8e666768cc40cc78cf93d9611019ddcb628": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x7457d5e02197480db681d3fdf256c7aca21bdc12": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "0x91c987bf62d25945db517bdaa840a6c661374402": {
 | 
				
			||||||
 | 
					            "balance": "0x56BC75E2D63100000"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "number": "0x0",
 | 
				
			||||||
 | 
					    "gasUsed": "0x0",
 | 
				
			||||||
 | 
					    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"5409ed021d9299bf6814279a6a1411a7e866a631","crypto":{"cipher":"aes-128-ctr","ciphertext":"7c7bdd62b303eb3a42d5d8e935825ed5a05a47cb2cef71e346c61b1bd582f1aa","cipherparams":{"iv":"7fd6c9d9f9893f2c480735b5386b6d75"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"79cc86edc3a668845a68fabb3913710b7504922e47aac8513ab3d6a28d090218"},"mac":"8a593ae0d0b964e47625bc964b6d389f5687f5bde631b4913136db4ab1b8083e"},"id":"29f637ba-6a65-4401-a0d1-30e1554bd776","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"6ecbe1db9ef729cbe972c83fb886247691fb6beb","crypto":{"cipher":"aes-128-ctr","ciphertext":"ecaf4f2839d74d92e2cb87c2fc7d52862661b46e697d70acfbe43f0893db73ed","cipherparams":{"iv":"7641c3a107228f8a901c07a07ea1f70d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c67c9fb30648df6985c0490b6603382147e7dc1ea28ca8c934af4a453ec0555b"},"mac":"985dca9ce65ad400fa4c9009742be2d409f402fe05203fc1278cfd1451729e8d"},"id":"e8634edc-08e6-415e-8d65-7985c4c4a05c","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"e36ea790bc9d7ab70c55260c66d52b1eca985f84","crypto":{"cipher":"aes-128-ctr","ciphertext":"49f89d7d612049f5f3581fc7c97d32ec9c9a2ca3c11165587139f16bfb29de6b","cipherparams":{"iv":"9767e0687a097c5b57e9cb30eec9bc0a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"3e8f23332df99d519b602a0f6f4724338ba3fd9e7e313c337a92ffd1cafa19f1"},"mac":"4892051a669d45bb7de32a5eab63ee8fe52485a02218ce1806515da2adbd6584"},"id":"3488ad36-4a9d-4282-8651-7939b822429d","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"e834ec434daba538cd1b9fe1582052b880bd7e63","crypto":{"cipher":"aes-128-ctr","ciphertext":"a8ae3896739c63fc3bfe034277f6a1924a1c0ddc3f6747391dada8e61e15a928","cipherparams":{"iv":"f4f4d786cd3650a428a8bac5a6c824b1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"9acecc321bcab9b69ffdea494b8894ad0221c30f05c17d2302e315db8708ecc6"},"mac":"fc416b8f539fdc1e39e87a3bd2a69b04455875de701ced60cc8948b222171380"},"id":"0d9703e8-14fc-45d0-a425-2c40b8ae846a","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"78dc5d2d739606d31509c31d654056a45185ecb6","crypto":{"cipher":"aes-128-ctr","ciphertext":"25e90e593f08e9e3adc426c8685d90db5d1c04957e9dc8d5fab4ae30c3306b61","cipherparams":{"iv":"72ece22297a27363e795b678bcbd6be5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2201502b9d3c4e2076d9d15bfd9da3a6c75d9e2e574aabb29c3bc5a3b5ec55a5"},"mac":"13d709ed4bd2f5bf4973fc1373f8434835f0d12dc99b32c6fc14d9df7f41c62d"},"id":"3902dff4-5681-4646-b825-849f96efeec5","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"a8dda8d7f5310e4a9e24f8eba77e091ac264f872","crypto":{"cipher":"aes-128-ctr","ciphertext":"0d67c13cf0b130e8ffa1aaca5df372f727164e633f8e0e28a3e54d0884ffb568","cipherparams":{"iv":"619cd539cda9f40abb45bba00b5fe53d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"4effcd9b6fe71ee31cfe9057290154329b9af3acb6dcc46be7f78b5b9dcd3f42"},"mac":"c6eecd25944f4250b7b875d76bfbb60cc4e8db1d081621d1a2ddb72ea4e52a6d"},"id":"556bd3f1-1e5b-47a4-9b6e-448b9989d7d3","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"06cef8e666768cc40cc78cf93d9611019ddcb628","crypto":{"cipher":"aes-128-ctr","ciphertext":"38c9ca150932dc8c5ec5c65796425b2de98295cae64db08b816da2c06fc52c20","cipherparams":{"iv":"512127e8e606c481612473e7bc4d38f1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"16c4cabfd13cae2df66d8ff9acc7f503c95c808b00d0bb6a12932203889c679b"},"mac":"52297b496e8751627dea1ee17bf5cbea1926f90bcde3ffc8baa089184672f875"},"id":"31102097-86e4-4e19-ad73-03c3de67bf3b","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d","crypto":{"cipher":"aes-128-ctr","ciphertext":"ca7aedbacc960fc0fcb418606d7bdf042c36cc2808a5c94ac222cc0b44a9970d","cipherparams":{"iv":"3b1fe5da1cf5d6cd2ceaaf24c008c897"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a94e4d41d77ff6dc54beda30c7a46d8f3cc312ebeffa0352d679f7e3fc5301dc"},"mac":"9a82bf60103d05878f8af3c07765c22cba3df9b1c4376eaf859e47b805666e42"},"id":"ab68c67b-e15a-4ade-b3d9-2180a32b28fe","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"7457d5e02197480db681d3fdf256c7aca21bdc12","crypto":{"cipher":"aes-128-ctr","ciphertext":"720dcc2889c7b3636f9f659650181b0d46d82420460e23454277273f528baaee","cipherparams":{"iv":"1510028e2b9988d1a73b71cbb692d085"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5db2b62f4d1f55a3f24c014c4f23f3ec9a2992dca6c2a89c24a566f99a079396"},"mac":"22c6fb134fd0a748195ea83e9ccb490ab2c9a3e8761f9d74ea6d02abbdeb8a43"},"id":"704c31f8-8ca2-4b49-9fdc-5923f5712dad","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"91c987bf62d25945db517bdaa840a6c661374402","crypto":{"cipher":"aes-128-ctr","ciphertext":"8f461f3c74643f382f7fc1f71719d5a89ed8cf75854d8a1b53e133997b53a386","cipherparams":{"iv":"cf595fb7680d36b4f5a01599ee54d2d1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"73a9e599369d2bfaedd044559415147240c3517f6cd1dec8f77a98993d1ceaf8"},"mac":"c8be4dc59ad28d40f7b549a6b72834d149c84d67dc35e687676bbee0e07be395"},"id":"21cca6fb-7876-4e39-a986-a0a37f90da6d","version":3}
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"address":"e8816898d851d5b61b7f950627d04d794c07ca37","crypto":{"cipher":"aes-128-ctr","ciphertext":"1ff4add6955cba7ddaf29f66d7d21c5e1d714ef6191fbc651ae60f2ea3c95e8f","cipherparams":{"iv":"3ff869fbdbe1a523cdb327780365976e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"7372dbae5fb318f8684902e099c311d4188721d677974d729711762c7ef6030c"},"mac":"485fa5dc701067782baa1589716a53110c7f917eb259e35ebca7265bbb7150b1"},"id":"89edb004-5b00-4607-a3af-a0d9ab9b1c34","version":3}
 | 
				
			||||||
							
								
								
									
										11
									
								
								packages/devnet/node0/password.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								packages/devnet/node0/password.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
 | 
					password
 | 
				
			||||||
							
								
								
									
										23
									
								
								packages/devnet/run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										23
									
								
								packages/devnet/run.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create log directory for Geth
 | 
				
			||||||
 | 
					mkdir -p /var/log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Start Geth in background and redirect output to log file
 | 
				
			||||||
 | 
					/geth --datadir node0/ --syncmode 'full' --nat none --nodiscover --port 30310 --txpool.journal '' \
 | 
				
			||||||
 | 
					    --rpc --rpcaddr '0.0.0.0' --rpcport 8501 --rpcapi 'personal,db,eth,net,web3,txpool,miner,debug' \
 | 
				
			||||||
 | 
					    --networkid 50 --gasprice '2000000000' --targetgaslimit '0x47b760' --mine --etherbase '0xe8816898d851d5b61b7f950627d04d794c07ca37' \
 | 
				
			||||||
 | 
					    --unlock '0xe8816898d851d5b61b7f950627d04d794c07ca37,0x5409ed021d9299bf6814279a6a1411a7e866a631,0x6ecbe1db9ef729cbe972c83fb886247691fb6beb,0xe36ea790bc9d7ab70c55260c66d52b1eca985f84,0xe834ec434daba538cd1b9fe1582052b880bd7e63,0x78dc5d2d739606d31509c31d654056a45185ecb6,0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872,0x06cef8e666768cc40cc78cf93d9611019ddcb628,0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d,0x7457d5e02197480db681d3fdf256c7aca21bdc12,0x91c987bf62d25945db517bdaa840a6c661374402' \
 | 
				
			||||||
 | 
					    --password=node0/password.txt \
 | 
				
			||||||
 | 
					    > /var/log/geth &
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Wait for Geth to unlock the first account
 | 
				
			||||||
 | 
					sleep 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Send a single transaction. We have to do this so that debug.setHead works
 | 
				
			||||||
 | 
					# correctly. (Geth does not seem to like debug.setHead(0), so by sending this
 | 
				
			||||||
 | 
					# transaction we increase the current block number to 1).
 | 
				
			||||||
 | 
					/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0xe8816898d851d5b61b7f950627d04d794c07ca37", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Use tail to re-attach to the log file and actually see the output.
 | 
				
			||||||
 | 
					tail -f /var/log/geth
 | 
				
			||||||
@@ -281,7 +281,6 @@ export class Web3Wrapper {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        const payload = {
 | 
					        const payload = {
 | 
				
			||||||
            jsonrpc: '2.0',
 | 
					            jsonrpc: '2.0',
 | 
				
			||||||
            id: this._jsonRpcRequestId++,
 | 
					 | 
				
			||||||
            method: 'eth_getLogs',
 | 
					            method: 'eth_getLogs',
 | 
				
			||||||
            params: [serializedFilter],
 | 
					            params: [serializedFilter],
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@@ -403,8 +402,44 @@ export class Web3Wrapper {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return receipt;
 | 
					        return receipt;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Start the CPU mining process with the given number of threads and
 | 
				
			||||||
 | 
					     * generate a new DAG if need be.
 | 
				
			||||||
 | 
					     * @param   threads The number of threads to mine on.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public async minerStartAsync(threads: number = 1): Promise<void> {
 | 
				
			||||||
 | 
					        await this._sendRawPayloadAsync<boolean>({
 | 
				
			||||||
 | 
					            method: 'miner_start',
 | 
				
			||||||
 | 
					            params: [threads],
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Stop the CPU mining process.
 | 
				
			||||||
 | 
					     * @param   threads The number of threads to mine on.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public async minerStopAsync(): Promise<void> {
 | 
				
			||||||
 | 
					        await this._sendRawPayloadAsync<boolean>({ method: 'miner_stop', params: [] });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns true if client is actively mining new blocks.
 | 
				
			||||||
 | 
					     * @returns A boolean indicating whether the node is currently mining.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public async isMiningAsync(): Promise<boolean> {
 | 
				
			||||||
 | 
					        const isMining = await promisify<boolean>(this._web3.eth.getMining)();
 | 
				
			||||||
 | 
					        return isMining;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets the current head of the local chain by block number. Note, this is a
 | 
				
			||||||
 | 
					     * destructive action and may severely damage your chain. Use with extreme
 | 
				
			||||||
 | 
					     * caution.
 | 
				
			||||||
 | 
					     * @param  blockNumber The block number to reset to.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public async setHeadAsync(blockNumber: number): Promise<void> {
 | 
				
			||||||
 | 
					        await this._sendRawPayloadAsync<void>({ method: 'debug_setHead', params: [this._web3.toHex(blockNumber)] });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    private async _sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> {
 | 
					    private async _sendRawPayloadAsync<A>(payload: Partial<JSONRPCRequestPayload>): Promise<A> {
 | 
				
			||||||
        const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
 | 
					        const sendAsync = this._web3.currentProvider.sendAsync.bind(this._web3.currentProvider);
 | 
				
			||||||
 | 
					        payload.id = this._jsonRpcRequestId++;
 | 
				
			||||||
        const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payload);
 | 
					        const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payload);
 | 
				
			||||||
        const result = response.result;
 | 
					        const result = response.result;
 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ import * as chai from 'chai';
 | 
				
			|||||||
import * as Ganache from 'ganache-core';
 | 
					import * as Ganache from 'ganache-core';
 | 
				
			||||||
import 'make-promises-safe';
 | 
					import 'make-promises-safe';
 | 
				
			||||||
import 'mocha';
 | 
					import 'mocha';
 | 
				
			||||||
 | 
					import * as Web3 from 'web3';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Web3Wrapper } from '../src';
 | 
					import { Web3Wrapper } from '../src';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,4 +38,22 @@ describe('Web3Wrapper tests', () => {
 | 
				
			|||||||
            expect(networkId).to.be.equal(NETWORK_ID);
 | 
					            expect(networkId).to.be.equal(NETWORK_ID);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    describe('mining functions', () => {
 | 
				
			||||||
 | 
					        it('starts and stops the miner', async () => {
 | 
				
			||||||
 | 
					            // Note: depending on our provider, the miner may or may not already
 | 
				
			||||||
 | 
					            // be mining. To account for both conditions, we have what might
 | 
				
			||||||
 | 
					            // look like too many stops and starts here, but it is necessary.
 | 
				
			||||||
 | 
					            await web3Wrapper.minerStopAsync();
 | 
				
			||||||
 | 
					            let isMining = await web3Wrapper.isMiningAsync();
 | 
				
			||||||
 | 
					            expect(isMining).to.be.false();
 | 
				
			||||||
 | 
					            await web3Wrapper.minerStartAsync(1);
 | 
				
			||||||
 | 
					            isMining = await web3Wrapper.isMiningAsync();
 | 
				
			||||||
 | 
					            expect(isMining).to.be.true();
 | 
				
			||||||
 | 
					            isMining = await web3Wrapper.isMiningAsync();
 | 
				
			||||||
 | 
					            expect(isMining).to.be.true();
 | 
				
			||||||
 | 
					            await web3Wrapper.minerStopAsync();
 | 
				
			||||||
 | 
					            isMining = await web3Wrapper.isMiningAsync();
 | 
				
			||||||
 | 
					            expect(isMining).to.be.false();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user