├── .dockerignore ├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── .npmignore ├── Dockerfile ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── args.js ├── cli.js ├── lib.js ├── package-lock.json ├── package.json ├── resources └── icons │ ├── ganache-cli-128x128.png │ └── ganache-cli.svg ├── scripts └── generate-otp.js └── webpack ├── plugins.js ├── webpack.docker.config.js └── webpack.node.config.js /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: ganache-cli CD 2 | 3 | on: 4 | push: 5 | branches: [ master, beta, alpha ] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-18.04 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: '10' 15 | 16 | - name: Apply workaround for git:// packages 17 | run: git config --global url.https://github.com/.insteadOf ssh://git@github.com/ 18 | 19 | - name: Install 20 | run: npm ci 21 | 22 | - name: Build 23 | run: npm run build 24 | 25 | - name: Release 26 | env: 27 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 28 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | NPM_OTP_KEY: ${{ secrets.NPM_OTP_KEY }} 30 | run: npm run otp && npx semantic-release 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | TODO 3 | *.log 4 | .eslintrc.js 5 | .tern-project 6 | .DS_Store 7 | .tern-port 8 | .vscode 9 | build 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | .tern-project 3 | .tern-port 4 | .vscode 5 | .eslintrc.js 6 | *.log 7 | build/ganache-core.docker.cli.js 8 | build/ganache-core.docker.cli.js.map 9 | webpack 10 | .dockerignore 11 | Dockerfile 12 | ISSUE_TEMPLATE.md 13 | lib.js 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mhart/alpine-node:14 as builder 2 | 3 | RUN apk add --no-cache make gcc g++ python git bash 4 | COPY package.json /app/package.json 5 | COPY package-lock.json /app/package-lock.json 6 | WORKDIR /app 7 | RUN git config --global url.https://github.com/.insteadOf ssh://git@github.com/ 8 | RUN npm ci 9 | COPY . . 10 | RUN npx webpack-cli --config ./webpack/webpack.docker.config.js 11 | 12 | FROM mhart/alpine-node:14 as runtime 13 | 14 | WORKDIR /app 15 | 16 | COPY --from=builder "/app/build/ganache-core.docker.cli.js" "./ganache-core.docker.cli.js" 17 | COPY --from=builder "/app/build/ganache-core.docker.cli.js.map" "./ganache-core.docker.cli.js.map" 18 | 19 | ENV DOCKER true 20 | 21 | EXPOSE 8545 22 | 23 | ENTRYPOINT ["node", "/app/ganache-core.docker.cli.js"] 24 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 12 | 13 | * I asked about this on [gitter](https://gitter.im/ConsenSys/truffle): [ ] 14 | * Link to my question on gitter: 15 | 16 | 25 | 26 | 27 | ## Expected Behavior 28 | 29 | 36 | 37 | ## Current Behavior 38 | 39 | 47 | 48 | ## Possible Solution 49 | 50 | 59 | 60 | ## Steps to Reproduce (for bugs) 61 | 62 | 75 | 1. 76 | 2. 77 | 3. 78 | 4. 79 | 80 | ## Context 81 | 91 | 92 | ## Your Environment 93 | * Version used: 94 | * Version of Truffle/Remix/Other tools used: 95 | * NodeJS Version: [ ] 6.x, [ ] 7.x (unsupported), [ ] 8.x, [ ] 9.x 96 | * Operating System and version (include distro if Linux): 97 | * Link to your project or repro gist: 98 | * Commit hash to use with above link for reproduction: 99 | * I intend to submit a pull request to fix this issue: [ ] 100 | 101 | 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Iuri Matias 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | NOTICE: ganache-cli has moved to ganache 3 |

