Skip to content

Commit 9d5f7bb

Browse files
committed
General cleanup of buidler-ganache
1 parent e92e59a commit 9d5f7bb

File tree

12 files changed

+173
-196
lines changed

12 files changed

+173
-196
lines changed

Diff for: packages/buidler-ganache/.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

Diff for: packages/buidler-ganache/README.md

+25-32
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,56 @@
11
[![npm](https://img.shields.io/npm/v/@nomiclabs/buidler-ethers.svg)](https://www.npmjs.com/package/@nomiclabs/buidler-ethers)
22

33
# buidler-ganache
4-
[Buidler](http://getbuidler.com) plugin to launch [ganache-core](https://github.com/trufflesuite/ganache-core) before running tests or run tasks.
4+
5+
This Buidler plugin automatically starts and stop [Ganache](https://github.com/trufflesuite/ganache-core) when running
6+
tests or scripts.
57

68
## What
7-
This plugin hooks into the `TASK_TEST`/`TASK_RUN` pipeline to start ganache-cli before anything and stop it afterwards.
9+
10+
This plugin creates an especial network named `ganache`. When this network is used, a Ganache server will be
11+
automatically started before running tests and scripts, and stopped when finished.
812

913
## Installation
14+
1015
```bash
11-
npm install @nomiclabs/buidler-ganache ganache-cli
16+
npm install @nomiclabs/buidler-ganache
1217
```
1318

1419
And add the following statement to your `buidler.config.js`:
20+
1521
```js
1622
usePlugin("@nomiclabs/buidler-ganache");
1723
```
1824

1925
## Tasks
26+
2027
This plugin creates no additional tasks.
2128

2229
## Environment extensions
23-
This plugin adds all ganache running configs (defaults and set by the config file) to the BRE.
24-
The default ganache options exposed are:
25-
```js
26-
defaultOptions = {
27-
url: "http://127.0.0.1:8545",
28-
gasPrice: 20000000000,
29-
gasLimit: 6721975,
30-
defaultBalanceEther: 100,
31-
totalAccounts: 10,
32-
hardfork: "petersburg",
33-
allowUnlimitedContractSize: false,
34-
locked: false,
35-
hdPath: "m/44'/60'/0'/0/",
36-
keepAliveTimeout: 5000
37-
}
38-
```
3930

31+
This plugin doesn't extend the Buidler Runtime Environment.
4032

4133
## Usage
34+
4235
There are no additional steps you need to take for this plugin to work.
4336

4437
## Configuration
45-
Any configuration is optional. But here it's an example that you can ass to your `buidler.config.js` file.
38+
39+
You can set any of the [Ganache's options](https://github.com/trufflesuite/ganache-core#options) through the `ganache`
40+
network config. All of them are supported, with the exception of `accounts`.
41+
42+
This example sets a larger block gas limit and the default balance of Ganache's accounts.
43+
4644
```js
4745
module.exports = {
48-
defaultNetwork: "ganache",
49-
networks: {
50-
ganache: {
51-
url: "http://127.0.0.1:8555",
52-
gasPrice: 20000000000,
53-
gasLimit: 6000000000,
54-
defaultBalanceEther: 10,
55-
totalAccounts: 3,
56-
mnemonic: "polar velvet stereo oval echo senior cause cruel tube hobby exact angry",
57-
},
46+
defaultNetwork: "ganache",
47+
networks: {
48+
ganache: {
49+
gasLimit: 6000000000,
50+
defaultBalanceEther: 10
5851
}
52+
}
5953
};
6054
```
61-
Here the list of all available options and constrains: [ganache-core options](https://github.com/trufflesuite/ganache-core#options).
62-
###
55+
6356
Note: The `accounts` option it's not currently supported.

Diff for: packages/buidler-ganache/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@nomiclabs/buidler-ganache",
3-
"version": "1.0.0-beta.9",
4-
"description": "Buidler plugin for managing ganache",
3+
"version": "1.0.0-beta.13",
4+
"description": "Buidler plugin for managing Ganache",
55
"homepage": "https://github.com/nomiclabs/buidler/tree/master/packages/buidler-ganache",
66
"repository": "github:nomiclabs/buidler",
77
"author": "Nomic Labs SRL",
@@ -39,13 +39,13 @@
3939
"ts-interface-checker": "^0.1.9"
4040
},
4141
"devDependencies": {
42-
"@nomiclabs/buidler": "^1.0.0-beta.9",
42+
"@nomiclabs/buidler": "^1.0.0-beta.13",
4343
"@types/debug": "^4.1.4",
4444
"@types/fs-extra": "^5.1.0",
4545
"chai": "^4.2.0",
4646
"ts-interface-builder": "^0.2.0"
4747
},
4848
"peerDependencies": {
49-
"@nomiclabs/buidler": "^1.0.0-beta.9"
49+
"@nomiclabs/buidler": "^1.0.0-beta.13"
5050
}
5151
}

Diff for: packages/buidler-ganache/src/ganache-service.ts

+107-56
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,51 @@
1+
import { BuidlerPluginError } from "@nomiclabs/buidler/internal/core/errors";
12
import debug from "debug";
23
import { URL } from "url";
34

45
const log = debug("buidler:plugin:ganache-service");
5-
log.color = "6";
6+
7+
declare interface GanacheOptions {
8+
url: string;
9+
keepAliveTimeout?: number;
10+
accountKeysPath?: string; // Translates to: account_keys_path
11+
accounts?: object[];
12+
allowUnlimitedContractSize?: boolean;
13+
blockTime?: number;
14+
dbPath?: string; // Translates to: db_path
15+
debug?: boolean;
16+
defaultBalanceEther?: number; // Translates to: default_balance_ether
17+
fork?: string | object;
18+
forkBlockNumber?: string | number; // Translates to: fork_block_number
19+
gasLimit?: number;
20+
gasPrice?: string | number;
21+
hardfork?: "byzantium" | "constantinople" | "petersburg";
22+
hdPath?: string; // Translates to: hd_path
23+
hostname?: string;
24+
locked?: boolean;
25+
logger?: {
26+
log(msg: string): void;
27+
};
28+
mnemonic?: string;
29+
networkId?: number;
30+
port?: number;
31+
seed?: any;
32+
time?: any; // Date
33+
totalAccounts?: number; // Translates to: total_accounts
34+
unlockedAccounts?: string[]; // Translates to: unlocked_accounts
35+
verbose?: boolean;
36+
vmErrorsOnRPCResponse?: boolean;
37+
ws?: boolean;
38+
}
39+
40+
const DEFAULT_PORT = 7545;
641

742
export class GanacheService {
8-
public static error: Error;
43+
public static error?: Error;
944
public static optionValidator: any;
1045

1146
public static getDefaultOptions(): GanacheOptions {
1247
return {
13-
url: "http://127.0.0.1:8545",
48+
url: `http://127.0.0.1:${DEFAULT_PORT}`,
1449
gasPrice: 20000000000,
1550
gasLimit: 6721975,
1651
defaultBalanceEther: 100,
@@ -54,13 +89,20 @@ export class GanacheService {
5489
} catch (e) {
5590
// Verify the expected error or throw it again
5691
if (e.name === "TypeError") {
57-
e.message = "One or more invalid values in ganache network options";
58-
if (!GanacheService.error) {
59-
log(e.message || e);
60-
GanacheService.error = e;
92+
if (GanacheService.error === undefined) {
93+
const error = new BuidlerPluginError(
94+
`Ganache plugin config is invalid: ${e.message}`,
95+
e
96+
);
97+
98+
log("Failed to initialize GanacheService\n", error);
99+
GanacheService.error = error;
61100
}
62101
} else {
63-
throw e;
102+
throw new BuidlerPluginError(
103+
`Failed to initialize GanacheService: ${e.message}`,
104+
e
105+
);
64106
}
65107
}
66108
}
@@ -78,15 +120,31 @@ export class GanacheService {
78120

79121
// Start server with current configs (port and hostname)
80122
await new Promise((resolve, reject) => {
81-
this._server.once("listening", resolve);
82-
this._server.once("error", reject);
123+
let onError: (err: Error) => void;
124+
125+
const onListening = () => {
126+
this._server.removeListener("error", onError);
127+
resolve();
128+
};
129+
130+
onError = err => {
131+
this._server.removeListener("listening", onListening);
132+
reject(err);
133+
};
134+
135+
this._server.once("listening", onListening);
136+
this._server.once("error", onError);
83137
this._server.listen(port, hostname);
84138
});
85139
} catch (e) {
86-
e.message = `Start Server > ${e.message}`;
87-
if (!GanacheService.error) {
88-
log(e.message || e);
89-
GanacheService.error = e;
140+
const error = new BuidlerPluginError(
141+
`Failed to start GanacheService: ${e.message}`,
142+
e
143+
);
144+
145+
if (GanacheService.error === undefined) {
146+
log("Failed to start GanacheService\n", error);
147+
GanacheService.error = error;
90148
}
91149
}
92150

@@ -104,22 +162,25 @@ export class GanacheService {
104162
// Stop server and Wait for it
105163
await new Promise((resolve, reject) => {
106164
this._server.close((err: Error) => {
107-
if (err) {
165+
if (err !== undefined && err !== null) {
108166
reject(err);
109167
} else {
110168
resolve();
111169
}
112170
});
113171
});
114172
} catch (e) {
115-
e.message = `Stop Server > ${e.message}`;
116-
if (!GanacheService.error) {
117-
log(e.message || e);
118-
GanacheService.error = e;
173+
const error = new BuidlerPluginError(
174+
`Failed to stop GanacheService: ${e.message}`,
175+
e
176+
);
177+
178+
if (GanacheService.error === undefined) {
179+
log("Failed to stop GanacheService\n", error);
180+
GanacheService.error = error;
119181
}
120182
}
121183

122-
// Verify service state before continue (TODO Maybe extract this to a decorator)
123184
this._checkForServiceErrors();
124185
}
125186

@@ -129,25 +190,33 @@ export class GanacheService {
129190
// Validate and parse hostname and port from URL (this validation is priority)
130191
const url = new URL(options.url);
131192
if (url.hostname !== "locahost" && url.hostname !== "127.0.0.1") {
132-
throw new Error("Config: ganache.hostname must resolve to locahost");
193+
throw new BuidlerPluginError("Ganache network only works with locahost");
133194
}
134195

135196
// Validate all options agains validator
136197
try {
137198
GanacheService.optionValidator.check(options);
138199
} catch (e) {
139-
e.message = e.message.replace("value.", "Config: ganache.");
140-
throw e;
200+
throw new BuidlerPluginError(
201+
`Ganache network config is invalid: ${e.message}`,
202+
e
203+
);
141204
}
142205

143206
// Test for unsupported commands
144207
if (options.accounts !== undefined) {
145-
throw new Error("Config: ganache.accounts unsupported for this network");
208+
throw new BuidlerPluginError(
209+
"Config: ganache.accounts unsupported for this network"
210+
);
146211
}
147212

148213
// Transform needed options to Ganache core server (not using SnakeCase lib for performance)
149214
validatedOptions.hostname = url.hostname;
150-
validatedOptions.port = Number(url.port) || 80;
215+
216+
validatedOptions.port =
217+
url.port !== undefined && url.port !== ""
218+
? parseInt(url.port, 10)
219+
: DEFAULT_PORT;
151220

152221
const optionsToInclude = [
153222
"accountsKeyPath",
@@ -157,7 +226,7 @@ export class GanacheService {
157226
"unlockedAccounts"
158227
];
159228
for (const [key, value] of Object.entries(options)) {
160-
if (value && optionsToInclude.includes(key)) {
229+
if (value !== undefined && optionsToInclude.includes(key)) {
161230
validatedOptions[this._snakeCase(key)] = value;
162231
delete validatedOptions[key];
163232
}
@@ -171,45 +240,27 @@ export class GanacheService {
171240

172241
// Add listener for general server errors
173242
server.on("error", function(err: any) {
174-
if (!GanacheService.error && err) {
175-
log(err.message || err);
243+
if (
244+
GanacheService.error === undefined &&
245+
err !== undefined &&
246+
err !== null
247+
) {
248+
log("An error occurred in GanacheService\n", err);
176249
GanacheService.error = err;
177250
}
178251
});
179-
180-
// Add listener for process uncaught errors (warning: this may catch non plugin related errors)
181-
// process.on("uncaughtException", function(e) {
182-
// log("Uncaught Exception", e.message);
183-
// server.close(function(err: any) {
184-
// if (!GanacheService.error && err) {
185-
// log(err.message || err.stack || err);
186-
// GanacheService.error = err;
187-
// }
188-
// });
189-
// });
190-
191-
// Add listener for standard POSIX signal SIGINT (usually generated with <Ctrl>+C)
192-
// process.on("SIGINT", function() {
193-
// log("SIGINT detected");
194-
// server.close(function(err: any) {
195-
// if (!GanacheService.error && err) {
196-
// log(err.message || err.stack || err);
197-
// GanacheService.error = err;
198-
// }
199-
// });
200-
// });
201-
202-
// TODO Maybe in the future, in new threat, some kind of ping checker to the server (every 30 seg)
203252
}
204253

205254
private _checkForServiceErrors() {
206-
if (GanacheService.error) {
207-
// Close server (if needed)
208-
if (this._server) {
255+
if (GanacheService.error !== undefined) {
256+
if (this._server !== undefined) {
209257
this._server.close();
210258
}
211259

212-
throw new Error(GanacheService.error.message);
260+
throw new BuidlerPluginError(
261+
`An error occurred in GanacheService: ${GanacheService.error.message}`,
262+
GanacheService.error
263+
);
213264
}
214265
}
215266

0 commit comments

Comments
 (0)