diff --git a/.gitignore b/.gitignore
index bae723592..13766594c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ out
package-lock.json
node_modules
.DS_Store
+.vscode
diff --git a/README.md b/README.md
index b5b18aac5..d8c990602 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,10 @@ Ganache is your personal blockchain for Ethereum development.
+### Getting started
+
+You can download a self-contained prebuilt Ganache binary for your platform of choice using the "Download" button on the [Ganache](http://truffleframework.com/ganache/) website, or from this repository's [releases](https://github.com/trufflesuite/ganache/releases) page.
+
### Contributing
Please open issues and pull requests for new features, questions, and bug fixes.
diff --git a/package.json b/package.json
index e09857e16..8db85e0ee 100644
--- a/package.json
+++ b/package.json
@@ -145,9 +145,9 @@
"electron-forge-maker-appimage": "^19.30.3",
"electron-settings": "^3.1.2",
"electron-squirrel-startup": "^1.0.0",
- "ethereumjs-testrpc": "^6.0.3",
"ethereumjs-units": "^0.2.0",
"find-process": "^1.1.0",
+ "ganache-cli": "^6.0.3",
"lodash": "^3.10.1",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
diff --git a/src/Components/AppShell/AppShell.js b/src/Components/AppShell/AppShell.js
index 20c00918d..538e0ac7a 100644
--- a/src/Components/AppShell/AppShell.js
+++ b/src/Components/AppShell/AppShell.js
@@ -8,10 +8,7 @@ import * as AppShellActions from '../../Actions/AppShell'
import TopNavbar from './TopNavbar'
import OnlyIf from '../../Elements/OnlyIf'
-import Modal from '../../Elements/Modal'
-
-import BugIcon from '../../Elements/icons/errorant.svg'
-
+import BugModal from './BugModal'
import ua from 'universal-analytics'
import ElectronCookies from '@exponent/electron-cookies'
@@ -110,25 +107,6 @@ class AppShell extends Component {
render () {
const path = this.props.location.pathname
- const segment = path.replace(/^\//g, '').replace(/\//g, '-') || 'root'
- let systemError = this.props.core.systemError
-
- if (systemError) {
- systemError = systemError.stack || systemError
-
- // Remove any user-specific paths in exception messages
- // Prepare our paths so we *always* will get a match no matter
- // path separator (oddly, on Windows, different errors will give
- // us different path separators)
- var appPath = app.getAppPath().replace(/\\/g, "/")
- systemError = systemError.replace(/\\/g, "/")
-
- // I couldn't figure out the regex, so a loop will do.
- while (systemError.indexOf(appPath) >= 0) {
- systemError = systemError.replace(appPath, "")
- }
- }
-
return (
@@ -136,55 +114,12 @@ class AppShell extends Component {
{this.props.children}
-
-
-
-
-
-
Uh Oh... That's a bug.
-
- Ganache encountered an error. Help us fix it by raising a GitHub issue!
Mention the following error information when writing your ticket, and please include as much information as possible. Sorry about that!
-
-
-
-
-
+
+
)
}
}
-export default connect(AppShell, "core", "settings")
+export default connect(AppShell, "core", "settings", "logs");
diff --git a/src/Components/AppShell/AppShell.scss b/src/Components/AppShell/AppShell.scss
index 730b3fd2f..5d55eb1fa 100644
--- a/src/Components/AppShell/AppShell.scss
+++ b/src/Components/AppShell/AppShell.scss
@@ -3,21 +3,6 @@
flex-direction: column;
height: 100%;
- .Bug {
- textarea {
- min-height: 5rem; /* Overwrite Modal textarea styles */
- max-height: 5rem;
- background-color: var(--app-button-primary-disabled-border-color);
- width: 100%;
- margin-bottom: 1rem;
- }
-
- svg {
- width: 192px;
- height: 192px;
- }
- }
-
.ShellContainer {
display: flex;
flex-grow: 1;
diff --git a/src/Components/AppShell/BugModal.js b/src/Components/AppShell/BugModal.js
new file mode 100644
index 000000000..2f33a1968
--- /dev/null
+++ b/src/Components/AppShell/BugModal.js
@@ -0,0 +1,118 @@
+import React, { Component } from 'react'
+
+import connect from '../Helpers/connect'
+
+import Modal from '../../Elements/Modal'
+
+import BugIcon from '../../Elements/icons/errorant.svg'
+
+import { sanitizeError, sanitizePaths } from '../Helpers/sanitize.js'
+
+import { shell } from 'electron'
+
+const { app } = require('electron').remote
+
+class BugModal extends Component {
+ constructor () {
+ super()
+ this.scrollDedupeTimeout = null
+ }
+
+ // grabs the last 500 log lines as a string formatted for inclusion as a github issue
+ renderAndSanitizeLogLines () {
+ let result = ''
+ if (this.props.logs && this.props.logs.lines && this.props.logs.lines.length > 0) {
+ let maxLines = -175 // negative because Array.slice -- we want the last 175 lines, not the first 175
+
+ // GitHub has a max URL length of ~8KiB, so we truncate logs to fit within that
+ while (encodeURIComponent(result = _getLastNLogLines(maxLines, this.props.logs)).length > 7500) {
+ maxLines++ // reduces number of lines we get next time
+ }
+ }
+ return sanitizePaths(result)
+ }
+
+ renderIssueBody(sanitizedSystemError, sanitizedLogLines) {
+ let issueBody =
+ "\n" +
+ "\n" +
+ "\n" +
+ `PLATFORM: ${process.platform}\n` +
+ `GANACHE VERSION: ${app.getVersion()}\n` +
+ "\n" +
+ "EXCEPTION:\n" +
+ "```\n" +
+ `${sanitizedSystemError}\n` +
+ "```"
+
+ if (sanitizedLogLines) {
+ issueBody += "\n" +
+ "\n" +
+ "APPLICATION LOG:\n" +
+ "```\n" +
+ `${sanitizedLogLines}\n` +
+ "```"
+ }
+ return encodeURIComponent(issueBody).replace(/%09/g, '')
+ }
+
+ render () {
+ let unsanitizedSystemError = this.props.systemError
+ let sanitizedSystemError = ''
+ let sanitizedLogLines = ''
+
+ if (unsanitizedSystemError) {
+ sanitizedSystemError = sanitizeError(unsanitizedSystemError)
+ sanitizedLogLines = this.renderAndSanitizeLogLines()
+ }
+
+ return (
+
+
+
+
Uh Oh... That's a bug.
+
+ Ganache encountered an error. Help us fix it by raising a GitHub issue!
Mention the following error information when writing your ticket, and please include as much information as possible. Sorry about that!
+
+
+
+
+
+ )
+ }
+}
+
+function _getLastNLogLines(maxLines, logs) {
+ let firstLogTime = logs.lines[0].time.getTime()
+ return logs.lines
+ .slice(maxLines)
+ .map(v => `T+${v.time.getTime() - firstLogTime}ms: ${v.line}`)
+ .join('\n')
+}
+
+
+export default connect(BugModal)
diff --git a/src/Components/AppShell/BugModal.scss b/src/Components/AppShell/BugModal.scss
new file mode 100644
index 000000000..92c5155e6
--- /dev/null
+++ b/src/Components/AppShell/BugModal.scss
@@ -0,0 +1,18 @@
+.Modal {
+ &.BugModal {
+ .Bug {
+ textarea {
+ min-height: 5rem; /* Overwrite Modal textarea styles */
+ max-height: 5rem;
+ background-color: var(--app-button-primary-disabled-border-color);
+ width: 100%;
+ margin-bottom: 1rem;
+ }
+
+ svg {
+ width: 192px;
+ height: 192px;
+ }
+ }
+ }
+}
diff --git a/src/Components/Helpers/sanitize.js b/src/Components/Helpers/sanitize.js
new file mode 100644
index 000000000..a42e7ebd8
--- /dev/null
+++ b/src/Components/Helpers/sanitize.js
@@ -0,0 +1,23 @@
+
+const { app } = require('electron').remote
+
+// return a sanitized error string from an Error object or string which contains an error message
+export function sanitizeError(errorUnsanitized) {
+ return sanitizePaths(errorUnsanitized.stack || errorUnsanitized)
+}
+
+// Remove any user-specific paths in exception messages
+export function sanitizePaths (message) {
+ // Prepare our paths so we *always* will get a match no matter
+ // path separator (oddly, on Windows, different errors will give
+ // us different path separators)
+ var appPath = app.getAppPath().replace(/\\/g, "/")
+
+ // I couldn't figure out the regex, so a loop will do.
+ while (message.indexOf(appPath) >= 0) {
+ message = message.replace(appPath, "")
+ }
+
+ return message
+}
+
diff --git a/src/chain.js b/src/chain.js
index 4eae6df41..b0709a764 100644
--- a/src/chain.js
+++ b/src/chain.js
@@ -1,5 +1,5 @@
#!/usr/bin/env node
-var TestRPC = require("ethereumjs-testrpc")
+var ganacheLib = require("ganache-cli")
var path = require("path")
var Web3 = require("web3")
@@ -41,7 +41,7 @@ function startServer(options) {
}
}
- server = TestRPC.server(options);
+ server = ganacheLib.server(options);
// We'll also log all methods that aren't marked internal by Ganache
var oldSendAsync = server.provider.sendAsync.bind(server.provider)
diff --git a/src/index.js b/src/index.js
index 644b464e5..6edda2cb2 100644
--- a/src/index.js
+++ b/src/index.js
@@ -54,6 +54,7 @@ const stylesheets = [
"./Components/FirstRun/FirstRunScreen.scss",
"./Components/AppShell/AppShell.scss",
"./Components/AppShell/TopNavbar.scss",
+ "./Components/AppShell/BugModal.scss",
"./Components/Accounts/AccountsScreen.scss",
"./Components/Accounts/AccountList.scss",
"./Components/Accounts/KeyModal.scss",