79 changed files with 2375 additions and 2251 deletions
@ -1,23 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './Alias.scss' |
|
||||
|
|
||||
const Alias = ({ alias, updateAlias }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<input |
|
||||
type="text" |
|
||||
placeholder="Satoshi" |
|
||||
className={styles.alias} |
|
||||
ref={input => input && input.focus()} |
|
||||
value={alias} |
|
||||
onChange={event => updateAlias(event.target.value)} |
|
||||
/> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
Alias.propTypes = { |
|
||||
alias: PropTypes.string.isRequired, |
|
||||
updateAlias: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Alias |
|
@ -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; |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import Alias from './Alias' |
|
||||
|
|
||||
export default Alias |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section className={`${styles.enable} ${autopilot ? styles.active : undefined}`}> |
|
||||
<div onClick={() => setAutopilot(true)}> |
|
||||
{autopilot ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.enable} /> |
|
||||
</span> |
|
||||
</div> |
|
||||
</section> |
|
||||
<section |
|
||||
className={`${styles.disable} ${ |
|
||||
!autopilot && autopilot !== null ? styles.active : undefined |
|
||||
}`}
|
|
||||
> |
|
||||
<div onClick={() => setAutopilot(false)}> |
|
||||
{!autopilot && autopilot !== null ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.disable} /> |
|
||||
</span> |
|
||||
</div> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
Autopilot.propTypes = { |
|
||||
autopilot: PropTypes.bool, |
|
||||
setAutopilot: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Autopilot |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import Autopilot from './Autopilot' |
|
||||
|
|
||||
export default Autopilot |
|
@ -1,7 +0,0 @@ |
|||||
import { defineMessages } from 'react-intl' |
|
||||
|
|
||||
/* eslint-disable max-len */ |
|
||||
export default defineMessages({ |
|
||||
enable: 'Enable Autopilot', |
|
||||
disable: 'Disable Autopilot' |
|
||||
}) |
|
@ -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 |
|
||||
}) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section className={styles.input}> |
|
||||
<label htmlFor="connectionString"> |
|
||||
<FormattedMessage {...messages.connection_string_label} />: |
|
||||
</label> |
|
||||
<textarea |
|
||||
type="text" |
|
||||
id="connectionString" |
|
||||
rows="10" |
|
||||
placeholder={intl.formatMessage({ ...messages.connection_string_placeholder })} |
|
||||
className={ |
|
||||
connectionString && (startLndHostError || !connectionStringIsValid) |
|
||||
? styles.error |
|
||||
: undefined |
|
||||
} |
|
||||
ref={input => input} |
|
||||
value={connectionString} |
|
||||
onChange={event => setConnectionString(event.target.value)} |
|
||||
/> |
|
||||
<p className={styles.description}> |
|
||||
<FormattedMessage {...messages.btcpay_description} /> |
|
||||
</p> |
|
||||
<p |
|
||||
className={`${styles.errorMessage} ${ |
|
||||
connectionString && !connectionStringIsValid ? styles.visible : undefined |
|
||||
}`}
|
|
||||
> |
|
||||
<FormattedMessage {...messages.btcpay_error} /> |
|
||||
</p> |
|
||||
<p |
|
||||
className={`${styles.errorMessage} ${ |
|
||||
connectionString && startLndHostError ? styles.visible : undefined |
|
||||
}`}
|
|
||||
> |
|
||||
{startLndHostError} |
|
||||
</p> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
BtcPayServer.propTypes = { |
|
||||
connectionString: PropTypes.string.isRequired, |
|
||||
connectionStringIsValid: PropTypes.bool.isRequired, |
|
||||
setConnectionString: PropTypes.func.isRequired, |
|
||||
startLndHostError: PropTypes.string |
|
||||
} |
|
||||
|
|
||||
export default injectIntl(BtcPayServer) |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import BtcPayServer from './BtcPayServer' |
|
||||
|
|
||||
export default BtcPayServer |
|
@ -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' |
|
||||
}) |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<h2> |
|
||||
<FormattedMessage {...messages.verify_host_title} />{' '} |
|
||||
<span className={styles.host}>{connectionHost.split(':')[0]}</span>?{' '} |
|
||||
</h2> |
|
||||
<p> |
|
||||
<FormattedMessage {...messages.verify_host_description} /> |
|
||||
</p> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
ConnectionConfirm.propTypes = { |
|
||||
connectionHost: PropTypes.string.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ConnectionConfirm |
|
@ -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); |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import ConnectionConfirm from './ConnectionConfirm' |
|
||||
|
|
||||
export default ConnectionConfirm |
|
@ -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.' |
|
||||
}) |
|
@ -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 |
|
||||
}) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section className={styles.input}> |
|
||||
<label htmlFor="connectionHost"> |
|
||||
<FormattedMessage {...messages.hostname_title} />: |
|
||||
</label> |
|
||||
<input |
|
||||
type="text" |
|
||||
id="connectionHost" |
|
||||
className={`${styles.host} ${startLndHostError ? styles.error : undefined}`} |
|
||||
ref={input => input} |
|
||||
value={connectionHost} |
|
||||
onChange={event => setConnectionHost(event.target.value)} |
|
||||
/> |
|
||||
<p className={styles.description}> |
|
||||
<FormattedMessage {...messages.hostname_description} /> |
|
||||
</p> |
|
||||
<p className={`${startLndHostError ? styles.visible : undefined} ${styles.errorMessage}`}> |
|
||||
{startLndHostError} |
|
||||
</p> |
|
||||
</section> |
|
||||
<section className={styles.input}> |
|
||||
<label htmlFor="connectionCert"> |
|
||||
<FormattedMessage {...messages.cert_title} />: |
|
||||
</label> |
|
||||
<input |
|
||||
type="text" |
|
||||
id="connectionCert" |
|
||||
className={`${styles.cert} ${startLndCertError ? styles.error : undefined}`} |
|
||||
ref={input => input} |
|
||||
value={connectionCert} |
|
||||
onChange={event => setConnectionCert(event.target.value)} |
|
||||
/> |
|
||||
<p className={styles.description}> |
|
||||
<FormattedMessage {...messages.cert_description} /> |
|
||||
</p> |
|
||||
<p className={`${startLndCertError ? styles.visible : undefined} ${styles.errorMessage}`}> |
|
||||
{startLndCertError} |
|
||||
</p> |
|
||||
</section> |
|
||||
<section className={styles.input}> |
|
||||
<label htmlFor="connectionMacaroon">Macaroon:</label> |
|
||||
<input |
|
||||
type="text" |
|
||||
id="connectionMacaroon" |
|
||||
className={`${styles.macaroon} ${startLndMacaroonError ? styles.error : undefined}`} |
|
||||
ref={input => input} |
|
||||
value={connectionMacaroon} |
|
||||
onChange={event => setConnectionMacaroon(event.target.value)} |
|
||||
/> |
|
||||
<p className={styles.description}> |
|
||||
<FormattedMessage {...messages.macaroon_description} /> |
|
||||
</p> |
|
||||
<p className={`${startLndMacaroonError ? styles.visible : undefined} ${styles.errorMessage}`}> |
|
||||
{startLndMacaroonError} |
|
||||
</p> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
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 |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import ConnectionDetails from './ConnectionDetails' |
|
||||
|
|
||||
export default ConnectionDetails |
|
@ -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' |
|
||||
}) |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section |
|
||||
className={`${styles.option} ${connectionType === 'local' ? styles.active : undefined}`} |
|
||||
> |
|
||||
<div className={`${styles.button}`} onClick={() => setConnectionType('local')}> |
|
||||
{connectionType === 'local' ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.default} />{' '} |
|
||||
<span className={styles.superscript}>testnet</span> |
|
||||
</span> |
|
||||
</div> |
|
||||
<div className={`${styles.description}`}> |
|
||||
<FormattedMessage {...messages.default_description} /> |
|
||||
<br /> |
|
||||
(testnet <FormattedMessage {...messages.only} />) |
|
||||
</div> |
|
||||
</section> |
|
||||
<section |
|
||||
className={`${styles.option} ${connectionType === 'custom' ? styles.active : undefined}`} |
|
||||
> |
|
||||
<div className={`${styles.button}`} onClick={() => setConnectionType('custom')}> |
|
||||
{connectionType === 'custom' ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.custom} /> |
|
||||
</span> |
|
||||
</div> |
|
||||
<div className={`${styles.description}`}> |
|
||||
<FormattedMessage {...messages.custom_description} /> |
|
||||
</div> |
|
||||
</section> |
|
||||
<section className={`${styles.option} ${connectionType === 'btcpayserver' && styles.active}`}> |
|
||||
<div className={`${styles.button}`} onClick={() => setConnectionType('btcpayserver')}> |
|
||||
{connectionType === 'btcpayserver' ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}>BTCPay Server</span> |
|
||||
</div> |
|
||||
<div className={`${styles.description}`}> |
|
||||
<FormattedMessage {...messages.btcpay_description} /> |
|
||||
</div> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
ConnectionType.propTypes = { |
|
||||
connectionType: PropTypes.string.isRequired, |
|
||||
setConnectionType: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default ConnectionType |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import ConnectionType from './ConnectionType' |
|
||||
|
|
||||
export default ConnectionType |
|
@ -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.' |
|
||||
}) |
|
@ -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 }) => ( |
|
||||
<div className={`${styles.container} ${theme}`}> |
|
||||
<header className={styles.header}> |
|
||||
<section> |
|
||||
<ZapLogo width="70px" height="32px" /> |
|
||||
</section> |
|
||||
<section> |
|
||||
<div |
|
||||
className={styles.help} |
|
||||
onClick={() => |
|
||||
shell.openExternal('https://ln-zap.github.io/zap-tutorials/zap-desktop-getting-started') |
|
||||
} |
|
||||
> |
|
||||
<FormattedMessage {...messages.help} /> |
|
||||
</div> |
|
||||
</section> |
|
||||
</header> |
|
||||
|
|
||||
<div className={styles.info}> |
|
||||
<h1>{title}</h1> |
|
||||
<p>{description}</p> |
|
||||
</div> |
|
||||
|
|
||||
<div className={styles.content}>{children}</div> |
|
||||
|
|
||||
<footer className={styles.footer}> |
|
||||
<div className={styles.buttonsContainer}> |
|
||||
<section> |
|
||||
{back && ( |
|
||||
<Button variant="secondary" onClick={back} px={0}> |
|
||||
<FaAngleLeft /> |
|
||||
<FormattedMessage {...messages.back} /> |
|
||||
</Button> |
|
||||
)} |
|
||||
</section> |
|
||||
<section> |
|
||||
{next && ( |
|
||||
<Button onClick={next}> |
|
||||
<FormattedMessage {...messages.next} /> |
|
||||
<FaAngleRight /> |
|
||||
</Button> |
|
||||
)} |
|
||||
</section> |
|
||||
</div> |
|
||||
</footer> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
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 |
|
@ -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; |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import FormContainer from './FormContainer' |
|
||||
|
|
||||
export default FormContainer |
|
@ -1,8 +0,0 @@ |
|||||
import { defineMessages } from 'react-intl' |
|
||||
|
|
||||
/* eslint-disable max-len */ |
|
||||
export default defineMessages({ |
|
||||
help: 'Need Help?', |
|
||||
next: 'Next', |
|
||||
back: 'back' |
|
||||
}) |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
{hasSeed ? <Login {...loginProps} /> : <Signup {...signupProps} />} |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
InitWallet.propTypes = { |
|
||||
hasSeed: PropTypes.bool.isRequired, |
|
||||
loginProps: PropTypes.object.isRequired, |
|
||||
signupProps: PropTypes.object.isRequired |
|
||||
} |
|
||||
|
|
||||
export default InitWallet |
|
@ -1,3 +0,0 @@ |
|||||
import InitWallet from './InitWallet' |
|
||||
|
|
||||
export default InitWallet |
|
@ -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 |
|
||||
}) => ( |
|
||||
<div className={styles.container}> |
|
||||
<input |
|
||||
type="password" |
|
||||
placeholder={intl.formatMessage({ ...messages.password_placeholder })} |
|
||||
className={`${styles.password} ${unlockWalletError.isError ? styles.inputError : undefined}`} |
|
||||
ref={input => input && input.focus()} |
|
||||
value={password} |
|
||||
onChange={event => updatePassword(event.target.value)} |
|
||||
onKeyPress={event => { |
|
||||
if (event.key === 'Enter') { |
|
||||
unlockWallet(password) |
|
||||
} |
|
||||
}} |
|
||||
/> |
|
||||
<p className={`${unlockWalletError.isError ? styles.active : undefined} ${styles.error}`}> |
|
||||
{unlockWalletError.message} |
|
||||
</p> |
|
||||
|
|
||||
<section className={styles.buttons}> |
|
||||
<Button |
|
||||
disabled={!passwordIsValid || unlockingWallet} |
|
||||
onClick={() => unlockWallet(password)} |
|
||||
processing={unlockingWallet} |
|
||||
> |
|
||||
{unlockingWallet ? ( |
|
||||
<FormattedMessage {...messages.unlocking} /> |
|
||||
) : ( |
|
||||
<FormattedMessage {...messages.unlock} /> |
|
||||
)} |
|
||||
</Button> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
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) |
|
@ -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; |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import Login from './Login' |
|
||||
|
|
||||
export default Login |
|
@ -1,8 +0,0 @@ |
|||||
import { defineMessages } from 'react-intl' |
|
||||
|
|
||||
/* eslint-disable max-len */ |
|
||||
export default defineMessages({ |
|
||||
password_placeholder: 'Password', |
|
||||
unlock: 'Unlock', |
|
||||
unlocking: 'Unlocking' |
|
||||
}) |
|
@ -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 |
|
||||
}) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section className={styles.input}> |
|
||||
<input |
|
||||
type="password" |
|
||||
placeholder={intl.formatMessage({ ...messages.password_placeholder })} |
|
||||
className={`${styles.password} ${ |
|
||||
showCreateWalletPasswordConfirmationError ? styles.error : undefined |
|
||||
} |
|
||||
${passwordMinCharsError && styles.error}`}
|
|
||||
value={createWalletPassword} |
|
||||
onChange={event => updateCreateWalletPassword(event.target.value)} |
|
||||
/> |
|
||||
</section> |
|
||||
|
|
||||
<section className={styles.input}> |
|
||||
<input |
|
||||
type="password" |
|
||||
placeholder={intl.formatMessage({ ...messages.password_confirm_placeholder })} |
|
||||
className={`${styles.password} ${ |
|
||||
showCreateWalletPasswordConfirmationError ? styles.error : undefined |
|
||||
} |
|
||||
${passwordMinCharsError && styles.error}`}
|
|
||||
value={createWalletPasswordConfirmation} |
|
||||
onChange={event => updateCreateWalletPasswordConfirmation(event.target.value)} |
|
||||
/> |
|
||||
<p |
|
||||
className={`${styles.errorMessage} ${ |
|
||||
showCreateWalletPasswordConfirmationError ? styles.visible : undefined |
|
||||
}`}
|
|
||||
> |
|
||||
<FormattedMessage {...messages.password_error_match} /> |
|
||||
</p> |
|
||||
<p className={`${styles.helpMessage} ${passwordMinCharsError ? styles.red : undefined}`}> |
|
||||
<FormattedMessage |
|
||||
{...messages.password_error_length} |
|
||||
values={{ |
|
||||
passwordMinLength: '8' |
|
||||
}} |
|
||||
/> |
|
||||
</p> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
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) |
|
@ -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); |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import NewWalletPassword from './NewWalletPassword' |
|
||||
|
|
||||
export default NewWalletPassword |
|
@ -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' |
|
||||
}) |
|
@ -1,26 +0,0 @@ |
|||||
import React from 'react' |
|
||||
import PropTypes from 'prop-types' |
|
||||
import styles from './NewWalletSeed.scss' |
|
||||
|
|
||||
const NewWalletSeed = ({ seed }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<ul className={styles.seedContainer}> |
|
||||
{seed.map((word, index) => ( |
|
||||
<li key={index}> |
|
||||
<section> |
|
||||
<label htmlFor={word}>{index + 1}</label> |
|
||||
</section> |
|
||||
<section> |
|
||||
<span>{word}</span> |
|
||||
</section> |
|
||||
</li> |
|
||||
))} |
|
||||
</ul> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
NewWalletSeed.propTypes = { |
|
||||
seed: PropTypes.array.isRequired |
|
||||
} |
|
||||
|
|
||||
export default NewWalletSeed |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import NewWalletSeed from './NewWalletSeed' |
|
||||
|
|
||||
export default NewWalletSeed |
|
@ -1,319 +1,297 @@ |
|||||
import React from 'react' |
import React from 'react' |
||||
import PropTypes from 'prop-types' |
import PropTypes from 'prop-types' |
||||
import { Redirect } from 'react-router-dom' |
import { Redirect } from 'react-router-dom' |
||||
|
|
||||
import { FormattedMessage } from 'react-intl' |
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 messages from './messages' |
||||
|
|
||||
import FormContainer from './FormContainer' |
class Onboarding extends React.Component { |
||||
import ConnectionType from './ConnectionType' |
static propTypes = { |
||||
import ConnectionDetails from './ConnectionDetails' |
// STATE
|
||||
import ConnectionConfirm from './ConnectionConfirm' |
alias: PropTypes.string, |
||||
import BtcPayServer from './BtcPayServer' |
autopilot: PropTypes.bool, |
||||
import Alias from './Alias' |
connectionType: PropTypes.string, |
||||
import Autopilot from './Autopilot' |
connectionHost: PropTypes.string, |
||||
import Login from './Login' |
connectionCert: PropTypes.string, |
||||
import Signup from './Signup' |
connectionMacaroon: PropTypes.string, |
||||
import RecoverForm from './RecoverForm' |
connectionString: PropTypes.string, |
||||
import NewWalletSeed from './NewWalletSeed' |
lndWalletStarted: PropTypes.bool, |
||||
import ReEnterSeed from './ReEnterSeed' |
lndWalletUnlockerStarted: PropTypes.bool, |
||||
import NewWalletPassword from './NewWalletPassword' |
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 = ({ |
componentWillUnmount() { |
||||
onboarding: { |
const { resetOnboarding } = this.props |
||||
step, |
resetOnboarding() |
||||
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 ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.connection_title} />} |
|
||||
description={<FormattedMessage {...messages.connection_description} />} |
|
||||
theme={theme} |
|
||||
back={null} |
|
||||
next={() => { |
|
||||
switch (connectionType) { |
|
||||
case 'custom': |
|
||||
changeStep(0.2) |
|
||||
break |
|
||||
case 'btcpayserver': |
|
||||
changeStep(0.3) |
|
||||
break |
|
||||
default: |
|
||||
changeStep(1) |
|
||||
} |
|
||||
}} |
|
||||
> |
|
||||
<ConnectionType {...connectionTypeProps} /> |
|
||||
</FormContainer> |
|
||||
) |
|
||||
|
|
||||
case 0.2: |
/** |
||||
return ( |
* Dynamically generte form steps to use in the onboarding Wizzard. |
||||
<FormContainer |
* @return {[Wizzard.Step]} A list of WizardSteps. |
||||
title={<FormattedMessage {...messages.connection_details_custom_title} />} |
*/ |
||||
description={<FormattedMessage {...messages.connection_details_custom_description} />} |
getSteps = () => { |
||||
theme={theme} |
const { |
||||
back={() => changeStep(0.1)} |
// STATE
|
||||
next={() => { |
alias, |
||||
// dont allow the user to move on if we don't at least have a hostname.
|
autopilot, |
||||
if (!connectionDetailProps.connectionHostIsValid) { |
connectionType, |
||||
return |
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) { |
||||
> |
/** |
||||
<ConnectionDetails {...connectionDetailProps} /> |
* Form steps for create flow. |
||||
</FormContainer> |
*/ |
||||
) |
case 'create': |
||||
|
formSteps = [ |
||||
|
...formSteps, |
||||
|
<Wizard.Step |
||||
|
key="SeedView" |
||||
|
component={SeedView} |
||||
|
{...{ seed, generateSeed, fetchingSeed }} |
||||
|
/>, |
||||
|
<Wizard.Step key="SeedConfirm" component={SeedConfirm} {...{ seed }} />, |
||||
|
<Wizard.Step key="Password" component={Password} {...{ setPassword }} />, |
||||
|
<Wizard.Step key="Alias" component={Alias} {...{ alias, setAlias }} />, |
||||
|
<Wizard.Step key="Autopilot" component={Autopilot} {...{ autopilot, setAutopilot }} />, |
||||
|
<Wizard.Step key="WalletCreate" component={WalletCreate} {...{ createNewWallet }} /> |
||||
|
] |
||||
|
break |
||||
|
|
||||
case 0.3: |
/** |
||||
return ( |
* Form steps for import flow. |
||||
<FormContainer |
*/ |
||||
title={<FormattedMessage {...messages.btcpay_title} />} |
case 'import': |
||||
description={<FormattedMessage {...messages.btcpay_description} />} |
formSteps = [ |
||||
theme={theme} |
...formSteps, |
||||
back={() => changeStep(0.1)} |
<Wizard.Step key="Recover" component={Recover} {...{ seed }} />, |
||||
next={() => { |
<Wizard.Step key="Password" component={Password} {...{ setPassword }} />, |
||||
// dont allow the user to move on if the connection string is invalid.
|
<Wizard.Step key="Alias" component={Alias} {...{ alias, setAlias }} />, |
||||
if (!connectionDetailProps.connectionStringIsValid) { |
<Wizard.Step key="Autopilot" component={Autopilot} {...{ autopilot, setAutopilot }} />, |
||||
return |
<Wizard.Step key="WalletRecover" component={WalletRecover} {...{ recoverOldWallet }} /> |
||||
} |
] |
||||
|
break |
||||
|
|
||||
changeStep(0.4) |
/** |
||||
|
* Form steps for custom connection flow. |
||||
|
*/ |
||||
|
case 'custom': |
||||
|
formSteps = [ |
||||
|
<Wizard.Step |
||||
|
key="ConnectionDetails" |
||||
|
component={ConnectionDetails} |
||||
|
{...{ |
||||
|
connectionHost, |
||||
|
connectionCert, |
||||
|
connectionMacaroon, |
||||
|
startLndHostError, |
||||
|
startLndCertError, |
||||
|
startLndMacaroonError, |
||||
|
setConnectionHost, |
||||
|
setConnectionCert, |
||||
|
setConnectionMacaroon, |
||||
|
validateHost, |
||||
|
validateCert, |
||||
|
validateMacaroon |
||||
}} |
}} |
||||
> |
/>, |
||||
<BtcPayServer {...connectionDetailProps} /> |
<Wizard.Step |
||||
</FormContainer> |
key="ConnectionConfirm" |
||||
) |
component={ConnectionConfirm} |
||||
|
{...{ |
||||
|
connectionType, |
||||
|
connectionHost, |
||||
|
connectionCert, |
||||
|
connectionMacaroon, |
||||
|
lndWalletStarted, |
||||
|
lndWalletUnlockerStarted, |
||||
|
startLndHostError, |
||||
|
startLndCertError, |
||||
|
startLndMacaroonError, |
||||
|
startLnd |
||||
|
}} |
||||
|
/>, |
||||
|
<Wizard.Step |
||||
|
key="Login" |
||||
|
component={Login} |
||||
|
{...{ unlockWallet, setUnlockWalletError, unlockWalletError }} |
||||
|
/> |
||||
|
] |
||||
|
break |
||||
|
|
||||
case 0.4: |
/** |
||||
return ( |
* Form steps for BTCPay Server connection flow. |
||||
<FormContainer |
*/ |
||||
title={<FormattedMessage {...messages.confirm_connection_title} />} |
case 'btcpayserver': |
||||
description={<FormattedMessage {...messages.confirm_connection_description} />} |
formSteps = [ |
||||
theme={theme} |
<Wizard.Step |
||||
back={() => changeStep(previousStep)} |
key="BtcPayServer" |
||||
next={() => { |
component={BtcPayServer} |
||||
startLnd({ |
{...{ |
||||
type: connectionType, |
connectionString, |
||||
string: connectionString, |
startLndHostError, |
||||
host: connectionHost, |
setConnectionString |
||||
cert: connectionCert, |
}} |
||||
macaroon: connectionMacaroon |
/>, |
||||
}) |
<Wizard.Step |
||||
|
key="ConnectionConfirm" |
||||
|
component={ConnectionConfirm} |
||||
|
{...{ |
||||
|
connectionType, |
||||
|
connectionString, |
||||
|
lndWalletStarted, |
||||
|
lndWalletUnlockerStarted, |
||||
|
startLndHostError, |
||||
|
startLndCertError, |
||||
|
startLndMacaroonError, |
||||
|
startLnd |
||||
}} |
}} |
||||
> |
/>, |
||||
<ConnectionConfirm {...connectionConfirmProps} /> |
<Wizard.Step |
||||
</FormContainer> |
key="Login" |
||||
) |
component={Login} |
||||
|
{...{ unlockWallet, setUnlockWalletError, unlockWalletError }} |
||||
|
/> |
||||
|
] |
||||
|
break |
||||
|
} |
||||
|
|
||||
case 1: |
const steps = [ |
||||
return ( |
<Wizard.Step |
||||
<FormContainer |
key="ConnectionType" |
||||
title={<FormattedMessage {...messages.alias_title} />} |
component={ConnectionType} |
||||
description={<FormattedMessage {...messages.alias_description} />} |
{...{ connectionType, setConnectionType, resetOnboarding, stopLnd }} |
||||
theme={theme} |
/>, |
||||
back={() => changeStep(0.1)} |
...formSteps |
||||
next={() => changeStep(2)} |
] |
||||
> |
return steps |
||||
<Alias {...aliasProps} /> |
} |
||||
</FormContainer> |
|
||||
) |
|
||||
case 2: |
|
||||
return ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.autopilot_title} />} |
|
||||
description={<FormattedMessage {...messages.autopilot_description} />} |
|
||||
theme={theme} |
|
||||
back={() => changeStep(1)} |
|
||||
next={() => startLnd({ type: connectionType, alias, autopilot })} |
|
||||
> |
|
||||
<Autopilot {...autopilotProps} /> |
|
||||
</FormContainer> |
|
||||
) |
|
||||
case 3: |
|
||||
return ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.login_title} />} |
|
||||
description={ |
|
||||
<FormattedMessage |
|
||||
{...messages.login_description} |
|
||||
values={{ |
|
||||
walletDir: |
|
||||
initWalletProps.loginProps.existingWalletDir && connectionType === 'local' |
|
||||
? initWalletProps.loginProps.existingWalletDir |
|
||||
: connectionHost.split(':')[0] |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
theme={theme} |
|
||||
back={null} |
|
||||
next={null} |
|
||||
> |
|
||||
<Login {...initWalletProps.loginProps} /> |
|
||||
</FormContainer> |
|
||||
) |
|
||||
case 4: |
|
||||
return ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.create_wallet_password_title} />} |
|
||||
description={<FormattedMessage {...messages.create_wallet_password_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 |
|
||||
} |
|
||||
|
|
||||
changeStep(5) |
/** |
||||
}} |
* 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. |
||||
<NewWalletPassword {...newWalletPasswordProps} /> |
*/ |
||||
</FormContainer> |
getBackButtonText = () => { |
||||
) |
const { seed } = this.props |
||||
case 5: |
return seed.length > 0 ? ( |
||||
return ( |
<FormattedMessage {...messages.start_over} /> |
||||
<FormContainer |
) : ( |
||||
title={<FormattedMessage {...messages.signup_title} />} |
<FormattedMessage {...messages.previous} /> |
||||
description={<FormattedMessage {...messages.signup_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 |
|
||||
} |
|
||||
|
|
||||
changeStep(initWalletProps.signupProps.signupForm.create ? 6 : 5.1) |
/** |
||||
}} |
* If we have already started the create new wallet process and generated a seed, configure the back button to |
||||
> |
* navigate back to step 1. |
||||
<Signup {...initWalletProps.signupProps} /> |
*/ |
||||
</FormContainer> |
getPreviousStep = () => { |
||||
) |
const { seed } = this.props |
||||
case 5.1: |
return seed.length > 0 ? 0 : null |
||||
return ( |
} |
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.import_title} />} |
|
||||
description={<FormattedMessage {...messages.import_description} />} |
|
||||
theme={theme} |
|
||||
back={() => changeStep(5)} |
|
||||
next={() => { |
|
||||
const recoverySeed = recoverFormProps.recoverSeedInput.map(input => input.word) |
|
||||
|
|
||||
recoverOldWallet(createWalletPassword, recoverySeed) |
render() { |
||||
}} |
const { connectionType, onboarded } = this.props |
||||
> |
const steps = this.getSteps() |
||||
<RecoverForm {...recoverFormProps} /> |
const previousStep = this.getPreviousStep() |
||||
</FormContainer> |
const backButtonText = this.getBackButtonText() |
||||
) |
|
||||
case 6: |
|
||||
return ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.save_seed_title} />} |
|
||||
description={<FormattedMessage {...messages.save_seed_description} />} |
|
||||
theme={theme} |
|
||||
back={() => changeStep(5)} |
|
||||
next={() => changeStep(7)} |
|
||||
> |
|
||||
<NewWalletSeed {...newWalletSeedProps} /> |
|
||||
</FormContainer> |
|
||||
) |
|
||||
case 7: |
|
||||
return ( |
|
||||
<FormContainer |
|
||||
title={<FormattedMessage {...messages.retype_seed_title} />} |
|
||||
description={ |
|
||||
<FormattedMessage |
|
||||
{...messages.retype_seed_description} |
|
||||
values={{ |
|
||||
word1: reEnterSeedProps.seedIndexesArr[0], |
|
||||
word2: reEnterSeedProps.seedIndexesArr[1], |
|
||||
word3: reEnterSeedProps.seedIndexesArr[2] |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
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 |
|
||||
} |
|
||||
|
|
||||
submitNewWallet(createWalletPassword, seed) |
if (onboarded) { |
||||
}} |
return <Redirect to={['create', 'import'].includes(connectionType) ? '/syncing' : '/app'} /> |
||||
> |
|
||||
<ReEnterSeed {...reEnterSeedProps} /> |
|
||||
</FormContainer> |
|
||||
) |
|
||||
} |
} |
||||
} |
|
||||
|
|
||||
return ( |
return ( |
||||
<Box width={1}> |
<Wizard steps={steps}> |
||||
{renderStep()} |
<Flex css={{ height: '100%' }}> |
||||
{onboarded && <Redirect to={connectionType === 'local' ? '/syncing' : '/app'} />} |
<Panel width={1}> |
||||
</Box> |
<Panel.Body width={9 / 16} mx="auto"> |
||||
) |
<Wizard.Steps /> |
||||
} |
</Panel.Body> |
||||
|
|
||||
Onboarding.propTypes = { |
<Panel.Footer> |
||||
onboarding: PropTypes.object.isRequired, |
<Flex justifyContent="space-between"> |
||||
connectionTypeProps: PropTypes.object.isRequired, |
<Box> |
||||
connectionDetailProps: PropTypes.object.isRequired, |
<Wizard.BackButton navigateTo={previousStep}>{backButtonText}</Wizard.BackButton> |
||||
connectionConfirmProps: PropTypes.object.isRequired, |
</Box> |
||||
aliasProps: PropTypes.object.isRequired, |
<Box ml="auto"> |
||||
autopilotProps: PropTypes.object.isRequired, |
<Wizard.NextButton> |
||||
initWalletProps: PropTypes.object.isRequired, |
<FormattedMessage {...messages.next} /> |
||||
newWalletSeedProps: PropTypes.object.isRequired, |
</Wizard.NextButton> |
||||
newWalletPasswordProps: PropTypes.object.isRequired, |
</Box> |
||||
recoverFormProps: PropTypes.object.isRequired, |
</Flex> |
||||
reEnterSeedProps: PropTypes.object.isRequired, |
</Panel.Footer> |
||||
changeStep: PropTypes.func.isRequired, |
</Panel> |
||||
startLnd: PropTypes.func.isRequired, |
</Flex> |
||||
submitNewWallet: PropTypes.func.isRequired, |
</Wizard> |
||||
recoverOldWallet: PropTypes.func.isRequired |
) |
||||
|
} |
||||
} |
} |
||||
|
|
||||
export default Onboarding |
export default Onboarding |
||||
|
@ -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 ( |
|
||||
<div className={styles.container}> |
|
||||
<ul className={styles.seedContainer}> |
|
||||
{seedIndexesArr.map(index => ( |
|
||||
<li key={index}> |
|
||||
<section> |
|
||||
<label htmlFor={index}>{index}</label> |
|
||||
</section> |
|
||||
<section> |
|
||||
<input |
|
||||
type="text" |
|
||||
id={index} |
|
||||
value={reEnterSeedInput[index] ? reEnterSeedInput[index] : ''} |
|
||||
onChange={event => updateReEnterSeedInput({ word: event.target.value, index })} |
|
||||
className={`${styles.word} ${ |
|
||||
reEnterSeedInput[index] && seed[index - 1] === reEnterSeedInput[index] |
|
||||
? styles.valid |
|
||||
: styles.invalid |
|
||||
}`}
|
|
||||
/> |
|
||||
</section> |
|
||||
</li> |
|
||||
))} |
|
||||
</ul> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
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 |
|
@ -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; |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import ReEnterSeed from './ReEnterSeed' |
|
||||
|
|
||||
export default ReEnterSeed |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<ul className={styles.seedContainer}> |
|
||||
{Array(24) |
|
||||
.fill('') |
|
||||
.map((word, index) => ( |
|
||||
<li key={index}> |
|
||||
<section> |
|
||||
<label htmlFor={index}>{index + 1}</label> |
|
||||
</section> |
|
||||
<section> |
|
||||
<input |
|
||||
type="text" |
|
||||
id={index} |
|
||||
placeholder={intl.formatMessage({ ...messages.word_placeholder })} |
|
||||
value={recoverSeedInput[index] ? recoverSeedInput[index].word : ''} |
|
||||
onChange={event => updateRecoverSeedInput({ word: event.target.value, index })} |
|
||||
className={styles.word} |
|
||||
/> |
|
||||
</section> |
|
||||
</li> |
|
||||
))} |
|
||||
</ul> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
RecoverForm.propTypes = { |
|
||||
recoverSeedInput: PropTypes.array.isRequired, |
|
||||
updateRecoverSeedInput: PropTypes.func.isRequired, |
|
||||
intl: PropTypes.object.isRequired |
|
||||
} |
|
||||
|
|
||||
export default injectIntl(RecoverForm) |
|
@ -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; |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import RecoverForm from './RecoverForm' |
|
||||
|
|
||||
export default RecoverForm |
|
@ -1,6 +0,0 @@ |
|||||
import { defineMessages } from 'react-intl' |
|
||||
|
|
||||
/* eslint-disable max-len */ |
|
||||
export default defineMessages({ |
|
||||
word_placeholder: 'word' |
|
||||
}) |
|
@ -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 }) => ( |
|
||||
<div className={styles.container}> |
|
||||
<section className={`${styles.enable} ${signupForm.create ? styles.active : undefined}`}> |
|
||||
<div onClick={setSignupCreate}> |
|
||||
{signupForm.create ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.signup_create} /> |
|
||||
</span> |
|
||||
</div> |
|
||||
</section> |
|
||||
<section className={`${styles.disable} ${signupForm.import ? styles.active : undefined}`}> |
|
||||
<div onClick={setSignupImport}> |
|
||||
{signupForm.import ? <FaCircle /> : <FaCircleThin />} |
|
||||
<span className={styles.label}> |
|
||||
<FormattedMessage {...messages.signup_import} /> |
|
||||
</span> |
|
||||
</div> |
|
||||
</section> |
|
||||
</div> |
|
||||
) |
|
||||
|
|
||||
Signup.propTypes = { |
|
||||
signupForm: PropTypes.object.isRequired, |
|
||||
setSignupCreate: PropTypes.func.isRequired, |
|
||||
setSignupImport: PropTypes.func.isRequired |
|
||||
} |
|
||||
|
|
||||
export default Signup |
|
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
import Signup from './Signup' |
|
||||
|
|
||||
export default Signup |
|
@ -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' |
|
||||
}) |
|
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = formState.submits > 0 |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.alias_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.alias_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
<Bar my={4} /> |
||||
|
<Box> |
||||
|
<Input |
||||
|
field="alias" |
||||
|
name="alias" |
||||
|
label={<FormattedMessage {...messages.nickname} />} |
||||
|
initialValue={alias} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
/> |
||||
|
</Box> |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(Alias) |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.autopilot_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.autopilot_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
<Bar my={4} /> |
||||
|
<RadioGroup |
||||
|
required |
||||
|
field="autopilot" |
||||
|
name="autopilot" |
||||
|
initialValue={autopilot ? 'enable' : 'disable'} |
||||
|
> |
||||
|
<Radio value="enable" label={<FormattedMessage {...messages.enable} />} /> |
||||
|
|
||||
|
<Radio value="disable" label={<FormattedMessage {...messages.disable} />} /> |
||||
|
</RadioGroup> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default Autopilot |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = formState.submits > 0 |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.btcpay_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.btcpay_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<TextArea |
||||
|
field="connectionString" |
||||
|
name="connectionString" |
||||
|
label={<FormattedMessage {...messages.connection_string_label} />} |
||||
|
description={ |
||||
|
<FormattedMessage {...messages.btcpay_connection_string_description} /> |
||||
|
} |
||||
|
placeholder={intl.formatMessage({ ...messages.connection_string_placeholder })} |
||||
|
initialValue={connectionString} |
||||
|
onValueChange={this.handleConnectionStringChange} |
||||
|
validate={this.validateConnectionString} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
required |
||||
|
rows="10" |
||||
|
/> |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(BtcPayServer) |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={getApi} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={async values => { |
||||
|
try { |
||||
|
await this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
} catch (e) { |
||||
|
wizardApi.onSubmitFailure() |
||||
|
wizardApi.previous() |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.confirm_connection_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.confirm_connection_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Text> |
||||
|
<FormattedMessage {...messages.verify_host_title} />{' '} |
||||
|
<Span color="superGreen">{hostname}</Span>?{' '} |
||||
|
</Text> |
||||
|
<Text mt={2}> |
||||
|
<FormattedMessage {...messages.verify_host_description} /> |
||||
|
</Text> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ConnectionConfirm |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = |
||||
|
formState.submits > 0 || startLndHostError || startLndCertError || startLndMacaroonError |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.connection_details_custom_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.connection_details_custom_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Box mb={3}> |
||||
|
<Input |
||||
|
field="connectionHost" |
||||
|
name="connectionHost" |
||||
|
label={<FormattedMessage {...messages.hostname_title} />} |
||||
|
description={<FormattedMessage {...messages.hostname_description} />} |
||||
|
initialValue={connectionHost} |
||||
|
onValueChange={this.handleConnectionHostChange} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
asyncValidate={this.validateHost} |
||||
|
required |
||||
|
/> |
||||
|
</Box> |
||||
|
|
||||
|
<Box mb={3}> |
||||
|
<Input |
||||
|
field="connectionCert" |
||||
|
name="connectionCert" |
||||
|
label={<FormattedMessage {...messages.cert_title} />} |
||||
|
description={<FormattedMessage {...messages.cert_description} />} |
||||
|
initialValue={connectionCert} |
||||
|
onValueChange={this.handleConnectionCertChange} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
asyncValidate={this.validateCert} |
||||
|
required |
||||
|
/> |
||||
|
</Box> |
||||
|
|
||||
|
<Box mb={3}> |
||||
|
<Input |
||||
|
field="connectionMacaroon" |
||||
|
name="connectionMacaroon" |
||||
|
label="Macaroon" |
||||
|
description={<FormattedMessage {...messages.macaroon_description} />} |
||||
|
initialValue={connectionMacaroon} |
||||
|
onValueChange={this.handleConnectionMacaroonChange} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
asyncValidate={this.validateMacaroon} |
||||
|
required |
||||
|
/> |
||||
|
</Box> |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ConnectionDetails |
@ -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 ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.connection_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.connection_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<RadioGroup |
||||
|
required |
||||
|
field="connectionType" |
||||
|
name="connectionType" |
||||
|
initialValue={connectionType} |
||||
|
> |
||||
|
<Radio |
||||
|
value="create" |
||||
|
label={<FormattedMessage {...messages.signup_create} />} |
||||
|
description="Let Zap crearte a new bitcoin wallet and lightning node for you." |
||||
|
/> |
||||
|
|
||||
|
<Radio |
||||
|
value="import" |
||||
|
label={<FormattedMessage {...messages.signup_import} />} |
||||
|
description="Import your own priivate key to recover an existing wallet." |
||||
|
/> |
||||
|
|
||||
|
<Radio |
||||
|
value="custom" |
||||
|
label="Connect your own node" |
||||
|
description={<FormattedMessage {...messages.custom_description} />} |
||||
|
/> |
||||
|
|
||||
|
<Radio |
||||
|
value="btcpayserver" |
||||
|
label="BTCPay Server" |
||||
|
description={<FormattedMessage {...messages.btcpay_description} />} |
||||
|
/> |
||||
|
</RadioGroup> |
||||
|
</Form> |
||||
|
</> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ConnectionType |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={async values => { |
||||
|
try { |
||||
|
await this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
} catch (e) { |
||||
|
wizardApi.onSubmitFailure() |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = formState.submits > 0 |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.login_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.login_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Box> |
||||
|
<PasswordInput |
||||
|
field="password" |
||||
|
name="password" |
||||
|
label={<FormattedMessage {...messages.password_label} />} |
||||
|
description={<FormattedMessage {...messages.password_description} />} |
||||
|
required |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
placeholder={intl.formatMessage({ ...messages.password_placeholder })} |
||||
|
autoComplete="current-password" |
||||
|
/> |
||||
|
</Box> |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(Login) |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={async values => { |
||||
|
await this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = formState.submits > 0 |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.create_wallet_password_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.create_wallet_password_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Box> |
||||
|
<PasswordInput |
||||
|
field="password" |
||||
|
name="password" |
||||
|
label={<FormattedMessage {...messages.password_label} />} |
||||
|
required |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
placeholder={intl.formatMessage({ ...messages.password_placeholder })} |
||||
|
autoComplete="current-password" |
||||
|
/> |
||||
|
</Box> |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(Password) |
@ -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 ( |
||||
|
<Flex key={`word${index}`} justifyContent="flex-start" alignItems="center" as="li" my={1}> |
||||
|
<Label htmlFor={`word${index}`} width={35} mb={0}> |
||||
|
{index} |
||||
|
</Label> |
||||
|
<Input |
||||
|
initialValue={word} |
||||
|
field={`word${index}`} |
||||
|
validate={this.validateWord} |
||||
|
variant="thin" |
||||
|
validateOnChange |
||||
|
placeholder={intl.formatMessage({ ...messages.word_placeholder })} |
||||
|
showMessage={false} |
||||
|
/> |
||||
|
</Flex> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={getApi} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={onSubmit} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.import_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.import_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
<Flex justifyContent="space-between"> |
||||
|
<Flex flexDirection="column" as="ul" mr={2}> |
||||
|
{indexes.slice(0, 6).map(word => ( |
||||
|
<SeedWordWithIntl key={word + 1} index={word + 1} word={seed[word]} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul" mx={2}> |
||||
|
{indexes.slice(6, 12).map(word => ( |
||||
|
<SeedWordWithIntl key={word + 1} index={word + 1} word={seed[word]} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul" mx={2}> |
||||
|
{indexes.slice(12, 18).map(word => ( |
||||
|
<SeedWordWithIntl key={word + 1} index={word + 1} word={seed[word]} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul" ml={2}> |
||||
|
{indexes.slice(18, 24).map(word => ( |
||||
|
<SeedWordWithIntl key={word + 1} index={word + 1} word={seed[word]} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
</Flex> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(SeedView) |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={onSubmit} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
{({ formState }) => { |
||||
|
const shouldValidateInline = formState.submits > 0 |
||||
|
return ( |
||||
|
<> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.retype_seed_title} />} |
||||
|
subtitle={ |
||||
|
<FormattedMessage |
||||
|
{...messages.retype_seed_description} |
||||
|
values={{ |
||||
|
word1: seedWordIndexes[0], |
||||
|
word2: seedWordIndexes[1], |
||||
|
word3: seedWordIndexes[2] |
||||
|
}} |
||||
|
/> |
||||
|
} |
||||
|
align="left" |
||||
|
/> |
||||
|
|
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
{seedWordIndexes.map((wordIndex, index) => { |
||||
|
return ( |
||||
|
<Flex key={`word${index}`} justifyContent="flex-start" mb={3}> |
||||
|
<Label htmlFor="alias" width={25} mt={18}> |
||||
|
{wordIndex} |
||||
|
</Label> |
||||
|
<Input |
||||
|
field={`word${index}`} |
||||
|
name={`word${index}`} |
||||
|
validateOnBlur={shouldValidateInline} |
||||
|
validateOnChange={shouldValidateInline} |
||||
|
validate={value => this.validateWord.call(null, wordIndex - 1, value)} |
||||
|
placeholder={intl.formatMessage({ ...messages.word_placeholder })} |
||||
|
required |
||||
|
/> |
||||
|
</Flex> |
||||
|
) |
||||
|
})} |
||||
|
</> |
||||
|
) |
||||
|
}} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(SeedConfirm) |
@ -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 }) => ( |
||||
|
<Text as="li" my={2}> |
||||
|
<Flex> |
||||
|
<Text fontWeight="normal" width={25}> |
||||
|
{index} |
||||
|
</Text> |
||||
|
<Text>{word}</Text> |
||||
|
</Flex> |
||||
|
</Text> |
||||
|
) |
||||
|
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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={getApi} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={onSubmit} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Header |
||||
|
title={<FormattedMessage {...messages.save_seed_title} />} |
||||
|
subtitle={<FormattedMessage {...messages.save_seed_description} />} |
||||
|
align="left" |
||||
|
/> |
||||
|
<Bar my={4} /> |
||||
|
|
||||
|
{fetchingSeed && ( |
||||
|
<Text textAlign="center"> |
||||
|
<Spinner /> |
||||
|
Generating Seed... |
||||
|
</Text> |
||||
|
)} |
||||
|
{!fetchingSeed && |
||||
|
seed.length > 0 && ( |
||||
|
<Flex justifyContent="space-between"> |
||||
|
<Flex flexDirection="column" as="ul"> |
||||
|
{seed.slice(0, 6).map((word, index) => ( |
||||
|
<SeedWord key={index} index={index + 1} word={word} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul"> |
||||
|
{seed.slice(6, 12).map((word, index) => ( |
||||
|
<SeedWord key={index} index={index + 7} word={word} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul"> |
||||
|
{seed.slice(12, 18).map((word, index) => ( |
||||
|
<SeedWord key={index} index={index + 13} word={word} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
<Flex flexDirection="column" as="ul"> |
||||
|
{seed.slice(18, 24).map((word, index) => ( |
||||
|
<SeedWord key={index} index={index + 19} word={word} /> |
||||
|
))} |
||||
|
</Flex> |
||||
|
</Flex> |
||||
|
)} |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default injectIntl(SeedView) |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Text textAlign="center"> |
||||
|
<Spinner /> |
||||
|
Creating wallet... |
||||
|
</Text> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default WalletCreate |
@ -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 ( |
||||
|
<Form |
||||
|
{...rest} |
||||
|
getApi={formApi => { |
||||
|
this.setFormApi(formApi) |
||||
|
if (getApi) { |
||||
|
getApi(formApi) |
||||
|
} |
||||
|
}} |
||||
|
onChange={onChange && (formState => onChange(formState, currentItem))} |
||||
|
preSubmit={preSubmit} |
||||
|
onSubmit={values => { |
||||
|
this.handleSubmit(values) |
||||
|
if (onSubmit) { |
||||
|
onSubmit(values) |
||||
|
} |
||||
|
}} |
||||
|
onSubmitFailure={onSubmitFailure} |
||||
|
> |
||||
|
<Text textAlign="center"> |
||||
|
<Spinner /> |
||||
|
Importing wallet... |
||||
|
</Text> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default WalletRecover |
@ -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' |
@ -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' |
||||
|
}) |
@ -1,3 +1 @@ |
|||||
import Onboarding from './Onboarding' |
export Onboarding from './Onboarding' |
||||
|
|
||||
export default Onboarding |
|
||||
|
@ -1,186 +1,70 @@ |
|||||
import { connect } from 'react-redux' |
import { connect } from 'react-redux' |
||||
|
import { Onboarding } from 'components/Onboarding' |
||||
import { themeSelectors } from 'reducers/theme' |
|
||||
import { |
import { |
||||
|
setAlias, |
||||
|
setAutopilot, |
||||
setConnectionType, |
setConnectionType, |
||||
setConnectionString, |
|
||||
setConnectionHost, |
setConnectionHost, |
||||
setConnectionCert, |
setConnectionCert, |
||||
setConnectionMacaroon, |
setConnectionMacaroon, |
||||
updateAlias, |
setConnectionString, |
||||
updatePassword, |
setPassword, |
||||
setAutopilot, |
setUnlockWalletError, |
||||
changeStep, |
|
||||
startLnd, |
startLnd, |
||||
createWallet, |
stopLnd, |
||||
updateCreateWalletPassword, |
validateHost, |
||||
updateCreateWalletPasswordConfirmation, |
validateCert, |
||||
submitNewWallet, |
validateMacaroon, |
||||
|
generateSeed, |
||||
|
createNewWallet, |
||||
recoverOldWallet, |
recoverOldWallet, |
||||
onboardingSelectors, |
resetOnboarding, |
||||
unlockWallet, |
unlockWallet |
||||
setSignupCreate, |
|
||||
setSignupImport, |
|
||||
updateReEnterSeedInput, |
|
||||
updateRecoverSeedInput, |
|
||||
setReEnterSeedIndexes |
|
||||
} from 'reducers/onboarding' |
} 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 = { |
const mapDispatchToProps = { |
||||
|
setAlias, |
||||
|
setAutopilot, |
||||
setConnectionType, |
setConnectionType, |
||||
setConnectionString, |
|
||||
setConnectionHost, |
setConnectionHost, |
||||
setConnectionCert, |
setConnectionCert, |
||||
setConnectionMacaroon, |
setConnectionMacaroon, |
||||
updateAlias, |
setConnectionString, |
||||
updatePassword, |
setPassword, |
||||
updateCreateWalletPassword, |
setUnlockWalletError, |
||||
updateCreateWalletPasswordConfirmation, |
|
||||
setAutopilot, |
|
||||
changeStep, |
|
||||
startLnd, |
startLnd, |
||||
createWallet, |
stopLnd, |
||||
submitNewWallet, |
validateHost, |
||||
|
validateCert, |
||||
|
validateMacaroon, |
||||
|
generateSeed, |
||||
|
createNewWallet, |
||||
recoverOldWallet, |
recoverOldWallet, |
||||
unlockWallet, |
resetOnboarding, |
||||
setSignupCreate, |
unlockWallet |
||||
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 |
|
||||
} |
|
||||
} |
} |
||||
|
|
||||
export default connect( |
export default connect( |
||||
mapStateToProps, |
mapStateToProps, |
||||
mapDispatchToProps, |
mapDispatchToProps |
||||
mergeProps |
|
||||
)(Onboarding) |
)(Onboarding) |
||||
|
@ -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 => ( |
||||
|
<Page css={{ height: 'calc(100vh - 40px)' }}> |
||||
|
<Modal onClose={linkTo('Containers.Home', 'Home')}>{story()}</Modal> |
||||
|
</Page> |
||||
|
)) |
||||
|
.add('Onboarding', () => { |
||||
|
return ( |
||||
|
<State store={store}> |
||||
|
<Onboarding |
||||
|
// DISPATCH
|
||||
|
resetOnboarding={resetOnboarding} |
||||
|
setAlias={setAlias} |
||||
|
setAutopilot={setAutopilot} |
||||
|
setConnectionType={setConnectionType} |
||||
|
setConnectionHost={setConnectionHost} |
||||
|
setConnectionCert={setConnectionCert} |
||||
|
setConnectionMacaroon={setConnectionMacaroon} |
||||
|
setConnectionString={setConnectionString} |
||||
|
setPassword={setPassword} |
||||
|
createNewWallet={createNewWallet} |
||||
|
recoverOldWallet={recoverOldWallet} |
||||
|
startLnd={startLnd} |
||||
|
stopLnd={stopLnd} |
||||
|
validateHost={validateHost} |
||||
|
validateCert={validateCert} |
||||
|
validateMacaroon={validateMacaroon} |
||||
|
generateSeed={generateSeed} |
||||
|
/> |
||||
|
</State> |
||||
|
) |
||||
|
}) |
@ -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', () => <ConnectionType />) |
||||
|
.add('ConnectionDetails', () => ( |
||||
|
<ConnectionDetails |
||||
|
setConnectionHost={setConnectionHost} |
||||
|
setConnectionCert={setConnectionCert} |
||||
|
setConnectionMacaroon={setConnectionMacaroon} |
||||
|
/> |
||||
|
)) |
||||
|
.add('ConnectionConfirm', () => <ConnectionConfirm connectionHost="example.com:10009" />) |
||||
|
.add('BtcPayServer', () => <BtcPayServer />) |
||||
|
.add('Login', () => <Login />) |
||||
|
.add('Password', () => <Password />) |
||||
|
.add('Recover', () => <Recover />) |
||||
|
.add('Alias', () => <Alias />) |
||||
|
.add('Autopilot', () => <Autopilot />) |
||||
|
.add('SeedConfirm', () => ( |
||||
|
<SeedConfirm |
||||
|
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' |
||||
|
]} |
||||
|
/> |
||||
|
)) |
||||
|
.add('SeedView', () => ( |
||||
|
<SeedView |
||||
|
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' |
||||
|
]} |
||||
|
/> |
||||
|
)) |
Loading…
Reference in new issue