4 | 5 |
6 | 7 | [![npm](https://img.shields.io/npm/v/ganache-cli.svg)]() 8 | [![npm](https://img.shields.io/npm/dm/ganache-cli.svg)]() 9 | [![Build Status](https://travis-ci.org/trufflesuite/ganache-cli.svg?branch=master)](https://travis-ci.org/trufflesuite/ganache-cli) 10 | 11 |

12 | 13 |

14 | 15 | ## Welcome to Ganache CLI 16 | Ganache CLI, part of the Truffle suite of Ethereum development tools, is the command line version of [Ganache](https://github.com/trufflesuite/ganache), your personal blockchain for Ethereum development. 17 | 18 | Ganache CLI uses ethereumjs to simulate full client behavior and make developing Ethereum applications faster, easier, and safer. It also includes all popular RPC functions and features (like events) and can be run deterministically to make development a breeze. 19 | 20 | ### Looking for TestRPC? 21 | 22 | If you came here expecting to find the TestRPC, you're in the right place! Truffle has taken the TestRPC under its wing and made it part of the Truffle suite of tools. From now on you can expect better support along with tons of new features that help make Ethereum development safer, easier, and more enjoyable. Use `ganache-cli` just as you would `testrpc`. 23 | 24 | ## Installation 25 | 26 | `ganache-cli` is written in JavaScript and distributed as a Node.js package via `npm`. Make sure you have Node.js (>= v8) installed. 27 | 28 | Using npm: 29 | 30 | ```Bash 31 | npm install -g ganache-cli 32 | ``` 33 | 34 | or, if you are using [Yarn](https://yarnpkg.com/): 35 | 36 | ```Bash 37 | yarn global add ganache-cli 38 | ``` 39 | 40 | `ganache-cli` utilizes [`ganache-core`](https://github.com/trufflesuite/ganache-core) internally, which is distributed with optional native dependencies for increased performance. If these native dependencies fail to install on your system `ganache-cli` will automatically fallback to `ganache-core`’s pre-bundled JavaScript build. 41 | 42 | Having problems? Be sure to check out the [FAQ](https://github.com/trufflesuite/ganache-cli/wiki/FAQ) and if you're still having issues and you're sure its a problem with `ganache-cli` please open an issue. 43 | 44 | ### Using Ganache CLI 45 | 46 | #### Command Line 47 | 48 | ```Bash 49 | $ ganache-cli 50 | ``` 51 | 52 | ## Options: 53 | 54 | * `-a` or `--accounts`: Specify the number of accounts to generate at startup. 55 | * `-e` or `--defaultBalanceEther`: Amount of ether to assign each test account. Default is 100. 56 | * `-b` or `--blockTime`: Specify blockTime in seconds for automatic mining. If you don't specify this flag, ganache will instantly mine a new block for every transaction. Using the --blockTime flag is discouraged unless you have tests which require a specific mining interval. 57 | * `-d` or `--deterministic`: Generate deterministic addresses based on a pre-defined mnemonic. 58 | * `-n` or `--secure`: Lock available accounts by default (good for third party transaction signing) 59 | * `-m` or `--mnemonic`: Use a bip39 mnemonic phrase for generating a PRNG seed, which is in turn used for hierarchical deterministic (HD) account generation. 60 | * `-p` or `--port`: Port number to listen on. Defaults to 8545. 61 | * `-h` or `--host` or `--hostname`: Hostname to listen on. Defaults to 127.0.0.1 (defaults to 0.0.0.0 for Docker instances of ganache-cli). 62 | * `-s` or `--seed`: Use arbitrary data to generate the HD wallet mnemonic to be used. 63 | * `-g` or `--gasPrice`: The price of gas in wei (defaults to 20000000000) 64 | * `-l` or `--gasLimit`: The block gas limit (defaults to 0x6691b7) 65 | * `--callGasLimit`: Sets the transaction gas limit for `eth_call` and `eth_estimateGas` calls. Must be specified as a `hex` string. Defaults to `"0x1fffffffffffff"` (`Number.MAX_SAFE_INTEGER`) 66 | * `-k` or `--hardfork`: Allows users to specify which hardfork should be used. Supported hardforks are `byzantium`, `constantinople`, `petersburg`, `istanbul`, and `muirGlacier` (default). 67 | * `-f` or `--fork`: Fork from another currently running Ethereum client at a given block. Input should be the HTTP location and port of the other client, e.g. `http://localhost:8545`. You can optionally specify the block to fork from using an `@` sign: `http://localhost:8545@1599200`. 68 | * `forkCacheSize`: `number` - The maximum size, in bytes, of the in-memory cache for queries on a chain fork. Defaults to `1_073_741_824` bytes (1 gigabyte). You can set this to `0` to disable caching (not recommended), or to `-1` for unlimited (will be limited by your node process). 69 | * `-i` or `--networkId`: Specify the network id ganache-cli will use to identify itself (defaults to the current time or the network id of the forked blockchain if configured) 70 | * `--chainId`: Specify the Chain ID ganache-cli will use for `eth_chainId` RPC and the `CHAINID` opcode. For legacy reasons, the default is currently `1337` for `eth_chainId` RPC and `1` for the `CHAINID` opcode. Setting this flag will align the chainId values. This will be fixed in the next major version of ganache-cli and ganache-core! 71 | * `--db`: Specify a path to a directory to save the chain database. If a database already exists, ganache-cli will initialize that chain instead of creating a new one. 72 | * `--debug`: Output VM opcodes for debugging 73 | * `--mem`: Output ganache-cli memory usage statistics. This replaces normal output. 74 | * `-q` or `--quiet`: Run ganache-cli without any logs. 75 | * `-v` or `--verbose`: Log all requests and responses to stdout 76 | * `-?` or `--help`: Display help information 77 | * `--version`: Display the version of ganache-cli 78 | * `--account_keys_path` or `--acctKeys`: Specifies a file to save accounts and private keys to, for testing. 79 | * `--noVMErrorsOnRPCResponse`: Do not transmit transaction failures as RPC errors. Enable this flag for error reporting behaviour which is compatible with other clients such as geth and Parity. 80 | * `--allowUnlimitedContractSize`: Allows unlimited contract sizes while debugging. By enabling this flag, the check within the EVM for contract size limit of 24KB (see EIP-170) is bypassed. Enabling this flag **will** cause ganache-cli to behave differently than production environments. 81 | * `--keepAliveTimeout`: Sets the HTTP server's `keepAliveTimeout` in milliseconds. See the [NodeJS HTTP docs](https://nodejs.org/api/http.html#http_server_keepalivetimeout) for details. `5000` by default. 82 | * `-t` or `--time`: Date (ISO 8601) that the first block should start. Use this feature, along with the evm_increaseTime method to test time-dependent code. 83 | 84 | Special Options: 85 | 86 | * `--account`: Specify `--account=...` (no 's') any number of times passing arbitrary private keys and their associated balances to generate initial addresses: 87 | 88 | ``` 89 | $ ganache-cli --account=",balance" [--account=",balance"] 90 | ``` 91 | 92 | Note that private keys are 64 characters long, and must be input as a 0x-prefixed hex string. Balance can either be input as an integer or 0x-prefixed hex value specifying the amount of wei in that account. 93 | 94 | An HD wallet will not be created for you when using `--account`. 95 | 96 | * `-u` or `--unlock`: Specify `--unlock ...` any number of times passing either an address or an account index to unlock specific accounts. When used in conjunction with `--secure`, `--unlock` will override the locked state of specified accounts. 97 | 98 | ``` 99 | $ ganache-cli --secure --unlock "0x1234..." --unlock "0xabcd..." 100 | ``` 101 | 102 | You can also specify a number, unlocking accounts by their index: 103 | 104 | ``` 105 | $ ganache-cli --secure -u 0 -u 1 106 | ``` 107 | 108 | This feature can also be used to impersonate accounts and unlock addresses you wouldn't otherwise have access to. When used with the `--fork` feature, you can use ganache-cli to make transactions as any address on the blockchain, which is very useful for testing and dynamic analysis. 109 | 110 | ## Usage 111 | 112 | As a [Web3](https://github.com/ethereum/web3.js/) provider: 113 | 114 | ```javascript 115 | const ganache = require("ganache-core"); 116 | const web3 = new Web3(ganache.provider()); 117 | ``` 118 | If web3 is already initialized: 119 | ```javascript 120 | const ganache = require("ganache-core"); 121 | web3.setProvider(ganache.provider()); 122 | ``` 123 | NOTE: depending on your web3 version, you may need to set a number of confirmation blocks 124 | ```javascript 125 | const web3 = new Web3(provider, null, { transactionConfirmationBlocks: 1 }); 126 | ``` 127 | 128 | As an [ethers.js](https://github.com/ethers-io/ethers.js/) provider: 129 | 130 | ```javascript 131 | const ganache = require("ganache-cli"); 132 | const provider = new ethers.providers.Web3Provider(ganache.provider()); 133 | ``` 134 | 135 | As a general HTTP and WebSocket server: 136 | 137 | ```javascript 138 | const ganache = require("ganache-cli"); 139 | const server = ganache.server(); 140 | server.listen(port, function(err, blockchain) {...}); 141 | ``` 142 | 143 | ## Options 144 | 145 | Both `.provider()` and `.server()` take a single object which allows you to specify behavior of ganache-cli. This parameter is optional. Available options are: 146 | 147 | * `"accounts"`: `Array` of `Object`'s. Each object should have a `balance` key with a hexadecimal value. The key `secretKey` can also be specified, which represents the account's private key. If no `secretKey`, the address is auto-generated with the given balance. If specified, the key is used to determine the account's address. 148 | * `"debug"`: `boolean` - Output VM opcodes for debugging 149 | * `"blockTime"`: `number` - Specify blockTime in seconds for automatic mining. If you don't specify this flag, ganache will instantly mine a new block for every transaction. Using the `blockTime` option is discouraged unless you have tests which require a specific mining interval. 150 | * `"logger"`: `Object` - Object, like `console`, that implements a `log()` function. 151 | * `"mnemonic"`: Use a specific HD wallet mnemonic to generate initial addresses. 152 | * `"port"`: `number` Port number to listen on when running as a server. 153 | * `"seed"`: Use arbitrary data to generate the HD wallet mnemonic to be used. 154 | * `"default_balance_ether"`: `number` - The default account balance, specified in ether. 155 | * `"total_accounts"`: `number` - Number of accounts to generate at startup. 156 | * `"fork"`: `string` or `object` - Fork from another currently running Ethereum client at a given block. When a `string`, input should be the HTTP location and port of the other client, e.g. `http://localhost:8545`. You can optionally specify the block to fork from using an `@` sign: `http://localhost:8545@1599200`. Can also be a `Web3 Provider` object, optionally used in conjunction with the `fork_block_number` option below. 157 | * `"fork_block_number"`: `string` or `number` - Block number the provider should fork from, when the `fork` option is specified. If the `fork` option is specified as a string including the `@` sign and a block number, the block number in the `fork` parameter takes precedence. 158 | `forkCacheSize`: `number` - The maximum size, in bytes, of the in-memory cache for queries on a chain fork. Defaults to `1_073_741_824` bytes (1 gigabyte). You can set this to `0` to disable caching (not recommended), or to `-1` for unlimited (will be limited by your node/browser process). 159 | * `"network_id"`: Specify the network id ganache-core will use to identify itself (defaults to the current time or the network id of the forked blockchain if configured) 160 | * `"time"`: `Date` - Date that the first block should start. Use this feature, along with the `evm_increaseTime` method to test time-dependent code. 161 | * `"locked"`: `boolean` - whether or not accounts are locked by default. 162 | * `"unlocked_accounts"`: `Array` - array of addresses or address indexes specifying which accounts should be unlocked. 163 | * `"db_path"`: `String` - Specify a path to a directory to save the chain database. If a database already exists, `ganache-cli` will initialize that chain instead of creating a new one. Note: You will not be able to modify state (accounts, balances, etc) on startup when you initialize ganache-core with a pre-existing database. 164 | * `"db"`: `Object` - Specify an alternative database instance, for instance [MemDOWN](https://github.com/level/memdown). 165 | * `"ws"`: `boolean` Enable a websocket server. This is `true` by default. 166 | * `"account_keys_path"`: `String` - Specifies a file to save accounts and private keys to, for testing. 167 | * `"vmErrorsOnRPCResponse"`: `boolean` - Whether or not to transmit transaction failures as RPC errors. Set to `false` for error reporting behaviour which is compatible with other clients such as geth and Parity. This is `true` by default to replicate the error reporting behavior of previous versions of ganache. 168 | * `"hdPath"`: The hierarchical deterministic path to use when generating accounts. Default: "m/44'/60'/0'/0/" 169 | * `"hardfork"`: `String` Allows users to specify which hardfork should be used. Supported hardforks are `byzantium`, `constantinople`, `petersburg`, `istanbul`, and `muirGlacier` (default). 170 | * `"allowUnlimitedContractSize"`: `boolean` - Allows unlimited contract sizes while debugging (NOTE: this setting is often used in conjuction with an increased `gasLimit`). By setting this to `true`, the check within the EVM for contract size limit of 24KB (see [EIP-170](https://git.io/vxZkK)) is bypassed. Setting this to `true` **will** cause `ganache-cli` to behave differently than production environments. (default: `false`; **ONLY** set to `true` during debugging). 171 | * `"gasPrice"`: `String::hex` Sets the default gas price for transactions if not otherwise specified. Must be specified as a `hex` encoded string in `wei`. Defaults to `"0x77359400"` (2 `gwei`). 172 | * `"gasLimit"`: `String::hex | number` Sets the block gas limit. Must be specified as a `hex` string or `number`. Defaults to `"0x6691b7"`. 173 | * `"callGasLimit"`: `number` Sets the transaction gas limit for `eth_call` and `eth_estimateGas` calls. Must be specified as a `hex` string. Defaults to `"0x1fffffffffffff"` (`Number.MAX_SAFE_INTEGER`). 174 | * `"keepAliveTimeout"`: `number` If using `.server()` - Sets the HTTP server's `keepAliveTimeout` in milliseconds. See the [NodeJS HTTP docs](https://nodejs.org/api/http.html#http_server_keepalivetimeout) for details. `5000` by default. 175 | 176 | ## Implemented Methods 177 | 178 | The RPC methods currently implemented are: 179 | 180 | * [eth_accounts](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts) 181 | * [eth_blockNumber](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blockNumber) 182 | * [eth_call](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call) 183 | * [eth_coinbase](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase) 184 | * [eth_estimateGas](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimateGas) 185 | * [eth_gasPrice](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasPrice) 186 | * [eth_getBalance](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getBalance) 187 | * [eth_getBlockByNumber](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getBlockByNumber) 188 | * [eth_getBlockByHash](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getBlockByHash) 189 | * [eth_getBlockTransactionCountByHash](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getBlockTransactionCountByHash) 190 | * [eth_getBlockTransactionCountByNumber](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getBlockTransactionCountByNumber) 191 | * [eth_getCode](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getCode) (only supports block number “latest”) 192 | * [eth_getCompilers](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getCompilers) 193 | * [eth_getFilterChanges](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getFilterChanges) 194 | * [eth_getFilterLogs](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getFilterLogs) 195 | * [eth_getLogs](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getLogs) 196 | * [eth_getStorageAt](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getStorageAt) 197 | * [eth_getTransactionByHash](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getTransactionByHash) 198 | * [eth_getTransactionByBlockHashAndIndex](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getTransactionByBlockHashAndIndex) 199 | * [eth_getTransactionByBlockNumberAndIndex](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getTransactionByBlockNumberAndIndex) 200 | * [eth_getTransactionCount](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getTransactionCount) 201 | * [eth_getTransactionReceipt](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getTransactionReceipt) 202 | * [eth_hashrate](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate) 203 | * [eth_mining](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining) 204 | * [eth_newBlockFilter](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newBlockFilter) 205 | * [eth_newFilter](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newFilter) (includes log/event filters) 206 | * [eth_protocolVersion](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolVersion) 207 | * [eth_sendTransaction](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendTransaction) 208 | * [eth_sendRawTransaction](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendRawTransaction) 209 | * [eth_sign](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) 210 | * `eth_signTypedData` 211 | * [eth_subscribe](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_subscribe) (only for websocket connections. "syncing" subscriptions are not yet supported) 212 | * [eth_unsubscribe](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_unsubscribe) (only for websocket connections. "syncing" subscriptions are not yet supported) 213 | * [shh_version](https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version) 214 | * [net_version](https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version) 215 | * [net_peerCount](https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peerCount) 216 | * [net_listening](https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening) 217 | * [eth_uninstallFilter](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallFilter) 218 | * [eth_syncing](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing) 219 | * [web3_clientVersion](https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientVersion) 220 | * [web3_sha3](https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3) 221 | * `bzz_hive` 222 | * `bzz_info` 223 | 224 | #### Management API Methods 225 | 226 | * [debug_traceTransaction](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#debug_tracetransaction) 227 | * [miner_start](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_start) 228 | * [miner_stop](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_stop) 229 | * [personal_sendTransaction](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sendTransaction) 230 | * [personal_unlockAccount](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_unlockAccount) 231 | * [personal_importRawKey](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_importRawKey) 232 | * [personal_newAccount](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_newAccount) 233 | * [personal_lockAccount](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_lockAccount) 234 | * [personal_listAccounts](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_listaccounts) 235 | 236 | ## Custom Methods 237 | 238 | Special non-standard methods that aren’t included within the original RPC specification: 239 | * `evm_snapshot` : Snapshot the state of the blockchain at the current block. Takes no parameters. Returns the integer id of the snapshot created. A snapshot can only be used once. After a successful `evm_revert`, the same snapshot id cannot be used again. Consider creating a new snapshot after each `evm_revert` *if you need to revert to the same point multiple times*. 240 | ```bash 241 | curl -H "Content-Type: application/json" -X POST --data \ 242 | '{"id":1337,"jsonrpc":"2.0","method":"evm_snapshot","params":[]}' \ 243 | http://localhost:8545 244 | ``` 245 | ```json 246 | { "id": 1337, "jsonrpc": "2.0", "result": "0x1" } 247 | ``` 248 | * `evm_revert` : Revert the state of the blockchain to a previous snapshot. Takes a single parameter, which is the snapshot id to revert to. This deletes the given snapshot, as well as any snapshots taken after (Ex: reverting to id `0x1` will delete snapshots with ids `0x1`, `0x2`, `etc`... If no snapshot id is passed it will revert to the latest snapshot. Returns `true`. 249 | ```bash 250 | # Ex: ID "1" (hex encoded string) 251 | curl -H "Content-Type: application/json" -X POST --data \ 252 | '{"id":1337,"jsonrpc":"2.0","method":"evm_revert","params":["0x1"]}' \ 253 | http://localhost:8545 254 | ``` 255 | ```json 256 | { "id": 1337, "jsonrpc": "2.0", "result": true } 257 | ``` 258 | * `evm_increaseTime` : Jump forward in time. Takes one parameter, which is the amount of time to increase in seconds. Returns the total time adjustment, in seconds. 259 | ```bash 260 | # Ex: 1 minute (number) 261 | curl -H "Content-Type: application/json" -X POST --data \ 262 | '{"id":1337,"jsonrpc":"2.0","method":"evm_increaseTime","params":[60]}' \ 263 | http://localhost:8545 264 | ``` 265 | ```json 266 | { "id": 1337, "jsonrpc": "2.0", "result": "060" } 267 | ``` 268 | * `evm_mine` : Force a block to be mined. Takes one optional parameter, which is the timestamp a block should setup as the mining time. Mines a block independent of whether or not mining is started or stopped. 269 | ```bash 270 | # Ex: new Date("2009-01-03T18:15:05+00:00").getTime() 271 | curl -H "Content-Type: application/json" -X POST --data \ 272 | '{"id":1337,"jsonrpc":"2.0","method":"evm_mine","params":[1231006505000]}' \ 273 | http://localhost:8545 274 | ``` 275 | 276 | ```json 277 | { "id": 1337, "jsonrpc": "2.0", "result": "0x0" } 278 | ``` 279 | * `evm_unlockUnknownAccount` : Unlocks any unknown account. Accounts known to the `personal` namespace and accounts 280 | returned by `eth_accounts` cannot be unlocked using this method; use `personal_unlockAccount` instead. 281 | ```bash 282 | # Ex: account: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" 283 | curl -H "Content-Type: application/json" -X POST --data \ 284 | '{"id":1337,"jsonrpc":"2.0","method":"evm_unlockUnknownAccount","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"]}' \ 285 | http://localhost:8545 286 | ``` 287 | 288 | ```json 289 | { "id": 1337, "jsonrpc": "2.0", "result": true } 290 | ``` 291 | * `evm_lockUnknownAccount` : Locks any unknown account. Accounts known to the `personal` namespace and accounts 292 | returned by `eth_accounts` cannot be locked using this method; use `personal_lockAccount` instead. 293 | ```bash 294 | # Ex: account: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" 295 | curl -H "Content-Type: application/json" -X POST --data \ 296 | '{"id":1337,"jsonrpc":"2.0","method":"evm_lockUnknownAccount","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"]}' \ 297 | http://localhost:8545 298 | ``` 299 | 300 | ```json 301 | { "id": 1337, "jsonrpc": "2.0", "result": true } 302 | ``` 303 | 304 | ## Unsupported Methods 305 | 306 | * `eth_compileSolidity`: If you'd like Solidity compilation in Javascript, please see the [solc-js project](https://github.com/ethereum/solc-js). 307 | 308 | ## Docker 309 | 310 | The Simplest way to get started with the Docker image: 311 | 312 | ```Bash 313 | docker run --detach --publish 8545:8545 trufflesuite/ganache-cli:latest 314 | ``` 315 | 316 | To pass options to ganache-cli through Docker simply add the arguments to 317 | the run command: 318 | 319 | ```Bash 320 | docker run --detach --publish 8545:8545 trufflesuite/ganache-cli:latest --accounts 10 --debug 321 | ^^^^^^^^^^^^^^^^^^^^^ 322 | ``` 323 | 324 | The Docker container adds an environment variable `DOCKER=true`; when this variable is set to `true` (case insensitive), `ganache-cli` use a default hostname IP of `0.0.0.0` instead of the normal default `127.0.0.1`. You can still specify a custom hostname however: 325 | 326 | ```Bash 327 | docker run --detach --publish 8545:8545 trufflesuite/ganache-cli:latest --host XXX.XXX.XXX.XXX 328 | ^^^^^^^^^^^^^^^^^^^^^^ 329 | ``` 330 | 331 | To build and run the Docker container from source: 332 | 333 | ```Bash 334 | git clone https://github.com/trufflesuite/ganache-cli.git && cd ganache-cli 335 | ``` 336 | then: 337 | ```Bash 338 | docker build --tag trufflesuite/ganache-cli . 339 | docker run --publish 8545:8545 trufflesuite/ganache-cli 340 | ``` 341 | or 342 | ```Bash 343 | npm run docker 344 | ``` 345 | 346 | 347 | ## Contributing to Ganache CLI 348 | 349 | The Ganache CLI repository contains the cli logic and Docker config/build only. It utilizes [ganache-core](https://github.com/trufflesuite/ganache-core), the core logic powering [Ganache](https://github.com/trufflesuite/ganache), internally. 350 | 351 | You can contribute to the core code at [ganache-core](https://github.com/trufflesuite/ganache-core). 352 | 353 | To contribue to ganache-cli, run: 354 | 355 | ```Bash 356 | git clone https://github.com/trufflesuite/ganache-cli.git && cd ganache-cli 357 | npm install 358 | ``` 359 | 360 | You'll need Python 2.7 installed, and on Windows, you'll likely need to install [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) from an Administrator PowerShell Prompt via `npm install --global windows-build-tools`. 361 | 362 | ### PR Message format: 363 | 364 | `(): ` 365 | 366 | Where `type` must be one of the following: 367 | 368 | * **feat**: A new feature 369 | * **fix**: A bug fix 370 | * **docs**: Documentation only changes 371 | * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing 372 | semi-colons, etc) 373 | * **refactor**: A code change that neither fixes a bug nor adds a feature 374 | * **perf**: A code change that improves performance 375 | * **test**: Adding missing or correcting existing tests 376 | * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation 377 | generation 378 | 379 | see: https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines 380 | 381 | # License 382 | [MIT](https://tldrlegal.com/license/mit-license) 383 | -------------------------------------------------------------------------------- /args.js: -------------------------------------------------------------------------------- 1 | module.exports = exports = function(yargs, version, isDocker) { 2 | return yargs 3 | .strict() 4 | .option('p', { 5 | group: 'Network:', 6 | alias: 'port', 7 | type: 'number', 8 | default: 8545, 9 | describe: 'Port number to listen on' 10 | }) 11 | .option('h', { 12 | group: 'Network:', 13 | alias: ['host', 'hostname'], 14 | type: 'string', 15 | default: isDocker ? '0.0.0.0' : '127.0.0.1', 16 | describe: 'Hostname to listen on' 17 | }) 18 | .option('keepAliveTimeout', { 19 | group: 'Network:', 20 | type: 'number', 21 | default: 5000, 22 | describe: 'The number of milliseconds of inactivity a server needs to wait for additional incoming data, after it has finished writing the last response, before a socket will be destroyed.' 23 | }) 24 | .option('a', { 25 | group: 'Accounts:', 26 | alias: 'accounts', 27 | describe: 'Number of accounts to generate at startup', 28 | type: 'number', 29 | default: 10 30 | }) 31 | .option('e', { 32 | group: 'Accounts:', 33 | alias: 'defaultBalanceEther', 34 | describe: 'Amount of ether to assign each test account', 35 | type: 'number', 36 | default: 100.0 37 | }) 38 | .option('account', { 39 | group: 'Accounts:', 40 | describe: "Account data in the form ',', can be specified multiple times. Note that private keys are 64 characters long and must be entered as an 0x-prefixed hex string. Balance can either be input as an integer, or as a 0x-prefixed hex string with either form specifying the initial balance in wei.", 41 | type: 'array', 42 | string: true, 43 | demandOption: false 44 | }) 45 | .option('account_keys_path', { 46 | group: 'Accounts:', 47 | alias: 'acctKeys', 48 | type: 'string', 49 | describe: 'saves generated accounts and private keys as JSON object in specified file', 50 | normalize: true, 51 | demandOption: false, 52 | default: null 53 | }) 54 | .option('n', { 55 | group: 'Accounts:', 56 | alias: 'secure', 57 | describe: 'Lock available accounts by default (good for third party transaction signing)', 58 | type: 'boolean', 59 | default: false 60 | }) 61 | .option('u', { 62 | group: 'Accounts:', 63 | alias: 'unlock', 64 | type: 'array', 65 | string: true, 66 | describe: 'Comma-separated list of accounts or indices to unlock', 67 | demandOption: false 68 | }) 69 | .option('k', { 70 | group: 'Chain:', 71 | alias: 'hardfork', 72 | type: 'string', 73 | describe: "Allows users to specify which hardfork should be used. Supported hardforks are `byzantium`, `constantinople`, `petersburg`, `istanbul` and `muirGlacier` (default).", 74 | default: "muirGlacier" 75 | }) 76 | .option('f', { 77 | group: 'Chain:', 78 | alias: 'fork', 79 | type: 'string', 80 | describe: "Fork from another currently running Ethereum client at a given block. Input should be the HTTP location and port of the other client, e.g. 'http://localhost:8545' or optionally provide a block number 'http://localhost:8545@1599200'", 81 | default: false 82 | }) 83 | .option('forkCacheSize', { 84 | group: 'Chain:', 85 | type: 'number', 86 | describe: "The maximum size, in bytes, of the in-memory cache for queries on a chain fork. Defaults to `1_073_741_824` bytes (1 gigabyte). You can set this to `0` to disable caching (not recommended), or to `-1` for unlimited (will be limited by your node process).", 87 | default: 1073741824 88 | }) 89 | .option('db', { 90 | group: 'Chain:', 91 | describe: 'Directory of chain database; creates one if it doesn\'t exist', 92 | type: 'string', 93 | normalize: true, 94 | default: null 95 | }) 96 | .option('s', { 97 | group: 'Chain:', 98 | alias: 'seed', 99 | type: 'string', 100 | describe: 'Arbitrary data to generate the HD wallet mnemonic to be used', 101 | defaultDescription: "Random value, unless -d is specified", 102 | conflicts: 'd', 103 | demandOption: false 104 | }) 105 | .option('hdPath', { 106 | group: 'Accounts:', 107 | alias: 'hd_path', 108 | describe: `The hierarchical deterministic path to use when generating accounts. Default: "m/44'/60'/0'/0/"`, 109 | type: 'string', 110 | demandOption: false 111 | }) 112 | .option('d', { 113 | group: 'Chain:', 114 | alias: 'deterministic', 115 | describe: 'Generate deterministic addresses based on a pre-defined mnemonic.', 116 | conflicts: 's', 117 | type: 'boolean', 118 | default: undefined, 119 | demandOption: false 120 | }) 121 | .option('m', { 122 | group: 'Chain:', 123 | alias: 'mnemonic', 124 | type: 'string', 125 | describe: 'bip39 mnemonic phrase for generating a PRNG seed, which is in turn used for hierarchical deterministic (HD) account generation', 126 | demandOption: false 127 | }) 128 | .option('noVMErrorsOnRPCResponse', { 129 | group: 'Chain:', 130 | describe: 'Do not transmit transaction failures as RPC errors. Enable this flag for error reporting behaviour which is compatible with other clients such as geth and Parity.', 131 | type: 'boolean', 132 | default: false 133 | }) 134 | .option('b', { 135 | group: 'Chain:', 136 | alias: 'blockTime', 137 | type: 'number', 138 | describe: 'Block time in seconds for automatic mining. Will instantly mine a new block for every transaction if option omitted. Avoid using unless your test cases require a specific mining interval.', 139 | demandOption: false 140 | }) 141 | .option('i', { 142 | group: 'Chain:', 143 | alias: 'networkId', 144 | type: 'number', 145 | describe: "The Network ID ganache-cli will use to identify itself.", 146 | defaultDescription: "System time at process start or Network ID of forked blockchain if configured.", 147 | demandOption: false 148 | }) 149 | .option('chainId', { 150 | group: 'Chain:', 151 | type: 'number', 152 | describe: "The Chain ID ganache-cli will use for `eth_chainId` RPC and the `CHAINID` opcode.", 153 | defaultDescription: "For legacy reasons, the default is currently `1337` for `eth_chainId` RPC and `1` for the `CHAINID` opcode. This will be fixed in the next major version of ganache-cli and ganache-core!", 154 | demandOption: false 155 | }) 156 | .option('g', { 157 | group: 'Chain:', 158 | alias: 'gasPrice', 159 | describe: 'The price of gas in wei', 160 | type: 'number', 161 | default: 20000000000 162 | }) 163 | .option('l', { 164 | group: 'Chain:', 165 | alias: 'gasLimit', 166 | describe: 'The block gas limit in wei', 167 | type: 'number', 168 | default: 0x6691b7 169 | }) 170 | .option('callGasLimit', { 171 | group: 'Chain:', 172 | describe: 'Sets the transaction gas limit for `eth_call` and `eth_estimateGas` calls. Must be specified as a hex string. Defaults to "0x1fffffffffffff" (Number.MAX_SAFE_INTEGER)', 173 | type: 'number', 174 | default: 0x1fffffffffffff 175 | }) 176 | .option('allowUnlimitedContractSize', { 177 | group: 'Chain:', 178 | describe: 'Allows unlimited contract sizes while debugging. By enabling this flag, the check within the EVM for contract size limit of 24KB (see EIP-170) is bypassed. Enabling this flag *will* cause ganache-cli to behave differently than production environments.', 179 | type: 'boolean', 180 | default: false 181 | }) 182 | .option('t', { 183 | group: 'Chain:', 184 | alias: 'time', 185 | describe: 'Date (ISO 8601) that the first block should start. Use this feature, along with the evm_increaseTime method to test time-dependent code.', 186 | type: 'string', 187 | coerce: (arg) => { 188 | let timestamp = Date.parse(arg); 189 | if (isNaN(timestamp)) { 190 | throw new Error('Invalid \'time\' format'); 191 | } 192 | return new Date(timestamp); 193 | } 194 | }) 195 | .option('debug', { 196 | group: 'Other:', 197 | describe: 'Output VM opcodes for debugging', 198 | type: 'boolean', 199 | default: false 200 | }) 201 | .option('v', { 202 | group: 'Other:', 203 | alias: 'verbose', 204 | describe: 'Log all requests and responses to stdout', 205 | type: 'boolean', 206 | default: false 207 | }) 208 | .option('mem', { 209 | group: 'Other:', 210 | describe: 'Only show memory output, not tx history', 211 | type: 'boolean', 212 | default: false 213 | }) 214 | .option('q', { 215 | group: 'Other:', 216 | alias: 'quiet', 217 | describe: 'Run ganache quietly (no logs)', 218 | type: 'boolean', 219 | default: false 220 | }) 221 | .showHelpOnFail(false, 'Specify -? or --help for available options') 222 | .help('help') 223 | .alias('help', '?') 224 | .wrap(Math.min(120, yargs.terminalWidth())) 225 | .version(version) 226 | .check((argv) => { 227 | if (argv.p < 1 || argv.p > 65535) { 228 | throw new Error(`Invalid port number '${argv.p}'`); 229 | } 230 | 231 | if (argv.h.trim() == '') { 232 | throw new Error('Cannot leave hostname blank; please provide a hostname'); 233 | } 234 | 235 | return true; 236 | }) 237 | } 238 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // make sourcemaps work! 4 | require('source-map-support').install(); 5 | 6 | var yargs = require("yargs"); 7 | var pkg = require("./package.json"); 8 | var {toChecksumAddress, BN} = require("ethereumjs-util"); 9 | var ganache; 10 | try { 11 | ganache = require("./lib"); 12 | } catch(e) { 13 | ganache = require("./build/ganache-core.node.cli.js"); 14 | } 15 | var to = ganache.to; 16 | var initArgs = require("./args") 17 | 18 | var detailedVersion = "Ganache CLI v" + pkg.version + " (ganache-core: " + ganache.version + ")"; 19 | 20 | var isDocker = "DOCKER" in process.env && process.env.DOCKER.toLowerCase() === "true"; 21 | var argv = initArgs(yargs, detailedVersion, isDocker).argv; 22 | 23 | function parseAccounts(accounts) { 24 | function splitAccount(account) { 25 | account = account.split(',') 26 | return { 27 | secretKey: account[0], 28 | balance: account[1] 29 | }; 30 | } 31 | 32 | if (typeof accounts === 'string') 33 | return [ splitAccount(accounts) ]; 34 | else if (!Array.isArray(accounts)) 35 | return; 36 | 37 | var ret = [] 38 | for (var i = 0; i < accounts.length; i++) { 39 | ret.push(splitAccount(accounts[i])); 40 | } 41 | return ret; 42 | } 43 | 44 | if (argv.d) { 45 | argv.s = "TestRPC is awesome!"; // Seed phrase; don't change to Ganache, maintain original determinism 46 | } 47 | 48 | if (typeof argv.unlock == "string") { 49 | argv.unlock = [argv.unlock]; 50 | } 51 | 52 | var logger = console; 53 | 54 | // If quiet argument passed, no output 55 | if (argv.q === true){ 56 | logger = { 57 | log: function() {} 58 | }; 59 | } 60 | 61 | // If the mem argument is passed, only show memory output, 62 | // not transaction history. 63 | if (argv.mem === true) { 64 | logger = { 65 | log: function() {} 66 | }; 67 | 68 | setInterval(function() { 69 | console.log(process.memoryUsage()); 70 | }, 1000); 71 | } 72 | 73 | var options = { 74 | port: argv.p, 75 | hostname: argv.h, 76 | debug: argv.debug, 77 | seed: argv.s, 78 | mnemonic: argv.m, 79 | total_accounts: argv.a, 80 | default_balance_ether: argv.e, 81 | blockTime: argv.b, 82 | gasPrice: argv.g, 83 | gasLimit: argv.l, 84 | callGasLimit: argv.callGasLimit, 85 | accounts: parseAccounts(argv.account), 86 | unlocked_accounts: argv.unlock, 87 | fork: argv.f, 88 | forkCacheSize: argv.forkCacheSize, 89 | hardfork: argv.k, 90 | network_id: argv.i, 91 | verbose: argv.v, 92 | secure: argv.n, 93 | db_path: argv.db, 94 | hd_path: argv.hdPath, 95 | account_keys_path: argv.account_keys_path, 96 | vmErrorsOnRPCResponse: !argv.noVMErrorsOnRPCResponse, 97 | logger: logger, 98 | allowUnlimitedContractSize: argv.allowUnlimitedContractSize, 99 | time: argv.t, 100 | keepAliveTimeout: argv.keepAliveTimeout, 101 | _chainId: argv.chainId, 102 | // gross! 103 | _chainIdRpc: argv.chainId 104 | } 105 | 106 | var server = ganache.server(options); 107 | 108 | console.log(detailedVersion); 109 | 110 | let started = false; 111 | process.on("uncaughtException", function(e) { 112 | if (started) { 113 | console.log(e); 114 | } else { 115 | console.log(e.stack); 116 | } 117 | process.exit(1); 118 | }) 119 | 120 | // See http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js 121 | if (process.platform === "win32") { 122 | require("readline").createInterface({ 123 | input: process.stdin, 124 | output: process.stdout 125 | }) 126 | .on("SIGINT", function () { 127 | process.emit("SIGINT"); 128 | }); 129 | } 130 | 131 | const closeHandler = function () { 132 | // graceful shutdown 133 | server.close(function(err) { 134 | if (err) { 135 | // https://nodejs.org/api/process.html#process_process_exit_code 136 | // writes to process.stdout in Node.js are sometimes asynchronous and may occur over 137 | // multiple ticks of the Node.js event loop. Calling process.exit(), however, forces 138 | // the process to exit before those additional writes to stdout can be performed. 139 | if(process.stdout._handle) process.stdout._handle.setBlocking(true); 140 | console.log(err.stack || err); 141 | process.exit(); 142 | } else { 143 | process.exit(0); 144 | } 145 | }); 146 | } 147 | 148 | process.on("SIGINT", closeHandler); 149 | process.on("SIGTERM", closeHandler); 150 | process.on("SIGHUP", closeHandler); 151 | 152 | function startGanache(err, result) { 153 | if (err) { 154 | console.log(err); 155 | return; 156 | } 157 | started = true; 158 | var state = result ? result : server.provider.manager.state; 159 | 160 | console.log(""); 161 | console.log("Available Accounts"); 162 | console.log("=================="); 163 | 164 | var accounts = state.accounts; 165 | var addresses = Object.keys(accounts); 166 | var ethInWei = new BN("1000000000000000000"); 167 | 168 | addresses.forEach(function(address, index) { 169 | var balance = new BN(accounts[address].account.balance); 170 | var strBalance = balance.divRound(ethInWei).toString(); 171 | var about = balance.mod(ethInWei).isZero() ? "" : "~"; 172 | var line = `(${index}) ${toChecksumAddress(address)} (${about}${strBalance} ETH)`; 173 | 174 | if (state.isUnlocked(address) == false) { 175 | line += " 🔒"; 176 | } 177 | 178 | console.log(line); 179 | }); 180 | 181 | console.log(""); 182 | console.log("Private Keys"); 183 | console.log("=================="); 184 | 185 | addresses.forEach(function(address, index) { 186 | console.log("(" + index + ") " + "0x" + accounts[address].secretKey.toString("hex")); 187 | }); 188 | 189 | 190 | if (options.account_keys_path != null) { 191 | console.log(""); 192 | console.log("Accounts and keys saved to " + options.account_keys_path); 193 | } 194 | 195 | if (options.accounts == null) { 196 | console.log(""); 197 | console.log("HD Wallet"); 198 | console.log("=================="); 199 | console.log("Mnemonic: " + state.mnemonic); 200 | console.log("Base HD Path: " + state.wallet_hdpath + "{account_index}") 201 | } 202 | 203 | if (options.gasPrice) { 204 | console.log(""); 205 | console.log("Gas Price"); 206 | console.log("=================="); 207 | console.log(options.gasPrice); 208 | } 209 | 210 | if (options.gasLimit) { 211 | console.log(""); 212 | console.log("Gas Limit"); 213 | console.log("=================="); 214 | console.log(options.gasLimit); 215 | } 216 | 217 | if (options.callGasLimit) { 218 | console.log(""); 219 | console.log("Call Gas Limit"); 220 | console.log("=================="); 221 | console.log(options.callGasLimit); 222 | } 223 | 224 | if (options.fork) { 225 | console.log(""); 226 | console.log("Forked Chain"); 227 | console.log("=================="); 228 | console.log("Location: " + state.blockchain.options.fork); 229 | console.log("Block: " + to.number(state.blockchain.forkBlockNumber)); 230 | console.log("Network ID: " + state.net_version); 231 | console.log("Time: " + (state.blockchain.startTime || new Date()).toString()); 232 | let maxCacheSize; 233 | if (options.forkCacheSize === -1) { 234 | maxCacheSize = "∞"; 235 | } else { 236 | maxCacheSize = options.forkCacheSize + " bytes"; 237 | } 238 | console.log("Max Cache Size: " + maxCacheSize); 239 | } 240 | 241 | console.log(""); 242 | console.log("Listening on " + options.hostname + ":" + options.port); 243 | } 244 | 245 | server.listen(options.port, options.hostname, startGanache); 246 | -------------------------------------------------------------------------------- /lib.js: -------------------------------------------------------------------------------- 1 | // make sourcemaps work! 2 | require('source-map-support').install(); 3 | 4 | module.exports = require("ganache-core/public-exports.js"); 5 | module.exports.version = require("ganache-core/package.json").version; 6 | module.exports.to = require("ganache-core/lib/utils/to"); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ganache-cli", 3 | "version": "6.12.1", 4 | "bin": { 5 | "ganache-cli": "cli.js" 6 | }, 7 | "main": "./build/ganache-core.node.cli.js", 8 | "scripts": { 9 | "start": "node cli.js", 10 | "build": "webpack-cli --config ./webpack/webpack.node.config.js", 11 | "docker": "docker build -t trufflesuite/ganache-cli . && docker run -p 8545:8545 trufflesuite/ganache-cli", 12 | "otp": "node ./scripts/generate-otp.js", 13 | "releaseNotes": "npx semantic-release --dry-run" 14 | }, 15 | "dependencies": { 16 | "ethereumjs-util": "6.2.1", 17 | "source-map-support": "0.5.12", 18 | "yargs": "13.2.4" 19 | }, 20 | "bundleDependencies": [ 21 | "source-map-support", 22 | "yargs", 23 | "ethereumjs-util" 24 | ], 25 | "devDependencies": { 26 | "@semantic-release/git": "^9.0.0", 27 | "ganache-core": "2.13.2", 28 | "node-loader": "^0.6.0", 29 | "notp": "2.0.3", 30 | "on-build-webpack": "^0.1.0", 31 | "prepend-file": "^1.3.1", 32 | "semantic-release": "^17.1.1", 33 | "shebang-loader": "0.0.1", 34 | "thirty-two": "1.0.2", 35 | "webpack": "4.43.0", 36 | "webpack-cli": "3.3.12" 37 | }, 38 | "repository": { 39 | "type": "git", 40 | "url": "https://github.com/trufflesuite/ganache-cli" 41 | }, 42 | "license": "MIT", 43 | "release": { 44 | "branches": [ 45 | "+([0-9])?(.{+([0-9]),x}).x", 46 | "master", 47 | { 48 | "name": "beta", 49 | "prerelease": true 50 | }, 51 | { 52 | "name": "alpha", 53 | "prerelease": true 54 | } 55 | ], 56 | "plugins": [ 57 | "@semantic-release/commit-analyzer", 58 | "@semantic-release/github", 59 | "@semantic-release/npm", 60 | [ 61 | "@semantic-release/git", 62 | { 63 | "assets": [ 64 | "package.json", 65 | "package-lock.json", 66 | "npm-shrinkwrap.json" 67 | ], 68 | "message": "${nextRelease.version}\n\n${nextRelease.notes}" 69 | } 70 | ], 71 | "@semantic-release/release-notes-generator" 72 | ] 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /resources/icons/ganache-cli-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsenSys-archive/ganache-cli-archive/fea952cd7628e4803b8a10c2aa8928404645f8bb/resources/icons/ganache-cli-128x128.png -------------------------------------------------------------------------------- /resources/icons/ganache-cli.svg: -------------------------------------------------------------------------------- 1 | ganache-cli-logo -------------------------------------------------------------------------------- /scripts/generate-otp.js: -------------------------------------------------------------------------------- 1 | const EOL = require("os").EOL; 2 | const path = require("path"); 3 | const fs = require("fs"); 4 | // we want to generate a TOTP in the _future_, and the `notp` 5 | // library doesn't let us do that unless we set `NODE_ENV = "test"` 6 | process.env.NODE_ENV = "test"; 7 | 8 | const b32 = require("thirty-two"); 9 | const notp = require("notp"); 10 | const bin = b32.decode(process.env.NPM_OTP_KEY); 11 | // generate a code 1 seconds in the future 12 | // 1 seconds is arbitrary, and may need to be tweaked if 13 | // the release process is discovered to be too fast or too slow. 14 | const timeOffset = 1000; 15 | const now = Date.now(); 16 | const time = now + timeOffset; 17 | // _t is the time at which we want the OTP to be valid for 18 | const otp = notp.totp.gen(bin, {_t: time}); 19 | 20 | // save to .npmrc so `npm publish` can pick it up later 21 | fs.appendFileSync(path.join(__dirname, "..", ".npmrc"), `${EOL}otp=${otp}`); 22 | -------------------------------------------------------------------------------- /webpack/plugins.js: -------------------------------------------------------------------------------- 1 | const { IgnorePlugin } = require("webpack"); 2 | const WebpackOnBuildPlugin = require("on-build-webpack"); 3 | const { EOL } = require("os"); 4 | const { chmodSync, existsSync } = require("fs"); 5 | const { join } = require("path"); 6 | 7 | const prependFile = require("prepend-file"); 8 | module.exports = (outputDir, outputFilename) => { 9 | return [ 10 | // ignore these plugins completely 11 | new IgnorePlugin(/^(?:electron|ws)$/), 12 | 13 | // Put the shebang back on and make sure it's executable. 14 | new WebpackOnBuildPlugin(function () { 15 | const outputFile = join(outputDir, outputFilename); 16 | if (existsSync(outputFile)) { 17 | prependFile.sync(outputFile, "#!/usr/bin/env node" + EOL); 18 | chmodSync(outputFile, "755"); 19 | } 20 | }) 21 | ]; 22 | }; -------------------------------------------------------------------------------- /webpack/webpack.docker.config.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("path"); 2 | const plugins = require("./plugins"); 3 | 4 | const outputDir = resolve(__dirname, "../build"); 5 | const outputFilename = "ganache-core.docker.cli.js"; 6 | module.exports = { 7 | entry: [ 8 | "./cli.js" 9 | ], 10 | target: "node", 11 | output: { 12 | path: outputDir, 13 | filename: outputFilename, 14 | library: "Ganache-Cli", 15 | libraryTarget: "umd", 16 | umdNamedDefine: true 17 | }, 18 | devtool: "source-map", 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.js$/, 23 | use: "shebang-loader" 24 | } 25 | ] 26 | }, 27 | resolve: { 28 | alias: { 29 | "./build/ganache-core.node.cli.js": "./lib.js" 30 | } 31 | }, 32 | plugins: plugins(outputDir, outputFilename), 33 | mode: "production" 34 | }; 35 | -------------------------------------------------------------------------------- /webpack/webpack.node.config.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require("path"); 2 | const plugins = require("./plugins"); 3 | 4 | const outputDir = resolve(__dirname, "../build"); 5 | const outputFilename = "ganache-core.node.cli.js"; 6 | module.exports = { 7 | entry: [ 8 | "./lib.js" 9 | ], 10 | target: "node", 11 | output: { 12 | path: outputDir, 13 | filename: outputFilename, 14 | library: "Ganache-Cli", 15 | libraryTarget: "umd", 16 | umdNamedDefine: true 17 | }, 18 | devtool: "source-map", 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.js$/, 23 | use: "shebang-loader" 24 | } 25 | ] 26 | }, 27 | externals: /^(source-map-support|yargs|bn.js)$/, 28 | resolve: { 29 | alias: { 30 | // eth-block-tracker is es6 but automatically builds an es5 version for us on install. 31 | "eth-block-tracker": "eth-block-tracker/dist/es5/index.js", 32 | } 33 | }, 34 | plugins: plugins(outputDir, outputFilename), 35 | mode: "production" 36 | }; 37 | --------------------------------------------------------------------------------