diff --git a/app/components/Onboarding/BtcPayServer.js b/app/components/Onboarding/BtcPayServer.js
new file mode 100644
index 00000000..3221f62a
--- /dev/null
+++ b/app/components/Onboarding/BtcPayServer.js
@@ -0,0 +1,58 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './BtcPayServer.scss'
+
+const BtcPayServer = ({
+ connectionString,
+ connectionStringIsValid,
+ setConnectionString,
+ startLndHostError
+}) => (
+
+)
+
+BtcPayServer.propTypes = {
+ connectionString: PropTypes.string.isRequired,
+ connectionStringIsValid: PropTypes.bool.isRequired,
+ setConnectionString: PropTypes.func.isRequired,
+ startLndHostError: PropTypes.string
+}
+
+export default BtcPayServer
diff --git a/app/components/Onboarding/BtcPayServer.scss b/app/components/Onboarding/BtcPayServer.scss
new file mode 100644
index 00000000..964ee3e1
--- /dev/null
+++ b/app/components/Onboarding/BtcPayServer.scss
@@ -0,0 +1,58 @@
+@import '../../styles/variables.scss';
+
+.container {
+ color: $white;
+
+ .input {
+ margin-bottom: 15px;
+ }
+
+ label {
+ display: block;
+ font-size: 12px;
+ line-height: 14px;
+ padding-bottom: 5px;
+ min-height: 14px;
+ }
+
+ textarea {
+ background: transparent;
+ outline: none;
+ border: 1px solid #404040;
+ border-radius: 4px;
+ padding: 10px;
+ color: $gold;
+ -webkit-text-fill-color: $white;
+ font-size: 14px;
+ width: 95%;
+ transition: all 0.25s;
+
+ &.error {
+ border: 1px solid $red;
+ }
+ }
+
+ textarea::-webkit-input-placeholder {
+ text-shadow: none;
+ -webkit-text-fill-color: initial;
+ }
+
+ .description {
+ margin-top: 8px;
+ font-size: 12px;
+ line-height: 18px;
+ opacity: 0.5;
+ }
+
+ .errorMessage {
+ margin-top: 8px;
+ font-size: 12px;
+ line-height: 18px;
+ color: $red;
+ display: none;
+
+ &.visible {
+ display: block;
+ }
+ }
+}
diff --git a/app/components/Onboarding/ConnectionConfirm.js b/app/components/Onboarding/ConnectionConfirm.js
new file mode 100644
index 00000000..939d137e
--- /dev/null
+++ b/app/components/Onboarding/ConnectionConfirm.js
@@ -0,0 +1,21 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import styles from './ConnectionConfirm.scss'
+
+const ConnectionConfirm = ({ connectionHost }) => (
+
+
+ Are you sure you want to connect to{' '}
+ {connectionHost.split(':')[0]}?{' '}
+
+
+ Please check the hostname carefully.
+
+
+)
+
+ConnectionConfirm.propTypes = {
+ connectionHost: PropTypes.string.isRequired
+}
+
+export default ConnectionConfirm
diff --git a/app/components/Onboarding/ConnectionConfirm.scss b/app/components/Onboarding/ConnectionConfirm.scss
new file mode 100644
index 00000000..dd1d54d8
--- /dev/null
+++ b/app/components/Onboarding/ConnectionConfirm.scss
@@ -0,0 +1,17 @@
+@import '../../styles/variables.scss';
+
+.container {
+ color: $white;
+
+ p {
+ margin-bottom: 20px;
+ }
+
+ strong {
+ font-weight: bold;
+ }
+
+ .host {
+ color: $green;
+ }
+}
diff --git a/app/components/Onboarding/ConnectionType.js b/app/components/Onboarding/ConnectionType.js
index 620e8619..334d88cf 100644
--- a/app/components/Onboarding/ConnectionType.js
+++ b/app/components/Onboarding/ConnectionType.js
@@ -18,6 +18,12 @@ const ConnectionType = ({ connectionType, setConnectionType }) => (
Custom
+
+ setConnectionType('btcpayserver')}>
+ {connectionType === 'btcpayserver' ? : }
+ BTCPay Server
+
+
)
diff --git a/app/components/Onboarding/ConnectionType.scss b/app/components/Onboarding/ConnectionType.scss
index ad820ba8..e94d994d 100644
--- a/app/components/Onboarding/ConnectionType.scss
+++ b/app/components/Onboarding/ConnectionType.scss
@@ -10,7 +10,7 @@
.button {
width: 150px;
text-align: center;
- display: inline-block;
+ display: flex;
padding: 20px;
border: 1px solid $white;
border-radius: 5px;
diff --git a/app/components/Onboarding/Onboarding.js b/app/components/Onboarding/Onboarding.js
index 1da47371..2fa4209c 100644
--- a/app/components/Onboarding/Onboarding.js
+++ b/app/components/Onboarding/Onboarding.js
@@ -6,6 +6,8 @@ import LoadingBolt from 'components/LoadingBolt'
import FormContainer from './FormContainer'
import ConnectionType from './ConnectionType'
import ConnectionDetails from './ConnectionDetails'
+import ConnectionConfirm from './ConnectionConfirm'
+import BtcPayServer from './BtcPayServer'
import Alias from './Alias'
import Autopilot from './Autopilot'
import Login from './Login'
@@ -19,7 +21,9 @@ import styles from './Onboarding.scss'
const Onboarding = ({
onboarding: {
step,
+ previousStep,
connectionType,
+ connectionString,
connectionHost,
connectionCert,
connectionMacaroon,
@@ -32,6 +36,7 @@ const Onboarding = ({
},
connectionTypeProps,
connectionDetailProps,
+ connectionConfirmProps,
changeStep,
startLnd,
submitNewWallet,
@@ -55,7 +60,18 @@ const Onboarding = ({
use Zap to control a remote node if you desire (for advanced users).
"
back={null}
- next={() => changeStep(connectionType === 'local' ? 1 : 0.2)}
+ next={() => {
+ switch (connectionType) {
+ case 'custom':
+ changeStep(0.2)
+ break
+ case 'btcpayserver':
+ changeStep(0.3)
+ break
+ default:
+ changeStep(1)
+ }
+ }}
>
@@ -67,16 +83,55 @@ const Onboarding = ({
title="Connection details"
description="Enter the connection details for your Lightning node."
back={() => changeStep(0.1)}
- next={() =>
+ next={() => {
+ // dont allow the user to move on if we don't at least have a hostname.
+ if (!connectionDetailProps.connectionHostIsValid) {
+ return
+ }
+
+ changeStep(0.4)
+ }}
+ >
+
+
+ )
+
+ case 0.3:
+ return (
+ changeStep(0.1)}
+ next={() => {
+ // dont allow the user to move on if the connection string is invalid.
+ if (!connectionDetailProps.connectionStringIsValid) {
+ return
+ }
+
+ changeStep(0.4)
+ }}
+ >
+
+
+ )
+
+ case 0.4:
+ return (
+ changeStep(previousStep)}
+ next={() => {
startLnd({
type: connectionType,
+ string: connectionString,
host: connectionHost,
cert: connectionCert,
macaroon: connectionMacaroon
})
- }
+ }}
>
-
+
)
@@ -224,6 +279,7 @@ Onboarding.propTypes = {
onboarding: PropTypes.object.isRequired,
connectionTypeProps: PropTypes.object.isRequired,
connectionDetailProps: PropTypes.object.isRequired,
+ connectionConfirmProps: PropTypes.object.isRequired,
aliasProps: PropTypes.object.isRequired,
autopilotProps: PropTypes.object.isRequired,
initWalletProps: PropTypes.object.isRequired,
diff --git a/app/containers/Root.js b/app/containers/Root.js
index c04206dd..2eaddd13 100644
--- a/app/containers/Root.js
+++ b/app/containers/Root.js
@@ -9,6 +9,7 @@ import Onboarding from '../components/Onboarding'
import Syncing from '../components/Onboarding/Syncing'
import {
setConnectionType,
+ setConnectionString,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
@@ -35,6 +36,7 @@ import Routes from '../routes'
const mapDispatchToProps = {
setConnectionType,
+ setConnectionString,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
@@ -68,7 +70,9 @@ const mapStateToProps = state => ({
showCreateWalletPasswordConfirmationError: onboardingSelectors.showCreateWalletPasswordConfirmationError(
state
),
- reEnterSeedChecker: onboardingSelectors.reEnterSeedChecker(state)
+ reEnterSeedChecker: onboardingSelectors.reEnterSeedChecker(state),
+ connectionStringIsValid: onboardingSelectors.connectionStringIsValid(state),
+ connectionHostIsValid: onboardingSelectors.connectionHostIsValid(state)
})
const mergeProps = (stateProps, dispatchProps, ownProps) => {
@@ -87,9 +91,13 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
}
const connectionDetailProps = {
+ connectionHostIsValid: stateProps.connectionHostIsValid,
+ connectionStringIsValid: stateProps.connectionStringIsValid,
+ connectionString: stateProps.onboarding.connectionString,
connectionHost: stateProps.onboarding.connectionHost,
connectionCert: stateProps.onboarding.connectionCert,
connectionMacaroon: stateProps.onboarding.connectionMacaroon,
+ setConnectionString: dispatchProps.setConnectionString,
setConnectionHost: dispatchProps.setConnectionHost,
setConnectionCert: dispatchProps.setConnectionCert,
setConnectionMacaroon: dispatchProps.setConnectionMacaroon,
@@ -98,6 +106,10 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
startLndMacaroonError: stateProps.onboarding.startLndMacaroonError
}
+ const connectionConfirmProps = {
+ connectionHost: stateProps.onboarding.connectionHost
+ }
+
const aliasProps = {
updateAlias: dispatchProps.updateAlias,
alias: stateProps.onboarding.alias
@@ -165,6 +177,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
submitNewWallet: dispatchProps.submitNewWallet,
connectionTypeProps,
connectionDetailProps,
+ connectionConfirmProps,
aliasProps,
autopilotProps,
initWalletProps,
diff --git a/app/lnd/config/index.js b/app/lnd/config/index.js
index d494977b..0fd58a74 100644
--- a/app/lnd/config/index.js
+++ b/app/lnd/config/index.js
@@ -58,12 +58,18 @@ if (process.env.NODE_ENV === 'development') {
}
export default {
- lnd: () => ({
- lndPath,
- configPath: join(appRootPath, 'resources', 'lnd.conf'),
- rpcProtoPath: join(appRootPath, 'resources', 'rpc.proto'),
- host: store.get('host') || 'localhost:10009',
- cert: store.get('cert') || join(userInfo().homedir, loc),
- macaroon: store.get('macaroon') || join(userInfo().homedir, macaroonPath)
- })
+ lnd: () => {
+ const cert = store.get('cert')
+ const host = store.get('host')
+ const macaroon = store.get('macaroon')
+
+ return {
+ lndPath,
+ configPath: join(appRootPath, 'resources', 'lnd.conf'),
+ rpcProtoPath: join(appRootPath, 'resources', 'rpc.proto'),
+ host: typeof host === 'undefined' ? 'localhost:10009' : host,
+ cert: typeof cert === 'undefined' ? join(userInfo().homedir, loc) : cert,
+ macaroon: typeof macaroon === 'undefined' ? join(userInfo().homedir, macaroonPath) : macaroon
+ }
+ }
}
diff --git a/app/lnd/lib/lightning.js b/app/lnd/lib/lightning.js
index ff46de3b..4fcc3ee4 100644
--- a/app/lnd/lib/lightning.js
+++ b/app/lnd/lib/lightning.js
@@ -16,7 +16,12 @@ process.env.GRPC_SSL_CIPHER_SUITES =
'ECDHE-ECDSA-AES128-GCM-SHA256',
'ECDHE-ECDSA-AES256-GCM-SHA384',
'ECDHE-ECDSA-AES128-CBC-SHA256',
- 'ECDHE-ECDSA-CHACHA20-POLY1305'
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
+
+ // BTCPay Server serves lnd behind an nginx proxy with a trusted SSL cert from Lets Encrypt.
+ // These certs use an RSA TLS cipher suite.
+ 'ECDHE-RSA-AES256-GCM-SHA384',
+ 'ECDHE-RSA-AES128-GCM-SHA256'
].join(':')
/**
diff --git a/app/lnd/lib/util.js b/app/lnd/lib/util.js
index 42540a81..381939cb 100644
--- a/app/lnd/lib/util.js
+++ b/app/lnd/lib/util.js
@@ -3,6 +3,7 @@ import fs from 'fs'
import axios from 'axios'
import { promisify } from 'util'
import { lookup } from 'ps-node'
+import path from 'path'
import grpc from 'grpc'
import isIP from 'validator/lib/isIP'
import isPort from 'validator/lib/isPort'
@@ -102,12 +103,14 @@ export const validateHost = async host => {
* @returns {grpc.ChanelCredentials}
*/
export const createSslCreds = async certPath => {
- const lndCert = await fsReadFile(certPath).catch(e => {
- const error = new Error(`SSL cert path could not be accessed: ${e.message}`)
- error.code = 'LND_GRPC_CERT_ERROR'
- throw error
- })
-
+ let lndCert
+ if (certPath) {
+ lndCert = await fsReadFile(certPath).catch(e => {
+ const error = new Error(`SSL cert path could not be accessed: ${e.message}`)
+ error.code = 'LND_GRPC_CERT_ERROR'
+ throw error
+ })
+ }
return grpc.credentials.createSsl(lndCert)
}
@@ -117,14 +120,19 @@ export const createSslCreds = async certPath => {
* @returns {grpc.CallCredentials}
*/
export const createMacaroonCreds = async macaroonPath => {
- const macaroon = await fsReadFile(macaroonPath).catch(e => {
- const error = new Error(`Macaroon path could not be accessed: ${e.message}`)
- error.code = 'LND_GRPC_MACAROON_ERROR'
- throw error
- })
-
const metadata = new grpc.Metadata()
- metadata.add('macaroon', macaroon.toString('hex'))
+
+ // If it's not a filepath, then assume it is a hex encoded string.
+ if (macaroonPath === path.basename(macaroonPath)) {
+ metadata.add('macaroon', macaroonPath)
+ } else {
+ const macaroon = await fsReadFile(macaroonPath).catch(e => {
+ const error = new Error(`Macaroon path could not be accessed: ${e.message}`)
+ error.code = 'LND_GRPC_MACAROON_ERROR'
+ throw error
+ })
+ metadata.add('macaroon', macaroon.toString('hex'))
+ }
return grpc.credentials.createFromMetadataGenerator((params, callback) =>
callback(null, metadata)
diff --git a/app/package.json b/app/package.json
index d7ae30db..15ba687d 100644
--- a/app/package.json
+++ b/app/package.json
@@ -14,7 +14,7 @@
},
"license": "MIT",
"dependencies": {
- "grpc": "^1.12.4",
+ "grpc": "^1.13.0",
"ps-node": "^0.1.6",
"react-icons": "^2.2.5"
}
diff --git a/app/reducers/onboarding.js b/app/reducers/onboarding.js
index 4efb96ff..8280a0e7 100644
--- a/app/reducers/onboarding.js
+++ b/app/reducers/onboarding.js
@@ -1,6 +1,7 @@
import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import Store from 'electron-store'
+import get from 'lodash.get'
const store = new Store({ name: 'connection' })
@@ -8,6 +9,7 @@ const store = new Store({ name: 'connection' })
// Constants
// ------------------------------------
export const SET_CONNECTION_TYPE = 'SET_CONNECTION_TYPE'
+export const SET_CONNECTION_STRING = 'SET_CONNECTION_STRING'
export const SET_CONNECTION_HOST = 'SET_CONNECTION_HOST'
export const SET_CONNECTION_CERT = 'SET_CONNECTION_CERT'
export const SET_CONNECTION_MACAROON = 'SET_CONNECTION_MACAROON'
@@ -45,14 +47,47 @@ export const SET_UNLOCK_WALLET_ERROR = 'SET_UNLOCK_WALLET_ERROR'
export const SET_SIGNUP_CREATE = 'SET_SIGNUP_CREATE'
export const SET_SIGNUP_IMPORT = 'SET_SIGNUP_IMPORT'
+// ------------------------------------
+// Helpers
+// ------------------------------------
+function prettyPrint(json) {
+ try {
+ return JSON.stringify(JSON.parse(json), undefined, 4)
+ } catch (e) {
+ return json
+ }
+}
+
// ------------------------------------
// Actions
// ------------------------------------
-export function setConnectionType(connectionType) {
- return {
+export const setConnectionType = connectionType => (dispatch, getState) => {
+ const previousType = connectionTypeSelector(getState())
+
+ // When changing the connection type clear out existing config.
+ if (previousType !== connectionType) {
+ dispatch(setConnectionString(''))
+ dispatch(setConnectionHost(''))
+ dispatch(setConnectionCert(''))
+ dispatch(setConnectionMacaroon(''))
+ dispatch(setStartLndError({}))
+ }
+
+ dispatch({
type: SET_CONNECTION_TYPE,
connectionType
- }
+ })
+}
+
+export const setConnectionString = connectionString => (dispatch, getState) => {
+ dispatch({
+ type: SET_CONNECTION_STRING,
+ connectionString: prettyPrint(connectionString)
+ })
+ const { host, port, macaroon } = onboardingSelectors.connectionStringParamsSelector(getState())
+ dispatch(setConnectionHost([host, port].join(':')))
+ dispatch(setConnectionMacaroon(macaroon))
+ dispatch(setConnectionCert(''))
}
export function setConnectionHost(connectionHost) {
@@ -142,6 +177,13 @@ export function changeStep(step) {
}
}
+export function setStartLndError(errors) {
+ return {
+ type: SET_START_LND_ERROR,
+ errors
+ }
+}
+
export function startLnd(options) {
// once the user submits the data needed to start LND we will alert the app that it should start LND
ipcRenderer.send('startLnd', options)
@@ -191,8 +233,18 @@ export const startOnboarding = () => dispatch => {
}
// Listener for errors connecting to LND gRPC
-export const startLndError = (event, errors) => dispatch => {
- dispatch({ type: SET_START_LND_ERROR, errors })
+export const startLndError = (event, errors) => (dispatch, getState) => {
+ dispatch(setStartLndError(errors))
+ const connectionType = connectionTypeSelector(getState())
+
+ switch (connectionType) {
+ case 'custom':
+ dispatch({ type: CHANGE_STEP, step: 0.2 })
+ break
+ case 'btcpayserver':
+ dispatch({ type: CHANGE_STEP, step: 0.3 })
+ break
+ }
}
// Listener from after the LND walletUnlocker has started
@@ -242,6 +294,7 @@ export const unlockWalletError = () => dispatch => {
// ------------------------------------
const ACTION_HANDLERS = {
[SET_CONNECTION_TYPE]: (state, { connectionType }) => ({ ...state, connectionType }),
+ [SET_CONNECTION_STRING]: (state, { connectionString }) => ({ ...state, connectionString }),
[SET_CONNECTION_HOST]: (state, { connectionHost }) => ({ ...state, connectionHost }),
[SET_CONNECTION_CERT]: (state, { connectionCert }) => ({ ...state, connectionCert }),
[SET_CONNECTION_MACAROON]: (state, { connectionMacaroon }) => ({ ...state, connectionMacaroon }),
@@ -272,7 +325,7 @@ const ACTION_HANDLERS = {
[SET_SEED]: (state, { seed }) => ({ ...state, seed, fetchingSeed: false }),
[SET_RE_ENTER_SEED_INDEXES]: (state, { seedIndexesArr }) => ({ ...state, seedIndexesArr }),
- [CHANGE_STEP]: (state, { step }) => ({ ...state, step }),
+ [CHANGE_STEP]: (state, { step }) => ({ ...state, step, previousStep: state.step }),
[ONBOARDING_STARTED]: state => ({ ...state, onboarded: false }),
[ONBOARDING_FINISHED]: state => ({ ...state, onboarded: true }),
@@ -305,6 +358,9 @@ const ACTION_HANDLERS = {
[SET_SIGNUP_IMPORT]: state => ({ ...state, signupForm: { create: false, import: true } })
}
+// ------------------------------------
+// Selector
+// ------------------------------------
const onboardingSelectors = {}
const passwordSelector = state => state.onboarding.password
@@ -316,6 +372,10 @@ const seedSelector = state => state.onboarding.seed
const seedIndexesArrSelector = state => state.onboarding.seedIndexesArr
const reEnterSeedInputSelector = state => state.onboarding.reEnterSeedInput
+const connectionStringSelector = state => state.onboarding.connectionString
+const connectionTypeSelector = state => state.onboarding.connectionType
+const connectionHostSelector = state => state.onboarding.connectionHost
+
onboardingSelectors.passwordIsValid = createSelector(
passwordSelector,
password => password.length >= 8
@@ -344,6 +404,36 @@ onboardingSelectors.reEnterSeedChecker = createSelector(
)
)
+onboardingSelectors.connectionHostIsValid = createSelector(
+ connectionHostSelector,
+ connectionHost => {
+ return connectionHost.length > 0
+ }
+)
+
+onboardingSelectors.connectionStringParamsSelector = createSelector(
+ connectionStringSelector,
+ connectionString => {
+ let config = {}
+ try {
+ config = JSON.parse(connectionString)
+ } catch (e) {
+ return {}
+ }
+
+ const configurations = get(config, 'configurations', [])
+ return configurations.find(c => c.type === 'grpc' && c.cryptoCode === 'BTC') || {}
+ }
+)
+
+onboardingSelectors.connectionStringIsValid = createSelector(
+ onboardingSelectors.connectionStringParamsSelector,
+ connectionStringParams => {
+ const { host, port, macaroon } = connectionStringParams
+ return Boolean(host && port && macaroon)
+ }
+)
+
export { onboardingSelectors }
// ------------------------------------
@@ -353,6 +443,7 @@ const initialState = {
onboarded: false,
step: 0.1,
connectionType: store.get('type', 'local'),
+ connectionString: store.get('string', ''),
connectionHost: store.get('host', ''),
connectionCert: store.get('cert', ''),
connectionMacaroon: store.get('macaroon', ''),
diff --git a/app/yarn.lock b/app/yarn.lock
index 5ce8646c..5c8af1df 100644
--- a/app/yarn.lock
+++ b/app/yarn.lock
@@ -171,9 +171,9 @@ glob@^7.0.5:
once "^1.3.0"
path-is-absolute "^1.0.0"
-grpc@^1.12.4:
- version "1.12.4"
- resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.12.4.tgz#85a3bc26dbf61fb8555d182aec42c1ab6b303ecd"
+grpc@^1.13.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.13.0.tgz#cbf884fa5e072edecb15ff019483db74b361e2c6"
dependencies:
lodash "^4.17.5"
nan "^2.0.0"
diff --git a/app/zap.js b/app/zap.js
index 8e9abc77..7618da63 100644
--- a/app/zap.js
+++ b/app/zap.js
@@ -201,21 +201,21 @@ class ZapController {
// Save the options.
const store = new Store({ name: 'connection' })
store.store = cleanOptions
- mainLog.info('Saved lnd config to:', store.path)
+ mainLog.info('Saved lnd config to %s: %o', store.path, store.store)
// If the requested connection type is a local one then start up a new lnd instance.
if (cleanOptions.type === 'local') {
mainLog.info('Starting new lnd instance')
- mainLog.debug(' > alias:', cleanOptions.alias)
- mainLog.debug(' > autopilot:', cleanOptions.autopilot)
+ mainLog.info(' > alias:', cleanOptions.alias)
+ mainLog.info(' > autopilot:', cleanOptions.autopilot)
this.startLnd(cleanOptions.alias, cleanOptions.autopilot)
}
// Otherwise attempt to connect to an lnd instance using user supplied connection details.
else {
mainLog.info('Connecting to custom lnd instance')
- mainLog.debug(' > host:', cleanOptions.host)
- mainLog.debug(' > cert:', cleanOptions.cert)
- mainLog.debug(' > macaroon:', cleanOptions.macaroon)
+ mainLog.info(' > host:', cleanOptions.host)
+ mainLog.info(' > cert:', cleanOptions.cert)
+ mainLog.info(' > macaroon:', cleanOptions.macaroon)
this.startGrpc()
.then(() => this.sendMessage('successfullyCreatedWallet'))
.catch(e => {