diff --git a/app/components/Onboarding/Alias/Alias.js b/app/components/Onboarding/Alias/Alias.js
deleted file mode 100644
index 500176c9..00000000
--- a/app/components/Onboarding/Alias/Alias.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import styles from './Alias.scss'
-
-const Alias = ({ alias, updateAlias }) => (
-
- input && input.focus()}
- value={alias}
- onChange={event => updateAlias(event.target.value)}
- />
-
-)
-
-Alias.propTypes = {
- alias: PropTypes.string.isRequired,
- updateAlias: PropTypes.func.isRequired
-}
-
-export default Alias
diff --git a/app/components/Onboarding/Alias/Alias.scss b/app/components/Onboarding/Alias/Alias.scss
deleted file mode 100644
index fb096d6a..00000000
--- a/app/components/Onboarding/Alias/Alias.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-@import 'styles/variables.scss';
-
-.alias {
- background: transparent;
- outline: none;
- border: 1px solid #404040;
- border-radius: 4px;
- padding: 15px;
- color: var(--lightningOrange);
- -webkit-text-fill-color: var(--primaryText);
- font-size: 22px;
-}
-
-.alias::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
-}
diff --git a/app/components/Onboarding/Alias/index.js b/app/components/Onboarding/Alias/index.js
deleted file mode 100644
index d0cfd152..00000000
--- a/app/components/Onboarding/Alias/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Alias from './Alias'
-
-export default Alias
diff --git a/app/components/Onboarding/Autopilot/Autopilot.js b/app/components/Onboarding/Autopilot/Autopilot.js
deleted file mode 100644
index f139376b..00000000
--- a/app/components/Onboarding/Autopilot/Autopilot.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import FaCircle from 'react-icons/lib/fa/circle'
-import FaCircleThin from 'react-icons/lib/fa/circle-thin'
-import { FormattedMessage } from 'react-intl'
-import messages from './messages'
-import styles from './Autopilot.scss'
-
-const Autopilot = ({ autopilot, setAutopilot }) => (
-
-
- setAutopilot(true)}>
- {autopilot ? : }
-
-
-
-
-
-
- setAutopilot(false)}>
- {!autopilot && autopilot !== null ? : }
-
-
-
-
-
-
-)
-
-Autopilot.propTypes = {
- autopilot: PropTypes.bool,
- setAutopilot: PropTypes.func.isRequired
-}
-
-export default Autopilot
diff --git a/app/components/Onboarding/Autopilot/Autopilot.scss b/app/components/Onboarding/Autopilot/Autopilot.scss
deleted file mode 100644
index 639d8552..00000000
--- a/app/components/Onboarding/Autopilot/Autopilot.scss
+++ /dev/null
@@ -1,53 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- section {
- margin-bottom: 0;
-
- &.enable {
- &.active {
- div {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div:hover {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- &.disable {
- &.active {
- div {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div:hover {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div {
- width: 30%;
- text-align: center;
- display: flex;
- padding: 20px;
- border: 1px solid var(--primaryText);
- border-radius: 5px;
- cursor: pointer;
- transition: all 0.25s;
- margin: 15px 20px 10px 0;
- }
-
- .label {
- margin-left: 15px;
- }
- }
-}
diff --git a/app/components/Onboarding/Autopilot/index.js b/app/components/Onboarding/Autopilot/index.js
deleted file mode 100644
index 576d33b8..00000000
--- a/app/components/Onboarding/Autopilot/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Autopilot from './Autopilot'
-
-export default Autopilot
diff --git a/app/components/Onboarding/Autopilot/messages.js b/app/components/Onboarding/Autopilot/messages.js
deleted file mode 100644
index 3866f377..00000000
--- a/app/components/Onboarding/Autopilot/messages.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- enable: 'Enable Autopilot',
- disable: 'Disable Autopilot'
-})
diff --git a/app/components/Onboarding/BtcPayServer/BtcPayServer.js b/app/components/Onboarding/BtcPayServer/BtcPayServer.js
deleted file mode 100644
index 10697551..00000000
--- a/app/components/Onboarding/BtcPayServer/BtcPayServer.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-
-import { FormattedMessage, injectIntl } from 'react-intl'
-import messages from './messages'
-
-import styles from './BtcPayServer.scss'
-
-const BtcPayServer = ({
- connectionString,
- connectionStringIsValid,
- setConnectionString,
- startLndHostError,
- intl
-}) => (
-
-)
-
-BtcPayServer.propTypes = {
- connectionString: PropTypes.string.isRequired,
- connectionStringIsValid: PropTypes.bool.isRequired,
- setConnectionString: PropTypes.func.isRequired,
- startLndHostError: PropTypes.string
-}
-
-export default injectIntl(BtcPayServer)
diff --git a/app/components/Onboarding/BtcPayServer/BtcPayServer.scss b/app/components/Onboarding/BtcPayServer/BtcPayServer.scss
deleted file mode 100644
index 07c31726..00000000
--- a/app/components/Onboarding/BtcPayServer/BtcPayServer.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- .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: var(--lightningOrange);
- -webkit-text-fill-color: var(--primaryText);
- font-size: 14px;
- width: 95%;
- transition: all 0.25s;
-
- &.error {
- border: 1px solid var(--superRed);
- }
- }
-
- 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: var(--superRed);
- display: none;
-
- &.visible {
- display: block;
- }
- }
-}
diff --git a/app/components/Onboarding/BtcPayServer/index.js b/app/components/Onboarding/BtcPayServer/index.js
deleted file mode 100644
index 582f7754..00000000
--- a/app/components/Onboarding/BtcPayServer/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import BtcPayServer from './BtcPayServer'
-
-export default BtcPayServer
diff --git a/app/components/Onboarding/BtcPayServer/messages.js b/app/components/Onboarding/BtcPayServer/messages.js
deleted file mode 100644
index 43b6be2b..00000000
--- a/app/components/Onboarding/BtcPayServer/messages.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- btcpay_description:
- "Paste the full content of your BTCPay Server connection config file. This can be found by clicking the link entitled 'Click here to open the configuration file' in your BTCPay Server gRPC settings.",
- btcpay_error: 'Invalid connection string.',
- connection_string_label: 'Connection String',
- connection_string_placeholder: 'BTCPay Server Connection String'
-})
diff --git a/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.js b/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.js
deleted file mode 100644
index fd5547f1..00000000
--- a/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { FormattedMessage } from 'react-intl'
-import messages from './messages'
-import styles from './ConnectionConfirm.scss'
-
-const ConnectionConfirm = ({ connectionHost }) => (
-
-
- {' '}
- {connectionHost.split(':')[0]}?{' '}
-
-
-
-
-
-)
-
-ConnectionConfirm.propTypes = {
- connectionHost: PropTypes.string.isRequired
-}
-
-export default ConnectionConfirm
diff --git a/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.scss b/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.scss
deleted file mode 100644
index 8884545d..00000000
--- a/app/components/Onboarding/ConnectionConfirm/ConnectionConfirm.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- h2 {
- font-size: 16px;
- margin-bottom: 20px;
- font-weight: 300;
- }
-
- .host {
- color: var(--superGreen);
- }
-}
diff --git a/app/components/Onboarding/ConnectionConfirm/index.js b/app/components/Onboarding/ConnectionConfirm/index.js
deleted file mode 100644
index fe5c15d3..00000000
--- a/app/components/Onboarding/ConnectionConfirm/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import ConnectionConfirm from './ConnectionConfirm'
-
-export default ConnectionConfirm
diff --git a/app/components/Onboarding/ConnectionConfirm/messages.js b/app/components/Onboarding/ConnectionConfirm/messages.js
deleted file mode 100644
index 311938f0..00000000
--- a/app/components/Onboarding/ConnectionConfirm/messages.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- verify_host_title: 'Are you sure you want to connect to',
- verify_host_description: 'Please check the hostname carefully.'
-})
diff --git a/app/components/Onboarding/ConnectionDetails/ConnectionDetails.js b/app/components/Onboarding/ConnectionDetails/ConnectionDetails.js
deleted file mode 100644
index 34098581..00000000
--- a/app/components/Onboarding/ConnectionDetails/ConnectionDetails.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { FormattedMessage } from 'react-intl'
-import messages from './messages'
-import styles from './ConnectionDetails.scss'
-
-const ConnectionDetails = ({
- connectionHost,
- connectionCert,
- connectionMacaroon,
- setConnectionHost,
- setConnectionCert,
- setConnectionMacaroon,
- startLndHostError,
- startLndCertError,
- startLndMacaroonError
-}) => (
-
-)
-
-ConnectionDetails.propTypes = {
- connectionHost: PropTypes.string.isRequired,
- connectionCert: PropTypes.string.isRequired,
- connectionMacaroon: PropTypes.string.isRequired,
- setConnectionHost: PropTypes.func.isRequired,
- setConnectionCert: PropTypes.func.isRequired,
- setConnectionMacaroon: PropTypes.func.isRequired,
- startLndHostError: PropTypes.string,
- startLndCertError: PropTypes.string,
- startLndMacaroonError: PropTypes.string
-}
-
-export default ConnectionDetails
diff --git a/app/components/Onboarding/ConnectionDetails/ConnectionDetails.scss b/app/components/Onboarding/ConnectionDetails/ConnectionDetails.scss
deleted file mode 100644
index f4aa0af8..00000000
--- a/app/components/Onboarding/ConnectionDetails/ConnectionDetails.scss
+++ /dev/null
@@ -1,57 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- .input {
- margin-bottom: 10px;
- }
-
- label {
- display: block;
- font-size: 14px;
- line-height: 18px;
- margin-bottom: 5px;
- }
-
- input {
- background: transparent;
- outline: none;
- border: 1px solid var(--primaryText);
- border-radius: 4px;
- padding: 8px;
- color: var(--lightningOrange);
- -webkit-text-fill-color: var(--primaryText);
- font-size: 18px;
- font-weight: 400;
- width: 600px;
- transition: all 0.25s;
- margin-bottom: 5px;
-
- &.error {
- border: 1px solid var(--superRed);
- }
- }
-
- input::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
- }
-
- .description {
- font-size: 12px;
- line-height: 18px;
- opacity: 0.5;
- }
-
- .errorMessage {
- font-size: 12px;
- line-height: 18px;
- color: var(--superRed);
- display: none;
-
- &.visible {
- display: block;
- }
- }
-}
diff --git a/app/components/Onboarding/ConnectionDetails/index.js b/app/components/Onboarding/ConnectionDetails/index.js
deleted file mode 100644
index 780beb4e..00000000
--- a/app/components/Onboarding/ConnectionDetails/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import ConnectionDetails from './ConnectionDetails'
-
-export default ConnectionDetails
diff --git a/app/components/Onboarding/ConnectionDetails/messages.js b/app/components/Onboarding/ConnectionDetails/messages.js
deleted file mode 100644
index 26426f76..00000000
--- a/app/components/Onboarding/ConnectionDetails/messages.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- hostname_title: 'Host',
- hostname_description: 'Hostname and port of the Lnd gRPC interface. Example: localhost:10009',
- cert_title: 'TLS Certificate',
- cert_description: 'Path to the lnd tls cert. Example: /path/to/tls.cert',
- macaroon_description: 'Path to the lnd macaroon file. Example: /path/to/admin.macaroon'
-})
diff --git a/app/components/Onboarding/ConnectionType/ConnectionType.js b/app/components/Onboarding/ConnectionType/ConnectionType.js
deleted file mode 100644
index c5ce4535..00000000
--- a/app/components/Onboarding/ConnectionType/ConnectionType.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import FaCircle from 'react-icons/lib/fa/circle'
-import FaCircleThin from 'react-icons/lib/fa/circle-thin'
-import { FormattedMessage } from 'react-intl'
-import messages from './messages'
-import styles from './ConnectionType.scss'
-
-const ConnectionType = ({ connectionType, setConnectionType }) => (
-
-
- setConnectionType('local')}>
- {connectionType === 'local' ? : }
-
- {' '}
- testnet
-
-
-
-
-
- (testnet )
-
-
-
- setConnectionType('custom')}>
- {connectionType === 'custom' ? : }
-
-
-
-
-
-
-
-
-
- setConnectionType('btcpayserver')}>
- {connectionType === 'btcpayserver' ? : }
- BTCPay Server
-
-
-
-
-
-
-)
-
-ConnectionType.propTypes = {
- connectionType: PropTypes.string.isRequired,
- setConnectionType: PropTypes.func.isRequired
-}
-
-export default ConnectionType
diff --git a/app/components/Onboarding/ConnectionType/ConnectionType.scss b/app/components/Onboarding/ConnectionType/ConnectionType.scss
deleted file mode 100644
index cad6b1d1..00000000
--- a/app/components/Onboarding/ConnectionType/ConnectionType.scss
+++ /dev/null
@@ -1,61 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- section {
- margin: 0;
- display: flex;
- align-items: center;
- line-height: 20px;
- font-size: 16px;
-
- .description {
- width: 80%;
- // opacity: 0.25;
- transition: all 0.25s;
- }
-
- &:hover .description {
- opacity: 0.5;
- }
-
- .button {
- width: 30%;
- text-align: center;
- display: flex;
- padding: 20px;
- border: 1px solid var(--primaryText);
- border-radius: 5px;
- cursor: pointer;
- transition: all 0.25s;
- margin: 15px 20px 10px 0;
- }
-
- &.active {
- .button {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
-
- .description {
- opacity: 0.8;
- color: var(--lightningOrange);
- }
- }
-
- .button:hover {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
-
- .label {
- margin-left: 15px;
- }
-
- .superscript {
- vertical-align: super;
- font-size: 10px;
- }
- }
-}
diff --git a/app/components/Onboarding/ConnectionType/index.js b/app/components/Onboarding/ConnectionType/index.js
deleted file mode 100644
index 904ab309..00000000
--- a/app/components/Onboarding/ConnectionType/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import ConnectionType from './ConnectionType'
-
-export default ConnectionType
diff --git a/app/components/Onboarding/ConnectionType/messages.js b/app/components/Onboarding/ConnectionType/messages.js
deleted file mode 100644
index 37c2f6c5..00000000
--- a/app/components/Onboarding/ConnectionType/messages.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- default: 'Default',
- default_description:
- 'By selecting the default mode we will do everything for you. Just click and go!',
- only: 'only',
- custom: 'Custom',
- custom_description:
- 'Connect to your own node. You will need to provide your own connection settings so this is for advanced users only.',
- btcpay_description:
- 'Connect to your own BTCPay Server instance to access your BTCPay Server wallet.'
-})
diff --git a/app/components/Onboarding/FormContainer/FormContainer.js b/app/components/Onboarding/FormContainer/FormContainer.js
deleted file mode 100644
index a21a2c79..00000000
--- a/app/components/Onboarding/FormContainer/FormContainer.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { shell } from 'electron'
-import React from 'react'
-import PropTypes from 'prop-types'
-import { FormattedMessage } from 'react-intl'
-import FaAngleLeft from 'react-icons/lib/fa/angle-left'
-import FaAngleRight from 'react-icons/lib/fa/angle-right'
-import ZapLogo from 'components/Icon/ZapLogo'
-import Button from 'components/UI/Button'
-import messages from './messages'
-import styles from './FormContainer.scss'
-
-const FormContainer = ({ title, description, back, next, children, theme }) => (
-
-
-
-
-
{title}
-
{description}
-
-
-
{children}
-
-
-
-)
-
-FormContainer.propTypes = {
- title: PropTypes.object.isRequired,
- description: PropTypes.object.isRequired,
- theme: PropTypes.string.isRequired,
-
- back: PropTypes.func,
- next: PropTypes.func,
-
- children: PropTypes.object.isRequired
-}
-
-export default FormContainer
diff --git a/app/components/Onboarding/FormContainer/FormContainer.scss b/app/components/Onboarding/FormContainer/FormContainer.scss
deleted file mode 100644
index 4607e98b..00000000
--- a/app/components/Onboarding/FormContainer/FormContainer.scss
+++ /dev/null
@@ -1,64 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- position: relative;
- height: 100vh;
- background: var(--tertiaryColor);
-}
-
-.header {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- padding: 40px 40px 20px 40px;
- color: var(--primaryText);
-
- .help {
- text-decoration: underline;
- cursor: pointer;
- transition: all 0.25s;
-
- &:hover {
- opacity: 0.5;
- }
- }
-}
-
-.info {
- color: var(--primaryText);
- margin-bottom: 20px;
- padding: 10px 40px 20px;
- height: 16vh;
-
- h1 {
- font-size: 22px;
- margin-bottom: 10px;
- }
-
- p {
- font-size: 12px;
- line-height: 1.5;
- width: 70%;
- }
-}
-
-.content {
- position: relative;
- background: var(--primaryColor);
- height: 100vh;
- padding: 20px 40px;
-}
-
-.footer {
- position: absolute;
- bottom: 0;
- padding: 25px 40px;
- color: var(--primaryText);
- width: 100%;
-
- .buttonsContainer {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
-}
diff --git a/app/components/Onboarding/FormContainer/index.js b/app/components/Onboarding/FormContainer/index.js
deleted file mode 100644
index 8007e06d..00000000
--- a/app/components/Onboarding/FormContainer/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import FormContainer from './FormContainer'
-
-export default FormContainer
diff --git a/app/components/Onboarding/FormContainer/messages.js b/app/components/Onboarding/FormContainer/messages.js
deleted file mode 100644
index 24618442..00000000
--- a/app/components/Onboarding/FormContainer/messages.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- help: 'Need Help?',
- next: 'Next',
- back: 'back'
-})
diff --git a/app/components/Onboarding/InitWallet/InitWallet.js b/app/components/Onboarding/InitWallet/InitWallet.js
deleted file mode 100644
index dccbd4a0..00000000
--- a/app/components/Onboarding/InitWallet/InitWallet.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import Signup from 'components/Onboarding/Signup'
-import Login from 'components/Onboarding/Login'
-import styles from './InitWallet.scss'
-
-const InitWallet = ({ hasSeed, loginProps, signupProps }) => (
-
- {hasSeed ? : }
-
-)
-
-InitWallet.propTypes = {
- hasSeed: PropTypes.bool.isRequired,
- loginProps: PropTypes.object.isRequired,
- signupProps: PropTypes.object.isRequired
-}
-
-export default InitWallet
diff --git a/app/components/Onboarding/InitWallet/InitWallet.scss b/app/components/Onboarding/InitWallet/InitWallet.scss
deleted file mode 100644
index e69de29b..00000000
diff --git a/app/components/Onboarding/InitWallet/index.js b/app/components/Onboarding/InitWallet/index.js
deleted file mode 100644
index 1c0a98e0..00000000
--- a/app/components/Onboarding/InitWallet/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import InitWallet from './InitWallet'
-
-export default InitWallet
diff --git a/app/components/Onboarding/Login/Login.js b/app/components/Onboarding/Login/Login.js
deleted file mode 100644
index 8e343956..00000000
--- a/app/components/Onboarding/Login/Login.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { FormattedMessage, injectIntl } from 'react-intl'
-import Button from 'components/UI/Button'
-import messages from './messages'
-import styles from './Login.scss'
-
-const Login = ({
- password,
- passwordIsValid,
- updatePassword,
- unlockingWallet,
- unlockWallet,
- unlockWalletError,
- intl
-}) => (
-
-
input && input.focus()}
- value={password}
- onChange={event => updatePassword(event.target.value)}
- onKeyPress={event => {
- if (event.key === 'Enter') {
- unlockWallet(password)
- }
- }}
- />
-
- {unlockWalletError.message}
-
-
-
-
-
-
-)
-
-Login.propTypes = {
- password: PropTypes.string.isRequired,
- passwordIsValid: PropTypes.bool.isRequired,
- updatePassword: PropTypes.func.isRequired,
- unlockingWallet: PropTypes.bool.isRequired,
- unlockWallet: PropTypes.func.isRequired,
- unlockWalletError: PropTypes.object.isRequired
-}
-
-export default injectIntl(Login)
diff --git a/app/components/Onboarding/Login/Login.scss b/app/components/Onboarding/Login/Login.scss
deleted file mode 100644
index a3383082..00000000
--- a/app/components/Onboarding/Login/Login.scss
+++ /dev/null
@@ -1,44 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- position: relative;
-}
-
-.password {
- background: transparent;
- outline: none;
- border: 1px solid #404040;
- border-radius: 4px;
- padding: 15px;
- color: var(--lightningOrange);
- -webkit-text-fill-color: var(--primaryText);
- font-size: 22px;
- transition: all 0.25s;
-
- &.inputError {
- border: 1px solid var(--superRed);
- }
-}
-
-.password::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
-}
-
-.error {
- margin-top: 20px;
- height: 20px;
- color: var(--superRed);
- visibility: hidden;
- font-size: 12px;
- transition: all 0.25s;
-
- &.active {
- visibility: visible;
- }
-}
-
-.buttons {
- margin-top: 15%;
- text-align: center;
-}
diff --git a/app/components/Onboarding/Login/index.js b/app/components/Onboarding/Login/index.js
deleted file mode 100644
index 393a6df4..00000000
--- a/app/components/Onboarding/Login/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Login from './Login'
-
-export default Login
diff --git a/app/components/Onboarding/Login/messages.js b/app/components/Onboarding/Login/messages.js
deleted file mode 100644
index 93223933..00000000
--- a/app/components/Onboarding/Login/messages.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- password_placeholder: 'Password',
- unlock: 'Unlock',
- unlocking: 'Unlocking'
-})
diff --git a/app/components/Onboarding/NewWalletPassword/NewWalletPassword.js b/app/components/Onboarding/NewWalletPassword/NewWalletPassword.js
deleted file mode 100644
index 5f0d9e0a..00000000
--- a/app/components/Onboarding/NewWalletPassword/NewWalletPassword.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { FormattedMessage, injectIntl } from 'react-intl'
-import messages from './messages'
-import styles from './NewWalletPassword.scss'
-
-const NewWalletPassword = ({
- createWalletPassword,
- createWalletPasswordConfirmation,
- showCreateWalletPasswordConfirmationError,
- passwordMinCharsError,
- updateCreateWalletPassword,
- updateCreateWalletPasswordConfirmation,
- intl
-}) => (
-
-)
-
-NewWalletPassword.propTypes = {
- createWalletPassword: PropTypes.string.isRequired,
- createWalletPasswordConfirmation: PropTypes.string.isRequired,
- showCreateWalletPasswordConfirmationError: PropTypes.bool.isRequired,
- passwordMinCharsError: PropTypes.bool.isRequired,
- updateCreateWalletPassword: PropTypes.func.isRequired,
- updateCreateWalletPasswordConfirmation: PropTypes.func.isRequired
-}
-
-export default injectIntl(NewWalletPassword)
diff --git a/app/components/Onboarding/NewWalletPassword/NewWalletPassword.scss b/app/components/Onboarding/NewWalletPassword/NewWalletPassword.scss
deleted file mode 100644
index 192fc0fa..00000000
--- a/app/components/Onboarding/NewWalletPassword/NewWalletPassword.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-@import 'styles/variables.scss';
-
-.input:nth-child(2) {
- margin-top: 30px;
-}
-
-.password {
- background: transparent;
- outline: none;
- border: 1px solid var(--primaryText);
- border-radius: 4px;
- padding: 15px;
- color: var(--lightningOrange);
- -webkit-text-fill-color: var(--primaryText);
- font-size: 22px;
- transition: all 0.25s;
-
- &.error {
- border: 1px solid var(--superRed);
- }
-}
-
-.password::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
-}
-
-.errorMessage {
- color: var(--superRed);
- margin-top: 10px;
- font-size: 10px;
- visibility: hidden;
-
- &.visible {
- visibility: visible;
- }
-}
-
-.helpMessage {
- color: var(--primaryText);
- opacity: 0.87;
- padding-top: 10px;
- font-size: 14px;
-
- &.red {
- color: var(--superRed);
- }
-}
diff --git a/app/components/Onboarding/NewWalletPassword/index.js b/app/components/Onboarding/NewWalletPassword/index.js
deleted file mode 100644
index fa9aa5d7..00000000
--- a/app/components/Onboarding/NewWalletPassword/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import NewWalletPassword from './NewWalletPassword'
-
-export default NewWalletPassword
diff --git a/app/components/Onboarding/NewWalletPassword/messages.js b/app/components/Onboarding/NewWalletPassword/messages.js
deleted file mode 100644
index 6b39edd5..00000000
--- a/app/components/Onboarding/NewWalletPassword/messages.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- password_placeholder: 'Password',
- password_confirm_placeholder: 'Confirm Password',
- password_error_match: 'Passwords do not match',
- password_error_length: 'Password must be at least {passwordMinLength} characters long',
- unlock: 'Unlock'
-})
diff --git a/app/components/Onboarding/NewWalletSeed/NewWalletSeed.js b/app/components/Onboarding/NewWalletSeed/NewWalletSeed.js
deleted file mode 100644
index 568b9a2f..00000000
--- a/app/components/Onboarding/NewWalletSeed/NewWalletSeed.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import styles from './NewWalletSeed.scss'
-
-const NewWalletSeed = ({ seed }) => (
-
-
- {seed.map((word, index) => (
- -
-
-
-
- ))}
-
-
-)
-
-NewWalletSeed.propTypes = {
- seed: PropTypes.array.isRequired
-}
-
-export default NewWalletSeed
diff --git a/app/components/Onboarding/NewWalletSeed/NewWalletSeed.scss b/app/components/Onboarding/NewWalletSeed/NewWalletSeed.scss
deleted file mode 100644
index 3e2a9ba8..00000000
--- a/app/components/Onboarding/NewWalletSeed/NewWalletSeed.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- font-size: 14px;
- color: var(--primaryText);
- letter-spacing: 1.5px;
-
- li {
- display: inline-block;
- margin: 5px 0;
- width: 25%;
- font-family: 'Courier', courier, sans-serif;
-
- section {
- display: inline-block;
- vertical-align: middle;
- color: var(--primaryText);
-
- &:nth-child(1) {
- width: 15%;
- text-align: center;
- opacity: 0.5;
- }
-
- &:nth-child(2) {
- width: calc(85% - 10px);
- margin: 0 5px;
- }
- }
- }
-}
diff --git a/app/components/Onboarding/NewWalletSeed/index.js b/app/components/Onboarding/NewWalletSeed/index.js
deleted file mode 100644
index a9861ec7..00000000
--- a/app/components/Onboarding/NewWalletSeed/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import NewWalletSeed from './NewWalletSeed'
-
-export default NewWalletSeed
diff --git a/app/components/Onboarding/Onboarding.js b/app/components/Onboarding/Onboarding.js
index a9e0a43a..e3a5c54e 100644
--- a/app/components/Onboarding/Onboarding.js
+++ b/app/components/Onboarding/Onboarding.js
@@ -1,319 +1,297 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Redirect } from 'react-router-dom'
-
import { FormattedMessage } from 'react-intl'
-import { Box } from 'rebass'
+import { Flex, Box } from 'rebass'
+import { Panel, Wizard } from 'components/UI'
+import {
+ Alias,
+ Autopilot,
+ BtcPayServer,
+ ConnectionType,
+ ConnectionDetails,
+ ConnectionConfirm,
+ Login,
+ Password,
+ Recover,
+ SeedConfirm,
+ SeedView,
+ WalletCreate,
+ WalletRecover
+} from './Steps'
import messages from './messages'
-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'
-import Signup from './Signup'
-import RecoverForm from './RecoverForm'
-import NewWalletSeed from './NewWalletSeed'
-import ReEnterSeed from './ReEnterSeed'
-import NewWalletPassword from './NewWalletPassword'
+class Onboarding extends React.Component {
+ static propTypes = {
+ // STATE
+ alias: PropTypes.string,
+ autopilot: PropTypes.bool,
+ connectionType: PropTypes.string,
+ connectionHost: PropTypes.string,
+ connectionCert: PropTypes.string,
+ connectionMacaroon: PropTypes.string,
+ connectionString: PropTypes.string,
+ lndWalletStarted: PropTypes.bool,
+ lndWalletUnlockerStarted: PropTypes.bool,
+ seed: PropTypes.array,
+ startLndHostError: PropTypes.string,
+ startLndCertError: PropTypes.string,
+ startLndMacaroonError: PropTypes.string,
+ onboarded: PropTypes.bool,
+ fetchingSeed: PropTypes.bool,
+ // DISPATCH
+ createNewWallet: PropTypes.func.isRequired,
+ generateSeed: PropTypes.func.isRequired,
+ recoverOldWallet: PropTypes.func.isRequired,
+ resetOnboarding: PropTypes.func.isRequired,
+ setAlias: PropTypes.func.isRequired,
+ setAutopilot: PropTypes.func.isRequired,
+ setConnectionType: PropTypes.func.isRequired,
+ setConnectionHost: PropTypes.func.isRequired,
+ setConnectionCert: PropTypes.func.isRequired,
+ setConnectionMacaroon: PropTypes.func.isRequired,
+ setConnectionString: PropTypes.func.isRequired,
+ setPassword: PropTypes.func.isRequired,
+ startLnd: PropTypes.func.isRequired,
+ stopLnd: PropTypes.func.isRequired
+ }
-const Onboarding = ({
- onboarding: {
- step,
- previousStep,
- connectionType,
- connectionString,
- connectionHost,
- connectionCert,
- connectionMacaroon,
- alias,
- autopilot,
- createWalletPassword,
- seed,
- onboarded
- },
- theme,
- connectionTypeProps,
- connectionDetailProps,
- connectionConfirmProps,
- changeStep,
- startLnd,
- submitNewWallet,
- recoverOldWallet,
- aliasProps,
- initWalletProps,
- autopilotProps,
- recoverFormProps,
- newWalletSeedProps,
- newWalletPasswordProps,
- reEnterSeedProps
-}) => {
- const renderStep = () => {
- switch (step) {
- case 0.1:
- return (
- }
- description={}
- theme={theme}
- back={null}
- next={() => {
- switch (connectionType) {
- case 'custom':
- changeStep(0.2)
- break
- case 'btcpayserver':
- changeStep(0.3)
- break
- default:
- changeStep(1)
- }
- }}
- >
-
-
- )
+ componentWillUnmount() {
+ const { resetOnboarding } = this.props
+ resetOnboarding()
+ }
- case 0.2:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(0.1)}
- next={() => {
- // dont allow the user to move on if we don't at least have a hostname.
- if (!connectionDetailProps.connectionHostIsValid) {
- return
- }
+ /**
+ * Dynamically generte form steps to use in the onboarding Wizzard.
+ * @return {[Wizzard.Step]} A list of WizardSteps.
+ */
+ getSteps = () => {
+ const {
+ // STATE
+ alias,
+ autopilot,
+ connectionType,
+ connectionHost,
+ connectionCert,
+ connectionMacaroon,
+ connectionString,
+ lndWalletStarted,
+ lndWalletUnlockerStarted,
+ seed,
+ startLndHostError,
+ startLndCertError,
+ startLndMacaroonError,
+ unlockWalletError,
+ fetchingSeed,
+ // DISPATCH
+ setAlias,
+ setAutopilot,
+ setConnectionType,
+ setConnectionHost,
+ setConnectionCert,
+ setConnectionMacaroon,
+ setConnectionString,
+ setUnlockWalletError,
+ setPassword,
+ startLnd,
+ validateHost,
+ validateCert,
+ validateMacaroon,
+ generateSeed,
+ resetOnboarding,
+ createNewWallet,
+ recoverOldWallet,
+ stopLnd,
+ unlockWallet
+ } = this.props
- changeStep(0.4)
- }}
- >
-
-
- )
+ let formSteps = []
+ switch (connectionType) {
+ /**
+ * Form steps for create flow.
+ */
+ case 'create':
+ formSteps = [
+ ...formSteps,
+ ,
+ ,
+ ,
+ ,
+ ,
+
+ ]
+ break
- case 0.3:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(0.1)}
- next={() => {
- // dont allow the user to move on if the connection string is invalid.
- if (!connectionDetailProps.connectionStringIsValid) {
- return
- }
+ /**
+ * Form steps for import flow.
+ */
+ case 'import':
+ formSteps = [
+ ...formSteps,
+ ,
+ ,
+ ,
+ ,
+
+ ]
+ break
- changeStep(0.4)
+ /**
+ * Form steps for custom connection flow.
+ */
+ case 'custom':
+ formSteps = [
+
-
-
- )
+ />,
+ ,
+
+ ]
+ break
- case 0.4:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(previousStep)}
- next={() => {
- startLnd({
- type: connectionType,
- string: connectionString,
- host: connectionHost,
- cert: connectionCert,
- macaroon: connectionMacaroon
- })
+ /**
+ * Form steps for BTCPay Server connection flow.
+ */
+ case 'btcpayserver':
+ formSteps = [
+ ,
+
-
-
- )
+ />,
+
+ ]
+ break
+ }
- case 1:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(0.1)}
- next={() => changeStep(2)}
- >
-
-
- )
- case 2:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(1)}
- next={() => startLnd({ type: connectionType, alias, autopilot })}
- >
-
-
- )
- case 3:
- return (
- }
- description={
-
- }
- theme={theme}
- back={null}
- next={null}
- >
-
-
- )
- case 4:
- return (
- }
- description={}
- theme={theme}
- back={null}
- next={() => {
- // dont allow the user to move on if the confirmation password doesnt match the original password
- // if the password is less than 8 characters or empty dont allow users to proceed
- if (
- newWalletPasswordProps.passwordMinCharsError ||
- !newWalletPasswordProps.createWalletPassword ||
- !newWalletPasswordProps.createWalletPasswordConfirmation ||
- newWalletPasswordProps.showCreateWalletPasswordConfirmationError
- ) {
- return
- }
+ const steps = [
+ ,
+ ...formSteps
+ ]
+ return steps
+ }
- changeStep(5)
- }}
- >
-
-
- )
- case 5:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(4)}
- next={() => {
- // require the user to select create wallet or import wallet
- if (
- !initWalletProps.signupProps.signupForm.create &&
- !initWalletProps.signupProps.signupForm.import
- ) {
- return
- }
+ /**
+ * If we have already started the create new wallet process and generated a seed, change the text on the back button
+ * since it will act as a reset button in this case.
+ */
+ getBackButtonText = () => {
+ const { seed } = this.props
+ return seed.length > 0 ? (
+
+ ) : (
+
+ )
+ }
- changeStep(initWalletProps.signupProps.signupForm.create ? 6 : 5.1)
- }}
- >
-
-
- )
- case 5.1:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(5)}
- next={() => {
- const recoverySeed = recoverFormProps.recoverSeedInput.map(input => input.word)
+ /**
+ * If we have already started the create new wallet process and generated a seed, configure the back button to
+ * navigate back to step 1.
+ */
+ getPreviousStep = () => {
+ const { seed } = this.props
+ return seed.length > 0 ? 0 : null
+ }
- recoverOldWallet(createWalletPassword, recoverySeed)
- }}
- >
-
-
- )
- case 6:
- return (
- }
- description={}
- theme={theme}
- back={() => changeStep(5)}
- next={() => changeStep(7)}
- >
-
-
- )
- case 7:
- return (
- }
- description={
-
- }
- theme={theme}
- back={() => changeStep(6)}
- next={() => {
- // don't allow them to move on if they havent re-entered the seed correctly
- if (!reEnterSeedProps.reEnterSeedChecker) {
- return
- }
+ render() {
+ const { connectionType, onboarded } = this.props
+ const steps = this.getSteps()
+ const previousStep = this.getPreviousStep()
+ const backButtonText = this.getBackButtonText()
- submitNewWallet(createWalletPassword, seed)
- }}
- >
-
-
- )
+ if (onboarded) {
+ return
}
- }
- return (
-
- {renderStep()}
- {onboarded && }
-
- )
-}
+ return (
+
+
+
+
+
+
-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,
- newWalletSeedProps: PropTypes.object.isRequired,
- newWalletPasswordProps: PropTypes.object.isRequired,
- recoverFormProps: PropTypes.object.isRequired,
- reEnterSeedProps: PropTypes.object.isRequired,
- changeStep: PropTypes.func.isRequired,
- startLnd: PropTypes.func.isRequired,
- submitNewWallet: PropTypes.func.isRequired,
- recoverOldWallet: PropTypes.func.isRequired
+
+
+
+ {backButtonText}
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
}
export default Onboarding
diff --git a/app/components/Onboarding/ReEnterSeed/ReEnterSeed.js b/app/components/Onboarding/ReEnterSeed/ReEnterSeed.js
deleted file mode 100644
index df602252..00000000
--- a/app/components/Onboarding/ReEnterSeed/ReEnterSeed.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import styles from './ReEnterSeed.scss'
-
-class ReEnterSeed extends React.Component {
- componentWillMount() {
- const { setReEnterSeedIndexes } = this.props
- setReEnterSeedIndexes()
- }
-
- render() {
- const { seed, reEnterSeedInput, updateReEnterSeedInput, seedIndexesArr } = this.props
-
- return (
-
-
- {seedIndexesArr.map(index => (
- -
-
-
-
- ))}
-
-
- )
- }
-}
-
-ReEnterSeed.propTypes = {
- seed: PropTypes.array.isRequired,
- reEnterSeedInput: PropTypes.object.isRequired,
- updateReEnterSeedInput: PropTypes.func.isRequired,
- setReEnterSeedIndexes: PropTypes.func.isRequired,
- seedIndexesArr: PropTypes.array.isRequired
-}
-
-export default ReEnterSeed
diff --git a/app/components/Onboarding/ReEnterSeed/ReEnterSeed.scss b/app/components/Onboarding/ReEnterSeed/ReEnterSeed.scss
deleted file mode 100644
index 6a003e5b..00000000
--- a/app/components/Onboarding/ReEnterSeed/ReEnterSeed.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-@import 'styles/variables.scss';
-
-.seedContainer {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- font-size: 12px;
- margin-top: 10%;
-
- li {
- display: inline-block;
- margin: 10px;
- width: 25%;
- border: 0.2px solid var(--primaryText);
- padding: 5px 10px;
-
- section {
- display: inline-block;
- color: var(--primaryText);
- margin: 0;
-
- &:nth-child(1) {
- text-align: center;
- opacity: 0.5;
- }
- }
- }
-}
-
-.word {
- margin: 0 3px;
- background-color: inherit;
- outline: 0;
- border: none;
- padding: 8px 10px 6px 10px;
- color: var(--primaryText);
- font-family: 'Courier', courier, sans-serif;
- font-size: 14px;
- line-height: 18px;
-
- &.valid {
- color: var(--superGreen);
- }
-
- &.invalid {
- color: var(--superRed);
- }
-}
-
-.word::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
-}
-
-.contentEditable {
- width: 100px;
- background: red;
-}
diff --git a/app/components/Onboarding/ReEnterSeed/index.js b/app/components/Onboarding/ReEnterSeed/index.js
deleted file mode 100644
index cac4ae9b..00000000
--- a/app/components/Onboarding/ReEnterSeed/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import ReEnterSeed from './ReEnterSeed'
-
-export default ReEnterSeed
diff --git a/app/components/Onboarding/RecoverForm/RecoverForm.js b/app/components/Onboarding/RecoverForm/RecoverForm.js
deleted file mode 100644
index 8791c94f..00000000
--- a/app/components/Onboarding/RecoverForm/RecoverForm.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { injectIntl } from 'react-intl'
-import messages from './messages'
-import styles from './RecoverForm.scss'
-
-const RecoverForm = ({ recoverSeedInput, updateRecoverSeedInput, intl }) => (
-
-
- {Array(24)
- .fill('')
- .map((word, index) => (
- -
-
-
-
- ))}
-
-
-)
-
-RecoverForm.propTypes = {
- recoverSeedInput: PropTypes.array.isRequired,
- updateRecoverSeedInput: PropTypes.func.isRequired,
- intl: PropTypes.object.isRequired
-}
-
-export default injectIntl(RecoverForm)
diff --git a/app/components/Onboarding/RecoverForm/RecoverForm.scss b/app/components/Onboarding/RecoverForm/RecoverForm.scss
deleted file mode 100644
index 937722d6..00000000
--- a/app/components/Onboarding/RecoverForm/RecoverForm.scss
+++ /dev/null
@@ -1,60 +0,0 @@
-@import 'styles/variables.scss';
-
-.seedContainer {
- position: relative;
- display: inline-block;
- font-size: 12px;
-
- li {
- display: inline-block;
- margin: 5px 0;
- width: 25%;
-
- section {
- display: inline-block;
- color: var(--primaryText);
- margin: 0;
-
- &:nth-child(1) {
- width: 10%;
- text-align: center;
- opacity: 0.5;
- }
-
- &:nth-child(2) {
- width: calc(90% - 10px);
- margin-right: 10px;
- }
- }
- }
-}
-
-.word {
- margin: 0 3px;
- background-color: var(--primaryText);
- outline: 0;
- border: none;
- padding: 8px 10px 6px 10px;
- color: var(--primaryText);
- font-family: 'Courier', courier, sans-serif;
- font-size: 14px;
- line-height: 18px;
-
- &.valid {
- color: var(--superGreen);
- }
-
- &.invalid {
- color: var(--superRed);
- }
-}
-
-.word::-webkit-input-placeholder {
- text-shadow: none;
- -webkit-text-fill-color: initial;
-}
-
-.contentEditable {
- width: 100px;
- background: red;
-}
diff --git a/app/components/Onboarding/RecoverForm/index.js b/app/components/Onboarding/RecoverForm/index.js
deleted file mode 100644
index ce3c455f..00000000
--- a/app/components/Onboarding/RecoverForm/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import RecoverForm from './RecoverForm'
-
-export default RecoverForm
diff --git a/app/components/Onboarding/RecoverForm/messages.js b/app/components/Onboarding/RecoverForm/messages.js
deleted file mode 100644
index dfcc86bc..00000000
--- a/app/components/Onboarding/RecoverForm/messages.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- word_placeholder: 'word'
-})
diff --git a/app/components/Onboarding/Signup/Signup.js b/app/components/Onboarding/Signup/Signup.js
deleted file mode 100644
index f22ccea6..00000000
--- a/app/components/Onboarding/Signup/Signup.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import FaCircle from 'react-icons/lib/fa/circle'
-import FaCircleThin from 'react-icons/lib/fa/circle-thin'
-import { FormattedMessage } from 'react-intl'
-import messages from './messages'
-import styles from './Signup.scss'
-
-const Signup = ({ signupForm, setSignupCreate, setSignupImport }) => (
-
-
-
- {signupForm.create ? : }
-
-
-
-
-
-
-
- {signupForm.import ? : }
-
-
-
-
-
-
-)
-
-Signup.propTypes = {
- signupForm: PropTypes.object.isRequired,
- setSignupCreate: PropTypes.func.isRequired,
- setSignupImport: PropTypes.func.isRequired
-}
-
-export default Signup
diff --git a/app/components/Onboarding/Signup/Signup.scss b/app/components/Onboarding/Signup/Signup.scss
deleted file mode 100644
index af0126db..00000000
--- a/app/components/Onboarding/Signup/Signup.scss
+++ /dev/null
@@ -1,51 +0,0 @@
-@import 'styles/variables.scss';
-
-.container {
- color: var(--primaryText);
-
- section {
- margin-bottom: 20px;
-
- &.enable {
- &.active {
- div {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div:hover {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- &.disable {
- &.active {
- div {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div:hover {
- color: var(--lightningOrange);
- border-color: var(--lightningOrange);
- }
- }
-
- div {
- width: 30%;
- display: inline-block;
- padding: 20px;
- border: 1px solid var(--primaryText);
- border-radius: 5px;
- cursor: pointer;
- transition: all 0.25s;
- }
-
- .label {
- margin-left: 15px;
- }
- }
-}
diff --git a/app/components/Onboarding/Signup/index.js b/app/components/Onboarding/Signup/index.js
deleted file mode 100644
index 68786149..00000000
--- a/app/components/Onboarding/Signup/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Signup from './Signup'
-
-export default Signup
diff --git a/app/components/Onboarding/Signup/messages.js b/app/components/Onboarding/Signup/messages.js
deleted file mode 100644
index d6d33ea4..00000000
--- a/app/components/Onboarding/Signup/messages.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { defineMessages } from 'react-intl'
-
-/* eslint-disable max-len */
-export default defineMessages({
- signup_create: 'Create new wallet',
- signup_import: 'Import existing wallet'
-})
diff --git a/app/components/Onboarding/Steps/Alias.js b/app/components/Onboarding/Steps/Alias.js
new file mode 100644
index 00000000..3198aeea
--- /dev/null
+++ b/app/components/Onboarding/Steps/Alias.js
@@ -0,0 +1,83 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import { Box } from 'rebass'
+import { Bar, Form, Header, Input } from 'components/UI'
+import messages from './messages'
+
+class Alias extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ alias: PropTypes.string,
+ setAlias: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ alias: ''
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ handleSubmit = values => {
+ const { setAlias } = this.props
+ setAlias(values.alias)
+ }
+
+ render() {
+ const { wizardApi, wizardState, alias, setAlias, intl, ...rest } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(Alias)
diff --git a/app/components/Onboarding/Steps/Autopilot.js b/app/components/Onboarding/Steps/Autopilot.js
new file mode 100644
index 00000000..9f4f0951
--- /dev/null
+++ b/app/components/Onboarding/Steps/Autopilot.js
@@ -0,0 +1,74 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage } from 'react-intl'
+import { Bar, Form, Header, RadioGroup, Radio } from 'components/UI'
+import messages from './messages'
+
+class Autopilot extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ autopilot: PropTypes.bool,
+ setAutopilot: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ autopilot: 'enable'
+ }
+
+ handleSubmit = values => {
+ const { setAutopilot } = this.props
+ setAutopilot(values.autopilot === 'enable' ? true : false)
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const { wizardApi, wizardState, autopilot, setAutopilot, ...rest } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+ return (
+
+ )
+ }
+}
+
+export default Autopilot
diff --git a/app/components/Onboarding/Steps/BtcPayServer.js b/app/components/Onboarding/Steps/BtcPayServer.js
new file mode 100644
index 00000000..945ced75
--- /dev/null
+++ b/app/components/Onboarding/Steps/BtcPayServer.js
@@ -0,0 +1,126 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import get from 'lodash.get'
+import { Bar, Form, Header, TextArea } from 'components/UI'
+import messages from './messages'
+
+class BtcPayServer extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ connectionString: PropTypes.string.isRequired,
+ setConnectionString: PropTypes.func.isRequired,
+ startLndHostError: PropTypes.string
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ componentDidUpdate(prevProps) {
+ const { startLndHostError } = this.props
+ if (startLndHostError && startLndHostError !== prevProps.startLndHostError) {
+ this.formApi.setError('connectionString', startLndHostError)
+ }
+ }
+
+ handleSubmit = values => {
+ const { setConnectionString } = this.props
+ setConnectionString(values.connectionString)
+ }
+
+ handleConnectionStringChange = () => {
+ this.formApi.setError('connectionString', null)
+ }
+
+ validateConnectionString = value => {
+ const { intl } = this.props
+ let config = {}
+ try {
+ config = JSON.parse(value)
+ } catch (e) {
+ return intl.formatMessage({ ...messages.btcpay_error })
+ }
+ const configs = get(config, 'configurations', [])
+ const params = configs.find(c => c.type === 'grpc' && c.cryptoCode === 'BTC') || {}
+ const { host, port, macaroon } = params
+ if (!host || !port || !macaroon) {
+ return intl.formatMessage({ ...messages.btcpay_error })
+ }
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ intl,
+ connectionString,
+ setConnectionString,
+ startLndHostError,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(BtcPayServer)
diff --git a/app/components/Onboarding/Steps/ConnectionConfirm.js b/app/components/Onboarding/Steps/ConnectionConfirm.js
new file mode 100644
index 00000000..0bf1ef78
--- /dev/null
+++ b/app/components/Onboarding/Steps/ConnectionConfirm.js
@@ -0,0 +1,139 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage } from 'react-intl'
+import get from 'lodash.get'
+import { Bar, Form, Header, Span, Text } from 'components/UI'
+import messages from './messages'
+
+const parseConnectionString = value => {
+ let config = {}
+ try {
+ config = JSON.parse(value)
+ } catch (e) {
+ return new Error('Invalid connection string')
+ }
+ const configs = get(config, 'configurations', [])
+ const params = configs.find(c => c.type === 'grpc' && c.cryptoCode === 'BTC') || {}
+ const { host, port, macaroon } = params
+ if (!host || !port || !macaroon) {
+ return new Error('Invalid connection string')
+ }
+ return { host, port, macaroon }
+}
+
+class ConnectionConfirm extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ connectionType: PropTypes.string.isRequired,
+ connectionHost: PropTypes.string,
+ connectionCert: PropTypes.string,
+ connectionMacaroon: PropTypes.string,
+ connectionString: PropTypes.string,
+ startLndHostError: PropTypes.string,
+ startLndCertError: PropTypes.string,
+ startLndMacaroonError: PropTypes.string,
+ startLnd: PropTypes.func.isRequired,
+ lndWalletUnlockerStarted: PropTypes.bool,
+ lndWalletStarted: PropTypes.bool
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ connectionHost: '',
+ connectionCert: '',
+ connectionMacaroon: '',
+ connectionString: '',
+ startLndHostError: '',
+ startLndCertError: '',
+ startLndMacaroonError: ''
+ }
+
+ handleSubmit = async () => {
+ let {
+ connectionType,
+ connectionHost,
+ connectionCert,
+ connectionMacaroon,
+ connectionString,
+ startLnd
+ } = this.props
+ let options = {
+ type: connectionType,
+ host: connectionHost,
+ cert: connectionCert,
+ macaroon: connectionMacaroon
+ }
+ if (connectionString) {
+ const { host, port, macaroon } = parseConnectionString(connectionString)
+ options = { type: connectionType, host: `${host}:${port}`, macaroon }
+ }
+ return startLnd(options)
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ connectionType,
+ connectionHost,
+ connectionCert,
+ connectionMacaroon,
+ connectionString,
+ lndWalletStarted,
+ lndWalletUnlockerStarted,
+ startLndHostError,
+ startLndCertError,
+ startLndMacaroonError,
+ startLnd,
+ ...rest
+ } = this.props
+ const { getApi, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+
+ // Determine the hostname.
+ let hostname = connectionHost.split(':')[0]
+ if (connectionString) {
+ const { host } = parseConnectionString(connectionString)
+ hostname = host
+ }
+
+ return (
+
+ )
+ }
+}
+
+export default ConnectionConfirm
diff --git a/app/components/Onboarding/Steps/ConnectionDetails.js b/app/components/Onboarding/Steps/ConnectionDetails.js
new file mode 100644
index 00000000..a7d9461e
--- /dev/null
+++ b/app/components/Onboarding/Steps/ConnectionDetails.js
@@ -0,0 +1,211 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage } from 'react-intl'
+import { Box } from 'rebass'
+import { Bar, Form, Header, Input } from 'components/UI'
+import messages from './messages'
+
+class ConnectionDetails extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ connectionHost: PropTypes.string,
+ connectionCert: PropTypes.string,
+ connectionMacaroon: PropTypes.string,
+ startLndHostError: PropTypes.string,
+ startLndCertError: PropTypes.string,
+ startLndMacaroonError: PropTypes.string,
+
+ setConnectionHost: PropTypes.func.isRequired,
+ setConnectionCert: PropTypes.func.isRequired,
+ setConnectionMacaroon: PropTypes.func.isRequired,
+ validateHost: PropTypes.func.isRequired,
+ validateCert: PropTypes.func.isRequired,
+ validateMacaroon: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ connectionHost: '',
+ connectionCert: '',
+ connectionMacaroon: '',
+ startLndHostError: '',
+ startLndCertError: '',
+ startLndMacaroonError: ''
+ }
+
+ componentDidMount() {
+ const { startLndHostError, startLndCertError, startLndMacaroonError } = this.props
+ if (startLndHostError) {
+ this.formApi.setError('connectionHost', startLndHostError)
+ }
+ if (startLndCertError) {
+ this.formApi.setError('connectionCert', startLndCertError)
+ }
+ if (startLndMacaroonError) {
+ this.formApi.setError('connectionMacaroon', startLndMacaroonError)
+ }
+ }
+
+ handleConnectionHostChange = () => {
+ const formState = this.formApi.getState()
+ delete formState.asyncErrors.connectionHost
+ this.formApi.setState(formState)
+ }
+
+ handleConnectionCertChange = () => {
+ const formState = this.formApi.getState()
+ delete formState.asyncErrors.connectionCert
+ this.formApi.setState(formState)
+ }
+
+ handleConnectionMacaroonChange = () => {
+ const formState = this.formApi.getState()
+ delete formState.asyncErrors.connectionMacaroon
+ this.formApi.setState(formState)
+ }
+
+ handleSubmit = values => {
+ const { setConnectionHost, setConnectionCert, setConnectionMacaroon } = this.props
+ setConnectionHost(values.connectionHost)
+ setConnectionCert(values.connectionCert)
+ setConnectionMacaroon(values.connectionMacaroon)
+ }
+
+ validateHost = async value => {
+ const { validateHost } = this.props
+ try {
+ await validateHost(value)
+ } catch (e) {
+ return e.toString()
+ }
+ }
+
+ validateCert = async value => {
+ const { validateCert } = this.props
+ try {
+ await validateCert(value)
+ } catch (e) {
+ return e.toString()
+ }
+ }
+
+ validateMacaroon = async value => {
+ const { validateMacaroon } = this.props
+ try {
+ await validateMacaroon(value)
+ } catch (e) {
+ return e.toString()
+ }
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ connectionHost,
+ connectionCert,
+ connectionMacaroon,
+ setConnectionHost,
+ setConnectionCert,
+ setConnectionMacaroon,
+ startLndHostError,
+ startLndCertError,
+ startLndMacaroonError,
+ validateHost,
+ validateCert,
+ validateMacaroon,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+ return (
+
+ )
+ }
+}
+
+export default ConnectionDetails
diff --git a/app/components/Onboarding/Steps/ConnectionType.js b/app/components/Onboarding/Steps/ConnectionType.js
new file mode 100644
index 00000000..962f60a5
--- /dev/null
+++ b/app/components/Onboarding/Steps/ConnectionType.js
@@ -0,0 +1,112 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage } from 'react-intl'
+import { Bar, Form, Header, RadioGroup, Radio } from 'components/UI'
+import messages from './messages'
+
+class ConnectionType extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ resetOnboarding: PropTypes.func.isRequired,
+ setConnectionType: PropTypes.func.isRequired,
+ stopLnd: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ componentDidMount() {
+ const { resetOnboarding, stopLnd } = this.props
+ stopLnd()
+ resetOnboarding()
+ }
+
+ handleSubmit = values => {
+ const { setConnectionType } = this.props
+ setConnectionType(values.connectionType)
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ connectionType,
+ setConnectionType,
+ resetOnboarding,
+ stopLnd,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+ return (
+ <>
+ }
+ subtitle={}
+ align="left"
+ />
+
+
+
+
+ >
+ )
+ }
+}
+
+export default ConnectionType
diff --git a/app/components/Onboarding/Steps/Login.js b/app/components/Onboarding/Steps/Login.js
new file mode 100644
index 00000000..92cd6bdc
--- /dev/null
+++ b/app/components/Onboarding/Steps/Login.js
@@ -0,0 +1,112 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Box } from 'rebass'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import { Bar, Form, Header, PasswordInput } from 'components/UI'
+import messages from './messages'
+
+class Login extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ walletDir: PropTypes.string.isRequired,
+ unlockWalletError: PropTypes.string,
+ setUnlockWalletError: PropTypes.func.isRequired,
+ unlockWallet: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ unlockWalletError: null
+ }
+
+ componentDidUpdate(prevProps) {
+ const { setUnlockWalletError, unlockWalletError } = this.props
+ // Set the form error if we got an error unlocking.
+ if (unlockWalletError && !prevProps.unlockWalletError) {
+ this.formApi.setError('password', unlockWalletError)
+ setUnlockWalletError(null)
+ }
+ }
+
+ handleSubmit = async values => {
+ const { unlockWallet } = this.props
+ await unlockWallet(values.password)
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ walletDir,
+ unlockWallet,
+ unlockWalletError,
+ setUnlockWalletError,
+ intl,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(Login)
diff --git a/app/components/Onboarding/Steps/Password.js b/app/components/Onboarding/Steps/Password.js
new file mode 100644
index 00000000..c71cb74a
--- /dev/null
+++ b/app/components/Onboarding/Steps/Password.js
@@ -0,0 +1,85 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Box } from 'rebass'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import { Bar, Form, Header, PasswordInput } from 'components/UI'
+import messages from './messages'
+
+class Password extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ setPassword: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ handleSubmit = async values => {
+ const { setPassword } = this.props
+ await setPassword(values.password)
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const { wizardApi, wizardState, setPassword, intl, ...rest } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(Password)
diff --git a/app/components/Onboarding/Steps/Recover.js b/app/components/Onboarding/Steps/Recover.js
new file mode 100644
index 00000000..8f057a40
--- /dev/null
+++ b/app/components/Onboarding/Steps/Recover.js
@@ -0,0 +1,105 @@
+/* eslint-disable react/no-multi-comp */
+
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import bip39 from 'bip39-en'
+import { Flex } from 'rebass'
+import { Bar, Form, Header, Input, Label } from 'components/UI'
+import messages from './messages'
+
+class SeedWord extends React.Component {
+ static propTypes = {
+ index: PropTypes.number.isRequired,
+ intl: PropTypes.object.isRequired,
+ word: PropTypes.string
+ }
+
+ validateWord = value => {
+ return !value || !bip39.includes(value) ? 'incorrect' : null
+ }
+
+ render() {
+ const { index, intl, word } = this.props
+ return (
+
+
+
+
+ )
+ }
+}
+
+const SeedWordWithIntl = injectIntl(SeedWord)
+
+class SeedView extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ seed: PropTypes.array.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ render() {
+ const { wizardApi, wizardState, seed, intl, ...rest } = this.props
+ const { getApi, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const indexes = Array.from(Array(24).keys())
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(SeedView)
diff --git a/app/components/Onboarding/Steps/SeedConfirm.js b/app/components/Onboarding/Steps/SeedConfirm.js
new file mode 100644
index 00000000..bf1ee3f7
--- /dev/null
+++ b/app/components/Onboarding/Steps/SeedConfirm.js
@@ -0,0 +1,115 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import { Flex } from 'rebass'
+import { Bar, Form, Header, Input, Label } from 'components/UI'
+import messages from './messages'
+
+class SeedConfirm extends React.Component {
+ state = {
+ seedWordIndexes: []
+ }
+
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ seed: PropTypes.array.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ componentDidMount() {
+ this.generateSeedWordIndexes()
+ }
+
+ generateSeedWordIndexes = () => {
+ const seedWordIndexes = []
+ while (seedWordIndexes.length < 3) {
+ const r = Math.floor(Math.random() * 24) + 1
+ if (seedWordIndexes.indexOf(r) === -1) {
+ seedWordIndexes.push(r)
+ }
+ }
+ this.setState({ seedWordIndexes })
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ validateWord = (index, word) => {
+ const { seed } = this.props
+ return !word || word !== seed[index] ? 'incorrect' : null
+ }
+
+ render() {
+ const { wizardApi, wizardState, seed, intl, ...rest } = this.props
+ const { seedWordIndexes } = this.state
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(SeedConfirm)
diff --git a/app/components/Onboarding/Steps/SeedView.js b/app/components/Onboarding/Steps/SeedView.js
new file mode 100644
index 00000000..fdcd5352
--- /dev/null
+++ b/app/components/Onboarding/Steps/SeedView.js
@@ -0,0 +1,102 @@
+/* eslint-disable react/no-multi-comp */
+import React from 'react'
+import PropTypes from 'prop-types'
+import { FormattedMessage, injectIntl } from 'react-intl'
+import { Flex } from 'rebass'
+import { Bar, Form, Header, Spinner, Text } from 'components/UI'
+import messages from './messages'
+
+const SeedWord = ({ index, word }) => (
+
+
+
+ {index}
+
+ {word}
+
+
+)
+SeedWord.propTypes = {
+ index: PropTypes.number.isRequired,
+ word: PropTypes.string.isRequired
+}
+
+class SeedView extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ seed: PropTypes.array,
+ fetchingSeed: PropTypes.bool,
+ generateSeed: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {},
+ seed: [],
+ fetchingSeed: false
+ }
+
+ async componentDidMount() {
+ const { seed, generateSeed } = this.props
+ if (seed.length === 0) {
+ generateSeed()
+ }
+ }
+
+ render() {
+ const { wizardApi, wizardState, seed, generateSeed, fetchingSeed, intl, ...rest } = this.props
+ const { getApi, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+
+ return (
+
+ )
+ }
+}
+
+export default injectIntl(SeedView)
diff --git a/app/components/Onboarding/Steps/WalletCreate.js b/app/components/Onboarding/Steps/WalletCreate.js
new file mode 100644
index 00000000..f4f3f78a
--- /dev/null
+++ b/app/components/Onboarding/Steps/WalletCreate.js
@@ -0,0 +1,69 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Form, Spinner, Text } from 'components/UI'
+
+class WalletCreate extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ createNewWallet: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ componentDidMount() {
+ this.formApi.submitForm()
+ }
+
+ handleSubmit = () => {
+ const { createNewWallet } = this.props
+ createNewWallet()
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ autopilot,
+ setWalletCreate,
+ createNewWallet,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+ return (
+
+ )
+ }
+}
+
+export default WalletCreate
diff --git a/app/components/Onboarding/Steps/WalletRecover.js b/app/components/Onboarding/Steps/WalletRecover.js
new file mode 100644
index 00000000..7e99600f
--- /dev/null
+++ b/app/components/Onboarding/Steps/WalletRecover.js
@@ -0,0 +1,69 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Form, Spinner, Text } from 'components/UI'
+
+class WalletRecover extends React.Component {
+ static propTypes = {
+ wizardApi: PropTypes.object,
+ wizardState: PropTypes.object,
+ recoverOldWallet: PropTypes.func.isRequired
+ }
+
+ static defaultProps = {
+ wizardApi: {},
+ wizardState: {}
+ }
+
+ componentDidMount() {
+ this.formApi.submitForm()
+ }
+
+ handleSubmit = () => {
+ const { recoverOldWallet } = this.props
+ recoverOldWallet()
+ }
+
+ setFormApi = formApi => {
+ this.formApi = formApi
+ }
+
+ render() {
+ const {
+ wizardApi,
+ wizardState,
+ autopilot,
+ setWalletRecover,
+ recoverOldWallet,
+ ...rest
+ } = this.props
+ const { getApi, onChange, preSubmit, onSubmit, onSubmitFailure } = wizardApi
+ const { currentItem } = wizardState
+ return (
+
+ )
+ }
+}
+
+export default WalletRecover
diff --git a/app/components/Onboarding/Steps/index.js b/app/components/Onboarding/Steps/index.js
new file mode 100644
index 00000000..f7722f0b
--- /dev/null
+++ b/app/components/Onboarding/Steps/index.js
@@ -0,0 +1,13 @@
+export Alias from './Alias'
+export Autopilot from './Autopilot'
+export BtcPayServer from './BtcPayServer'
+export ConnectionConfirm from './ConnectionConfirm'
+export ConnectionDetails from './ConnectionDetails'
+export ConnectionType from './ConnectionType'
+export Login from './Login'
+export Password from './Password'
+export Recover from './Recover'
+export SeedConfirm from './SeedConfirm'
+export SeedView from './SeedView'
+export WalletCreate from './WalletCreate'
+export WalletRecover from './WalletRecover'
diff --git a/app/components/Onboarding/Steps/messages.js b/app/components/Onboarding/Steps/messages.js
new file mode 100644
index 00000000..7ea1865f
--- /dev/null
+++ b/app/components/Onboarding/Steps/messages.js
@@ -0,0 +1,73 @@
+import { defineMessages } from 'react-intl'
+
+/* eslint-disable max-len */
+export default defineMessages({
+ alias_description: 'Set your nickname to help others connect with you on the Lightning Network',
+ alias_title: 'What should we call you?',
+ autopilot_description:
+ 'Autopilot is an automatic network manager. Instead of manually adding people to build your network to make payments, enable autopilot to automatically connect you to the Lightning Network using 60% of your balance.',
+ autopilot_title: 'Autopilot',
+ back: 'back',
+ btcpay_connection_string_description:
+ "Paste the full content of your BTCPay Server connection config file. This can be found by clicking the link entitled 'Click here to open the configuration file' in your BTCPay Server gRPC settings.",
+ btcpay_connection_type_description:
+ 'Connect to your own BTCPay Server instance to access your BTCPay Server wallet.',
+ btcpay_description: 'Enter the connection details for your BTCPay Server node.',
+ btcpay_error: 'Invalid connection string.',
+ btcpay_title: 'Connect to BTCPay Server',
+ cert_description: 'Path to the lnd tls cert. Example: /path/to/tls.cert',
+ cert_title: 'TLS Certificate',
+ confirm_connection_description: 'Confirm the connection details for your Lightning node.',
+ confirm_connection_title: 'Confirm connection',
+ connection_description: 'Let Zap spin up and manage a node for you, or connect to your own node.',
+ connection_details_custom_description: 'Enter the connection details for your Lightning node.',
+ connection_details_custom_title: 'Connection details',
+ connection_string_label: 'Connection String',
+ connection_string_placeholder: 'BTCPay Server Connection String',
+ connection_title: 'How do you want to connect to the Lightning Network?',
+ create_wallet_password_description:
+ 'Looks like you are new here. Set a password to encrypt your wallet. This password will be needed to unlock Zap in the future',
+ create_wallet_password_title: 'Welcome!',
+ custom: 'Custom',
+ custom_description:
+ 'Connect to your own node. You will need to provide your own connection settings so this is for advanced users only.',
+ default: 'Default',
+ default_description:
+ 'By selecting the defualt mode we will do everything for you. Just click and go!',
+ disable: 'Disable Autopilot',
+ enable: 'Enable Autopilot',
+ help: 'Need Help?',
+ hostname_description: 'Hostname and port of the Lnd gRPC interface. Example: localhost:10009',
+ hostname_title: 'Host',
+ import_description: "Recovering a wallet, nice. You don't need anyone else, you got yourself :)",
+ import_title: 'Import your seed',
+ login_description:
+ 'It looks like you already have a wallet (wallet found at: `{walletDir}`). Please enter your wallet password to unlock it.',
+ login_title: 'Welcome back!',
+ macaroon_description: 'Path to the lnd macaroon file. Example: /path/to/admin.macaroon',
+ next: 'Next',
+ nickname: 'Nickname',
+ only: 'only',
+ password_confirm_placeholder: 'Confirm Password',
+ password_error_length: 'Password must be at least {passwordMinLength} characters long',
+ password_error_match: 'Passwords do not match',
+ password_label: 'Password',
+ password_placeholder: 'Enter your password',
+ password_description:
+ 'You would have set your password when first creating your walet. This is separate from your 24 word seed.',
+ retype_seed_description:
+ "Your seed is important! If you lose your seed you'll have no way to recover your wallet. To make sure that you have properly saved your seed, please retype words {word1}, {word2} & {word3}",
+ retype_seed_title: 'Retype your seed',
+ save_seed_description:
+ 'Please save these 24 words securely! This will allow you to recover your wallet in the future',
+ save_seed_title: 'Save your wallet seed',
+ signup_create: 'Create new wallet',
+ signup_description: 'Would you like to create a new wallet or import an existing one?',
+ signup_import: 'Import existing wallet',
+ signup_title: "Alright, let's get set up",
+ unlock: 'Unlock',
+ unlocking: 'Unlocking',
+ verify_host_description: 'Please check the hostname carefully.',
+ verify_host_title: 'Are you sure you want to connect to',
+ word_placeholder: 'word'
+})
diff --git a/app/components/Onboarding/index.js b/app/components/Onboarding/index.js
index cb4cc808..8cae54ac 100644
--- a/app/components/Onboarding/index.js
+++ b/app/components/Onboarding/index.js
@@ -1,3 +1 @@
-import Onboarding from './Onboarding'
-
-export default Onboarding
+export Onboarding from './Onboarding'
diff --git a/app/components/Onboarding/messages.js b/app/components/Onboarding/messages.js
index d7feb033..5dbbbbb8 100644
--- a/app/components/Onboarding/messages.js
+++ b/app/components/Onboarding/messages.js
@@ -2,34 +2,7 @@ import { defineMessages } from 'react-intl'
/* eslint-disable max-len */
export default defineMessages({
- connection_title: 'How do you want to connect to the Lightning Network?',
- connection_description:
- 'By default, Zap will spin up a node for you and handle all the nerdy stuff in the background. However, you can also set up a custom node connection and use Zap to control a remote node if you desire (for advanced users).',
- connection_details_custom_title: 'Connection details',
- connection_details_custom_description: 'Enter the connection details for your Lightning node.',
- btcpay_title: 'BTCPay Server',
- btcpay_description: 'Enter the connection details for your BTCPay Server node.',
- confirm_connection_title: 'Confirm connection',
- confirm_connection_description: 'Confirm the connection details for your Lightning node.',
- alias_title: 'What should we call you?',
- alias_description: 'Set your nickname to help others connect with you on the Lightning Network',
- autopilot_title: 'Autopilot',
- autopilot_description:
- 'Autopilot is an automatic network manager. Instead of manually adding people to build your network to make payments, enable autopilot to automatically connect you to the Lightning Network using 60% of your balance.',
- create_wallet_password_title: 'Welcome!',
- create_wallet_password_description:
- 'Looks like you are new here. Set a password to encrypt your wallet. This password will be needed to unlock Zap in the future',
- signup_title: "Alright, let's get set up",
- signup_description: 'Would you like to create a new wallet or import an existing one?',
- login_title: 'Welcome back!',
- login_description:
- 'It looks like you already have a wallet (wallet found at: `{walletDir}`). Please enter your wallet password to unlock it.',
- import_title: 'Import your seed',
- import_description: "Recovering a wallet, nice. You don't need anyone else, you got yourself :)",
- save_seed_title: 'Save your wallet seed',
- save_seed_description:
- 'Please save these 24 words securely! This will allow you to recover your wallet in the future',
- retype_seed_title: 'Retype your seed',
- retype_seed_description:
- "Your seed is important! If you lose your seed you'll have no way to recover your wallet. To make sure that you have properly saved your seed, please retype words {word1}, {word2} & {word3}"
+ next: 'Next',
+ previous: 'Back',
+ start_over: 'Start over'
})
diff --git a/app/containers/Onboarding.js b/app/containers/Onboarding.js
index 424662f9..9fa115e6 100644
--- a/app/containers/Onboarding.js
+++ b/app/containers/Onboarding.js
@@ -1,186 +1,70 @@
import { connect } from 'react-redux'
-
-import { themeSelectors } from 'reducers/theme'
+import { Onboarding } from 'components/Onboarding'
import {
+ setAlias,
+ setAutopilot,
setConnectionType,
- setConnectionString,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
- updateAlias,
- updatePassword,
- setAutopilot,
- changeStep,
+ setConnectionString,
+ setPassword,
+ setUnlockWalletError,
startLnd,
- createWallet,
- updateCreateWalletPassword,
- updateCreateWalletPasswordConfirmation,
- submitNewWallet,
+ stopLnd,
+ validateHost,
+ validateCert,
+ validateMacaroon,
+ generateSeed,
+ createNewWallet,
recoverOldWallet,
- onboardingSelectors,
- unlockWallet,
- setSignupCreate,
- setSignupImport,
- updateReEnterSeedInput,
- updateRecoverSeedInput,
- setReEnterSeedIndexes
+ resetOnboarding,
+ unlockWallet
} from 'reducers/onboarding'
-import Onboarding from 'components/Onboarding'
+const mapStateToProps = state => ({
+ alias: state.onboarding.alias,
+ autopilot: state.onboarding.autopilot,
+ connectionType: state.onboarding.connectionType,
+ connectionHost: state.onboarding.connectionHost,
+ connectionCert: state.onboarding.connectionCert,
+ connectionMacaroon: state.onboarding.connectionMacaroon,
+ connectionString: state.onboarding.connectionString,
+ lndWalletStarted: state.onboarding.lndWalletStarted,
+ lndWalletUnlockerStarted: state.onboarding.lndWalletUnlockerStarted,
+ startLndHostError: state.onboarding.startLndHostError,
+ startLndCertError: state.onboarding.startLndCertError,
+ startLndMacaroonError: state.onboarding.startLndMacaroonError,
+ seed: state.onboarding.seed,
+ signupMode: state.onboarding.signupMode,
+ unlockWalletError: state.onboarding.unlockWalletError,
+ onboarded: state.onboarding.onboarded,
+ fetchingSeed: state.onboarding.fetchingSeed
+})
const mapDispatchToProps = {
+ setAlias,
+ setAutopilot,
setConnectionType,
- setConnectionString,
setConnectionHost,
setConnectionCert,
setConnectionMacaroon,
- updateAlias,
- updatePassword,
- updateCreateWalletPassword,
- updateCreateWalletPasswordConfirmation,
- setAutopilot,
- changeStep,
+ setConnectionString,
+ setPassword,
+ setUnlockWalletError,
startLnd,
- createWallet,
- submitNewWallet,
+ stopLnd,
+ validateHost,
+ validateCert,
+ validateMacaroon,
+ generateSeed,
+ createNewWallet,
recoverOldWallet,
- unlockWallet,
- setSignupCreate,
- setSignupImport,
- updateReEnterSeedInput,
- updateRecoverSeedInput,
- setReEnterSeedIndexes
-}
-
-const mapStateToProps = state => ({
- currentTheme: themeSelectors.currentTheme(state),
- onboarding: state.onboarding,
- passwordIsValid: onboardingSelectors.passwordIsValid(state),
- passwordMinCharsError: onboardingSelectors.passwordMinCharsError(state),
- showCreateWalletPasswordConfirmationError: onboardingSelectors.showCreateWalletPasswordConfirmationError(
- state
- ),
- reEnterSeedChecker: onboardingSelectors.reEnterSeedChecker(state),
- connectionStringIsValid: onboardingSelectors.connectionStringIsValid(state),
- connectionHostIsValid: onboardingSelectors.connectionHostIsValid(state)
-})
-
-const mergeProps = (stateProps, dispatchProps, ownProps) => {
- const connectionTypeProps = {
- connectionType: stateProps.onboarding.connectionType,
- setConnectionType: dispatchProps.setConnectionType
- }
-
- 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,
- startLndHostError: stateProps.onboarding.startLndHostError,
- startLndCertError: stateProps.onboarding.startLndCertError,
- startLndMacaroonError: stateProps.onboarding.startLndMacaroonError
- }
-
- const connectionConfirmProps = {
- connectionHost: stateProps.onboarding.connectionHost
- }
-
- const aliasProps = {
- updateAlias: dispatchProps.updateAlias,
- alias: stateProps.onboarding.alias
- }
-
- const autopilotProps = {
- autopilot: stateProps.onboarding.autopilot,
- setAutopilot: dispatchProps.setAutopilot
- }
-
- const initWalletProps = {
- hasSeed: stateProps.onboarding.hasSeed,
-
- loginProps: {
- password: stateProps.onboarding.password,
- passwordIsValid: stateProps.passwordIsValid,
- hasSeed: stateProps.onboarding.hasSeed,
- existingWalletDir: stateProps.onboarding.existingWalletDir,
- unlockingWallet: stateProps.onboarding.unlockingWallet,
- unlockWalletError: stateProps.onboarding.unlockWalletError,
-
- updatePassword: dispatchProps.updatePassword,
- createWallet: dispatchProps.createWallet,
- unlockWallet: dispatchProps.unlockWallet
- },
-
- signupProps: {
- signupForm: stateProps.onboarding.signupForm,
-
- setSignupCreate: dispatchProps.setSignupCreate,
- setSignupImport: dispatchProps.setSignupImport
- }
- }
-
- const newWalletSeedProps = {
- seed: stateProps.onboarding.seed
- }
-
- const newWalletPasswordProps = {
- createWalletPassword: stateProps.onboarding.createWalletPassword,
- createWalletPasswordConfirmation: stateProps.onboarding.createWalletPasswordConfirmation,
- showCreateWalletPasswordConfirmationError: stateProps.showCreateWalletPasswordConfirmationError,
- passwordMinCharsError: stateProps.passwordMinCharsError,
- updateCreateWalletPassword: dispatchProps.updateCreateWalletPassword,
- updateCreateWalletPasswordConfirmation: dispatchProps.updateCreateWalletPasswordConfirmation
- }
-
- const recoverFormProps = {
- recoverSeedInput: stateProps.onboarding.recoverSeedInput,
- updateRecoverSeedInput: dispatchProps.updateRecoverSeedInput
- }
-
- const reEnterSeedProps = {
- seed: stateProps.onboarding.seed,
- reEnterSeedInput: stateProps.onboarding.reEnterSeedInput,
- seedIndexesArr: stateProps.onboarding.seedIndexesArr,
- reEnterSeedChecker: stateProps.reEnterSeedChecker,
- updateReEnterSeedInput: dispatchProps.updateReEnterSeedInput,
- setReEnterSeedIndexes: dispatchProps.setReEnterSeedIndexes
- }
-
- const onboardingProps = {
- onboarding: stateProps.onboarding,
- theme: stateProps.currentTheme,
- changeStep: dispatchProps.changeStep,
- startLnd: dispatchProps.startLnd,
- submitNewWallet: dispatchProps.submitNewWallet,
- recoverOldWallet: dispatchProps.recoverOldWallet,
- connectionTypeProps,
- connectionDetailProps,
- connectionConfirmProps,
- aliasProps,
- autopilotProps,
- initWalletProps,
- newWalletSeedProps,
- newWalletPasswordProps,
- recoverFormProps,
- reEnterSeedProps
- }
-
- return {
- ...stateProps,
- ...dispatchProps,
- ...ownProps,
- ...onboardingProps
- }
+ resetOnboarding,
+ unlockWallet
}
export default connect(
mapStateToProps,
- mapDispatchToProps,
- mergeProps
+ mapDispatchToProps
)(Onboarding)
diff --git a/app/lib/lnd/walletUnlockerMethods/index.js b/app/lib/lnd/walletUnlockerMethods/index.js
index 19d2f56b..913a79fa 100644
--- a/app/lib/lnd/walletUnlockerMethods/index.js
+++ b/app/lib/lnd/walletUnlockerMethods/index.js
@@ -25,7 +25,7 @@ export default function(walletUnlocker, log, event, msg, data, lndConfig) {
walletController
.unlockWallet(walletUnlocker, data)
.then(() => event.sender.send('walletUnlocked'))
- .catch(() => event.sender.send('unlockWalletError'))
+ .catch(e => event.sender.send('setUnlockWalletError', e.message))
break
case 'initWallet':
walletController
diff --git a/app/lib/zap/controller.js b/app/lib/zap/controller.js
index fa1ff530..95058ee7 100644
--- a/app/lib/zap/controller.js
+++ b/app/lib/zap/controller.js
@@ -69,11 +69,11 @@ class ZapController {
{ name: 'startOnboarding', from: '*', to: 'onboarding' },
{ name: 'startLocalLnd', from: 'onboarding', to: 'running' },
{ name: 'startRemoteLnd', from: 'onboarding', to: 'connected' },
+ { name: 'stopLnd', from: '*', to: 'onboarding' },
{ name: 'terminate', from: '*', to: 'terminated' }
],
methods: {
onOnboarding: this.onOnboarding.bind(this),
- onStartOnboarding: this.onStartOnboarding.bind(this),
onBeforeStartLocalLnd: this.onBeforeStartLocalLnd.bind(this),
onBeforeStartRemoteLnd: this.onBeforeStartRemoteLnd.bind(this),
onTerminated: this.onTerminated.bind(this),
@@ -134,6 +134,9 @@ class ZapController {
startRemoteLnd(...args: any[]) {
return this.fsm.startRemoteLnd(...args)
}
+ stopLnd(...args: any[]) {
+ return this.fsm.stopLnd(...args)
+ }
terminate(...args: any[]) {
return this.fsm.terminate(...args)
}
@@ -168,14 +171,9 @@ class ZapController {
}
// Give the grpc connections a chance to be properly closed out.
- return new Promise(resolve => setTimeout(resolve, 200))
- }
-
- onStartOnboarding() {
- mainLog.debug('[FSM] onStartOnboarding...')
-
- // Notify the app to start the onboarding process.
- this.sendMessage('startOnboarding')
+ return new Promise(resolve => setTimeout(resolve, 200)).then(() =>
+ this.sendMessage('startOnboarding')
+ )
}
onBeforeStartLocalLnd() {
@@ -195,39 +193,41 @@ class ZapController {
mainLog.info(' > cert:', this.lndConfig.cert)
mainLog.info(' > macaroon:', this.lndConfig.macaroon)
- return this.startLightningWallet()
- .then(() => this.sendMessage('walletConnected'))
- .catch(e => {
- const errors = {}
- // There was a problem connecting to the host.
- if (e.code === 'LND_GRPC_HOST_ERROR') {
- errors.host = e.message
- }
- // There was a problem accessing the ssl cert.
- if (e.code === 'LND_GRPC_CERT_ERROR') {
- errors.cert = e.message
- }
- // There was a problem accessing the macaroon file.
- else if (e.code === 'LND_GRPC_MACAROON_ERROR') {
- errors.macaroon = e.message
- }
- // Other error codes such as UNAVAILABLE most likely indicate that there is a problem with the host.
- else {
- errors.host = `Unable to connect to host: ${e.details || e.message}`
- }
+ return this.startLightningWallet().catch(e => {
+ const errors = {}
+ // There was a problem connecting to the host.
+ if (e.code === 'LND_GRPC_HOST_ERROR') {
+ errors.host = e.message
+ }
+ // There was a problem accessing the ssl cert.
+ if (e.code === 'LND_GRPC_CERT_ERROR') {
+ errors.cert = e.message
+ }
+ // There was a problem accessing the macaroon file.
+ else if (
+ e.code === 'LND_GRPC_MACAROON_ERROR' ||
+ e.message.includes('cannot determine data format of binary-encoded macaroon')
+ ) {
+ errors.macaroon = e.message
+ }
+ // Other error codes such as UNAVAILABLE most likely indicate that there is a problem with the host.
+ else {
+ errors.host = `Unable to connect to host: ${e.details || e.message}`
+ }
- // The `startLightningWallet` call attempts to call the `getInfo` method on the Lightning service in order to
- // verify that it is accessible. If it is not, an error 12 is thrown which is the gRPC code for `UNIMPLEMENTED`
- // which indicates that the requested operation is not implemented or not supported/enabled in the service.
- // See https://github.com/grpc/grpc-node/blob/master/packages/grpc-native-core/src/constants.js#L129
- if (e.code === 12) {
- return this.startWalletUnlocker()
- }
+ // The `startLightningWallet` call attempts to call the `getInfo` method on the Lightning service in order to
+ // verify that it is accessible. If it is not, an error 12 is thrown which is the gRPC code for `UNIMPLEMENTED`
+ // which indicates that the requested operation is not implemented or not supported/enabled in the service.
+ // See https://github.com/grpc/grpc-node/blob/master/packages/grpc-native-core/src/constants.js#L129
+ if (e.code === 12) {
+ this.sendMessage('startLndSuccess')
+ return this.startWalletUnlocker()
+ }
- // Notify the app of errors.
- this.sendMessage('startLndError', errors)
- throw e
- })
+ // Notify the app of errors.
+ this.sendMessage('startLndError', errors)
+ throw e
+ })
}
async onTerminated(lifecycle: any) {
@@ -458,6 +458,7 @@ class ZapController {
return this.startOnboarding()
})
)
+ ipcMain.on('stopLnd', () => this.stopLnd())
}
/**
@@ -465,6 +466,7 @@ class ZapController {
*/
_removeIpcListeners() {
ipcMain.removeAllListeners('startLnd')
+ ipcMain.removeAllListeners('stopLnd')
ipcMain.removeAllListeners('startLightningWallet')
ipcMain.removeAllListeners('walletUnlocker')
ipcMain.removeAllListeners('lnd')
diff --git a/app/reducers/ipc.js b/app/reducers/ipc.js
index 7c5e626c..e6a1dee3 100644
--- a/app/reducers/ipc.js
+++ b/app/reducers/ipc.js
@@ -47,8 +47,7 @@ import {
receiveSeedError,
walletCreated,
walletUnlocked,
- walletConnected,
- unlockWalletError
+ setUnlockWalletError
} from './onboarding'
// Import all receiving IPC event handlers and pass them into createIpc
@@ -119,8 +118,7 @@ const ipc = createIpc({
receiveSeedError,
walletCreated,
walletUnlocked,
- walletConnected,
- unlockWalletError
+ setUnlockWalletError
})
export default ipc
diff --git a/app/reducers/onboarding.js b/app/reducers/onboarding.js
index ca489744..ad331a63 100644
--- a/app/reducers/onboarding.js
+++ b/app/reducers/onboarding.js
@@ -1,7 +1,10 @@
+import crypto from 'crypto'
import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import get from 'lodash.get'
import db from 'store/db'
+import { validateHost as doHostValidation } from 'lib/utils/validateHost'
+import { fileExists } from 'lib/utils/fileExists'
import { fetchInfo } from './info'
import { setError } from './error'
@@ -13,23 +16,14 @@ 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'
-
-export const UPDATE_ALIAS = 'UPDATE_ALIAS'
-export const UPDATE_PASSWORD = 'UPDATE_PASSWORD'
-export const UPDATE_CREATE_WALLET_PASSWORD = 'UPDATE_CREATE_WALLET_PASSWORD'
-export const UPDATE_CREATE_WALLET_PASSWORD_CONFIRMATION =
- 'UPDATE_CREATE_WALLET_PASSWORD_CONFIRMATION'
-export const UPDATE_RE_ENTER_SEED_INPUT = 'UPDATE_RE_ENTER_SEED_INPUT'
-export const UPDATE_RECOVER_SEED_INPUT = 'UPDATE_RECOVER_SEED_INPUT'
-
-export const CHANGE_STEP = 'CHANGE_STEP'
-
+export const SET_ALIAS = 'SET_ALIAS'
export const SET_AUTOPILOT = 'SET_AUTOPILOT'
+export const SET_PASSWORD = 'SET_PASSWORD'
+export const SET_LND_WALLET_UNLOCKER_STARTED = 'SET_LND_WALLET_UNLOCKER_STARTED'
+export const SET_LND_WALLET_STARTED = 'SET_LND_WALLET_STARTED'
export const FETCH_SEED = 'FETCH_SEED'
export const SET_SEED = 'SET_SEED'
-export const SET_HAS_SEED = 'SET_HAS_SEED'
-export const SET_RE_ENTER_SEED_INDEXES = 'SET_RE_ENTER_SEED_INDEXES'
export const ONBOARDING_STARTED = 'ONBOARDING_STARTED'
export const ONBOARDING_FINISHED = 'ONBOARDING_FINISHED'
@@ -38,18 +32,22 @@ export const STARTING_LND = 'STARTING_LND'
export const LND_STARTED = 'LND_STARTED'
export const SET_START_LND_ERROR = 'SET_START_LND_ERROR'
-export const LOADING_EXISTING_WALLET = 'LOADING_EXISTING_WALLET'
+export const STOPPING_LND = 'STOPPING_LND'
+export const LND_STOPPED = 'LND_STOPPED'
+export const LOADING_EXISTING_WALLET = 'LOADING_EXISTING_WALLET'
export const CREATING_NEW_WALLET = 'CREATING_NEW_WALLET'
-
export const RECOVERING_OLD_WALLET = 'RECOVERING_OLD_WALLET'
export const UNLOCKING_WALLET = 'UNLOCKING_WALLET'
export const WALLET_UNLOCKED = 'WALLET_UNLOCKED'
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'
+export const VALIDATING_HOST = 'VALIDATING_HOST'
+export const VALIDATING_CERT = 'VALIDATING_CERT'
+export const VALIDATING_MACAROON = 'VALIDATING_MACAROON'
+
+export const RESET_ONBOARDING = 'RESET_ONBOARDING'
// ------------------------------------
// Helpers
@@ -65,6 +63,11 @@ function prettyPrint(json) {
// ------------------------------------
// Actions
// ------------------------------------
+
+export const resetOnboarding = () => dispatch => {
+ dispatch({ type: SET_SEED, seed: [] })
+}
+
export const setConnectionType = connectionType => async (dispatch, getState) => {
const previousType = connectionTypeSelector(getState())
@@ -75,7 +78,7 @@ export const setConnectionType = connectionType => async (dispatch, getState) =>
dispatch(setConnectionHost(wallet.host || initialState.connectionHost))
dispatch(setConnectionCert(wallet.cert || initialState.connectionCert))
dispatch(setConnectionMacaroon(wallet.macaroon || initialState.connectionMacaroon))
- dispatch(updateAlias(wallet.alias || initialState.alias))
+ dispatch(setAlias(wallet.alias || initialState.alias))
dispatch(setAutopilot(wallet.autopilot || initialState.autopilot))
dispatch(setStartLndError({}))
}
@@ -103,12 +106,14 @@ export function setConnectionHost(connectionHost) {
connectionHost
}
}
+
export function setConnectionCert(connectionCert) {
return {
type: SET_CONNECTION_CERT,
connectionCert
}
}
+
export function setConnectionMacaroon(connectionMacaroon) {
return {
type: SET_CONNECTION_MACAROON,
@@ -116,96 +121,112 @@ export function setConnectionMacaroon(connectionMacaroon) {
}
}
-export function updateAlias(alias) {
+export function setAlias(alias) {
return {
- type: UPDATE_ALIAS,
+ type: SET_ALIAS,
alias
}
}
-export function updatePassword(password) {
- return {
- type: UPDATE_PASSWORD,
- password
- }
-}
-
-export function updateCreateWalletPassword(createWalletPassword) {
- return {
- type: UPDATE_CREATE_WALLET_PASSWORD,
- createWalletPassword
- }
-}
-
-export function updateCreateWalletPasswordConfirmation(createWalletPasswordConfirmation) {
+export function setAutopilot(autopilot) {
return {
- type: UPDATE_CREATE_WALLET_PASSWORD_CONFIRMATION,
- createWalletPasswordConfirmation
+ type: SET_AUTOPILOT,
+ autopilot
}
}
-export function updateReEnterSeedInput(inputSeedObj) {
+export function setPassword(password) {
return {
- type: UPDATE_RE_ENTER_SEED_INPUT,
- inputSeedObj
+ type: SET_PASSWORD,
+ password
}
}
-export function updateRecoverSeedInput(inputSeedObj) {
+export function setLndWalletUnlockerStarted() {
return {
- type: UPDATE_RECOVER_SEED_INPUT,
- inputSeedObj
+ type: SET_LND_WALLET_UNLOCKER_STARTED
}
}
-export function setAutopilot(autopilot) {
+export function setLndWalletStarted() {
return {
- type: SET_AUTOPILOT,
- autopilot
+ type: SET_LND_WALLET_STARTED
}
}
-export function setSignupCreate() {
- return {
- type: SET_SIGNUP_CREATE
+export const validateHost = host => async dispatch => {
+ try {
+ dispatch({ type: VALIDATING_HOST, validatingHost: true })
+ const res = await doHostValidation(host)
+ dispatch({ type: VALIDATING_HOST, validatingHost: false })
+ return res
+ } catch (e) {
+ dispatch({ type: VALIDATING_HOST, validatingHost: false })
+ throw e.message
}
}
-export function setSignupImport() {
- return {
- type: SET_SIGNUP_IMPORT
+export const validateCert = certPath => async dispatch => {
+ try {
+ dispatch({ type: VALIDATING_CERT, validatingCert: true })
+ const res = await fileExists(certPath)
+ dispatch({ type: VALIDATING_CERT, validatingCert: false })
+ return res
+ } catch (e) {
+ dispatch({ type: VALIDATING_CERT, validatingCert: false })
+ if (e.code === 'ENOENT') {
+ e.message = 'no such file or directory'
+ }
+ throw e.message
}
}
-export function changeStep(step) {
- return {
- type: CHANGE_STEP,
- step
+export const validateMacaroon = macaroonPath => async dispatch => {
+ try {
+ dispatch({ type: VALIDATING_MACAROON, validatingMacaroon: true })
+ const res = await fileExists(macaroonPath)
+ dispatch({ type: VALIDATING_MACAROON, validatingMacaroon: false })
+ return res
+ } catch (e) {
+ dispatch({ type: VALIDATING_MACAROON, validatingMacaroon: false })
+ if (e.code === 'ENOENT') {
+ e.message = 'no such file or directory'
+ }
+ throw e.message
}
}
export const startLnd = options => async dispatch => {
- // Attempt to load the wallet settings.
- // TODO: Currently, this only support a single wallet config per type.
- let wallet = await db.wallets.get({ type: options.type })
+ return new Promise((resolve, reject) => {
+ // Tell the main process to start lnd using the supplied connection details.
+ dispatch({ type: STARTING_LND })
+ ipcRenderer.send('startLnd', options)
+
+ ipcRenderer.once('startLndError', error => {
+ ipcRenderer.removeListener('startLndSuccess', resolve)
+ reject(error)
+ })
- // If a wallet was found, merge in our user selected options and update in the db.
- if (wallet) {
- Object.assign(wallet, options)
- await db.wallets.put(wallet)
- }
+ ipcRenderer.once('startLndSuccess', res => {
+ ipcRenderer.removeListener('startLndError', reject)
+ resolve(res)
+ })
+ })
+}
- // Otherwise, save the new wallet config.
- else {
- const id = await db.wallets.put(options)
- wallet = Object.assign(options, { id })
+// Listener for errors connecting to LND gRPC
+export const startLndError = (event, errors) => (dispatch, getState) => {
+ const connectionType = connectionTypeSelector(getState())
+ switch (connectionType) {
+ case 'custom':
+ dispatch(setStartLndError(errors))
+ break
+ case 'btcpayserver':
+ dispatch(setStartLndError(errors))
+ break
+ default:
+ dispatch(setError(errors))
}
-
- // Tell the main process to start lnd using the supplied connection details.
- ipcRenderer.send('startLnd', wallet)
-
- // Update the store.
- dispatch({ type: STARTING_LND })
}
export const lndStarted = () => async dispatch => {
@@ -219,35 +240,130 @@ export function setStartLndError(errors) {
}
}
-export function setReEnterSeedIndexes() {
- // we only want the user to have to verify 3 random indexes from the seed they were just given
- const INDEX_AMOUNT = 3
+export const stopLnd = () => async dispatch => {
+ dispatch({ type: STOPPING_LND })
+ ipcRenderer.send('stopLnd')
+}
+
+export const lndStopped = () => async dispatch => {
+ dispatch({ type: LND_STOPPED })
+}
+
+export const generateSeed = () => async dispatch => {
+ dispatch({ type: FETCH_SEED })
+ ipcRenderer.send('startLnd', {
+ id: `tmp`,
+ type: 'local',
+ chain: 'bitcoin',
+ network: 'testnet'
+ })
+}
- const seedIndexesArr = []
- while (seedIndexesArr.length < INDEX_AMOUNT) {
- // add 1 because we dont want this to be 0 index based
- const ranNum = Math.floor(Math.random() * 24) + 1
+export const createNewWallet = () => (dispatch, getState) => {
+ crypto.randomBytes(16, async (err, buffer) => {
+ const state = getState().onboarding
- if (seedIndexesArr.indexOf(ranNum) > -1) {
- continue
+ // Define the wallet config.
+ const wallet = {
+ id: buffer.toString('hex'),
+ type: 'local',
+ chain: 'bitcoin',
+ network: 'testnet',
+ settings: {
+ autopilot: state.autopilot,
+ alias: state.alias
+ }
}
- seedIndexesArr[seedIndexesArr.length] = ranNum
- }
+ // Save the wallet config.
+ await db.wallets.put(wallet)
- return {
- type: SET_RE_ENTER_SEED_INDEXES,
- seedIndexesArr
+ // Start Lnd and trigger the wallet to be initialised as soon as the wallet unlocker is available.
+ dispatch({ type: CREATING_NEW_WALLET })
+ ipcRenderer.send('startLnd', wallet)
+ })
+}
+
+export const recoverOldWallet = () => dispatch => {
+ crypto.randomBytes(16, function(err, buffer) {
+ const id = buffer.toString('hex')
+
+ dispatch({ type: RECOVERING_OLD_WALLET })
+ ipcRenderer.send('startLnd', {
+ id,
+ type: 'local',
+ chain: 'bitcoin',
+ network: 'testnet'
+ })
+ })
+}
+
+export const startActiveWallet = () => async dispatch => {
+ const activeWallet = await db.settings.get({ key: 'activeWallet' })
+ if (activeWallet) {
+ const wallet = await db.wallets.get({ id: activeWallet.value })
+ if (wallet) {
+ dispatch(startLnd(wallet))
+ }
}
}
+export const unlockWallet = password => async dispatch => {
+ dispatch({ type: UNLOCKING_WALLET })
+ ipcRenderer.send('walletUnlocker', {
+ msg: 'unlockWallet',
+ data: { wallet_password: password }
+ })
+}
+
/**
* As soon as we have an active connection to a WalletUnlocker service, attempt to generate a new seed which kicks off
* the process of creating or unlocking a wallet.
*/
-export const lndWalletUnlockerStarted = () => dispatch => {
- ipcRenderer.send('walletUnlocker', { msg: 'genSeed' })
- dispatch({ type: FETCH_SEED })
+export const lndWalletUnlockerStarted = () => (dispatch, getState) => {
+ dispatch(setLndWalletUnlockerStarted('active'))
+ const state = getState().onboarding
+
+ // Handle generate seed.
+ if (state.fetchingSeed) {
+ ipcRenderer.send('walletUnlocker', { msg: 'genSeed' })
+ }
+
+ // Handle unlock wallet.
+ else if (state.unlockingWallet) {
+ ipcRenderer.send('walletUnlocker', {
+ msg: 'unlockWallet',
+ data: { wallet_password: state.password }
+ })
+ }
+
+ // Handle create wallet.
+ else if (state.creatingNewWallet) {
+ ipcRenderer.send('walletUnlocker', {
+ msg: 'initWallet',
+ data: { wallet_password: state.password, cipher_seed_mnemonic: state.seed }
+ })
+ }
+
+ // Handle recover wallet.
+ else if (state.recoveringOldWallet) {
+ ipcRenderer.send('walletUnlocker', {
+ msg: 'initWallet',
+ data: {
+ wallet_password: state.password,
+ cipher_seed_mnemonic: state.seed,
+ recovery_window: 250
+ }
+ })
+ }
+
+ // // Handle remote connect.
+ // else if (state.startingLnd) {
+ // ipcRenderer.send('walletUnlocker', {
+ // msg: 'unlockWallet',
+ // data: { wallet_password: state.password }
+ // })
+ // }
}
/**
@@ -255,6 +371,8 @@ export const lndWalletUnlockerStarted = () => dispatch => {
* early as possible.
*/
export const lndWalletStarted = lndConfig => async dispatch => {
+ dispatch(setLndWalletStarted())
+
// Save the wallet settings.
const walletId = await db.wallets.put(lndConfig)
@@ -266,113 +384,32 @@ export const lndWalletStarted = lndConfig => async dispatch => {
dispatch(fetchInfo())
dispatch(lndStarted(lndConfig))
-}
-
-export const submitNewWallet = (
- wallet_password,
- cipher_seed_mnemonic,
- aezeed_passphrase
-) => dispatch => {
- // once the user submits the data needed to start LND we will alert the app that it should start LND
- ipcRenderer.send('walletUnlocker', {
- msg: 'initWallet',
- data: { wallet_password, cipher_seed_mnemonic, aezeed_passphrase }
- })
- dispatch({ type: CREATING_NEW_WALLET })
-}
-
-export const recoverOldWallet = (
- wallet_password,
- cipher_seed_mnemonic,
- aezeed_passphrase
-) => dispatch => {
- // once the user submits the data needed to start LND we will alert the app that it should start LND
- ipcRenderer.send('walletUnlocker', {
- msg: 'initWallet',
- data: { wallet_password, cipher_seed_mnemonic, aezeed_passphrase, recovery_window: 250 }
- })
- dispatch({ type: RECOVERING_OLD_WALLET })
+ dispatch({ type: ONBOARDING_FINISHED })
}
// Listener for errors connecting to LND gRPC
-export const startOnboarding = () => async dispatch => {
- // If we have an active wallet saved, load it's settings.
- const activeWallet = await db.settings.get({ key: 'activeWallet' })
- if (activeWallet) {
- const wallet = await db.wallets.get({ id: activeWallet.value })
- if (wallet) {
- dispatch(setConnectionType(wallet.type))
-
- switch (wallet.type) {
- case 'local':
- dispatch(updateAlias(wallet.alias))
- dispatch(setAutopilot(wallet.autopilot))
- break
- case 'custom':
- dispatch(setConnectionHost(wallet.host))
- dispatch(setConnectionCert(wallet.cert))
- dispatch(setConnectionMacaroon(wallet.macaroon))
- break
- case 'btcpayserver':
- dispatch(setConnectionString(wallet.string))
- break
- }
- }
+export const startOnboarding = () => async (dispatch, getState) => {
+ const state = getState().onboarding
+ if (state.stoppingLnd) {
+ dispatch(lndStopped())
}
dispatch({ type: ONBOARDING_STARTED })
}
-// Listener for errors connecting to LND gRPC
-export const startLndError = (event, errors) => (dispatch, getState) => {
- const connectionType = connectionTypeSelector(getState())
-
- switch (connectionType) {
- case 'local':
- dispatch(setError(errors))
- dispatch({ type: CHANGE_STEP, step: 0.1 })
- break
- case 'custom':
- dispatch(setStartLndError(errors))
- dispatch({ type: CHANGE_STEP, step: 0.2 })
- break
- case 'btcpayserver':
- dispatch(setStartLndError(errors))
- dispatch({ type: CHANGE_STEP, step: 0.3 })
- break
- }
-}
-
-export const createWallet = () => dispatch => {
- ipcRenderer.send('walletUnlocker', { msg: 'genSeed' })
- dispatch({ type: CHANGE_STEP, step: 4 })
-}
-
-export const finishOnboarding = () => dispatch => dispatch({ type: ONBOARDING_FINISHED })
-
// Listener for when LND creates and sends us a generated seed
export const receiveSeed = (event, { cipher_seed_mnemonic }) => dispatch => {
- dispatch({ type: CHANGE_STEP, step: 4 })
- // there was no seed and we just generated a new one, send user to the login component
dispatch({ type: SET_SEED, seed: cipher_seed_mnemonic })
+ dispatch(stopLnd())
}
// Listener for when LND throws an error on seed creation
export const receiveSeedError = (event, error) => dispatch => {
- dispatch({ type: SET_HAS_SEED, hasSeed: true })
- // there is already a seed, send user to the login component
- dispatch({ type: CHANGE_STEP, step: 3 })
dispatch({
type: LOADING_EXISTING_WALLET,
existingWalletDir: get(error, 'context.lndDataDir')
})
}
-// Unlock an existing wallet with a wallet password
-export const unlockWallet = wallet_password => dispatch => {
- ipcRenderer.send('walletUnlocker', { msg: 'unlockWallet', data: { wallet_password } })
- dispatch({ type: UNLOCKING_WALLET })
-}
-
export const walletCreated = () => dispatch => {
dispatch({ type: WALLET_UNLOCKED })
dispatch({ type: ONBOARDING_FINISHED })
@@ -385,13 +422,8 @@ export const walletUnlocked = () => dispatch => {
ipcRenderer.send('startLightningWallet')
}
-export const walletConnected = () => dispatch => {
- dispatch({ type: WALLET_UNLOCKED })
- dispatch({ type: ONBOARDING_FINISHED })
-}
-
-export const unlockWalletError = () => dispatch => {
- dispatch({ type: SET_UNLOCK_WALLET_ERROR })
+export const setUnlockWalletError = (event, unlockWalletError) => dispatch => {
+ dispatch({ type: SET_UNLOCK_WALLET_ERROR, unlockWalletError })
}
// ------------------------------------
@@ -403,41 +435,37 @@ const ACTION_HANDLERS = {
[SET_CONNECTION_HOST]: (state, { connectionHost }) => ({ ...state, connectionHost }),
[SET_CONNECTION_CERT]: (state, { connectionCert }) => ({ ...state, connectionCert }),
[SET_CONNECTION_MACAROON]: (state, { connectionMacaroon }) => ({ ...state, connectionMacaroon }),
- [UPDATE_ALIAS]: (state, { alias }) => ({ ...state, alias }),
- [UPDATE_PASSWORD]: (state, { password }) => ({ ...state, password }),
- [UPDATE_CREATE_WALLET_PASSWORD]: (state, { createWalletPassword }) => ({
+ [SET_ALIAS]: (state, { alias }) => ({ ...state, alias }),
+ [SET_AUTOPILOT]: (state, { autopilot }) => ({ ...state, autopilot }),
+ [FETCH_SEED]: state => ({ ...state, fetchingSeed: true }),
+ [SET_SEED]: (state, { seed }) => ({ ...state, seed, fetchingSeed: false }),
+ [SET_PASSWORD]: (state, { password }) => ({ ...state, password }),
+ [SET_LND_WALLET_UNLOCKER_STARTED]: state => ({
...state,
- createWalletPassword
+ lndWalletUnlockerStarted: true,
+ lndWalletStarted: false
}),
- [UPDATE_CREATE_WALLET_PASSWORD_CONFIRMATION]: (state, { createWalletPasswordConfirmation }) => ({
+ [SET_LND_WALLET_STARTED]: state => ({
...state,
- createWalletPasswordConfirmation
+ lndWalletStarted: true,
+ lndWalletUnlockerStarted: false
}),
- [UPDATE_RE_ENTER_SEED_INPUT]: (state, { inputSeedObj }) => ({
+ [ONBOARDING_STARTED]: state => ({ ...state, onboarding: true, onboarded: false }),
+ [ONBOARDING_FINISHED]: state => ({ ...state, onboarding: false, onboarded: true }),
+ [STARTING_LND]: state => ({
...state,
- reEnterSeedInput: { ...state.reEnterSeedInput, [inputSeedObj.index]: inputSeedObj.word }
+ startingLnd: true,
+ startLndHostError: '',
+ startLndCertError: '',
+ startLndMacaroonError: ''
}),
- [UPDATE_RECOVER_SEED_INPUT]: (state, { inputSeedObj }) => ({
+ [LND_STARTED]: state => ({
...state,
- recoverSeedInput: Object.assign([], state.recoverSeedInput, {
- [inputSeedObj.index]: inputSeedObj
- })
+ startingLnd: false,
+ startLndHostError: '',
+ startLndCertError: '',
+ startLndMacaroonError: ''
}),
-
- [SET_AUTOPILOT]: (state, { autopilot }) => ({ ...state, autopilot }),
-
- [FETCH_SEED]: state => ({ ...state, fetchingSeed: true }),
- [SET_HAS_SEED]: (state, { hasSeed }) => ({ ...state, hasSeed, fetchingSeed: false }),
- [SET_SEED]: (state, { seed }) => ({ ...state, seed, fetchingSeed: false }),
- [SET_RE_ENTER_SEED_INDEXES]: (state, { seedIndexesArr }) => ({ ...state, seedIndexesArr }),
-
- [CHANGE_STEP]: (state, { step }) => ({ ...state, step, previousStep: state.step }),
-
- [ONBOARDING_STARTED]: state => ({ ...state, onboarding: true, onboarded: false }),
- [ONBOARDING_FINISHED]: state => ({ ...state, onboarding: false, onboarded: true }),
-
- [STARTING_LND]: state => ({ ...state, startingLnd: true }),
- [LND_STARTED]: state => ({ ...state, startingLnd: false }),
[SET_START_LND_ERROR]: (state, { errors }) => ({
...state,
startingLnd: false,
@@ -445,84 +473,44 @@ const ACTION_HANDLERS = {
startLndCertError: errors.cert,
startLndMacaroonError: errors.macaroon
}),
-
+ [STOPPING_LND]: state => ({
+ ...state,
+ stoppingLnd: true,
+ lndWalletStarted: false,
+ lndWalletUnlockerStarted: false
+ }),
+ [LND_STOPPED]: state => ({ ...state, stoppingLnd: false }),
[LOADING_EXISTING_WALLET]: (state, { existingWalletDir }) => ({ ...state, existingWalletDir }),
-
[CREATING_NEW_WALLET]: state => ({ ...state, creatingNewWallet: true }),
-
[RECOVERING_OLD_WALLET]: state => ({ ...state, recoveringOldWallet: true }),
-
[UNLOCKING_WALLET]: state => ({ ...state, unlockingWallet: true }),
[WALLET_UNLOCKED]: state => ({
...state,
unlockingWallet: false,
- unlockWalletError: { isError: false, message: '' }
+ unlockWalletError: ''
}),
- [SET_UNLOCK_WALLET_ERROR]: state => ({
+ [SET_UNLOCK_WALLET_ERROR]: (state, { unlockWalletError }) => ({
...state,
unlockingWallet: false,
- unlockWalletError: { isError: true, message: 'Incorrect password' }
+ unlockWalletError
}),
-
- [SET_SIGNUP_CREATE]: state => ({ ...state, signupForm: { create: true, import: false } }),
- [SET_SIGNUP_IMPORT]: state => ({ ...state, signupForm: { create: false, import: true } })
+ [VALIDATING_HOST]: (state, { validatingHost }) => ({ ...state, validatingHost }),
+ [VALIDATING_CERT]: (state, { validatingCert }) => ({ ...state, validatingCert }),
+ [VALIDATING_MACAROON]: (state, { validatingMacaroon }) => ({ ...state, validatingMacaroon }),
+ [RESET_ONBOARDING]: state => ({ ...state, ...initialState })
}
// ------------------------------------
// Selector
// ------------------------------------
const onboardingSelectors = {}
-const passwordSelector = state => state.onboarding.password
-
-const createWalletPasswordSelector = state => state.onboarding.createWalletPassword
-const createWalletPasswordConfirmationSelector = state =>
- state.onboarding.createWalletPasswordConfirmation
-
-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.startingLnd = state => state.onboarding.startingLnd
-onboardingSelectors.passwordIsValid = createSelector(
- passwordSelector,
- password => password.length >= 8
-)
-
-onboardingSelectors.passwordMinCharsError = createSelector(
- createWalletPasswordSelector,
- createWalletPasswordConfirmationSelector,
- (pass1, pass2) => pass1 === pass2 && pass1.length < 8 && pass1.length > 0
-)
-
-onboardingSelectors.showCreateWalletPasswordConfirmationError = createSelector(
- createWalletPasswordSelector,
- createWalletPasswordConfirmationSelector,
- (pass1, pass2) => pass1 !== pass2 && pass2.length > 0
-)
-
-onboardingSelectors.reEnterSeedChecker = createSelector(
- seedSelector,
- seedIndexesArrSelector,
- reEnterSeedInputSelector,
- (seed, seedIndexArr, reEnterSeedInput) =>
- Object.keys(reEnterSeedInput).length >= seedIndexArr.length &&
- seedIndexArr.every(
- index => reEnterSeedInput[index] && reEnterSeedInput[index] === seed[index - 1]
- )
-)
-
-onboardingSelectors.connectionHostIsValid = createSelector(
- connectionHostSelector,
- connectionHost => {
- return connectionHost.length > 0
- }
-)
-
onboardingSelectors.connectionStringParamsSelector = createSelector(
connectionStringSelector,
connectionString => {
@@ -538,14 +526,6 @@ onboardingSelectors.connectionStringParamsSelector = createSelector(
}
)
-onboardingSelectors.connectionStringIsValid = createSelector(
- onboardingSelectors.connectionStringParamsSelector,
- connectionStringParams => {
- const { host, port, macaroon } = connectionStringParams
- return Boolean(host && port && macaroon)
- }
-)
-
export { onboardingSelectors }
// ------------------------------------
@@ -555,8 +535,7 @@ export { onboardingSelectors }
const initialState = {
onboarding: false,
onboarded: false,
- step: 0.1,
- connectionType: 'default',
+ connectionType: 'create',
connectionString: '',
connectionHost: '',
connectionCert: '',
@@ -564,43 +543,22 @@ const initialState = {
alias: '',
autopilot: true,
password: '',
-
startingLnd: false,
startLndHostError: '',
startLndCertError: '',
startLndMacaroonError: '',
-
fetchingSeed: false,
- hasSeed: false,
seed: [],
-
- // wallet password. password used to encrypt the wallet and is required to unlock the daemon after set
- createWalletPassword: '',
- createWalletPasswordConfirmation: '',
creatingNewWallet: false,
recoveringOldWallet: false,
-
existingWalletDir: null,
unlockingWallet: false,
- unlockWalletError: {
- isError: false,
- message: ''
- },
-
- seedIndexesArr: [],
- // object of inputs for when the user re-enters their seed
- // {
- // index: word,
- // index: word,
- // index: word
- // }
- reEnterSeedInput: {},
- recoverSeedInput: [],
- // step where the user decides whether they want a newly created seed or to import an existing one
- signupForm: {
- create: true,
- import: false
- }
+ unlockWalletError: '',
+ validatingHost: false,
+ validatingCert: false,
+ validatingMacaroon: false,
+ lndWalletUnlockerStarted: false,
+ lndWalletStarted: false
}
// ------------------------------------
diff --git a/package.json b/package.json
index 58fca8ef..26fd6fcd 100644
--- a/package.json
+++ b/package.json
@@ -306,6 +306,7 @@
"@grpc/proto-loader": "0.3.0",
"@rebass/components": "4.0.0-1",
"axios": "0.18.0",
+ "bip39-en": "1.1.1",
"bitcoinjs-lib": "4.0.2",
"bolt11": "https://github.com/bitcoinjs/bolt11.git",
"connected-react-router": "5.0.1",
diff --git a/stories/containers/onboarding.stories.js b/stories/containers/onboarding.stories.js
new file mode 100644
index 00000000..828b8b5f
--- /dev/null
+++ b/stories/containers/onboarding.stories.js
@@ -0,0 +1,155 @@
+import React from 'react'
+import { storiesOf } from '@storybook/react'
+import { action } from '@storybook/addon-actions'
+import { linkTo } from '@storybook/addon-links'
+import { State, Store } from '@sambego/storybook-state'
+import { Modal, Page } from 'components/UI'
+import { Onboarding } from 'components/Onboarding'
+
+const delay = time => new Promise(resolve => setTimeout(() => resolve(), time))
+
+const initialValues = {
+ alias: '',
+ connectionType: 'local',
+ connectionHost: '',
+ connectionCert: '',
+ connectionMacaroon: '',
+ connectionString: `{
+ "configurations": [
+ {
+ "type": "grpc",
+ "cryptoCode": "BTC",
+ "host": "host",
+ "port": "19000",
+ "macaroon": "macaroon"
+ }
+ ]
+}`,
+ startLndHostError: '',
+ startLndCertError: '',
+ startLndMacaroonError: '',
+ password: '',
+ seed: [],
+ onboarded: false,
+ onboarding: true
+}
+
+const store = new Store(initialValues)
+
+// State
+const setConnectionType = connectionType => store.set({ connectionType })
+const setConnectionHost = connectionHost => store.set({ connectionHost })
+const setConnectionCert = connectionCert => store.set({ connectionCert })
+const setConnectionMacaroon = connectionMacaroon => store.set({ connectionMacaroon })
+const setConnectionString = connectionString => store.set({ connectionString })
+const setAlias = alias => store.set({ alias })
+const setAutopilot = autopilot => store.set({ autopilot })
+const setPassword = password => store.set({ password })
+
+const resetOnboarding = () => {
+ store.set(initialValues)
+}
+
+const generateSeed = async () => {
+ await delay(1000)
+ store.set({
+ seed: [
+ 'idle',
+ 'fork',
+ 'derive',
+ 'idea',
+ 'pony',
+ 'exercise',
+ 'balance',
+ 'squirrel',
+ 'around',
+ 'sustain',
+ 'outdoor',
+ 'beach',
+ 'thrive',
+ 'fringe',
+ 'broom',
+ 'sea',
+ 'sick',
+ 'bacon',
+ 'card',
+ 'palace',
+ 'slender',
+ 'blue',
+ 'day',
+ 'fix'
+ ]
+ })
+}
+
+const startLnd = async () => {
+ action('startLnd')
+ await delay(500)
+}
+const stopLnd = async () => {
+ action('stopLnd')
+ await delay(500)
+}
+
+const validateHost = async value => {
+ action('validateHost')
+ await delay(300)
+ return value === 'valid'
+ ? Promise.resolve()
+ : Promise.reject(new Error('invalid hostname (enter "valid")'))
+}
+const validateCert = async value => {
+ action('validateCert')
+ await delay(300)
+ return value === 'valid'
+ ? Promise.resolve()
+ : Promise.reject(new Error('invalid cert (enter "valid")'))
+}
+const validateMacaroon = async value => {
+ action('validateMacaroon')
+ await delay(300)
+ return value === 'valid'
+ ? Promise.resolve()
+ : Promise.reject(new Error('invalid macaroon (enter "valid")'))
+}
+
+const recoverOldWallet = async () => action('recoverOldWallet')
+const createNewWallet = async () => action('recoverOldWallet')
+
+storiesOf('Containers.Onboarding', module)
+ .addParameters({
+ info: {
+ disable: true
+ }
+ })
+ .addDecorator(story => (
+
+ {story()}
+
+ ))
+ .add('Onboarding', () => {
+ return (
+
+
+
+ )
+ })
diff --git a/stories/containers/onboarding/components.stories.js b/stories/containers/onboarding/components.stories.js
new file mode 100644
index 00000000..7114f408
--- /dev/null
+++ b/stories/containers/onboarding/components.stories.js
@@ -0,0 +1,96 @@
+import React from 'react'
+import { storiesOf } from '@storybook/react'
+import {
+ Alias,
+ Autopilot,
+ BtcPayServer,
+ ConnectionType,
+ ConnectionDetails,
+ ConnectionConfirm,
+ Login,
+ Password,
+ Recover,
+ SeedConfirm,
+ SeedView
+} from 'components/Onboarding/Steps'
+
+const setConnectionHost = () => ({})
+const setConnectionCert = () => ({})
+const setConnectionMacaroon = () => ({})
+
+storiesOf('Containers.Onboarding.Forms', module)
+ .add('ConnectionType', () => )
+ .add('ConnectionDetails', () => (
+
+ ))
+ .add('ConnectionConfirm', () => )
+ .add('BtcPayServer', () => )
+ .add('Login', () => )
+ .add('Password', () => )
+ .add('Recover', () => )
+ .add('Alias', () => )
+ .add('Autopilot', () => )
+ .add('SeedConfirm', () => (
+
+ ))
+ .add('SeedView', () => (
+
+ ))
diff --git a/yarn.lock b/yarn.lock
index dc2e2f65..f145574e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4164,6 +4164,11 @@ bip32@^1.0.0:
typeforce "^1.11.5"
wif "^2.0.6"
+bip39-en@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/bip39-en/-/bip39-en-1.1.1.tgz#0046f3081fdf2f4c87b277008d712ec6fc397721"
+ integrity sha512-ZlwJCe+4LdWlNQoNeaeEdpW5NoBGnSXr0pGCHCKzkwuyndFV5kr+C671VxCTQT74fwNzYh7c0oCUrdcaQKhXkQ==
+
bip66@^1.1.0, bip66@^1.1.3:
version "1.1.5"
resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22"